From e389d5e8a676ceb4f9c1037cc010c238c94b72e5 Mon Sep 17 00:00:00 2001 From: "Dana H. Myers" Date: Tue, 2 Feb 2021 21:57:58 -0800 Subject: [PATCH 1/2] Initial attempt at sparkfun-redv BSP --- bsp/sparkfun-redv/README.md | 13 + bsp/sparkfun-redv/core.dts | 250 ++ bsp/sparkfun-redv/design.dts | 10 + bsp/sparkfun-redv/design.reglist | 54 + bsp/sparkfun-redv/design.svd | 3169 ++++++++++++++++++++++++ bsp/sparkfun-redv/metal-inline.h | 374 +++ bsp/sparkfun-redv/metal-platform.h | 298 +++ bsp/sparkfun-redv/metal.default.lds | 301 +++ bsp/sparkfun-redv/metal.freertos.lds | 327 +++ bsp/sparkfun-redv/metal.h | 1468 +++++++++++ bsp/sparkfun-redv/metal.ramrodata.lds | 306 +++ bsp/sparkfun-redv/metal.scratchpad.lds | 294 +++ bsp/sparkfun-redv/settings.mk | 13 + 13 files changed, 6877 insertions(+) create mode 100644 bsp/sparkfun-redv/README.md create mode 100644 bsp/sparkfun-redv/core.dts create mode 100644 bsp/sparkfun-redv/design.dts create mode 100644 bsp/sparkfun-redv/design.reglist create mode 100644 bsp/sparkfun-redv/design.svd create mode 100644 bsp/sparkfun-redv/metal-inline.h create mode 100644 bsp/sparkfun-redv/metal-platform.h create mode 100644 bsp/sparkfun-redv/metal.default.lds create mode 100644 bsp/sparkfun-redv/metal.freertos.lds create mode 100644 bsp/sparkfun-redv/metal.h create mode 100644 bsp/sparkfun-redv/metal.ramrodata.lds create mode 100644 bsp/sparkfun-redv/metal.scratchpad.lds create mode 100644 bsp/sparkfun-redv/settings.mk diff --git a/bsp/sparkfun-redv/README.md b/bsp/sparkfun-redv/README.md new file mode 100644 index 000000000..f5abca5bf --- /dev/null +++ b/bsp/sparkfun-redv/README.md @@ -0,0 +1,13 @@ +HiFive1 Rev B is a low-cost, Arduino-compatible development board featuring the Freedom E310. It’s the best way to start prototyping and developing your RISC‑V applications. + +This target is ideal for getting familiar with the RISC-V ISA instruction set and the freedom-metal libraries. It supports: + +- 1 hart with RV32IMAC core +- 4 hardware breakpoints +- Physical Memory Protection with 8 regions +- 16 local interrupts signal that can be connected to off core complex devices +- Up to 127 PLIC interrupt signals that can be connected to off core complex devices, with 7 priority levels +- GPIO memory with 16 interrupt lines +- SPI memory with 1 interrupt line +- Serial port with 1 interrupt line +- 1 RGB LEDS diff --git a/bsp/sparkfun-redv/core.dts b/bsp/sparkfun-redv/core.dts new file mode 100644 index 000000000..268199547 --- /dev/null +++ b/bsp/sparkfun-redv/core.dts @@ -0,0 +1,250 @@ +/dts-v1/; +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "sparkfun,redv"; + model = "sparkfun,rev"; + cpus { + #address-cells = <1>; + #size-cells = <0>; + compatible = "sifive,fe310-g000"; + L6: cpu@0 { + clocks = <&hfclk>; + compatible = "sifive,rocket0", "riscv"; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <16384>; + next-level-cache = <&spi0>; + reg = <0>; + riscv,isa = "rv32imac"; + riscv,pmpregions = <8>; + sifive,itim = <&itim>; + sifive,dtim = <&dtim>; + status = "okay"; + timebase-frequency = <16000000>; + hardware-exec-breakpoint-count = <4>; + hlic: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + }; + soc { + #address-cells = <1>; + #size-cells = <1>; + #clock-cells = <1>; + compatible = "sifive,hifive1"; + ranges; + hfxoscin: clock@0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <16000000>; + }; + hfxoscout: clock@1 { + compatible = "sifive,fe310-g000,hfxosc"; + clocks = <&hfxoscin>; + reg = <&prci 0x4>; + reg-names = "config"; + }; + hfroscin: clock@2 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <72000000>; + }; + hfroscout: clock@3 { + compatible = "sifive,fe310-g000,hfrosc"; + clocks = <&hfroscin>; + reg = <&prci 0x0>; + reg-names = "config"; + }; + hfclk: clock@4 { + compatible = "sifive,fe310-g000,pll"; + clocks = <&hfxoscout &hfroscout>; + clock-names = "pllref", "pllsel0"; + reg = <&prci 0x8 &prci 0xc>; + reg-names = "config", "divider"; + clock-frequency = <16000000>; + }; + lfrosc: clock@5 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + psdlfaltclk: clock@6 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + lfclk: clock@7 { + compatible = "sifive,fe310-g000,lfrosc"; + clocks = <&lfrosc &psdlfaltclk>; + clock-names = "lfrosc", "psdlfaltclk"; + reg = <&aon 0x70 &aon 0x7C>; + reg-names = "config", "mux"; + }; + debug-controller@0 { + compatible = "sifive,debug-011", "riscv,debug-011"; + interrupts-extended = <&hlic 65535>; + reg = <0x0 0x1000>; + reg-names = "control"; + }; + /* Missing: Error device */ + maskrom@1000 { + reg = <0x1000 0x2000>; + reg-names = "mem"; + }; + otp@20000 { + reg = <0x20000 0x2000 0x10010000 0x1000>; + reg-names = "mem", "control"; + }; + clint: clint@2000000 { + compatible = "riscv,clint0"; + interrupts-extended = <&hlic 3 &hlic 7>; + reg = <0x2000000 0x10000>; + reg-names = "control"; + }; + itim: itim@8000000 { + compatible = "sifive,itim0"; + reg = <0x8000000 0x2000>; + reg-names = "mem"; + }; + plic: interrupt-controller@c000000 { + #interrupt-cells = <1>; + compatible = "riscv,plic0"; + interrupt-controller; + interrupts-extended = <&hlic 11>; + reg = <0xc000000 0x4000000>; + reg-names = "control"; + riscv,max-priority = <7>; + riscv,ndev = <52>; + }; + aon: aon@10000000 { + compatible = "sifive,aon0"; + reg = <0x10000000 0x8000>; + reg-names = "mem"; + interrupt-parent = <&plic>; + interrupts = <1 2>; + clocks = <&lfclk>; + }; + prci: prci@10008000 { + compatible = "sifive,fe310-g000,prci"; + reg = <0x10008000 0x8000>; + reg-names = "mem"; + }; + gpio0: gpio@10012000 { + compatible = "sifive,gpio0"; + interrupt-parent = <&plic>; + interrupts = <8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + 23 24 25 26 27 28 29 30 31 32 33 34 35 36 + 27 28 29>; + reg = <0x10012000 0x1000>; + reg-names = "control"; + }; + led@0 { + compatible = "sifive,gpio-leds"; + label = "LD0"; + gpios = <&gpio0 5>; + linux,default-trigger = "none"; + }; + uart0: serial@10013000 { + compatible = "sifive,uart0"; + interrupt-parent = <&plic>; + interrupts = <3>; + reg = <0x10013000 0x1000>; + reg-names = "control"; + clocks = <&hfclk>; + pinmux = <&gpio0 0x0 0x30000>; + }; + spi0: spi@10014000 { + compatible = "sifive,spi0"; + interrupt-parent = <&plic>; + interrupts = <5>; + reg = <0x10014000 0x1000 0x20000000 0x7A120>; + reg-names = "control", "mem"; + clocks = <&hfclk>; + pinmux = <&gpio0 0x0 0x0>; + #address-cells = <1>; + #size-cells = <1>; + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0x20000000 0x424000>; + }; + }; + pwm0: pwm@10015000 { + compatible = "sifive,pwm0"; + sifive,comparator-widthbits = <8>; + sifive,ncomparators = <4>; + interrupt-parent = <&plic>; + interrupts = <40 41 42 43>; + reg = <0x10015000 0x1000>; + reg-names = "control"; + clocks = <&hfclk>; + pinmux = <&gpio0 0x0F 0x0F>; + }; + i2c0: i2c@10016000 { + compatible = "sifive,i2c0"; + interrupt-parent = <&plic>; + interrupts = <52>; + reg = <0x10016000 0x1000>; + reg-names = "control"; + clocks = <&hfclk>; + pinmux = <&gpio0 0x0 0x3000>; + }; + uart1: serial@10023000 { + compatible = "sifive,uart0"; + interrupt-parent = <&plic>; + interrupts = <4>; + reg = <0x10023000 0x1000>; + reg-names = "control"; + clocks = <&hfclk>; + pinmux = <&gpio0 0x0 0x840000>; + }; + spi1: spi@10024000 { + compatible = "sifive,spi0"; + interrupt-parent = <&plic>; + interrupts = <6>; + reg = <0x10024000 0x1000>; + reg-names = "control"; + clocks = <&hfclk>; + pinmux = <&gpio0 0x0 0x0003C>; + }; + pwm1: pwm@10025000 { + compatible = "sifive,pwm0"; + sifive,comparator-widthbits = <16>; + sifive,ncomparators = <4>; + interrupt-parent = <&plic>; + interrupts = <44 45 46 47>; + reg = <0x10025000 0x1000>; + reg-names = "control"; + clocks = <&hfclk>; + pinmux = <&gpio0 0x780000 0x780000>; + }; + spi2: spi@10034000 { + compatible = "sifive,spi0"; + interrupt-parent = <&plic>; + interrupts = <7>; + reg = <0x10034000 0x1000>; + reg-names = "control"; + clocks = <&hfclk>; + pinmux = <&gpio0 0x0 0xFC000000>; + }; + pwm2: pwm@10035000 { + compatible = "sifive,pwm0"; + sifive,comparator-widthbits = <16>; + sifive,ncomparators = <4>; + interrupt-parent = <&plic>; + interrupts = <48 49 50 51>; + reg = <0x10035000 0x1000>; + reg-names = "control"; + clocks = <&hfclk>; + pinmux = <&gpio0 0x3C00 0x3C00>; + }; + dtim: dtim@80000000 { + compatible = "sifive,dtim0"; + reg = <0x80000000 0x4000>; + reg-names = "mem"; + }; + }; +}; diff --git a/bsp/sparkfun-redv/design.dts b/bsp/sparkfun-redv/design.dts new file mode 100644 index 000000000..098c25c4b --- /dev/null +++ b/bsp/sparkfun-redv/design.dts @@ -0,0 +1,10 @@ +/include/ "core.dts" +/ { + chosen { + metal,entry = <&spi0 1 65536>; + metal,boothart = <&L6>; + stdout-path = "/soc/serial@10013000:115200"; + metal,itim = <&itim 0 0>; + metal,ram = <&dtim 0 0>; + }; +}; diff --git a/bsp/sparkfun-redv/design.reglist b/bsp/sparkfun-redv/design.reglist new file mode 100644 index 000000000..921dd83ac --- /dev/null +++ b/bsp/sparkfun-redv/design.reglist @@ -0,0 +1,54 @@ +zero +ra +sp +gp +tp +t0 +t1 +t2 +fp +s1 +a0 +a1 +a2 +a3 +a4 +a5 +a6 +a7 +s2 +s3 +s4 +s5 +s6 +s7 +s8 +s9 +s10 +s11 +t3 +t4 +t5 +t6 +pc +mstatus +misa +mie +mtvec +mscratch +mepc +mcause +mtval +mip +mvendorid +marchid +mimpid +mhartid +tselect +tdata1 +tdata2 +tdata3 +dcsr +dpc +dscratch +priv diff --git a/bsp/sparkfun-redv/design.svd b/bsp/sparkfun-redv/design.svd new file mode 100644 index 000000000..3ad2768bd --- /dev/null +++ b/bsp/sparkfun-redv/design.svd @@ -0,0 +1,3169 @@ + + + sifive_hifive1_revb + 0.1 + From sifive,hifive1-revb,model device generator + 8 + 32 + 32 + read-write + + + riscv_clint0_0 + From riscv,clint0,control peripheral generator + 0x2000000 + + 0 + 0x10000 + registers + + + + msip_0 + MSIP Register for hart 0 + 0x0 + + + mtimecmp_0 + MTIMECMP Register for hart 0 + 0x4000 + 64 + + + mtime + MTIME Register + 0xBFF8 + 64 + + + + + riscv_plic0_0 + From riscv,plic0,control peripheral generator + 0xC000000 + + 0 + 0x4000000 + registers + + + + priority_1 + PRIORITY Register for interrupt id 1 + 0x4 + + + priority_2 + PRIORITY Register for interrupt id 2 + 0x8 + + + priority_3 + PRIORITY Register for interrupt id 3 + 0xC + + + priority_4 + PRIORITY Register for interrupt id 4 + 0x10 + + + priority_5 + PRIORITY Register for interrupt id 5 + 0x14 + + + priority_6 + PRIORITY Register for interrupt id 6 + 0x18 + + + priority_7 + PRIORITY Register for interrupt id 7 + 0x1C + + + priority_8 + PRIORITY Register for interrupt id 8 + 0x20 + + + priority_9 + PRIORITY Register for interrupt id 9 + 0x24 + + + priority_10 + PRIORITY Register for interrupt id 10 + 0x28 + + + priority_11 + PRIORITY Register for interrupt id 11 + 0x2C + + + priority_12 + PRIORITY Register for interrupt id 12 + 0x30 + + + priority_13 + PRIORITY Register for interrupt id 13 + 0x34 + + + priority_14 + PRIORITY Register for interrupt id 14 + 0x38 + + + priority_15 + PRIORITY Register for interrupt id 15 + 0x3C + + + priority_16 + PRIORITY Register for interrupt id 16 + 0x40 + + + priority_17 + PRIORITY Register for interrupt id 17 + 0x44 + + + priority_18 + PRIORITY Register for interrupt id 18 + 0x48 + + + priority_19 + PRIORITY Register for interrupt id 19 + 0x4C + + + priority_20 + PRIORITY Register for interrupt id 20 + 0x50 + + + priority_21 + PRIORITY Register for interrupt id 21 + 0x54 + + + priority_22 + PRIORITY Register for interrupt id 22 + 0x58 + + + priority_23 + PRIORITY Register for interrupt id 23 + 0x5C + + + priority_24 + PRIORITY Register for interrupt id 24 + 0x60 + + + priority_25 + PRIORITY Register for interrupt id 25 + 0x64 + + + priority_26 + PRIORITY Register for interrupt id 26 + 0x68 + + + priority_27 + PRIORITY Register for interrupt id 27 + 0x6C + + + priority_28 + PRIORITY Register for interrupt id 28 + 0x70 + + + priority_29 + PRIORITY Register for interrupt id 29 + 0x74 + + + priority_30 + PRIORITY Register for interrupt id 30 + 0x78 + + + priority_31 + PRIORITY Register for interrupt id 31 + 0x7C + + + priority_32 + PRIORITY Register for interrupt id 32 + 0x80 + + + priority_33 + PRIORITY Register for interrupt id 33 + 0x84 + + + priority_34 + PRIORITY Register for interrupt id 34 + 0x88 + + + priority_35 + PRIORITY Register for interrupt id 35 + 0x8C + + + priority_36 + PRIORITY Register for interrupt id 36 + 0x90 + + + priority_37 + PRIORITY Register for interrupt id 37 + 0x94 + + + priority_38 + PRIORITY Register for interrupt id 38 + 0x98 + + + priority_39 + PRIORITY Register for interrupt id 39 + 0x9C + + + priority_40 + PRIORITY Register for interrupt id 40 + 0xA0 + + + priority_41 + PRIORITY Register for interrupt id 41 + 0xA4 + + + priority_42 + PRIORITY Register for interrupt id 42 + 0xA8 + + + priority_43 + PRIORITY Register for interrupt id 43 + 0xAC + + + priority_44 + PRIORITY Register for interrupt id 44 + 0xB0 + + + priority_45 + PRIORITY Register for interrupt id 45 + 0xB4 + + + priority_46 + PRIORITY Register for interrupt id 46 + 0xB8 + + + priority_47 + PRIORITY Register for interrupt id 47 + 0xBC + + + priority_48 + PRIORITY Register for interrupt id 48 + 0xC0 + + + priority_49 + PRIORITY Register for interrupt id 49 + 0xC4 + + + priority_50 + PRIORITY Register for interrupt id 50 + 0xC8 + + + priority_51 + PRIORITY Register for interrupt id 51 + 0xCC + + + priority_52 + PRIORITY Register for interrupt id 52 + 0xD0 + + + pending_0 + PENDING Register for interrupt ids 31 to 0 + 0x1000 + + + pending_1 + PENDING Register for interrupt ids 52 to 32 + 0x1004 + + + enable_0_0 + ENABLE Register for interrupt ids 31 to 0 for hart 0 + 0x2000 + + + enable_1_0 + ENABLE Register for interrupt ids 52 to 32 for hart 0 + 0x2004 + + + threshold_0 + PRIORITY THRESHOLD Register for hart 0 + 0x200000 + + + claimplete_0 + CLAIM and COMPLETE Register for hart 0 + 0x200004 + + + + + sifive_aon0_0 + From sifive,aon0,mem peripheral generator + 0x10000000 + + 0 + 0x8000 + registers + + + + backup_0 + Backup Register 0 + 0x80 + + + backup_1 + Backup Register 1 + 0x84 + + + backup_2 + Backup Register 2 + 0x88 + + + backup_3 + Backup Register 3 + 0x8C + + + backup_4 + Backup Register 4 + 0x90 + + + backup_5 + Backup Register 5 + 0x94 + + + backup_6 + Backup Register 6 + 0x98 + + + backup_7 + Backup Register 7 + 0x9C + + + backup_8 + Backup Register 8 + 0xA0 + + + backup_9 + Backup Register 9 + 0xA4 + + + backup_10 + Backup Register 10 + 0xA8 + + + backup_11 + Backup Register 11 + 0xAC + + + backup_12 + Backup Register 12 + 0xB0 + + + backup_13 + Backup Register 13 + 0xB4 + + + backup_14 + Backup Register 14 + 0xB8 + + + backup_15 + Backup Register 15 + 0xBC + + + wdogcfg + wdog Configuration + 0x0 + + + wdogscale + Counter scale value. + [3:0] + read-write + + + wdogrsten + Controls whether the comparator output can set the wdogrst bit and hence cause a full reset. + [8:8] + read-write + + + wdogzerocmp + Reset counter to zero after match. + [9:9] + read-write + + + wdogenalways + Enable Always - run continuously + [12:12] + read-write + + + wdogcoreawake + Increment the watchdog counter if the processor is not asleep + [13:13] + read-write + + + wdogip0 + Interrupt 0 Pending + [28:28] + read-write + + + + + wdogcount + Counter Register + 0x8 + + + wdogs + Scaled value of Counter + 0x10 + + + wdogfeed + Feed register + 0x18 + + + wdogkey + Key Register + 0x1C + + + wdogcmp0 + Comparator 0 + 0x20 + + + rtccfg + rtc Configuration + 0x40 + + + rtcscale + Counter scale value. + [3:0] + read-write + + + rtcenalways + Enable Always - run continuously + [12:12] + read-write + + + rtcip0 + Interrupt 0 Pending + [28:28] + read-write + + + + + rtccountlo + Low bits of Counter + 0x48 + + + rtccounthi + High bits of Counter + 0x4C + + + rtcs + Scaled value of Counter + 0x50 + + + rtccmp0 + Comparator 0 + 0x60 + + + pmuwakeupi0 + Wakeup program instruction 0 + 0x100 + + + pmuwakeupi1 + Wakeup program instruction 1 + 0x104 + + + pmuwakeupi2 + Wakeup program instruction 2 + 0x108 + + + pmuwakeupi3 + Wakeup program instruction 3 + 0x10C + + + pmuwakeupi4 + Wakeup program instruction 4 + 0x110 + + + pmuwakeupi5 + Wakeup program instruction 5 + 0x114 + + + pmuwakeupi6 + Wakeup program instruction 6 + 0x118 + + + pmuwakeupi7 + Wakeup program instruction 7 + 0x11C + + + pmusleepi0 + Sleep program instruction 0 + 0x120 + + + pmusleepi1 + Sleep program instruction 1 + 0x124 + + + pmusleepi2 + Sleep program instruction 2 + 0x128 + + + pmusleepi3 + Sleep program instruction 3 + 0x12C + + + pmusleepi4 + Sleep program instruction 4 + 0x130 + + + pmusleepi5 + Sleep program instruction 5 + 0x134 + + + pmusleepi6 + Sleep program instruction 6 + 0x138 + + + pmusleepi7 + Sleep program instruction 7 + 0x13C + + + pmuie + PMU Interrupt Enables + 0x140 + + + pmucause + PMU Wakeup Cause + 0x144 + + + pmusleep + Initiate PMU Sleep Sequence + 0x148 + + + pmukey + PMU Key. Reads as 1 when PMU is unlocked + 0x14C + + + aoncfg + AON Block Configuration Information + 0x300 + + + has_bandgap + Bandgap feature is present + [0:0] + read-only + + + has_bod + Brownout detector feature is present + [1:1] + read-only + + + has_lfrosc + Low Frequency Ring Oscillator feature is present + [2:2] + read-only + + + has_lfrcosc + Low Frequency RC Oscillator feature is present + [3:3] + read-only + + + has_lfxosc + Low Frequency Crystal Oscillator feature is present + [4:4] + read-only + + + has_por + Power-On-Reset feature is present + [5:5] + read-only + + + has_ldo + Low Dropout Regulator feature is present + [6:6] + read-only + + + + + lfrosccfg + Ring Oscillator Configuration and Status + 0x70 + + + lfroscdiv + Ring Oscillator Divider Register + [5:0] + read-write + + + lfrosctrim + Ring Oscillator Trim Register + [20:16] + read-write + + + lfroscen + Ring Oscillator Enable + [30:30] + read-write + + + lfroscrdy + Ring Oscillator Ready + [31:31] + read-only + + + + + lfclkmux + Low-Frequency Clock Mux Control and Status + 0x7C + + + lfextclk_sel + Low Frequency Clock Source Selector + [0:0] + read-write + + + internal + Use internal LF clock source + 0 + + + external + Use external LF clock source + 1 + + + + + lfextclk_mux_status + Setting of the aon_lfclksel pin + [31:31] + read-only + + + external + Use external LF clock source + 0 + + + sw + Use clock source selected by lfextclk_sel + 1 + + + + + + + + + sifive_fe310_g000_prci_0 + From sifive,fe310-g000,prci,mem peripheral generator + 0x10008000 + + 0 + 0x8000 + registers + + + + hfrosccfg + Ring Oscillator Configuration and Status + 0x0 + + + hfroscdiv + Ring Oscillator Divider Register + [5:0] + read-write + + + hfrosctrim + Ring Oscillator Trim Register + [20:16] + read-write + + + hfroscen + Ring Oscillator Enable + [30:30] + read-write + + + hfroscrdy + Ring Oscillator Ready + [31:31] + read-only + + + + + hfxosccfg + Crystal Oscillator Configuration and Status + 0x4 + + + hfxoscen + Crystal Oscillator Enable + [30:30] + read-write + + + hfxoscrdy + Crystal Oscillator Ready + [31:31] + read-only + + + + + pllcfg + PLL Configuration and Status + 0x8 + + + pllr + PLL R Value + [2:0] + read-write + + + pllf + PLL F Value + [9:4] + read-write + + + pllq + PLL Q Value + [11:10] + read-write + + + pllsel + PLL Select + [16:16] + read-write + + + pllrefsel + PLL Reference Select + [17:17] + read-write + + + pllbypass + PLL Bypass + [18:18] + read-write + + + plllock + PLL Lock + [31:31] + read-only + + + + + plloutdiv + PLL Final Divide Configuration + 0xC + + + plloutdiv + PLL Final Divider Value + [5:0] + read-write + + + plloutdivby1 + PLL Final Divide By 1 + [13:8] + read-write + + + + + procmoncfg + Process Monitor Configuration and Status + 0xF0 + + + procmon_div_sel + Proccess Monitor Divider + [4:0] + read-write + + + procmon_delay_sel + Process Monitor Delay Selector + [12:8] + read-write + + + procmon_en + Process Monitor Enable + [16:16] + read-write + + + procomon_sel + Process Monitor Select + [25:24] + read-write + + + + + + + sifive_gpio0_0 + From sifive,gpio0,control peripheral generator + 0x10012000 + + 0 + 0x1000 + registers + + + + input_val + Pin value + 0x0 + + + input_en + Pin input enable + 0x4 + + + output_en + Pin output enable + 0x8 + + + output_val + Output value + 0xC + + + pue + Internal pull-up enable + 0x10 + + + ds + Pin drive strength + 0x14 + + + rise_ie + Rise interrupt enable + 0x18 + + + rise_ip + Rise interrupt pending + 0x1C + + + fall_ie + Fall interrupt enable + 0x20 + + + fall_ip + Fall interrupt pending + 0x24 + + + high_ie + High interrupt enable + 0x28 + + + high_ip + High interrupt pending + 0x2C + + + low_ie + Low interrupt enable + 0x30 + + + low_ip + Low interrupt pending + 0x34 + + + iof_en + I/O function enable + 0x38 + + + iof_sel + I/O function select + 0x3C + + + out_xor + Output XOR (invert) + 0x40 + + + + + sifive_uart0_0 + From sifive,uart0,control peripheral generator + 0x10013000 + + 0 + 0x1000 + registers + + + + txdata + Transmit data register + 0x0 + + + data + Transmit data + [7:0] + read-write + + + full + Transmit FIFO full + [31:31] + read-only + + + + + rxdata + Receive data register + 0x4 + + + data + Received data + [7:0] + read-only + + + empty + Receive FIFO empty + [31:31] + read-only + + + + + txctrl + Transmit control register + 0x8 + + + txen + Transmit enable + [0:0] + read-write + + + nstop + Number of stop bits + [1:1] + read-write + + + txcnt + Transmit watermark level + [18:16] + read-write + + + + + rxctrl + Receive control register + 0xC + + + rxen + Receive enable + [0:0] + read-write + + + rxcnt + Receive watermark level + [18:16] + read-write + + + + + ie + UART interrupt enable + 0x10 + + + txwm + Transmit watermark interrupt enable + [0:0] + read-write + + + rxwm + Receive watermark interrupt enable + [1:1] + read-write + + + + + ip + UART interrupt pending + 0x14 + + + txwm + Transmit watermark interrupt pending + [0:0] + read-only + + + rxwm + Receive watermark interrupt pending + [1:1] + read-only + + + + + div + Baud rate divisor + 0x18 + + + div + Baud rate divisor. + [15:0] + read-write + + + + + + + sifive_spi0_0 + From sifive,spi0,control peripheral generator + 0x10014000 + + 0 + 0x1000 + registers + + + + sckdiv + Serial clock divisor + 0x0 + + + div + Divisor for serial clock. + [11:0] + read-write + + + + + sckmode + Serial clock mode + 0x4 + + + pha + Serial clock phase + [0:0] + read-write + + + pol + Serial clock polarity + [1:1] + read-write + + + + + csid + Chip select ID + 0x10 + + + csid + Chip select ID. + [31:0] + read-write + + + + + csdef + Chip select default + 0x14 + + + csdef + Chip select default value. Reset to all-1s. + [31:0] + read-write + + + + + csmode + Chip select mode + 0x18 + + + mode + Chip select mode + [1:0] + read-write + + + + + delay0 + Delay control 0 + 0x28 + + + cssck + CS to SCK Delay + [7:0] + read-write + + + sckcs + SCK to CS Delay + [23:16] + read-write + + + + + delay1 + Delay control 1 + 0x2C + + + intercs + Minimum CS inactive time + [7:0] + read-write + + + interxfr + Maximum interframe delay + [23:16] + read-write + + + + + extradel + SPI extra sampling delay to increase the SPI frequency + 0x38 + + + coarse + Coarse grain sample delay (multiples of system clocks) + [11:0] + read-write + + + fine + Fine grain sample delay (multiples of process-specific buffer delay) + [16:12] + read-write + + + + + sampledel + Number of delay stages from slave to the SPI controller + 0x3C + + + sd + Number of delay stages from slave to SPI controller + [4:0] + read-write + + + + + fmt + Frame format + 0x40 + + + proto + SPI protocol + [1:0] + read-write + + + endian + SPI endianness + [2:2] + read-write + + + dir + SPI I/O direction. This is reset to 1 for flash-enabled SPI controllers, 0 otherwise. + [3:3] + read-write + + + len + Number of bits per frame + [19:16] + read-write + + + + + txdata + Tx FIFO Data + 0x48 + + + data + Transmit data + [7:0] + read-write + + + full + FIFO full flag + [31:31] + read-only + + + + + rxdata + Rx FIFO data + 0x4C + + + data + Received data + [7:0] + read-only + + + empty + FIFO empty flag + [31:31] + read-write + + + + + txmark + Tx FIFO watermark + 0x50 + + + txmark + Transmit watermark. The reset value is 1 for flash-enabled controllers, 0 otherwise. + [2:0] + read-write + + + + + rxmark + Rx FIFO watermark + 0x54 + + + rxmark + Receive watermark + [2:0] + read-write + + + + + fctrl + SPI flash interface control + 0x60 + + + en + SPI Flash Mode Select + [0:0] + read-write + + + + + ffmt + SPI flash instruction format + 0x64 + + + cmd_en + Enable sending of command + [0:0] + read-write + + + addr_len + Number of address bytes (0 to 4) + [3:1] + read-write + + + pad_cnt + Number of dummy cycles + [7:4] + read-write + + + cmd_proto + Protocol for transmitting command + [9:8] + read-write + + + addr_proto + Protocol for transmitting address and padding + [11:10] + read-write + + + data_proto + Protocol for receiving data bytes + [13:12] + read-write + + + cmd_code + Value of command byte + [23:16] + read-write + + + pad_code + First 8 bits to transmit during dummy cycles + [31:24] + read-write + + + + + ie + SPI interrupt enable + 0x70 + + + txwm + Transmit watermark enable + [0:0] + read-write + + + rxwm + Receive watermark enable + [1:1] + read-write + + + + + ip + SPI interrupt pending + 0x74 + + + txwm + Transmit watermark pending + [0:0] + read-only + + + rxwm + Receive watermark pending + [1:1] + read-only + + + + + + + sifive_pwm0_0 + From sifive,pwm0,control peripheral generator + 0x10015000 + + 0 + 0x1000 + registers + + + + pwmcfg + PWM configuration register + 0x0 + + + pwmscale + PWM Counter scale + [3:0] + read-write + + + pwmsticky + PWM Sticky - disallow clearing pwmcmpXip bits + [8:8] + read-write + + + pwmzerocmp + PWM Zero - counter resets to zero after match + [9:9] + read-write + + + pwmdeglitch + PWM Deglitch - latch pwmcmpXip within same cycle + [10:10] + read-write + + + pwmenalways + PWM enable always - run continuously + [12:12] + read-write + + + pwmenoneshot + PWM enable one shot - run one cycle + [13:13] + read-write + + + pwmcmp0center + PWM0 Compare Center + [16:16] + read-write + + + pwmcmp1center + PWM1 Compare Center + [17:17] + read-write + + + pwmcmp2center + PWM2 Compare Center + [18:18] + read-write + + + pwmcmp3center + PWM3 Compare Center + [19:19] + read-write + + + pwmcmp0invert + PWM0 Invert + [20:20] + read-write + + + pwmcmp1invert + PWM1 Invert + [21:21] + read-write + + + pwmcmp2invert + PWM2 Invert + [22:22] + read-write + + + pwmcmp3invert + PWM3 Invert + [23:23] + read-write + + + pwmcmp0gang + PWM0/PWM1 Compare Gang + [24:24] + read-write + + + pwmcmp1gang + PWM1/PWM2 Compare Gang + [25:25] + read-write + + + pwmcmp2gang + PWM2/PWM3 Compare Gang + [26:26] + read-write + + + pwmcmp3gang + PWM3/PWM0 Compare Gang + [27:27] + read-write + + + pwmcmp0ip + PWM0 Interrupt Pending + [28:28] + read-write + + + pwmcmp1ip + PWM1 Interrupt Pending + [29:29] + read-write + + + pwmcmp2ip + PWM2 Interrupt Pending + [30:30] + read-write + + + pwmcmp3ip + PWM3 Interrupt Pending + [31:31] + read-write + + + + + pwmcount + PWM count register + 0x8 + + + pwmcount + PWM count register. + [30:0] + read-write + + + + + pwms + Scaled PWM count register + 0x10 + + + pwms + Scaled PWM count register. + [15:0] + read-write + + + + + pwmcmp0 + PWM 0 compare register + 0x20 + + + pwmcmp0 + PWM 0 Compare Value + [15:0] + read-write + + + + + pwmcmp1 + PWM 1 compare register + 0x24 + + + pwmcmp1 + PWM 1 Compare Value + [15:0] + read-write + + + + + pwmcmp2 + PWM 2 compare register + 0x28 + + + pwmcmp2 + PWM 2 Compare Value + [15:0] + read-write + + + + + pwmcmp3 + PWM 3 compare register + 0x2C + + + pwmcmp3 + PWM 3 Compare Value + [15:0] + read-write + + + + + + + sifive_i2c0_0 + From sifive,i2c0,control peripheral generator + 0x10016000 + + 0 + 0x1000 + registers + + + + prescale_low + Clock Prescale register lo-byte + 0x0 + + + prescale_high + Clock Prescale register hi-byte + 0x4 + + + control + Control register + 0x8 + + + en + I2C core enable bit + [6:6] + read-write + + + ien + I2C core interrupt enable bit + [7:7] + read-write + + + + + transmit__receive + Transmit and receive data byte register + 0xC + + + command__status + Command write and status read register + 0x10 + + + wr_iack__rd_if + Clear interrupt and Interrupt pending + [0:0] + read-write + + + wr_res__rd_tip + Reserved and Transfer in progress + [1:1] + read-write + + + wr_res__rd_res + Reserved and Reserved + [2:2] + read-write + + + wr_ack__rd_res + Send ACK/NACK and Reserved + [3:3] + read-write + + + wr_txd__rd_res + Transmit data and Reserved + [4:4] + read-write + + + wr_rxd__rd_al + Receive data and Arbitration lost + [5:5] + read-write + + + wr_sto__rd_busy + Generate stop and I2C bus busy + [6:6] + read-write + + + wr_sta__rd_rxack + Generate start and Got ACK/NACK + [7:7] + read-write + + + + + + + sifive_uart0_1 + From sifive,uart0,control peripheral generator + 0x10023000 + + 0 + 0x1000 + registers + + + + txdata + Transmit data register + 0x0 + + + data + Transmit data + [7:0] + read-write + + + full + Transmit FIFO full + [31:31] + read-only + + + + + rxdata + Receive data register + 0x4 + + + data + Received data + [7:0] + read-only + + + empty + Receive FIFO empty + [31:31] + read-only + + + + + txctrl + Transmit control register + 0x8 + + + txen + Transmit enable + [0:0] + read-write + + + nstop + Number of stop bits + [1:1] + read-write + + + txcnt + Transmit watermark level + [18:16] + read-write + + + + + rxctrl + Receive control register + 0xC + + + rxen + Receive enable + [0:0] + read-write + + + rxcnt + Receive watermark level + [18:16] + read-write + + + + + ie + UART interrupt enable + 0x10 + + + txwm + Transmit watermark interrupt enable + [0:0] + read-write + + + rxwm + Receive watermark interrupt enable + [1:1] + read-write + + + + + ip + UART interrupt pending + 0x14 + + + txwm + Transmit watermark interrupt pending + [0:0] + read-only + + + rxwm + Receive watermark interrupt pending + [1:1] + read-only + + + + + div + Baud rate divisor + 0x18 + + + div + Baud rate divisor. + [15:0] + read-write + + + + + + + sifive_spi0_1 + From sifive,spi0,control peripheral generator + 0x10024000 + + 0 + 0x1000 + registers + + + + sckdiv + Serial clock divisor + 0x0 + + + div + Divisor for serial clock. + [11:0] + read-write + + + + + sckmode + Serial clock mode + 0x4 + + + pha + Serial clock phase + [0:0] + read-write + + + pol + Serial clock polarity + [1:1] + read-write + + + + + csid + Chip select ID + 0x10 + + + csid + Chip select ID. + [31:0] + read-write + + + + + csdef + Chip select default + 0x14 + + + csdef + Chip select default value. Reset to all-1s. + [31:0] + read-write + + + + + csmode + Chip select mode + 0x18 + + + mode + Chip select mode + [1:0] + read-write + + + + + delay0 + Delay control 0 + 0x28 + + + cssck + CS to SCK Delay + [7:0] + read-write + + + sckcs + SCK to CS Delay + [23:16] + read-write + + + + + delay1 + Delay control 1 + 0x2C + + + intercs + Minimum CS inactive time + [7:0] + read-write + + + interxfr + Maximum interframe delay + [23:16] + read-write + + + + + extradel + SPI extra sampling delay to increase the SPI frequency + 0x38 + + + coarse + Coarse grain sample delay (multiples of system clocks) + [11:0] + read-write + + + fine + Fine grain sample delay (multiples of process-specific buffer delay) + [16:12] + read-write + + + + + sampledel + Number of delay stages from slave to the SPI controller + 0x3C + + + sd + Number of delay stages from slave to SPI controller + [4:0] + read-write + + + + + fmt + Frame format + 0x40 + + + proto + SPI protocol + [1:0] + read-write + + + endian + SPI endianness + [2:2] + read-write + + + dir + SPI I/O direction. This is reset to 1 for flash-enabled SPI controllers, 0 otherwise. + [3:3] + read-write + + + len + Number of bits per frame + [19:16] + read-write + + + + + txdata + Tx FIFO Data + 0x48 + + + data + Transmit data + [7:0] + read-write + + + full + FIFO full flag + [31:31] + read-only + + + + + rxdata + Rx FIFO data + 0x4C + + + data + Received data + [7:0] + read-only + + + empty + FIFO empty flag + [31:31] + read-write + + + + + txmark + Tx FIFO watermark + 0x50 + + + txmark + Transmit watermark. The reset value is 1 for flash-enabled controllers, 0 otherwise. + [2:0] + read-write + + + + + rxmark + Rx FIFO watermark + 0x54 + + + rxmark + Receive watermark + [2:0] + read-write + + + + + fctrl + SPI flash interface control + 0x60 + + + en + SPI Flash Mode Select + [0:0] + read-write + + + + + ffmt + SPI flash instruction format + 0x64 + + + cmd_en + Enable sending of command + [0:0] + read-write + + + addr_len + Number of address bytes (0 to 4) + [3:1] + read-write + + + pad_cnt + Number of dummy cycles + [7:4] + read-write + + + cmd_proto + Protocol for transmitting command + [9:8] + read-write + + + addr_proto + Protocol for transmitting address and padding + [11:10] + read-write + + + data_proto + Protocol for receiving data bytes + [13:12] + read-write + + + cmd_code + Value of command byte + [23:16] + read-write + + + pad_code + First 8 bits to transmit during dummy cycles + [31:24] + read-write + + + + + ie + SPI interrupt enable + 0x70 + + + txwm + Transmit watermark enable + [0:0] + read-write + + + rxwm + Receive watermark enable + [1:1] + read-write + + + + + ip + SPI interrupt pending + 0x74 + + + txwm + Transmit watermark pending + [0:0] + read-only + + + rxwm + Receive watermark pending + [1:1] + read-only + + + + + + + sifive_pwm0_1 + From sifive,pwm0,control peripheral generator + 0x10025000 + + 0 + 0x1000 + registers + + + + pwmcfg + PWM configuration register + 0x0 + + + pwmscale + PWM Counter scale + [3:0] + read-write + + + pwmsticky + PWM Sticky - disallow clearing pwmcmpXip bits + [8:8] + read-write + + + pwmzerocmp + PWM Zero - counter resets to zero after match + [9:9] + read-write + + + pwmdeglitch + PWM Deglitch - latch pwmcmpXip within same cycle + [10:10] + read-write + + + pwmenalways + PWM enable always - run continuously + [12:12] + read-write + + + pwmenoneshot + PWM enable one shot - run one cycle + [13:13] + read-write + + + pwmcmp0center + PWM0 Compare Center + [16:16] + read-write + + + pwmcmp1center + PWM1 Compare Center + [17:17] + read-write + + + pwmcmp2center + PWM2 Compare Center + [18:18] + read-write + + + pwmcmp3center + PWM3 Compare Center + [19:19] + read-write + + + pwmcmp0invert + PWM0 Invert + [20:20] + read-write + + + pwmcmp1invert + PWM1 Invert + [21:21] + read-write + + + pwmcmp2invert + PWM2 Invert + [22:22] + read-write + + + pwmcmp3invert + PWM3 Invert + [23:23] + read-write + + + pwmcmp0gang + PWM0/PWM1 Compare Gang + [24:24] + read-write + + + pwmcmp1gang + PWM1/PWM2 Compare Gang + [25:25] + read-write + + + pwmcmp2gang + PWM2/PWM3 Compare Gang + [26:26] + read-write + + + pwmcmp3gang + PWM3/PWM0 Compare Gang + [27:27] + read-write + + + pwmcmp0ip + PWM0 Interrupt Pending + [28:28] + read-write + + + pwmcmp1ip + PWM1 Interrupt Pending + [29:29] + read-write + + + pwmcmp2ip + PWM2 Interrupt Pending + [30:30] + read-write + + + pwmcmp3ip + PWM3 Interrupt Pending + [31:31] + read-write + + + + + pwmcount + PWM count register + 0x8 + + + pwmcount + PWM count register. + [30:0] + read-write + + + + + pwms + Scaled PWM count register + 0x10 + + + pwms + Scaled PWM count register. + [15:0] + read-write + + + + + pwmcmp0 + PWM 0 compare register + 0x20 + + + pwmcmp0 + PWM 0 Compare Value + [15:0] + read-write + + + + + pwmcmp1 + PWM 1 compare register + 0x24 + + + pwmcmp1 + PWM 1 Compare Value + [15:0] + read-write + + + + + pwmcmp2 + PWM 2 compare register + 0x28 + + + pwmcmp2 + PWM 2 Compare Value + [15:0] + read-write + + + + + pwmcmp3 + PWM 3 compare register + 0x2C + + + pwmcmp3 + PWM 3 Compare Value + [15:0] + read-write + + + + + + + sifive_spi0_2 + From sifive,spi0,control peripheral generator + 0x10034000 + + 0 + 0x1000 + registers + + + + sckdiv + Serial clock divisor + 0x0 + + + div + Divisor for serial clock. + [11:0] + read-write + + + + + sckmode + Serial clock mode + 0x4 + + + pha + Serial clock phase + [0:0] + read-write + + + pol + Serial clock polarity + [1:1] + read-write + + + + + csid + Chip select ID + 0x10 + + + csid + Chip select ID. + [31:0] + read-write + + + + + csdef + Chip select default + 0x14 + + + csdef + Chip select default value. Reset to all-1s. + [31:0] + read-write + + + + + csmode + Chip select mode + 0x18 + + + mode + Chip select mode + [1:0] + read-write + + + + + delay0 + Delay control 0 + 0x28 + + + cssck + CS to SCK Delay + [7:0] + read-write + + + sckcs + SCK to CS Delay + [23:16] + read-write + + + + + delay1 + Delay control 1 + 0x2C + + + intercs + Minimum CS inactive time + [7:0] + read-write + + + interxfr + Maximum interframe delay + [23:16] + read-write + + + + + extradel + SPI extra sampling delay to increase the SPI frequency + 0x38 + + + coarse + Coarse grain sample delay (multiples of system clocks) + [11:0] + read-write + + + fine + Fine grain sample delay (multiples of process-specific buffer delay) + [16:12] + read-write + + + + + sampledel + Number of delay stages from slave to the SPI controller + 0x3C + + + sd + Number of delay stages from slave to SPI controller + [4:0] + read-write + + + + + fmt + Frame format + 0x40 + + + proto + SPI protocol + [1:0] + read-write + + + endian + SPI endianness + [2:2] + read-write + + + dir + SPI I/O direction. This is reset to 1 for flash-enabled SPI controllers, 0 otherwise. + [3:3] + read-write + + + len + Number of bits per frame + [19:16] + read-write + + + + + txdata + Tx FIFO Data + 0x48 + + + data + Transmit data + [7:0] + read-write + + + full + FIFO full flag + [31:31] + read-only + + + + + rxdata + Rx FIFO data + 0x4C + + + data + Received data + [7:0] + read-only + + + empty + FIFO empty flag + [31:31] + read-write + + + + + txmark + Tx FIFO watermark + 0x50 + + + txmark + Transmit watermark. The reset value is 1 for flash-enabled controllers, 0 otherwise. + [2:0] + read-write + + + + + rxmark + Rx FIFO watermark + 0x54 + + + rxmark + Receive watermark + [2:0] + read-write + + + + + fctrl + SPI flash interface control + 0x60 + + + en + SPI Flash Mode Select + [0:0] + read-write + + + + + ffmt + SPI flash instruction format + 0x64 + + + cmd_en + Enable sending of command + [0:0] + read-write + + + addr_len + Number of address bytes (0 to 4) + [3:1] + read-write + + + pad_cnt + Number of dummy cycles + [7:4] + read-write + + + cmd_proto + Protocol for transmitting command + [9:8] + read-write + + + addr_proto + Protocol for transmitting address and padding + [11:10] + read-write + + + data_proto + Protocol for receiving data bytes + [13:12] + read-write + + + cmd_code + Value of command byte + [23:16] + read-write + + + pad_code + First 8 bits to transmit during dummy cycles + [31:24] + read-write + + + + + ie + SPI interrupt enable + 0x70 + + + txwm + Transmit watermark enable + [0:0] + read-write + + + rxwm + Receive watermark enable + [1:1] + read-write + + + + + ip + SPI interrupt pending + 0x74 + + + txwm + Transmit watermark pending + [0:0] + read-only + + + rxwm + Receive watermark pending + [1:1] + read-only + + + + + + + sifive_pwm0_2 + From sifive,pwm0,control peripheral generator + 0x10035000 + + 0 + 0x1000 + registers + + + + pwmcfg + PWM configuration register + 0x0 + + + pwmscale + PWM Counter scale + [3:0] + read-write + + + pwmsticky + PWM Sticky - disallow clearing pwmcmpXip bits + [8:8] + read-write + + + pwmzerocmp + PWM Zero - counter resets to zero after match + [9:9] + read-write + + + pwmdeglitch + PWM Deglitch - latch pwmcmpXip within same cycle + [10:10] + read-write + + + pwmenalways + PWM enable always - run continuously + [12:12] + read-write + + + pwmenoneshot + PWM enable one shot - run one cycle + [13:13] + read-write + + + pwmcmp0center + PWM0 Compare Center + [16:16] + read-write + + + pwmcmp1center + PWM1 Compare Center + [17:17] + read-write + + + pwmcmp2center + PWM2 Compare Center + [18:18] + read-write + + + pwmcmp3center + PWM3 Compare Center + [19:19] + read-write + + + pwmcmp0invert + PWM0 Invert + [20:20] + read-write + + + pwmcmp1invert + PWM1 Invert + [21:21] + read-write + + + pwmcmp2invert + PWM2 Invert + [22:22] + read-write + + + pwmcmp3invert + PWM3 Invert + [23:23] + read-write + + + pwmcmp0gang + PWM0/PWM1 Compare Gang + [24:24] + read-write + + + pwmcmp1gang + PWM1/PWM2 Compare Gang + [25:25] + read-write + + + pwmcmp2gang + PWM2/PWM3 Compare Gang + [26:26] + read-write + + + pwmcmp3gang + PWM3/PWM0 Compare Gang + [27:27] + read-write + + + pwmcmp0ip + PWM0 Interrupt Pending + [28:28] + read-write + + + pwmcmp1ip + PWM1 Interrupt Pending + [29:29] + read-write + + + pwmcmp2ip + PWM2 Interrupt Pending + [30:30] + read-write + + + pwmcmp3ip + PWM3 Interrupt Pending + [31:31] + read-write + + + + + pwmcount + PWM count register + 0x8 + + + pwmcount + PWM count register. + [30:0] + read-write + + + + + pwms + Scaled PWM count register + 0x10 + + + pwms + Scaled PWM count register. + [15:0] + read-write + + + + + pwmcmp0 + PWM 0 compare register + 0x20 + + + pwmcmp0 + PWM 0 Compare Value + [15:0] + read-write + + + + + pwmcmp1 + PWM 1 compare register + 0x24 + + + pwmcmp1 + PWM 1 Compare Value + [15:0] + read-write + + + + + pwmcmp2 + PWM 2 compare register + 0x28 + + + pwmcmp2 + PWM 2 Compare Value + [15:0] + read-write + + + + + pwmcmp3 + PWM 3 compare register + 0x2C + + + pwmcmp3 + PWM 3 Compare Value + [15:0] + read-write + + + + + + + \ No newline at end of file diff --git a/bsp/sparkfun-redv/metal-inline.h b/bsp/sparkfun-redv/metal-inline.h new file mode 100644 index 000000000..7933a9c4c --- /dev/null +++ b/bsp/sparkfun-redv/metal-inline.h @@ -0,0 +1,374 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +#ifndef ASSEMBLY + +#ifndef METAL_INLINE_H +#define METAL_INLINE_H + +#include + + +/* --------------------- fixed_clock ------------ */ +extern __inline__ unsigned long __metal_driver_fixed_clock_rate(const struct metal_clock *clock); + + +/* --------------------- fixed_factor_clock ------------ */ + + +/* --------------------- sifive_clint0 ------------ */ +extern __inline__ unsigned long __metal_driver_sifive_clint0_control_base(struct metal_interrupt *controller); +extern __inline__ unsigned long __metal_driver_sifive_clint0_control_size(struct metal_interrupt *controller); +extern __inline__ int __metal_driver_sifive_clint0_num_interrupts(struct metal_interrupt *controller); +extern __inline__ struct metal_interrupt * __metal_driver_sifive_clint0_interrupt_parents(struct metal_interrupt *controller, int idx); +extern __inline__ int __metal_driver_sifive_clint0_interrupt_lines(struct metal_interrupt *controller, int idx); + + +/* --------------------- cpu ------------ */ +extern __inline__ int __metal_driver_cpu_hartid(struct metal_cpu *cpu); +extern __inline__ int __metal_driver_cpu_timebase(struct metal_cpu *cpu); +extern __inline__ struct metal_interrupt * __metal_driver_cpu_interrupt_controller(struct metal_cpu *cpu); +extern __inline__ int __metal_driver_cpu_num_pmp_regions(struct metal_cpu *cpu); +extern __inline__ struct metal_buserror * __metal_driver_cpu_buserror(struct metal_cpu *cpu); + + +/* --------------------- sifive_plic0 ------------ */ +extern __inline__ unsigned long __metal_driver_sifive_plic0_control_base(struct metal_interrupt *controller); +extern __inline__ unsigned long __metal_driver_sifive_plic0_control_size(struct metal_interrupt *controller); +extern __inline__ int __metal_driver_sifive_plic0_num_interrupts(struct metal_interrupt *controller); +extern __inline__ int __metal_driver_sifive_plic0_max_priority(struct metal_interrupt *controller); +extern __inline__ struct metal_interrupt * __metal_driver_sifive_plic0_interrupt_parents(struct metal_interrupt *controller, int idx); +extern __inline__ int __metal_driver_sifive_plic0_interrupt_lines(struct metal_interrupt *controller, int idx); +extern __inline__ int __metal_driver_sifive_plic0_context_ids(int hartid); + + +/* --------------------- sifive_buserror0 ------------ */ + + +/* --------------------- sifive_clic0 ------------ */ + + +/* --------------------- sifive_local_external_interrupts0 ------------ */ + + +/* --------------------- sifive_global_external_interrupts0 ------------ */ + + +/* --------------------- sifive_gpio0 ------------ */ +extern __inline__ unsigned long __metal_driver_sifive_gpio0_base(struct metal_gpio *gpio); +extern __inline__ unsigned long __metal_driver_sifive_gpio0_size(struct metal_gpio *gpio); +extern __inline__ int __metal_driver_sifive_gpio0_num_interrupts(struct metal_gpio *gpio); +extern __inline__ struct metal_interrupt * __metal_driver_sifive_gpio0_interrupt_parent(struct metal_gpio *gpio); +extern __inline__ int __metal_driver_sifive_gpio0_interrupt_lines(struct metal_gpio *gpio, int idx); + + +/* --------------------- sifive_gpio_button ------------ */ + + +/* --------------------- sifive_gpio_led ------------ */ +extern __inline__ struct metal_gpio * __metal_driver_sifive_gpio_led_gpio(struct metal_led *led); +extern __inline__ int __metal_driver_sifive_gpio_led_pin(struct metal_led *led); +extern __inline__ char * __metal_driver_sifive_gpio_led_label(struct metal_led *led); + + +/* --------------------- sifive_gpio_switch ------------ */ + + +/* --------------------- sifive_i2c0 ------------ */ +extern __inline__ unsigned long __metal_driver_sifive_i2c0_control_base(struct metal_i2c *i2c); +extern __inline__ unsigned long __metal_driver_sifive_i2c0_control_size(struct metal_i2c *i2c); +extern __inline__ int __metal_driver_sifive_i2c0_num_interrupts(struct metal_i2c *i2c); +extern __inline__ struct metal_interrupt * __metal_driver_sifive_i2c0_interrupt_parent(struct metal_i2c *i2c); +extern __inline__ int __metal_driver_sifive_i2c0_interrupt_line(struct metal_i2c *i2c); +extern __inline__ struct metal_clock * __metal_driver_sifive_i2c0_clock(struct metal_i2c *i2c); +extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_i2c0_pinmux(struct metal_i2c *i2c); +extern __inline__ unsigned long __metal_driver_sifive_i2c0_pinmux_output_selector(struct metal_i2c *i2c); +extern __inline__ unsigned long __metal_driver_sifive_i2c0_pinmux_source_selector(struct metal_i2c *i2c); + + +/* --------------------- sifive_pwm0 ------------ */ +extern __inline__ unsigned long __metal_driver_sifive_pwm0_control_base(struct metal_pwm *pwm); +extern __inline__ unsigned long __metal_driver_sifive_pwm0_control_size(struct metal_pwm *pwm); +extern __inline__ int __metal_driver_sifive_pwm0_num_interrupts(struct metal_pwm *pwm); +extern __inline__ struct metal_interrupt * __metal_driver_sifive_pwm0_interrupt_parent(struct metal_pwm *pwm); +extern __inline__ int __metal_driver_sifive_pwm0_interrupt_lines(struct metal_pwm *pwm, int idx); +extern __inline__ struct metal_clock * __metal_driver_sifive_pwm0_clock(struct metal_pwm *pwm); +extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_pwm0_pinmux(struct metal_pwm *pwm); +extern __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_output_selector(struct metal_pwm *pwm); +extern __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_source_selector(struct metal_pwm *pwm); +extern __inline__ int __metal_driver_sifive_pwm0_compare_width(struct metal_pwm *pwm); +extern __inline__ int __metal_driver_sifive_pwm0_comparator_count(struct metal_pwm *pwm); + + +/* --------------------- sifive_rtc0 ------------ */ +extern __inline__ unsigned long __metal_driver_sifive_rtc0_control_base(const struct metal_rtc *const rtc); +extern __inline__ unsigned long __metal_driver_sifive_rtc0_control_size(const struct metal_rtc *const rtc); +extern __inline__ struct metal_interrupt * __metal_driver_sifive_rtc0_interrupt_parent(const struct metal_rtc *const rtc); +extern __inline__ int __metal_driver_sifive_rtc0_interrupt_line(const struct metal_rtc *const rtc); +extern __inline__ struct metal_clock * __metal_driver_sifive_rtc0_clock(const struct metal_rtc *const rtc); + + +/* --------------------- sifive_spi0 ------------ */ +extern __inline__ unsigned long __metal_driver_sifive_spi0_control_base(struct metal_spi *spi); +extern __inline__ unsigned long __metal_driver_sifive_spi0_control_size(struct metal_spi *spi); +extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_spi0_pinmux(struct metal_spi *spi); +extern __inline__ unsigned long __metal_driver_sifive_spi0_pinmux_output_selector(struct metal_spi *spi); +extern __inline__ unsigned long __metal_driver_sifive_spi0_pinmux_source_selector(struct metal_spi *spi); + + +/* --------------------- sifive_test0 ------------ */ + + +/* --------------------- sifive_trace ------------ */ + +/* --------------------- sifive_uart0 ------------ */ +extern __inline__ unsigned long __metal_driver_sifive_uart0_control_base(struct metal_uart *uart); +extern __inline__ unsigned long __metal_driver_sifive_uart0_control_size(struct metal_uart *uart); +extern __inline__ int __metal_driver_sifive_uart0_num_interrupts(struct metal_uart *uart); +extern __inline__ struct metal_interrupt * __metal_driver_sifive_uart0_interrupt_parent(struct metal_uart *uart); +extern __inline__ int __metal_driver_sifive_uart0_interrupt_line(struct metal_uart *uart); +extern __inline__ struct metal_clock * __metal_driver_sifive_uart0_clock(struct metal_uart *uart); +extern __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uart0_pinmux(struct metal_uart *uart); +extern __inline__ unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart); +extern __inline__ unsigned long __metal_driver_sifive_uart0_pinmux_source_selector(struct metal_uart *uart); + + +/* --------------------- sifive_simuart0 ------------ */ + + +/* --------------------- sifive_wdog0 ------------ */ +extern __inline__ unsigned long __metal_driver_sifive_wdog0_control_base(const struct metal_watchdog *const watchdog); +extern __inline__ unsigned long __metal_driver_sifive_wdog0_control_size(const struct metal_watchdog *const watchdog); +extern __inline__ struct metal_interrupt * __metal_driver_sifive_wdog0_interrupt_parent(const struct metal_watchdog *const watchdog); +extern __inline__ int __metal_driver_sifive_wdog0_interrupt_line(const struct metal_watchdog *const watchdog); +extern __inline__ struct metal_clock * __metal_driver_sifive_wdog0_clock(const struct metal_watchdog *const watchdog); + + +/* --------------------- sifive_fe310_g000_hfrosc ------------ */ +extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_hfrosc_ref(const struct metal_clock *clock); +extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_base(const struct metal_clock *clock); +extern __inline__ const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_vtable(struct metal_clock *clock); +extern __inline__ long __metal_driver_sifive_fe310_g000_hfrosc_config_offset(const struct metal_clock *clock); + + +/* --------------------- sifive_fe310_g000_hfxosc ------------ */ +extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_hfxosc_ref(const struct metal_clock *clock); +extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfxosc_config_base(const struct metal_clock *clock); +extern __inline__ long __metal_driver_sifive_fe310_g000_hfxosc_config_offset(const struct metal_clock *clock); + + +/* --------------------- sifive_fe310_g000_lfrosc ------------ */ +extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_lfrosc_lfrosc(const struct metal_clock *clock); +extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_lfrosc_psdlfaltclk(const struct metal_clock *clock); +extern __inline__ unsigned long int __metal_driver_sifive_fe310_g000_lfrosc_config_reg(const struct metal_clock *clock); +extern __inline__ unsigned long int __metal_driver_sifive_fe310_g000_lfrosc_mux_reg(const struct metal_clock *clock); + + +/* --------------------- sifive_fe310_g000_pll ------------ */ +extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllsel0(const struct metal_clock *clock); +extern __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllref(const struct metal_clock *clock); +extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_config_base( ); +extern __inline__ long __metal_driver_sifive_fe310_g000_pll_config_offset( ); +extern __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_divider_base(const struct metal_clock *clock); +extern __inline__ long __metal_driver_sifive_fe310_g000_pll_divider_offset(const struct metal_clock *clock); +extern __inline__ long __metal_driver_sifive_fe310_g000_pll_init_rate( ); + + +/* --------------------- fe310_g000_prci ------------ */ +extern __inline__ long __metal_driver_sifive_fe310_g000_prci_base( ); +extern __inline__ long __metal_driver_sifive_fe310_g000_prci_size( ); +extern __inline__ const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_prci_vtable( ); + + +/* From clock@0 */ +struct __metal_driver_fixed_clock __metal_dt_clock_0 = { + .clock.vtable = &__metal_driver_vtable_fixed_clock.clock, +}; + +/* From clock@2 */ +struct __metal_driver_fixed_clock __metal_dt_clock_2 = { + .clock.vtable = &__metal_driver_vtable_fixed_clock.clock, +}; + +/* From clock@5 */ +struct __metal_driver_fixed_clock __metal_dt_clock_5 = { + .clock.vtable = &__metal_driver_vtable_fixed_clock.clock, +}; + +/* From clock@6 */ +struct __metal_driver_fixed_clock __metal_dt_clock_6 = { + .clock.vtable = &__metal_driver_vtable_fixed_clock.clock, +}; + +struct metal_memory __metal_dt_mem_dtim_80000000 = { + ._base_address = 2147483648UL, + ._size = 16384UL, + ._attrs = { + .R = 1, + .W = 1, + .X = 1, + .C = 1, + .A = 1}, +}; + +struct metal_memory __metal_dt_mem_itim_8000000 = { + ._base_address = 134217728UL, + ._size = 8192UL, + ._attrs = { + .R = 1, + .W = 1, + .X = 1, + .C = 1, + .A = 1}, +}; + +struct metal_memory __metal_dt_mem_spi_10014000 = { + ._base_address = 536870912UL, + ._size = 500000UL, + ._attrs = { + .R = 1, + .W = 1, + .X = 1, + .C = 1, + .A = 1}, +}; + +struct metal_memory __metal_dt_mem_spi_10024000 = { + ._attrs = { + .R = 1, + .W = 1, + .X = 1, + .C = 1, + .A = 1}, +}; + +struct metal_memory __metal_dt_mem_spi_10034000 = { + ._attrs = { + .R = 1, + .W = 1, + .X = 1, + .C = 1, + .A = 1}, +}; + +/* From clint@2000000 */ +struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000 = { + .controller.vtable = &__metal_driver_vtable_riscv_clint0.clint_vtable, + .init_done = 0, +}; + +/* From cpu@0 */ +struct __metal_driver_cpu __metal_dt_cpu_0 = { + .cpu.vtable = &__metal_driver_vtable_cpu.cpu_vtable, + .hpm_count = 0, +}; + +/* From interrupt_controller */ +struct __metal_driver_riscv_cpu_intc __metal_dt_cpu_0_interrupt_controller = { + .controller.vtable = &__metal_driver_vtable_riscv_cpu_intc.controller_vtable, + .init_done = 0, +}; + +/* From interrupt_controller@c000000 */ +struct __metal_driver_riscv_plic0 __metal_dt_interrupt_controller_c000000 = { + .controller.vtable = &__metal_driver_vtable_riscv_plic0.plic_vtable, + .init_done = 0, +}; + +struct metal_pmp __metal_dt_pmp; + +/* From gpio@10012000 */ +struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000 = { + .gpio.vtable = &__metal_driver_vtable_sifive_gpio0.gpio, +}; + +/* From led@0 */ +struct __metal_driver_sifive_gpio_led __metal_dt_led_0 = { + .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable, +}; + +/* From i2c@10016000 */ +struct __metal_driver_sifive_i2c0 __metal_dt_i2c_10016000 = { + .i2c.vtable = &__metal_driver_vtable_sifive_i2c0.i2c, +}; + +/* From pwm@10015000 */ +struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10015000 = { + .pwm.vtable = &__metal_driver_vtable_sifive_pwm0.pwm, +}; + +/* From pwm@10025000 */ +struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10025000 = { + .pwm.vtable = &__metal_driver_vtable_sifive_pwm0.pwm, +}; + +/* From pwm@10035000 */ +struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10035000 = { + .pwm.vtable = &__metal_driver_vtable_sifive_pwm0.pwm, +}; + +/* From aon@10000000 */ +struct __metal_driver_sifive_rtc0 __metal_dt_rtc_10000000 = { + .rtc.vtable = &__metal_driver_vtable_sifive_rtc0.rtc, +}; + +/* From spi@10014000 */ +struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000 = { + .spi.vtable = &__metal_driver_vtable_sifive_spi0.spi, +}; + +/* From spi@10024000 */ +struct __metal_driver_sifive_spi0 __metal_dt_spi_10024000 = { + .spi.vtable = &__metal_driver_vtable_sifive_spi0.spi, +}; + +/* From spi@10034000 */ +struct __metal_driver_sifive_spi0 __metal_dt_spi_10034000 = { + .spi.vtable = &__metal_driver_vtable_sifive_spi0.spi, +}; + +/* From serial@10013000 */ +struct __metal_driver_sifive_uart0 __metal_dt_serial_10013000 = { + .uart.vtable = &__metal_driver_vtable_sifive_uart0.uart, +}; + +/* From serial@10023000 */ +struct __metal_driver_sifive_uart0 __metal_dt_serial_10023000 = { + .uart.vtable = &__metal_driver_vtable_sifive_uart0.uart, +}; + +/* From aon@10000000 */ +struct __metal_driver_sifive_wdog0 __metal_dt_aon_10000000 = { + .watchdog.vtable = &__metal_driver_vtable_sifive_wdog0.watchdog, +}; + +/* From clock@3 */ +struct __metal_driver_sifive_fe310_g000_hfrosc __metal_dt_clock_3 = { + .clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_hfrosc.clock, +}; + +/* From clock@1 */ +struct __metal_driver_sifive_fe310_g000_hfxosc __metal_dt_clock_1 = { + .clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_hfxosc.clock, +}; + +/* From clock@7 */ +struct __metal_driver_sifive_fe310_g000_lfrosc __metal_dt_clock_7 = { + .clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_lfrosc.clock, +}; + +/* From clock@4 */ +struct __metal_driver_sifive_fe310_g000_pll __metal_dt_clock_4 = { + .clock.vtable = &__metal_driver_vtable_sifive_fe310_g000_pll.clock, +}; + +/* From prci@10008000 */ +struct __metal_driver_sifive_fe310_g000_prci __metal_dt_prci_10008000 = { + .vtable = &__metal_driver_vtable_sifive_fe310_g000_prci, +}; + + +#endif /* METAL_INLINE_H*/ +#endif /* ! ASSEMBLY */ diff --git a/bsp/sparkfun-redv/metal-platform.h b/bsp/sparkfun-redv/metal-platform.h new file mode 100644 index 000000000..6ac626004 --- /dev/null +++ b/bsp/sparkfun-redv/metal-platform.h @@ -0,0 +1,298 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +#ifndef METAL_PLATFORM_H +#define METAL_PLATFORM_H + +/* From clock@0 */ +#define METAL_FIXED_CLOCK_0_CLOCK_FREQUENCY 16000000UL + +/* From clock@2 */ +#define METAL_FIXED_CLOCK_2_CLOCK_FREQUENCY 72000000UL + +/* From clock@5 */ +#define METAL_FIXED_CLOCK_5_CLOCK_FREQUENCY 32768UL + +/* From clock@6 */ +#define METAL_FIXED_CLOCK_6_CLOCK_FREQUENCY 32768UL + +#define METAL_FIXED_CLOCK + +/* From clint@2000000 */ +#define METAL_RISCV_CLINT0_2000000_BASE_ADDRESS 33554432UL +#define METAL_RISCV_CLINT0_0_BASE_ADDRESS 33554432UL +#define METAL_RISCV_CLINT0_2000000_SIZE 65536UL +#define METAL_RISCV_CLINT0_0_SIZE 65536UL + +#define METAL_RISCV_CLINT0 +#define METAL_RISCV_CLINT0_MSIP_BASE 0UL +#define METAL_RISCV_CLINT0_MTIMECMP_BASE 16384UL +#define METAL_RISCV_CLINT0_MTIME 49144UL + +/* From interrupt_controller@c000000 */ +#define METAL_RISCV_PLIC0_C000000_BASE_ADDRESS 201326592UL +#define METAL_RISCV_PLIC0_0_BASE_ADDRESS 201326592UL +#define METAL_RISCV_PLIC0_C000000_SIZE 67108864UL +#define METAL_RISCV_PLIC0_0_SIZE 67108864UL +#define METAL_RISCV_PLIC0_C000000_RISCV_MAX_PRIORITY 7UL +#define METAL_RISCV_PLIC0_0_RISCV_MAX_PRIORITY 7UL +#define METAL_RISCV_PLIC0_C000000_RISCV_NDEV 53UL +#define METAL_RISCV_PLIC0_0_RISCV_NDEV 53UL + +#define METAL_RISCV_PLIC0 +#define METAL_RISCV_PLIC0_PRIORITY_BASE 0UL +#define METAL_RISCV_PLIC0_PENDING_BASE 4096UL +#define METAL_RISCV_PLIC0_ENABLE_BASE 8192UL +#define METAL_RISCV_PLIC0_ENABLE_PER_HART 128UL +#define METAL_RISCV_PLIC0_CONTEXT_BASE 2097152UL +#define METAL_RISCV_PLIC0_CONTEXT_PER_HART 4096UL +#define METAL_RISCV_PLIC0_CONTEXT_THRESHOLD 0UL +#define METAL_RISCV_PLIC0_CONTEXT_CLAIM 4UL + +/* From aon@10000000 */ +#define METAL_SIFIVE_AON0_10000000_BASE_ADDRESS 268435456UL +#define METAL_SIFIVE_AON0_0_BASE_ADDRESS 268435456UL +#define METAL_SIFIVE_AON0_10000000_SIZE 32768UL +#define METAL_SIFIVE_AON0_0_SIZE 32768UL + +#define METAL_SIFIVE_AON0 +#define METAL_SIFIVE_AON0_WDOGCFG 0UL +#define METAL_SIFIVE_AON0_WDOGCOUNT 8UL +#define METAL_SIFIVE_AON0_WDOGS 16UL +#define METAL_SIFIVE_AON0_WDOGFEED 24UL +#define METAL_SIFIVE_AON0_WDOGKEY 28UL +#define METAL_SIFIVE_AON0_WDOGCMP 32UL +#define METAL_SIFIVE_AON0_RTCCFG 64UL +#define METAL_SIFIVE_AON0_RTCLO 72UL +#define METAL_SIFIVE_AON0_RTCHI 72UL +#define METAL_SIFIVE_AON0_RTCS 80UL +#define METAL_SIFIVE_AON0_RTCCMP 96UL +#define METAL_SIFIVE_AON0_LFROSCCFG 112UL +#define METAL_SIFIVE_AON0_BACKUP0 128UL +#define METAL_SIFIVE_AON0_BACKUP1 132UL +#define METAL_SIFIVE_AON0_BACKUP2 136UL +#define METAL_SIFIVE_AON0_BACKUP3 140UL +#define METAL_SIFIVE_AON0_BACKUP4 144UL +#define METAL_SIFIVE_AON0_BACKUP5 148UL +#define METAL_SIFIVE_AON0_BACKUP6 152UL +#define METAL_SIFIVE_AON0_BACKUP7 152UL +#define METAL_SIFIVE_AON0_BACKUP8 160UL +#define METAL_SIFIVE_AON0_BACKUP9 164UL +#define METAL_SIFIVE_AON0_BACKUP10 168UL +#define METAL_SIFIVE_AON0_BACKUP11 172UL +#define METAL_SIFIVE_AON0_BACKUP12 176UL +#define METAL_SIFIVE_AON0_BACKUP13 180UL +#define METAL_SIFIVE_AON0_BACKUP14 184UL +#define METAL_SIFIVE_AON0_BACKUP15 188UL +#define METAL_SIFIVE_AON0_BACKUP16 192UL +#define METAL_SIFIVE_AON0_BACKUP17 196UL +#define METAL_SIFIVE_AON0_BACKUP18 200UL +#define METAL_SIFIVE_AON0_BACKUP19 204UL +#define METAL_SIFIVE_AON0_BACKUP20 208UL +#define METAL_SIFIVE_AON0_BACKUP21 212UL +#define METAL_SIFIVE_AON0_BACKUP22 216UL +#define METAL_SIFIVE_AON0_BACKUP23 220UL +#define METAL_SIFIVE_AON0_BACKUP24 224UL +#define METAL_SIFIVE_AON0_BACKUP25 228UL +#define METAL_SIFIVE_AON0_BACKUP26 232UL +#define METAL_SIFIVE_AON0_BACKUP27 236UL +#define METAL_SIFIVE_AON0_BACKUP28 240UL +#define METAL_SIFIVE_AON0_BACKUP29 244UL +#define METAL_SIFIVE_AON0_BACKUP30 248UL +#define METAL_SIFIVE_AON0_BACKUP31 252UL +#define METAL_SIFIVE_AON0_PMU_WAKEUP_BASE 256UL +#define METAL_SIFIVE_AON0_PWM_SLEEP_BASE 288UL +#define METAL_SIFIVE_AON0_PMUIE 320UL +#define METAL_SIFIVE_AON0_PMUCAUSE 324UL +#define METAL_SIFIVE_AON0_PMUSLEEP 328UL +#define METAL_SIFIVE_AON0_PMUKEY 332UL + +/* From clock@3 */ + +#define METAL_SIFIVE_FE310_G000_HFROSC + +/* From clock@1 */ + +#define METAL_SIFIVE_FE310_G000_HFXOSC + +/* From clock@7 */ + +#define METAL_SIFIVE_FE310_G000_LFROSC + +/* From prci@10008000 */ +#define METAL_SIFIVE_FE310_G000_PRCI_10008000_BASE_ADDRESS 268468224UL +#define METAL_SIFIVE_FE310_G000_PRCI_0_BASE_ADDRESS 268468224UL +#define METAL_SIFIVE_FE310_G000_PRCI_10008000_SIZE 32768UL +#define METAL_SIFIVE_FE310_G000_PRCI_0_SIZE 32768UL + +#define METAL_SIFIVE_FE310_G000_PRCI +#define METAL_SIFIVE_FE310_G000_PRCI_HFROSCCFG 0UL +#define METAL_SIFIVE_FE310_G000_PRCI_HFXOSCCFG 4UL +#define METAL_SIFIVE_FE310_G000_PRCI_PLLCFG 8UL +#define METAL_SIFIVE_FE310_G000_PRCI_PLLOUTDIV 12UL + +/* From clock@4 */ +#define METAL_SIFIVE_FE310_G000_PLL_4_CLOCK_FREQUENCY 16000000UL + +#define METAL_SIFIVE_FE310_G000_PLL + +/* From gpio@10012000 */ +#define METAL_SIFIVE_GPIO0_10012000_BASE_ADDRESS 268509184UL +#define METAL_SIFIVE_GPIO0_0_BASE_ADDRESS 268509184UL +#define METAL_SIFIVE_GPIO0_10012000_SIZE 4096UL +#define METAL_SIFIVE_GPIO0_0_SIZE 4096UL + +#define METAL_SIFIVE_GPIO0 +#define METAL_SIFIVE_GPIO0_VALUE 0UL +#define METAL_SIFIVE_GPIO0_INPUT_EN 4UL +#define METAL_SIFIVE_GPIO0_OUTPUT_EN 8UL +#define METAL_SIFIVE_GPIO0_PORT 12UL +#define METAL_SIFIVE_GPIO0_PUE 16UL +#define METAL_SIFIVE_GPIO0_DS 20UL +#define METAL_SIFIVE_GPIO0_RISE_IE 24UL +#define METAL_SIFIVE_GPIO0_RISE_IP 28UL +#define METAL_SIFIVE_GPIO0_FALL_IE 32UL +#define METAL_SIFIVE_GPIO0_FALL_IP 36UL +#define METAL_SIFIVE_GPIO0_HIGH_IE 40UL +#define METAL_SIFIVE_GPIO0_HIGH_IP 44UL +#define METAL_SIFIVE_GPIO0_LOW_IE 48UL +#define METAL_SIFIVE_GPIO0_LOW_IP 52UL +#define METAL_SIFIVE_GPIO0_IOF_EN 56UL +#define METAL_SIFIVE_GPIO0_IOF_SEL 60UL +#define METAL_SIFIVE_GPIO0_OUT_XOR 64UL + +/* From led@0 */ + +#define METAL_SIFIVE_GPIO_LEDS + +/* From i2c@10016000 */ +#define METAL_SIFIVE_I2C0_10016000_BASE_ADDRESS 268525568UL +#define METAL_SIFIVE_I2C0_0_BASE_ADDRESS 268525568UL +#define METAL_SIFIVE_I2C0_10016000_SIZE 4096UL +#define METAL_SIFIVE_I2C0_0_SIZE 4096UL + +#define METAL_SIFIVE_I2C0 +#define METAL_SIFIVE_I2C0_PRESCALE_LOW 0UL +#define METAL_SIFIVE_I2C0_PRESCALE_HIGH 4UL +#define METAL_SIFIVE_I2C0_CONTROL 8UL +#define METAL_SIFIVE_I2C0_TRANSMIT 12UL +#define METAL_SIFIVE_I2C0_RECEIVE 12UL +#define METAL_SIFIVE_I2C0_COMMAND 16UL +#define METAL_SIFIVE_I2C0_STATUS 16UL + +/* From pwm@10015000 */ +#define METAL_SIFIVE_PWM0_10015000_BASE_ADDRESS 268521472UL +#define METAL_SIFIVE_PWM0_0_BASE_ADDRESS 268521472UL +#define METAL_SIFIVE_PWM0_10015000_SIZE 4096UL +#define METAL_SIFIVE_PWM0_0_SIZE 4096UL + +/* From pwm@10025000 */ +#define METAL_SIFIVE_PWM0_10025000_BASE_ADDRESS 268587008UL +#define METAL_SIFIVE_PWM0_1_BASE_ADDRESS 268587008UL +#define METAL_SIFIVE_PWM0_10025000_SIZE 4096UL +#define METAL_SIFIVE_PWM0_1_SIZE 4096UL + +/* From pwm@10035000 */ +#define METAL_SIFIVE_PWM0_10035000_BASE_ADDRESS 268652544UL +#define METAL_SIFIVE_PWM0_2_BASE_ADDRESS 268652544UL +#define METAL_SIFIVE_PWM0_10035000_SIZE 4096UL +#define METAL_SIFIVE_PWM0_2_SIZE 4096UL + +#define METAL_SIFIVE_PWM0 +#define METAL_SIFIVE_PWM0_PWMCFG 0UL +#define METAL_SIFIVE_PWM0_PWMCOUNT 8UL +#define METAL_SIFIVE_PWM0_PWMS 16UL +#define METAL_SIFIVE_PWM0_PWMCMP0 32UL +#define METAL_SIFIVE_PWM0_PWMCMP1 36UL +#define METAL_SIFIVE_PWM0_PWMCMP2 40UL +#define METAL_SIFIVE_PWM0_PWMCMP3 44UL + +/* From aon@10000000 */ +#define METAL_SIFIVE_AON0_10000000_BASE_ADDRESS 268435456UL +#define METAL_SIFIVE_AON0_0_BASE_ADDRESS 268435456UL +#define METAL_SIFIVE_AON0_10000000_SIZE 32768UL +#define METAL_SIFIVE_AON0_0_SIZE 32768UL + +#define METAL_SIFIVE_RTC0 +#define METAL_SIFIVE_RTC0_RTCCFG 64UL +#define METAL_SIFIVE_RTC0_RTCCOUNTLO 72UL +#define METAL_SIFIVE_RTC0_RTCCOUNTHI 76UL +#define METAL_SIFIVE_RTC0_RTCS 80UL +#define METAL_SIFIVE_RTC0_RTCCMP0 96UL + +/* From spi@10014000 */ +#define METAL_SIFIVE_SPI0_10014000_BASE_ADDRESS 268517376UL +#define METAL_SIFIVE_SPI0_0_BASE_ADDRESS 268517376UL +#define METAL_SIFIVE_SPI0_10014000_SIZE 4096UL +#define METAL_SIFIVE_SPI0_0_SIZE 4096UL + +/* From spi@10024000 */ +#define METAL_SIFIVE_SPI0_10024000_BASE_ADDRESS 268582912UL +#define METAL_SIFIVE_SPI0_1_BASE_ADDRESS 268582912UL +#define METAL_SIFIVE_SPI0_10024000_SIZE 4096UL +#define METAL_SIFIVE_SPI0_1_SIZE 4096UL + +/* From spi@10034000 */ +#define METAL_SIFIVE_SPI0_10034000_BASE_ADDRESS 268648448UL +#define METAL_SIFIVE_SPI0_2_BASE_ADDRESS 268648448UL +#define METAL_SIFIVE_SPI0_10034000_SIZE 4096UL +#define METAL_SIFIVE_SPI0_2_SIZE 4096UL + +#define METAL_SIFIVE_SPI0 +#define METAL_SIFIVE_SPI0_SCKDIV 0UL +#define METAL_SIFIVE_SPI0_SCKMODE 4UL +#define METAL_SIFIVE_SPI0_CSID 16UL +#define METAL_SIFIVE_SPI0_CSDEF 20UL +#define METAL_SIFIVE_SPI0_CSMODE 24UL +#define METAL_SIFIVE_SPI0_DELAY0 40UL +#define METAL_SIFIVE_SPI0_DELAY1 44UL +#define METAL_SIFIVE_SPI0_FMT 64UL +#define METAL_SIFIVE_SPI0_TXDATA 72UL +#define METAL_SIFIVE_SPI0_RXDATA 76UL +#define METAL_SIFIVE_SPI0_TXMARK 80UL +#define METAL_SIFIVE_SPI0_RXMARK 84UL +#define METAL_SIFIVE_SPI0_FCTRL 96UL +#define METAL_SIFIVE_SPI0_FFMT 100UL +#define METAL_SIFIVE_SPI0_IE 112UL +#define METAL_SIFIVE_SPI0_IP 116UL + +/* From serial@10013000 */ +#define METAL_SIFIVE_UART0_10013000_BASE_ADDRESS 268513280UL +#define METAL_SIFIVE_UART0_0_BASE_ADDRESS 268513280UL +#define METAL_SIFIVE_UART0_10013000_SIZE 4096UL +#define METAL_SIFIVE_UART0_0_SIZE 4096UL + +/* From serial@10023000 */ +#define METAL_SIFIVE_UART0_10023000_BASE_ADDRESS 268578816UL +#define METAL_SIFIVE_UART0_1_BASE_ADDRESS 268578816UL +#define METAL_SIFIVE_UART0_10023000_SIZE 4096UL +#define METAL_SIFIVE_UART0_1_SIZE 4096UL + +#define METAL_SIFIVE_UART0 +#define METAL_SIFIVE_UART0_TXDATA 0UL +#define METAL_SIFIVE_UART0_RXDATA 4UL +#define METAL_SIFIVE_UART0_TXCTRL 8UL +#define METAL_SIFIVE_UART0_RXCTRL 12UL +#define METAL_SIFIVE_UART0_IE 16UL +#define METAL_SIFIVE_UART0_IP 20UL +#define METAL_SIFIVE_UART0_DIV 24UL + +/* From aon@10000000 */ +#define METAL_SIFIVE_AON0_10000000_BASE_ADDRESS 268435456UL +#define METAL_SIFIVE_AON0_0_BASE_ADDRESS 268435456UL +#define METAL_SIFIVE_AON0_10000000_SIZE 32768UL +#define METAL_SIFIVE_AON0_0_SIZE 32768UL + +#define METAL_SIFIVE_WDOG0 +#define METAL_SIFIVE_WDOG0_MAGIC_KEY 5370206UL +#define METAL_SIFIVE_WDOG0_MAGIC_FOOD 218755085UL +#define METAL_SIFIVE_WDOG0_WDOGCFG 0UL +#define METAL_SIFIVE_WDOG0_WDOGCOUNT 8UL +#define METAL_SIFIVE_WDOG0_WDOGS 16UL +#define METAL_SIFIVE_WDOG0_WDOGFEED 24UL +#define METAL_SIFIVE_WDOG0_WDOGKEY 28UL +#define METAL_SIFIVE_WDOG0_WDOGCMP 32UL + +#endif /* METAL_PLATFORM_H*/ diff --git a/bsp/sparkfun-redv/metal.default.lds b/bsp/sparkfun-redv/metal.default.lds new file mode 100644 index 000000000..094dcb61e --- /dev/null +++ b/bsp/sparkfun-redv/metal.default.lds @@ -0,0 +1,301 @@ +/* Copyright (c) 2020 SiFive Inc. */ +/* SPDX-License-Identifier: Apache-2.0 */ +OUTPUT_ARCH("riscv") + +/* Default Linker Script + * + * This is the default linker script for all Freedom Metal applications. + */ + +ENTRY(_enter) + +MEMORY +{ + itim (airwx) : ORIGIN = 0x8000000, LENGTH = 0x2000 + ram (arw!xi) : ORIGIN = 0x80000000, LENGTH = 0x4000 + rom (irx!wa) : ORIGIN = 0x20010000, LENGTH = 0x6a120 +} + +PHDRS +{ + rom PT_LOAD; + ram_init PT_LOAD; + tls PT_TLS; + ram PT_LOAD; + itim_init PT_LOAD; + text PT_LOAD; + lim_init PT_LOAD; +} + +SECTIONS +{ + /* Each hart is allocated its own stack of size __stack_size. This value + * can be overriden at build-time by adding the following to CFLAGS: + * + * -Xlinker --defsym=__stack_size=0xf00 + * + * where 0xf00 can be replaced with a multiple of 16 of your choice. + * + * __stack_size is PROVIDE-ed as a symbol so that initialization code + * initializes the stack pointers for each hart at the right offset from + * the _sp symbol. + */ + __stack_size = DEFINED(__stack_size) ? __stack_size : 0x400; + PROVIDE(__stack_size = __stack_size); + + /* The size of the heap can be overriden at build-time by adding the + * following to CFLAGS: + * + * -Xlinker --defsym=__heap_size=0xf00 + * + * where 0xf00 can be replaced with the value of your choice. + * + * Altertatively, the heap can be grown to fill the entire remaining region + * of RAM by adding the following to CFLAGS: + * + * -Xlinker --defsym=__heap_max=1 + * + * Note that depending on the memory layout, the bitness (32/64bit) of the + * target, and the code model in use, this might cause a relocation error. + */ + __heap_size = DEFINED(__heap_size) ? __heap_size : 0x800; + + /* The boot hart sets which hart runs the pre-main initialization routines, + * including copying .data into RAM, zeroing the BSS region, running + * constructors, etc. After initialization, the boot hart is also the only + * hart which runs application code unless the application overrides the + * secondary_main() function to start execution on secondary harts. + */ + PROVIDE(__metal_boot_hart = 0); + + /* The chicken bit is used by pre-main initialization to enable/disable + * certain core features */ + PROVIDE(__metal_chicken_bit = 1); + + /* The memory_ecc_scrub bit is used by _entry code to enable/disable + * memories scrubbing to zero */ + PROVIDE(__metal_eccscrub_bit = 0); + + /* The RAM memories map for ECC scrubbing */ + PROVIDE( metal_dtim_0_memory_start = 0x80000000 ); + PROVIDE( metal_dtim_0_memory_end = 0x80000000 + 0x4000 ); + PROVIDE( metal_itim_0_memory_start = 0x8000000 ); + PROVIDE( metal_itim_0_memory_end = 0x8000000 + 0x2000 ); + + /* ROM SECTION + * + * The following sections contain data which lives in read-only memory, if + * such memory is present in the design, for the entire duration of program + * execution. + */ + + .init : { + /* The _enter symbol is placed in the .text.metal.init.enter section + * and must be placed at the beginning of the program */ + KEEP (*(.text.metal.init.enter)) + KEEP (*(.text.metal.init.*)) + KEEP (*(SORT_NONE(.init))) + KEEP (*(.text.libgloss.start)) + } >rom :rom + + .fini : { + KEEP (*(SORT_NONE(.fini))) + } >rom :rom + + .preinit_array : ALIGN(8) { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >rom :rom + + .init_array : ALIGN(8) { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE_HIDDEN ( metal_constructors_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.metal.init_array.*))); + KEEP (*(.metal.init_array)); + PROVIDE_HIDDEN ( metal_constructors_end = .); + } >rom :rom + + .fini_array : ALIGN(8) { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + PROVIDE_HIDDEN ( metal_destructors_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.metal.fini_array.*))); + KEEP (*(.metal.fini_array)); + PROVIDE_HIDDEN ( metal_destructors_end = .); + } >rom :rom + + + + .ctors : { + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*(.metal.ctors .metal.ctors.*)) + } >rom :rom + + .dtors : { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + KEEP (*(.metal.dtors .metal.dtors.*)) + } >rom : rom + + .rodata : { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >rom :rom + + /* ITIM SECTION + * + * The following sections contain data which is copied from read-only + * memory into an instruction tightly-integrated memory (ITIM), if one + * is present in the design, during pre-main program initialization. + * + * Generally, the data copied into the ITIM should be performance-critical + * functions which benefit from low instruction-fetch latency. + */ + + .itim : ALIGN(8) { + *(.itim .itim.*) + } >itim AT>rom :itim_init + + PROVIDE( metal_segment_itim_source_start = LOADADDR(.itim) ); + PROVIDE( metal_segment_itim_target_start = ADDR(.itim) ); + PROVIDE( metal_segment_itim_target_end = ADDR(.itim) + SIZEOF(.itim) ); + + /* LIM SECTION + * + * The following sections contain data which is copied from read-only + * memory into a loosely integrated memory (LIM), which is shared with L2 + * cache, during pre-main program initialization. + * + * Generally, the data copied into the LIM should be performance-critical + * functions which benefit from low instruction-fetch latency. + */ + + .lim : ALIGN(8) { + *(.lim .lim.*) + } >ram AT>rom :lim_init + + PROVIDE( metal_segment_lim_source_start = LOADADDR(.lim) ); + PROVIDE( metal_segment_lim_target_start = ADDR(.lim) ); + PROVIDE( metal_segment_lim_target_end = ADDR(.lim) + SIZEOF(.lim) ); + + /* TEXT SECTION + * + * The following section contains the code of the program, excluding + * everything that's been allocated into the ITIM/LIM already + */ + + .text : { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >rom :text + + /* RAM SECTION + * + * The following sections contain data which is copied from read-only + * memory into a read-write-capable memory such as data tightly-integrated + * memory (DTIM) or another main memory, as well as the BSS, stack, and + * heap. + * + * You might notice that .data, .tdata, .tbss, .tbss_space, and .bss all + * have an apparently unnecessary ALIGN at their top. This is because + * the implementation of _start in Freedom Metal libgloss depends on the + * ADDR and LOADADDR being 8-byte aligned. + */ + + .data : ALIGN(8) { + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.* .sdata2.*) + *(.gnu.linkonce.s.*) + } >ram AT>rom :ram_init + + .tdata : ALIGN(8) { + PROVIDE( __tls_base = . ); + *(.tdata .tdata.* .gnu.linkonce.td.*) + } >ram AT>rom :tls :ram_init + + PROVIDE( __tdata_source = LOADADDR(.tdata) ); + PROVIDE( __tdata_size = SIZEOF(.tdata) ); + + PROVIDE( metal_segment_data_source_start = LOADADDR(.data) ); + PROVIDE( metal_segment_data_target_start = ADDR(.data) ); + PROVIDE( metal_segment_data_target_end = ADDR(.tdata) + SIZEOF(.tdata) ); + + .tbss : ALIGN(8) { + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + PROVIDE( __tls_end = . ); + } >ram AT>ram :tls :ram + PROVIDE( __tbss_size = SIZEOF(.tbss) ); + PROVIDE( __tls_size = __tls_end - __tls_base ); + + .tbss_space : ALIGN(8) { + . = . + __tbss_size; + } >ram :ram + + .bss (NOLOAD): ALIGN(8) { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } >ram :ram + + PROVIDE( metal_segment_bss_source_start = LOADADDR(.tbss) ); + PROVIDE( metal_segment_bss_target_start = ADDR(.tbss) ); + PROVIDE( metal_segment_bss_target_end = ADDR(.bss) + SIZEOF(.bss) ); + + + + .stack (NOLOAD) : ALIGN(16) { + PROVIDE(metal_segment_stack_begin = .); + . += __stack_size; /* Hart 0 */ + PROVIDE( _sp = . ); + PROVIDE(metal_segment_stack_end = .); + } >ram :ram + + .heap (NOLOAD) : ALIGN(8) { + PROVIDE( __end = . ); + PROVIDE( __heap_start = . ); + PROVIDE( metal_segment_heap_target_start = . ); + /* If __heap_max is defined, grow the heap to use the rest of RAM, + * otherwise set the heap size to __heap_size */ + . = DEFINED(__heap_max) ? MIN( LENGTH(ram) - ( . - ORIGIN(ram)) , 0x10000000) : __heap_size; + PROVIDE( metal_segment_heap_target_end = . ); + PROVIDE( _heap_end = . ); + PROVIDE( __heap_end = . ); + } >ram :ram + + /* C++ exception handling information is + * not useful with our current runtime environment, + * and it consumes flash space. Discard it until + * we have something that can use it + */ + /DISCARD/ : { + *(.eh_frame .eh_frame.*) + } +} \ No newline at end of file diff --git a/bsp/sparkfun-redv/metal.freertos.lds b/bsp/sparkfun-redv/metal.freertos.lds new file mode 100644 index 000000000..4798504ed --- /dev/null +++ b/bsp/sparkfun-redv/metal.freertos.lds @@ -0,0 +1,327 @@ +/* Copyright (c) 2020 SiFive Inc. */ +/* SPDX-License-Identifier: Apache-2.0 */ +OUTPUT_ARCH("riscv") + +/* Privileged mode Linker Script + * + * This linker script is based on metal.default.lds. It introduce specific + * section to isolate (acessible only from machine mode) and others that can be + * used in every execution mode. This linker script it tailored for FreeRTOS + * applications. + */ + +ENTRY(_enter) + +MEMORY +{ + itim (airwx) : ORIGIN = 0x8000000, LENGTH = 0x2000 + ram (arw!xi) : ORIGIN = 0x80000000, LENGTH = 0x4000 + rom (irx!wa) : ORIGIN = 0x20010000, LENGTH = 0x6a120 +} + +PHDRS +{ + rom PT_LOAD; + ram_init PT_LOAD; + tls PT_TLS; + ram PT_LOAD; + itim_init PT_LOAD; + text PT_LOAD; + lim_init PT_LOAD; +} + +SECTIONS +{ + /* Each hart is allocated its own stack of size __stack_size. This value + * can be overriden at build-time by adding the following to CFLAGS: + * + * -Xlinker --defsym=__stack_size=0xf00 + * + * where 0xf00 can be replaced with a multiple of 16 of your choice. + * + * __stack_size is PROVIDE-ed as a symbol so that initialization code + * initializes the stack pointers for each hart at the right offset from + * the _sp symbol. + */ + __stack_size = DEFINED(__stack_size) ? __stack_size : 0x400; + PROVIDE(__stack_size = __stack_size); + + /* The size of the heap can be overriden at build-time by adding the + * following to CFLAGS: + * + * -Xlinker --defsym=__heap_size=0xf00 + * + * where 0xf00 can be replaced with the value of your choice. + * + * Altertatively, the heap can be grown to fill the entire remaining region + * of RAM by adding the following to CFLAGS: + * + * -Xlinker --defsym=__heap_max=1 + * + * Note that depending on the memory layout, the bitness (32/64bit) of the + * target, and the code model in use, this might cause a relocation error. + */ + __heap_size = DEFINED(__heap_size) ? __heap_size : 0x800; + + /* The boot hart sets which hart runs the pre-main initialization routines, + * including copying .data into RAM, zeroing the BSS region, running + * constructors, etc. After initialization, the boot hart is also the only + * hart which runs application code unless the application overrides the + * secondary_main() function to start execution on secondary harts. + */ + PROVIDE(__metal_boot_hart = 0); + + /* The chicken bit is used by pre-main initialization to enable/disable + * certain core features */ + PROVIDE(__metal_chicken_bit = 1); + + /* The memory_ecc_scrub bit is used by _entry code to enable/disable + * memories scrubbing to zero */ + PROVIDE(__metal_eccscrub_bit = 0); + + /* The RAM memories map for ECC scrubbing */ + PROVIDE( metal_dtim_0_memory_start = 0x80000000 ); + PROVIDE( metal_dtim_0_memory_end = 0x80000000 + 0x4000 ); + PROVIDE( metal_itim_0_memory_start = 0x8000000 ); + PROVIDE( metal_itim_0_memory_end = 0x8000000 + 0x2000 ); + + /* ROM SECTION + * + * The following sections contain data which lives in read-only memory, if + * such memory is present in the design, for the entire duration of program + * execution. + */ + + .init : { + /* The _enter symbol is placed in the .text.metal.init.enter section + * and must be placed at the beginning of the program */ + KEEP (*(.text.metal.init.enter)) + KEEP (*(.text.metal.init.*)) + KEEP (*(SORT_NONE(.init))) + KEEP (*(.text.libgloss.start)) + } >rom :rom + + .fini : { + KEEP (*(SORT_NONE(.fini))) + } >rom :rom + + .preinit_array : ALIGN(8) { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >rom :rom + + .init_array : ALIGN(8) { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE_HIDDEN ( metal_constructors_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.metal.init_array.*))); + KEEP (*(.metal.init_array)); + PROVIDE_HIDDEN ( metal_constructors_end = .); + } >rom :rom + + .fini_array : ALIGN(8) { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + PROVIDE_HIDDEN ( metal_destructors_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.metal.fini_array.*))); + KEEP (*(.metal.fini_array)); + PROVIDE_HIDDEN ( metal_destructors_end = .); + } >rom :rom + + .privileged_functions : ALIGN (32) { + __privileged_functions_start__ = .; + KEEP(*(privileged_functions)) + . = ALIGN(32); + __privileged_functions_end__ = .; + } >rom + + + .ctors : { + . = ALIGN(32); + __unprivileged_section_start__ = .; + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*(.metal.ctors .metal.ctors.*)) + } >rom :rom + + .dtors : { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + KEEP (*(.metal.dtors .metal.dtors.*)) + } >rom : rom + + .rodata : { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >rom :rom + + /* ITIM SECTION + * + * The following sections contain data which is copied from read-only + * memory into an instruction tightly-integrated memory (ITIM), if one + * is present in the design, during pre-main program initialization. + * + * Generally, the data copied into the ITIM should be performance-critical + * functions which benefit from low instruction-fetch latency. + */ + + .itim : ALIGN(8) { + *(.itim .itim.*) + } >itim AT>rom :itim_init + + PROVIDE( metal_segment_itim_source_start = LOADADDR(.itim) ); + PROVIDE( metal_segment_itim_target_start = ADDR(.itim) ); + PROVIDE( metal_segment_itim_target_end = ADDR(.itim) + SIZEOF(.itim) ); + + /* LIM SECTION + * + * The following sections contain data which is copied from read-only + * memory into a loosely integrated memory (LIM), which is shared with L2 + * cache, during pre-main program initialization. + * + * Generally, the data copied into the LIM should be performance-critical + * functions which benefit from low instruction-fetch latency. + */ + + .lim : ALIGN(8) { + *(.lim .lim.*) + } >ram AT>rom :lim_init + + PROVIDE( metal_segment_lim_source_start = LOADADDR(.lim) ); + PROVIDE( metal_segment_lim_target_start = ADDR(.lim) ); + PROVIDE( metal_segment_lim_target_end = ADDR(.lim) + SIZEOF(.lim) ); + + /* TEXT SECTION + * + * The following section contains the code of the program, excluding + * everything that's been allocated into the ITIM/LIM already + */ + + .text : { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + *(freertos_system_calls) + . = ALIGN(32); + __unprivileged_section_end__ = .; + } >rom :text + + /* RAM SECTION + * + * The following sections contain data which is copied from read-only + * memory into a read-write-capable memory such as data tightly-integrated + * memory (DTIM) or another main memory, as well as the BSS, stack, and + * heap. + * + * You might notice that .data, .tdata, .tbss, .tbss_space, and .bss all + * have an apparently unnecessary ALIGN at their top. This is because + * the implementation of _start in Freedom Metal libgloss depends on the + * ADDR and LOADADDR being 8-byte aligned. + */ + + .data : ALIGN(8) { + . = ALIGN(32); + __unprivileged_data_section_start__ = .; + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.* .sdata2.*) + *(.gnu.linkonce.s.*) + } >ram AT>rom :ram_init + + .tdata : ALIGN(8) { + PROVIDE( __tls_base = . ); + *(.tdata .tdata.* .gnu.linkonce.td.*) + } >ram AT>rom :tls :ram_init + + PROVIDE( __tdata_source = LOADADDR(.tdata) ); + PROVIDE( __tdata_size = SIZEOF(.tdata) ); + + PROVIDE( metal_segment_data_source_start = LOADADDR(.data) ); + PROVIDE( metal_segment_data_target_start = ADDR(.data) ); + PROVIDE( metal_segment_data_target_end = ADDR(.tdata) + SIZEOF(.tdata) ); + + .tbss : ALIGN(8) { + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + PROVIDE( __tls_end = . ); + } >ram AT>ram :tls :ram + PROVIDE( __tbss_size = SIZEOF(.tbss) ); + PROVIDE( __tls_size = __tls_end - __tls_base ); + + .tbss_space : ALIGN(8) { + . = . + __tbss_size; + } >ram :ram + + .bss (NOLOAD): ALIGN(8) { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(32); + __unprivileged_data_section_end__ = .; + } >ram :ram + + PROVIDE( metal_segment_bss_source_start = LOADADDR(.tbss) ); + PROVIDE( metal_segment_bss_target_start = ADDR(.tbss) ); + PROVIDE( metal_segment_bss_target_end = ADDR(.bss) + SIZEOF(.bss) ); + + .privileged_data (NOLOAD) : ALIGN(32) { + __privileged_data_start__ = .; + *(privileged_data) + /* Non kernel data is kept out of the first _Privileged_Data_Region_Size + bytes of SRAM. */ + . = ALIGN(32); + __privileged_data_end__ = .; + } >ram + + + .stack (NOLOAD) : ALIGN(16) { + PROVIDE(metal_segment_stack_begin = .); + . += __stack_size; /* Hart 0 */ + PROVIDE( _sp = . ); + PROVIDE(metal_segment_stack_end = .); + } >ram :ram + + .heap (NOLOAD) : ALIGN(8) { + PROVIDE( __end = . ); + PROVIDE( __heap_start = . ); + PROVIDE( metal_segment_heap_target_start = . ); + /* If __heap_max is defined, grow the heap to use the rest of RAM, + * otherwise set the heap size to __heap_size */ + . = DEFINED(__heap_max) ? MIN( LENGTH(ram) - ( . - ORIGIN(ram)) , 0x10000000) : __heap_size; + PROVIDE( metal_segment_heap_target_end = . ); + PROVIDE( _heap_end = . ); + PROVIDE( __heap_end = . ); + } >ram :ram + + /* C++ exception handling information is + * not useful with our current runtime environment, + * and it consumes flash space. Discard it until + * we have something that can use it + */ + /DISCARD/ : { + *(.eh_frame .eh_frame.*) + } +} \ No newline at end of file diff --git a/bsp/sparkfun-redv/metal.h b/bsp/sparkfun-redv/metal.h new file mode 100644 index 000000000..b00885c3a --- /dev/null +++ b/bsp/sparkfun-redv/metal.h @@ -0,0 +1,1468 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* ----------------------------------- */ +/* ----------------------------------- */ + +#ifndef ASSEMBLY + +#include + +#ifdef __METAL_MACHINE_MACROS + +#ifndef MACROS_IF_METAL_H +#define MACROS_IF_METAL_H + +#define __METAL_CLINT_NUM_PARENTS 2 + +#ifndef __METAL_CLINT_NUM_PARENTS +#define __METAL_CLINT_NUM_PARENTS 0 +#endif +#define __METAL_PLIC_SUBINTERRUPTS 53 + +#define __METAL_PLIC_NUM_PARENTS 1 + +#ifndef __METAL_PLIC_SUBINTERRUPTS +#define __METAL_PLIC_SUBINTERRUPTS 0 +#endif +#ifndef __METAL_PLIC_NUM_PARENTS +#define __METAL_PLIC_NUM_PARENTS 0 +#endif +#ifndef __METAL_CLIC_SUBINTERRUPTS +#define __METAL_CLIC_SUBINTERRUPTS 0 +#endif + +#endif /* MACROS_IF_METAL_H*/ + +#else /* ! __METAL_MACHINE_MACROS */ + +#ifndef MACROS_ELSE_METAL_H +#define MACROS_ELSE_METAL_H + +#define __METAL_CLINT_2000000_INTERRUPTS 2 + +#define METAL_MAX_CLINT_INTERRUPTS 2 + +#define __METAL_CLINT_NUM_PARENTS 2 + +#define __METAL_INTERRUPT_CONTROLLER_C000000_INTERRUPTS 1 + +#define __METAL_PLIC_SUBINTERRUPTS 53 + +#define METAL_MAX_PLIC_INTERRUPTS 1 + +#define __METAL_PLIC_NUM_PARENTS 1 + +#define __METAL_CLIC_SUBINTERRUPTS 0 +#define METAL_MAX_CLIC_INTERRUPTS 0 + +#define METAL_MAX_LOCAL_EXT_INTERRUPTS 0 + +#define METAL_MAX_GLOBAL_EXT_INTERRUPTS 0 + +#define __METAL_GPIO_10012000_INTERRUPTS 32 + +#define METAL_MAX_GPIO_INTERRUPTS 32 + +#define __METAL_I2C_10016000_INTERRUPTS 1 + +#define METAL_MAX_I2C0_INTERRUPTS 1 + +#define __METAL_PWM_10015000_INTERRUPTS 4 + +#define __METAL_PWM_10025000_INTERRUPTS 4 + +#define __METAL_PWM_10035000_INTERRUPTS 4 + +#define METAL_MAX_PWM0_INTERRUPTS 4 + +#define METAL_MAX_PWM0_NCMP 4 + +#define __METAL_SERIAL_10013000_INTERRUPTS 1 + +#define __METAL_SERIAL_10023000_INTERRUPTS 1 + +#define METAL_MAX_UART_INTERRUPTS 1 + +#define METAL_MAX_SIMUART_INTERRUPTS 0 + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* From clock@0 */ +extern struct __metal_driver_fixed_clock __metal_dt_clock_0; + +/* From clock@2 */ +extern struct __metal_driver_fixed_clock __metal_dt_clock_2; + +/* From clock@5 */ +extern struct __metal_driver_fixed_clock __metal_dt_clock_5; + +/* From clock@6 */ +extern struct __metal_driver_fixed_clock __metal_dt_clock_6; + +extern struct metal_memory __metal_dt_mem_dtim_80000000; + +extern struct metal_memory __metal_dt_mem_itim_8000000; + +extern struct metal_memory __metal_dt_mem_spi_10014000; + +extern struct metal_memory __metal_dt_mem_spi_10024000; + +extern struct metal_memory __metal_dt_mem_spi_10034000; + +/* From clint@2000000 */ +extern struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000; + +/* From cpu@0 */ +extern struct __metal_driver_cpu __metal_dt_cpu_0; + +extern struct __metal_driver_riscv_cpu_intc __metal_dt_cpu_0_interrupt_controller; + +/* From interrupt_controller@c000000 */ +extern struct __metal_driver_riscv_plic0 __metal_dt_interrupt_controller_c000000; + +extern struct metal_pmp __metal_dt_pmp; + +/* From gpio@10012000 */ +extern struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000; + +/* From led@0 */ +extern struct __metal_driver_sifive_gpio_led __metal_dt_led_0; + +/* From i2c@10016000 */ +extern struct __metal_driver_sifive_i2c0 __metal_dt_i2c_10016000; + +/* From pwm@10015000 */ +extern struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10015000; + +/* From pwm@10025000 */ +extern struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10025000; + +/* From pwm@10035000 */ +extern struct __metal_driver_sifive_pwm0 __metal_dt_pwm_10035000; + +/* From aon@10000000 */ +extern struct __metal_driver_sifive_rtc0 __metal_dt_rtc_10000000; + +/* From spi@10014000 */ +extern struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000; + +/* From spi@10024000 */ +extern struct __metal_driver_sifive_spi0 __metal_dt_spi_10024000; + +/* From spi@10034000 */ +extern struct __metal_driver_sifive_spi0 __metal_dt_spi_10034000; + +/* From serial@10013000 */ +extern struct __metal_driver_sifive_uart0 __metal_dt_serial_10013000; + +/* From serial@10023000 */ +extern struct __metal_driver_sifive_uart0 __metal_dt_serial_10023000; + +/* From aon@10000000 */ +extern struct __metal_driver_sifive_wdog0 __metal_dt_aon_10000000; + +/* From clock@3 */ +extern struct __metal_driver_sifive_fe310_g000_hfrosc __metal_dt_clock_3; + +/* From clock@1 */ +extern struct __metal_driver_sifive_fe310_g000_hfxosc __metal_dt_clock_1; + +/* From clock@7 */ +extern struct __metal_driver_sifive_fe310_g000_lfrosc __metal_dt_clock_7; + +/* From clock@4 */ +extern struct __metal_driver_sifive_fe310_g000_pll __metal_dt_clock_4; + +/* From prci@10008000 */ +extern struct __metal_driver_sifive_fe310_g000_prci __metal_dt_prci_10008000; + + + +/* --------------------- fixed_clock ------------ */ +static __inline__ unsigned long __metal_driver_fixed_clock_rate(const struct metal_clock *clock) +{ + if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_0) { + return METAL_FIXED_CLOCK_0_CLOCK_FREQUENCY; + } + else if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_2) { + return METAL_FIXED_CLOCK_2_CLOCK_FREQUENCY; + } + else if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_5) { + return METAL_FIXED_CLOCK_5_CLOCK_FREQUENCY; + } + else if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_6) { + return METAL_FIXED_CLOCK_6_CLOCK_FREQUENCY; + } + else { + return 0; + } +} + + + +/* --------------------- fixed_factor_clock ------------ */ + + +/* --------------------- sifive_clint0 ------------ */ +static __inline__ unsigned long __metal_driver_sifive_clint0_control_base(struct metal_interrupt *controller) +{ + if ((uintptr_t)controller == (uintptr_t)&__metal_dt_clint_2000000) { + return METAL_RISCV_CLINT0_2000000_BASE_ADDRESS; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_clint0_control_size(struct metal_interrupt *controller) +{ + if ((uintptr_t)controller == (uintptr_t)&__metal_dt_clint_2000000) { + return METAL_RISCV_CLINT0_2000000_SIZE; + } + else { + return 0; + } +} + +static __inline__ int __metal_driver_sifive_clint0_num_interrupts(struct metal_interrupt *controller) +{ + if ((uintptr_t)controller == (uintptr_t)&__metal_dt_clint_2000000) { + return METAL_MAX_CLINT_INTERRUPTS; + } + else { + return 0; + } +} + +static __inline__ struct metal_interrupt * __metal_driver_sifive_clint0_interrupt_parents(struct metal_interrupt *controller, int idx) +{ + if (idx == 0) { + return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller; + } + else if (idx == 1) { + return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller; + } + else { + return NULL; + } +} + +static __inline__ int __metal_driver_sifive_clint0_interrupt_lines(struct metal_interrupt *controller, int idx) +{ + if (idx == 0) { + return 3; + } + else if (idx == 1) { + return 7; + } + else { + return 0; + } +} + + + +/* --------------------- cpu ------------ */ +static __inline__ int __metal_driver_cpu_hartid(struct metal_cpu *cpu) +{ + if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) { + return 0; + } + else { + return -1; + } +} + +static __inline__ int __metal_driver_cpu_timebase(struct metal_cpu *cpu) +{ + if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) { + return 16000000; + } + else { + return 0; + } +} + +static __inline__ struct metal_interrupt * __metal_driver_cpu_interrupt_controller(struct metal_cpu *cpu) +{ + if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) { + return &__metal_dt_cpu_0_interrupt_controller.controller; + } + else { + return NULL; + } +} + +static __inline__ int __metal_driver_cpu_num_pmp_regions(struct metal_cpu *cpu) +{ + if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) { + return 8; + } + else { + return 0; + } +} + +static __inline__ struct metal_buserror * __metal_driver_cpu_buserror(struct metal_cpu *cpu) +{ + if ((uintptr_t)cpu == (uintptr_t)&__metal_dt_cpu_0) { + return NULL; + } + else { + return NULL; + } +} + + + +/* --------------------- sifive_plic0 ------------ */ +static __inline__ unsigned long __metal_driver_sifive_plic0_control_base(struct metal_interrupt *controller) +{ + if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) { + return METAL_RISCV_PLIC0_C000000_BASE_ADDRESS; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_plic0_control_size(struct metal_interrupt *controller) +{ + if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) { + return METAL_RISCV_PLIC0_C000000_SIZE; + } + else { + return 0; + } +} + +static __inline__ int __metal_driver_sifive_plic0_num_interrupts(struct metal_interrupt *controller) +{ + if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) { + return METAL_RISCV_PLIC0_C000000_RISCV_NDEV; + } + else { + return 0; + } +} + +static __inline__ int __metal_driver_sifive_plic0_max_priority(struct metal_interrupt *controller) +{ + if ((uintptr_t)controller == (uintptr_t)&__metal_dt_interrupt_controller_c000000) { + return METAL_RISCV_PLIC0_C000000_RISCV_MAX_PRIORITY; + } + else { + return 0; + } +} + +static __inline__ struct metal_interrupt * __metal_driver_sifive_plic0_interrupt_parents(struct metal_interrupt *controller, int idx) +{ + if (idx == 0) { + return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller; + } + else { + return NULL; + } +} + +static __inline__ int __metal_driver_sifive_plic0_interrupt_lines(struct metal_interrupt *controller, int idx) +{ + if (idx == 0) { + return 11; + } + else { + return 0; + } +} + +static __inline__ int __metal_driver_sifive_plic0_context_ids(int hartid) +{ + if (hartid == 0) { + return 0; + } + else { + return -1; + } +} + + + +/* --------------------- sifive_buserror0 ------------ */ + + +/* --------------------- sifive_clic0 ------------ */ + + +/* --------------------- sifive_local_external_interrupts0 ------------ */ + + +/* --------------------- sifive_global_external_interrupts0 ------------ */ + + +/* --------------------- sifive_gpio0 ------------ */ +static __inline__ unsigned long __metal_driver_sifive_gpio0_base(struct metal_gpio *gpio) +{ + if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) { + return METAL_SIFIVE_GPIO0_10012000_BASE_ADDRESS; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_gpio0_size(struct metal_gpio *gpio) +{ + if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) { + return METAL_SIFIVE_GPIO0_10012000_SIZE; + } + else { + return 0; + } +} + +static __inline__ int __metal_driver_sifive_gpio0_num_interrupts(struct metal_gpio *gpio) +{ + if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) { + return METAL_MAX_GPIO_INTERRUPTS; + } + else { + return 0; + } +} + +static __inline__ struct metal_interrupt * __metal_driver_sifive_gpio0_interrupt_parent(struct metal_gpio *gpio) +{ + if ((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) { + return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller; + } + else { + return 0; + } +} + +static __inline__ int __metal_driver_sifive_gpio0_interrupt_lines(struct metal_gpio *gpio, int idx) +{ + if (((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 0)) { + return 8; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 1))) { + return 9; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 2))) { + return 10; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 3))) { + return 11; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 4))) { + return 12; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 5))) { + return 13; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 6))) { + return 14; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 7))) { + return 15; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 8))) { + return 16; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 9))) { + return 17; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 10))) { + return 18; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 11))) { + return 19; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 12))) { + return 20; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 13))) { + return 21; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 14))) { + return 22; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 15))) { + return 23; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 16))) { + return 24; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 17))) { + return 25; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 18))) { + return 26; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 19))) { + return 27; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 20))) { + return 28; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 21))) { + return 29; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 22))) { + return 30; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 23))) { + return 31; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 24))) { + return 32; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 25))) { + return 33; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 26))) { + return 34; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 27))) { + return 35; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 28))) { + return 36; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 29))) { + return 27; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 30))) { + return 28; + } + else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 31))) { + return 29; + } + else { + return 0; + } +} + + + +/* --------------------- sifive_gpio_button ------------ */ + + +/* --------------------- sifive_gpio_led ------------ */ +static __inline__ struct metal_gpio * __metal_driver_sifive_gpio_led_gpio(struct metal_led *led) +{ + if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0) { + return (struct metal_gpio *)&__metal_dt_gpio_10012000; + } + else { + return NULL; + } +} + +static __inline__ int __metal_driver_sifive_gpio_led_pin(struct metal_led *led) +{ + if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0) { + return 5; + } + else { + return 0; + } +} + +static __inline__ char * __metal_driver_sifive_gpio_led_label(struct metal_led *led) +{ + if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0) { + return "LD0"; + } + else { + return ""; + } +} + + + +/* --------------------- sifive_gpio_switch ------------ */ + + +/* --------------------- sifive_i2c0 ------------ */ +static __inline__ unsigned long __metal_driver_sifive_i2c0_control_base(struct metal_i2c *i2c) +{ + if ((uintptr_t)i2c == (uintptr_t)&__metal_dt_i2c_10016000) { + return METAL_SIFIVE_I2C0_10016000_BASE_ADDRESS; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_i2c0_control_size(struct metal_i2c *i2c) +{ + if ((uintptr_t)i2c == (uintptr_t)&__metal_dt_i2c_10016000) { + return METAL_SIFIVE_I2C0_10016000_SIZE; + } + else { + return 0; + } +} + +static __inline__ struct metal_clock * __metal_driver_sifive_i2c0_clock(struct metal_i2c *i2c) +{ + if ((uintptr_t)i2c == (uintptr_t)&__metal_dt_i2c_10016000) { + return (struct metal_clock *)&__metal_dt_clock_4.clock; + } + else { + return NULL; + } +} + +static __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_i2c0_pinmux(struct metal_i2c *i2c) +{ + if ((uintptr_t)i2c == (uintptr_t)&__metal_dt_i2c_10016000) { + return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000; + } + else { + return NULL; + } +} + +static __inline__ unsigned long __metal_driver_sifive_i2c0_pinmux_output_selector(struct metal_i2c *i2c) +{ + if ((uintptr_t)i2c == (uintptr_t)&__metal_dt_i2c_10016000) { + return 0; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_i2c0_pinmux_source_selector(struct metal_i2c *i2c) +{ + if ((uintptr_t)i2c == (uintptr_t)&__metal_dt_i2c_10016000) { + return 12288; + } + else { + return 0; + } +} + +static __inline__ int __metal_driver_sifive_i2c0_num_interrupts(struct metal_i2c *i2c) +{ + return METAL_MAX_I2C0_INTERRUPTS; +} + +static __inline__ struct metal_interrupt * __metal_driver_sifive_i2c0_interrupt_parent(struct metal_i2c *i2c) +{ + return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller; +} + +static __inline__ int __metal_driver_sifive_i2c0_interrupt_line(struct metal_i2c *i2c) +{ + if ((uintptr_t)i2c == (uintptr_t)&__metal_dt_i2c_10016000) { + return 52; + } + else { + return 0; + } +} + + + +/* --------------------- sifive_pwm0 ------------ */ +static __inline__ unsigned long __metal_driver_sifive_pwm0_control_base(struct metal_pwm *pwm) +{ + if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) { + return METAL_SIFIVE_PWM0_10015000_BASE_ADDRESS; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) { + return METAL_SIFIVE_PWM0_10025000_BASE_ADDRESS; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) { + return METAL_SIFIVE_PWM0_10035000_BASE_ADDRESS; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_pwm0_control_size(struct metal_pwm *pwm) +{ + if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) { + return METAL_SIFIVE_PWM0_10015000_SIZE; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) { + return METAL_SIFIVE_PWM0_10025000_SIZE; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) { + return METAL_SIFIVE_PWM0_10035000_SIZE; + } + else { + return 0; + } +} + +static __inline__ struct metal_clock * __metal_driver_sifive_pwm0_clock(struct metal_pwm *pwm) +{ + if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) { + return (struct metal_clock *)&__metal_dt_clock_4.clock; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) { + return (struct metal_clock *)&__metal_dt_clock_4.clock; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) { + return (struct metal_clock *)&__metal_dt_clock_4.clock; + } + else { + return NULL; + } +} + +static __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_pwm0_pinmux(struct metal_pwm *pwm) +{ + if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) { + return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) { + return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) { + return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000; + } + else { + return NULL; + } +} + +static __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_output_selector(struct metal_pwm *pwm) +{ + if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) { + return 15; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) { + return 7864320; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) { + return 15360; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_pwm0_pinmux_source_selector(struct metal_pwm *pwm) +{ + if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) { + return 15; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) { + return 7864320; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) { + return 15360; + } + else { + return 0; + } +} + +static __inline__ int __metal_driver_sifive_pwm0_num_interrupts(struct metal_pwm *pwm) +{ + if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) { + return __METAL_PWM_10015000_INTERRUPTS; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) { + return __METAL_PWM_10025000_INTERRUPTS; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) { + return __METAL_PWM_10035000_INTERRUPTS; + } + else { + return 0; + } +} + +static __inline__ struct metal_interrupt * __metal_driver_sifive_pwm0_interrupt_parent(struct metal_pwm *pwm) +{ + return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller; +} + +static __inline__ int __metal_driver_sifive_pwm0_interrupt_lines(struct metal_pwm *pwm, int idx) +{ + if (((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) && (idx == 0)) { + return 40; + } + else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) && (idx == 1))) { + return 41; + } + else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) && (idx == 2))) { + return 42; + } + else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) && (idx == 3))) { + return 43; + } + else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) && (idx == 0))) { + return 44; + } + else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) && (idx == 1))) { + return 45; + } + else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) && (idx == 2))) { + return 46; + } + else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) && (idx == 3))) { + return 47; + } + else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) && (idx == 0))) { + return 48; + } + else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) && (idx == 1))) { + return 49; + } + else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) && (idx == 2))) { + return 50; + } + else if ((((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) && (idx == 3))) { + return 51; + } + else { + return 0; + } +} + +static __inline__ int __metal_driver_sifive_pwm0_compare_width(struct metal_pwm *pwm) +{ + if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) { + return 8; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) { + return 16; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) { + return 16; + } + else { + return 0; + } +} + +static __inline__ int __metal_driver_sifive_pwm0_comparator_count(struct metal_pwm *pwm) +{ + if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10015000) { + return 4; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10025000) { + return 4; + } + else if ((uintptr_t)pwm == (uintptr_t)&__metal_dt_pwm_10035000) { + return 4; + } + else { + return 0; + } +} + + + +/* --------------------- sifive_rtc0 ------------ */ +static __inline__ unsigned long __metal_driver_sifive_rtc0_control_base(const struct metal_rtc *const rtc) +{ + if ((uintptr_t)rtc == (uintptr_t)&__metal_dt_rtc_10000000) { + return METAL_SIFIVE_AON0_10000000_BASE_ADDRESS; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_rtc0_control_size(const struct metal_rtc *const rtc) +{ + if ((uintptr_t)rtc == (uintptr_t)&__metal_dt_rtc_10000000) { + return METAL_SIFIVE_AON0_10000000_SIZE; + } + else { + return 0; + } +} + +static __inline__ struct metal_interrupt * __metal_driver_sifive_rtc0_interrupt_parent(const struct metal_rtc *const rtc) +{ + if ((uintptr_t)rtc == (uintptr_t)&__metal_dt_rtc_10000000) { + return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller; + } + else { + return 0; + } +} + +static __inline__ int __metal_driver_sifive_rtc0_interrupt_line(const struct metal_rtc *const rtc) +{ + if ((uintptr_t)rtc == (uintptr_t)&__metal_dt_rtc_10000000) { + return 2; + } + else { + return 0; + } +} + +static __inline__ struct metal_clock * __metal_driver_sifive_rtc0_clock(const struct metal_rtc *const rtc) +{ + if ((uintptr_t)rtc == (uintptr_t)&__metal_dt_rtc_10000000) { + return (struct metal_clock *)&__metal_dt_clock_7.clock; + } + else { + return 0; + } +} + + +static __inline__ unsigned long __metal_driver_sifive_spi0_control_base(struct metal_spi *spi) +{ + if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) { + return METAL_SIFIVE_SPI0_10014000_BASE_ADDRESS; + } + else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10024000) { + return METAL_SIFIVE_SPI0_10024000_BASE_ADDRESS; + } + else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10034000) { + return METAL_SIFIVE_SPI0_10034000_BASE_ADDRESS; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_spi0_control_size(struct metal_spi *spi) +{ + if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) { + return METAL_SIFIVE_SPI0_10014000_SIZE; + } + else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10024000) { + return METAL_SIFIVE_SPI0_10024000_SIZE; + } + else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10034000) { + return METAL_SIFIVE_SPI0_10034000_SIZE; + } + else { + return 0; + } +} + +static __inline__ struct metal_clock * __metal_driver_sifive_spi0_clock(struct metal_spi *spi) +{ + if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) { + return (struct metal_clock *)&__metal_dt_clock_4.clock; + } + else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10024000) { + return (struct metal_clock *)&__metal_dt_clock_4.clock; + } + else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10034000) { + return (struct metal_clock *)&__metal_dt_clock_4.clock; + } + else { + return 0; + } +} + +static __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_spi0_pinmux(struct metal_spi *spi) +{ + if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) { + return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000; + } + else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10024000) { + return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000; + } + else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10034000) { + return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_spi0_pinmux_output_selector(struct metal_spi *spi) +{ + if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) { + return 0; + } + else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10024000) { + return 0; + } + else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10034000) { + return 0; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_spi0_pinmux_source_selector(struct metal_spi *spi) +{ + if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10014000) { + return 0; + } + else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10024000) { + return 60; + } + else if ((uintptr_t)spi == (uintptr_t)&__metal_dt_spi_10034000) { + return 4227858432; + } + else { + return 0; + } +} + + + +/* --------------------- sifive_test0 ------------ */ + + +/* --------------------- sifive_trace ------------ */ + +/* --------------------- sifive_uart0 ------------ */ +static __inline__ unsigned long __metal_driver_sifive_uart0_control_base(struct metal_uart *uart) +{ + if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { + return METAL_SIFIVE_UART0_10013000_BASE_ADDRESS; + } + else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) { + return METAL_SIFIVE_UART0_10023000_BASE_ADDRESS; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_uart0_control_size(struct metal_uart *uart) +{ + if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { + return METAL_SIFIVE_UART0_10013000_SIZE; + } + else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) { + return METAL_SIFIVE_UART0_10023000_SIZE; + } + else { + return 0; + } +} + +static __inline__ int __metal_driver_sifive_uart0_num_interrupts(struct metal_uart *uart) +{ + if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { + return METAL_MAX_UART_INTERRUPTS; + } + else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) { + return METAL_MAX_UART_INTERRUPTS; + } + else { + return 0; + } +} + +static __inline__ struct metal_interrupt * __metal_driver_sifive_uart0_interrupt_parent(struct metal_uart *uart) +{ + if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { + return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller; + } + else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) { + return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller; + } + else { + return 0; + } +} + +static __inline__ int __metal_driver_sifive_uart0_interrupt_line(struct metal_uart *uart) +{ + if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { + return 3; + } + else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) { + return 4; + } + else { + return 0; + } +} + +static __inline__ struct metal_clock * __metal_driver_sifive_uart0_clock(struct metal_uart *uart) +{ + if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { + return (struct metal_clock *)&__metal_dt_clock_4.clock; + } + else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) { + return (struct metal_clock *)&__metal_dt_clock_4.clock; + } + else { + return 0; + } +} + +static __inline__ struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uart0_pinmux(struct metal_uart *uart) +{ + if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { + return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000; + } + else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) { + return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart) +{ + if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { + return 0; + } + else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) { + return 0; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_uart0_pinmux_source_selector(struct metal_uart *uart) +{ + if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10013000) { + return 196608; + } + else if ((uintptr_t)uart == (uintptr_t)&__metal_dt_serial_10023000) { + return 8650752; + } + else { + return 0; + } +} + + + +/* --------------------- sifive_simuart0 ------------ */ + + +/* --------------------- sifive_wdog0 ------------ */ +static __inline__ unsigned long __metal_driver_sifive_wdog0_control_base(const struct metal_watchdog *const watchdog) +{ + if ((uintptr_t)watchdog == (uintptr_t)&__metal_dt_aon_10000000) { + return METAL_SIFIVE_AON0_10000000_BASE_ADDRESS; + } + else { + return 0; + } +} + +static __inline__ unsigned long __metal_driver_sifive_wdog0_control_size(const struct metal_watchdog *const watchdog) +{ + if ((uintptr_t)watchdog == (uintptr_t)&__metal_dt_aon_10000000) { + return METAL_SIFIVE_AON0_10000000_SIZE; + } + else { + return 0; + } +} + +static __inline__ struct metal_interrupt * __metal_driver_sifive_wdog0_interrupt_parent(const struct metal_watchdog *const watchdog) +{ + if ((uintptr_t)watchdog == (uintptr_t)&__metal_dt_aon_10000000) { + return (struct metal_interrupt *)&__metal_dt_interrupt_controller_c000000.controller; + } + else { + return 0; + } +} + +static __inline__ int __metal_driver_sifive_wdog0_interrupt_line(const struct metal_watchdog *const watchdog) +{ + if ((uintptr_t)watchdog == (uintptr_t)&__metal_dt_aon_10000000) { + return 1; + } + else { + return 0; + } +} + +static __inline__ struct metal_clock * __metal_driver_sifive_wdog0_clock(const struct metal_watchdog *const watchdog) +{ + if ((uintptr_t)watchdog == (uintptr_t)&__metal_dt_aon_10000000) { + return (struct metal_clock *)&__metal_dt_clock_7.clock; + } + else { + return 0; + } +} + + + +/* --------------------- sifive_fe310_g000_hfrosc ------------ */ +static __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_hfrosc_ref(const struct metal_clock *clock) +{ + return (struct metal_clock *)&__metal_dt_clock_2.clock; +} + +static __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_base(const struct metal_clock *clock) +{ + return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000; +} + +static __inline__ const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfrosc_config_vtable(struct metal_clock *clock) +{ + return &__metal_driver_vtable_sifive_fe310_g000_prci; +} + +static __inline__ long __metal_driver_sifive_fe310_g000_hfrosc_config_offset(const struct metal_clock *clock) +{ + return METAL_SIFIVE_FE310_G000_PRCI_HFROSCCFG; +} + + + +/* --------------------- sifive_fe310_g000_hfxosc ------------ */ +static __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_hfxosc_ref(const struct metal_clock *clock) +{ + return (struct metal_clock *)&__metal_dt_clock_0.clock; +} + +static __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_hfxosc_config_base(const struct metal_clock *clock) +{ + return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000; +} + +static __inline__ long __metal_driver_sifive_fe310_g000_hfxosc_config_offset(const struct metal_clock *clock) +{ + return METAL_SIFIVE_FE310_G000_PRCI_HFXOSCCFG; +} + + + +/* --------------------- sifive_fe310_g000_lfrosc ------------ */ +static __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_lfrosc_lfrosc(const struct metal_clock *clock) +{ + if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_7) { + return (struct metal_clock *)&__metal_dt_clock_5.clock; + } + else { + return NULL; + } +} + +static __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_lfrosc_psdlfaltclk(const struct metal_clock *clock) +{ + if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_7) { + return (struct metal_clock *)&__metal_dt_clock_6.clock; + } + else { + return NULL; + } +} + +static __inline__ unsigned long int __metal_driver_sifive_fe310_g000_lfrosc_config_reg(const struct metal_clock *clock) +{ + if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_7) { + return 112; + } + else { + return 0; + } +} + +static __inline__ unsigned long int __metal_driver_sifive_fe310_g000_lfrosc_mux_reg(const struct metal_clock *clock) +{ + if ((uintptr_t)clock == (uintptr_t)&__metal_dt_clock_7) { + return 124; + } + else { + return 0; + } +} + + + +/* --------------------- sifive_fe310_g000_pll ------------ */ +static __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllsel0(const struct metal_clock *clock) +{ + return (struct metal_clock *)&__metal_dt_clock_3.clock; +} + +static __inline__ struct metal_clock * __metal_driver_sifive_fe310_g000_pll_pllref(const struct metal_clock *clock) +{ + return (struct metal_clock *)&__metal_dt_clock_1.clock; +} + +static __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_divider_base(const struct metal_clock *clock) +{ + return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000; +} + +static __inline__ long __metal_driver_sifive_fe310_g000_pll_divider_offset(const struct metal_clock *clock) +{ + return METAL_SIFIVE_FE310_G000_PRCI_PLLOUTDIV; +} + +static __inline__ struct __metal_driver_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_pll_config_base( ) +{ + return (struct __metal_driver_sifive_fe310_g000_prci *)&__metal_dt_prci_10008000; +} + +static __inline__ long __metal_driver_sifive_fe310_g000_pll_config_offset( ) +{ + return METAL_SIFIVE_FE310_G000_PRCI_PLLCFG; +} + +static __inline__ long __metal_driver_sifive_fe310_g000_pll_init_rate( ) +{ + return 16000000; +} + + + +/* --------------------- sifive_fe310_g000_prci ------------ */ +static __inline__ long __metal_driver_sifive_fe310_g000_prci_base( ) +{ + return METAL_SIFIVE_FE310_G000_PRCI_10008000_BASE_ADDRESS; +} + +static __inline__ long __metal_driver_sifive_fe310_g000_prci_size( ) +{ + return METAL_SIFIVE_FE310_G000_PRCI_10008000_SIZE; +} + +static __inline__ const struct __metal_driver_vtable_sifive_fe310_g000_prci * __metal_driver_sifive_fe310_g000_prci_vtable( ) +{ + return &__metal_driver_vtable_sifive_fe310_g000_prci; +} + + + +#define __METAL_DT_MAX_MEMORIES 3 + +__asm__ (".weak __metal_memory_table"); +struct metal_memory *__metal_memory_table[] = { + &__metal_dt_mem_dtim_80000000, + &__metal_dt_mem_itim_8000000, + &__metal_dt_mem_spi_10014000}; + +/* From serial@10013000 */ +#define __METAL_DT_STDOUT_UART_HANDLE (&__metal_dt_serial_10013000.uart) + +#define __METAL_DT_SERIAL_10013000_HANDLE (&__metal_dt_serial_10013000.uart) + +#define __METAL_DT_STDOUT_UART_BAUD 115200 + +/* From clint@2000000 */ +#define __METAL_DT_RISCV_CLINT0_HANDLE (&__metal_dt_clint_2000000.controller) + +#define __METAL_DT_CLINT_2000000_HANDLE (&__metal_dt_clint_2000000.controller) + +#define __METAL_DT_MAX_HARTS 1 + +#define __METAL_CPU_0_ICACHE_HANDLE 1 + +__asm__ (".weak __metal_cpu_table"); +struct __metal_driver_cpu *__metal_cpu_table[] = { + &__metal_dt_cpu_0}; + +/* From interrupt_controller@c000000 */ +#define __METAL_DT_RISCV_PLIC0_HANDLE (&__metal_dt_interrupt_controller_c000000.controller) + +#define __METAL_DT_INTERRUPT_CONTROLLER_C000000_HANDLE (&__metal_dt_interrupt_controller_c000000.controller) + +#define __METAL_DT_PMP_HANDLE (&__metal_dt_pmp) + +#define __MEE_DT_MAX_GPIOS 1 + +__asm__ (".weak __metal_gpio_table"); +struct __metal_driver_sifive_gpio0 *__metal_gpio_table[] = { + &__metal_dt_gpio_10012000}; + +#define __METAL_DT_MAX_BUTTONS 0 + +__asm__ (".weak __metal_button_table"); +struct __metal_driver_sifive_gpio_button *__metal_button_table[] = { + NULL }; +#define __METAL_DT_MAX_LEDS 1 + +__asm__ (".weak __metal_led_table"); +struct __metal_driver_sifive_gpio_led *__metal_led_table[] = { + &__metal_dt_led_0}; + +#define __METAL_DT_MAX_SWITCHES 0 + +__asm__ (".weak __metal_switch_table"); +struct __metal_driver_sifive_gpio_switch *__metal_switch_table[] = { + NULL }; +#define __METAL_DT_MAX_I2CS 1 + +__asm__ (".weak __metal_i2c_table"); +struct __metal_driver_sifive_i2c0 *__metal_i2c_table[] = { + &__metal_dt_i2c_10016000}; + +#define __METAL_DT_MAX_PWMS 3 + +__asm__ (".weak __metal_pwm_table"); +struct __metal_driver_sifive_pwm0 *__metal_pwm_table[] = { + &__metal_dt_pwm_10015000, + &__metal_dt_pwm_10025000, + &__metal_dt_pwm_10035000}; + +#define __METAL_DT_MAX_RTCS 1 + +__asm__ (".weak __metal_rtc_table"); +struct __metal_driver_sifive_rtc0 *__metal_rtc_table[] = { + &__metal_dt_rtc_10000000}; + +#define __METAL_DT_MAX_SPIS 3 + +__asm__ (".weak __metal_spi_table"); +struct __metal_driver_sifive_spi0 *__metal_spi_table[] = { + &__metal_dt_spi_10014000, + &__metal_dt_spi_10024000, + &__metal_dt_spi_10034000}; + +#define __METAL_DT_MAX_UARTS 2 + +__asm__ (".weak __metal_uart_table"); +struct __metal_driver_sifive_uart0 *__metal_uart_table[] = { + &__metal_dt_serial_10013000, + &__metal_dt_serial_10023000}; + +#define __METAL_DT_MAX_SIMUARTS 0 + +__asm__ (".weak __metal_simuart_table"); +struct __metal_driver_sifive_simuart0 *__metal_simuart_table[] = { + NULL }; +#define __METAL_DT_MAX_WDOGS 1 + +__asm__ (".weak __metal_wdog_table"); +struct __metal_driver_sifive_wdog0 *__metal_wdog_table[] = { + &__metal_dt_aon_10000000}; + +/* From clock@4 */ +#define __METAL_DT_SIFIVE_FE310_G000_PLL_HANDLE (&__metal_dt_clock_4) + +#define __METAL_DT_CLOCK_4_HANDLE (&__metal_dt_clock_4) + +#endif /* MACROS_ELSE_METAL_H*/ + +#endif /* ! __METAL_MACHINE_MACROS */ + +#endif /* ! ASSEMBLY */ diff --git a/bsp/sparkfun-redv/metal.ramrodata.lds b/bsp/sparkfun-redv/metal.ramrodata.lds new file mode 100644 index 000000000..6803873ce --- /dev/null +++ b/bsp/sparkfun-redv/metal.ramrodata.lds @@ -0,0 +1,306 @@ +/* Copyright (c) 2020 SiFive Inc. */ +/* SPDX-License-Identifier: Apache-2.0 */ +OUTPUT_ARCH("riscv") + +/* RAM Read-Only Data Linker Script + * + * This linker script places application code and read-only data into writable + * memories in an attempt to improve performance, since writable memories + * are generally lower-latency. This linker script may cause your application + * to overflow RAM, since it dramatically increases the quantity of data vying + * for space there. + */ + +ENTRY(_enter) + +MEMORY +{ + itim (airwx) : ORIGIN = 0x8000000, LENGTH = 0x2000 + ram (arw!xi) : ORIGIN = 0x80000000, LENGTH = 0x4000 + rom (irx!wa) : ORIGIN = 0x20010000, LENGTH = 0x6a120 +} + +PHDRS +{ + rom PT_LOAD; + ram_init PT_LOAD; + tls PT_TLS; + ram PT_LOAD; + itim_init PT_LOAD; + text PT_LOAD; + lim_init PT_LOAD; +} + +SECTIONS +{ + /* Each hart is allocated its own stack of size __stack_size. This value + * can be overriden at build-time by adding the following to CFLAGS: + * + * -Xlinker --defsym=__stack_size=0xf00 + * + * where 0xf00 can be replaced with a multiple of 16 of your choice. + * + * __stack_size is PROVIDE-ed as a symbol so that initialization code + * initializes the stack pointers for each hart at the right offset from + * the _sp symbol. + */ + __stack_size = DEFINED(__stack_size) ? __stack_size : 0x400; + PROVIDE(__stack_size = __stack_size); + + /* The size of the heap can be overriden at build-time by adding the + * following to CFLAGS: + * + * -Xlinker --defsym=__heap_size=0xf00 + * + * where 0xf00 can be replaced with the value of your choice. + * + * Altertatively, the heap can be grown to fill the entire remaining region + * of RAM by adding the following to CFLAGS: + * + * -Xlinker --defsym=__heap_max=1 + * + * Note that depending on the memory layout, the bitness (32/64bit) of the + * target, and the code model in use, this might cause a relocation error. + */ + __heap_size = DEFINED(__heap_size) ? __heap_size : 0x800; + + /* The boot hart sets which hart runs the pre-main initialization routines, + * including copying .data into RAM, zeroing the BSS region, running + * constructors, etc. After initialization, the boot hart is also the only + * hart which runs application code unless the application overrides the + * secondary_main() function to start execution on secondary harts. + */ + PROVIDE(__metal_boot_hart = 0); + + /* The chicken bit is used by pre-main initialization to enable/disable + * certain core features */ + PROVIDE(__metal_chicken_bit = 1); + + /* The memory_ecc_scrub bit is used by _entry code to enable/disable + * memories scrubbing to zero */ + PROVIDE(__metal_eccscrub_bit = 0); + + /* The RAM memories map for ECC scrubbing */ + PROVIDE( metal_dtim_0_memory_start = 0x80000000 ); + PROVIDE( metal_dtim_0_memory_end = 0x80000000 + 0x4000 ); + PROVIDE( metal_itim_0_memory_start = 0x8000000 ); + PROVIDE( metal_itim_0_memory_end = 0x8000000 + 0x2000 ); + + /* ROM SECTION + * + * The following sections contain data which lives in read-only memory, if + * such memory is present in the design, for the entire duration of program + * execution. + */ + + .init : { + /* The _enter symbol is placed in the .text.metal.init.enter section + * and must be placed at the beginning of the program */ + KEEP (*(.text.metal.init.enter)) + KEEP (*(.text.metal.init.*)) + KEEP (*(SORT_NONE(.init))) + KEEP (*(.text.libgloss.start)) + } >rom :rom + + .fini : { + KEEP (*(SORT_NONE(.fini))) + } >rom :rom + + .preinit_array : ALIGN(8) { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >rom :rom + + .init_array : ALIGN(8) { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE_HIDDEN ( metal_constructors_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.metal.init_array.*))); + KEEP (*(.metal.init_array)); + PROVIDE_HIDDEN ( metal_constructors_end = .); + } >rom :rom + + .fini_array : ALIGN(8) { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + PROVIDE_HIDDEN ( metal_destructors_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.metal.fini_array.*))); + KEEP (*(.metal.fini_array)); + PROVIDE_HIDDEN ( metal_destructors_end = .); + } >rom :rom + + + + .ctors : { + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*(.metal.ctors .metal.ctors.*)) + } >rom :rom + + .dtors : { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + KEEP (*(.metal.dtors .metal.dtors.*)) + } >rom : rom + + + /* ITIM SECTION + * + * The following sections contain data which is copied from read-only + * memory into an instruction tightly-integrated memory (ITIM), if one + * is present in the design, during pre-main program initialization. + * + * Generally, the data copied into the ITIM should be performance-critical + * functions which benefit from low instruction-fetch latency. + */ + + .itim : ALIGN(8) { + *(.itim .itim.*) + } >itim AT>rom :itim_init + + PROVIDE( metal_segment_itim_source_start = LOADADDR(.itim) ); + PROVIDE( metal_segment_itim_target_start = ADDR(.itim) ); + PROVIDE( metal_segment_itim_target_end = ADDR(.itim) + SIZEOF(.itim) ); + + /* LIM SECTION + * + * The following sections contain data which is copied from read-only + * memory into a loosely integrated memory (LIM), which is shared with L2 + * cache, during pre-main program initialization. + * + * Generally, the data copied into the LIM should be performance-critical + * functions which benefit from low instruction-fetch latency. + */ + + .lim : ALIGN(8) { + *(.lim .lim.*) + } >ram AT>rom :lim_init + + PROVIDE( metal_segment_lim_source_start = LOADADDR(.lim) ); + PROVIDE( metal_segment_lim_target_start = ADDR(.lim) ); + PROVIDE( metal_segment_lim_target_end = ADDR(.lim) + SIZEOF(.lim) ); + + /* TEXT SECTION + * + * The following section contains the code of the program, excluding + * everything that's been allocated into the ITIM/LIM already + */ + + .text : { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >rom :text + + /* RAM SECTION + * + * The following sections contain data which is copied from read-only + * memory into a read-write-capable memory such as data tightly-integrated + * memory (DTIM) or another main memory, as well as the BSS, stack, and + * heap. + * + * You might notice that .data, .tdata, .tbss, .tbss_space, and .bss all + * have an apparently unnecessary ALIGN at their top. This is because + * the implementation of _start in Freedom Metal libgloss depends on the + * ADDR and LOADADDR being 8-byte aligned. + */ + + .data : ALIGN(8) { + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.* .sdata2.*) + *(.gnu.linkonce.s.*) + /* Read-only data is placed in RAM to improve performance, since + * read-only memory generally has higher latency than RAM */ + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + . = ALIGN(8); + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } >ram AT>rom :ram_init + + .tdata : ALIGN(8) { + PROVIDE( __tls_base = . ); + *(.tdata .tdata.* .gnu.linkonce.td.*) + } >ram AT>rom :tls :ram_init + + PROVIDE( __tdata_source = LOADADDR(.tdata) ); + PROVIDE( __tdata_size = SIZEOF(.tdata) ); + + PROVIDE( metal_segment_data_source_start = LOADADDR(.data) ); + PROVIDE( metal_segment_data_target_start = ADDR(.data) ); + PROVIDE( metal_segment_data_target_end = ADDR(.tdata) + SIZEOF(.tdata) ); + + .tbss : ALIGN(8) { + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + PROVIDE( __tls_end = . ); + } >ram AT>ram :tls :ram + PROVIDE( __tbss_size = SIZEOF(.tbss) ); + PROVIDE( __tls_size = __tls_end - __tls_base ); + + .tbss_space : ALIGN(8) { + . = . + __tbss_size; + } >ram :ram + + .bss (NOLOAD): ALIGN(8) { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } >ram :ram + + PROVIDE( metal_segment_bss_source_start = LOADADDR(.tbss) ); + PROVIDE( metal_segment_bss_target_start = ADDR(.tbss) ); + PROVIDE( metal_segment_bss_target_end = ADDR(.bss) + SIZEOF(.bss) ); + + + + .stack (NOLOAD) : ALIGN(16) { + PROVIDE(metal_segment_stack_begin = .); + . += __stack_size; /* Hart 0 */ + PROVIDE( _sp = . ); + PROVIDE(metal_segment_stack_end = .); + } >ram :ram + + .heap (NOLOAD) : ALIGN(8) { + PROVIDE( __end = . ); + PROVIDE( __heap_start = . ); + PROVIDE( metal_segment_heap_target_start = . ); + /* If __heap_max is defined, grow the heap to use the rest of RAM, + * otherwise set the heap size to __heap_size */ + . = DEFINED(__heap_max) ? MIN( LENGTH(ram) - ( . - ORIGIN(ram)) , 0x10000000) : __heap_size; + PROVIDE( metal_segment_heap_target_end = . ); + PROVIDE( _heap_end = . ); + PROVIDE( __heap_end = . ); + } >ram :ram + + /* C++ exception handling information is + * not useful with our current runtime environment, + * and it consumes flash space. Discard it until + * we have something that can use it + */ + /DISCARD/ : { + *(.eh_frame .eh_frame.*) + } +} \ No newline at end of file diff --git a/bsp/sparkfun-redv/metal.scratchpad.lds b/bsp/sparkfun-redv/metal.scratchpad.lds new file mode 100644 index 000000000..356726912 --- /dev/null +++ b/bsp/sparkfun-redv/metal.scratchpad.lds @@ -0,0 +1,294 @@ +/* Copyright (c) 2020 SiFive Inc. */ +/* SPDX-License-Identifier: Apache-2.0 */ +OUTPUT_ARCH("riscv") + +/* Scratchpad Linker Script + * + * This linker script is for executing in "scratchpad" mode, where all + * application code and data is placed in writable memory. + */ + +ENTRY(_enter) + +MEMORY +{ + itim (airwx) : ORIGIN = 0x8000000, LENGTH = 0x2000 + ram (arw!xi) : ORIGIN = 0x80000000, LENGTH = 0x4000 + rom (irx!wa) : ORIGIN = 0x20010000, LENGTH = 0x6a120 +} + +PHDRS +{ + rom PT_LOAD; + ram_init PT_LOAD; + tls PT_TLS; + ram PT_LOAD; + itim_init PT_LOAD; + text PT_LOAD; + lim_init PT_LOAD; +} + +SECTIONS +{ + /* Each hart is allocated its own stack of size __stack_size. This value + * can be overriden at build-time by adding the following to CFLAGS: + * + * -Xlinker --defsym=__stack_size=0xf00 + * + * where 0xf00 can be replaced with a multiple of 16 of your choice. + * + * __stack_size is PROVIDE-ed as a symbol so that initialization code + * initializes the stack pointers for each hart at the right offset from + * the _sp symbol. + */ + __stack_size = DEFINED(__stack_size) ? __stack_size : 0x400; + PROVIDE(__stack_size = __stack_size); + + /* The size of the heap can be overriden at build-time by adding the + * following to CFLAGS: + * + * -Xlinker --defsym=__heap_size=0xf00 + * + * where 0xf00 can be replaced with the value of your choice. + * + * Altertatively, the heap can be grown to fill the entire remaining region + * of RAM by adding the following to CFLAGS: + * + * -Xlinker --defsym=__heap_max=1 + * + * Note that depending on the memory layout, the bitness (32/64bit) of the + * target, and the code model in use, this might cause a relocation error. + */ + __heap_size = DEFINED(__heap_size) ? __heap_size : 0x800; + + /* The boot hart sets which hart runs the pre-main initialization routines, + * including copying .data into RAM, zeroing the BSS region, running + * constructors, etc. After initialization, the boot hart is also the only + * hart which runs application code unless the application overrides the + * secondary_main() function to start execution on secondary harts. + */ + PROVIDE(__metal_boot_hart = 0); + + /* The chicken bit is used by pre-main initialization to enable/disable + * certain core features */ + PROVIDE(__metal_chicken_bit = 1); + + PROVIDE(__metal_eccscrub_bit = 0); + + /* ROM SECTION + * + * The following sections contain data which lives in read-only memory, if + * such memory is present in the design, for the entire duration of program + * execution. + */ + + .init : { + /* The _enter symbol is placed in the .text.metal.init.enter section + * and must be placed at the beginning of the program */ + KEEP (*(.text.metal.init.enter)) + KEEP (*(.text.metal.init.*)) + KEEP (*(SORT_NONE(.init))) + KEEP (*(.text.libgloss.start)) + } >ram :rom + + .fini : { + KEEP (*(SORT_NONE(.fini))) + } >ram :rom + + .preinit_array : ALIGN(8) { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >ram :rom + + .init_array : ALIGN(8) { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE_HIDDEN ( metal_constructors_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.metal.init_array.*))); + KEEP (*(.metal.init_array)); + PROVIDE_HIDDEN ( metal_constructors_end = .); + } >ram :rom + + .fini_array : ALIGN(8) { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + PROVIDE_HIDDEN ( metal_destructors_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.metal.fini_array.*))); + KEEP (*(.metal.fini_array)); + PROVIDE_HIDDEN ( metal_destructors_end = .); + } >ram :rom + + + + .ctors : { + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*(.metal.ctors .metal.ctors.*)) + } >ram :rom + + .dtors : { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + KEEP (*(.metal.dtors .metal.dtors.*)) + } >ram : rom + + .rodata : { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } >ram :rom + + /* ITIM SECTION + * + * The following sections contain data which is copied from read-only + * memory into an instruction tightly-integrated memory (ITIM), if one + * is present in the design, during pre-main program initialization. + * + * Generally, the data copied into the ITIM should be performance-critical + * functions which benefit from low instruction-fetch latency. + */ + + .itim : ALIGN(8) { + *(.itim .itim.*) + } >itim AT>ram :itim_init + + PROVIDE( metal_segment_itim_source_start = LOADADDR(.itim) ); + PROVIDE( metal_segment_itim_target_start = ADDR(.itim) ); + PROVIDE( metal_segment_itim_target_end = ADDR(.itim) + SIZEOF(.itim) ); + + /* LIM SECTION + * + * The following sections contain data which is copied from read-only + * memory into a loosely integrated memory (LIM), which is shared with L2 + * cache, during pre-main program initialization. + * + * Generally, the data copied into the LIM should be performance-critical + * functions which benefit from low instruction-fetch latency. + */ + + .lim : ALIGN(8) { + *(.lim .lim.*) + } >ram AT>ram :lim_init + + PROVIDE( metal_segment_lim_source_start = LOADADDR(.lim) ); + PROVIDE( metal_segment_lim_target_start = ADDR(.lim) ); + PROVIDE( metal_segment_lim_target_end = ADDR(.lim) + SIZEOF(.lim) ); + + /* TEXT SECTION + * + * The following section contains the code of the program, excluding + * everything that's been allocated into the ITIM/LIM already + */ + + .text : { + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >ram :text + + /* RAM SECTION + * + * The following sections contain data which is copied from read-only + * memory into a read-write-capable memory such as data tightly-integrated + * memory (DTIM) or another main memory, as well as the BSS, stack, and + * heap. + * + * You might notice that .data, .tdata, .tbss, .tbss_space, and .bss all + * have an apparently unnecessary ALIGN at their top. This is because + * the implementation of _start in Freedom Metal libgloss depends on the + * ADDR and LOADADDR being 8-byte aligned. + */ + + .data : ALIGN(8) { + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.* .sdata2.*) + *(.gnu.linkonce.s.*) + } >ram AT>ram :ram_init + + .tdata : ALIGN(8) { + PROVIDE( __tls_base = . ); + *(.tdata .tdata.* .gnu.linkonce.td.*) + } >ram AT>ram :tls :ram_init + + PROVIDE( __tdata_source = LOADADDR(.tdata) ); + PROVIDE( __tdata_size = SIZEOF(.tdata) ); + + PROVIDE( metal_segment_data_source_start = LOADADDR(.data) ); + PROVIDE( metal_segment_data_target_start = ADDR(.data) ); + PROVIDE( metal_segment_data_target_end = ADDR(.tdata) + SIZEOF(.tdata) ); + + .tbss : ALIGN(8) { + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon .tcommon.*) + PROVIDE( __tls_end = . ); + } >ram AT>ram :tls :ram + PROVIDE( __tbss_size = SIZEOF(.tbss) ); + PROVIDE( __tls_size = __tls_end - __tls_base ); + + .tbss_space : ALIGN(8) { + . = . + __tbss_size; + } >ram :ram + + .bss (NOLOAD): ALIGN(8) { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + } >ram :ram + + PROVIDE( metal_segment_bss_source_start = LOADADDR(.tbss) ); + PROVIDE( metal_segment_bss_target_start = ADDR(.tbss) ); + PROVIDE( metal_segment_bss_target_end = ADDR(.bss) + SIZEOF(.bss) ); + + + + .stack (NOLOAD) : ALIGN(16) { + PROVIDE(metal_segment_stack_begin = .); + . += __stack_size; /* Hart 0 */ + PROVIDE( _sp = . ); + PROVIDE(metal_segment_stack_end = .); + } >ram :ram + + .heap (NOLOAD) : ALIGN(8) { + PROVIDE( __end = . ); + PROVIDE( __heap_start = . ); + PROVIDE( metal_segment_heap_target_start = . ); + /* If __heap_max is defined, grow the heap to use the rest of RAM, + * otherwise set the heap size to __heap_size */ + . = DEFINED(__heap_max) ? MIN( LENGTH(ram) - ( . - ORIGIN(ram)) , 0x10000000) : __heap_size; + PROVIDE( metal_segment_heap_target_end = . ); + PROVIDE( _heap_end = . ); + PROVIDE( __heap_end = . ); + } >ram :ram + + /* C++ exception handling information is + * not useful with our current runtime environment, + * and it consumes flash space. Discard it until + * we have something that can use it + */ + /DISCARD/ : { + *(.eh_frame .eh_frame.*) + } +} \ No newline at end of file diff --git a/bsp/sparkfun-redv/settings.mk b/bsp/sparkfun-redv/settings.mk new file mode 100644 index 000000000..a8ddd99f2 --- /dev/null +++ b/bsp/sparkfun-redv/settings.mk @@ -0,0 +1,13 @@ +# Copyright (C) 2020 SiFive Inc +# SPDX-License-Identifier: Apache-2.0 + +RISCV_ARCH = rv32imac +RISCV_ABI = ilp32 +RISCV_CMODEL = medlow +RISCV_SERIES = sifive-3-series + +TARGET_TAGS = board jlink +TARGET_DHRY_ITERS = 20000000 +TARGET_CORE_ITERS = 5000 +TARGET_FREERTOS_WAIT_MS = 1000 +TARGET_INTR_WAIT_CYCLE = 0 \ No newline at end of file From 6fc2855abebcec9bc71fe250009f6809b8858500 Mon Sep 17 00:00:00 2001 From: Dana Date: Wed, 3 Feb 2021 07:39:49 -0800 Subject: [PATCH 2/2] Update README.md for Sparkfun RED-V --- bsp/sparkfun-redv/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsp/sparkfun-redv/README.md b/bsp/sparkfun-redv/README.md index f5abca5bf..52cc3132c 100644 --- a/bsp/sparkfun-redv/README.md +++ b/bsp/sparkfun-redv/README.md @@ -1,4 +1,4 @@ -HiFive1 Rev B is a low-cost, Arduino-compatible development board featuring the Freedom E310. It’s the best way to start prototyping and developing your RISC‑V applications. +Sparkfun RED-V is a low-cost, Arduino-compatible development board featuring the Freedom E310. It’s one of the best ways to start prototyping and developing your RISC‑V applications. This target is ideal for getting familiar with the RISC-V ISA instruction set and the freedom-metal libraries. It supports: @@ -10,4 +10,4 @@ This target is ideal for getting familiar with the RISC-V ISA instruction set an - GPIO memory with 16 interrupt lines - SPI memory with 1 interrupt line - Serial port with 1 interrupt line -- 1 RGB LEDS +- 1 blue LED