diff --git a/bsp/sparkfun-redv/README.md b/bsp/sparkfun-redv/README.md
new file mode 100644
index 00000000..52cc3132
--- /dev/null
+++ b/bsp/sparkfun-redv/README.md
@@ -0,0 +1,13 @@
+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:
+
+- 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 blue LED
diff --git a/bsp/sparkfun-redv/core.dts b/bsp/sparkfun-redv/core.dts
new file mode 100644
index 00000000..26819954
--- /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 00000000..098c25c4
--- /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 00000000..921dd83a
--- /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 00000000..3ad2768b
--- /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 00000000..7933a9c4
--- /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 00000000..6ac62600
--- /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 00000000..094dcb61
--- /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 00000000..4798504e
--- /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 00000000..b00885c3
--- /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 00000000..6803873c
--- /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 00000000..35672691
--- /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 00000000..a8ddd99f
--- /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