From e54c51cf2fed02efb3bf8a4b871905ebede14052 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Tue, 6 Apr 2021 17:27:13 +0200 Subject: [PATCH 01/36] if you are not in the soc directory the svd files end up in the wrong place. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1a25e0a..4935578 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ This project is developed and maintained by [DerFetzer][team]. 1. Install Litex as described [here][litex]. 2. Install [ecpprog][ecpprog]. 4. Connect a USB to JTAG adaptor to your board. -5. Build and flash the SOC with something like the following: +5. Build and flash the SOC with the following (in the soc directory): ``` -python soc/colorlight_5a_75x.py --build --flash --board=5a-75e --revision=6.0 --with-ethernet --sys-clk-freq 50e6 --use-internal-osc +python colorlight_5a_75x.py --build --flash --board=5a-75e --revision=6.0 --with-ethernet --sys-clk-freq 50e6 --use-internal-osc ``` 4. Follow the instructions in [eth_demo][eth_demo] to build the software. @@ -26,4 +26,4 @@ and the Litex [target file][target] for the Colorlight board. [litex-example]: https://github.com/icebreaker-fpga/icebreaker-litex-examples [colorlight]: http://www.colorlight-led.com/product/colorlight-5a-75e-led-display-receiving-card.html [target]: https://github.com/litex-hub/litex-boards/blob/master/litex_boards/targets/colorlight_5a_75x.py -[eth_demo]: rust/eth_demo/README.md +[eth_demo]: rust/eth_demo/README.md From 0dc8be337c45411e5589e703cc2d897dba88f4ce Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Tue, 6 Apr 2021 17:30:41 +0200 Subject: [PATCH 02/36] 1. For the colorlight5A-75b V7 there needs to be 0 tx delay, otherwise the PHY doesnt work. 2. The peripheral code has to be inserted at the end of the peripherals list. For me it got inserted at the end after vendorExtentions and this didn't work. --- soc/colorlight_5a_75x.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index 0fb031e..08908f0 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -202,9 +202,15 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi # Ethernet / Etherbone --------------------------------------------------------------------- if with_ethernet or with_etherbone: - self.submodules.ethphy = LiteEthPHYRGMII( - clock_pads = self.platform.request("eth_clocks", eth_phy), - pads = self.platform.request("eth", eth_phy)) + if board == "5a-75b" and revision == "7.0": + self.submodules.ethphy = LiteEthPHYRGMII( + clock_pads = self.platform.request("eth_clocks", eth_phy), + pads = self.platform.request("eth", eth_phy), + tx_delay = 0e-9) + else: + self.submodules.ethphy = LiteEthPHYRGMII( + clock_pads = self.platform.request("eth_clocks", eth_phy), + pads = self.platform.request("eth", eth_phy)) self.add_csr("ethphy") if with_ethernet: self.add_ethernet(phy=self.ethphy) @@ -217,6 +223,14 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi def modify_svd(builder_kwargs): # Add Ethernet buffer peripheral to svd with open(builder_kwargs["csr_svd"], "r") as f: + line_number = 0 + for l in f: # search for the right place to insert + line_number += 1 + if """""" in l: + line = line_number + print("inserting before line:") + print(line) + f.seek(0) s = f.readlines() registers = """ ETHMEM @@ -303,7 +317,7 @@ def modify_svd(builder_kwargs): """ - s.insert(-2, registers) + s.insert(line-1, registers) with open(builder_kwargs["csr_svd"], "w") as f: f.writelines(s) From 071f0bb40385f25ee71418a546cd073552f5fc08 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Tue, 6 Apr 2021 18:30:26 +0200 Subject: [PATCH 03/36] commit build outputs for me --- rust/litex-pac/clSOC.svd | 344 +++++++++++++++++---------------------- rust/litex-pac/memory.x | 4 +- 2 files changed, 147 insertions(+), 201 deletions(-) diff --git a/rust/litex-pac/clSOC.svd b/rust/litex-pac/clSOC.svd index 1596c26..d5fb117 100644 --- a/rust/litex-pac/clSOC.svd +++ b/rust/litex-pac/clSOC.svd @@ -2,7 +2,7 @@ litex - ETHMAC + SOC 8 32 @@ -14,16 +14,15 @@ CTRL - 0xE0000000 + 0xF0000000 CTRL RESET - + 0x0000 0x00 32 - read-write reset @@ -41,7 +40,6 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of 0x0004 0x12345678 32 - read-write scratch @@ -57,7 +55,6 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of 0x0008 0x00 32 - read-only bus_errors @@ -76,7 +73,7 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of IDENTIFIER_MEM - 0xE0001000 + 0xF0001000 IDENTIFIER_MEM @@ -85,7 +82,6 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of 0x0000 0x00 32 - read-write identifier_mem @@ -102,36 +98,9 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of registers - - UART_PHY - 0xE0001800 - UART_PHY - - - TUNING_WORD - 0x0000 - 0x96feb4 - 32 - read-write - - - tuning_word - 31 - [31:0] - 0 - - - - - - 0 - 0x4 - registers - - UART - 0xE0002000 + 0xF0002000 UART @@ -139,7 +108,6 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of 0x0000 0x00 32 - read-write rxtx @@ -154,7 +122,6 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of 0x0004 0x00 32 - read-only txfull @@ -169,7 +136,6 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of 0x0008 0x00 32 - read-only rxempty @@ -181,46 +147,73 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of EV_STATUS + 0x000c 0x00 32 - read-write - status - 1 - [1:0] + tx + 0 + [0:0] 0 + + + + rx + 1 + [1:1] + 1 + EV_PENDING + 0x0010 0x00 32 - read-write - pending - 1 - [1:0] + tx + 0 + [0:0] 0 + + + + rx + 1 + [1:1] + 1 + EV_ENABLE + 0x0014 0x00 32 - read-write - enable - 1 - [1:0] + tx + 0 + [0:0] 0 + + + + rx + 1 + [1:1] + 1 + @@ -229,7 +222,6 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of 0x0018 0x00 32 - read-only txempty @@ -244,7 +236,6 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of 0x001c 0x00 32 - read-only rxfull @@ -267,7 +258,7 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of TIMER0 - 0xE0002800 + 0xF0002800 TIMER0 @@ -277,7 +268,6 @@ this register specifies the Timer's duration in clock cycles.]]> 0x0000 0x00 32 - read-write load @@ -294,7 +284,6 @@ this register specify the Timer's period in clock cycles.]]> 0x0004 0x00 32 - read-write reload @@ -311,7 +300,6 @@ to ``0`` to disable the Timer.]]> 0x0008 0x00 32 - read-write en @@ -328,7 +316,6 @@ the current countdown value to ``value`` register.]]> 0x000c 0x00 32 - read-write update_value @@ -344,7 +331,6 @@ the current countdown value to ``value`` register.]]> 0x0010 0x00 32 - read-only value @@ -356,46 +342,52 @@ the current countdown value to ``value`` register.]]> EV_STATUS + 0x0014 0x00 32 - read-write - status + zero 0 [0:0] 0 + EV_PENDING + 0x0018 0x00 32 - read-write - pending + zero 0 [0:0] 0 + EV_ENABLE + 0x001c 0x00 32 - read-write - enable + zero 0 [0:0] 0 + @@ -412,7 +404,7 @@ the current countdown value to ``value`` register.]]> SDRAM - 0xE0003000 + 0xF0003000 SDRAM @@ -420,7 +412,6 @@ the current countdown value to ``value`` register.]]> 0x0000 0x01 32 - read-write sel @@ -457,7 +448,6 @@ the current countdown value to ``value`` register.]]> 0x0004 0x00 32 - read-write dfii_pi0_command @@ -472,7 +462,6 @@ the current countdown value to ``value`` register.]]> 0x0008 0x00 32 - read-write dfii_pi0_command_issue @@ -487,7 +476,6 @@ the current countdown value to ``value`` register.]]> 0x000c 0x00 32 - read-write dfii_pi0_address @@ -502,12 +490,11 @@ the current countdown value to ``value`` register.]]> 0x0010 0x00 32 - read-write dfii_pi0_baddress - 1 - [1:0] + 0 + [0:0] 0 @@ -517,7 +504,6 @@ the current countdown value to ``value`` register.]]> 0x0014 0x00 32 - read-write dfii_pi0_wrdata @@ -532,7 +518,6 @@ the current countdown value to ``value`` register.]]> 0x0018 0x00 32 - read-only dfii_pi0_rddata @@ -542,106 +527,16 @@ the current countdown value to ``value`` register.]]> - - DFII_PI1_COMMAND - 0x001c - 0x00 - 32 - read-write - - - dfii_pi1_command - 5 - [5:0] - 0 - - - - - DFII_PI1_COMMAND_ISSUE - 0x0020 - 0x00 - 32 - read-write - - - dfii_pi1_command_issue - 0 - [0:0] - 0 - - - - - DFII_PI1_ADDRESS - 0x0024 - 0x00 - 32 - read-write - - - dfii_pi1_address - 10 - [10:0] - 0 - - - - - DFII_PI1_BADDRESS - 0x0028 - 0x00 - 32 - read-write - - - dfii_pi1_baddress - 1 - [1:0] - 0 - - - - - DFII_PI1_WRDATA - 0x002c - 0x00 - 32 - read-write - - - dfii_pi1_wrdata - 31 - [31:0] - 0 - - - - - DFII_PI1_RDDATA - 0x0030 - 0x00 - 32 - read-only - - - dfii_pi1_rddata - 31 - [31:0] - 0 - - - 0 - 0x34 + 0x1c registers SPIFLASH - 0xE0003800 + 0xF0003800 SPIFLASH @@ -650,7 +545,6 @@ the current countdown value to ``value`` register.]]> 0x0000 0x00 32 - read-write mosi @@ -688,7 +582,6 @@ the current countdown value to ``value`` register.]]> 0x0004 0x00 32 - read-only miso @@ -704,7 +597,6 @@ the current countdown value to ``value`` register.]]> 0x0008 0x00 32 - read-write bitbang_en @@ -723,7 +615,7 @@ the current countdown value to ``value`` register.]]> ETHPHY - 0xE0004000 + 0xF0004000 ETHPHY @@ -731,7 +623,6 @@ the current countdown value to ``value`` register.]]> 0x0000 0x00 32 - read-write crg_reset @@ -746,7 +637,6 @@ the current countdown value to ``value`` register.]]> 0x0004 0x00 32 - read-only link_status @@ -776,7 +666,6 @@ the current countdown value to ``value`` register.]]> 0x0008 0x00 32 - read-write mdc @@ -806,7 +695,6 @@ the current countdown value to ``value`` register.]]> 0x000c 0x00 32 - read-only r @@ -826,7 +714,7 @@ the current countdown value to ``value`` register.]]> ETHMAC - 0xE0004800 + 0xF0004800 ETHMAC @@ -834,7 +722,6 @@ the current countdown value to ``value`` register.]]> 0x0000 0x00 32 - read-only sram_writer_slot @@ -849,7 +736,6 @@ the current countdown value to ``value`` register.]]> 0x0004 0x00 32 - read-only sram_writer_length @@ -864,7 +750,6 @@ the current countdown value to ``value`` register.]]> 0x0008 0x00 32 - read-only sram_writer_errors @@ -876,46 +761,53 @@ the current countdown value to ``value`` register.]]> SRAM_WRITER_EV_STATUS + 0x000c 0x00 32 - read-write - sram_writer_ev_status + available 0 [0:0] 0 + SRAM_WRITER_EV_PENDING + 0x0010 0x00 32 - read-write - sram_writer_ev_pending + available 0 [0:0] 0 + SRAM_WRITER_EV_ENABLE + 0x0014 0x00 32 - read-write - sram_writer_ev_enable + available 0 [0:0] 0 + @@ -924,7 +816,6 @@ the current countdown value to ``value`` register.]]> 0x0018 0x00 32 - read-write sram_reader_start @@ -939,7 +830,6 @@ the current countdown value to ``value`` register.]]> 0x001c 0x00 32 - read-only sram_reader_ready @@ -954,7 +844,6 @@ the current countdown value to ``value`` register.]]> 0x0020 0x00 32 - read-only sram_reader_level @@ -969,7 +858,6 @@ the current countdown value to ``value`` register.]]> 0x0024 0x00 32 - read-write sram_reader_slot @@ -984,7 +872,6 @@ the current countdown value to ``value`` register.]]> 0x0028 0x00 32 - read-write sram_reader_length @@ -996,46 +883,52 @@ the current countdown value to ``value`` register.]]> SRAM_READER_EV_STATUS + 0x002c 0x00 32 - read-write - sram_reader_ev_status + done 0 [0:0] 0 + SRAM_READER_EV_PENDING + 0x0030 0x00 32 - read-write - sram_reader_ev_pending + done 0 [0:0] 0 + SRAM_READER_EV_ENABLE + 0x0034 0x00 32 - read-write - sram_reader_ev_enable + done 0 [0:0] 0 + @@ -1044,7 +937,6 @@ the current countdown value to ``value`` register.]]> 0x0038 0x01 32 - read-only preamble_crc @@ -1059,7 +951,6 @@ the current countdown value to ``value`` register.]]> 0x003c 0x00 32 - read-only preamble_errors @@ -1074,7 +965,6 @@ the current countdown value to ``value`` register.]]> 0x0040 0x00 32 - read-only crc_errors @@ -1180,4 +1070,60 @@ the current countdown value to ``value`` register.]]> + + + + SRAM + 0x10000000 + 0x00002000 + + + MAIN_RAM + 0x40000000 + 0x00400000 + + + SPIFLASH + 0x20000000 + 0x02000000 + + + ROM + 0x20100000 + 0x01F00000 + + + ETHMAC + 0x80000000 + 0x00002000 + + + CSR + 0xF0000000 + 0x00010000 + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rust/litex-pac/memory.x b/rust/litex-pac/memory.x index 2ac22b8..7d37e38 100644 --- a/rust/litex-pac/memory.x +++ b/rust/litex-pac/memory.x @@ -1,10 +1,10 @@ MEMORY { sram : ORIGIN = 0x10000000, LENGTH = 0x00002000 - main_ram : ORIGIN = 0x40000000, LENGTH = 0x00800000 + main_ram : ORIGIN = 0x40000000, LENGTH = 0x00400000 spiflash : ORIGIN = 0x20000000, LENGTH = 0x02000000 rom : ORIGIN = 0x20100000, LENGTH = 0x01f00000 ethmac : ORIGIN = 0x80000000, LENGTH = 0x00002000 - csr : ORIGIN = 0xe0000000, LENGTH = 0x00010000 + csr : ORIGIN = 0xf0000000, LENGTH = 0x00010000 } REGION_ALIAS("REGION_TEXT", spiflash); From cd3d9b4e938d162cd24fdff938c2824dc9421b6a Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Tue, 6 Apr 2021 21:30:18 +0200 Subject: [PATCH 04/36] blinkyblinkyblink :) --- rust/eth_demo/src/leds.rs | 50 +++++++++++++++++++++++++++ rust/eth_demo/src/main.rs | 7 ++++ rust/litex-pac/clSOC.svd | 41 ++++++++++++++++++++++ soc/colorlight_5a_75x.py | 72 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+) create mode 100644 rust/eth_demo/src/leds.rs diff --git a/rust/eth_demo/src/leds.rs b/rust/eth_demo/src/leds.rs new file mode 100644 index 0000000..52a1712 --- /dev/null +++ b/rust/eth_demo/src/leds.rs @@ -0,0 +1,50 @@ +use litex_pac::LEDS; + +pub struct Leds { + registers: LEDS, +} + +#[allow(dead_code)] +impl Leds { + pub fn new(registers: LEDS) -> Self { + Self { registers } + } + + pub fn set_single(&mut self, red: bool, yellow: bool, + green: bool) { + self.registers.out.write(|w| { + w.r().bit(red); + w.g().bit(green); + w.y().bit(yellow) + }); + } + + pub fn set(&mut self, leds: u32) { + unsafe { + self.registers.out.write(|w| w.bits(leds)); + } + } + + pub fn off(&mut self) { + unsafe { + self.registers.out.write(|w| w.bits(0x0000_0000)); + } + } + + pub fn on(&mut self) { + unsafe { + self.registers.out.write(|w| w.bits(0xFFFF_FFFF)); + } + } + + pub fn toggle(&mut self) { + self.toggle_mask(0xFFFF_FFFF); + } + + pub fn toggle_mask(&mut self, mask: u32) { + let val: u32 = self.registers.out.read().bits() ^ mask; + unsafe { + self.registers.out.write(|w| w.bits(val)); + } + } +} diff --git a/rust/eth_demo/src/main.rs b/rust/eth_demo/src/main.rs index 876ec3c..3eb349f 100644 --- a/rust/eth_demo/src/main.rs +++ b/rust/eth_demo/src/main.rs @@ -9,9 +9,11 @@ use riscv_rt::entry; mod ethernet; mod print; mod timer; +mod leds; use crate::ethernet::Eth; use timer::Timer; +use leds::Leds; use managed::ManagedSlice; use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache}; @@ -62,6 +64,8 @@ fn main() -> ! { let mut timer = Timer::new(peripherals.TIMER0); + let mut leds = Leds::new(peripherals.LEDS); + let clock = mock::Clock::new(); let device = Eth::new(peripherals.ETHMAC, peripherals.ETHMEM); @@ -177,6 +181,9 @@ fn main() -> ! { None => clock.advance(Duration::from_millis(1)), } trace!("Clock elapsed: {}", clock.elapsed()); + + msleep(&mut timer, 1000 as u32); + leds.toggle(); } } diff --git a/rust/litex-pac/clSOC.svd b/rust/litex-pac/clSOC.svd index d5fb117..cd819e2 100644 --- a/rust/litex-pac/clSOC.svd +++ b/rust/litex-pac/clSOC.svd @@ -985,6 +985,47 @@ register to disable individual events.]]> 2 + + LEDS + 0xF0005000 + LEDS + + + OUT + 0x0000 + 0x00 + 32 + + + r + 0 + [0:0] + 0 + + + + y + 1 + [1:1] + 1 + + + + g + 2 + [2:2] + 2 + + + + + + + 0 + 0x4 + registers + + ETHMEM 0x80000000 diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index 08908f0..b296dd7 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -26,6 +26,7 @@ from litex.soc.integration.builder import Builder, builder_argdict, builder_args from litex.soc.integration.soc_core import soc_core_argdict, soc_core_args from litex.soc.interconnect.csr import AutoCSR, CSRStorage, CSRStatus, CSRField +from litex.soc.integration.doc import AutoDoc, ModuleDoc from litex.build.generic_platform import * @@ -48,6 +49,58 @@ def load_bitstream(self, bitstream_file): subprocess.call(["ecpprog", "-S", bitstream_file]) +# My IOs ------------------------------------------------------------------------------------------- + +_dac = [ + ("dac", 0, Pins("j4:0"), IOStandard("LVCMOS33")), + ("dac", 1, Pins("j4:1"), IOStandard("LVCMOS33")), # sigma-delta dac output +] + +_leds = [ + ("g", 0, Pins("j6:5"), IOStandard("LVCMOS33")), + ("r", 0, Pins("j6:7"), IOStandard("LVCMOS33")), + ("y", 0, Pins("j6:9"), IOStandard("LVCMOS33")), +] + +_adc_first_order = [ + ("in", 0, Pins("j1:1"), IOStandard("LVDS")), + ("sd", 0, Pins("j1:2"), IOStandard("LVCMOS33")), # sigma delta out + ("p3v", 0, Pins("j1:0"), IOStandard("LVCMOS33")), # this will make 3V on the connector + ("p5v", 0, Pins("j1:14"), IOStandard("LVCMOS33")), # this will make 5V on the connector bc buffer IC +] + +_adc_second_order = [ + ("in", 0, Pins("j1:1"), IOStandard("LVDS")), + ("sd", 0, Pins("j1:5"), IOStandard("LVCMOS33")), # sigma delta out + ("sd", 1, Pins("j1:7"), IOStandard("LVCMOS33")), # sigma delta out + ("p3v", 0, Pins("j1:0"), IOStandard("LVCMOS33")), # this will make 3V on the connector + ("p5v", 0, Pins("j1:14"), IOStandard("LVCMOS33")), # this will make 5V on the connector bc buffer IC +] + + +# LEDs --------------------------------------------------------------------------------------------- + +class Leds(Module, AutoCSR, AutoDoc): + """LED control. + 3 LEDs connected to random IOs + Attributes: + led_pin: Signals of the LED pin outputs. + led_polarity: Bit pattern to adjust polarity. 0 stays the same 1 inverts the signal. + led_name: Array of the LED names and descriptions. [["name1", "description1"], ["name2", "description2"]] + """ + def __init__(self, led_pin, led_polarity=0x00, led_name=[]): + # Documentation + self.intro = ModuleDoc("""LED control. + The LEDs are normal LEDs. Good information. :) + """) + + # HDL Implementationj + self._out = CSRStorage(len(led_pin), fields=[ + CSRField(fld[0], description=fld[1]) for fld in led_name + ]) + self.comb += led_pin.eq(self._out.storage ^ led_polarity) + + # CRG ---------------------------------------------------------------------------------------------- class _CRG(Module): @@ -218,6 +271,25 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi self.add_etherbone(phy=self.ethphy) + # add IO extentions + platform.add_extension(_leds) + + + # LEDs blinkyblinky :) + + self.submodules.leds = Leds(Cat( + platform.request("r"), + platform.request("y"), + platform.request("g")), + led_polarity=0x00, + led_name=[ + ["r", "The Red LED."], + ["y", "The Yellow LED."], + ["g", "The Green Red LED."]]) + + self.add_csr("leds") + + # Helper functions --------------------------------------------------------------------------------- def modify_svd(builder_kwargs): From cb8804c16231922d6dfd41e5e100082f28c3cec8 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Wed, 7 Apr 2021 09:49:24 +0200 Subject: [PATCH 05/36] Accedently pushed to master.. Revert "1. For the colorlight5A-75b V7 there needs to be 0 tx delay, otherwise the PHY doesnt work. 2. The peripheral code has to be inserted at the end of the peripherals list. For me it got inserted at the end after vendorExtentions and this didn't work." This reverts commit 0dc8be337c45411e5589e703cc2d897dba88f4ce. --- soc/colorlight_5a_75x.py | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index b296dd7..c2dd5b4 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -255,15 +255,9 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi # Ethernet / Etherbone --------------------------------------------------------------------- if with_ethernet or with_etherbone: - if board == "5a-75b" and revision == "7.0": - self.submodules.ethphy = LiteEthPHYRGMII( - clock_pads = self.platform.request("eth_clocks", eth_phy), - pads = self.platform.request("eth", eth_phy), - tx_delay = 0e-9) - else: - self.submodules.ethphy = LiteEthPHYRGMII( - clock_pads = self.platform.request("eth_clocks", eth_phy), - pads = self.platform.request("eth", eth_phy)) + self.submodules.ethphy = LiteEthPHYRGMII( + clock_pads = self.platform.request("eth_clocks", eth_phy), + pads = self.platform.request("eth", eth_phy)) self.add_csr("ethphy") if with_ethernet: self.add_ethernet(phy=self.ethphy) @@ -295,14 +289,6 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi def modify_svd(builder_kwargs): # Add Ethernet buffer peripheral to svd with open(builder_kwargs["csr_svd"], "r") as f: - line_number = 0 - for l in f: # search for the right place to insert - line_number += 1 - if """""" in l: - line = line_number - print("inserting before line:") - print(line) - f.seek(0) s = f.readlines() registers = """ ETHMEM @@ -389,7 +375,7 @@ def modify_svd(builder_kwargs): """ - s.insert(line-1, registers) + s.insert(-2, registers) with open(builder_kwargs["csr_svd"], "w") as f: f.writelines(s) From 246728ec88e2c1b6cf3d03f18f42565a61088ccd Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Wed, 7 Apr 2021 09:55:27 +0200 Subject: [PATCH 06/36] Revert "Accedently pushed to master.. Revert "1. For the colorlight5A-75b V7 there needs to be 0 tx delay, otherwise the PHY doesnt work. 2. The peripheral code has to be inserted at the end of the peripherals list. For me it got inserted at the end after vendorExtentions and this didn't work."" This reverts commit cb8804c16231922d6dfd41e5e100082f28c3cec8. --- soc/colorlight_5a_75x.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index c2dd5b4..b296dd7 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -255,9 +255,15 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi # Ethernet / Etherbone --------------------------------------------------------------------- if with_ethernet or with_etherbone: - self.submodules.ethphy = LiteEthPHYRGMII( - clock_pads = self.platform.request("eth_clocks", eth_phy), - pads = self.platform.request("eth", eth_phy)) + if board == "5a-75b" and revision == "7.0": + self.submodules.ethphy = LiteEthPHYRGMII( + clock_pads = self.platform.request("eth_clocks", eth_phy), + pads = self.platform.request("eth", eth_phy), + tx_delay = 0e-9) + else: + self.submodules.ethphy = LiteEthPHYRGMII( + clock_pads = self.platform.request("eth_clocks", eth_phy), + pads = self.platform.request("eth", eth_phy)) self.add_csr("ethphy") if with_ethernet: self.add_ethernet(phy=self.ethphy) @@ -289,6 +295,14 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi def modify_svd(builder_kwargs): # Add Ethernet buffer peripheral to svd with open(builder_kwargs["csr_svd"], "r") as f: + line_number = 0 + for l in f: # search for the right place to insert + line_number += 1 + if """""" in l: + line = line_number + print("inserting before line:") + print(line) + f.seek(0) s = f.readlines() registers = """ ETHMEM @@ -375,7 +389,7 @@ def modify_svd(builder_kwargs): """ - s.insert(-2, registers) + s.insert(line-1, registers) with open(builder_kwargs["csr_svd"], "w") as f: f.writelines(s) From c89baad2799cb61ab3b0b4c44f26847e76bdc76c Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Wed, 7 Apr 2021 09:56:44 +0200 Subject: [PATCH 07/36] Thats what I wanted to revert.. Revert "commit build outputs for me" This reverts commit 071f0bb40385f25ee71418a546cd073552f5fc08. --- rust/litex-pac/clSOC.svd | 344 ++++++++++++++++++++++----------------- rust/litex-pac/memory.x | 4 +- 2 files changed, 201 insertions(+), 147 deletions(-) diff --git a/rust/litex-pac/clSOC.svd b/rust/litex-pac/clSOC.svd index cd819e2..1a16422 100644 --- a/rust/litex-pac/clSOC.svd +++ b/rust/litex-pac/clSOC.svd @@ -2,7 +2,7 @@ litex - SOC + ETHMAC 8 32 @@ -14,15 +14,16 @@ CTRL - 0xF0000000 + 0xE0000000 CTRL RESET - + 0x0000 0x00 32 + read-write reset @@ -40,6 +41,7 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of 0x0004 0x12345678 32 + read-write scratch @@ -55,6 +57,7 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of 0x0008 0x00 32 + read-only bus_errors @@ -73,7 +76,7 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of IDENTIFIER_MEM - 0xF0001000 + 0xE0001000 IDENTIFIER_MEM @@ -82,6 +85,7 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of 0x0000 0x00 32 + read-write identifier_mem @@ -98,9 +102,36 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of registers + + UART_PHY + 0xE0001800 + UART_PHY + + + TUNING_WORD + 0x0000 + 0x96feb4 + 32 + read-write + + + tuning_word + 31 + [31:0] + 0 + + + + + + 0 + 0x4 + registers + + UART - 0xF0002000 + 0xE0002000 UART @@ -108,6 +139,7 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of 0x0000 0x00 32 + read-write rxtx @@ -122,6 +154,7 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of 0x0004 0x00 32 + read-only txfull @@ -136,6 +169,7 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of 0x0008 0x00 32 + read-only rxempty @@ -147,73 +181,46 @@ to the Wishbone/CSR bus are working correctly. The initial reset value of EV_STATUS - 0x000c 0x00 32 + read-write - tx - 0 - [0:0] - 0 - - - - rx + status 1 - [1:1] - 1 - + [1:0] + 0 EV_PENDING - 0x0010 0x00 32 + read-write - tx - 0 - [0:0] - 0 - - - - rx + pending 1 - [1:1] - 1 - + [1:0] + 0 EV_ENABLE - 0x0014 0x00 32 + read-write - tx - 0 - [0:0] - 0 - - - - rx + enable 1 - [1:1] - 1 - + [1:0] + 0 @@ -222,6 +229,7 @@ register to disable individual events.]]> 0x0018 0x00 32 + read-only txempty @@ -236,6 +244,7 @@ register to disable individual events.]]> 0x001c 0x00 32 + read-only rxfull @@ -258,7 +267,7 @@ register to disable individual events.]]> TIMER0 - 0xF0002800 + 0xE0002800 TIMER0 @@ -268,6 +277,7 @@ this register specifies the Timer's duration in clock cycles.]]> 0x0000 0x00 32 + read-write load @@ -284,6 +294,7 @@ this register specify the Timer's period in clock cycles.]]> 0x0004 0x00 32 + read-write reload @@ -300,6 +311,7 @@ to ``0`` to disable the Timer.]]> 0x0008 0x00 32 + read-write en @@ -316,6 +328,7 @@ the current countdown value to ``value`` register.]]> 0x000c 0x00 32 + read-write update_value @@ -331,6 +344,7 @@ the current countdown value to ``value`` register.]]> 0x0010 0x00 32 + read-only value @@ -342,52 +356,46 @@ the current countdown value to ``value`` register.]]> EV_STATUS - 0x0014 0x00 32 + read-write - zero + status 0 [0:0] 0 - EV_PENDING - 0x0018 0x00 32 + read-write - zero + pending 0 [0:0] 0 - EV_ENABLE - 0x001c 0x00 32 + read-write - zero + enable 0 [0:0] 0 - @@ -404,7 +412,7 @@ register to disable individual events.]]> SDRAM - 0xF0003000 + 0xE0003000 SDRAM @@ -412,6 +420,7 @@ register to disable individual events.]]> 0x0000 0x01 32 + read-write sel @@ -448,6 +457,7 @@ register to disable individual events.]]> 0x0004 0x00 32 + read-write dfii_pi0_command @@ -462,6 +472,7 @@ register to disable individual events.]]> 0x0008 0x00 32 + read-write dfii_pi0_command_issue @@ -476,6 +487,7 @@ register to disable individual events.]]> 0x000c 0x00 32 + read-write dfii_pi0_address @@ -490,11 +502,12 @@ register to disable individual events.]]> 0x0010 0x00 32 + read-write dfii_pi0_baddress - 0 - [0:0] + 1 + [1:0] 0 @@ -504,6 +517,7 @@ register to disable individual events.]]> 0x0014 0x00 32 + read-write dfii_pi0_wrdata @@ -518,6 +532,7 @@ register to disable individual events.]]> 0x0018 0x00 32 + read-only dfii_pi0_rddata @@ -527,16 +542,106 @@ register to disable individual events.]]> + + DFII_PI1_COMMAND + 0x001c + 0x00 + 32 + read-write + + + dfii_pi1_command + 5 + [5:0] + 0 + + + + + DFII_PI1_COMMAND_ISSUE + 0x0020 + 0x00 + 32 + read-write + + + dfii_pi1_command_issue + 0 + [0:0] + 0 + + + + + DFII_PI1_ADDRESS + 0x0024 + 0x00 + 32 + read-write + + + dfii_pi1_address + 10 + [10:0] + 0 + + + + + DFII_PI1_BADDRESS + 0x0028 + 0x00 + 32 + read-write + + + dfii_pi1_baddress + 1 + [1:0] + 0 + + + + + DFII_PI1_WRDATA + 0x002c + 0x00 + 32 + read-write + + + dfii_pi1_wrdata + 31 + [31:0] + 0 + + + + + DFII_PI1_RDDATA + 0x0030 + 0x00 + 32 + read-only + + + dfii_pi1_rddata + 31 + [31:0] + 0 + + + 0 - 0x1c + 0x34 registers SPIFLASH - 0xF0003800 + 0xE0003800 SPIFLASH @@ -545,6 +650,7 @@ register to disable individual events.]]> 0x0000 0x00 32 + read-write mosi @@ -582,6 +688,7 @@ register to disable individual events.]]> 0x0004 0x00 32 + read-only miso @@ -597,6 +704,7 @@ register to disable individual events.]]> 0x0008 0x00 32 + read-write bitbang_en @@ -615,7 +723,7 @@ register to disable individual events.]]> ETHPHY - 0xF0004000 + 0xE0004000 ETHPHY @@ -623,6 +731,7 @@ register to disable individual events.]]> 0x0000 0x00 32 + read-write crg_reset @@ -637,6 +746,7 @@ register to disable individual events.]]> 0x0004 0x00 32 + read-only link_status @@ -666,6 +776,7 @@ register to disable individual events.]]> 0x0008 0x00 32 + read-write mdc @@ -695,6 +806,7 @@ register to disable individual events.]]> 0x000c 0x00 32 + read-only r @@ -714,7 +826,7 @@ register to disable individual events.]]> ETHMAC - 0xF0004800 + 0xE0004800 ETHMAC @@ -722,6 +834,7 @@ register to disable individual events.]]> 0x0000 0x00 32 + read-only sram_writer_slot @@ -736,6 +849,7 @@ register to disable individual events.]]> 0x0004 0x00 32 + read-only sram_writer_length @@ -750,6 +864,7 @@ register to disable individual events.]]> 0x0008 0x00 32 + read-only sram_writer_errors @@ -761,53 +876,46 @@ register to disable individual events.]]> SRAM_WRITER_EV_STATUS - 0x000c 0x00 32 + read-write - available + sram_writer_ev_status 0 [0:0] 0 - SRAM_WRITER_EV_PENDING - 0x0010 0x00 32 + read-write - available + sram_writer_ev_pending 0 [0:0] 0 - SRAM_WRITER_EV_ENABLE - 0x0014 0x00 32 + read-write - available + sram_writer_ev_enable 0 [0:0] 0 - @@ -816,6 +924,7 @@ register to disable individual events.]]> 0x0018 0x00 32 + read-write sram_reader_start @@ -830,6 +939,7 @@ register to disable individual events.]]> 0x001c 0x00 32 + read-only sram_reader_ready @@ -844,6 +954,7 @@ register to disable individual events.]]> 0x0020 0x00 32 + read-only sram_reader_level @@ -858,6 +969,7 @@ register to disable individual events.]]> 0x0024 0x00 32 + read-write sram_reader_slot @@ -872,6 +984,7 @@ register to disable individual events.]]> 0x0028 0x00 32 + read-write sram_reader_length @@ -883,52 +996,46 @@ register to disable individual events.]]> SRAM_READER_EV_STATUS - 0x002c 0x00 32 + read-write - done + sram_reader_ev_status 0 [0:0] 0 - SRAM_READER_EV_PENDING - 0x0030 0x00 32 + read-write - done + sram_reader_ev_pending 0 [0:0] 0 - SRAM_READER_EV_ENABLE - 0x0034 0x00 32 + read-write - done + sram_reader_ev_enable 0 [0:0] 0 - @@ -937,6 +1044,7 @@ register to disable individual events.]]> 0x0038 0x01 32 + read-only preamble_crc @@ -951,6 +1059,7 @@ register to disable individual events.]]> 0x003c 0x00 32 + read-only preamble_errors @@ -965,6 +1074,7 @@ register to disable individual events.]]> 0x0040 0x00 32 + read-only crc_errors @@ -1111,60 +1221,4 @@ register to disable individual events.]]> - - - - SRAM - 0x10000000 - 0x00002000 - - - MAIN_RAM - 0x40000000 - 0x00400000 - - - SPIFLASH - 0x20000000 - 0x02000000 - - - ROM - 0x20100000 - 0x01F00000 - - - ETHMAC - 0x80000000 - 0x00002000 - - - CSR - 0xF0000000 - 0x00010000 - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/rust/litex-pac/memory.x b/rust/litex-pac/memory.x index 7d37e38..2ac22b8 100644 --- a/rust/litex-pac/memory.x +++ b/rust/litex-pac/memory.x @@ -1,10 +1,10 @@ MEMORY { sram : ORIGIN = 0x10000000, LENGTH = 0x00002000 - main_ram : ORIGIN = 0x40000000, LENGTH = 0x00400000 + main_ram : ORIGIN = 0x40000000, LENGTH = 0x00800000 spiflash : ORIGIN = 0x20000000, LENGTH = 0x02000000 rom : ORIGIN = 0x20100000, LENGTH = 0x01f00000 ethmac : ORIGIN = 0x80000000, LENGTH = 0x00002000 - csr : ORIGIN = 0xf0000000, LENGTH = 0x00010000 + csr : ORIGIN = 0xe0000000, LENGTH = 0x00010000 } REGION_ALIAS("REGION_TEXT", spiflash); From ddacad2053ecf5dd8066d80c19f64e07994c7262 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Wed, 7 Apr 2021 09:57:05 +0200 Subject: [PATCH 08/36] And that. Revert "blinkyblinkyblink :)" This reverts commit cd3d9b4e938d162cd24fdff938c2824dc9421b6a. --- rust/eth_demo/src/leds.rs | 50 --------------------------- rust/eth_demo/src/main.rs | 7 ---- rust/litex-pac/clSOC.svd | 41 ---------------------- soc/colorlight_5a_75x.py | 72 --------------------------------------- 4 files changed, 170 deletions(-) delete mode 100644 rust/eth_demo/src/leds.rs diff --git a/rust/eth_demo/src/leds.rs b/rust/eth_demo/src/leds.rs deleted file mode 100644 index 52a1712..0000000 --- a/rust/eth_demo/src/leds.rs +++ /dev/null @@ -1,50 +0,0 @@ -use litex_pac::LEDS; - -pub struct Leds { - registers: LEDS, -} - -#[allow(dead_code)] -impl Leds { - pub fn new(registers: LEDS) -> Self { - Self { registers } - } - - pub fn set_single(&mut self, red: bool, yellow: bool, - green: bool) { - self.registers.out.write(|w| { - w.r().bit(red); - w.g().bit(green); - w.y().bit(yellow) - }); - } - - pub fn set(&mut self, leds: u32) { - unsafe { - self.registers.out.write(|w| w.bits(leds)); - } - } - - pub fn off(&mut self) { - unsafe { - self.registers.out.write(|w| w.bits(0x0000_0000)); - } - } - - pub fn on(&mut self) { - unsafe { - self.registers.out.write(|w| w.bits(0xFFFF_FFFF)); - } - } - - pub fn toggle(&mut self) { - self.toggle_mask(0xFFFF_FFFF); - } - - pub fn toggle_mask(&mut self, mask: u32) { - let val: u32 = self.registers.out.read().bits() ^ mask; - unsafe { - self.registers.out.write(|w| w.bits(val)); - } - } -} diff --git a/rust/eth_demo/src/main.rs b/rust/eth_demo/src/main.rs index 3eb349f..876ec3c 100644 --- a/rust/eth_demo/src/main.rs +++ b/rust/eth_demo/src/main.rs @@ -9,11 +9,9 @@ use riscv_rt::entry; mod ethernet; mod print; mod timer; -mod leds; use crate::ethernet::Eth; use timer::Timer; -use leds::Leds; use managed::ManagedSlice; use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache}; @@ -64,8 +62,6 @@ fn main() -> ! { let mut timer = Timer::new(peripherals.TIMER0); - let mut leds = Leds::new(peripherals.LEDS); - let clock = mock::Clock::new(); let device = Eth::new(peripherals.ETHMAC, peripherals.ETHMEM); @@ -181,9 +177,6 @@ fn main() -> ! { None => clock.advance(Duration::from_millis(1)), } trace!("Clock elapsed: {}", clock.elapsed()); - - msleep(&mut timer, 1000 as u32); - leds.toggle(); } } diff --git a/rust/litex-pac/clSOC.svd b/rust/litex-pac/clSOC.svd index 1a16422..1596c26 100644 --- a/rust/litex-pac/clSOC.svd +++ b/rust/litex-pac/clSOC.svd @@ -1095,47 +1095,6 @@ the current countdown value to ``value`` register.]]> 2 - - LEDS - 0xF0005000 - LEDS - - - OUT - 0x0000 - 0x00 - 32 - - - r - 0 - [0:0] - 0 - - - - y - 1 - [1:1] - 1 - - - - g - 2 - [2:2] - 2 - - - - - - - 0 - 0x4 - registers - - ETHMEM 0x80000000 diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index b296dd7..08908f0 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -26,7 +26,6 @@ from litex.soc.integration.builder import Builder, builder_argdict, builder_args from litex.soc.integration.soc_core import soc_core_argdict, soc_core_args from litex.soc.interconnect.csr import AutoCSR, CSRStorage, CSRStatus, CSRField -from litex.soc.integration.doc import AutoDoc, ModuleDoc from litex.build.generic_platform import * @@ -49,58 +48,6 @@ def load_bitstream(self, bitstream_file): subprocess.call(["ecpprog", "-S", bitstream_file]) -# My IOs ------------------------------------------------------------------------------------------- - -_dac = [ - ("dac", 0, Pins("j4:0"), IOStandard("LVCMOS33")), - ("dac", 1, Pins("j4:1"), IOStandard("LVCMOS33")), # sigma-delta dac output -] - -_leds = [ - ("g", 0, Pins("j6:5"), IOStandard("LVCMOS33")), - ("r", 0, Pins("j6:7"), IOStandard("LVCMOS33")), - ("y", 0, Pins("j6:9"), IOStandard("LVCMOS33")), -] - -_adc_first_order = [ - ("in", 0, Pins("j1:1"), IOStandard("LVDS")), - ("sd", 0, Pins("j1:2"), IOStandard("LVCMOS33")), # sigma delta out - ("p3v", 0, Pins("j1:0"), IOStandard("LVCMOS33")), # this will make 3V on the connector - ("p5v", 0, Pins("j1:14"), IOStandard("LVCMOS33")), # this will make 5V on the connector bc buffer IC -] - -_adc_second_order = [ - ("in", 0, Pins("j1:1"), IOStandard("LVDS")), - ("sd", 0, Pins("j1:5"), IOStandard("LVCMOS33")), # sigma delta out - ("sd", 1, Pins("j1:7"), IOStandard("LVCMOS33")), # sigma delta out - ("p3v", 0, Pins("j1:0"), IOStandard("LVCMOS33")), # this will make 3V on the connector - ("p5v", 0, Pins("j1:14"), IOStandard("LVCMOS33")), # this will make 5V on the connector bc buffer IC -] - - -# LEDs --------------------------------------------------------------------------------------------- - -class Leds(Module, AutoCSR, AutoDoc): - """LED control. - 3 LEDs connected to random IOs - Attributes: - led_pin: Signals of the LED pin outputs. - led_polarity: Bit pattern to adjust polarity. 0 stays the same 1 inverts the signal. - led_name: Array of the LED names and descriptions. [["name1", "description1"], ["name2", "description2"]] - """ - def __init__(self, led_pin, led_polarity=0x00, led_name=[]): - # Documentation - self.intro = ModuleDoc("""LED control. - The LEDs are normal LEDs. Good information. :) - """) - - # HDL Implementationj - self._out = CSRStorage(len(led_pin), fields=[ - CSRField(fld[0], description=fld[1]) for fld in led_name - ]) - self.comb += led_pin.eq(self._out.storage ^ led_polarity) - - # CRG ---------------------------------------------------------------------------------------------- class _CRG(Module): @@ -271,25 +218,6 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi self.add_etherbone(phy=self.ethphy) - # add IO extentions - platform.add_extension(_leds) - - - # LEDs blinkyblinky :) - - self.submodules.leds = Leds(Cat( - platform.request("r"), - platform.request("y"), - platform.request("g")), - led_polarity=0x00, - led_name=[ - ["r", "The Red LED."], - ["y", "The Yellow LED."], - ["g", "The Green Red LED."]]) - - self.add_csr("leds") - - # Helper functions --------------------------------------------------------------------------------- def modify_svd(builder_kwargs): From abeb9d335357da89d323e3d522e01f6c0d411be0 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Sun, 11 Apr 2021 14:11:12 +0200 Subject: [PATCH 09/36] adc with csr and data transmition via TCP and uart working --- python/recieve.py | 8 ++ python/socket | 0 rust/{eth_demo => adc_eth_test}/.cargo/config | 0 .../.cargo/flash.sh | 0 rust/{eth_demo => adc_eth_test}/Cargo.lock | 36 +++++---- rust/{eth_demo => adc_eth_test}/Cargo.toml | 7 +- rust/{eth_demo => adc_eth_test}/README.md | 0 rust/adc_eth_test/src/adc.rs | 17 ++++ .../src/ethernet.rs | 0 rust/{eth_demo => adc_eth_test}/src/leds.rs | 0 rust/adc_eth_test/src/macro_test.rs | 7 ++ rust/{eth_demo => adc_eth_test}/src/main.rs | 61 ++++++++------ rust/{eth_demo => adc_eth_test}/src/print.rs | 0 rust/{eth_demo => adc_eth_test}/src/timer.rs | 0 rust/litex-pac/clSOC.svd | 27 +++++++ soc/adc.py | 79 +++++++++++++++++++ soc/colorlight_5a_75x.py | 47 ++++++++++- 17 files changed, 248 insertions(+), 41 deletions(-) create mode 100755 python/recieve.py create mode 100644 python/socket rename rust/{eth_demo => adc_eth_test}/.cargo/config (100%) rename rust/{eth_demo => adc_eth_test}/.cargo/flash.sh (100%) rename rust/{eth_demo => adc_eth_test}/Cargo.lock (98%) rename rust/{eth_demo => adc_eth_test}/Cargo.toml (88%) rename rust/{eth_demo => adc_eth_test}/README.md (100%) create mode 100644 rust/adc_eth_test/src/adc.rs rename rust/{eth_demo => adc_eth_test}/src/ethernet.rs (100%) rename rust/{eth_demo => adc_eth_test}/src/leds.rs (100%) create mode 100644 rust/adc_eth_test/src/macro_test.rs rename rust/{eth_demo => adc_eth_test}/src/main.rs (87%) rename rust/{eth_demo => adc_eth_test}/src/print.rs (100%) rename rust/{eth_demo => adc_eth_test}/src/timer.rs (100%) create mode 100644 soc/adc.py diff --git a/python/recieve.py b/python/recieve.py new file mode 100755 index 0000000..b05faa9 --- /dev/null +++ b/python/recieve.py @@ -0,0 +1,8 @@ +import socket + +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.connect(('192.168.1.50', 1234)) + +msg = s.recv(1024) + +print([x for x in msg]) \ No newline at end of file diff --git a/python/socket b/python/socket new file mode 100644 index 0000000..e69de29 diff --git a/rust/eth_demo/.cargo/config b/rust/adc_eth_test/.cargo/config similarity index 100% rename from rust/eth_demo/.cargo/config rename to rust/adc_eth_test/.cargo/config diff --git a/rust/eth_demo/.cargo/flash.sh b/rust/adc_eth_test/.cargo/flash.sh similarity index 100% rename from rust/eth_demo/.cargo/flash.sh rename to rust/adc_eth_test/.cargo/flash.sh diff --git a/rust/eth_demo/Cargo.lock b/rust/adc_eth_test/Cargo.lock similarity index 98% rename from rust/eth_demo/Cargo.lock rename to rust/adc_eth_test/Cargo.lock index a02c090..4e520a7 100644 --- a/rust/eth_demo/Cargo.lock +++ b/rust/adc_eth_test/Cargo.lock @@ -1,5 +1,19 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "adc_test" +version = "0.1.0" +dependencies = [ + "litex-pac", + "log", + "managed", + "panic-halt", + "riscv", + "riscv-rt", + "smoltcp", + "vexriscv", +] + [[package]] name = "addr2line" version = "0.13.0" @@ -87,9 +101,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "byteorder" -version = "1.3.4" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cast" @@ -150,18 +164,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "eth_demo" -version = "0.1.0" -dependencies = [ - "litex-pac", - "log", - "managed", - "panic-halt", - "riscv-rt", - "smoltcp", -] - [[package]] name = "gimli" version = "0.22.0" @@ -574,6 +576,12 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +[[package]] +name = "vexriscv" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eac3d398d0468c76272ea6b2c187d3696f0ed126325f8f41ccc711e9e74cd06" + [[package]] name = "winapi" version = "0.3.9" diff --git a/rust/eth_demo/Cargo.toml b/rust/adc_eth_test/Cargo.toml similarity index 88% rename from rust/eth_demo/Cargo.toml rename to rust/adc_eth_test/Cargo.toml index 1988207..c61aa7b 100644 --- a/rust/eth_demo/Cargo.toml +++ b/rust/adc_eth_test/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "eth_demo" +name = "adc_test" version = "0.1.0" -authors = ["Piotr Esden-Tempski ", "DerFetzer "] +authors = ["Piotr Esden-Tempski ", "DerFetzer ", "SingularitySurfer"] edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -9,6 +9,8 @@ edition = "2018" [dependencies] litex-pac = { path = "../litex-pac" } riscv-rt = "0.8.0" +riscv = "0.6.0" +vexriscv = "0.0.3" panic-halt = "0.2" log = "0.4.11" smoltcp = { version = "0.6", default-features = false, features = ["ethernet", "proto-ipv4", "socket-udp" ,"socket-tcp", "log"] } @@ -22,4 +24,3 @@ debug = true # Improve code generation lto = true codegen-units = 1 - diff --git a/rust/eth_demo/README.md b/rust/adc_eth_test/README.md similarity index 100% rename from rust/eth_demo/README.md rename to rust/adc_eth_test/README.md diff --git a/rust/adc_eth_test/src/adc.rs b/rust/adc_eth_test/src/adc.rs new file mode 100644 index 0000000..da4927b --- /dev/null +++ b/rust/adc_eth_test/src/adc.rs @@ -0,0 +1,17 @@ +use litex_pac::ADC; + +pub struct Adc { + registers: ADC, +} + +#[allow(dead_code)] +impl Adc { + pub fn new(registers: ADC) -> Self { + Self { registers } + } + + pub fn read(&mut self) -> u32 { + self.registers.adc_value.read().bits() + } + +} diff --git a/rust/eth_demo/src/ethernet.rs b/rust/adc_eth_test/src/ethernet.rs similarity index 100% rename from rust/eth_demo/src/ethernet.rs rename to rust/adc_eth_test/src/ethernet.rs diff --git a/rust/eth_demo/src/leds.rs b/rust/adc_eth_test/src/leds.rs similarity index 100% rename from rust/eth_demo/src/leds.rs rename to rust/adc_eth_test/src/leds.rs diff --git a/rust/adc_eth_test/src/macro_test.rs b/rust/adc_eth_test/src/macro_test.rs new file mode 100644 index 0000000..21e1db5 --- /dev/null +++ b/rust/adc_eth_test/src/macro_test.rs @@ -0,0 +1,7 @@ + +pub mod bazmod { + #[macro_export] + macro_rules! baz { + () => () + } +} diff --git a/rust/eth_demo/src/main.rs b/rust/adc_eth_test/src/main.rs similarity index 87% rename from rust/eth_demo/src/main.rs rename to rust/adc_eth_test/src/main.rs index 3eb349f..b2499b1 100644 --- a/rust/eth_demo/src/main.rs +++ b/rust/adc_eth_test/src/main.rs @@ -1,19 +1,23 @@ #![no_std] #![no_main] - extern crate panic_halt; + +// use litex_pac::baz; use litex_pac; use riscv_rt::entry; + mod ethernet; mod print; mod timer; mod leds; +mod adc; use crate::ethernet::Eth; use timer::Timer; use leds::Leds; +use adc::Adc; use managed::ManagedSlice; use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache}; @@ -26,8 +30,18 @@ use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; use crate::print::UartLogger; use log::{debug, info, trace}; + + const SYSTEM_CLOCK_FREQUENCY: u32 = 49_600_000; + + +// interrupt::interrupt!(TIMER0, isr); + +// fn isr(){ +// let a = 1 + 2; +// } + mod mock { use core::cell::Cell; use smoltcp::time::{Duration, Instant}; @@ -66,6 +80,8 @@ fn main() -> ! { let mut leds = Leds::new(peripherals.LEDS); + let mut adc = Adc::new(peripherals.ADC); + let clock = mock::Clock::new(); let device = Eth::new(peripherals.ETHMAC, peripherals.ETHMEM); @@ -126,6 +142,8 @@ fn main() -> ! { let tcp_server_handle = socket_set.add(tcp_server_socket); let udp_server_handle = socket_set.add(udp_server_socket); + let mut vec: [u8; 5] = [1,2,3,4,5]; + info!("Main loop..."); loop { @@ -146,31 +164,23 @@ fn main() -> ! { if socket.can_send() { info!("Can send..."); - socket.send_slice(b"Hello World!\r\n").unwrap(); - socket.close(); + socket.send_slice(&vec).unwrap(); } - } - { - let mut socket = socket_set.get::(udp_server_handle); - if !socket.is_open() { - socket.bind(5678).unwrap() - } + msleep(&mut timer, 1000 as u32); + vec.rotate_right(1); + leds.toggle(); - let client = match socket.recv() { - Ok((data, endpoint)) => { - debug!("udp:5678 recv data: {:?} from {}", data, endpoint); - Some(endpoint) - } - Err(_) => None, - }; - if let Some(endpoint) = client { - let data = b"Hello World!\r\n"; - debug!("udp:5678 send data: {:?}", data); - socket.send_slice(data, endpoint).unwrap(); + let adcval: u32 = adc.read(); + + if socket.can_send() { + socket.send_slice(&adcval.to_be_bytes()).unwrap(); } + + info!("adcval: {}", adcval); } + match iface.poll_delay(&socket_set, clock.elapsed()) { Some(Duration { millis: 0 }) => {} Some(delay) => { @@ -182,11 +192,18 @@ fn main() -> ! { } trace!("Clock elapsed: {}", clock.elapsed()); - msleep(&mut timer, 1000 as u32); - leds.toggle(); + } } +fn u32_to_u8(x:u32) -> [u8;4] { + let b1 : u8 = ((x >> 24) & 0xff) as u8; + let b2 : u8 = ((x >> 16) & 0xff) as u8; + let b3 : u8 = ((x >> 8) & 0xff) as u8; + let b4 : u8 = (x & 0xff) as u8; + return [b1, b2, b3, b4] +} + fn msleep(timer: &mut Timer, ms: u32) { timer.disable(); diff --git a/rust/eth_demo/src/print.rs b/rust/adc_eth_test/src/print.rs similarity index 100% rename from rust/eth_demo/src/print.rs rename to rust/adc_eth_test/src/print.rs diff --git a/rust/eth_demo/src/timer.rs b/rust/adc_eth_test/src/timer.rs similarity index 100% rename from rust/eth_demo/src/timer.rs rename to rust/adc_eth_test/src/timer.rs diff --git a/rust/litex-pac/clSOC.svd b/rust/litex-pac/clSOC.svd index cd819e2..67c28ae 100644 --- a/rust/litex-pac/clSOC.svd +++ b/rust/litex-pac/clSOC.svd @@ -1026,6 +1026,33 @@ register to disable individual events.]]> registers + + ADC + 0xF0005800 + ADC + + + ADC_VALUE + + 0x0000 + 0x00 + 32 + + + adc_value + 31 + [31:0] + 0 + + + + + + 0 + 0x4 + registers + + ETHMEM 0x80000000 diff --git a/soc/adc.py b/soc/adc.py new file mode 100644 index 0000000..383dcdd --- /dev/null +++ b/soc/adc.py @@ -0,0 +1,79 @@ +# SingularitySurfer 2020 + + +import numpy as np +from migen import * +from litex.soc.interconnect.csr import * +from functools import reduce +from operator import and_ + + +class ADC(Module, AutoCSR): + """Basic sigma-delta ADC with a CIC decimator running at sys clock. + The decimator gain is such that the output bitwidth will always be maximized. + """ + def __init__(self, cic_order=6, cic_ratechange=2**7, width_o=32): + self.inp = Signal() # analog in + self.sd = Signal() # sigma-delta switching pin + self.dout = Signal(width_o) + self.stb = Signal() # data out strobe + ### + + width_csr = 32 + self.adc_val = CSRStatus(width_csr, name="adc_value", description="adc conversion value (continuously updated)") + + + if not(cic_ratechange & (cic_ratechange-1) == 0) and not cic_ratechange != 0: + raise ValueError() # not a power of two + + b_max = np.ceil(np.log2(cic_ratechange)) # max bit growth + + self.sync += [ # do the sigma-delta + self.sd.eq(self.inp) + ] + + width = (int(b_max)*cic_order)+1 + sig = Signal((width, True), reset_less=True) + self.comb += sig.eq(self.sd) + for _ in range(cic_order): # integrator cascade + sum = Signal((width, True), reset_less=True) + self.sync += [ + sum.eq(sum + sig) + ] + sig = sum + + cnt = Signal(int(b_max)) + self.sync += cnt.eq(cnt+1) + for _ in range(cic_order): # comb cascade + dif = Signal((width, True), reset_less=True) + reg = Signal((width, True), reset_less=True) + self.sync += [ + self.stb.eq(0), + If(reduce(and_, cnt), # counter up and therefore new output sample + self.stb.eq(1), + reg.eq(sig), + dif.eq(sig - reg) + ) + ] + sig = dif + + self.comb += self.dout.eq(sig[-width_o:]) # highest bits are the data output + self.sync += self.adc_val.status.eq(sig[-width_csr:]) # continuously update CSR + + + def sim(self): + yield + yield self.inp.eq(1) + for i in range(10000): + yield + if(i==3000): + yield self.inp.eq(~self.inp) + if (i == 5000): + yield self.inp.eq(~self.inp) + if i>7000: + yield self.inp.eq(~self.inp) + + +if __name__ == "__main__": + test = ADC(6,2**8,16) + run_simulation(test, test.sim(), vcd_name="adc.vcd") \ No newline at end of file diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index b296dd7..6c460cf 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -38,6 +38,8 @@ import litex.soc.doc as lxsocdoc +from adc import ADC + class ECP5Programmer(GenericProgrammer): needs_bitreverse = False @@ -51,6 +53,18 @@ def load_bitstream(self, bitstream_file): # My IOs ------------------------------------------------------------------------------------------- + Subsignal("tx", Pins("P11")), # led (J19 DATA_LED-) + Subsignal("rx", Pins("M13")), # btn (J19 KEY+) + IOStandard("LVCMOS33") + +_myserial = [ + ("myserial", 0, + Subsignal("tx", Pins("j1:14")), + Subsignal("rx", Pins("j1:13")), + IOStandard("LVCMOS33") + ) +] + _dac = [ ("dac", 0, Pins("j4:0"), IOStandard("LVCMOS33")), ("dac", 1, Pins("j4:1"), IOStandard("LVCMOS33")), # sigma-delta dac output @@ -58,7 +72,7 @@ def load_bitstream(self, bitstream_file): _leds = [ ("g", 0, Pins("j6:5"), IOStandard("LVCMOS33")), - ("r", 0, Pins("j6:7"), IOStandard("LVCMOS33")), + ("r", 0, Pins("j6:10"), IOStandard("LVCMOS33")), # Not really here but there is congestion with the pins otherwise.. ("y", 0, Pins("j6:9"), IOStandard("LVCMOS33")), ] @@ -72,7 +86,7 @@ def load_bitstream(self, bitstream_file): _adc_second_order = [ ("in", 0, Pins("j1:1"), IOStandard("LVDS")), ("sd", 0, Pins("j1:5"), IOStandard("LVCMOS33")), # sigma delta out - ("sd", 1, Pins("j1:7"), IOStandard("LVCMOS33")), # sigma delta out + ("sd", 1, Pins("j1:7"), IOStandard("LVCMOS33")), # sigma delta out (copy of first) ("p3v", 0, Pins("j1:0"), IOStandard("LVCMOS33")), # this will make 3V on the connector ("p5v", 0, Pins("j1:14"), IOStandard("LVCMOS33")), # this will make 5V on the connector bc buffer IC ] @@ -185,6 +199,9 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi if board == "5a-75e" and revision == "6.0" and (with_etherbone or with_ethernet): assert use_internal_osc, "You cannot use the 25MHz clock as system clock since it is provided by the Ethernet PHY and will stop during PHY reset." + # add custom serial port ios + platform.add_extension(_myserial) + # Set cpu name and variant defaults when none are provided if "cpu_variant" not in kwargs: if debug: @@ -200,6 +217,9 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi # Set CPU reset address kwargs["cpu_reset_address"] = self.mem_map["spiflash"] + flash_offset + # defaul uart myserial + kwargs["uart_name"] = "myserial" + # Select "crossover" as soc uart instead of "serial" # We have to make that selection before calling the parent initializer if debug: @@ -273,6 +293,7 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi # add IO extentions platform.add_extension(_leds) + platform.add_extension(_adc_second_order) # LEDs blinkyblinky :) @@ -290,6 +311,28 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi self.add_csr("leds") + # sigma delta ADC using lame CSR for now + + self.submodules.adc = adc = ADC() + + adc_in = platform.request("in") + adc_sd = platform.request("sd", 0) + adc_sd2 = platform.request("sd", 1) + #p5v = platform.request("p5v") + p3v = platform.request("p3v") + + self.comb += [ + adc.inp.eq(adc_in), + adc_sd.eq(adc.sd), + adc_sd2.eq(adc.sd), + #p5v.eq(1), + p3v.eq(1), + ] + + self.add_csr("adc") + + + # Helper functions --------------------------------------------------------------------------------- def modify_svd(builder_kwargs): From a464df1d03bd251f953ef93a9354ffb42909475f Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Tue, 13 Apr 2021 14:38:50 +0200 Subject: [PATCH 10/36] yay, interrupts are doing something at least! --- rust/adc_eth_test/src/main.rs | 61 +++++++++++++++++++++++++++++----- rust/adc_eth_test/src/timer.rs | 6 ++++ 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/rust/adc_eth_test/src/main.rs b/rust/adc_eth_test/src/main.rs index b2499b1..8eea433 100644 --- a/rust/adc_eth_test/src/main.rs +++ b/rust/adc_eth_test/src/main.rs @@ -3,10 +3,14 @@ extern crate panic_halt; -// use litex_pac::baz; +extern crate riscv; +extern crate riscv_rt; use litex_pac; use riscv_rt::entry; +use vexriscv::register::{vdci, vmim, vmip, vsim, vsip}; +use riscv::register::{mstatus, mcause, mie}; + mod ethernet; mod print; @@ -170,14 +174,42 @@ fn main() -> ! { msleep(&mut timer, 1000 as u32); vec.rotate_right(1); leds.toggle(); - - let adcval: u32 = adc.read(); - - if socket.can_send() { - socket.send_slice(&adcval.to_be_bytes()).unwrap(); + // + // let adcval: u32 = adc.read(); + // + // if socket.can_send() { + // socket.send_slice(&adcval.to_be_bytes()).unwrap(); + // } + + info!("\nbefore:"); + info!("vmip: {}", vmip::read()); + info!("vmim: {}", vmim::read()); + info!("mcause: {}", mcause::read().bits()); + info!("mie: {}", mie::read().bits()); + + timer.en_interrupt(); + + + unsafe{ + vmim::write(0); // Disable all machine interrupts + mie::set_msoft(); + mie::set_mtimer(); + mie::set_mext(); + mstatus::set_mie(); // Enable CPU interrupts + mstatus::clear_mie(); + vmim::write(2); + mstatus::set_mie(); } - - info!("adcval: {}", adcval); + msleep(&mut timer, 500 as u32); + info!("\nafter:"); + info!("vmip: {}", vmip::read()); + info!("vmim: {}", vmim::read()); + info!("mcause: {}", mcause::read().bits()); + info!("mie: {}", mie::read().bits()); + vmim::write(0); + + // info!("vsim: {}", vsim::read()); + // info!("vsip: {}", vsip::read()); } @@ -196,6 +228,19 @@ fn main() -> ! { } } +// #[no_mangle] +// pub fn trap_handler() { +// unsafe{mstatus::clear_mie(); +// vmim::write(0);} +// } + +#[no_mangle] +fn DefaultHandler() { + unsafe{mstatus::clear_mie(); + vmim::write(0); + } +} + fn u32_to_u8(x:u32) -> [u8;4] { let b1 : u8 = ((x >> 24) & 0xff) as u8; let b2 : u8 = ((x >> 16) & 0xff) as u8; diff --git a/rust/adc_eth_test/src/timer.rs b/rust/adc_eth_test/src/timer.rs index 130d887..ab253b1 100644 --- a/rust/adc_eth_test/src/timer.rs +++ b/rust/adc_eth_test/src/timer.rs @@ -40,4 +40,10 @@ impl Timer { self.registers.value.read().bits() } + + pub fn en_interrupt(&mut self) { + unsafe { + self.registers.ev_enable.write(|w| w.bits(1)); + } + } } From 86aaf6c2e1afc9cfc72198151232c925173650b7 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Tue, 13 Apr 2021 15:39:51 +0200 Subject: [PATCH 11/36] using peripherals in interrupt routies works --- rust/adc_eth_test/src/main.rs | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/rust/adc_eth_test/src/main.rs b/rust/adc_eth_test/src/main.rs index 8eea433..92bab85 100644 --- a/rust/adc_eth_test/src/main.rs +++ b/rust/adc_eth_test/src/main.rs @@ -173,7 +173,7 @@ fn main() -> ! { msleep(&mut timer, 1000 as u32); vec.rotate_right(1); - leds.toggle(); + // leds.toggle_mask(4); // // let adcval: u32 = adc.read(); // @@ -228,19 +228,36 @@ fn main() -> ! { } } -// #[no_mangle] -// pub fn trap_handler() { -// unsafe{mstatus::clear_mie(); -// vmim::write(0);} -// } #[no_mangle] fn DefaultHandler() { - unsafe{mstatus::clear_mie(); - vmim::write(0); + let mc = mcause::read(); + let irqs_pending = vmip::read(); + vmim::write(0); // absolutely neccessary right now to disable interrupts otherwise the processor is stuck. + + if mc.is_exception() {}; + + if irqs_pending == 2 { + handle_timer_irq(); } + +} + +fn handle_timer_irq() { + + let peripherals = unsafe{ litex_pac::Peripherals::steal() }; + + let mut timer = Timer::new(peripherals.TIMER0); + let mut leds = Leds::new(peripherals.LEDS); + + leds.toggle_mask(2); + timer.disable(); + } + + + fn u32_to_u8(x:u32) -> [u8;4] { let b1 : u8 = ((x >> 24) & 0xff) as u8; let b2 : u8 = ((x >> 16) & 0xff) as u8; From 74281982c6cf8e34d2d1b9b92cbc1a95e7981e15 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Tue, 13 Apr 2021 16:16:30 +0200 Subject: [PATCH 12/36] fixed ecpprog with two ftdis --- rust/adc_eth_test/.cargo/flash.sh | 2 +- rust/adc_eth_test/src/main.rs | 6 +++--- rust/adc_eth_test/src/timer.rs | 6 ++++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/rust/adc_eth_test/.cargo/flash.sh b/rust/adc_eth_test/.cargo/flash.sh index 8743142..5ab4e60 100755 --- a/rust/adc_eth_test/.cargo/flash.sh +++ b/rust/adc_eth_test/.cargo/flash.sh @@ -6,4 +6,4 @@ set -e riscv64-unknown-elf-objcopy $1 -O binary $1.bin # Program Colorlight -ecpprog -o 0x00100000 $1.bin +ecpprog -o 0x00100000 -d i:0x0403:0x6014:1 $1.bin diff --git a/rust/adc_eth_test/src/main.rs b/rust/adc_eth_test/src/main.rs index 92bab85..4b0a363 100644 --- a/rust/adc_eth_test/src/main.rs +++ b/rust/adc_eth_test/src/main.rs @@ -233,7 +233,7 @@ fn main() -> ! { fn DefaultHandler() { let mc = mcause::read(); let irqs_pending = vmip::read(); - vmim::write(0); // absolutely neccessary right now to disable interrupts otherwise the processor is stuck. + vmim::write(0); // absolutely neccessary right now to disable interrupts otherwise the processor is stuck. if mc.is_exception() {}; @@ -250,8 +250,8 @@ fn handle_timer_irq() { let mut timer = Timer::new(peripherals.TIMER0); let mut leds = Leds::new(peripherals.LEDS); - leds.toggle_mask(2); - timer.disable(); + leds.toggle(); + timer.dis_interrupt(); } diff --git a/rust/adc_eth_test/src/timer.rs b/rust/adc_eth_test/src/timer.rs index ab253b1..d64cc56 100644 --- a/rust/adc_eth_test/src/timer.rs +++ b/rust/adc_eth_test/src/timer.rs @@ -46,4 +46,10 @@ impl Timer { self.registers.ev_enable.write(|w| w.bits(1)); } } + + pub fn dis_interrupt(&mut self) { + unsafe { + self.registers.ev_enable.write(|w| w.bits(1)); + } + } } From 2f90d94b8316d7fea4ac7fa07ff14ced65215a2d Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Tue, 13 Apr 2021 16:19:30 +0200 Subject: [PATCH 13/36] yey, fixed the interrupt storm! --- rust/adc_eth_test/src/main.rs | 2 +- rust/adc_eth_test/src/timer.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/adc_eth_test/src/main.rs b/rust/adc_eth_test/src/main.rs index 4b0a363..10b673b 100644 --- a/rust/adc_eth_test/src/main.rs +++ b/rust/adc_eth_test/src/main.rs @@ -233,7 +233,7 @@ fn main() -> ! { fn DefaultHandler() { let mc = mcause::read(); let irqs_pending = vmip::read(); - vmim::write(0); // absolutely neccessary right now to disable interrupts otherwise the processor is stuck. + // vmim::write(0); // absolutely neccessary right now to disable interrupts otherwise the processor is stuck. if mc.is_exception() {}; diff --git a/rust/adc_eth_test/src/timer.rs b/rust/adc_eth_test/src/timer.rs index d64cc56..06bc393 100644 --- a/rust/adc_eth_test/src/timer.rs +++ b/rust/adc_eth_test/src/timer.rs @@ -49,7 +49,7 @@ impl Timer { pub fn dis_interrupt(&mut self) { unsafe { - self.registers.ev_enable.write(|w| w.bits(1)); + self.registers.ev_enable.write(|w| w.bits(0)); } } } From 8c361441607a18f080f2bea81b249e2d6c824589 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Tue, 13 Apr 2021 23:15:16 +0200 Subject: [PATCH 14/36] Understanding the liteX event manager a bit now. still only timer triggers CPU interrupt handler but both get registered in the vexriscv register --- rust/adc_eth_test/src/gpio.rs | 46 ++++++++++++++++ rust/adc_eth_test/src/main.rs | 33 ++++++++++-- rust/adc_eth_test/src/timer.rs | 8 ++- rust/litex-pac/clSOC.svd | 98 ++++++++++++++++++++++++++++++++++ soc/colorlight_5a_75x.py | 8 ++- 5 files changed, 187 insertions(+), 6 deletions(-) create mode 100644 rust/adc_eth_test/src/gpio.rs diff --git a/rust/adc_eth_test/src/gpio.rs b/rust/adc_eth_test/src/gpio.rs new file mode 100644 index 0000000..0bc799c --- /dev/null +++ b/rust/adc_eth_test/src/gpio.rs @@ -0,0 +1,46 @@ +use litex_pac::GPIO; + +pub struct Gpio { + registers: GPIO, +} + +#[allow(dead_code)] +impl Gpio { + + pub fn new(registers: GPIO) -> Self { + Self { registers } + } + + pub fn status(&mut self) -> u32 { + self.registers.in_.read().bits() + } + + pub fn set_interrupt_polarity(&mut self, pol: bool) { + unsafe { + if pol { + self.registers.polarity.write(|w| w.bits(1)); + }else { + self.registers.polarity.write(|w| w.bits(0)); + } + } + } + + pub fn en_interrupt(&mut self) { + unsafe { + self.registers.ev_enable.write(|w| w.bits(0xFFFF_FFFF)); + } + } + + pub fn clr_interrupt(&mut self) { + unsafe { + self.registers.ev_pending.write(|w| w.bits(0xFFFF_FFFF)); + } + } + + pub fn dis_interrupt(&mut self) { + unsafe { + self.registers.ev_enable.write(|w| w.bits(0)); + } + } + +} diff --git a/rust/adc_eth_test/src/main.rs b/rust/adc_eth_test/src/main.rs index 10b673b..0c8339d 100644 --- a/rust/adc_eth_test/src/main.rs +++ b/rust/adc_eth_test/src/main.rs @@ -17,11 +17,13 @@ mod print; mod timer; mod leds; mod adc; +mod gpio; use crate::ethernet::Eth; use timer::Timer; use leds::Leds; use adc::Adc; +use gpio::Gpio; use managed::ManagedSlice; use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache}; @@ -86,6 +88,8 @@ fn main() -> ! { let mut adc = Adc::new(peripherals.ADC); + let mut gpio = Gpio::new(peripherals.GPIO); + let clock = mock::Clock::new(); let device = Eth::new(peripherals.ETHMAC, peripherals.ETHMEM); @@ -171,6 +175,10 @@ fn main() -> ! { socket.send_slice(&vec).unwrap(); } + + gpio.set_interrupt_polarity(true); // falling edge + gpio.en_interrupt(); + msleep(&mut timer, 1000 as u32); vec.rotate_right(1); // leds.toggle_mask(4); @@ -186,6 +194,7 @@ fn main() -> ! { info!("vmim: {}", vmim::read()); info!("mcause: {}", mcause::read().bits()); info!("mie: {}", mie::read().bits()); + info!("btn: {}", gpio.status()); timer.en_interrupt(); @@ -197,7 +206,7 @@ fn main() -> ! { mie::set_mext(); mstatus::set_mie(); // Enable CPU interrupts mstatus::clear_mie(); - vmim::write(2); + vmim::write(0xa); // 1010 for timer and gpio mstatus::set_mie(); } msleep(&mut timer, 500 as u32); @@ -237,10 +246,15 @@ fn DefaultHandler() { if mc.is_exception() {}; - if irqs_pending == 2 { + + if irqs_pending & (1 << 1) != 0 { handle_timer_irq(); } + if irqs_pending & (1 << 3) != 0 { + handle_btn_irq(); + } + } fn handle_timer_irq() { @@ -250,9 +264,20 @@ fn handle_timer_irq() { let mut timer = Timer::new(peripherals.TIMER0); let mut leds = Leds::new(peripherals.LEDS); - leds.toggle(); - timer.dis_interrupt(); + leds.toggle_mask(4); // toggle green led + timer.clr_interrupt(); + +} + +fn handle_btn_irq() { + + let peripherals = unsafe{ litex_pac::Peripherals::steal() }; + + let mut gpio = Gpio::new(peripherals.GPIO); + let mut leds = Leds::new(peripherals.LEDS); + leds.toggle_mask(2); // toggle yellow led + gpio.clr_interrupt(); } diff --git a/rust/adc_eth_test/src/timer.rs b/rust/adc_eth_test/src/timer.rs index 06bc393..abfc2d0 100644 --- a/rust/adc_eth_test/src/timer.rs +++ b/rust/adc_eth_test/src/timer.rs @@ -43,7 +43,13 @@ impl Timer { pub fn en_interrupt(&mut self) { unsafe { - self.registers.ev_enable.write(|w| w.bits(1)); + self.registers.ev_enable.write(|w| w.bits(0xFFFF_FFFF)); + } + } + + pub fn clr_interrupt(&mut self) { + unsafe { + self.registers.ev_pending.write(|w| w.bits(0xFFFF_FFFF)); } } diff --git a/rust/litex-pac/clSOC.svd b/rust/litex-pac/clSOC.svd index 67c28ae..6872647 100644 --- a/rust/litex-pac/clSOC.svd +++ b/rust/litex-pac/clSOC.svd @@ -1053,6 +1053,103 @@ register to disable individual events.]]> registers + + GPIO + 0xF0006000 + GPIO + + + IN + + 0x0000 + 0x00 + 32 + + + in + 0 + [0:0] + 0 + + + + + POLARITY + + 0x0004 + 0x00 + 32 + + + polarity + 0 + [0:0] + 0 + + + + + EV_STATUS + + 0x0008 + 0x00 + 32 + + + i0 + 0 + [0:0] + 0 + + + + + + EV_PENDING + + 0x000c + 0x00 + 32 + + + i0 + 0 + [0:0] + 0 + + + + + + EV_ENABLE + + 0x0010 + 0x00 + 32 + + + i0 + 0 + [0:0] + 0 + + + + + + + 0 + 0x14 + registers + + + gpio + 3 + + ETHMEM 0x80000000 @@ -1190,6 +1287,7 @@ register to disable individual events.]]> + diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index 6c460cf..50a98aa 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -40,6 +40,8 @@ from adc import ADC +from litex.soc.cores.gpio import GPIOIn + class ECP5Programmer(GenericProgrammer): needs_bitreverse = False @@ -231,7 +233,7 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi ident_version = True, **kwargs) - with_rst = kwargs["uart_name"] not in ["serial", "bridge", "crossover"] # serial_rx shared with user_btn_n. + with_rst = False # kwargs["uart_name"] not in ["serial", "bridge", "crossover"] # serial_rx shared with user_btn_n. with_usb_pll = kwargs.get("uart_name", None) == "usb_acm" self.submodules.crg = _CRG(platform, sys_clk_freq, use_internal_osc=use_internal_osc, with_usb_pll=with_usb_pll, with_rst=with_rst, sdram_rate=sdram_rate) @@ -331,6 +333,10 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi self.add_csr("adc") + self.submodules.gpio = gpio = GPIOIn(platform.request("user_btn_n", 0), with_irq=True) + + self.add_csr("gpio") + self.add_interrupt("gpio") # Helper functions --------------------------------------------------------------------------------- From f8dd9e02ddfa5632dcf48d66fec088d259c9150c Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Tue, 20 Apr 2021 12:40:50 +0200 Subject: [PATCH 15/36] struggeling about with interrupts. They work but LED toggeling in the ISR somehow effects the irq behaviour and causes a second trigger sometimes.. --- rust/adc_eth_test/src/gpio.rs | 15 ++- rust/adc_eth_test/src/gpio1.rs | 59 +++++++++++ rust/adc_eth_test/src/main.rs | 180 ++++++++++++++++++++++++--------- rust/adc_eth_test/src/timer.rs | 14 ++- rust/litex-pac/clSOC.svd | 98 ++++++++++++++++++ soc/colorlight_5a_75x.py | 13 ++- 6 files changed, 327 insertions(+), 52 deletions(-) create mode 100644 rust/adc_eth_test/src/gpio1.rs diff --git a/rust/adc_eth_test/src/gpio.rs b/rust/adc_eth_test/src/gpio.rs index 0bc799c..10e9655 100644 --- a/rust/adc_eth_test/src/gpio.rs +++ b/rust/adc_eth_test/src/gpio.rs @@ -27,7 +27,8 @@ impl Gpio { pub fn en_interrupt(&mut self) { unsafe { - self.registers.ev_enable.write(|w| w.bits(0xFFFF_FFFF)); + + self.registers.ev_enable.write(|w| w.bits(0xffff)); } } @@ -43,4 +44,16 @@ impl Gpio { } } + pub fn ev_pending(&mut self) -> u32 { + self.registers.ev_pending.read().bits() + } + + pub fn ev_status(&mut self) -> u32 { + self.registers.ev_status.read().bits() + } + + pub fn ev_enable(&mut self) -> u32 { + self.registers.ev_enable.read().bits() + } + } diff --git a/rust/adc_eth_test/src/gpio1.rs b/rust/adc_eth_test/src/gpio1.rs new file mode 100644 index 0000000..903c9a4 --- /dev/null +++ b/rust/adc_eth_test/src/gpio1.rs @@ -0,0 +1,59 @@ +use litex_pac::GPIO1; + +pub struct Gpio1 { + registers: GPIO1, +} + +#[allow(dead_code)] +impl Gpio1 { + + pub fn new(registers: GPIO1) -> Self { + Self { registers } + } + + pub fn status(&mut self) -> u32 { + self.registers.in_.read().bits() + } + + pub fn set_interrupt_polarity(&mut self, pol: bool) { + unsafe { + if pol { + self.registers.polarity.write(|w| w.bits(1)); + }else { + self.registers.polarity.write(|w| w.bits(0)); + } + } + } + + pub fn en_interrupt(&mut self) { + unsafe { + + self.registers.ev_enable.write(|w| w.bits(0xffff)); + } + } + + pub fn clr_interrupt(&mut self) { + unsafe { + self.registers.ev_pending.write(|w| w.bits(0xFFFF_FFFF)); + } + } + + pub fn dis_interrupt(&mut self) { + unsafe { + self.registers.ev_enable.write(|w| w.bits(0)); + } + } + + pub fn ev_pending(&mut self) -> u32 { + self.registers.ev_pending.read().bits() + } + + pub fn ev_status(&mut self) -> u32 { + self.registers.ev_status.read().bits() + } + + pub fn ev_enable(&mut self) -> u32 { + self.registers.ev_enable.read().bits() + } + +} diff --git a/rust/adc_eth_test/src/main.rs b/rust/adc_eth_test/src/main.rs index 0c8339d..816f04d 100644 --- a/rust/adc_eth_test/src/main.rs +++ b/rust/adc_eth_test/src/main.rs @@ -18,12 +18,14 @@ mod timer; mod leds; mod adc; mod gpio; +mod gpio1; use crate::ethernet::Eth; use timer::Timer; use leds::Leds; use adc::Adc; use gpio::Gpio; +use gpio1::Gpio1; use managed::ManagedSlice; use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache}; @@ -90,6 +92,8 @@ fn main() -> ! { let mut gpio = Gpio::new(peripherals.GPIO); + let mut gpio1 = Gpio1::new(peripherals.GPIO1); + let clock = mock::Clock::new(); let device = Eth::new(peripherals.ETHMAC, peripherals.ETHMEM); @@ -152,34 +156,40 @@ fn main() -> ! { let mut vec: [u8; 5] = [1,2,3,4,5]; - info!("Main loop..."); - - loop { - match iface.poll(&mut socket_set, clock.elapsed()) { - Ok(_) => {} - Err(e) => { - debug!("Poll error: {}", e); - } - } - - { - let mut socket = socket_set.get::(tcp_server_handle); - - if !socket.is_active() && !socket.is_listening() { - info!("Start listen..."); - socket.listen(1234).unwrap(); - } - - if socket.can_send() { - info!("Can send..."); - socket.send_slice(&vec).unwrap(); - } + gpio.en_interrupt(); + gpio1.en_interrupt(); - gpio.set_interrupt_polarity(true); // falling edge - gpio.en_interrupt(); + info!("Main loop..."); - msleep(&mut timer, 1000 as u32); + loop { + // match iface.poll(&mut socket_set, clock.elapsed()) { + // Ok(_) => {} + // Err(e) => { + // debug!("Poll error: {}", e); + // } + // } + // + // { + // let mut socket = socket_set.get::(tcp_server_handle); + // + // if !socket.is_active() && !socket.is_listening() { + // info!("Start listen..."); + // socket.listen(1234).unwrap(); + // } + // + // if socket.can_send() { + // info!("Can send..."); + // socket.send_slice(&vec).unwrap(); + // } + // + // + // gpio.set_interrupt_polarity(true); // falling edge + // gpio.dis_interrupt(); + // gpio1.set_interrupt_polarity(false); // falling edge + // gpio1.dis_interrupt(); + // + // msleep(&mut timer, &mut leds, 1000 as u32); vec.rotate_right(1); // leds.toggle_mask(4); // @@ -195,43 +205,79 @@ fn main() -> ! { info!("mcause: {}", mcause::read().bits()); info!("mie: {}", mie::read().bits()); info!("btn: {}", gpio.status()); + info!("ev_pending_gpio: {}", gpio.ev_pending()); + info!("ev_status_gpio: {}", gpio.ev_status()); + info!("ev_enable_gpio: {}", gpio.ev_enable()); + info!("ev_pending_timer: {}", timer.ev_pending()); + info!("ev_status_timer: {}", timer.ev_status()); + info!("ev_enable_timer: {}", timer.ev_enable()); + + + // + // timer.dis_interrupt(); + // timer.clr_interrupt(); + + for i in 0..10000{ + for j in 0..1000{ + leds.toggle_mask(2); // toggle yellow led + } + } - timer.en_interrupt(); + + // timer.disable(); + + // timer.reload(0); + // timer.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * 1000); + + // timer.enable(); + unsafe{ vmim::write(0); // Disable all machine interrupts mie::set_msoft(); - mie::set_mtimer(); + // mie::set_mtimer(); mie::set_mext(); mstatus::set_mie(); // Enable CPU interrupts - mstatus::clear_mie(); - vmim::write(0xa); // 1010 for timer and gpio + vmim::write(0xFFFF_FFFF); // 1010 for timer and gpio mstatus::set_mie(); } - msleep(&mut timer, 500 as u32); + // msleep(&mut timer, &mut leds, 500 as u32); info!("\nafter:"); info!("vmip: {}", vmip::read()); info!("vmim: {}", vmim::read()); info!("mcause: {}", mcause::read().bits()); info!("mie: {}", mie::read().bits()); - vmim::write(0); + info!("btn: {}", gpio.status()); + info!("ev_pending_gpio: {}", gpio.ev_pending()); + info!("ev_status_gpio: {}", gpio.ev_status()); + info!("ev_enable_gpio: {}", gpio.ev_enable()); + info!("ev_pending_timer: {}", timer.ev_pending()); + info!("ev_status_timer: {}", timer.ev_status()); + info!("ev_enable_timer: {}", timer.ev_enable()); + // vmim::write(0); // info!("vsim: {}", vsim::read()); // info!("vsip: {}", vsip::read()); - } + // } - - match iface.poll_delay(&socket_set, clock.elapsed()) { - Some(Duration { millis: 0 }) => {} - Some(delay) => { - trace!("sleeping for {} ms", delay); - msleep(&mut timer, delay.total_millis() as u32); - clock.advance(delay) + for i in 0..10000{ + for j in 0..1000{ + leds.toggle_mask(2); // toggle yellow led } - None => clock.advance(Duration::from_millis(1)), } - trace!("Clock elapsed: {}", clock.elapsed()); + + // + // match iface.poll_delay(&socket_set, clock.elapsed()) { + // Some(Duration { millis: 0 }) => {} + // Some(delay) => { + // trace!("sleeping for {} ms", delay); + // msleep(&mut timer, &mut leds, delay.total_millis() as u32); + // clock.advance(delay) + // } + // None => clock.advance(Duration::from_millis(1)), + // } + // trace!("Clock elapsed: {}", clock.elapsed()); } @@ -239,7 +285,7 @@ fn main() -> ! { #[no_mangle] -fn DefaultHandler() { +fn MachineExternal() { let mc = mcause::read(); let irqs_pending = vmip::read(); // vmim::write(0); // absolutely neccessary right now to disable interrupts otherwise the processor is stuck. @@ -247,6 +293,18 @@ fn DefaultHandler() { if mc.is_exception() {}; + let peripherals = unsafe{ litex_pac::Peripherals::steal() }; + + let mut timer = Timer::new(peripherals.TIMER0); + let mut leds = Leds::new(peripherals.LEDS); + let mut gpio1 = Gpio1::new(peripherals.GPIO1); + let mut gpio = Gpio::new(peripherals.GPIO); + gpio1.clr_interrupt(); + // gpio.clr_interrupt(); + + + + if irqs_pending & (1 << 1) != 0 { handle_timer_irq(); } @@ -255,6 +313,10 @@ fn DefaultHandler() { handle_btn_irq(); } + + // timer.clr_interrupt(); + + } fn handle_timer_irq() { @@ -271,13 +333,39 @@ fn handle_timer_irq() { fn handle_btn_irq() { + + let peripherals = unsafe{ litex_pac::Peripherals::steal() }; let mut gpio = Gpio::new(peripherals.GPIO); let mut leds = Leds::new(peripherals.LEDS); - leds.toggle_mask(2); // toggle yellow led + // gpio.clr_interrupt() + leds.toggle_mask(4); + if gpio.ev_pending() == 0 { + leds.toggle_mask(4); // toggle green led + } + // leds.toggle_mask(4); // toggle green led + // leds.toggle_mask(4); // toggle green led + for i in 0..2000{ + for j in 0..1045{ + leds.toggle_mask(2); // toggle yellow led + } + } gpio.clr_interrupt(); + if gpio.ev_pending() == 0 { + leds.toggle_mask(4); // toggle green led + } + for i in 0..5000{ + for j in 0..1000{ + leds.toggle_mask(2); // toggle yellow led + } + } + // vmim::write(0); + // gpio.dis_interrupt(); + // gpio.clr_interrupt(); + // gpio.en_interrupt(); + // gpio.clr_interrupt(); } @@ -291,7 +379,7 @@ fn u32_to_u8(x:u32) -> [u8;4] { return [b1, b2, b3, b4] } -fn msleep(timer: &mut Timer, ms: u32) { +fn msleep(timer: &mut Timer, leds : &mut Leds, ms: u32) { timer.disable(); timer.reload(0); @@ -300,6 +388,8 @@ fn msleep(timer: &mut Timer, ms: u32) { timer.enable(); // Wait until the time has elapsed - while timer.value() > 0 {} + while timer.value() > 0 { + // leds.toggle_mask(2); // toggle yellow led + } timer.disable(); } diff --git a/rust/adc_eth_test/src/timer.rs b/rust/adc_eth_test/src/timer.rs index abfc2d0..98f8abc 100644 --- a/rust/adc_eth_test/src/timer.rs +++ b/rust/adc_eth_test/src/timer.rs @@ -43,7 +43,7 @@ impl Timer { pub fn en_interrupt(&mut self) { unsafe { - self.registers.ev_enable.write(|w| w.bits(0xFFFF_FFFF)); + self.registers.ev_enable.write(|w| w.bits(0x1)); } } @@ -58,4 +58,16 @@ impl Timer { self.registers.ev_enable.write(|w| w.bits(0)); } } + + pub fn ev_pending(&mut self) -> u32 { + self.registers.ev_pending.read().bits() + } + + pub fn ev_status(&mut self) -> u32 { + self.registers.ev_status.read().bits() + } + + pub fn ev_enable(&mut self) -> u32 { + self.registers.ev_enable.read().bits() + } } diff --git a/rust/litex-pac/clSOC.svd b/rust/litex-pac/clSOC.svd index 6872647..b9fd69b 100644 --- a/rust/litex-pac/clSOC.svd +++ b/rust/litex-pac/clSOC.svd @@ -1150,6 +1150,103 @@ register to disable individual events.]]> 3 + + GPIO1 + 0xF0006800 + GPIO1 + + + IN + + 0x0000 + 0x00 + 32 + + + in + 0 + [0:0] + 0 + + + + + POLARITY + + 0x0004 + 0x00 + 32 + + + polarity + 0 + [0:0] + 0 + + + + + EV_STATUS + + 0x0008 + 0x00 + 32 + + + i0 + 0 + [0:0] + 0 + + + + + + EV_PENDING + + 0x000c + 0x00 + 32 + + + i0 + 0 + [0:0] + 0 + + + + + + EV_ENABLE + + 0x0010 + 0x00 + 32 + + + i0 + 0 + [0:0] + 0 + + + + + + + 0 + 0x14 + registers + + + gpio1 + 4 + + ETHMEM 0x80000000 @@ -1288,6 +1385,7 @@ register to disable individual events.]]> + diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index 50a98aa..1a5984b 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -55,9 +55,6 @@ def load_bitstream(self, bitstream_file): # My IOs ------------------------------------------------------------------------------------------- - Subsignal("tx", Pins("P11")), # led (J19 DATA_LED-) - Subsignal("rx", Pins("M13")), # btn (J19 KEY+) - IOStandard("LVCMOS33") _myserial = [ ("myserial", 0, @@ -76,6 +73,7 @@ def load_bitstream(self, bitstream_file): ("g", 0, Pins("j6:5"), IOStandard("LVCMOS33")), ("r", 0, Pins("j6:10"), IOStandard("LVCMOS33")), # Not really here but there is congestion with the pins otherwise.. ("y", 0, Pins("j6:9"), IOStandard("LVCMOS33")), + ("iox", 0, Pins("j3:1"), IOStandard("LVCMOS33")), ] _adc_first_order = [ @@ -321,14 +319,14 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi adc_sd = platform.request("sd", 0) adc_sd2 = platform.request("sd", 1) #p5v = platform.request("p5v") - p3v = platform.request("p3v") + #p3v = platform.request("p3v") self.comb += [ adc.inp.eq(adc_in), adc_sd.eq(adc.sd), adc_sd2.eq(adc.sd), #p5v.eq(1), - p3v.eq(1), + #p3v.eq(1), ] self.add_csr("adc") @@ -338,6 +336,11 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi self.add_csr("gpio") self.add_interrupt("gpio") + self.submodules.gpio1 = gpio1 = GPIOIn(platform.request("p3v"), with_irq=True) + + self.add_csr("gpio1") + self.add_interrupt("gpio1") + # Helper functions --------------------------------------------------------------------------------- From e66af2edc15adf785f653b524ed227561a2c595e Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Tue, 20 Apr 2021 12:56:38 +0200 Subject: [PATCH 16/36] Update README.md --- README.md | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 4935578..6eb5f0c 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,11 @@ -# `Colorlight 5A-75X Litex Ethernet Demo` +# `Rust SoC Playground using LiteX, VexRiscV and the Colorlight 5A-75B board` -> Litex SoC and Rust software for [Colorlight 5A-75X][colorlight] board as a simple Ethernet demo. +Trying lots of different things (in different branches). -This project is developed and maintained by [DerFetzer][team]. - -## Usage - -1. Install Litex as described [here][litex]. -2. Install [ecpprog][ecpprog]. -4. Connect a USB to JTAG adaptor to your board. -5. Build and flash the SOC with the following (in the soc directory): -``` -python colorlight_5a_75x.py --build --flash --board=5a-75e --revision=6.0 --with-ethernet --sys-clk-freq 50e6 --use-internal-osc -``` -4. Follow the instructions in [eth_demo][eth_demo] to build the software. +Working so far: +- Ethernet with smoltcp thanks to https://github.com/DerFetzer/colorlight-litex +- Interrupts by staring a lot at https://github.com/betrusted-io/xous-core +- A simple second order sigma-delta ADC using a CIC decimator ## Credits From d6c1e7a4782cf2f33b988e62e0ac1a0f96a600a0 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Tue, 20 Apr 2021 13:58:23 +0200 Subject: [PATCH 17/36] Update README.md --- README.md | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 4935578..6eb5f0c 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,11 @@ -# `Colorlight 5A-75X Litex Ethernet Demo` +# `Rust SoC Playground using LiteX, VexRiscV and the Colorlight 5A-75B board` -> Litex SoC and Rust software for [Colorlight 5A-75X][colorlight] board as a simple Ethernet demo. +Trying lots of different things (in different branches). -This project is developed and maintained by [DerFetzer][team]. - -## Usage - -1. Install Litex as described [here][litex]. -2. Install [ecpprog][ecpprog]. -4. Connect a USB to JTAG adaptor to your board. -5. Build and flash the SOC with the following (in the soc directory): -``` -python colorlight_5a_75x.py --build --flash --board=5a-75e --revision=6.0 --with-ethernet --sys-clk-freq 50e6 --use-internal-osc -``` -4. Follow the instructions in [eth_demo][eth_demo] to build the software. +Working so far: +- Ethernet with smoltcp thanks to https://github.com/DerFetzer/colorlight-litex +- Interrupts by staring a lot at https://github.com/betrusted-io/xous-core +- A simple second order sigma-delta ADC using a CIC decimator ## Credits From 58ff7a14a1a6658db4b460bdb2ded19b5032756f Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Wed, 21 Apr 2021 12:27:27 +0200 Subject: [PATCH 18/36] interrupt problems where due to memory congestion bc the man function uses the LEDs and the ISR toggles them, too. Seperate LED peripherals behave as expected. --- rust/adc_eth_test/src/leds.rs | 52 ++++++++- rust/adc_eth_test/src/main.rs | 63 ++++++++--- rust/adc_eth_test/src/timer.rs | 75 ++++++++++++- rust/litex-pac/clSOC.svd | 194 ++++++++++++++++++++++++++++++++- soc/colorlight_5a_75x.py | 34 +++++- 5 files changed, 394 insertions(+), 24 deletions(-) diff --git a/rust/adc_eth_test/src/leds.rs b/rust/adc_eth_test/src/leds.rs index 52a1712..0921950 100644 --- a/rust/adc_eth_test/src/leds.rs +++ b/rust/adc_eth_test/src/leds.rs @@ -1,4 +1,4 @@ -use litex_pac::LEDS; +use litex_pac::{LEDS,LEDS2}; pub struct Leds { registers: LEDS, @@ -48,3 +48,53 @@ impl Leds { } } } + + +pub struct Leds2 { + registers: LEDS2, +} + +#[allow(dead_code)] +impl Leds2 { + pub fn new(registers: LEDS2) -> Self { + Self { registers } + } + + pub fn set_single(&mut self, red: bool, yellow: bool, + green: bool) { + self.registers.out.write(|w| { + w.r1().bit(red); + w.g1().bit(green); + w.y1().bit(yellow) + }); + } + + pub fn set(&mut self, leds: u32) { + unsafe { + self.registers.out.write(|w| w.bits(leds)); + } + } + + pub fn off(&mut self) { + unsafe { + self.registers.out.write(|w| w.bits(0x0000_0000)); + } + } + + pub fn on(&mut self) { + unsafe { + self.registers.out.write(|w| w.bits(0xFFFF_FFFF)); + } + } + + pub fn toggle(&mut self) { + self.toggle_mask(0xFFFF_FFFF); + } + + pub fn toggle_mask(&mut self, mask: u32) { + let val: u32 = self.registers.out.read().bits() ^ mask; + unsafe { + self.registers.out.write(|w| w.bits(val)); + } + } +} diff --git a/rust/adc_eth_test/src/main.rs b/rust/adc_eth_test/src/main.rs index 816f04d..6e3c0ea 100644 --- a/rust/adc_eth_test/src/main.rs +++ b/rust/adc_eth_test/src/main.rs @@ -22,7 +22,9 @@ mod gpio1; use crate::ethernet::Eth; use timer::Timer; +use timer::Timer2; use leds::Leds; +use leds::Leds2; use adc::Adc; use gpio::Gpio; use gpio1::Gpio1; @@ -85,6 +87,7 @@ fn main() -> ! { info!("Logger initialized"); let mut timer = Timer::new(peripherals.TIMER0); + let mut timer2 = Timer2::new(peripherals.TIMER2); let mut leds = Leds::new(peripherals.LEDS); @@ -156,8 +159,15 @@ fn main() -> ! { let mut vec: [u8; 5] = [1,2,3,4,5]; - gpio.en_interrupt(); - gpio1.en_interrupt(); + // gpio.en_interrupt(); + // gpio1.en_interrupt(); + + + timer2.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * 4000); + + timer2.enable(); + + timer2.en_interrupt(); info!("Main loop..."); @@ -238,7 +248,7 @@ fn main() -> ! { mie::set_msoft(); // mie::set_mtimer(); mie::set_mext(); - mstatus::set_mie(); // Enable CPU interrupts + // mstatus::set_mie(); // Enable CPU interrupts vmim::write(0xFFFF_FFFF); // 1010 for timer and gpio mstatus::set_mie(); } @@ -266,6 +276,7 @@ fn main() -> ! { leds.toggle_mask(2); // toggle yellow led } } + leds.set(0x0); // // match iface.poll_delay(&socket_set, clock.elapsed()) { @@ -313,6 +324,10 @@ fn MachineExternal() { handle_btn_irq(); } + if irqs_pending & (1 << 5) != 0 { + handle_timer2_irq(); + } + // timer.clr_interrupt(); @@ -331,6 +346,25 @@ fn handle_timer_irq() { } +fn handle_timer2_irq() { + + let peripherals = unsafe{ litex_pac::Peripherals::steal() }; + + let mut timer2 = Timer2::new(peripherals.TIMER2); + let mut leds2 = Leds2::new(peripherals.LEDS2); + + leds2.toggle_mask(0xf); + timer2.clr_interrupt(); + timer2.disable(); + + timer2.reload(0); + + timer2.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * 4000); + + timer2.enable(); + +} + fn handle_btn_irq() { @@ -341,24 +375,25 @@ fn handle_btn_irq() { let mut leds = Leds::new(peripherals.LEDS); // gpio.clr_interrupt() - leds.toggle_mask(4); - if gpio.ev_pending() == 0 { - leds.toggle_mask(4); // toggle green led - } + leds.toggle_mask(0x10); + // if gpio.ev_pending() == 0 { + // leds.toggle_mask(0x2); // toggle green led + // } // leds.toggle_mask(4); // toggle green led // leds.toggle_mask(4); // toggle green led - for i in 0..2000{ + for i in 0..10000{ for j in 0..1045{ - leds.toggle_mask(2); // toggle yellow led + leds.toggle_mask(0x8); // toggle yellow led } } gpio.clr_interrupt(); - if gpio.ev_pending() == 0 { - leds.toggle_mask(4); // toggle green led - } - for i in 0..5000{ + leds.toggle_mask(0xff); + // if gpio.ev_pending() == 0 { + // leds.toggle_mask(0xff); // toggle green led + // } + for i in 0..2000{ for j in 0..1000{ - leds.toggle_mask(2); // toggle yellow led + leds.toggle_mask(0x8); // toggle yellow led } } // vmim::write(0); diff --git a/rust/adc_eth_test/src/timer.rs b/rust/adc_eth_test/src/timer.rs index 98f8abc..81ca1ba 100644 --- a/rust/adc_eth_test/src/timer.rs +++ b/rust/adc_eth_test/src/timer.rs @@ -1,4 +1,4 @@ -use litex_pac::TIMER0; +use litex_pac::{TIMER0,TIMER2}; pub struct Timer { registers: TIMER0, @@ -71,3 +71,76 @@ impl Timer { self.registers.ev_enable.read().bits() } } + + +pub struct Timer2 { + registers: TIMER2, +} + +impl Timer2 { + pub fn new(registers: TIMER2) -> Self { + Self { registers } + } + + pub fn enable(&mut self) { + unsafe { + self.registers.en.write(|w| w.bits(1)); + } + } + + pub fn disable(&mut self) { + unsafe { + self.registers.en.write(|w| w.bits(0)); + } + } + + pub fn load(&mut self, value: u32) { + unsafe { + self.registers.load.write(|w| w.bits(value)); + } + } + + pub fn reload(&mut self, value: u32) { + unsafe { + self.registers.reload.write(|w| w.bits(value)); + } + } + + pub fn value(&mut self) -> u32 { + unsafe { + self.registers.update_value.write(|w| w.bits(1)); + } + + self.registers.value.read().bits() + } + + pub fn en_interrupt(&mut self) { + unsafe { + self.registers.ev_enable.write(|w| w.bits(0x1)); + } + } + + pub fn clr_interrupt(&mut self) { + unsafe { + self.registers.ev_pending.write(|w| w.bits(0xFFFF_FFFF)); + } + } + + pub fn dis_interrupt(&mut self) { + unsafe { + self.registers.ev_enable.write(|w| w.bits(0)); + } + } + + pub fn ev_pending(&mut self) -> u32 { + self.registers.ev_pending.read().bits() + } + + pub fn ev_status(&mut self) -> u32 { + self.registers.ev_status.read().bits() + } + + pub fn ev_enable(&mut self) -> u32 { + self.registers.ev_enable.read().bits() + } +} diff --git a/rust/litex-pac/clSOC.svd b/rust/litex-pac/clSOC.svd index b9fd69b..82bd288 100644 --- a/rust/litex-pac/clSOC.svd +++ b/rust/litex-pac/clSOC.svd @@ -1027,8 +1027,49 @@ register to disable individual events.]]> - ADC + LEDS2 0xF0005800 + LEDS2 + + + OUT + 0x0000 + 0x00 + 32 + + + r1 + 0 + [0:0] + 0 + + + + y1 + 1 + [1:1] + 1 + + + + g1 + 2 + [2:2] + 2 + + + + + + + 0 + 0x4 + registers + + + + ADC + 0xF0006000 ADC @@ -1055,7 +1096,7 @@ register to disable individual events.]]> GPIO - 0xF0006000 + 0xF0006800 GPIO @@ -1152,7 +1193,7 @@ register to disable individual events.]]> GPIO1 - 0xF0006800 + 0xF0007000 GPIO1 @@ -1247,6 +1288,152 @@ register to disable individual events.]]> 4 + + TIMER2 + 0xF0007800 + TIMER2 + + + LOAD + + 0x0000 + 0x00 + 32 + + + load + 31 + [31:0] + 0 + + + + + RELOAD + + 0x0004 + 0x00 + 32 + + + reload + 31 + [31:0] + 0 + + + + + EN + + 0x0008 + 0x00 + 32 + + + en + 0 + [0:0] + 0 + + + + + UPDATE_VALUE + + 0x000c + 0x00 + 32 + + + update_value + 0 + [0:0] + 0 + + + + + VALUE + + 0x0010 + 0x00 + 32 + + + value + 31 + [31:0] + 0 + + + + + EV_STATUS + + 0x0014 + 0x00 + 32 + + + zero + 0 + [0:0] + 0 + + + + + + EV_PENDING + + 0x0018 + 0x00 + 32 + + + zero + 0 + [0:0] + 0 + + + + + + EV_ENABLE + + 0x001c + 0x00 + 32 + + + zero + 0 + [0:0] + 0 + + + + + + + 0 + 0x20 + registers + + + timer2 + 5 + + ETHMEM 0x80000000 @@ -1387,6 +1574,7 @@ register to disable individual events.]]> + diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index 1a5984b..ff328ea 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -27,6 +27,7 @@ from litex.soc.integration.soc_core import soc_core_argdict, soc_core_args from litex.soc.interconnect.csr import AutoCSR, CSRStorage, CSRStatus, CSRField from litex.soc.integration.doc import AutoDoc, ModuleDoc +from litex.soc.cores.timer import Timer from litex.build.generic_platform import * @@ -73,7 +74,9 @@ def load_bitstream(self, bitstream_file): ("g", 0, Pins("j6:5"), IOStandard("LVCMOS33")), ("r", 0, Pins("j6:10"), IOStandard("LVCMOS33")), # Not really here but there is congestion with the pins otherwise.. ("y", 0, Pins("j6:9"), IOStandard("LVCMOS33")), - ("iox", 0, Pins("j3:1"), IOStandard("LVCMOS33")), + ("g1", 0, Pins("j7:1"), IOStandard("LVCMOS33")), + ("r1", 0, Pins("j7:0"), IOStandard("LVCMOS33")), + ("y1", 0, Pins("j7:2"), IOStandard("LVCMOS33")), ] _adc_first_order = [ @@ -301,15 +304,34 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi self.submodules.leds = Leds(Cat( platform.request("r"), platform.request("y"), - platform.request("g")), + platform.request("g") + ), led_polarity=0x00, led_name=[ ["r", "The Red LED."], ["y", "The Yellow LED."], - ["g", "The Green Red LED."]]) + ["g", "The Green Red LED."] + ]) self.add_csr("leds") + self.submodules.leds2 = Leds(Cat( + platform.request("r1"), + platform.request("y1"), + platform.request("g1") + ), + led_polarity=0x00, + led_name=[ + ["r1", "The second Red LED."], + ["y1", "The second Yellow LED."], + ["g1", "The second Green Red LED."] + ]) + + self.add_csr("leds2") + + + + # sigma delta ADC using lame CSR for now @@ -332,15 +354,17 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi self.add_csr("adc") self.submodules.gpio = gpio = GPIOIn(platform.request("user_btn_n", 0), with_irq=True) - self.add_csr("gpio") self.add_interrupt("gpio") self.submodules.gpio1 = gpio1 = GPIOIn(platform.request("p3v"), with_irq=True) - self.add_csr("gpio1") self.add_interrupt("gpio1") + self.submodules.timer2 = Timer() + self.add_csr("timer2") + self.add_interrupt("timer2") + # Helper functions --------------------------------------------------------------------------------- From 5eea2819e1e6769afbe1e4cbaf945cb5ba52d407 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Thu, 29 Apr 2021 12:30:38 +0200 Subject: [PATCH 19/36] rename --- rust/adc_eth_test/src/gpio1.rs | 59 --- rust/adc_eth_test/src/macro_test.rs | 7 - rust/adc_eth_test/src/main.rs | 430 ------------------ rust/adc_eth_test/src/timer.rs | 146 ------ .../.cargo/config | 0 .../.cargo/flash.sh | 0 .../Cargo.lock | 0 .../Cargo.toml | 0 .../README.md | 0 .../src/adc.rs | 0 .../src/ethernet.rs | 0 .../src/gpio.rs | 0 .../src/leds.rs | 0 rust/temp_controller/src/main.rs | 183 ++++++++ .../src/print.rs | 0 rust/temp_controller/src/timer.rs | 74 +++ soc/colorlight_5a_75x.py | 4 - 17 files changed, 257 insertions(+), 646 deletions(-) delete mode 100644 rust/adc_eth_test/src/gpio1.rs delete mode 100644 rust/adc_eth_test/src/macro_test.rs delete mode 100644 rust/adc_eth_test/src/main.rs delete mode 100644 rust/adc_eth_test/src/timer.rs rename rust/{adc_eth_test => temp_controller}/.cargo/config (100%) rename rust/{adc_eth_test => temp_controller}/.cargo/flash.sh (100%) rename rust/{adc_eth_test => temp_controller}/Cargo.lock (100%) rename rust/{adc_eth_test => temp_controller}/Cargo.toml (100%) rename rust/{adc_eth_test => temp_controller}/README.md (100%) rename rust/{adc_eth_test => temp_controller}/src/adc.rs (100%) rename rust/{adc_eth_test => temp_controller}/src/ethernet.rs (100%) rename rust/{adc_eth_test => temp_controller}/src/gpio.rs (100%) rename rust/{adc_eth_test => temp_controller}/src/leds.rs (100%) create mode 100644 rust/temp_controller/src/main.rs rename rust/{adc_eth_test => temp_controller}/src/print.rs (100%) create mode 100644 rust/temp_controller/src/timer.rs diff --git a/rust/adc_eth_test/src/gpio1.rs b/rust/adc_eth_test/src/gpio1.rs deleted file mode 100644 index 903c9a4..0000000 --- a/rust/adc_eth_test/src/gpio1.rs +++ /dev/null @@ -1,59 +0,0 @@ -use litex_pac::GPIO1; - -pub struct Gpio1 { - registers: GPIO1, -} - -#[allow(dead_code)] -impl Gpio1 { - - pub fn new(registers: GPIO1) -> Self { - Self { registers } - } - - pub fn status(&mut self) -> u32 { - self.registers.in_.read().bits() - } - - pub fn set_interrupt_polarity(&mut self, pol: bool) { - unsafe { - if pol { - self.registers.polarity.write(|w| w.bits(1)); - }else { - self.registers.polarity.write(|w| w.bits(0)); - } - } - } - - pub fn en_interrupt(&mut self) { - unsafe { - - self.registers.ev_enable.write(|w| w.bits(0xffff)); - } - } - - pub fn clr_interrupt(&mut self) { - unsafe { - self.registers.ev_pending.write(|w| w.bits(0xFFFF_FFFF)); - } - } - - pub fn dis_interrupt(&mut self) { - unsafe { - self.registers.ev_enable.write(|w| w.bits(0)); - } - } - - pub fn ev_pending(&mut self) -> u32 { - self.registers.ev_pending.read().bits() - } - - pub fn ev_status(&mut self) -> u32 { - self.registers.ev_status.read().bits() - } - - pub fn ev_enable(&mut self) -> u32 { - self.registers.ev_enable.read().bits() - } - -} diff --git a/rust/adc_eth_test/src/macro_test.rs b/rust/adc_eth_test/src/macro_test.rs deleted file mode 100644 index 21e1db5..0000000 --- a/rust/adc_eth_test/src/macro_test.rs +++ /dev/null @@ -1,7 +0,0 @@ - -pub mod bazmod { - #[macro_export] - macro_rules! baz { - () => () - } -} diff --git a/rust/adc_eth_test/src/main.rs b/rust/adc_eth_test/src/main.rs deleted file mode 100644 index 6e3c0ea..0000000 --- a/rust/adc_eth_test/src/main.rs +++ /dev/null @@ -1,430 +0,0 @@ -#![no_std] -#![no_main] -extern crate panic_halt; - - -extern crate riscv; -extern crate riscv_rt; -use litex_pac; -use riscv_rt::entry; - -use vexriscv::register::{vdci, vmim, vmip, vsim, vsip}; -use riscv::register::{mstatus, mcause, mie}; - - -mod ethernet; -mod print; -mod timer; -mod leds; -mod adc; -mod gpio; -mod gpio1; - -use crate::ethernet::Eth; -use timer::Timer; -use timer::Timer2; -use leds::Leds; -use leds::Leds2; -use adc::Adc; -use gpio::Gpio; -use gpio1::Gpio1; - -use managed::ManagedSlice; -use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache}; -use smoltcp::socket::{ - SocketSet, TcpSocket, TcpSocketBuffer, UdpPacketMetadata, UdpSocket, UdpSocketBuffer, -}; -use smoltcp::time::Duration; -use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; - -use crate::print::UartLogger; -use log::{debug, info, trace}; - - - -const SYSTEM_CLOCK_FREQUENCY: u32 = 49_600_000; - - - -// interrupt::interrupt!(TIMER0, isr); - -// fn isr(){ -// let a = 1 + 2; -// } - -mod mock { - use core::cell::Cell; - use smoltcp::time::{Duration, Instant}; - - #[derive(Debug)] - pub struct Clock(Cell); - - impl Clock { - pub fn new() -> Clock { - Clock(Cell::new(Instant::from_millis(0))) - } - - pub fn advance(&self, duration: Duration) { - self.0.set(self.0.get() + duration) - } - - pub fn elapsed(&self) -> Instant { - self.0.get() - } - } -} - -// This is the entry point for the application. -// It is not allowed to return. -#[entry] -fn main() -> ! { - let peripherals = litex_pac::Peripherals::take().unwrap(); - - print::print_hardware::set_hardware(peripherals.UART); - - UartLogger::init().unwrap(); - - info!("Logger initialized"); - - let mut timer = Timer::new(peripherals.TIMER0); - let mut timer2 = Timer2::new(peripherals.TIMER2); - - let mut leds = Leds::new(peripherals.LEDS); - - let mut adc = Adc::new(peripherals.ADC); - - let mut gpio = Gpio::new(peripherals.GPIO); - - let mut gpio1 = Gpio1::new(peripherals.GPIO1); - - let clock = mock::Clock::new(); - let device = Eth::new(peripherals.ETHMAC, peripherals.ETHMEM); - - let mut neighbor_cache_entries = [None; 8]; - let neighbor_cache = NeighborCache::new(&mut neighbor_cache_entries[..]); - let mut ip_addr = [IpCidr::new(IpAddress::v4(192, 168, 1, 50), 24)]; - let ip_addrs = ManagedSlice::Borrowed(&mut ip_addr); - let mut iface = EthernetInterfaceBuilder::new(device) - .ethernet_addr(EthernetAddress::from_bytes(&[ - 0xF6, 0x48, 0x74, 0xC8, 0xC4, 0x83, - ])) - .neighbor_cache(neighbor_cache) - .ip_addrs(ip_addrs) - .finalize(); - - let tcp_server_socket = { - // It is not strictly necessary to use a `static mut` and unsafe code here, but - // on embedded systems that smoltcp targets it is far better to allocate the data - // statically to verify that it fits into RAM rather than get undefined behavior - // when stack overflows. - #[link_section = ".main_ram"] - static mut TCP_SERVER_RX_DATA: [u8; 8192] = [0; 8192]; - #[link_section = ".main_ram"] - static mut TCP_SERVER_TX_DATA: [u8; 8192] = [0; 8192]; - let tcp_rx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_SERVER_RX_DATA[..] }); - let tcp_tx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_SERVER_TX_DATA[..] }); - TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer) - }; - - let udp_server_socket = { - // It is not strictly necessary to use a `static mut` and unsafe code here, but - // on embedded systems that smoltcp targets it is far better to allocate the data - // statically to verify that it fits into RAM rather than get undefined behavior - // when stack overflows. - #[link_section = ".main_ram"] - static mut UDP_SERVER_RX_METADATA: [UdpPacketMetadata; 32] = [UdpPacketMetadata::EMPTY; 32]; - #[link_section = ".main_ram"] - static mut UDP_SERVER_TX_METADATA: [UdpPacketMetadata; 32] = [UdpPacketMetadata::EMPTY; 32]; - #[link_section = ".main_ram"] - static mut UDP_SERVER_RX_DATA: [u8; 8192] = [0; 8192]; - #[link_section = ".main_ram"] - static mut UDP_SERVER_TX_DATA: [u8; 8192] = [0; 8192]; - let udp_rx_buffer = - UdpSocketBuffer::new(unsafe { &mut UDP_SERVER_RX_METADATA[..] }, unsafe { - &mut UDP_SERVER_RX_DATA[..] - }); - let udp_tx_buffer = - UdpSocketBuffer::new(unsafe { &mut UDP_SERVER_TX_METADATA[..] }, unsafe { - &mut UDP_SERVER_TX_DATA[..] - }); - UdpSocket::new(udp_rx_buffer, udp_tx_buffer) - }; - - info!("Add sockets"); - - let mut socket_set_entries: [_; 2] = Default::default(); - let mut socket_set = SocketSet::new(&mut socket_set_entries[..]); - let tcp_server_handle = socket_set.add(tcp_server_socket); - let udp_server_handle = socket_set.add(udp_server_socket); - - let mut vec: [u8; 5] = [1,2,3,4,5]; - - // gpio.en_interrupt(); - // gpio1.en_interrupt(); - - - timer2.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * 4000); - - timer2.enable(); - - timer2.en_interrupt(); - - - info!("Main loop..."); - - loop { - // match iface.poll(&mut socket_set, clock.elapsed()) { - // Ok(_) => {} - // Err(e) => { - // debug!("Poll error: {}", e); - // } - // } - // - // { - // let mut socket = socket_set.get::(tcp_server_handle); - // - // if !socket.is_active() && !socket.is_listening() { - // info!("Start listen..."); - // socket.listen(1234).unwrap(); - // } - // - // if socket.can_send() { - // info!("Can send..."); - // socket.send_slice(&vec).unwrap(); - // } - // - // - // gpio.set_interrupt_polarity(true); // falling edge - // gpio.dis_interrupt(); - // gpio1.set_interrupt_polarity(false); // falling edge - // gpio1.dis_interrupt(); - // - // msleep(&mut timer, &mut leds, 1000 as u32); - vec.rotate_right(1); - // leds.toggle_mask(4); - // - // let adcval: u32 = adc.read(); - // - // if socket.can_send() { - // socket.send_slice(&adcval.to_be_bytes()).unwrap(); - // } - - info!("\nbefore:"); - info!("vmip: {}", vmip::read()); - info!("vmim: {}", vmim::read()); - info!("mcause: {}", mcause::read().bits()); - info!("mie: {}", mie::read().bits()); - info!("btn: {}", gpio.status()); - info!("ev_pending_gpio: {}", gpio.ev_pending()); - info!("ev_status_gpio: {}", gpio.ev_status()); - info!("ev_enable_gpio: {}", gpio.ev_enable()); - info!("ev_pending_timer: {}", timer.ev_pending()); - info!("ev_status_timer: {}", timer.ev_status()); - info!("ev_enable_timer: {}", timer.ev_enable()); - - - // - // timer.dis_interrupt(); - // timer.clr_interrupt(); - - for i in 0..10000{ - for j in 0..1000{ - leds.toggle_mask(2); // toggle yellow led - } - } - - - - - // timer.disable(); - - // timer.reload(0); - // timer.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * 1000); - - // timer.enable(); - - unsafe{ - vmim::write(0); // Disable all machine interrupts - mie::set_msoft(); - // mie::set_mtimer(); - mie::set_mext(); - // mstatus::set_mie(); // Enable CPU interrupts - vmim::write(0xFFFF_FFFF); // 1010 for timer and gpio - mstatus::set_mie(); - } - // msleep(&mut timer, &mut leds, 500 as u32); - info!("\nafter:"); - info!("vmip: {}", vmip::read()); - info!("vmim: {}", vmim::read()); - info!("mcause: {}", mcause::read().bits()); - info!("mie: {}", mie::read().bits()); - info!("btn: {}", gpio.status()); - info!("ev_pending_gpio: {}", gpio.ev_pending()); - info!("ev_status_gpio: {}", gpio.ev_status()); - info!("ev_enable_gpio: {}", gpio.ev_enable()); - info!("ev_pending_timer: {}", timer.ev_pending()); - info!("ev_status_timer: {}", timer.ev_status()); - info!("ev_enable_timer: {}", timer.ev_enable()); - // vmim::write(0); - - // info!("vsim: {}", vsim::read()); - // info!("vsip: {}", vsip::read()); - // } - - for i in 0..10000{ - for j in 0..1000{ - leds.toggle_mask(2); // toggle yellow led - } - } - leds.set(0x0); - - // - // match iface.poll_delay(&socket_set, clock.elapsed()) { - // Some(Duration { millis: 0 }) => {} - // Some(delay) => { - // trace!("sleeping for {} ms", delay); - // msleep(&mut timer, &mut leds, delay.total_millis() as u32); - // clock.advance(delay) - // } - // None => clock.advance(Duration::from_millis(1)), - // } - // trace!("Clock elapsed: {}", clock.elapsed()); - - - } -} - - -#[no_mangle] -fn MachineExternal() { - let mc = mcause::read(); - let irqs_pending = vmip::read(); - // vmim::write(0); // absolutely neccessary right now to disable interrupts otherwise the processor is stuck. - - if mc.is_exception() {}; - - - let peripherals = unsafe{ litex_pac::Peripherals::steal() }; - - let mut timer = Timer::new(peripherals.TIMER0); - let mut leds = Leds::new(peripherals.LEDS); - let mut gpio1 = Gpio1::new(peripherals.GPIO1); - let mut gpio = Gpio::new(peripherals.GPIO); - gpio1.clr_interrupt(); - // gpio.clr_interrupt(); - - - - - if irqs_pending & (1 << 1) != 0 { - handle_timer_irq(); - } - - if irqs_pending & (1 << 3) != 0 { - handle_btn_irq(); - } - - if irqs_pending & (1 << 5) != 0 { - handle_timer2_irq(); - } - - - // timer.clr_interrupt(); - - -} - -fn handle_timer_irq() { - - let peripherals = unsafe{ litex_pac::Peripherals::steal() }; - - let mut timer = Timer::new(peripherals.TIMER0); - let mut leds = Leds::new(peripherals.LEDS); - - leds.toggle_mask(4); // toggle green led - timer.clr_interrupt(); - -} - -fn handle_timer2_irq() { - - let peripherals = unsafe{ litex_pac::Peripherals::steal() }; - - let mut timer2 = Timer2::new(peripherals.TIMER2); - let mut leds2 = Leds2::new(peripherals.LEDS2); - - leds2.toggle_mask(0xf); - timer2.clr_interrupt(); - timer2.disable(); - - timer2.reload(0); - - timer2.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * 4000); - - timer2.enable(); - -} - -fn handle_btn_irq() { - - - - let peripherals = unsafe{ litex_pac::Peripherals::steal() }; - - let mut gpio = Gpio::new(peripherals.GPIO); - let mut leds = Leds::new(peripherals.LEDS); - - // gpio.clr_interrupt() - leds.toggle_mask(0x10); - // if gpio.ev_pending() == 0 { - // leds.toggle_mask(0x2); // toggle green led - // } - // leds.toggle_mask(4); // toggle green led - // leds.toggle_mask(4); // toggle green led - for i in 0..10000{ - for j in 0..1045{ - leds.toggle_mask(0x8); // toggle yellow led - } - } - gpio.clr_interrupt(); - leds.toggle_mask(0xff); - // if gpio.ev_pending() == 0 { - // leds.toggle_mask(0xff); // toggle green led - // } - for i in 0..2000{ - for j in 0..1000{ - leds.toggle_mask(0x8); // toggle yellow led - } - } - // vmim::write(0); - // gpio.dis_interrupt(); - // gpio.clr_interrupt(); - // gpio.en_interrupt(); - // gpio.clr_interrupt(); -} - - - - -fn u32_to_u8(x:u32) -> [u8;4] { - let b1 : u8 = ((x >> 24) & 0xff) as u8; - let b2 : u8 = ((x >> 16) & 0xff) as u8; - let b3 : u8 = ((x >> 8) & 0xff) as u8; - let b4 : u8 = (x & 0xff) as u8; - return [b1, b2, b3, b4] -} - -fn msleep(timer: &mut Timer, leds : &mut Leds, ms: u32) { - timer.disable(); - - timer.reload(0); - timer.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * ms); - - timer.enable(); - - // Wait until the time has elapsed - while timer.value() > 0 { - // leds.toggle_mask(2); // toggle yellow led - } - timer.disable(); -} diff --git a/rust/adc_eth_test/src/timer.rs b/rust/adc_eth_test/src/timer.rs deleted file mode 100644 index 81ca1ba..0000000 --- a/rust/adc_eth_test/src/timer.rs +++ /dev/null @@ -1,146 +0,0 @@ -use litex_pac::{TIMER0,TIMER2}; - -pub struct Timer { - registers: TIMER0, -} - -impl Timer { - pub fn new(registers: TIMER0) -> Self { - Self { registers } - } - - pub fn enable(&mut self) { - unsafe { - self.registers.en.write(|w| w.bits(1)); - } - } - - pub fn disable(&mut self) { - unsafe { - self.registers.en.write(|w| w.bits(0)); - } - } - - pub fn load(&mut self, value: u32) { - unsafe { - self.registers.load.write(|w| w.bits(value)); - } - } - - pub fn reload(&mut self, value: u32) { - unsafe { - self.registers.reload.write(|w| w.bits(value)); - } - } - - pub fn value(&mut self) -> u32 { - unsafe { - self.registers.update_value.write(|w| w.bits(1)); - } - - self.registers.value.read().bits() - } - - pub fn en_interrupt(&mut self) { - unsafe { - self.registers.ev_enable.write(|w| w.bits(0x1)); - } - } - - pub fn clr_interrupt(&mut self) { - unsafe { - self.registers.ev_pending.write(|w| w.bits(0xFFFF_FFFF)); - } - } - - pub fn dis_interrupt(&mut self) { - unsafe { - self.registers.ev_enable.write(|w| w.bits(0)); - } - } - - pub fn ev_pending(&mut self) -> u32 { - self.registers.ev_pending.read().bits() - } - - pub fn ev_status(&mut self) -> u32 { - self.registers.ev_status.read().bits() - } - - pub fn ev_enable(&mut self) -> u32 { - self.registers.ev_enable.read().bits() - } -} - - -pub struct Timer2 { - registers: TIMER2, -} - -impl Timer2 { - pub fn new(registers: TIMER2) -> Self { - Self { registers } - } - - pub fn enable(&mut self) { - unsafe { - self.registers.en.write(|w| w.bits(1)); - } - } - - pub fn disable(&mut self) { - unsafe { - self.registers.en.write(|w| w.bits(0)); - } - } - - pub fn load(&mut self, value: u32) { - unsafe { - self.registers.load.write(|w| w.bits(value)); - } - } - - pub fn reload(&mut self, value: u32) { - unsafe { - self.registers.reload.write(|w| w.bits(value)); - } - } - - pub fn value(&mut self) -> u32 { - unsafe { - self.registers.update_value.write(|w| w.bits(1)); - } - - self.registers.value.read().bits() - } - - pub fn en_interrupt(&mut self) { - unsafe { - self.registers.ev_enable.write(|w| w.bits(0x1)); - } - } - - pub fn clr_interrupt(&mut self) { - unsafe { - self.registers.ev_pending.write(|w| w.bits(0xFFFF_FFFF)); - } - } - - pub fn dis_interrupt(&mut self) { - unsafe { - self.registers.ev_enable.write(|w| w.bits(0)); - } - } - - pub fn ev_pending(&mut self) -> u32 { - self.registers.ev_pending.read().bits() - } - - pub fn ev_status(&mut self) -> u32 { - self.registers.ev_status.read().bits() - } - - pub fn ev_enable(&mut self) -> u32 { - self.registers.ev_enable.read().bits() - } -} diff --git a/rust/adc_eth_test/.cargo/config b/rust/temp_controller/.cargo/config similarity index 100% rename from rust/adc_eth_test/.cargo/config rename to rust/temp_controller/.cargo/config diff --git a/rust/adc_eth_test/.cargo/flash.sh b/rust/temp_controller/.cargo/flash.sh similarity index 100% rename from rust/adc_eth_test/.cargo/flash.sh rename to rust/temp_controller/.cargo/flash.sh diff --git a/rust/adc_eth_test/Cargo.lock b/rust/temp_controller/Cargo.lock similarity index 100% rename from rust/adc_eth_test/Cargo.lock rename to rust/temp_controller/Cargo.lock diff --git a/rust/adc_eth_test/Cargo.toml b/rust/temp_controller/Cargo.toml similarity index 100% rename from rust/adc_eth_test/Cargo.toml rename to rust/temp_controller/Cargo.toml diff --git a/rust/adc_eth_test/README.md b/rust/temp_controller/README.md similarity index 100% rename from rust/adc_eth_test/README.md rename to rust/temp_controller/README.md diff --git a/rust/adc_eth_test/src/adc.rs b/rust/temp_controller/src/adc.rs similarity index 100% rename from rust/adc_eth_test/src/adc.rs rename to rust/temp_controller/src/adc.rs diff --git a/rust/adc_eth_test/src/ethernet.rs b/rust/temp_controller/src/ethernet.rs similarity index 100% rename from rust/adc_eth_test/src/ethernet.rs rename to rust/temp_controller/src/ethernet.rs diff --git a/rust/adc_eth_test/src/gpio.rs b/rust/temp_controller/src/gpio.rs similarity index 100% rename from rust/adc_eth_test/src/gpio.rs rename to rust/temp_controller/src/gpio.rs diff --git a/rust/adc_eth_test/src/leds.rs b/rust/temp_controller/src/leds.rs similarity index 100% rename from rust/adc_eth_test/src/leds.rs rename to rust/temp_controller/src/leds.rs diff --git a/rust/temp_controller/src/main.rs b/rust/temp_controller/src/main.rs new file mode 100644 index 0000000..e44e8f3 --- /dev/null +++ b/rust/temp_controller/src/main.rs @@ -0,0 +1,183 @@ +#![no_std] +#![no_main] +extern crate panic_halt; + + +extern crate riscv; +extern crate riscv_rt; +use litex_pac; +use riscv_rt::entry; + +use vexriscv::register::{vdci, vmim, vmip, vsim, vsip}; +use riscv::register::{mstatus, mcause, mie}; + + +mod ethernet; +mod print; +mod timer; +mod leds; +mod adc; +mod gpio; + +use crate::ethernet::Eth; +use timer::Timer; +use leds::Leds; +use leds::Leds2; +use adc::Adc; +use gpio::Gpio; + +use managed::ManagedSlice; +use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache}; +use smoltcp::socket::{ + SocketSet, TcpSocket, TcpSocketBuffer, UdpPacketMetadata, UdpSocket, UdpSocketBuffer, +}; +use smoltcp::time::Duration; +use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; + +use crate::print::UartLogger; +use log::{debug, info, trace}; + + + +const SYSTEM_CLOCK_FREQUENCY: u32 = 49_600_000; + + + +mod mock { + use core::cell::Cell; + use smoltcp::time::{Duration, Instant}; + + #[derive(Debug)] + pub struct Clock(Cell); + + impl Clock { + pub fn new() -> Clock { + Clock(Cell::new(Instant::from_millis(0))) + } + + pub fn advance(&self, duration: Duration) { + self.0.set(self.0.get() + duration) + } + + pub fn elapsed(&self) -> Instant { + self.0.get() + } + } +} + +// This is the entry point for the application. +// It is not allowed to return. +#[entry] +fn main() -> ! { + let peripherals = litex_pac::Peripherals::take().unwrap(); + + print::print_hardware::set_hardware(peripherals.UART); + + UartLogger::init().unwrap(); + + info!("Logger initialized"); + + let mut timer = Timer::new(peripherals.TIMER0); + let mut timer2 = Timer::new(peripherals.TIMER2); + + let mut leds = Leds::new(peripherals.LEDS); + + let mut adc = Adc::new(peripherals.ADC); + + let mut gpio = Gpio::new(peripherals.GPIO); + + let clock = mock::Clock::new(); + let device = Eth::new(peripherals.ETHMAC, peripherals.ETHMEM); + + let mut neighbor_cache_entries = [None; 8]; + let neighbor_cache = NeighborCache::new(&mut neighbor_cache_entries[..]); + let mut ip_addr = [IpCidr::new(IpAddress::v4(192, 168, 1, 50), 24)]; + let ip_addrs = ManagedSlice::Borrowed(&mut ip_addr); + let mut iface = EthernetInterfaceBuilder::new(device) + .ethernet_addr(EthernetAddress::from_bytes(&[ + 0xF6, 0x48, 0x74, 0xC8, 0xC4, 0x83, + ])) + .neighbor_cache(neighbor_cache) + .ip_addrs(ip_addrs) + .finalize(); + + let tcp_server_socket = { + // It is not strictly necessary to use a `static mut` and unsafe code here, but + // on embedded systems that smoltcp targets it is far better to allocate the data + // statically to verify that it fits into RAM rather than get undefined behavior + // when stack overflows. + #[link_section = ".main_ram"] + static mut TCP_SERVER_RX_DATA: [u8; 8192] = [0; 8192]; + #[link_section = ".main_ram"] + static mut TCP_SERVER_TX_DATA: [u8; 8192] = [0; 8192]; + let tcp_rx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_SERVER_RX_DATA[..] }); + let tcp_tx_buffer = TcpSocketBuffer::new(unsafe { &mut TCP_SERVER_TX_DATA[..] }); + TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer) + }; + + let udp_server_socket = { + // It is not strictly necessary to use a `static mut` and unsafe code here, but + // on embedded systems that smoltcp targets it is far better to allocate the data + // statically to verify that it fits into RAM rather than get undefined behavior + // when stack overflows. + #[link_section = ".main_ram"] + static mut UDP_SERVER_RX_METADATA: [UdpPacketMetadata; 32] = [UdpPacketMetadata::EMPTY; 32]; + #[link_section = ".main_ram"] + static mut UDP_SERVER_TX_METADATA: [UdpPacketMetadata; 32] = [UdpPacketMetadata::EMPTY; 32]; + #[link_section = ".main_ram"] + static mut UDP_SERVER_RX_DATA: [u8; 8192] = [0; 8192]; + #[link_section = ".main_ram"] + static mut UDP_SERVER_TX_DATA: [u8; 8192] = [0; 8192]; + let udp_rx_buffer = + UdpSocketBuffer::new(unsafe { &mut UDP_SERVER_RX_METADATA[..] }, unsafe { + &mut UDP_SERVER_RX_DATA[..] + }); + let udp_tx_buffer = + UdpSocketBuffer::new(unsafe { &mut UDP_SERVER_TX_METADATA[..] }, unsafe { + &mut UDP_SERVER_TX_DATA[..] + }); + UdpSocket::new(udp_rx_buffer, udp_tx_buffer) + }; + + info!("Add sockets"); + + let mut socket_set_entries: [_; 2] = Default::default(); + let mut socket_set = SocketSet::new(&mut socket_set_entries[..]); + let tcp_server_handle = socket_set.add(tcp_server_socket); + let udp_server_handle = socket_set.add(udp_server_socket); + + timer2.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * 4000); + + timer2.enable(); + + timer2.en_interrupt(); + + + info!("Main loop..."); + + loop { + info!("{}", timer2.value()); + } +} + + +#[no_mangle] +fn MachineExternal() { + let mc = mcause::read(); + let irqs_pending = vmip::read(); + if mc.is_exception() {}; +} + +// fn msleep(timer: &mut Timer, leds : &mut Leds, ms: u32) { +// timer.disable(); +// +// timer.reload(0); +// timer.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * ms); +// +// timer.enable(); +// +// // Wait until the time has elapsed +// while timer.value() > 0 { +// } +// timer.disable(); +// } diff --git a/rust/adc_eth_test/src/print.rs b/rust/temp_controller/src/print.rs similarity index 100% rename from rust/adc_eth_test/src/print.rs rename to rust/temp_controller/src/print.rs diff --git a/rust/temp_controller/src/timer.rs b/rust/temp_controller/src/timer.rs new file mode 100644 index 0000000..f099720 --- /dev/null +++ b/rust/temp_controller/src/timer.rs @@ -0,0 +1,74 @@ +use litex_pac::{TIMER0, TIMER2}; + + +pub struct Timer { + registers: T, +} + +impl Timer { + pub fn new(registers: T) -> Self { + Self { registers } + } + + pub fn enable(&mut self) { + unsafe { + self.registers.en.write(|w| w.bits(1)); + } + } + + pub fn disable(&mut self) { + unsafe { + self.registers.en.write(|w| w.bits(0)); + } + } + + pub fn load(&mut self, value: u32) { + unsafe { + self.registers.load.write(|w| w.bits(value)); + } + } + + pub fn reload(&mut self, value: u32) { + unsafe { + self.registers.reload.write(|w| w.bits(value)); + } + } + + pub fn value(&mut self) -> u32 { + unsafe { + self.registers.update_value.write(|w| w.bits(1)); + } + + self.registers.value.read().bits() + } + + pub fn en_interrupt(&mut self) { + unsafe { + self.registers.ev_enable.write(|w| w.bits(0x1)); + } + } + + pub fn clr_interrupt(&mut self) { + unsafe { + self.registers.ev_pending.write(|w| w.bits(0xFFFF_FFFF)); + } + } + + pub fn dis_interrupt(&mut self) { + unsafe { + self.registers.ev_enable.write(|w| w.bits(0)); + } + } + + pub fn ev_pending(&mut self) -> u32 { + self.registers.ev_pending.read().bits() + } + + pub fn ev_status(&mut self) -> u32 { + self.registers.ev_status.read().bits() + } + + pub fn ev_enable(&mut self) -> u32 { + self.registers.ev_enable.read().bits() + } +} diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index ff328ea..1162be4 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -357,10 +357,6 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi self.add_csr("gpio") self.add_interrupt("gpio") - self.submodules.gpio1 = gpio1 = GPIOIn(platform.request("p3v"), with_irq=True) - self.add_csr("gpio1") - self.add_interrupt("gpio1") - self.submodules.timer2 = Timer() self.add_csr("timer2") self.add_interrupt("timer2") From 88dc0dc9dc2ca8128766b83c46a3788250ffe49e Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Thu, 29 Apr 2021 12:52:24 +0200 Subject: [PATCH 20/36] baseline prepared --- rust/temp_controller/src/gpio.rs | 60 +++++++++++++++++++++- rust/temp_controller/src/main.rs | 38 ++++++++++++-- rust/temp_controller/src/timer.rs | 82 +++++++++++++++++++++++++++++-- 3 files changed, 169 insertions(+), 11 deletions(-) diff --git a/rust/temp_controller/src/gpio.rs b/rust/temp_controller/src/gpio.rs index 10e9655..460b37d 100644 --- a/rust/temp_controller/src/gpio.rs +++ b/rust/temp_controller/src/gpio.rs @@ -1,4 +1,4 @@ -use litex_pac::GPIO; +use litex_pac::{GPIO}; pub struct Gpio { registers: GPIO, @@ -57,3 +57,61 @@ impl Gpio { } } + +// pub struct Gpio2 { +// registers: GPIO2, +// } +// +// #[allow(dead_code)] +// impl Gpio2 { +// +// pub fn new(registers: GPIO2) -> Self { +// Self { registers } +// } +// +// pub fn status(&mut self) -> u32 { +// self.registers.in_.read().bits() +// } +// +// pub fn set_interrupt_polarity(&mut self, pol: bool) { +// unsafe { +// if pol { +// self.registers.polarity.write(|w| w.bits(1)); +// }else { +// self.registers.polarity.write(|w| w.bits(0)); +// } +// } +// } +// +// pub fn en_interrupt(&mut self) { +// unsafe { +// +// self.registers.ev_enable.write(|w| w.bits(0xffff)); +// } +// } +// +// pub fn clr_interrupt(&mut self) { +// unsafe { +// self.registers.ev_pending.write(|w| w.bits(0xFFFF_FFFF)); +// } +// } +// +// pub fn dis_interrupt(&mut self) { +// unsafe { +// self.registers.ev_enable.write(|w| w.bits(0)); +// } +// } +// +// pub fn ev_pending(&mut self) -> u32 { +// self.registers.ev_pending.read().bits() +// } +// +// pub fn ev_status(&mut self) -> u32 { +// self.registers.ev_status.read().bits() +// } +// +// pub fn ev_enable(&mut self) -> u32 { +// self.registers.ev_enable.read().bits() +// } +// +// } diff --git a/rust/temp_controller/src/main.rs b/rust/temp_controller/src/main.rs index e44e8f3..c3ccf66 100644 --- a/rust/temp_controller/src/main.rs +++ b/rust/temp_controller/src/main.rs @@ -20,11 +20,10 @@ mod adc; mod gpio; use crate::ethernet::Eth; -use timer::Timer; -use leds::Leds; -use leds::Leds2; +use timer::{Timer,Timer2}; +use leds::{Leds,Leds2}; use adc::Adc; -use gpio::Gpio; +use gpio::{Gpio}; use managed::ManagedSlice; use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache}; @@ -78,9 +77,10 @@ fn main() -> ! { info!("Logger initialized"); let mut timer = Timer::new(peripherals.TIMER0); - let mut timer2 = Timer::new(peripherals.TIMER2); + let mut timer2 = Timer2::new(peripherals.TIMER2); let mut leds = Leds::new(peripherals.LEDS); + let mut leds2 = Leds2::new(peripherals.LEDS2); let mut adc = Adc::new(peripherals.ADC); @@ -152,11 +152,17 @@ fn main() -> ! { timer2.en_interrupt(); + unsafe{ + vmim::write(0xFFFF_FFFF); // 1010 for timer and gpio + mstatus::set_mie(); + mie::set_mext(); + } info!("Main loop..."); loop { info!("{}", timer2.value()); + leds.toggle_mask(0xf); } } @@ -166,6 +172,28 @@ fn MachineExternal() { let mc = mcause::read(); let irqs_pending = vmip::read(); if mc.is_exception() {}; + if irqs_pending & (1 << 5) != 0 { + handle_timer2_irq(); + } +} + +fn handle_timer2_irq() { + + let peripherals = unsafe{ litex_pac::Peripherals::steal() }; + + let mut timer2 = Timer2::new(peripherals.TIMER2); + let mut leds2 = Leds2::new(peripherals.LEDS2); + + leds2.toggle_mask(0xf); + timer2.clr_interrupt(); + timer2.disable(); + + timer2.reload(0); + + timer2.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * 4000); + + timer2.enable(); + } // fn msleep(timer: &mut Timer, leds : &mut Leds, ms: u32) { diff --git a/rust/temp_controller/src/timer.rs b/rust/temp_controller/src/timer.rs index f099720..81ca1ba 100644 --- a/rust/temp_controller/src/timer.rs +++ b/rust/temp_controller/src/timer.rs @@ -1,12 +1,84 @@ -use litex_pac::{TIMER0, TIMER2}; +use litex_pac::{TIMER0,TIMER2}; + +pub struct Timer { + registers: TIMER0, +} + +impl Timer { + pub fn new(registers: TIMER0) -> Self { + Self { registers } + } + + pub fn enable(&mut self) { + unsafe { + self.registers.en.write(|w| w.bits(1)); + } + } + + pub fn disable(&mut self) { + unsafe { + self.registers.en.write(|w| w.bits(0)); + } + } + + pub fn load(&mut self, value: u32) { + unsafe { + self.registers.load.write(|w| w.bits(value)); + } + } + + pub fn reload(&mut self, value: u32) { + unsafe { + self.registers.reload.write(|w| w.bits(value)); + } + } + + pub fn value(&mut self) -> u32 { + unsafe { + self.registers.update_value.write(|w| w.bits(1)); + } + + self.registers.value.read().bits() + } + + pub fn en_interrupt(&mut self) { + unsafe { + self.registers.ev_enable.write(|w| w.bits(0x1)); + } + } + + pub fn clr_interrupt(&mut self) { + unsafe { + self.registers.ev_pending.write(|w| w.bits(0xFFFF_FFFF)); + } + } + + pub fn dis_interrupt(&mut self) { + unsafe { + self.registers.ev_enable.write(|w| w.bits(0)); + } + } + + pub fn ev_pending(&mut self) -> u32 { + self.registers.ev_pending.read().bits() + } + + pub fn ev_status(&mut self) -> u32 { + self.registers.ev_status.read().bits() + } + + pub fn ev_enable(&mut self) -> u32 { + self.registers.ev_enable.read().bits() + } +} -pub struct Timer { - registers: T, +pub struct Timer2 { + registers: TIMER2, } -impl Timer { - pub fn new(registers: T) -> Self { +impl Timer2 { + pub fn new(registers: TIMER2) -> Self { Self { registers } } From 994f0e3bd4cd7bdadfdeb8e6abb574c23b6598ac Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Thu, 29 Apr 2021 16:32:25 +0200 Subject: [PATCH 21/36] pac formated! and interrupts now use the pac enum --- rust/litex-pac/clSOC.svd | 146 +++++++++--------------------- rust/temp_controller/src/adc.rs | 1 - rust/temp_controller/src/gpio.rs | 7 +- rust/temp_controller/src/leds.rs | 9 +- rust/temp_controller/src/main.rs | 53 ++++++----- rust/temp_controller/src/pwm.rs | 23 +++++ rust/temp_controller/src/timer.rs | 3 +- soc/colorlight_5a_75x.py | 34 +++---- soc/leds.py | 27 ++++++ soc/pwm.py | 35 +++++++ 10 files changed, 180 insertions(+), 158 deletions(-) create mode 100644 rust/temp_controller/src/pwm.rs create mode 100644 soc/leds.py create mode 100644 soc/pwm.py diff --git a/rust/litex-pac/clSOC.svd b/rust/litex-pac/clSOC.svd index 82bd288..d9b6eb5 100644 --- a/rust/litex-pac/clSOC.svd +++ b/rust/litex-pac/clSOC.svd @@ -1191,106 +1191,9 @@ register to disable individual events.]]> 3 - - GPIO1 - 0xF0007000 - GPIO1 - - - IN - - 0x0000 - 0x00 - 32 - - - in - 0 - [0:0] - 0 - - - - - POLARITY - - 0x0004 - 0x00 - 32 - - - polarity - 0 - [0:0] - 0 - - - - - EV_STATUS - - 0x0008 - 0x00 - 32 - - - i0 - 0 - [0:0] - 0 - - - - - - EV_PENDING - - 0x000c - 0x00 - 32 - - - i0 - 0 - [0:0] - 0 - - - - - - EV_ENABLE - - 0x0010 - 0x00 - 32 - - - i0 - 0 - [0:0] - 0 - - - - - - - 0 - 0x14 - registers - - - gpio1 - 4 - - TIMER2 - 0xF0007800 + 0xF0007000 TIMER2 @@ -1431,9 +1334,51 @@ register to disable individual events.]]> timer2 - 5 + 4 + + PWM + 0xF0007800 + PWM + + + PERIOD + + 0x0000 + 0x00 + 32 + + + period + 31 + [31:0] + 0 + + + + + VALUE + + 0x0004 + 0x00 + 32 + + + value + 31 + [31:0] + 0 + + + + + + 0 + 0x8 + registers + + ETHMEM 0x80000000 @@ -1572,9 +1517,8 @@ register to disable individual events.]]> - - + diff --git a/rust/temp_controller/src/adc.rs b/rust/temp_controller/src/adc.rs index da4927b..ba4cbc8 100644 --- a/rust/temp_controller/src/adc.rs +++ b/rust/temp_controller/src/adc.rs @@ -13,5 +13,4 @@ impl Adc { pub fn read(&mut self) -> u32 { self.registers.adc_value.read().bits() } - } diff --git a/rust/temp_controller/src/gpio.rs b/rust/temp_controller/src/gpio.rs index 460b37d..5c28f83 100644 --- a/rust/temp_controller/src/gpio.rs +++ b/rust/temp_controller/src/gpio.rs @@ -1,4 +1,4 @@ -use litex_pac::{GPIO}; +use litex_pac::GPIO; pub struct Gpio { registers: GPIO, @@ -6,7 +6,6 @@ pub struct Gpio { #[allow(dead_code)] impl Gpio { - pub fn new(registers: GPIO) -> Self { Self { registers } } @@ -19,7 +18,7 @@ impl Gpio { unsafe { if pol { self.registers.polarity.write(|w| w.bits(1)); - }else { + } else { self.registers.polarity.write(|w| w.bits(0)); } } @@ -27,7 +26,6 @@ impl Gpio { pub fn en_interrupt(&mut self) { unsafe { - self.registers.ev_enable.write(|w| w.bits(0xffff)); } } @@ -55,7 +53,6 @@ impl Gpio { pub fn ev_enable(&mut self) -> u32 { self.registers.ev_enable.read().bits() } - } // pub struct Gpio2 { diff --git a/rust/temp_controller/src/leds.rs b/rust/temp_controller/src/leds.rs index 0921950..df6e647 100644 --- a/rust/temp_controller/src/leds.rs +++ b/rust/temp_controller/src/leds.rs @@ -1,4 +1,4 @@ -use litex_pac::{LEDS,LEDS2}; +use litex_pac::{LEDS, LEDS2}; pub struct Leds { registers: LEDS, @@ -10,8 +10,7 @@ impl Leds { Self { registers } } - pub fn set_single(&mut self, red: bool, yellow: bool, - green: bool) { + pub fn set_single(&mut self, red: bool, yellow: bool, green: bool) { self.registers.out.write(|w| { w.r().bit(red); w.g().bit(green); @@ -49,7 +48,6 @@ impl Leds { } } - pub struct Leds2 { registers: LEDS2, } @@ -60,8 +58,7 @@ impl Leds2 { Self { registers } } - pub fn set_single(&mut self, red: bool, yellow: bool, - green: bool) { + pub fn set_single(&mut self, red: bool, yellow: bool, green: bool) { self.registers.out.write(|w| { w.r1().bit(red); w.g1().bit(green); diff --git a/rust/temp_controller/src/main.rs b/rust/temp_controller/src/main.rs index c3ccf66..0908268 100644 --- a/rust/temp_controller/src/main.rs +++ b/rust/temp_controller/src/main.rs @@ -2,28 +2,28 @@ #![no_main] extern crate panic_halt; - extern crate riscv; extern crate riscv_rt; use litex_pac; use riscv_rt::entry; +use riscv::register::{mcause, mie, mstatus}; use vexriscv::register::{vdci, vmim, vmip, vsim, vsip}; -use riscv::register::{mstatus, mcause, mie}; - +mod adc; mod ethernet; +mod gpio; +mod leds; mod print; +mod pwm; mod timer; -mod leds; -mod adc; -mod gpio; use crate::ethernet::Eth; -use timer::{Timer,Timer2}; -use leds::{Leds,Leds2}; use adc::Adc; -use gpio::{Gpio}; +use gpio::Gpio; +use leds::{Leds, Leds2}; +use pwm::Pwm; +use timer::{Timer, Timer2}; use managed::ManagedSlice; use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache}; @@ -36,12 +36,8 @@ use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; use crate::print::UartLogger; use log::{debug, info, trace}; - - const SYSTEM_CLOCK_FREQUENCY: u32 = 49_600_000; - - mod mock { use core::cell::Cell; use smoltcp::time::{Duration, Instant}; @@ -86,6 +82,8 @@ fn main() -> ! { let mut gpio = Gpio::new(peripherals.GPIO); + let mut pwm = Pwm::new(peripherals.PWM); + let clock = mock::Clock::new(); let device = Eth::new(peripherals.ETHMAC, peripherals.ETHMEM); @@ -152,8 +150,11 @@ fn main() -> ! { timer2.en_interrupt(); - unsafe{ - vmim::write(0xFFFF_FFFF); // 1010 for timer and gpio + pwm.set_period(1 << 15); + pwm.set_value(1 << 13); + + unsafe { + vmim::write(0xFFFF_FFFF); // 1010 for timer and gpio mstatus::set_mie(); mie::set_mext(); } @@ -166,20 +167,31 @@ fn main() -> ! { } } - #[no_mangle] fn MachineExternal() { let mc = mcause::read(); let irqs_pending = vmip::read(); if mc.is_exception() {}; - if irqs_pending & (1 << 5) != 0 { - handle_timer2_irq(); + for irq_no in 0..32 { + if irqs_pending & (1 << irq_no) != 0 { + match isr_to_interrupt(irq_no) { + Some(1) => system_tick(), + _ => {} //unsafe{vmim::write(vmim::read() ^ (1< Option { + if isr == (litex_pac::Interrupt::TIMER2 as u8) { + return Some(1); + } - let peripherals = unsafe{ litex_pac::Peripherals::steal() }; + None +} + +fn system_tick() { + let peripherals = unsafe { litex_pac::Peripherals::steal() }; // steal all but only use the safe ones ;) let mut timer2 = Timer2::new(peripherals.TIMER2); let mut leds2 = Leds2::new(peripherals.LEDS2); @@ -193,7 +205,6 @@ fn handle_timer2_irq() { timer2.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * 4000); timer2.enable(); - } // fn msleep(timer: &mut Timer, leds : &mut Leds, ms: u32) { diff --git a/rust/temp_controller/src/pwm.rs b/rust/temp_controller/src/pwm.rs new file mode 100644 index 0000000..780b63c --- /dev/null +++ b/rust/temp_controller/src/pwm.rs @@ -0,0 +1,23 @@ +use litex_pac::PWM; + +pub struct Pwm { + registers: PWM, +} + +impl Pwm { + pub fn new(registers: PWM) -> Self { + Self { registers } + } + + pub fn set_period(&mut self, period: u32) { + unsafe { + self.registers.period.write(|w| w.bits(period)); + } + } + + pub fn set_value(&mut self, val: u32) { + unsafe { + self.registers.value.write(|w| w.bits(val)); + } + } +} diff --git a/rust/temp_controller/src/timer.rs b/rust/temp_controller/src/timer.rs index 81ca1ba..e15ebb2 100644 --- a/rust/temp_controller/src/timer.rs +++ b/rust/temp_controller/src/timer.rs @@ -1,4 +1,4 @@ -use litex_pac::{TIMER0,TIMER2}; +use litex_pac::{TIMER0, TIMER2}; pub struct Timer { registers: TIMER0, @@ -72,7 +72,6 @@ impl Timer { } } - pub struct Timer2 { registers: TIMER2, } diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index 1162be4..ac8d85a 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -40,6 +40,8 @@ import litex.soc.doc as lxsocdoc from adc import ADC +from leds import Leds +from pwm import PWM from litex.soc.cores.gpio import GPIOIn @@ -70,6 +72,10 @@ def load_bitstream(self, bitstream_file): ("dac", 1, Pins("j4:1"), IOStandard("LVCMOS33")), # sigma-delta dac output ] +_pwm = [ + ("pwm", 0, Pins("j3:0"), IOStandard("LVCMOS33")), +] + _leds = [ ("g", 0, Pins("j6:5"), IOStandard("LVCMOS33")), ("r", 0, Pins("j6:10"), IOStandard("LVCMOS33")), # Not really here but there is congestion with the pins otherwise.. @@ -95,28 +101,6 @@ def load_bitstream(self, bitstream_file): ] -# LEDs --------------------------------------------------------------------------------------------- - -class Leds(Module, AutoCSR, AutoDoc): - """LED control. - 3 LEDs connected to random IOs - Attributes: - led_pin: Signals of the LED pin outputs. - led_polarity: Bit pattern to adjust polarity. 0 stays the same 1 inverts the signal. - led_name: Array of the LED names and descriptions. [["name1", "description1"], ["name2", "description2"]] - """ - def __init__(self, led_pin, led_polarity=0x00, led_name=[]): - # Documentation - self.intro = ModuleDoc("""LED control. - The LEDs are normal LEDs. Good information. :) - """) - - # HDL Implementationj - self._out = CSRStorage(len(led_pin), fields=[ - CSRField(fld[0], description=fld[1]) for fld in led_name - ]) - self.comb += led_pin.eq(self._out.storage ^ led_polarity) - # CRG ---------------------------------------------------------------------------------------------- @@ -296,6 +280,7 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi # add IO extentions platform.add_extension(_leds) + platform.add_extension(_pwm) platform.add_extension(_adc_second_order) @@ -361,6 +346,11 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi self.add_csr("timer2") self.add_interrupt("timer2") + self.submodules.pwm = PWM(platform.request("pwm"), width=32) + self.add_csr("pwm") + + + # Helper functions --------------------------------------------------------------------------------- diff --git a/soc/leds.py b/soc/leds.py new file mode 100644 index 0000000..3920cf0 --- /dev/null +++ b/soc/leds.py @@ -0,0 +1,27 @@ + +import numpy as np +from migen import * +from litex.soc.interconnect.csr import AutoCSR, CSRStorage, CSRStatus, CSRField +from litex.soc.integration.doc import AutoDoc, ModuleDoc + +# LEDs --------------------------------------------------------------------------------------------- + +class Leds(Module, AutoCSR, AutoDoc): + """LED control. + 3 LEDs connected to random IOs + Attributes: + led_pin: Signals of the LED pin outputs. + led_polarity: Bit pattern to adjust polarity. 0 stays the same 1 inverts the signal. + led_name: Array of the LED names and descriptions. [["name1", "description1"], ["name2", "description2"]] + """ + def __init__(self, led_pin, led_polarity=0x00, led_name=[]): + # Documentation + self.intro = ModuleDoc("""LED control. + The LEDs are normal LEDs. Good information. :) + """) + + # HDL Implementationj + self._out = CSRStorage(len(led_pin), fields=[ + CSRField(fld[0], description=fld[1]) for fld in led_name + ]) + self.comb += led_pin.eq(self._out.storage ^ led_polarity) diff --git a/soc/pwm.py b/soc/pwm.py new file mode 100644 index 0000000..42e65d0 --- /dev/null +++ b/soc/pwm.py @@ -0,0 +1,35 @@ +# SingularitySurfer 2020 + + +import numpy as np +from migen import * +from litex.soc.interconnect.csr import AutoCSR, CSRStorage, CSRStatus, CSRField +from litex.soc.integration.doc import AutoDoc, ModuleDoc + + +class PWM(Module, AutoCSR): + """A simple PWM peripheral that uses a timer at sysclock. + + Parameters + ---------- + pin : output pin + width : width of the physical counter + """ + def __init__(self, pin, width=32): + + # Documentation + self.intro = ModuleDoc("""A simple PWM peripheral that uses a timer at sysclock. + PWM period software adjustable. If pwm output value larger that period -> kaputt. + """) + + self.period = CSRStorage(width, description='pwm period in sys cycles') + self.value = CSRStorage(width, description='pwm output value in sys cycles') + + + cnt = Signal(width) + + self.sync += { + cnt.eq(cnt+1), + If(cnt == self.period.storage, cnt.eq(0)), + pin.eq(cnt < self.value.storage) + } \ No newline at end of file From 602b40a37a0f280de80ea468770f802dcf858bbf Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Fri, 30 Apr 2021 15:59:14 +0200 Subject: [PATCH 22/36] IIR working i think --- rust/temp_controller/Cargo.lock | 28 +++++++++---------- rust/temp_controller/Cargo.toml | 2 +- rust/temp_controller/rust-project.json | 4 +++ rust/temp_controller/src/iir.rs | 37 ++++++++++++++++++++++++++ rust/temp_controller/src/main.rs | 30 ++++++++++++--------- 5 files changed, 74 insertions(+), 27 deletions(-) create mode 100644 rust/temp_controller/rust-project.json create mode 100644 rust/temp_controller/src/iir.rs diff --git a/rust/temp_controller/Cargo.lock b/rust/temp_controller/Cargo.lock index 4e520a7..75871bb 100644 --- a/rust/temp_controller/Cargo.lock +++ b/rust/temp_controller/Cargo.lock @@ -1,19 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "adc_test" -version = "0.1.0" -dependencies = [ - "litex-pac", - "log", - "managed", - "panic-halt", - "riscv", - "riscv-rt", - "smoltcp", - "vexriscv", -] - [[package]] name = "addr2line" version = "0.13.0" @@ -493,6 +479,20 @@ dependencies = [ "unicode-xid 0.2.1", ] +[[package]] +name = "temp_controller" +version = "0.1.0" +dependencies = [ + "litex-pac", + "log", + "managed", + "panic-halt", + "riscv", + "riscv-rt", + "smoltcp", + "vexriscv", +] + [[package]] name = "termcolor" version = "1.1.0" diff --git a/rust/temp_controller/Cargo.toml b/rust/temp_controller/Cargo.toml index c61aa7b..f5ac603 100644 --- a/rust/temp_controller/Cargo.toml +++ b/rust/temp_controller/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "adc_test" +name = "temp_controller" version = "0.1.0" authors = ["Piotr Esden-Tempski ", "DerFetzer ", "SingularitySurfer"] edition = "2018" diff --git a/rust/temp_controller/rust-project.json b/rust/temp_controller/rust-project.json new file mode 100644 index 0000000..8bdd868 --- /dev/null +++ b/rust/temp_controller/rust-project.json @@ -0,0 +1,4 @@ +{ + "rust.target": "riscv32imac-unknown-none-elf", + "rust.all_targets": false +} diff --git a/rust/temp_controller/src/iir.rs b/rust/temp_controller/src/iir.rs new file mode 100644 index 0000000..663c0f3 --- /dev/null +++ b/rust/temp_controller/src/iir.rs @@ -0,0 +1,37 @@ + + +// Biquadratic (BiQuad) Infinite Impulse Response (IIR) Filter. + + +/// Generic vector for integer IIR filter. +/// This struct is used to hold the x/y input/output data vector or the b/a coefficient +/// vector. +pub type Vec5 = [i32; 5]; + + +/// Main IIR struct holds coefficient vector and a shift value which defines the fixed point position +pub struct Iir { + pub ba: Vec5, // b and a coeffitients can be changed. [a0,a1,b0,b1,b2] + pub shift: i32, // shift for fixed point pos + pub xy: Vec5, // x and y internal filter states [x0,x1,y0,y1,y2] +} + +impl Iir { + /// Filter tick. Takes a new inout sample and returns a new output sample. + pub fn tick(&mut self, x0: i32) -> i32 { + + // shift in x0 + self.xy.copy_within(0..4, 1); + self.xy[0] = x0; + + let y0 = 1 << ((self.shift as i64) - 1); + let y = &self.xy + .iter() + .zip(&self.ba) + .map(|(xi, ai)| *xi as i64 * *ai as i64) + .fold(y0, |y, xa| y + xa); + + self.xy[2] = (y >> self.shift) as i32; + self.xy[2] + } +} diff --git a/rust/temp_controller/src/main.rs b/rust/temp_controller/src/main.rs index 0908268..6f2e90b 100644 --- a/rust/temp_controller/src/main.rs +++ b/rust/temp_controller/src/main.rs @@ -17,6 +17,8 @@ mod leds; mod print; mod pwm; mod timer; +mod iir; + use crate::ethernet::Eth; use adc::Adc; @@ -25,6 +27,8 @@ use leds::{Leds, Leds2}; use pwm::Pwm; use timer::{Timer, Timer2}; +use iir::Iir; + use managed::ManagedSlice; use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache}; use smoltcp::socket::{ @@ -84,6 +88,12 @@ fn main() -> ! { let mut pwm = Pwm::new(peripherals.PWM); + let mut iir = Iir{ + ba : [1<<30,1<<30,1<<30,0,0], + shift : 30, + xy : [0,0,0,0,0], + }; + let clock = mock::Clock::new(); let device = Eth::new(peripherals.ETHMAC, peripherals.ETHMEM); @@ -144,10 +154,9 @@ fn main() -> ! { let tcp_server_handle = socket_set.add(tcp_server_socket); let udp_server_handle = socket_set.add(udp_server_socket); - timer2.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * 4000); - + timer2.load(0); + timer2.reload(SYSTEM_CLOCK_FREQUENCY / 1_000 * 500); timer2.enable(); - timer2.en_interrupt(); pwm.set_period(1 << 15); @@ -162,7 +171,8 @@ fn main() -> ! { info!("Main loop..."); loop { - info!("{}", timer2.value()); + let x = timer2.value(); + info!("x:{} y:{} ", x, iir.tick(x as i32)); leds.toggle_mask(0xf); } } @@ -190,21 +200,17 @@ pub fn isr_to_interrupt(isr: u8) -> Option { None } + +// Main signal processing routine. Triggered by Timer2. fn system_tick() { - let peripherals = unsafe { litex_pac::Peripherals::steal() }; // steal all but only use the safe ones ;) + let peripherals = unsafe { litex_pac::Peripherals::steal() }; // steal all but only use the safe ones ;) let mut timer2 = Timer2::new(peripherals.TIMER2); let mut leds2 = Leds2::new(peripherals.LEDS2); + // leds2.on(); leds2.toggle_mask(0xf); timer2.clr_interrupt(); - timer2.disable(); - - timer2.reload(0); - - timer2.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * 4000); - - timer2.enable(); } // fn msleep(timer: &mut Timer, leds : &mut Leds, ms: u32) { From 5828360ad746f56129dc2e674006a569d59a568e Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Sun, 2 May 2021 12:19:14 +0200 Subject: [PATCH 23/36] ADC -> RiscV IRQ with Biquad IIR -> DAC works :) Using unsafe static mutables bc Mutex is wierd and i dont understand. --- rust/litex-pac/clSOC.svd | 27 ++++++++++++++++++++++++ rust/temp_controller/src/dac.rs | 18 ++++++++++++++++ rust/temp_controller/src/main.rs | 36 ++++++++++++++++++++++++++++---- soc/colorlight_5a_75x.py | 20 ++++++++++++++++-- 4 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 rust/temp_controller/src/dac.rs diff --git a/rust/litex-pac/clSOC.svd b/rust/litex-pac/clSOC.svd index d9b6eb5..eef42a2 100644 --- a/rust/litex-pac/clSOC.svd +++ b/rust/litex-pac/clSOC.svd @@ -1379,6 +1379,33 @@ register to disable individual events.]]> registers + + DAC + 0xF0008000 + DAC + + + VAL + + 0x0000 + 0x00 + 32 + + + val + 15 + [15:0] + 0 + + + + + + 0 + 0x4 + registers + + ETHMEM 0x80000000 diff --git a/rust/temp_controller/src/dac.rs b/rust/temp_controller/src/dac.rs new file mode 100644 index 0000000..f900898 --- /dev/null +++ b/rust/temp_controller/src/dac.rs @@ -0,0 +1,18 @@ +use litex_pac::DAC; + +pub struct Dac { + registers: DAC, +} + +#[allow(dead_code)] +impl Dac { + pub fn new(registers: DAC) -> Self { + Self { registers } + } + + pub fn set(&mut self, value: u32) { + unsafe{ + self.registers.val.write(|w| w.bits(value)); + } + } +} diff --git a/rust/temp_controller/src/main.rs b/rust/temp_controller/src/main.rs index 6f2e90b..e5aeca3 100644 --- a/rust/temp_controller/src/main.rs +++ b/rust/temp_controller/src/main.rs @@ -10,6 +10,9 @@ use riscv_rt::entry; use riscv::register::{mcause, mie, mstatus}; use vexriscv::register::{vdci, vmim, vmip, vsim, vsip}; +use riscv::interrupt::{self, Mutex}; +use core::cell::Cell; + mod adc; mod ethernet; mod gpio; @@ -18,7 +21,7 @@ mod print; mod pwm; mod timer; mod iir; - +mod dac; use crate::ethernet::Eth; use adc::Adc; @@ -26,6 +29,7 @@ use gpio::Gpio; use leds::{Leds, Leds2}; use pwm::Pwm; use timer::{Timer, Timer2}; +use dac::Dac; use iir::Iir; @@ -42,6 +46,22 @@ use log::{debug, info, trace}; const SYSTEM_CLOCK_FREQUENCY: u32 = 49_600_000; + +// static IIR: Mutex> = Mutex::new(Cell::new(Iir{ +// ba : [1<<30,1<<30,1<<30,0,0], +// shift : 30, +// xy : [0,0,0,0,0], +// })); + +static mut IIR: Iir = Iir{ + ba : [1<<30,1<<30,1<<30,0,0], + shift : 30, + xy : [0,0,0,0,0], + }; + + + + mod mock { use core::cell::Cell; use smoltcp::time::{Duration, Instant}; @@ -88,6 +108,8 @@ fn main() -> ! { let mut pwm = Pwm::new(peripherals.PWM); + let mut dac = Dac::new(peripherals.DAC); + let mut iir = Iir{ ba : [1<<30,1<<30,1<<30,0,0], shift : 30, @@ -155,7 +177,7 @@ fn main() -> ! { let udp_server_handle = socket_set.add(udp_server_socket); timer2.load(0); - timer2.reload(SYSTEM_CLOCK_FREQUENCY / 1_000 * 500); + timer2.reload(SYSTEM_CLOCK_FREQUENCY / 1_000 * 1); timer2.enable(); timer2.en_interrupt(); @@ -171,8 +193,9 @@ fn main() -> ! { info!("Main loop..."); loop { - let x = timer2.value(); + let x = adc.read(); info!("x:{} y:{} ", x, iir.tick(x as i32)); + // dac.set(timer2.value() >> 12); leds.toggle_mask(0xf); } } @@ -203,11 +226,16 @@ pub fn isr_to_interrupt(isr: u8) -> Option { // Main signal processing routine. Triggered by Timer2. fn system_tick() { - let peripherals = unsafe { litex_pac::Peripherals::steal() }; // steal all but only use the safe ones ;) let mut timer2 = Timer2::new(peripherals.TIMER2); let mut leds2 = Leds2::new(peripherals.LEDS2); + let mut dac = Dac::new(peripherals.DAC); + let mut adc = Adc::new(peripherals.ADC); + // interrupt::free(|cs| let y = IIR.borrow(cs).get_mut().tick(timer2.value())); + unsafe {let y = IIR.tick(adc.read() as i32); + dac.set(y as u32 >> 16); + } // leds2.on(); leds2.toggle_mask(0xf); timer2.clr_interrupt(); diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index ac8d85a..c6e8828 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -155,6 +155,18 @@ def __init__(self, platform, sys_clk_freq, use_internal_osc=False, with_usb_pll= self.specials += DDROutput(1, 0, platform.request("sdram_clock"), sdram_clk) +class DAC(Module, AutoCSR): + """Basic first order sigma-delta DAC running at sys clock""" + def __init__(self, pin, bits): + self.val = CSRStorage(bits, description='dac output value') + accu = Signal(bits+1) + self.sync += [ + accu.eq(accu[:-1] + self.val.storage), # clever form of integrator with feedback + pin.eq(accu[-1]) + ] + + + # BaseSoC ------------------------------------------------------------------------------------------ class BaseSoC(SoCCore): @@ -282,6 +294,7 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi platform.add_extension(_leds) platform.add_extension(_pwm) platform.add_extension(_adc_second_order) + platform.add_extension(_dac) # LEDs blinkyblinky :) @@ -326,14 +339,14 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi adc_sd = platform.request("sd", 0) adc_sd2 = platform.request("sd", 1) #p5v = platform.request("p5v") - #p3v = platform.request("p3v") + p3v = platform.request("p3v") self.comb += [ adc.inp.eq(adc_in), adc_sd.eq(adc.sd), adc_sd2.eq(adc.sd), #p5v.eq(1), - #p3v.eq(1), + p3v.eq(1), ] self.add_csr("adc") @@ -349,6 +362,9 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi self.submodules.pwm = PWM(platform.request("pwm"), width=32) self.add_csr("pwm") + self.submodules.dac = DAC(platform.request("dac", 1), bits=16) + self.add_csr("dac") + From d54319288bd159717b92871a2900946c0b9ad6b1 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Sun, 2 May 2021 13:20:59 +0200 Subject: [PATCH 24/36] higher sample rate and led timing --- rust/temp_controller/src/main.rs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/rust/temp_controller/src/main.rs b/rust/temp_controller/src/main.rs index e5aeca3..f8dc173 100644 --- a/rust/temp_controller/src/main.rs +++ b/rust/temp_controller/src/main.rs @@ -44,7 +44,7 @@ use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; use crate::print::UartLogger; use log::{debug, info, trace}; -const SYSTEM_CLOCK_FREQUENCY: u32 = 49_600_000; +const SYSTEM_CLOCK_FREQUENCY: u32 = 60_000_000; // static IIR: Mutex> = Mutex::new(Cell::new(Iir{ @@ -110,12 +110,6 @@ fn main() -> ! { let mut dac = Dac::new(peripherals.DAC); - let mut iir = Iir{ - ba : [1<<30,1<<30,1<<30,0,0], - shift : 30, - xy : [0,0,0,0,0], - }; - let clock = mock::Clock::new(); let device = Eth::new(peripherals.ETHMAC, peripherals.ETHMEM); @@ -177,7 +171,7 @@ fn main() -> ! { let udp_server_handle = socket_set.add(udp_server_socket); timer2.load(0); - timer2.reload(SYSTEM_CLOCK_FREQUENCY / 1_000 * 1); + timer2.reload(SYSTEM_CLOCK_FREQUENCY / 100_000); timer2.enable(); timer2.en_interrupt(); @@ -193,9 +187,6 @@ fn main() -> ! { info!("Main loop..."); loop { - let x = adc.read(); - info!("x:{} y:{} ", x, iir.tick(x as i32)); - // dac.set(timer2.value() >> 12); leds.toggle_mask(0xf); } } @@ -231,13 +222,13 @@ fn system_tick() { let mut leds2 = Leds2::new(peripherals.LEDS2); let mut dac = Dac::new(peripherals.DAC); let mut adc = Adc::new(peripherals.ADC); - + leds2.on(); // interrupt::free(|cs| let y = IIR.borrow(cs).get_mut().tick(timer2.value())); unsafe {let y = IIR.tick(adc.read() as i32); dac.set(y as u32 >> 16); } // leds2.on(); - leds2.toggle_mask(0xf); + leds2.off(); timer2.clr_interrupt(); } From 15ef3d7bc85f321e4c4c1f1c300af2c34da33a39 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Mon, 3 May 2021 07:59:11 +0200 Subject: [PATCH 25/36] Yay, tamed that computer into linearity, at least somewhat.. --- rust/temp_controller/src/iir.rs | 6 ++-- rust/temp_controller/src/main.rs | 61 +++++++++++++++++++++----------- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/rust/temp_controller/src/iir.rs b/rust/temp_controller/src/iir.rs index 663c0f3..d0ef881 100644 --- a/rust/temp_controller/src/iir.rs +++ b/rust/temp_controller/src/iir.rs @@ -11,9 +11,9 @@ pub type Vec5 = [i32; 5]; /// Main IIR struct holds coefficient vector and a shift value which defines the fixed point position pub struct Iir { - pub ba: Vec5, // b and a coeffitients can be changed. [a0,a1,b0,b1,b2] + pub ba: Vec5, // b and a coeffitients can be changed. [b0,b1,b2,a1,a2] pub shift: i32, // shift for fixed point pos - pub xy: Vec5, // x and y internal filter states [x0,x1,y0,y1,y2] + pub xy: Vec5, // x and y internal filter states [x0,x1,y0,y1,y2] } impl Iir { @@ -24,7 +24,7 @@ impl Iir { self.xy.copy_within(0..4, 1); self.xy[0] = x0; - let y0 = 1 << ((self.shift as i64) - 1); + let y0 = 1 << ((self.shift) - 1); let y = &self.xy .iter() .zip(&self.ba) diff --git a/rust/temp_controller/src/main.rs b/rust/temp_controller/src/main.rs index f8dc173..85e3ee3 100644 --- a/rust/temp_controller/src/main.rs +++ b/rust/temp_controller/src/main.rs @@ -53,9 +53,19 @@ const SYSTEM_CLOCK_FREQUENCY: u32 = 60_000_000; // xy : [0,0,0,0,0], // })); -static mut IIR: Iir = Iir{ - ba : [1<<30,1<<30,1<<30,0,0], - shift : 30, +static mut iir: Iir = Iir{ + // ba : [12190614,-15880203,12190614,138662614,943580235], + // shift : 31, + // ba : [10926271,-19764559,10926271,67672592,1008157215], + // shift : 31, + // ba : [283852882,-553640919,283852882,142568885,190173743], + // shift : 31, + ba : [138600,-270332,138600,69614,92858], + shift : 20, + // ba : [10691554,-21298801,10691554,13430401,1060395729], + // shift : 31, + // ba: [1<<10,1<<10,1<<10,1<<10,1<<10], + // shift : 12, xy : [0,0,0,0,0], }; @@ -171,7 +181,7 @@ fn main() -> ! { let udp_server_handle = socket_set.add(udp_server_socket); timer2.load(0); - timer2.reload(SYSTEM_CLOCK_FREQUENCY / 100_000); + timer2.reload(SYSTEM_CLOCK_FREQUENCY / 10_000); timer2.enable(); timer2.en_interrupt(); @@ -186,7 +196,17 @@ fn main() -> ! { info!("Main loop..."); + let mut x = -(1<<25); + loop { + // unsafe {let y = iir.tick(x as i32); + // dac.set(y as u32 >> 16); + // // info!("ba: {:?}", adc.read() as i32); + // info!("ba: {:?}", iir.ba); + // info!("xy: {:?}", iir.xy); + // } + // x += 1000000; + msleep(&mut timer, 1000 as u32); leds.toggle_mask(0xf); } } @@ -223,25 +243,24 @@ fn system_tick() { let mut dac = Dac::new(peripherals.DAC); let mut adc = Adc::new(peripherals.ADC); leds2.on(); - // interrupt::free(|cs| let y = IIR.borrow(cs).get_mut().tick(timer2.value())); - unsafe {let y = IIR.tick(adc.read() as i32); - dac.set(y as u32 >> 16); + unsafe {let y = iir.tick(adc.read() as i32); + dac.set((y as u32 >> 13)+(1<<15)); + // dac.set(adc.read() as u32 >> 15 ); } - // leds2.on(); leds2.off(); timer2.clr_interrupt(); } -// fn msleep(timer: &mut Timer, leds : &mut Leds, ms: u32) { -// timer.disable(); -// -// timer.reload(0); -// timer.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * ms); -// -// timer.enable(); -// -// // Wait until the time has elapsed -// while timer.value() > 0 { -// } -// timer.disable(); -// } +fn msleep(timer: &mut Timer, ms: u32) { + timer.disable(); + + timer.reload(0); + timer.load(SYSTEM_CLOCK_FREQUENCY / 1_000 * ms); + + timer.enable(); + + // Wait until the time has elapsed + while timer.value() > 0 { + } + timer.disable(); +} From 5e76904af2d2c4985bd9cd6f859b1923fc757fb5 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Mon, 3 May 2021 08:01:55 +0200 Subject: [PATCH 26/36] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6eb5f0c..9de94e5 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Working so far: - Ethernet with smoltcp thanks to https://github.com/DerFetzer/colorlight-litex - Interrupts by staring a lot at https://github.com/betrusted-io/xous-core - A simple second order sigma-delta ADC using a CIC decimator +- An IIR filter using on-chip sigma-delta ADC/DAC ## Credits From db09340371f00379e41d75679e4b7b169b5608e1 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Mon, 3 May 2021 08:03:06 +0200 Subject: [PATCH 27/36] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6eb5f0c..9de94e5 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Working so far: - Ethernet with smoltcp thanks to https://github.com/DerFetzer/colorlight-litex - Interrupts by staring a lot at https://github.com/betrusted-io/xous-core - A simple second order sigma-delta ADC using a CIC decimator +- An IIR filter using on-chip sigma-delta ADC/DAC ## Credits From 33065403c8c3d02e591ce05f8f8dc1d9edb999ec Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Mon, 3 May 2021 14:23:11 +0200 Subject: [PATCH 28/36] ratiometric ADC working :) --- rust/temp_controller/src/main.rs | 23 ++++++++++++----------- soc/adc.py | 19 +++++++++++++++---- soc/colorlight_5a_75x.py | 24 +++++++++++++++++++++--- 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/rust/temp_controller/src/main.rs b/rust/temp_controller/src/main.rs index 85e3ee3..04b8086 100644 --- a/rust/temp_controller/src/main.rs +++ b/rust/temp_controller/src/main.rs @@ -199,13 +199,14 @@ fn main() -> ! { let mut x = -(1<<25); loop { - // unsafe {let y = iir.tick(x as i32); - // dac.set(y as u32 >> 16); - // // info!("ba: {:?}", adc.read() as i32); - // info!("ba: {:?}", iir.ba); - // info!("xy: {:?}", iir.xy); - // } - // x += 1000000; + unsafe { + // let y = iir.tick(x as i32); + dac.set((1<<17)-1); + info!("adc: {:?}", adc.read() as u32); + // info!("ba: {:?}", iir.ba); + // info!("xy: {:?}", iir.xy); + } + x += 1000000; msleep(&mut timer, 1000 as u32); leds.toggle_mask(0xf); } @@ -243,10 +244,10 @@ fn system_tick() { let mut dac = Dac::new(peripherals.DAC); let mut adc = Adc::new(peripherals.ADC); leds2.on(); - unsafe {let y = iir.tick(adc.read() as i32); - dac.set((y as u32 >> 13)+(1<<15)); - // dac.set(adc.read() as u32 >> 15 ); - } + // unsafe {let y = iir.tick(adc.read() as i32); + // dac.set((y as u32 >> 13)+(1<<15)); + // dac.set(adc.read() as u32 >> 15 ); + // } leds2.off(); timer2.clr_interrupt(); } diff --git a/soc/adc.py b/soc/adc.py index 383dcdd..5bd2906 100644 --- a/soc/adc.py +++ b/soc/adc.py @@ -12,7 +12,7 @@ class ADC(Module, AutoCSR): """Basic sigma-delta ADC with a CIC decimator running at sys clock. The decimator gain is such that the output bitwidth will always be maximized. """ - def __init__(self, cic_order=6, cic_ratechange=2**7, width_o=32): + def __init__(self, cic_order=6, cic_ratechange=2**7, width_o=32, clk_div=4): self.inp = Signal() # analog in self.sd = Signal() # sigma-delta switching pin self.dout = Signal(width_o) @@ -26,11 +26,22 @@ def __init__(self, cic_order=6, cic_ratechange=2**7, width_o=32): if not(cic_ratechange & (cic_ratechange-1) == 0) and not cic_ratechange != 0: raise ValueError() # not a power of two + + if clk_div != 0: + divcnt = Signal(clk_div) + self.sync += divcnt.eq(divcnt+1) + b_max = np.ceil(np.log2(cic_ratechange)) # max bit growth - self.sync += [ # do the sigma-delta - self.sd.eq(self.inp) - ] + if clk_div != 0: + self.sync += [ + If(reduce(and_, divcnt), # do the sigma-delta + self.sd.eq(self.inp)) + ] + else: + self.sync += [ # do the sigma-delta + self.sd.eq(self.inp) + ] width = (int(b_max)*cic_order)+1 sig = Signal((width, True), reset_less=True) diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index c6e8828..ce7a4a9 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -72,8 +72,19 @@ def load_bitstream(self, bitstream_file): ("dac", 1, Pins("j4:1"), IOStandard("LVCMOS33")), # sigma-delta dac output ] +_peltier_driver = [ + ("pd", 0, Pins("j3:0"), IOStandard("LVCMOS33")), + ("pd", 1, Pins("j3:1"), IOStandard("LVCMOS33")), + ("pd", 2, Pins("j3:2"), IOStandard("LVCMOS33")), + ("pd", 3, Pins("j3:4"), IOStandard("LVCMOS33")), + ("pd", 4, Pins("j2:2"), IOStandard("LVCMOS33")), + ("pd", 5, Pins("j2:4"), IOStandard("LVCMOS33")), + ("pd", 6, Pins("j2:5"), IOStandard("LVCMOS33")), + ("pd", 7, Pins("j2:6"), IOStandard("LVCMOS33")), +] + _pwm = [ - ("pwm", 0, Pins("j3:0"), IOStandard("LVCMOS33")), + ("pwm", 0, Pins("j2:0"), IOStandard("LVCMOS33")), ] _leds = [ @@ -159,6 +170,7 @@ class DAC(Module, AutoCSR): """Basic first order sigma-delta DAC running at sys clock""" def __init__(self, pin, bits): self.val = CSRStorage(bits, description='dac output value') + self.pin = pin accu = Signal(bits+1) self.sync += [ accu.eq(accu[:-1] + self.val.storage), # clever form of integrator with feedback @@ -295,6 +307,7 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi platform.add_extension(_pwm) platform.add_extension(_adc_second_order) platform.add_extension(_dac) + platform.add_extension(_peltier_driver) # LEDs blinkyblinky :) @@ -333,7 +346,7 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi # sigma delta ADC using lame CSR for now - self.submodules.adc = adc = ADC() + self.submodules.adc = adc = ADC(cic_order=5, cic_ratechange=2**22) adc_in = platform.request("in") adc_sd = platform.request("sd", 0) @@ -362,9 +375,14 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi self.submodules.pwm = PWM(platform.request("pwm"), width=32) self.add_csr("pwm") - self.submodules.dac = DAC(platform.request("dac", 1), bits=16) + self.submodules.dac = dac = DAC(platform.request("dac", 1), bits=16) self.add_csr("dac") + # using line drivers in parallel as peltier driver + self.comb += [ + Cat([platform.request("pd", i) for i in range(8)]).eq(Cat([dac.pin for i in range(8)])) + ] + From a3470de0ca36b98eee87e4070a7d13ed58e5f133 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Tue, 4 May 2021 21:53:45 +0200 Subject: [PATCH 29/36] hmm so many thngs... Temperature control loop with ethernet tele somewhat working.. --- python/recieve.py | 44 ++++++++++- python/recieve_test.py | 9 +++ rust/temp_controller/src/main.rs | 131 ++++++++++++++++++++++++++----- soc/adc.py | 2 +- soc/colorlight_5a_75x.py | 2 +- 5 files changed, 164 insertions(+), 24 deletions(-) create mode 100755 python/recieve_test.py diff --git a/python/recieve.py b/python/recieve.py index b05faa9..6d4b7a9 100755 --- a/python/recieve.py +++ b/python/recieve.py @@ -1,8 +1,48 @@ import socket +import matplotlib.pyplot as plt +import matplotlib.animation as animation +import datetime as dt s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('192.168.1.50', 1234)) -msg = s.recv(1024) +msg = s.recv(4) +s.close() +val = int.from_bytes(msg, byteorder='big', signed=False) +print([x for x in msg]) +print(val) -print([x for x in msg]) \ No newline at end of file +fig = plt.figure() +ax = fig.add_subplot(1, 1, 1) +xs = [] +ys = [] + + + +def animate(i, xs, ys): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect(('192.168.1.50', 1234)) + msg = s.recv(4) + s.close() + val = int.from_bytes(msg, byteorder='big', signed=False) + print([x for x in msg]) + print(val) + xs.append(dt.datetime.now().strftime('%H:%M:%S.%f')) + ys.append(val) + # Limit x and y lists to 100 items + xs = xs[-200:] + ys = ys[-200:] + + # Draw x and y lists + ax.clear() + ax.plot(xs, ys) + + # Format plot + plt.xticks(rotation=45, ha='right') + plt.subplots_adjust(bottom=0.30) + plt.title('SoCstream') + plt.ylabel('Temperature') + +# Set up plot to call animate() function periodically +ani = animation.FuncAnimation(fig, animate, fargs=(xs, ys), interval=500) +plt.show() \ No newline at end of file diff --git a/python/recieve_test.py b/python/recieve_test.py new file mode 100755 index 0000000..1ad4c1c --- /dev/null +++ b/python/recieve_test.py @@ -0,0 +1,9 @@ + +import socket + +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.connect(('192.168.1.50', 1234)) + +msg = s.recv(1024) + +print([x for x in msg]) \ No newline at end of file diff --git a/rust/temp_controller/src/main.rs b/rust/temp_controller/src/main.rs index 04b8086..441251a 100644 --- a/rust/temp_controller/src/main.rs +++ b/rust/temp_controller/src/main.rs @@ -53,19 +53,28 @@ const SYSTEM_CLOCK_FREQUENCY: u32 = 60_000_000; // xy : [0,0,0,0,0], // })); +static mut set_temp: i32 = 700_000_000; +static mut err: i32 = 0; +static mut drive: u32 = 0; + static mut iir: Iir = Iir{ - // ba : [12190614,-15880203,12190614,138662614,943580235], + // ba : [12190614,-15880203,12190614,138662614,943580235], // lowpass // shift : 31, + // ba : [10926271,-19764559,10926271,67672592,1008157215], // shift : 31, // ba : [283852882,-553640919,283852882,142568885,190173743], // shift : 31, - ba : [138600,-270332,138600,69614,92858], - shift : 20, + + // ba : [138600,-270332,138600,69614,92858], // highpass + // shift : 20, + // ba : [10691554,-21298801,10691554,13430401,1060395729], // shift : 31, - // ba: [1<<10,1<<10,1<<10,1<<10,1<<10], + // ba: [1<<12,0,0,0,0], // shift : 12, + ba: [736909014,736184239,0,-1072668083,0], // maybe PI controller? + shift : 31, xy : [0,0,0,0,0], }; @@ -94,6 +103,8 @@ mod mock { } } + + // This is the entry point for the application. // It is not allowed to return. #[entry] @@ -181,7 +192,7 @@ fn main() -> ! { let udp_server_handle = socket_set.add(udp_server_socket); timer2.load(0); - timer2.reload(SYSTEM_CLOCK_FREQUENCY / 10_000); + timer2.reload(SYSTEM_CLOCK_FREQUENCY / 5); timer2.enable(); timer2.en_interrupt(); @@ -196,19 +207,74 @@ fn main() -> ! { info!("Main loop..."); - let mut x = -(1<<25); + loop { - unsafe { - // let y = iir.tick(x as i32); - dac.set((1<<17)-1); - info!("adc: {:?}", adc.read() as u32); - // info!("ba: {:?}", iir.ba); - // info!("xy: {:?}", iir.xy); + match iface.poll(&mut socket_set, clock.elapsed()) { + Ok(_) => {} + Err(e) => { + debug!("Poll error: {}", e); + } + } + + { + let mut socket = socket_set.get::(tcp_server_handle); + + if !socket.is_active() && !socket.is_listening() { + info!("Start listen..."); + socket.listen(1234).unwrap(); + } + + if socket.can_send() { + // info!("Can send..."); + unsafe{ + info!("adc:\t{:?}", adc.read() as u32); + info!("error:\t{:?}", err as i32); + info!("drive:\t{:?}", drive as i32); + } + // socket.send_slice(b"Hello World!\r\n").unwrap(); + let adcval: u32 = adc.read(); + socket.send_slice(&adcval.to_be_bytes()).unwrap(); + } + } + + { + let mut socket = socket_set.get::(udp_server_handle); + if !socket.is_open() { + socket.bind(5678).unwrap() + } + + match socket.recv() { + Ok((data, endpoint)) => { + + let data4 = [data[0]-48,data[1]-48,data[2]-48,data[3]-48]; + let val = as_u32_be(&data4); + unsafe{ set_temp = val as i32;} + info!("udp:5678 data/value received: {:?}/{} from {}", data, val,endpoint); + } + Err(_) => debug!("Err"), + }; } - x += 1000000; - msleep(&mut timer, 1000 as u32); - leds.toggle_mask(0xf); + + match iface.poll_delay(&socket_set, clock.elapsed()) { + Some(Duration { millis: 0 }) => {} + Some(delay) => { + trace!("sleeping for {} ms", delay); + msleep(&mut timer, delay.total_millis() as u32); + clock.advance(delay) + } + None => clock.advance(Duration::from_millis(1)), + } + trace!("Clock elapsed: {}", clock.elapsed()); + // unsafe { + // // let y = iir.tick(x as i32); + // // dac.set((1<<17)-1); + // info!("adc: {:?}", adc.read() as u32); + // // info!("ba: {:?}", iir.ba); + // // info!("xy: {:?}", iir.xy); + // } + // msleep(&mut timer, 1000 as u32); + // leds.toggle_mask(0xf); } } @@ -221,7 +287,7 @@ fn MachineExternal() { if irqs_pending & (1 << irq_no) != 0 { match isr_to_interrupt(irq_no) { Some(1) => system_tick(), - _ => {} //unsafe{vmim::write(vmim::read() ^ (1< unsafe{vmim::write(vmim::read() ^ (1<> 13)+(1<<15)); - // dac.set(adc.read() as u32 >> 15 ); - // } + unsafe { + err = set_temp - (adc.read() as i32); + let y = iir.tick(err); + if y < 0{ + drive = 0; + } else { + drive = (y as u32 >> 9); + } + // drive = (y as u32 >> 15); + if drive > (1<<16) { + drive = (1 << 16) - 1; + } + dac.set(drive); + // dac.set(adc.read() as u32 >> 15 ); + } leds2.off(); timer2.clr_interrupt(); } @@ -265,3 +342,17 @@ fn msleep(timer: &mut Timer, ms: u32) { } timer.disable(); } + +fn as_u32_be(array: &[u8; 4]) -> u32 { + ((array[0] as u32) << 24) + + ((array[1] as u32) << 16) + + ((array[2] as u32) << 8) + + ((array[3] as u32) << 0) +} + +fn as_u32_le(array: &[u8; 4]) -> u32 { + ((array[0] as u32) << 0) + + ((array[1] as u32) << 8) + + ((array[2] as u32) << 16) + + ((array[3] as u32) << 24) +} diff --git a/soc/adc.py b/soc/adc.py index 5bd2906..4026930 100644 --- a/soc/adc.py +++ b/soc/adc.py @@ -12,7 +12,7 @@ class ADC(Module, AutoCSR): """Basic sigma-delta ADC with a CIC decimator running at sys clock. The decimator gain is such that the output bitwidth will always be maximized. """ - def __init__(self, cic_order=6, cic_ratechange=2**7, width_o=32, clk_div=4): + def __init__(self, cic_order=6, cic_ratechange=2**7, width_o=32, clk_div=0): self.inp = Signal() # analog in self.sd = Signal() # sigma-delta switching pin self.dout = Signal(width_o) diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index ce7a4a9..23c1b4f 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -346,7 +346,7 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi # sigma delta ADC using lame CSR for now - self.submodules.adc = adc = ADC(cic_order=5, cic_ratechange=2**22) + self.submodules.adc = adc = ADC(cic_order=5, cic_ratechange=2**25, clk_div=4) adc_in = platform.request("in") adc_sd = platform.request("sd", 0) From 032b1e44c98c3d82480f7ec1fd55df19950eb886 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Sat, 15 May 2021 16:21:17 +0200 Subject: [PATCH 30/36] pre-cleanup --- .../.cargo/config | 0 .../.cargo/flash.sh | 0 rust/{temp_controller => SoC_demo}/Cargo.lock | 0 rust/{temp_controller => SoC_demo}/Cargo.toml | 0 rust/{temp_controller => SoC_demo}/README.md | 0 .../rust-project.json | 0 rust/{temp_controller => SoC_demo}/src/adc.rs | 0 rust/{temp_controller => SoC_demo}/src/dac.rs | 0 .../src/ethernet.rs | 0 .../{temp_controller => SoC_demo}/src/gpio.rs | 0 rust/{temp_controller => SoC_demo}/src/iir.rs | 0 .../{temp_controller => SoC_demo}/src/leds.rs | 0 .../{temp_controller => SoC_demo}/src/main.rs | 93 ++----------------- .../src/print.rs | 0 rust/{temp_controller => SoC_demo}/src/pwm.rs | 0 .../src/timer.rs | 0 16 files changed, 8 insertions(+), 85 deletions(-) rename rust/{temp_controller => SoC_demo}/.cargo/config (100%) rename rust/{temp_controller => SoC_demo}/.cargo/flash.sh (100%) rename rust/{temp_controller => SoC_demo}/Cargo.lock (100%) rename rust/{temp_controller => SoC_demo}/Cargo.toml (100%) rename rust/{temp_controller => SoC_demo}/README.md (100%) rename rust/{temp_controller => SoC_demo}/rust-project.json (100%) rename rust/{temp_controller => SoC_demo}/src/adc.rs (100%) rename rust/{temp_controller => SoC_demo}/src/dac.rs (100%) rename rust/{temp_controller => SoC_demo}/src/ethernet.rs (100%) rename rust/{temp_controller => SoC_demo}/src/gpio.rs (100%) rename rust/{temp_controller => SoC_demo}/src/iir.rs (100%) rename rust/{temp_controller => SoC_demo}/src/leds.rs (100%) rename rust/{temp_controller => SoC_demo}/src/main.rs (74%) rename rust/{temp_controller => SoC_demo}/src/print.rs (100%) rename rust/{temp_controller => SoC_demo}/src/pwm.rs (100%) rename rust/{temp_controller => SoC_demo}/src/timer.rs (100%) diff --git a/rust/temp_controller/.cargo/config b/rust/SoC_demo/.cargo/config similarity index 100% rename from rust/temp_controller/.cargo/config rename to rust/SoC_demo/.cargo/config diff --git a/rust/temp_controller/.cargo/flash.sh b/rust/SoC_demo/.cargo/flash.sh similarity index 100% rename from rust/temp_controller/.cargo/flash.sh rename to rust/SoC_demo/.cargo/flash.sh diff --git a/rust/temp_controller/Cargo.lock b/rust/SoC_demo/Cargo.lock similarity index 100% rename from rust/temp_controller/Cargo.lock rename to rust/SoC_demo/Cargo.lock diff --git a/rust/temp_controller/Cargo.toml b/rust/SoC_demo/Cargo.toml similarity index 100% rename from rust/temp_controller/Cargo.toml rename to rust/SoC_demo/Cargo.toml diff --git a/rust/temp_controller/README.md b/rust/SoC_demo/README.md similarity index 100% rename from rust/temp_controller/README.md rename to rust/SoC_demo/README.md diff --git a/rust/temp_controller/rust-project.json b/rust/SoC_demo/rust-project.json similarity index 100% rename from rust/temp_controller/rust-project.json rename to rust/SoC_demo/rust-project.json diff --git a/rust/temp_controller/src/adc.rs b/rust/SoC_demo/src/adc.rs similarity index 100% rename from rust/temp_controller/src/adc.rs rename to rust/SoC_demo/src/adc.rs diff --git a/rust/temp_controller/src/dac.rs b/rust/SoC_demo/src/dac.rs similarity index 100% rename from rust/temp_controller/src/dac.rs rename to rust/SoC_demo/src/dac.rs diff --git a/rust/temp_controller/src/ethernet.rs b/rust/SoC_demo/src/ethernet.rs similarity index 100% rename from rust/temp_controller/src/ethernet.rs rename to rust/SoC_demo/src/ethernet.rs diff --git a/rust/temp_controller/src/gpio.rs b/rust/SoC_demo/src/gpio.rs similarity index 100% rename from rust/temp_controller/src/gpio.rs rename to rust/SoC_demo/src/gpio.rs diff --git a/rust/temp_controller/src/iir.rs b/rust/SoC_demo/src/iir.rs similarity index 100% rename from rust/temp_controller/src/iir.rs rename to rust/SoC_demo/src/iir.rs diff --git a/rust/temp_controller/src/leds.rs b/rust/SoC_demo/src/leds.rs similarity index 100% rename from rust/temp_controller/src/leds.rs rename to rust/SoC_demo/src/leds.rs diff --git a/rust/temp_controller/src/main.rs b/rust/SoC_demo/src/main.rs similarity index 74% rename from rust/temp_controller/src/main.rs rename to rust/SoC_demo/src/main.rs index 441251a..d1de09b 100644 --- a/rust/temp_controller/src/main.rs +++ b/rust/SoC_demo/src/main.rs @@ -10,28 +10,22 @@ use riscv_rt::entry; use riscv::register::{mcause, mie, mstatus}; use vexriscv::register::{vdci, vmim, vmip, vsim, vsip}; -use riscv::interrupt::{self, Mutex}; +use riscv::interrupt::{self}; use core::cell::Cell; -mod adc; mod ethernet; mod gpio; mod leds; mod print; mod pwm; mod timer; -mod iir; -mod dac; use crate::ethernet::Eth; -use adc::Adc; use gpio::Gpio; use leds::{Leds, Leds2}; use pwm::Pwm; use timer::{Timer, Timer2}; -use dac::Dac; -use iir::Iir; use managed::ManagedSlice; use smoltcp::iface::{EthernetInterfaceBuilder, NeighborCache}; @@ -47,39 +41,6 @@ use log::{debug, info, trace}; const SYSTEM_CLOCK_FREQUENCY: u32 = 60_000_000; -// static IIR: Mutex> = Mutex::new(Cell::new(Iir{ -// ba : [1<<30,1<<30,1<<30,0,0], -// shift : 30, -// xy : [0,0,0,0,0], -// })); - -static mut set_temp: i32 = 700_000_000; -static mut err: i32 = 0; -static mut drive: u32 = 0; - -static mut iir: Iir = Iir{ - // ba : [12190614,-15880203,12190614,138662614,943580235], // lowpass - // shift : 31, - - // ba : [10926271,-19764559,10926271,67672592,1008157215], - // shift : 31, - // ba : [283852882,-553640919,283852882,142568885,190173743], - // shift : 31, - - // ba : [138600,-270332,138600,69614,92858], // highpass - // shift : 20, - - // ba : [10691554,-21298801,10691554,13430401,1060395729], - // shift : 31, - // ba: [1<<12,0,0,0,0], - // shift : 12, - ba: [736909014,736184239,0,-1072668083,0], // maybe PI controller? - shift : 31, - xy : [0,0,0,0,0], - }; - - - mod mock { use core::cell::Cell; @@ -123,14 +84,10 @@ fn main() -> ! { let mut leds = Leds::new(peripherals.LEDS); let mut leds2 = Leds2::new(peripherals.LEDS2); - let mut adc = Adc::new(peripherals.ADC); - let mut gpio = Gpio::new(peripherals.GPIO); let mut pwm = Pwm::new(peripherals.PWM); - let mut dac = Dac::new(peripherals.DAC); - let clock = mock::Clock::new(); let device = Eth::new(peripherals.ETHMAC, peripherals.ETHMEM); @@ -228,13 +185,9 @@ fn main() -> ! { if socket.can_send() { // info!("Can send..."); unsafe{ - info!("adc:\t{:?}", adc.read() as u32); - info!("error:\t{:?}", err as i32); - info!("drive:\t{:?}", drive as i32); + socket.send_slice(b"Hello World!\r\n").unwrap(); + info!("Hello World"); } - // socket.send_slice(b"Hello World!\r\n").unwrap(); - let adcval: u32 = adc.read(); - socket.send_slice(&adcval.to_be_bytes()).unwrap(); } } @@ -246,11 +199,7 @@ fn main() -> ! { match socket.recv() { Ok((data, endpoint)) => { - - let data4 = [data[0]-48,data[1]-48,data[2]-48,data[3]-48]; - let val = as_u32_be(&data4); - unsafe{ set_temp = val as i32;} - info!("udp:5678 data/value received: {:?}/{} from {}", data, val,endpoint); + info!("Hello World"); } Err(_) => debug!("Err"), }; @@ -266,15 +215,6 @@ fn main() -> ! { None => clock.advance(Duration::from_millis(1)), } trace!("Clock elapsed: {}", clock.elapsed()); - // unsafe { - // // let y = iir.tick(x as i32); - // // dac.set((1<<17)-1); - // info!("adc: {:?}", adc.read() as u32); - // // info!("ba: {:?}", iir.ba); - // // info!("xy: {:?}", iir.xy); - // } - // msleep(&mut timer, 1000 as u32); - // leds.toggle_mask(0xf); } } @@ -286,7 +226,7 @@ fn MachineExternal() { for irq_no in 0..32 { if irqs_pending & (1 << irq_no) != 0 { match isr_to_interrupt(irq_no) { - Some(1) => system_tick(), + Some(0) => system_tick(), _ => unsafe{vmim::write(vmim::read() ^ (1< Option { - if isr == (litex_pac::Interrupt::TIMER2 as u8) { - return Some(1); - } + if isr == (litex_pac::Interrupt::TIMER2 as u8) {return Some(0)} + if isr == (litex_pac::Interrupt::GPIO as u8) {return Some(1)} None } @@ -307,24 +246,8 @@ fn system_tick() { let peripherals = unsafe { litex_pac::Peripherals::steal() }; // steal all but only use the safe ones ;) let mut timer2 = Timer2::new(peripherals.TIMER2); let mut leds2 = Leds2::new(peripherals.LEDS2); - let mut dac = Dac::new(peripherals.DAC); - let mut adc = Adc::new(peripherals.ADC); leds2.on(); - unsafe { - err = set_temp - (adc.read() as i32); - let y = iir.tick(err); - if y < 0{ - drive = 0; - } else { - drive = (y as u32 >> 9); - } - // drive = (y as u32 >> 15); - if drive > (1<<16) { - drive = (1 << 16) - 1; - } - dac.set(drive); - // dac.set(adc.read() as u32 >> 15 ); - } + leds2.off(); timer2.clr_interrupt(); } diff --git a/rust/temp_controller/src/print.rs b/rust/SoC_demo/src/print.rs similarity index 100% rename from rust/temp_controller/src/print.rs rename to rust/SoC_demo/src/print.rs diff --git a/rust/temp_controller/src/pwm.rs b/rust/SoC_demo/src/pwm.rs similarity index 100% rename from rust/temp_controller/src/pwm.rs rename to rust/SoC_demo/src/pwm.rs diff --git a/rust/temp_controller/src/timer.rs b/rust/SoC_demo/src/timer.rs similarity index 100% rename from rust/temp_controller/src/timer.rs rename to rust/SoC_demo/src/timer.rs From 56042a77ee312dcbad614ae90355c4233418c3fd Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Sat, 15 May 2021 18:48:39 +0200 Subject: [PATCH 31/36] HORRAYY computer likes when I say hi via TCP :) --- rust/SoC_demo/src/main.rs | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/rust/SoC_demo/src/main.rs b/rust/SoC_demo/src/main.rs index d1de09b..a86105c 100644 --- a/rust/SoC_demo/src/main.rs +++ b/rust/SoC_demo/src/main.rs @@ -103,6 +103,8 @@ fn main() -> ! { .ip_addrs(ip_addrs) .finalize(); + let mut data = [0;128]; + let tcp_server_socket = { // It is not strictly necessary to use a `static mut` and unsafe code here, but // on embedded systems that smoltcp targets it is far better to allocate the data @@ -176,19 +178,36 @@ fn main() -> ! { { let mut socket = socket_set.get::(tcp_server_handle); + let mut yay = false; if !socket.is_active() && !socket.is_listening() { info!("Start listen..."); socket.listen(1234).unwrap(); } + else if socket.can_send() && socket.can_recv() { + let bytes_rcvd = socket.recv_slice(&mut data); + info!("bytes rcvd: {:?}", bytes_rcvd.unwrap()); + socket.send_slice(&data).unwrap(); + if(data[0]=='h' as u8 && data[1]=='i' as u8) {yay = true;}; + for elem in data.iter_mut() { *elem = 0; } + } if socket.can_send() { - // info!("Can send..."); - unsafe{ - socket.send_slice(b"Hello World!\r\n").unwrap(); - info!("Hello World"); + if(yay){ + socket.send_slice(b"Horrayy!\r\n").unwrap(); + yay = false; } + } + + + // if socket.can_send() { + // // info!("Can send..."); + // unsafe{ + // socket.send_slice(b"Hello World!\r\n").unwrap(); + // info!("Hello World"); + // } + // } } { From d571fe783f961f032a798b9d9c69d29f8e838105 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Sun, 16 May 2021 15:56:28 +0200 Subject: [PATCH 32/36] demo SoC working! :) --- rust/SoC_demo/src/gpio.rs | 15 ++------ rust/SoC_demo/src/main.rs | 73 ++++++++++++++++++++++++++++----------- rust/litex-pac/clSOC.svd | 69 ++++++------------------------------ soc/colorlight_5a_75x.py | 38 +++----------------- 4 files changed, 71 insertions(+), 124 deletions(-) diff --git a/rust/SoC_demo/src/gpio.rs b/rust/SoC_demo/src/gpio.rs index 5c28f83..8fcd819 100644 --- a/rust/SoC_demo/src/gpio.rs +++ b/rust/SoC_demo/src/gpio.rs @@ -26,7 +26,7 @@ impl Gpio { pub fn en_interrupt(&mut self) { unsafe { - self.registers.ev_enable.write(|w| w.bits(0xffff)); + self.registers.ev_enable.write(|w| w.bits(0xFFFF_FFFF)); } } @@ -41,18 +41,7 @@ impl Gpio { self.registers.ev_enable.write(|w| w.bits(0)); } } - - pub fn ev_pending(&mut self) -> u32 { - self.registers.ev_pending.read().bits() - } - - pub fn ev_status(&mut self) -> u32 { - self.registers.ev_status.read().bits() - } - - pub fn ev_enable(&mut self) -> u32 { - self.registers.ev_enable.read().bits() - } + } // pub struct Gpio2 { diff --git a/rust/SoC_demo/src/main.rs b/rust/SoC_demo/src/main.rs index a86105c..6e48766 100644 --- a/rust/SoC_demo/src/main.rs +++ b/rust/SoC_demo/src/main.rs @@ -40,6 +40,8 @@ use log::{debug, info, trace}; const SYSTEM_CLOCK_FREQUENCY: u32 = 60_000_000; +static mut interrupted:bool = false; +// state of the button interrupt. static mut allows (unsafe) communication between main and irq. mod mock { @@ -151,13 +153,17 @@ fn main() -> ! { let udp_server_handle = socket_set.add(udp_server_socket); timer2.load(0); - timer2.reload(SYSTEM_CLOCK_FREQUENCY / 5); + timer2.reload(SYSTEM_CLOCK_FREQUENCY / 2); timer2.enable(); timer2.en_interrupt(); pwm.set_period(1 << 15); pwm.set_value(1 << 13); + gpio.set_interrupt_polarity(true); + gpio.en_interrupt(); + + unsafe { vmim::write(0xFFFF_FFFF); // 1010 for timer and gpio mstatus::set_mie(); @@ -189,25 +195,43 @@ fn main() -> ! { let bytes_rcvd = socket.recv_slice(&mut data); info!("bytes rcvd: {:?}", bytes_rcvd.unwrap()); socket.send_slice(&data).unwrap(); - if(data[0]=='h' as u8 && data[1]=='i' as u8) {yay = true;}; + + if(&data[0..3] == "hi\n".as_bytes()) {socket.send_slice(b"Horrayy! :)\r\n").unwrap();} + + else if(&data[0..7] == "led on\n".as_bytes()) { + leds.on(); + info!("turned led on"); + } + else if(&data[0..8] == "led off\n".as_bytes()) { + leds.off(); + info!("turned led off"); + } + else if(&data[0..15] == "tell me a joke\n".as_bytes()) { + socket.send_slice(b"Was machen die Pilze auf der Pizza? Als Belag funghieren. Ha.\r\n").unwrap(); + } + else if(&data[0..7] == "set pwm".as_bytes()) { + let value = as_u32_be(&data[9..13]); + pwm.set_value(value); + socket.send_slice(b"set pwm value.\r\n").unwrap(); + info!("set pwm value to {}", value); + } + else { + socket.send_slice(b"I didn't understand, sorry...\r\n").unwrap(); + info!("wtf is this other computer talking about??"); + } + for elem in data.iter_mut() { *elem = 0; } } + if socket.can_send() { - if(yay){ - socket.send_slice(b"Horrayy!\r\n").unwrap(); - yay = false; + unsafe { + if interrupted { + socket.send_slice(b"Someone pressed my Button!\r\n").unwrap(); + info!("interrupt noticed"); + interrupted=false; + } } - } - - - // if socket.can_send() { - // // info!("Can send..."); - // unsafe{ - // socket.send_slice(b"Hello World!\r\n").unwrap(); - // info!("Hello World"); - // } - // } } { @@ -246,6 +270,7 @@ fn MachineExternal() { if irqs_pending & (1 << irq_no) != 0 { match isr_to_interrupt(irq_no) { Some(0) => system_tick(), + Some(1) => button_irq(), _ => unsafe{vmim::write(vmim::read() ^ (1< u32 { + +fn as_u32_be(array: &[u8]) -> u32 { ((array[0] as u32) << 24) + ((array[1] as u32) << 16) + ((array[2] as u32) << 8) + ((array[3] as u32) << 0) } -fn as_u32_le(array: &[u8; 4]) -> u32 { +fn as_u32_le(array: &[u8]) -> u32 { ((array[0] as u32) << 0) + ((array[1] as u32) << 8) + ((array[2] as u32) << 16) + diff --git a/rust/litex-pac/clSOC.svd b/rust/litex-pac/clSOC.svd index eef42a2..963a81e 100644 --- a/rust/litex-pac/clSOC.svd +++ b/rust/litex-pac/clSOC.svd @@ -1017,6 +1017,13 @@ register to disable individual events.]]> 2 + + user_led_n + 3 + [3:3] + 3 + + @@ -1067,36 +1074,9 @@ register to disable individual events.]]> registers - - ADC - 0xF0006000 - ADC - - - ADC_VALUE - - 0x0000 - 0x00 - 32 - - - adc_value - 31 - [31:0] - 0 - - - - - - 0 - 0x4 - registers - - GPIO - 0xF0006800 + 0xF0006000 GPIO @@ -1193,7 +1173,7 @@ register to disable individual events.]]> TIMER2 - 0xF0007000 + 0xF0006800 TIMER2 @@ -1339,7 +1319,7 @@ register to disable individual events.]]> PWM - 0xF0007800 + 0xF0007000 PWM @@ -1379,33 +1359,6 @@ register to disable individual events.]]> registers - - DAC - 0xF0008000 - DAC - - - VAL - - 0x0000 - 0x00 - 32 - - - val - 15 - [15:0] - 0 - - - - - - 0 - 0x4 - registers - - ETHMEM 0x80000000 @@ -1525,7 +1478,7 @@ register to disable individual events.]]> - + diff --git a/soc/colorlight_5a_75x.py b/soc/colorlight_5a_75x.py index 23c1b4f..fe43c52 100755 --- a/soc/colorlight_5a_75x.py +++ b/soc/colorlight_5a_75x.py @@ -315,13 +315,15 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi self.submodules.leds = Leds(Cat( platform.request("r"), platform.request("y"), - platform.request("g") + platform.request("g"), + platform.request("user_led_n"), ), - led_polarity=0x00, + led_polarity=0x8, led_name=[ ["r", "The Red LED."], ["y", "The Yellow LED."], - ["g", "The Green Red LED."] + ["g", "The Green Red LED."], + ["user_led_n", "The onboard LED."] ]) self.add_csr("leds") @@ -340,30 +342,6 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi self.add_csr("leds2") - - - - - # sigma delta ADC using lame CSR for now - - self.submodules.adc = adc = ADC(cic_order=5, cic_ratechange=2**25, clk_div=4) - - adc_in = platform.request("in") - adc_sd = platform.request("sd", 0) - adc_sd2 = platform.request("sd", 1) - #p5v = platform.request("p5v") - p3v = platform.request("p3v") - - self.comb += [ - adc.inp.eq(adc_in), - adc_sd.eq(adc.sd), - adc_sd2.eq(adc.sd), - #p5v.eq(1), - p3v.eq(1), - ] - - self.add_csr("adc") - self.submodules.gpio = gpio = GPIOIn(platform.request("user_btn_n", 0), with_irq=True) self.add_csr("gpio") self.add_interrupt("gpio") @@ -375,13 +353,7 @@ def __init__(self, debug, flash_offset, board, revision, with_ethernet=False, wi self.submodules.pwm = PWM(platform.request("pwm"), width=32) self.add_csr("pwm") - self.submodules.dac = dac = DAC(platform.request("dac", 1), bits=16) - self.add_csr("dac") - # using line drivers in parallel as peltier driver - self.comb += [ - Cat([platform.request("pd", i) for i in range(8)]).eq(Cat([dac.pin for i in range(8)])) - ] From 9a3d3a3c8a12e5d47b6948f0390b737fed4c699b Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Sun, 16 May 2021 16:41:46 +0200 Subject: [PATCH 33/36] Update README.md --- README.md | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9de94e5..14fa8bd 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,32 @@ # `Rust SoC Playground using LiteX, VexRiscV and the Colorlight 5A-75B board` -Trying lots of different things (in different branches). +This repository contains a lot of fun with rust and RiscV. -Working so far: +The main branch is a small demo of a TCP connection with different options like turning LEDs on/off or registering an external button interrupt. +It is somewhat ceaned up and meant for people who want to get started. + +Most of the instructions are adapted from https://github.com/DerFetzer/colorlight-litex and https://github.com/icebreaker-fpga/icebreaker-litex-examples: + +1. Install Litex as described [here][litex]. +2. Install [ecpprog][ecpprog]. +4. Connect a USB to JTAG adaptor to your board. +5. Build and flash the SOC with something like the following: +``` +python3 colorlight_5a_75x.py --flash --board=5a-75b --revision=7.0 --with-ethernet --sys-clk-freq 60e6 + +``` +4. Follow the instructions in [eth_demo][eth_demo] to build the software. + + +There are a few things added to the standard Colorlight 5A-75B. If you just want to try the SoC with one onboard LED, the onboard button and just the TX of the UART you do not need to modify anything. + + +Working in some branch: - Ethernet with smoltcp thanks to https://github.com/DerFetzer/colorlight-litex - Interrupts by staring a lot at https://github.com/betrusted-io/xous-core - A simple second order sigma-delta ADC using a CIC decimator - An IIR filter using on-chip sigma-delta ADC/DAC +- A peltier temperature controller using a custom on-SoC ratiometric ADC, an IIR filter triggered by timer interrupts, TCP telemetry, UDP temperature set and the onboard line drivers in parallel as peltier drivers ;) ## Credits @@ -19,4 +39,4 @@ and the Litex [target file][target] for the Colorlight board. [litex-example]: https://github.com/icebreaker-fpga/icebreaker-litex-examples [colorlight]: http://www.colorlight-led.com/product/colorlight-5a-75e-led-display-receiving-card.html [target]: https://github.com/litex-hub/litex-boards/blob/master/litex_boards/targets/colorlight_5a_75x.py -[eth_demo]: rust/eth_demo/README.md +[SoC_demo]: rust/SoC_demo/README.md From bc4136aaf1d76bcf6c2cf5c3accdd5eebae269cf Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Sun, 16 May 2021 16:42:25 +0200 Subject: [PATCH 34/36] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 14fa8bd..ed5086f 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Most of the instructions are adapted from https://github.com/DerFetzer/colorligh python3 colorlight_5a_75x.py --flash --board=5a-75b --revision=7.0 --with-ethernet --sys-clk-freq 60e6 ``` -4. Follow the instructions in [eth_demo][eth_demo] to build the software. +4. Follow the instructions in [SoC_demo][SoC_demo] to build the software. There are a few things added to the standard Colorlight 5A-75B. If you just want to try the SoC with one onboard LED, the onboard button and just the TX of the UART you do not need to modify anything. From 200ad0d515ce4ecb04e850aecc322301be77647e Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Sun, 16 May 2021 16:49:46 +0200 Subject: [PATCH 35/36] Update README.md --- rust/SoC_demo/README.md | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/rust/SoC_demo/README.md b/rust/SoC_demo/README.md index d7c5afc..c3b48c1 100644 --- a/rust/SoC_demo/README.md +++ b/rust/SoC_demo/README.md @@ -32,28 +32,22 @@ cargo run --release It might be necessary to reset the board with a power cycle or by loading the SOC bitstream again. -You now should have a TCP endpoint at `192.168.1.50:1234` and a UDP endpoint at `192.168.1.50:5678` listening for connections. +You now should have a TCP endpoint at `192.168.1.50:1234`. Connect your computer to the board's Ethernet port an assign a static IP from the `192.168.1.0/24` subnet. -You can now connect to the sockets and get a `Hello World!` back. +You can now connect to the SoC using netcat: ``` -echo "" | netcat 192.168.1.50 1234 -echo "" | netcat -u 192.168.1.50 5678 -``` +rlwrap nc -vv 192.168.1.50 1234 -Connect a USB to UART adapter as described in [litex-boards][uart]. +``` -You should be able to access the console output by running the wishbone-tool. +Now you should have a TCP connection with the SoC and you can talk to it. For example just type "hi" and press enter. Or "led on". If you press the button, you should get a "button pressed" message via TCP. Have a look at main.rs to see which commands the SoC can parse. -``` -wishbone-tool --uart /dev/ttyUSB1 -s terminal -``` -You can find the wishbone-tool here: https://github.com/litex-hub/wishbone-utils -NOTE: If you decided to build your SOC without the `--debug` parameter you can access the console output directly. For example using screen: +NOTE: You can also look at the UART output. Just connect a UART probe to the correct pins (look at the custom pinout at the top of the LiteX SoC description). Example using screen: ``` screen /dev/ttyUSB1 115200 @@ -63,4 +57,3 @@ To exit screen you can type `Ctrl-a k` or `Ctrl-a Ctrl-k` [bug]: https://github.com/rust-lang/cargo/issues/7915#issuecomment-683294870 -[uart]: https://github.com/litex-hub/litex-boards/blob/e4cdbe0f7ad0653e825556d992d233a1723273e3/litex_boards/targets/colorlight_5a_75x.py#L11 From 70ee1ce3e3123cbc6ee33ee5673b54014c46fff3 Mon Sep 17 00:00:00 2001 From: SingularitySurfer Date: Sun, 16 May 2021 16:50:31 +0200 Subject: [PATCH 36/36] Update README.md --- rust/SoC_demo/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/SoC_demo/README.md b/rust/SoC_demo/README.md index c3b48c1..5d699c3 100644 --- a/rust/SoC_demo/README.md +++ b/rust/SoC_demo/README.md @@ -43,7 +43,7 @@ rlwrap nc -vv 192.168.1.50 1234 ``` -Now you should have a TCP connection with the SoC and you can talk to it. For example just type "hi" and press enter. Or "led on". If you press the button, you should get a "button pressed" message via TCP. Have a look at main.rs to see which commands the SoC can parse. +Now you should have a TCP connection with the SoC and you can talk to it. For example just type "hi" and press enter. Or "led on". If you press the button on the board, you should get a "button pressed" message via TCP. Have a look at main.rs to see which commands the SoC can parse.