summaryrefslogtreecommitdiff
path: root/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio')
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/.cproject174
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/.project303
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/.settings/language.settings.xml26
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/FreeRTOSConfig.h101
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/blinky_demo/main_blinky.c197
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/design.dts209
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/design.reglist54
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/button.h59
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/cache.h58
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/clock.h119
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/compiler.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/cpu.h271
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/fixed-clock.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/fixed-factor-clock.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/riscv_clint0.h24
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/riscv_cpu.h203
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/riscv_plic0.h31
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_clic0.h42
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_hfrosc.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_hfxosc.h20
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_pll.h26
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_prci.h23
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fu540-c000_l2.h23
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_global-external-interrupts0.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio-buttons.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio-leds.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio-switches.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio0.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_local-external-interrupts0.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_spi0.h24
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_test0.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_uart0.h28
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/gpio.h151
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/interrupt.h134
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/io.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/itim.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/led.h68
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/lock.h127
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/machine.h872
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/machine/inline.h249
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/machine/platform.h237
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/memory.h81
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/pmp.h204
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/privilege.h122
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/shutdown.h36
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/spi.h78
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/switch.h51
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/timer.h36
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/tty.h23
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/uart.h94
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal-inline.h249
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal-platform.h237
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal.default.lds236
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal.h872
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/doc/link_to_docs_in_github.url5
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/crt0.S246
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/nanosleep.c9
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/synchronize_harts.c59
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_access.c8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_chdir.c8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_chmod.c9
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_chown.c9
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_close.c8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_execve.c8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_exit.c8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_faccessat.c8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_fork.c8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_fstat.c9
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_fstatat.c9
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_ftime.c9
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_getcwd.c8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_getpid.c7
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_gettimeofday.c21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_isatty.c7
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_kill.c8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_link.c7
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_lseek.c9
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_lstat.c8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_open.c8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_openat.c8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_read.c9
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_sbrk.c39
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_stat.c9
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_sysconf.c16
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_times.c42
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_unlink.c8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_utime.c9
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_wait.c7
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_write.c19
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/button.h59
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/cache.h96
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/clock.h154
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/compiler.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/cpu.h271
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/fixed-clock.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/fixed-factor-clock.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_clint0.h24
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_cpu.h192
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_plic0.h31
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_ccache0.h23
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_clic0.h43
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_hfrosc.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_hfxosc.h20
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_lfrosc.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_pll.h26
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_prci.h24
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fu540-c000_l2.h23
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_global-external-interrupts0.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-buttons.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-leds.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-switches.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio0.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_local-external-interrupts0.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_rtc0.h27
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_spi0.h26
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_test0.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_trace.h23
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_uart0.h30
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_wdog0.h26
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/gpio.h284
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/interrupt.h461
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/io.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/itim.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/led.h68
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/lock.h146
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/memory.h81
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/pmp.h209
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/privilege.h122
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/rtc.h127
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/shutdown.h36
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/spi.h90
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/switch.h51
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/time.h18
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/timer.h36
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/tty.h52
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/uart.h106
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/watchdog.h163
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/button.c27
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/cache.c187
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/clock.c12
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/cpu.c59
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/fixed-clock.c29
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/fixed-factor-clock.c34
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/inline.c5
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/riscv_clint0.c283
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/riscv_cpu.c999
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/riscv_plic0.c195
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_ccache0.c84
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_clic0.c736
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfrosc.c44
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfxosc.c43
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_lfrosc.c53
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_pll.c360
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_prci.c28
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fu540-c000_l2.c84
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_global-external-interrupts0.c169
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-buttons.c57
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-leds.c85
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-switches.c56
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio0.c221
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_local-external-interrupts0.c151
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_rtc0.c121
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_spi0.c405
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_test0.c30
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_trace.c95
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_uart0.c173
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_wdog0.c213
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/entry.S106
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/gpio.c30
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/interrupt.c82
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/led.c38
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/lock.c8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/memory.c26
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/pmp.c586
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/privilege.c57
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/rtc.c27
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/shutdown.c22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/spi.c21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/switch.c27
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/synchronize_harts.c62
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/time.c30
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/timer.c80
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/trap.S53
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/tty.c51
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/uart.c11
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/vector.S160
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/full_demo/RegTest.S266
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/full_demo/main_full.c306
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/main.c275
189 files changed, 17952 insertions, 0 deletions
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/.cproject b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/.cproject
new file mode 100644
index 000000000..8efeeeefd
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/.cproject
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+
+ <cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480">
+
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480" moduleId="org.eclipse.cdt.core.settings" name="Debug">
+
+ <externalSettings/>
+
+ <extensions>
+
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+
+ </extensions>
+
+ </storageModule>
+
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+
+ <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480" name="Debug" parent="cdt.managedbuild.config.gnu.cross.exe.debug">
+
+ <folderInfo id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480." name="/" resourcePath="">
+
+ <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.debug.1023181676" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.debug">
+
+ <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.1119183919" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
+
+ <builder buildPath="${workspace_loc:/RTOSDemo}/Debug" id="cdt.managedbuild.builder.gnu.cross.1388532167" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.builder.gnu.cross"/>
+
+ <tool command="riscv64-unknown-elf-gcc.exe" id="cdt.managedbuild.tool.gnu.cross.c.compiler.1469975065" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
+
+ <option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.option.optimization.level.440219377" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
+
+ <option id="gnu.c.compiler.option.debugging.level.1721555429" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated"/>
+
+ <option id="gnu.c.compiler.option.dialect.std.1648189865" name="Language standard" superClass="gnu.c.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.c.compiler.dialect.default" valueType="enumerated"/>
+
+ <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.include.paths.1720192082" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
+
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/FreeRTOS_Source/include}&quot;"/>
+
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/full_demo/Common_Demo_Tasks/include}&quot;"/>
+
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}}&quot;"/>
+
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/FreeRTOS_Source/portable/GCC/RISC-V}&quot;"/>
+
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/FreeRTOS_Source/include}&quot;"/>
+
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/freedom-metal}&quot;"/>
+
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/bsp/install/include}&quot;"/>
+
+ </option>
+
+ <option id="gnu.c.compiler.option.misc.other.257964774" name="Other flags" superClass="gnu.c.compiler.option.misc.other" useByScannerDiscovery="false" value="-c -fmessage-length=0 -march=rv32imac -mabi=ilp32 -mcmodel=medlow -ffunction-sections -fdata-sections --specs=nano.specs -Wno-unused-parameter" valueType="string"/>
+
+ <option id="gnu.c.compiler.option.warnings.extrawarn.1802410957" name="Extra warnings (-Wextra)" superClass="gnu.c.compiler.option.warnings.extrawarn" useByScannerDiscovery="false" value="true" valueType="boolean"/>
+
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1079251302" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+
+ </tool>
+
+ <tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.420742449" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
+
+ <option id="gnu.cpp.compiler.option.optimization.level.1056760450" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
+
+ <option id="gnu.cpp.compiler.option.debugging.level.52506316" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
+
+ </tool>
+
+ <tool command="riscv64-unknown-elf-gcc.exe" id="cdt.managedbuild.tool.gnu.cross.c.linker.558060359" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker">
+
+ <option id="gnu.c.link.option.ldflags.46965227" name="Linker flags" superClass="gnu.c.link.option.ldflags" useByScannerDiscovery="false" value="-Xlinker --gc-sections -Wl,-Map,RTOSDemo.map -T../bsp/metal.default.lds -march=rv32imac -mabi=ilp32 -mcmodel=medlow -Wl,--start-group -lc -lgcc -Wl,--end-group --specs=nano.specs" valueType="string"/>
+
+ <option id="gnu.c.link.option.nostart.1038463237" name="Do not use standard start files (-nostartfiles)" superClass="gnu.c.link.option.nostart" useByScannerDiscovery="false" value="true" valueType="boolean"/>
+
+ <option id="gnu.c.link.option.nostdlibs.934043026" name="No startup or default libs (-nostdlib)" superClass="gnu.c.link.option.nostdlibs" useByScannerDiscovery="false" value="false" valueType="boolean"/>
+
+ <option id="gnu.c.link.option.nodeflibs.1095611620" name="Do not use default libraries (-nodefaultlibs)" superClass="gnu.c.link.option.nodeflibs" useByScannerDiscovery="false" value="false" valueType="boolean"/>
+
+ <inputType id="cdt.managedbuild.tool.gnu.c.linker.input.549526426" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
+
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+
+ </inputType>
+
+ </tool>
+
+ <tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.2105463183" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker"/>
+
+ <tool id="cdt.managedbuild.tool.gnu.cross.archiver.424513814" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
+
+ <tool command="riscv64-unknown-elf-gcc.exe" id="cdt.managedbuild.tool.gnu.cross.assembler.825438707" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
+
+ <option id="gnu.both.asm.option.flags.1946908814" name="Assembler flags" superClass="gnu.both.asm.option.flags" useByScannerDiscovery="false" value="-march=rv32imac -mabi=ilp32 -mcmodel=medlow -c -DportasmHANDLE_INTERRUPT=handle_trap -g3" valueType="string"/>
+
+ <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.both.asm.option.include.paths.1448234506" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
+
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/FreeRTOS_Source/portable/GCC/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions}&quot;"/>
+
+ </option>
+
+ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1723023894" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+
+ </tool>
+
+ </toolChain>
+
+ </folderInfo>
+
+ <sourceEntries>
+
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
+
+ </sourceEntries>
+
+ </configuration>
+
+ </storageModule>
+
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+
+ </cconfiguration>
+
+ </storageModule>
+
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+
+ <project id="RTOSDemo.cdt.managedbuild.target.gnu.cross.exe.1669036252" name="Executable" projectType="cdt.managedbuild.target.gnu.cross.exe"/>
+
+ </storageModule>
+
+ <storageModule moduleId="scannerConfiguration">
+
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+
+ <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.cross.exe.debug.206163480;cdt.managedbuild.config.gnu.cross.exe.debug.206163480.;cdt.managedbuild.tool.gnu.cross.c.compiler.1469975065;cdt.managedbuild.tool.gnu.c.compiler.input.1079251302">
+
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+
+ </scannerConfigBuildInfo>
+
+ </storageModule>
+
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+
+ <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+
+ <storageModule moduleId="refreshScope" versionNumber="2">
+
+ <configuration configurationName="Debug">
+
+ <resource resourceType="PROJECT" workspacePath="/RTOSDemo"/>
+
+ </configuration>
+
+ </storageModule>
+
+</cproject>
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/.project b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/.project
new file mode 100644
index 000000000..f22f74077
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/.project
@@ -0,0 +1,303 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>RTOSDemo</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+ <triggers>clean,full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+ <triggers>full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.cdt.core.cnature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+ </natures>
+ <linkedResources>
+ <link>
+ <name>FreeRTOS_Source</name>
+ <type>2</type>
+ <locationURI>FREERTOS_ROOT/FreeRTOS/Source</locationURI>
+ </link>
+ <link>
+ <name>full_demo/Common_Demo_Tasks</name>
+ <type>2</type>
+ <locationURI>FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal</locationURI>
+ </link>
+ <link>
+ <name>full_demo/Common_Demo_Tasks/include</name>
+ <type>2</type>
+ <locationURI>FREERTOS_ROOT/FreeRTOS/Demo/Common/include</locationURI>
+ </link>
+ </linkedResources>
+ <filteredResources>
+ <filter>
+ <id>1570727806810</id>
+ <name>FreeRTOS_Source</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-event_groups.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727806825</id>
+ <name>FreeRTOS_Source</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-list.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727806841</id>
+ <name>FreeRTOS_Source</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-queue.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727806841</id>
+ <name>FreeRTOS_Source</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-stream_buffer.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727806841</id>
+ <name>FreeRTOS_Source</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-timers.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727806856</id>
+ <name>FreeRTOS_Source</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-tasks.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727892841</id>
+ <name>FreeRTOS_Source/include</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-event_groups.h</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727892856</id>
+ <name>FreeRTOS_Source/include</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-FreeRTOS.h</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727892856</id>
+ <name>FreeRTOS_Source/include</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-message_buffer.h</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727892856</id>
+ <name>FreeRTOS_Source/include</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-queue.h</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727892872</id>
+ <name>FreeRTOS_Source/include</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-semphr.h</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727892872</id>
+ <name>FreeRTOS_Source/include</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-stream_buffer.h</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727892888</id>
+ <name>FreeRTOS_Source/include</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-task.h</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727892888</id>
+ <name>FreeRTOS_Source/include</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-timers.h</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727962643</id>
+ <name>FreeRTOS_Source/portable</name>
+ <type>9</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-MemMang</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727962643</id>
+ <name>FreeRTOS_Source/portable</name>
+ <type>9</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-GCC</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1571005814144</id>
+ <name>full_demo/Common_Demo_Tasks</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-TimerDemo.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1571005814150</id>
+ <name>full_demo/Common_Demo_Tasks</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-blocktim.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1571005814159</id>
+ <name>full_demo/Common_Demo_Tasks</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-dynamic.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1571005814167</id>
+ <name>full_demo/Common_Demo_Tasks</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-TaskNotify.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727992991</id>
+ <name>FreeRTOS_Source/portable/GCC</name>
+ <type>9</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-RISC-V</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570727979500</id>
+ <name>FreeRTOS_Source/portable/MemMang</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-heap_4.c</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1571005832815</id>
+ <name>full_demo/Common_Demo_Tasks/include</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-TimerDemo.h</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1571005832820</id>
+ <name>full_demo/Common_Demo_Tasks/include</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-blocktim.h</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1571005832824</id>
+ <name>full_demo/Common_Demo_Tasks/include</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-dynamic.h</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1571005832829</id>
+ <name>full_demo/Common_Demo_Tasks/include</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-MessageBufferDemo.h</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1571005832835</id>
+ <name>full_demo/Common_Demo_Tasks/include</name>
+ <type>5</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-TaskNotify.h</arguments>
+ </matcher>
+ </filter>
+ <filter>
+ <id>1570728021983</id>
+ <name>FreeRTOS_Source/portable/GCC/RISC-V/chip_specific_extensions</name>
+ <type>9</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-name-matches-false-false-RV32I_CLINT_no_extensions</arguments>
+ </matcher>
+ </filter>
+ </filteredResources>
+ <variableList>
+ <variable>
+ <name>FREERTOS_ROOT</name>
+ <value>$%7BPARENT-3-PROJECT_LOC%7D</value>
+ </variable>
+ </variableList>
+</projectDescription>
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/.settings/language.settings.xml b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/.settings/language.settings.xml
new file mode 100644
index 000000000..b0d04ea76
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/.settings/language.settings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project>
+
+ <configuration id="cdt.managedbuild.config.gnu.cross.exe.debug.206163480" name="Debug">
+
+ <extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
+
+ <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
+
+ <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
+
+ <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
+
+ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-316647897902857" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+
+ <language-scope id="org.eclipse.cdt.core.gcc"/>
+
+ <language-scope id="org.eclipse.cdt.core.g++"/>
+
+ </provider>
+
+ </extension>
+
+ </configuration>
+
+</project>
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/FreeRTOSConfig.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/FreeRTOSConfig.h
new file mode 100644
index 000000000..a7a0c1180
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/FreeRTOSConfig.h
@@ -0,0 +1,101 @@
+/*
+ * FreeRTOS Kernel V10.2.1
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html.
+ *----------------------------------------------------------*/
+#define CLINT_CTRL_ADDR ( 0x02000000UL )
+#define configCLINT_BASE_ADDRESS CLINT_CTRL_ADDR
+#define configUSE_PREEMPTION 1
+#define configUSE_IDLE_HOOK 0
+#define configUSE_TICK_HOOK 1
+#define configCPU_CLOCK_HZ ( 32768 )
+#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
+#define configMAX_PRIORITIES ( 7 )
+#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 120 ) /* Only needs to be this high as some demo tasks also use this constant. In production only the idle task would use this. */
+#define configTOTAL_HEAP_SIZE ( ( size_t ) 10900 )
+#define configMAX_TASK_NAME_LEN ( 16 )
+#define configUSE_TRACE_FACILITY 0
+#define configUSE_16_BIT_TICKS 0
+#define configIDLE_SHOULD_YIELD 0
+#define configUSE_MUTEXES 1
+#define configQUEUE_REGISTRY_SIZE 8
+#define configCHECK_FOR_STACK_OVERFLOW 2
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configUSE_MALLOC_FAILED_HOOK 1
+#define configUSE_APPLICATION_TASK_TAG 0
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configGENERATE_RUN_TIME_STATS 0
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
+
+/* Co-routine definitions. */
+#define configUSE_CO_ROUTINES 0
+#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
+
+/* Software timer definitions. */
+#define configUSE_TIMERS 1
+#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
+#define configTIMER_QUEUE_LENGTH 8
+#define configTIMER_TASK_STACK_DEPTH ( 160 )
+
+/* Task priorities. Allow these to be overridden. */
+#ifndef uartPRIMARY_PRIORITY
+ #define uartPRIMARY_PRIORITY ( configMAX_PRIORITIES - 3 )
+#endif
+
+/* Set the following definitions to 1 to include the API function, or zero
+to exclude the API function. */
+#define INCLUDE_vTaskPrioritySet 1
+#define INCLUDE_uxTaskPriorityGet 1
+#define INCLUDE_vTaskDelete 1
+#define INCLUDE_vTaskCleanUpResources 1
+#define INCLUDE_vTaskSuspend 1
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_eTaskGetState 1
+#define INCLUDE_xTimerPendFunctionCall 1
+#define INCLUDE_xTaskAbortDelay 1
+#define INCLUDE_xTaskGetHandle 1
+#define INCLUDE_xSemaphoreGetMutexHolder 1
+
+/* Normal assert() semantics without relying on the provision of an assert.h
+header file. */
+void vAssertCalled( void );
+#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled()
+
+#endif /* FREERTOS_CONFIG_H */
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/blinky_demo/main_blinky.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/blinky_demo/main_blinky.c
new file mode 100644
index 000000000..30aeb1baa
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/blinky_demo/main_blinky.c
@@ -0,0 +1,197 @@
+/*
+ * FreeRTOS Kernel V10.2.1
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+
+/******************************************************************************
+ * NOTE 1: This project provides two demo applications. A simple blinky
+ * style project, and a more comprehensive test and demo application. The
+ * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select
+ * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY
+ * in main.c. This file implements the simply blinky style version.
+ *
+ * NOTE 2: This file only contains the source code that is specific to the
+ * blinky demo. Generic functions, such FreeRTOS hook functions, and functions
+ * required to configure the hardware are defined in main.c.
+ ******************************************************************************
+ *
+ * main_blinky() creates one queue, and two tasks. It then starts the
+ * scheduler.
+ *
+ * The Queue Send Task:
+ * The queue send task is implemented by the prvQueueSendTask() function in
+ * this file. prvQueueSendTask() sits in a loop that causes it to repeatedly
+ * block for 1000 milliseconds, before sending the value 100 to the queue that
+ * was created within main_blinky(). Once the value is sent, the task loops
+ * back around to block for another 1000 milliseconds...and so on.
+ *
+ * The Queue Receive Task:
+ * The queue receive task is implemented by the prvQueueReceiveTask() function
+ * in this file. prvQueueReceiveTask() sits in a loop where it repeatedly
+ * blocks on attempts to read data from the queue that was created within
+ * main_blinky(). When data is received, the task checks the value of the
+ * data, and if the value equals the expected 100, toggles an LED. The 'block
+ * time' parameter passed to the queue receive function specifies that the task
+ * should be held in the Blocked state indefinitely to wait for data to be
+ * available on the queue. The queue receive task will only leave the Blocked
+ * state when the queue send task writes to the queue. As the queue send task
+ * writes to the queue every 1000 milliseconds, the queue receive task leaves
+ * the Blocked state every 1000 milliseconds, and therefore toggles the LED
+ * every 200 milliseconds.
+ */
+
+/* Standard includes. */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Kernel includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+
+/* Priorities used by the tasks. */
+#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
+#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
+
+/* The rate at which data is sent to the queue. The 200ms value is converted
+to ticks using the pdMS_TO_TICKS() macro. */
+#define mainQUEUE_SEND_FREQUENCY_MS pdMS_TO_TICKS( 1000 )
+
+/* The maximum number items the queue can hold. The priority of the receiving
+task is above the priority of the sending task, so the receiving task will
+preempt the sending task and remove the queue items each time the sending task
+writes to the queue. Therefore the queue will never have more than one item in
+it at any time, and even with a queue length of 1, the sending task will never
+find the queue full. */
+#define mainQUEUE_LENGTH ( 1 )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Called by main when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1 in
+ * main.c.
+ */
+void main_blinky( void );
+
+/*
+ * The tasks as described in the comments at the top of this file.
+ */
+static void prvQueueReceiveTask( void *pvParameters );
+static void prvQueueSendTask( void *pvParameters );
+
+/*-----------------------------------------------------------*/
+
+/* The queue used by both tasks. */
+static QueueHandle_t xQueue = NULL;
+
+/*-----------------------------------------------------------*/
+
+void main_blinky( void )
+{
+ /* Create the queue. */
+ xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
+
+ if( xQueue != NULL )
+ {
+ /* Start the two tasks as described in the comments at the top of this
+ file. */
+ xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */
+ "Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
+ configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
+ NULL, /* The parameter passed to the task - not used in this case. */
+ mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */
+ NULL ); /* The task handle is not required, so NULL is passed. */
+
+ xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );
+
+ /* Start the tasks and timer running. */
+ vTaskStartScheduler();
+ }
+
+ /* If all is well, the scheduler will now be running, and the following
+ line will never be reached. If the following line does execute, then
+ there was insufficient FreeRTOS heap memory available for the Idle and/or
+ timer tasks to be created. See the memory management section on the
+ FreeRTOS web site for more details on the FreeRTOS heap
+ http://www.freertos.org/a00111.html. */
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+static void prvQueueSendTask( void *pvParameters )
+{
+TickType_t xNextWakeTime;
+const unsigned long ulValueToSend = 100UL;
+BaseType_t xReturned;
+
+ /* Remove compiler warning about unused parameter. */
+ ( void ) pvParameters;
+
+ /* Initialise xNextWakeTime - this only needs to be done once. */
+ xNextWakeTime = xTaskGetTickCount();
+
+ for( ;; )
+ {
+ /* Place this task in the blocked state until it is time to run again. */
+ vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );
+
+ /* Send to the queue - causing the queue receive task to unblock and
+ toggle the LED. 0 is used as the block time so the sending operation
+ will not block - it shouldn't need to block as the queue should always
+ be empty at this point in the code. */
+ xReturned = xQueueSend( xQueue, &ulValueToSend, 0U );
+ configASSERT( xReturned == pdPASS );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvQueueReceiveTask( void *pvParameters )
+{
+unsigned long ulReceivedValue;
+const unsigned long ulExpectedValue = 100UL;
+extern void vToggleLED( void );
+
+ /* Remove compiler warning about unused parameter. */
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ /* Wait until something arrives in the queue - this task will block
+ indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
+ FreeRTOSConfig.h. */
+ xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
+
+ /* To get here something must have been received from the queue, but
+ is it the expected value? If it is, toggle the LED. */
+ if( ulReceivedValue == ulExpectedValue )
+ {
+ vToggleLED();
+ ulReceivedValue = 0U;
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/design.dts b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/design.dts
new file mode 100644
index 000000000..970d3be72
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/design.dts
@@ -0,0 +1,209 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "sifive,hifive1-revb";
+ model = "sifive,hifive1-revb";
+
+ chosen {
+ stdout-path = "/soc/serial@10013000:115200";
+ metal,entry = <&spi0 0x10000>;
+ };
+
+ 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,dtim = <&dtim>;
+ status = "okay";
+ timebase-frequency = <1000000>;
+ 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>;
+ };
+
+ lfroscin: clock@5 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32000000>;
+ };
+ lfclk: clock@6 {
+ compatible = "sifive,fe310-g000,lfrosc";
+ clocks = <&lfroscin>;
+ reg = <&aon 0x70>;
+ reg-names = "config";
+ };
+
+ aon: aon@10000000 {
+ compatible = "sifive,aon0";
+ reg = <0x10000000 0x8000>;
+ reg-names = "mem";
+ };
+
+ prci: prci@10008000 {
+ compatible = "sifive,fe310-g000,prci";
+ reg = <0x10008000 0x8000>;
+ reg-names = "mem";
+ };
+
+ clint: clint@2000000 {
+ compatible = "riscv,clint0";
+ interrupts-extended = <&hlic 3 &hlic 7>;
+ reg = <0x2000000 0x10000>;
+ reg-names = "control";
+ };
+ local-external-interrupts-0 {
+ compatible = "sifive,local-external-interrupts0";
+ interrupt-parent = <&hlic>;
+ interrupts = <16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31>;
+ };
+ 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 = <26>;
+ };
+ global-external-interrupts {
+ compatile = "sifive,global-external-interrupts0";
+ interrupt-parent = <&plic>;
+ interrupts = <1 2 3 4>;
+ };
+
+ debug-controller@0 {
+ compatible = "sifive,debug-011", "riscv,debug-011";
+ interrupts-extended = <&hlic 65535>;
+ reg = <0x0 0x100>;
+ reg-names = "control";
+ };
+
+ maskrom@1000 {
+ reg = <0x1000 0x2000>;
+ reg-names = "mem";
+ };
+ otp@20000 {
+ reg = <0x20000 0x2000 0x10010000 0x1000>;
+ reg-names = "mem", "control";
+ };
+
+ dtim: dtim@80000000 {
+ compatible = "sifive,dtim0";
+ reg = <0x80000000 0x4000>;
+ reg-names = "mem";
+ };
+
+ pwm@10015000 {
+ compatible = "sifive,pwm0";
+ interrupt-parent = <&plic>;
+ interrupts = <23 24 25 26>;
+ reg = <0x10015000 0x1000>;
+ reg-names = "control";
+ };
+ gpio0: gpio@10012000 {
+ compatible = "sifive,gpio0";
+ interrupt-parent = <&plic>;
+ interrupts = <7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22>;
+ reg = <0x10012000 0x1000>;
+ reg-names = "control";
+ };
+ uart0: serial@10013000 {
+ compatible = "sifive,uart0";
+ interrupt-parent = <&plic>;
+ interrupts = <5>;
+ reg = <0x10013000 0x1000>;
+ reg-names = "control";
+ clocks = <&hfclk>;
+ pinmux = <&gpio0 0x30000 0x30000>;
+ };
+ spi0: spi@10014000 {
+ compatible = "sifive,spi0";
+ interrupt-parent = <&plic>;
+ interrupts = <6>;
+ reg = <0x10014000 0x1000 0x20000000 0x7A120>;
+ reg-names = "control", "mem";
+ clocks = <&hfclk>;
+ pinmux = <&gpio0 0x0003C 0x0003C>;
+ };
+ i2c0: i2c@10016000 {
+ compatible = "sifive,i2c0";
+ interrupt-parent = <&plic>;
+ interrupts = <52>;
+ reg = <0x10016000 0x1000>;
+ reg-names = "control";
+ };
+ led@0red {
+ compatible = "sifive,gpio-leds";
+ label = "LD0red";
+ gpios = <&gpio0 22>;
+ linux,default-trigger = "none";
+ };
+ led@0green {
+ compatible = "sifive,gpio-leds";
+ label = "LD0green";
+ gpios = <&gpio0 19>;
+ linux,default-trigger = "none";
+ };
+ led@0blue {
+ compatible = "sifive,gpio-leds";
+ label = "LD0blue";
+ gpios = <&gpio0 21>;
+ linux,default-trigger = "none";
+ };
+ };
+};
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/design.reglist b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/design.reglist
new file mode 100644
index 000000000..921dd83ac
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/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/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/button.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/button.h
new file mode 100644
index 000000000..0c26f435a
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/button.h
@@ -0,0 +1,59 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__BUTTON_H
+#define METAL__BUTTON_H
+
+/*!
+ * @file button.h
+ * API for interfacing with physical buttons
+ */
+
+#include <metal/interrupt.h>
+
+struct metal_button;
+
+struct metal_button_vtable {
+ int (*button_exist)(struct metal_button *button, char *label);
+ struct metal_interrupt* (*interrupt_controller)(struct metal_button *button);
+ int (*get_interrupt_id)(struct metal_button *button);
+};
+
+/*!
+ * @brief A button device handle
+ *
+ * A `struct metal_button` is an implementation-defined object which represents
+ * a button on a development board.
+ */
+struct metal_button {
+ const struct metal_button_vtable *vtable;
+};
+
+/*!
+ * @brief Get a reference to a button
+ *
+ * @param label The DeviceTree label for the button
+ * @return A handle for the button
+ */
+struct metal_button* metal_button_get(char *label);
+
+
+/*!
+ * @brief Get the interrupt controller for a button
+ *
+ * @param button The handle for the button
+ * @return A pointer to the interrupt controller responsible for handling
+ * button interrupts.
+ */
+inline struct metal_interrupt*
+ metal_button_interrupt_controller(struct metal_button *button) { return button->vtable->interrupt_controller(button); }
+
+/*!
+ * @brief Get the interrupt id for a button
+ *
+ * @param button The handle for the button
+ * @return The interrupt id corresponding to a button.
+ */
+inline int metal_button_get_interrupt_id(struct metal_button *button) { return button->vtable->get_interrupt_id(button); }
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/cache.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/cache.h
new file mode 100644
index 000000000..a8a60ada6
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/cache.h
@@ -0,0 +1,58 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__CACHE_H
+#define METAL__CACHE_H
+
+/*!
+ * @file cache.h
+ *
+ * @brief API for configuring caches
+ */
+
+struct metal_cache;
+
+struct __metal_cache_vtable {
+ void (*init)(struct metal_cache *cache, int ways);
+ int (*get_enabled_ways)(struct metal_cache *cache);
+ int (*set_enabled_ways)(struct metal_cache *cache, int ways);
+};
+
+/*!
+ * @brief a handle for a cache
+ */
+struct metal_cache {
+ const struct __metal_cache_vtable *vtable;
+};
+
+/*!
+ * @brief Initialize a cache
+ * @param cache The handle for the cache to initialize
+ * @param ways The number of ways to enable
+ *
+ * Initializes a cache with the requested number of ways enabled.
+ */
+inline void metal_cache_init(struct metal_cache *cache, int ways) {
+ return cache->vtable->init(cache, ways);
+}
+
+/*!
+ * @brief Get the current number of enabled cache ways
+ * @param cache The handle for the cache
+ * @return The current number of enabled cache ways
+ */
+inline int metal_cache_get_enabled_ways(struct metal_cache *cache) {
+ return cache->vtable->get_enabled_ways(cache);
+}
+
+/*!
+ * @brief Enable the requested number of cache ways
+ * @param cache The handle for the cache
+ * @param ways The number of ways to enabled
+ * @return 0 if the ways are successfully enabled
+ */
+inline int metal_cache_set_enabled_ways(struct metal_cache *cache, int ways) {
+ return cache->vtable->set_enabled_ways(cache, ways);
+}
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/clock.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/clock.h
new file mode 100644
index 000000000..277841e01
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/clock.h
@@ -0,0 +1,119 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__CLOCK_H
+#define METAL__CLOCK_H
+
+/*!
+ * @file clock.h
+ * @brief API for manipulating clock sources
+ *
+ * The clock interface allows for controlling the rate of various clocks in the system.
+ */
+
+struct metal_clock;
+
+#include <stddef.h>
+
+/* The generic interface to all clocks. */
+struct __metal_clock_vtable {
+ long (*get_rate_hz)(const struct metal_clock *clk);
+ long (*set_rate_hz)(struct metal_clock *clk, long hz);
+};
+
+/*!
+ * @brief Function signature of clock pre-rate change callbacks
+ */
+typedef void (*metal_clock_pre_rate_change_callback)(void *priv);
+
+/*!
+ * @brief Function signature of clock post-rate change callbacks
+ */
+typedef void (*metal_clock_post_rate_change_callback)(void *priv);
+
+/*!
+ * @struct metal_clock
+ * @brief The handle for a clock
+ *
+ * Clocks are defined as a pointer to a `struct metal_clock`, the contents of which
+ * are implementation defined. Users of the clock interface must call functions
+ * which accept a `struct metal_clock *` as an argument to interract with the clock.
+ *
+ * Note that no mechanism for obtaining a pointer to a `struct metal_clock` has been
+ * defined, making it impossible to call any of these functions without invoking
+ * implementation-defined behavior.
+ */
+struct metal_clock {
+ const struct __metal_clock_vtable *vtable;
+
+ /* Pre-rate change callback */
+ metal_clock_pre_rate_change_callback _pre_rate_change_callback;
+ void *_pre_rate_change_callback_priv;
+
+ /* Post-rate change callback */
+ metal_clock_post_rate_change_callback _post_rate_change_callback;
+ void *_post_rate_change_callback_priv;
+};
+
+/*!
+ * @brief Returns the current rate of the given clock
+ *
+ * @param clk The handle for the clock
+ * @return The current rate of the clock in Hz
+ */
+inline long metal_clock_get_rate_hz(const struct metal_clock *clk) { return clk->vtable->get_rate_hz(clk); }
+
+/*!
+ * @brief Set the current rate of a clock
+ *
+ * @param clk The handle for the clock
+ * @param hz The desired rate in Hz
+ * @return The new rate of the clock in Hz.
+ *
+ * Attempts to set the current rate of the given clock to as close as possible
+ * to the given rate in Hz. Returns the actual value that's been selected, which
+ * could be anything!
+ *
+ * Prior to and after the rate change of the clock, this will call the registered
+ * pre- and post-rate change callbacks.
+ */
+inline long metal_clock_set_rate_hz(struct metal_clock *clk, long hz)
+{
+ if(clk->_pre_rate_change_callback != NULL)
+ clk->_pre_rate_change_callback(clk->_pre_rate_change_callback_priv);
+
+ long out = clk->vtable->set_rate_hz(clk, hz);
+
+ if (clk->_post_rate_change_callback != NULL)
+ clk->_post_rate_change_callback(clk->_post_rate_change_callback_priv);
+
+ return out;
+}
+
+/*!
+ * @brief Register a callback that must be called before a rate change
+ *
+ * @param clk The handle for the clock
+ * @param cb The callback to be registered
+ * @param priv Private data for the callback handler
+ */
+inline void metal_clock_register_pre_rate_change_callback(struct metal_clock *clk, metal_clock_pre_rate_change_callback cb, void *priv)
+{
+ clk->_pre_rate_change_callback = cb;
+ clk->_pre_rate_change_callback_priv = priv;
+}
+
+/*!
+ * @brief Registers a callback that must be called after a rate change
+ *
+ * @param clk The handle for the clock
+ * @param cb The callback to be registered
+ * @param priv Private data for the callback handler
+ */
+inline void metal_clock_register_post_rate_change_callback(struct metal_clock *clk, metal_clock_post_rate_change_callback cb, void *priv)
+{
+ clk->_post_rate_change_callback = cb;
+ clk->_post_rate_change_callback_priv = priv;
+}
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/compiler.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/compiler.h
new file mode 100644
index 000000000..62c0ea975
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/compiler.h
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__COMPILER_H
+#define METAL__COMPILER_H
+
+#define __METAL_DECLARE_VTABLE(type) \
+ extern const struct type type;
+
+#define __METAL_DEFINE_VTABLE(type) \
+ const struct type type
+
+#define __METAL_GET_FIELD(reg, mask) \
+ (((reg) & (mask)) / ((mask) & ~((mask) << 1)))
+
+/* Set field with mask for a given value */
+#define __METAL_SET_FIELD(reg, mask, val) \
+ (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask)))
+
+void _metal_trap(int ecode);
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/cpu.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/cpu.h
new file mode 100644
index 000000000..453bd12de
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/cpu.h
@@ -0,0 +1,271 @@
+/* Copyright 2018 SiFive, Inc */
+
+/* SPDX-License-Identifier: Apache-2.0 */
+
+/*! @file cpu.h
+ * @brief API for accessing CPU capabilities.
+ */
+
+#ifndef METAL__CPU_H
+#define METAL__CPU_H
+
+#include <stdint.h>
+#include <metal/interrupt.h>
+
+struct metal_cpu;
+
+/*!
+ * @brief Function signature for exception handlers
+ */
+typedef void (*metal_exception_handler_t) (struct metal_cpu *cpu, int ecode);
+
+struct metal_cpu_vtable {
+ unsigned long long (*timer_get)(struct metal_cpu *cpu);
+ unsigned long long (*timebase_get)(struct metal_cpu *cpu);
+ unsigned long long (*mtime_get)(struct metal_cpu *cpu);
+ int (*mtimecmp_set)(struct metal_cpu *cpu, unsigned long long time);
+ struct metal_interrupt* (*tmr_controller_interrupt)(struct metal_cpu *cpu);
+ int (*get_tmr_interrupt_id)(struct metal_cpu *cpu);
+ struct metal_interrupt* (*sw_controller_interrupt)(struct metal_cpu *cpu);
+ int (*get_sw_interrupt_id)(struct metal_cpu *cpu);
+ int (*set_sw_ipi)(struct metal_cpu *cpu, int hartid);
+ int (*clear_sw_ipi)(struct metal_cpu *cpu, int hartid);
+ int (*get_msip)(struct metal_cpu *cpu, int hartid);
+ struct metal_interrupt* (*controller_interrupt)(struct metal_cpu *cpu);
+ int (*exception_register)(struct metal_cpu *cpu, int ecode, metal_exception_handler_t handler);
+ int (*get_ilen)(struct metal_cpu *cpu, uintptr_t epc);
+ uintptr_t (*get_epc)(struct metal_cpu *cpu);
+ int (*set_epc)(struct metal_cpu *cpu, uintptr_t epc);
+};
+
+/*! @brief A device handle for a CPU hart
+ */
+struct metal_cpu {
+ const struct metal_cpu_vtable *vtable;
+};
+
+/*! @brief Get a reference to a CPU hart
+ *
+ * @param hartid The ID of the desired CPU hart
+ * @return A pointer to the CPU device handle
+ */
+struct metal_cpu* metal_cpu_get(int hartid);
+
+/*! @brief Get the hartid of the CPU hart executing this function
+ *
+ * @return The hartid of the current CPU hart */
+int metal_cpu_get_current_hartid();
+
+/*! @brief Get the number of CPU harts
+ *
+ * @return The number of CPU harts */
+int metal_cpu_get_num_harts();
+
+/*! @brief Get the CPU cycle count timer value
+ *
+ * Get the value of the cycle count timer for a given CPU
+ *
+ * @param cpu The CPU device handle
+ * @return The value of the CPU cycle count timer
+ */
+inline unsigned long long metal_cpu_get_timer(struct metal_cpu *cpu)
+{ return cpu->vtable->timer_get(cpu); }
+
+/*! @brief Get the timebase of the CPU
+ *
+ * Get the value of the timebase of the cycle count timer
+ *
+ * @param cpu The CPU device handle
+ * @return The value of the cycle count timer timebase
+ */
+inline unsigned long long metal_cpu_get_timebase(struct metal_cpu *cpu)
+{ return cpu->vtable->timebase_get(cpu); }
+
+/*! @brief Get the value of the mtime RTC
+ *
+ * Get the value of the mtime real-time clock. The CPU interrupt controller
+ * must be initialized before this function is called or the return value
+ * will be 0.
+ *
+ * @param cpu The CPU device handle
+ * @return The value of mtime, or 0 if failure
+ */
+inline unsigned long long metal_cpu_get_mtime(struct metal_cpu *cpu)
+{ return cpu->vtable->mtime_get(cpu); }
+
+/*! @brief Set the value of the RTC mtimecmp RTC
+ *
+ * Set the value of the mtime real-time clock compare register. The CPU
+ * interrupt controller must be initialized before this function is called
+ * or the return value will be -1;
+ *
+ * @param cpu The CPU device handle
+ * @param time The value to set the compare register to
+ * @return The value of mtimecmp or -1 if error
+ */
+inline int metal_cpu_set_mtimecmp(struct metal_cpu *cpu, unsigned long long time)
+{ return cpu->vtable->mtimecmp_set(cpu, time); }
+
+/*! @brief Get a reference to RTC timer interrupt controller
+ *
+ * Get a reference to the interrupt controller for the real-time clock interrupt.
+ * The controller returned by this function must be initialized before any interrupts
+ * are registered or enabled with it.
+ *
+ * @param cpu The CPU device handle
+ * @return A pointer to the timer interrupt handle
+ */
+inline struct metal_interrupt* metal_cpu_timer_interrupt_controller(struct metal_cpu *cpu)
+{ return cpu->vtable->tmr_controller_interrupt(cpu); }
+
+/*! @brief Get the RTC timer interrupt id
+ *
+ * Get the interrupt ID of the real-time clock interrupt
+ *
+ * @param cpu The CPU device handle
+ * @return The timer interrupt ID
+ */
+inline int metal_cpu_timer_get_interrupt_id(struct metal_cpu *cpu)
+{ return cpu->vtable->get_tmr_interrupt_id(cpu); }
+
+/*! @brief Get a reference to the software interrupt controller
+ *
+ * Get a reference to the interrupt controller for the software/inter-process
+ * interrupt. The controller returned by this function must be initialized before
+ * any interrupts are registered or enabled with it.
+ *
+ * @param cpu The CPU device handle
+ * @return A pointer to the software interrupt handle
+ */
+inline struct metal_interrupt* metal_cpu_software_interrupt_controller(struct metal_cpu *cpu)
+{ return cpu->vtable->sw_controller_interrupt(cpu); }
+
+/*! @brief Get the software interrupt id
+ *
+ * Get the interrupt ID for the software/inter-process interrupt
+ *
+ * @param cpu The CPU device handle
+ * @return the software interrupt ID
+ */
+inline int metal_cpu_software_get_interrupt_id(struct metal_cpu *cpu)
+{ return cpu->vtable->get_sw_interrupt_id(cpu); }
+
+/*!
+ * @brief Set the inter-process interrupt for a hart
+ *
+ * Trigger a software/inter-process interrupt for a hart. The CPU interrupt
+ * controller for the CPU handle passed to this function must be initialized
+ * before this function is called.
+ *
+ * @param cpu The CPU device handle
+ * @param hartid The CPU hart ID to be interrupted
+ * @return 0 upon success
+ */
+inline int metal_cpu_software_set_ipi(struct metal_cpu *cpu, int hartid)
+{ return cpu->vtable->set_sw_ipi(cpu, hartid); }
+
+/*!
+ * @brief Clear the inter-process interrupt for a hart
+ *
+ * Clear the software/inter-process interrupt for a hart. The CPU interrupt
+ * controller for the CPU handle passed to this function must be initialized
+ * before this function is called.
+ *
+ * @param cpu The CPU device handle
+ * @param hartid The CPU hart ID to clear
+ * @return 0 upon success
+ */
+inline int metal_cpu_software_clear_ipi(struct metal_cpu *cpu, int hartid)
+{ return cpu->vtable->clear_sw_ipi(cpu, hartid); }
+
+/*!
+ * @brief Get the value of MSIP for the given hart
+ *
+ * Get the value of the machine software interrupt pending bit for
+ * the given hart. The CPU interrupt controller for the CPU handle passed
+ * as argument to this function must be initialized before this function
+ * is called.
+ *
+ * @param cpu the CPU device handle
+ * @param hartid The CPU hart to read
+ * @return 0 upon success
+ */
+inline int metal_cpu_get_msip(struct metal_cpu *cpu, int hartid)
+{ return cpu->vtable->get_msip(cpu, hartid); }
+
+/*!
+ * @brief Get the interrupt controller for the CPU
+ *
+ * Get the CPU interrupt controller. The controller returned by this
+ * function must be initialized before any interrupts are registered
+ * or enabled and before any exception handlers are registered with
+ * this CPU.
+ *
+ * @param cpu The CPU device handle
+ * @return The handle for the CPU interrupt controller
+ */
+inline struct metal_interrupt* metal_cpu_interrupt_controller(struct metal_cpu *cpu)
+{ return cpu->vtable->controller_interrupt(cpu); }
+
+/*!
+ * @brief Register an exception handler
+ *
+ * Register an exception handler for the CPU. The CPU interrupt controller must be initialized
+ * before this function is called.
+ *
+ * @param cpu The CPU device handle
+ * @param ecode The exception code to register a handler for
+ * @param handler Callback function for the exception handler
+ * @return 0 upon success
+ */
+inline int metal_cpu_exception_register(struct metal_cpu *cpu, int ecode, metal_exception_handler_t handler)
+{ return cpu->vtable->exception_register(cpu, ecode, handler); }
+
+/*!
+ * @brief Get the length of an instruction in bytes
+ *
+ * Get the length of an instruction in bytes.
+ *
+ * On RISC-V platforms, this is useful for detecting whether an instruction is
+ * compressed (2 bytes long) or uncompressed (4 bytes long).
+ *
+ * This function is useful in conjuction with `metal_cpu_get_exception_pc()`
+ * and `metal_cpu_set_exception_pc()` in order to cause the exception handler to
+ * return execution after the faulting instruction.
+ *
+ * @param cpu The CPU device handle
+ * @param epc The address of the instruction to measure
+ * @return the length of the instruction in bytes
+ */
+inline int metal_cpu_get_instruction_length(struct metal_cpu *cpu, uintptr_t epc)
+{ return cpu->vtable->get_ilen(cpu, epc); }
+
+/*!
+ * @brief Get the program counter of the current exception.
+ *
+ * This function must be called within an exception handler. The behavior is
+ * undefined outside of an exception handler.
+ *
+ * @param cpu The CPU device handle
+ * @return The value of the program counter at the time of the exception
+ */
+inline uintptr_t metal_cpu_get_exception_pc(struct metal_cpu *cpu)
+{ return cpu->vtable->get_epc(cpu); }
+
+/*!
+ * @brief Set the exception program counter
+ *
+ * This function must be called within an exception handler. The behavior
+ * is undefined outside of an exception handler.
+ *
+ * This function can be used to cause an exception handler to return execution
+ * to an address other than the one that caused the exception.
+ *
+ * @param cpu the CPU device handle
+ * @param epc The address to set the exception program counter to
+ * @return 0 upon success
+ */
+inline int metal_cpu_set_exception_pc(struct metal_cpu *cpu, uintptr_t epc)
+{ return cpu->vtable->set_epc(cpu, epc); }
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/fixed-clock.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/fixed-clock.h
new file mode 100644
index 000000000..2647c5981
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/fixed-clock.h
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__FIXED_CLOCK_H
+#define METAL__DRIVERS__FIXED_CLOCK_H
+
+struct __metal_driver_fixed_clock;
+
+#include <metal/compiler.h>
+#include <metal/clock.h>
+
+struct __metal_driver_vtable_fixed_clock {
+ struct __metal_clock_vtable clock;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_fixed_clock)
+
+struct __metal_driver_fixed_clock {
+ struct metal_clock clock;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/fixed-factor-clock.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/fixed-factor-clock.h
new file mode 100644
index 000000000..936ce8d77
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/fixed-factor-clock.h
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__FIXED_FACTOR_CLOCK_H
+#define METAL__DRIVERS__FIXED_FACTOR_CLOCK_H
+
+struct __metal_driver_fixed_factor_clock;
+
+#include <metal/compiler.h>
+#include <metal/clock.h>
+
+struct __metal_driver_vtable_fixed_factor_clock {
+ struct __metal_clock_vtable clock;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_fixed_factor_clock)
+
+struct __metal_driver_fixed_factor_clock {
+ struct metal_clock clock;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/riscv_clint0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/riscv_clint0.h
new file mode 100644
index 000000000..08d571e1c
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/riscv_clint0.h
@@ -0,0 +1,24 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__RISCV_CLINT0_H
+#define METAL__DRIVERS__RISCV_CLINT0_H
+
+#include <metal/compiler.h>
+#include <metal/drivers/riscv_cpu.h>
+
+struct __metal_driver_vtable_riscv_clint0 {
+ struct metal_interrupt_vtable clint_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_riscv_clint0)
+
+#define __METAL_MACHINE_MACROS
+#include <metal/machine.h>
+struct __metal_driver_riscv_clint0 {
+ struct metal_interrupt controller;
+ int init_done;
+};
+#undef __METAL_MACHINE_MACROS
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/riscv_cpu.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/riscv_cpu.h
new file mode 100644
index 000000000..eb1e5b8ca
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/riscv_cpu.h
@@ -0,0 +1,203 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__RISCV_CPU_H
+#define METAL__DRIVERS__RISCV_CPU_H
+
+#include <stdint.h>
+#include <metal/cpu.h>
+#include <metal/compiler.h>
+
+#define METAL_MAX_CORES 8
+#define METAL_MAX_MI 32 /* Per ISA MCause interrupts 32+ are Reserved */
+#define METAL_MAX_ME 12 /* Per ISA Exception codes 12+ are Reserved */
+#define METAL_DEFAULT_RTC_FREQ 32768
+
+#define METAL_DISABLE 0
+#define METAL_ENABLE 1
+
+#define METAL_ISA_A_EXTENSIONS 0x0001
+#define METAL_ISA_C_EXTENSIONS 0x0004
+#define METAL_ISA_D_EXTENSIONS 0x0008
+#define METAL_ISA_E_EXTENSIONS 0x0010
+#define METAL_ISA_F_EXTENSIONS 0x0020
+#define METAL_ISA_G_EXTENSIONS 0x0040
+#define METAL_ISA_I_EXTENSIONS 0x0100
+#define METAL_ISA_M_EXTENSIONS 0x1000
+#define METAL_ISA_N_EXTENSIONS 0x2000
+#define METAL_ISA_Q_EXTENSIONS 0x10000
+#define METAL_ISA_S_EXTENSIONS 0x40000
+#define METAL_ISA_U_EXTENSIONS 0x100000
+#define METAL_ISA_V_EXTENSIONS 0x200000
+#define METAL_ISA_XL32_EXTENSIONS 0x40000000UL
+#define METAL_ISA_XL64_EXTENSIONS 0x8000000000000000UL
+#define METAL_ISA_XL128_EXTENSIONS 0xC000000000000000UL
+
+#define METAL_MTVEC_DIRECT 0x00
+#define METAL_MTVEC_VECTORED 0x01
+#define METAL_MTVEC_CLIC 0x02
+#define METAL_MTVEC_CLIC_VECTORED 0x03
+#define METAL_MTVEC_CLIC_RESERVED 0x3C
+#define METAL_MTVEC_MASK 0x3F
+#if __riscv_xlen == 32
+#define METAL_MCAUSE_INTR 0x80000000UL
+#define METAL_MCAUSE_CAUSE 0x000003FFUL
+#else
+#define METAL_MCAUSE_INTR 0x8000000000000000UL
+#define METAL_MCAUSE_CAUSE 0x00000000000003FFUL
+#endif
+#define METAL_MCAUSE_MINHV 0x40000000UL
+#define METAL_MCAUSE_MPP 0x30000000UL
+#define METAL_MCAUSE_MPIE 0x08000000UL
+#define METAL_MCAUSE_MPIL 0x00FF0000UL
+#define METAL_MSTATUS_MIE 0x00000008UL
+#define METAL_MSTATUS_MPIE 0x00000080UL
+#define METAL_MSTATUS_MPP 0x00001800UL
+#define METAL_MSTATUS_FS_INIT 0x00002000UL
+#define METAL_MSTATUS_FS_CLEAN 0x00004000UL
+#define METAL_MSTATUS_FS_DIRTY 0x00006000UL
+#define METAL_MSTATUS_MPRV 0x00020000UL
+#define METAL_MSTATUS_MXR 0x00080000UL
+#define METAL_MINTSTATUS_MIL 0xFF000000UL
+#define METAL_MINTSTATUS_SIL 0x0000FF00UL
+#define METAL_MINTSTATUS_UIL 0x000000FFUL
+
+#define METAL_LOCAL_INTR(X) (16 + X)
+#define METAL_MCAUSE_EVAL(cause) (cause & METAL_MCAUSE_INTR)
+#define METAL_INTERRUPT(cause) (METAL_MCAUSE_EVAL(cause) ? 1 : 0)
+#define METAL_EXCEPTION(cause) (METAL_MCAUSE_EVAL(cause) ? 0 : 1)
+#define METAL_SW_INTR_EXCEPTION (METAL_MCAUSE_INTR + 3)
+#define METAL_TMR_INTR_EXCEPTION (METAL_MCAUSE_INTR + 7)
+#define METAL_EXT_INTR_EXCEPTION (METAL_MCAUSE_INTR + 11)
+#define METAL_LOCAL_INTR_EXCEPTION(X) (METAL_MCAUSE_INTR + METAL_LOCAL_INTR(X))
+#define METAL_LOCAL_INTR_RESERVE0 1
+#define METAL_LOCAL_INTR_RESERVE1 2
+#define METAL_LOCAL_INTR_RESERVE2 4
+#define METAL_LOCAL_INTERRUPT_SW 8 /* Bit3 0x008 */
+#define METAL_LOCAL_INTR_RESERVE4 16
+#define METAL_LOCAL_INTR_RESERVE5 32
+#define METAL_LOCAL_INTR_RESERVE6 64
+#define METAL_LOCAL_INTERRUPT_TMR 128 /* Bit7 0x080 */
+#define METAL_LOCAL_INTR_RESERVE8 256
+#define METAL_LOCAL_INTR_RESERVE9 512
+#define METAL_LOCAL_INTR_RESERVE10 1024
+#define METAL_LOCAL_INTERRUPT_EXT 2048 /* Bit11 0x800 */
+/* Bit12 to Bit15 are Reserved */
+#define METAL_LOCAL_INTERRUPT(X) (0x10000 << X) /* Bit16+ Start of Custom Local Interrupt */
+#define METAL_MIE_INTERRUPT METAL_MSTATUS_MIE
+
+typedef enum {
+ METAL_MACHINE_PRIVILEGE_MODE,
+ METAL_SUPERVISOR_PRIVILEGE_MODE,
+ METAL_USER_PRIVILEGE_MODE,
+} metal_privilege_mode_e;
+
+typedef enum {
+ METAL_INTERRUPT_ID_BASE,
+ METAL_INTERRUPT_ID_SW = (METAL_INTERRUPT_ID_BASE + 3),
+ METAL_INTERRUPT_ID_TMR = (METAL_INTERRUPT_ID_BASE + 7),
+ METAL_INTERRUPT_ID_EXT = (METAL_INTERRUPT_ID_BASE + 11),
+ METAL_INTERRUPT_ID_LC0 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(0)),
+ METAL_INTERRUPT_ID_LC1 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(1)),
+ METAL_INTERRUPT_ID_LC2 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(2)),
+ METAL_INTERRUPT_ID_LC3 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(3)),
+ METAL_INTERRUPT_ID_LC4 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(4)),
+ METAL_INTERRUPT_ID_LC5 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(5)),
+ METAL_INTERRUPT_ID_LC6 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(6)),
+ METAL_INTERRUPT_ID_LC7 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(7)),
+ METAL_INTERRUPT_ID_LC8 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(8)),
+ METAL_INTERRUPT_ID_LC9 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(9)),
+ METAL_INTERRUPT_ID_LC10 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(10)),
+ METAL_INTERRUPT_ID_LC11 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(11)),
+ METAL_INTERRUPT_ID_LC12 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(12)),
+ METAL_INTERRUPT_ID_LC13 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(13)),
+ METAL_INTERRUPT_ID_LC14 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(14)),
+ METAL_INTERRUPT_ID_LC15 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(15)),
+ METAL_INTERRUPT_ID_LCMX,
+ METAL_INTERRUPT_ID_GL0 = METAL_INTERRUPT_ID_LCMX,
+ METAL_INTERRUPT_ID_GLMX = (METAL_MCAUSE_CAUSE + 1),
+} metal_interrupt_id_e;
+
+typedef enum {
+ METAL_IAM_EXCEPTION_CODE, /* Instruction address misaligned */
+ METAL_IAF_EXCEPTION_CODE, /* Instruction access faultd */
+ METAL_II_EXCEPTION_CODE, /* Illegal instruction */
+ METAL_BREAK_EXCEPTION_CODE, /* Breakpoint */
+ METAL_LAM_EXCEPTION_CODE, /* Load address misaligned */
+ METAL_LAF_EXCEPTION_CODE, /* Load access fault */
+ METAL_SAMOAM_EXCEPTION_CODE, /* Store/AMO address misaligned */
+ METAL_SAMOAF_EXCEPTION_CODE, /* Store/AMO access fault */
+ METAL_ECALL_U_EXCEPTION_CODE, /* Environment call from U-mode */
+ METAL_R9_EXCEPTION_CODE, /* Reserved */
+ METAL_R10_EXCEPTION_CODE, /* Reserved */
+ METAL_ECALL_M_EXCEPTION_CODE, /* Environment call from M-mode */
+ METAL_MAX_EXCEPTION_CODE,
+} metal_exception_code_e;
+
+typedef enum {
+ METAL_TIMER_MTIME_GET = 1,
+ METAL_SOFTWARE_IPI_CLEAR,
+ METAL_SOFTWARE_IPI_SET,
+ METAL_SOFTWARE_MSIP_GET,
+ METAL_MAX_INTERRUPT_GET,
+ METAL_INDEX_INTERRUPT_GET,
+} metal_interrup_cmd_e;
+
+typedef struct __metal_interrupt_data {
+ long long pad : 64;
+ metal_interrupt_handler_t handler;
+ void *sub_int;
+ void *exint_data;
+} __metal_interrupt_data;
+
+/* CPU interrupt controller */
+
+uintptr_t __metal_myhart_id(void);
+
+struct __metal_driver_interrupt_controller_vtable {
+ void (*interrupt_init)(struct metal_interrupt *controller);
+ int (*interrupt_register)(struct metal_interrupt *controller,
+ int id, metal_interrupt_handler_t isr, void *priv_data);
+ int (*interrupt_enable)(struct metal_interrupt *controller, int id);
+ int (*interrupt_disable)(struct metal_interrupt *controller, int id);
+ int (*command_request)(struct metal_interrupt *intr, int cmd, void *data);
+};
+
+struct __metal_driver_vtable_riscv_cpu_intc {
+ struct metal_interrupt_vtable controller_vtable;
+};
+
+
+void __metal_interrupt_global_enable(void);
+void __metal_interrupt_global_disable(void);
+void __metal_controller_interrupt_vector(metal_vector_mode mode, void *vec_table);
+inline int __metal_controller_interrupt_is_selective_vectored (void)
+{
+ uintptr_t val;
+
+ asm volatile ("csrr %0, mtvec" : "=r"(val));
+ return ((val & METAL_MTVEC_CLIC_VECTORED) == METAL_MTVEC_CLIC);
+}
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_riscv_cpu_intc)
+
+struct __metal_driver_riscv_cpu_intc {
+ struct metal_interrupt controller;
+ int init_done;
+ uintptr_t metal_mtvec_table[METAL_MAX_MI];
+ __metal_interrupt_data metal_int_table[METAL_MAX_MI];
+ metal_exception_handler_t metal_exception_table[METAL_MAX_ME];
+};
+
+/* CPU driver*/
+struct __metal_driver_vtable_cpu {
+ struct metal_cpu_vtable cpu_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_cpu)
+
+struct __metal_driver_cpu {
+ struct metal_cpu cpu;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/riscv_plic0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/riscv_plic0.h
new file mode 100644
index 000000000..159ee6d69
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/riscv_plic0.h
@@ -0,0 +1,31 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__RISCV_PLIC0_H
+#define METAL__DRIVERS__RISCV_PLIC0_H
+
+#include <metal/compiler.h>
+#include <metal/drivers/riscv_cpu.h>
+
+#define METAL_PLIC_SOURCE_MASK 0x1F
+#define METAL_PLIC_SOURCE_SHIFT 5
+#define METAL_PLIC_SOURCE_PRIORITY_SHIFT 2
+#define METAL_PLIC_SOURCE_PENDING_SHIFT 0
+
+struct __metal_driver_vtable_riscv_plic0 {
+ struct metal_interrupt_vtable plic_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_riscv_plic0)
+
+#define __METAL_MACHINE_MACROS
+#include <metal/machine.h>
+struct __metal_driver_riscv_plic0 {
+ struct metal_interrupt controller;
+ int init_done;
+ metal_interrupt_handler_t metal_exint_table[__METAL_PLIC_SUBINTERRUPTS];
+ __metal_interrupt_data metal_exdata_table[__METAL_PLIC_SUBINTERRUPTS];
+};
+#undef __METAL_MACHINE_MACROS
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_clic0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_clic0.h
new file mode 100644
index 000000000..db9674625
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_clic0.h
@@ -0,0 +1,42 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_CLIC0_H
+#define METAL__DRIVERS__SIFIVE_CLIC0_H
+
+#include <metal/compiler.h>
+#include <metal/drivers/riscv_cpu.h>
+
+#define METAL_CLIC_MAX_NMBITS 2
+#define METAL_CLIC_MAX_NLBITS 8
+#define METAL_CLIC_MAX_NVBITS 1
+
+#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_MMODE 0x00
+#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_SMODE1 0x20
+#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_SMODE2 0x40
+#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_MASK 0x60
+#define METAL_SIFIVE_CLIC0_CLICCFG_NLBITS_MASK 0x1E
+#define METAL_SIFIVE_CLIC0_CLICCFG_NVBIT_MASK 0x01
+
+#define METAL_CLIC_ICTRL_SMODE1_MASK 0x7F /* b8 set imply M-mode */
+#define METAL_CLIC_ICTRL_SMODE2_MASK 0x3F /* b8 set M-mode, b7 clear U-mode */
+
+#define METAL_MAX_INTERRUPT_LEVEL ((1 << METAL_CLIC_MAX_NLBITS) - 1)
+
+struct __metal_driver_vtable_sifive_clic0 {
+ struct metal_interrupt_vtable clic_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_clic0)
+
+#define __METAL_MACHINE_MACROS
+#include <metal/machine.h>
+struct __metal_driver_sifive_clic0 {
+ struct metal_interrupt controller;
+ int init_done;
+ metal_interrupt_handler_t metal_mtvt_table[__METAL_CLIC_SUBINTERRUPTS];
+ __metal_interrupt_data metal_exint_table[__METAL_CLIC_SUBINTERRUPTS];
+};
+#undef __METAL_MACHINE_MACROS
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_hfrosc.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_hfrosc.h
new file mode 100644
index 000000000..d311f0cf2
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_hfrosc.h
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_HFROSC_H
+#define METAL__DRIVERS__SIFIVE_FE310_G000_HFROSC_H
+
+#include <metal/drivers/sifive_fe310-g000_prci.h>
+#include <metal/compiler.h>
+#include <metal/clock.h>
+#include <metal/io.h>
+
+struct __metal_driver_vtable_sifive_fe310_g000_hfrosc {
+ struct __metal_clock_vtable clock;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_hfrosc)
+
+struct __metal_driver_sifive_fe310_g000_hfrosc {
+ struct metal_clock clock;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_hfxosc.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_hfxosc.h
new file mode 100644
index 000000000..b86926fba
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_hfxosc.h
@@ -0,0 +1,20 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_HFXOSC_H
+#define METAL__DRIVERS__SIFIVE_FE310_G000_HFXOSC_H
+
+#include <metal/clock.h>
+#include <metal/drivers/sifive_fe310-g000_prci.h>
+
+struct __metal_driver_vtable_sifive_fe310_g000_hfxosc {
+ struct __metal_clock_vtable clock;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_hfxosc)
+
+struct __metal_driver_sifive_fe310_g000_hfxosc {
+ struct metal_clock clock;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_pll.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_pll.h
new file mode 100644
index 000000000..67f818f7b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_pll.h
@@ -0,0 +1,26 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_PLL_H
+#define METAL__DRIVERS__SIFIVE_FE310_G000_PLL_H
+
+struct __metal_driver_sifive_fe310_g000_pll;
+
+#include <metal/clock.h>
+#include <metal/drivers/sifive_fe310-g000_prci.h>
+#include <metal/machine.h>
+
+struct __metal_driver_vtable_sifive_fe310_g000_pll {
+ void (*init)(struct __metal_driver_sifive_fe310_g000_pll *pll);
+ struct __metal_clock_vtable clock;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_pll)
+
+struct __metal_driver_sifive_fe310_g000_pll {
+ struct metal_clock clock;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_prci.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_prci.h
new file mode 100644
index 000000000..87c9ca985
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fe310-g000_prci.h
@@ -0,0 +1,23 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_PRCI_H
+#define METAL__DRIVERS__SIFIVE_FE310_G000_PRCI_H
+
+#include <metal/compiler.h>
+#include <metal/io.h>
+
+struct __metal_driver_sifive_fe310_g000_prci;
+
+struct __metal_driver_vtable_sifive_fe310_g000_prci {
+ long (*get_reg)(const struct __metal_driver_sifive_fe310_g000_prci *, long offset);
+ long (*set_reg)(const struct __metal_driver_sifive_fe310_g000_prci *, long offset, long value);
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_prci)
+
+struct __metal_driver_sifive_fe310_g000_prci {
+};
+
+#endif
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fu540-c000_l2.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fu540-c000_l2.h
new file mode 100644
index 000000000..8c3cf907e
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_fu540-c000_l2.h
@@ -0,0 +1,23 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_FU540_C000_L2_H
+#define METAL__DRIVERS__SIFIVE_FU540_C000_L2_H
+
+struct __metal_driver_sifive_fu540_c000_l2;
+
+#include <stdint.h>
+#include <metal/cache.h>
+
+struct __metal_driver_vtable_sifive_fu540_c000_l2 {
+ struct __metal_cache_vtable cache;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fu540_c000_l2)
+
+struct __metal_driver_sifive_fu540_c000_l2 {
+ struct metal_cache cache;
+};
+
+#endif
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_global-external-interrupts0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_global-external-interrupts0.h
new file mode 100644
index 000000000..9e6f2faf6
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_global-external-interrupts0.h
@@ -0,0 +1,21 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_GLOBAL_EXTERNAL_INTERRUPTS0_H
+#define METAL__DRIVERS__SIFIVE_GLOBAL_EXTERNAL_INTERRUPTS0_H
+
+#include <metal/compiler.h>
+#include <metal/drivers/riscv_cpu.h>
+
+struct __metal_driver_vtable_sifive_global_external_interrupts0 {
+ struct metal_interrupt_vtable global0_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_global_external_interrupts0)
+
+struct __metal_driver_sifive_global_external_interrupts0 {
+ struct metal_interrupt irc;
+ int init_done;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio-buttons.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio-buttons.h
new file mode 100644
index 000000000..a0caeaba8
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio-buttons.h
@@ -0,0 +1,21 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_GPIO_BUTTONS_H
+#define METAL__DRIVERS__SIFIVE_GPIO_BUTTONS_H
+
+#include <string.h>
+#include <metal/button.h>
+#include <metal/compiler.h>
+
+struct __metal_driver_vtable_sifive_button {
+ struct metal_button_vtable button_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_button)
+
+struct __metal_driver_sifive_gpio_button {
+ struct metal_button button;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio-leds.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio-leds.h
new file mode 100644
index 000000000..a8dacf116
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio-leds.h
@@ -0,0 +1,21 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_GPIO_LEDS_H
+#define METAL__DRIVERS__SIFIVE_GPIO_LEDS_H
+
+#include <metal/drivers/sifive_gpio0.h>
+#include <metal/led.h>
+#include <metal/compiler.h>
+
+struct __metal_driver_vtable_sifive_led {
+ struct metal_led_vtable led_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_led)
+
+struct __metal_driver_sifive_gpio_led {
+ struct metal_led led;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio-switches.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio-switches.h
new file mode 100644
index 000000000..c9c7839e9
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio-switches.h
@@ -0,0 +1,21 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_GPIO_SWITCHES_H
+#define METAL__DRIVERS__SIFIVE_GPIO_SWITCHES_H
+
+#include <metal/drivers/sifive_gpio0.h>
+#include <metal/switch.h>
+#include <metal/compiler.h>
+
+struct __metal_driver_vtable_sifive_switch {
+ struct metal_switch_vtable switch_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_switch)
+
+struct __metal_driver_sifive_gpio_switch {
+ struct metal_switch flip;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio0.h
new file mode 100644
index 000000000..cc56dc722
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_gpio0.h
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_GPIO0_H
+#define METAL__DRIVERS__SIFIVE_GPIO0_H
+
+#include <metal/compiler.h>
+#include <metal/gpio.h>
+
+struct __metal_driver_vtable_sifive_gpio0 {
+ const struct __metal_gpio_vtable gpio;
+};
+
+//struct __metal_driver_sifive_gpio0;
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_gpio0)
+
+struct __metal_driver_sifive_gpio0 {
+ struct metal_gpio gpio;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_local-external-interrupts0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_local-external-interrupts0.h
new file mode 100644
index 000000000..aa8d63078
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_local-external-interrupts0.h
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_EXTERNAL_INTERRUPTS0_H
+#define METAL__DRIVERS__SIFIVE_EXTERNAL_INTERRUPTS0_H
+
+#include <metal/compiler.h>
+#include <metal/drivers/riscv_cpu.h>
+
+struct __metal_driver_vtable_sifive_local_external_interrupts0 {
+ struct metal_interrupt_vtable local0_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_local_external_interrupts0)
+
+struct __metal_driver_sifive_local_external_interrupts0 {
+ struct metal_interrupt irc;
+ int init_done;
+};
+
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_spi0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_spi0.h
new file mode 100644
index 000000000..90d4c831e
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_spi0.h
@@ -0,0 +1,24 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_SPI0_H
+#define METAL__DRIVERS__SIFIVE_SPI0_H
+
+#include <metal/drivers/sifive_gpio0.h>
+#include <metal/clock.h>
+#include <metal/compiler.h>
+#include <metal/io.h>
+#include <metal/spi.h>
+
+struct __metal_driver_vtable_sifive_spi0 {
+ const struct metal_spi_vtable spi;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_spi0)
+
+struct __metal_driver_sifive_spi0 {
+ struct metal_spi spi;
+ unsigned long baud_rate;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_test0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_test0.h
new file mode 100644
index 000000000..e87db2c83
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_test0.h
@@ -0,0 +1,21 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_TEST0_H
+#define METAL__DRIVERS__SIFIVE_TEST0_H
+
+#include <metal/compiler.h>
+#include <metal/shutdown.h>
+
+struct __metal_driver_vtable_sifive_test0 {
+ const struct __metal_shutdown_vtable shutdown;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_test0)
+
+struct __metal_driver_sifive_test0 {
+ struct __metal_shutdown shutdown;
+};
+
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_uart0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_uart0.h
new file mode 100644
index 000000000..11d954002
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/drivers/sifive_uart0.h
@@ -0,0 +1,28 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_UART0_H
+#define METAL__DRIVERS__SIFIVE_UART0_H
+
+#include <metal/drivers/sifive_gpio0.h>
+#include <metal/drivers/riscv_plic0.h>
+#include <metal/clock.h>
+#include <metal/io.h>
+#include <metal/uart.h>
+#include <metal/compiler.h>
+
+struct __metal_driver_vtable_sifive_uart0 {
+ const struct metal_uart_vtable uart;
+};
+
+struct __metal_driver_sifive_uart0;
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_uart0)
+
+struct __metal_driver_sifive_uart0 {
+ struct metal_uart uart;
+ unsigned long baud_rate;
+};
+
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/gpio.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/gpio.h
new file mode 100644
index 000000000..513687dd7
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/gpio.h
@@ -0,0 +1,151 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__GPIO_H
+#define METAL__GPIO_H
+
+#include <metal/compiler.h>
+
+/*!
+ * @file gpio.h
+ * @brief API for manipulating general-purpose input/output
+ */
+
+struct metal_gpio;
+
+struct __metal_gpio_vtable {
+ int (*disable_input)(struct metal_gpio *, long pins);
+ long (*output)(struct metal_gpio *);
+ int (*enable_output)(struct metal_gpio *, long pins);
+ int (*output_set)(struct metal_gpio *, long value);
+ int (*output_clear)(struct metal_gpio *, long value);
+ int (*output_toggle)(struct metal_gpio *, long value);
+ int (*enable_io)(struct metal_gpio *, long pins, long dest);
+};
+
+/*!
+ * @struct metal_gpio
+ * @brief The handle for a GPIO interface
+ */
+struct metal_gpio {
+ const struct __metal_gpio_vtable *vtable;
+};
+
+/*!
+ * @brief Get a GPIO device handle
+ * @param device_num The GPIO device index
+ * @return The GPIO device handle, or NULL if there is no device at that index
+ */
+struct metal_gpio *metal_gpio_get_device(int device_num);
+
+/*!
+ * @brief Disable input on a pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @return 0 if the input is successfully disabled
+ */
+inline int metal_gpio_disable_input(struct metal_gpio *gpio, int pin) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->disable_input(gpio, (1 << pin));
+}
+
+/*!
+ * @brief Enable output on a pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @return 0 if the output is successfully enabled
+ */
+inline int metal_gpio_enable_output(struct metal_gpio *gpio, int pin) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->enable_output(gpio, (1 << pin));
+}
+
+/*!
+ * @brief Set the output value of a GPIO pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @param value The value to set the pin to
+ * @return 0 if the output is successfully set
+ */
+inline int metal_gpio_set_pin(struct metal_gpio *gpio, int pin, int value) {
+ if(!gpio) {
+ return 1;
+ }
+
+ if(value == 0) {
+ return gpio->vtable->output_clear(gpio, (1 << pin));
+ } else {
+ return gpio->vtable->output_set(gpio, (1 << pin));
+ }
+}
+
+/*!
+ * @brief Get the value of the GPIO pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @return The value of the GPIO pin
+ */
+inline int metal_gpio_get_pin(struct metal_gpio *gpio, int pin) {
+ if(!gpio) {
+ return 0;
+ }
+
+ long value = gpio->vtable->output(gpio);
+
+ if(value & (1 << pin)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ * @brief Clears the value of the GPIO pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @return 0 if the pin is successfully cleared
+ */
+inline int metal_gpio_clear_pin(struct metal_gpio *gpio, int pin) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->output_clear(gpio, (1 << pin));
+}
+
+/*!
+ * @brief Toggles the value of the GPIO pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @return 0 if the pin is successfully toggled
+ */
+inline int metal_gpio_toggle_pin(struct metal_gpio *gpio, int pin) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->output_toggle(gpio, (1 << pin));
+}
+
+/*!
+ * @brief Enables and sets the pinmux for a GPIO pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The bitmask for the pin to enable pinmux on
+ * @param io_function The IO function to set
+ * @return 0 if the pinmux is successfully set
+ */
+inline int metal_gpio_enable_pinmux(struct metal_gpio *gpio, int pin, int io_function) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->enable_io(gpio, (1 << pin), (io_function << pin));
+}
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/interrupt.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/interrupt.h
new file mode 100644
index 000000000..43f587aca
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/interrupt.h
@@ -0,0 +1,134 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__INTERRUPT_H
+#define METAL__INTERRUPT_H
+
+/*! @file interrupt.h
+ * @brief API for registering and manipulating interrupts
+ */
+
+#include <stddef.h>
+
+/*!
+ * @brief Possible mode of interrupts to operate
+ */
+typedef enum metal_vector_mode_ {
+ METAL_DIRECT_MODE = 0,
+ METAL_VECTOR_MODE = 1,
+ METAL_SELECTIVE_VECTOR_MODE = 2,
+ METAL_HARDWARE_VECTOR_MODE = 3
+} metal_vector_mode;
+
+/*!
+ * @brief Function signature for interrupt callback handlers
+ */
+typedef void (*metal_interrupt_handler_t) (int, void *);
+
+struct metal_interrupt;
+
+struct metal_interrupt_vtable {
+ void (*interrupt_init)(struct metal_interrupt *controller);
+ int (*interrupt_register)(struct metal_interrupt *controller, int id,
+ metal_interrupt_handler_t isr, void *priv_data);
+ int (*interrupt_enable)(struct metal_interrupt *controller, int id);
+ int (*interrupt_disable)(struct metal_interrupt *controller, int id);
+ int (*interrupt_vector_enable)(struct metal_interrupt *controller,
+ int id, metal_vector_mode mode);
+ int (*interrupt_vector_disable)(struct metal_interrupt *controller, int id);
+ int (*command_request)(struct metal_interrupt *controller, int cmd, void *data);
+ int (*mtimecmp_set)(struct metal_interrupt *controller, int hartid, unsigned long long time);
+};
+
+/*!
+ * @brief A handle for an interrupt
+ */
+struct metal_interrupt {
+ const struct metal_interrupt_vtable *vtable;
+};
+
+/*!
+ * @brief Initialize a given interrupt controller
+ *
+ * Initialize a given interrupt controller. This function must be called
+ * before any interrupts are registered or enabled with the handler. It
+ * is invalid to initialize an interrupt controller more than once.
+ *
+ * @param controller The handle for the interrupt controller
+ */
+inline void metal_interrupt_init(struct metal_interrupt *controller)
+{
+ return controller->vtable->interrupt_init(controller);
+}
+
+
+/*!
+ * @brief Register an interrupt handler
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to register
+ * @param handler The interrupt handler callback
+ * @param priv_data Private data for the interrupt handler
+ * @return 0 upon success
+ */
+inline int metal_interrupt_register_handler(struct metal_interrupt *controller,
+ int id,
+ metal_interrupt_handler_t handler,
+ void *priv_data)
+{
+ return controller->vtable->interrupt_register(controller, id, handler, priv_data);
+}
+
+/*!
+ * @brief Enable an interrupt
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to enable
+ * @return 0 upon success
+ */
+inline int metal_interrupt_enable(struct metal_interrupt *controller, int id)
+{
+ return controller->vtable->interrupt_enable(controller, id);
+}
+
+/*!
+ * @brief Disable an interrupt
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to disable
+ * @return 0 upon success
+ */
+inline int metal_interrupt_disable(struct metal_interrupt *controller, int id)
+{
+ return controller->vtable->interrupt_disable(controller, id);
+}
+
+/*!
+ * @brief Enable an interrupt vector
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to enable
+ * @param mode The interrupt mode type to enable
+ * @return 0 upon success
+ */
+inline int metal_interrupt_vector_enable(struct metal_interrupt *controller,
+ int id, metal_vector_mode mode)
+{
+ return controller->vtable->interrupt_vector_enable(controller, id, mode);
+}
+
+/*!
+ * @brief Disable an interrupt vector
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to disable
+ * @return 0 upon success
+ */
+inline int metal_interrupt_vector_disable(struct metal_interrupt *controller, int id)
+{
+ return controller->vtable->interrupt_vector_disable(controller, id);
+}
+
+/* Utilities function to controll, manages devices via a given interrupt controller */
+inline int _metal_interrupt_command_request(struct metal_interrupt *controller,
+ int cmd, void *data)
+{
+ return controller->vtable->command_request(controller, cmd, data);
+}
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/io.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/io.h
new file mode 100644
index 000000000..450054142
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/io.h
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__IO_H
+#define METAL__IO_H
+
+/* This macro enforces that the compiler will not elide the given access. */
+#define __METAL_ACCESS_ONCE(x) (*(typeof(*x) volatile *)(x))
+
+/* Allows users to specify arbitrary fences. */
+#define __METAL_IO_FENCE(pred, succ) __asm__ volatile ("fence " #pred "," #succ ::: "memory");
+
+/* Types that explicitly describe an address as being used for memory-mapped
+ * IO. These should only be accessed via __METAL_ACCESS_ONCE. */
+typedef unsigned char __metal_io_u8;
+typedef unsigned short __metal_io_u16;
+typedef unsigned int __metal_io_u32;
+#if __riscv_xlen >= 64
+typedef unsigned long __metal_io_u64;
+#endif
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/itim.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/itim.h
new file mode 100644
index 000000000..1a2a05b8b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/itim.h
@@ -0,0 +1,21 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__ITIM_H
+#define METAL__ITIM_H
+
+/*! @file itim.h
+ *
+ * API for manipulating ITIM allocation
+ */
+
+
+/*! @def METAL_PLACE_IN_ITIM
+ * @brief Link a function into the ITIM
+ *
+ * Link a function into the ITIM (Instruction Tightly Integrated
+ * Memory) if the ITIM is present on the target device.
+ */
+#define METAL_PLACE_IN_ITIM __attribute__((section(".itim")))
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/led.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/led.h
new file mode 100644
index 000000000..a430b84c2
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/led.h
@@ -0,0 +1,68 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__LED_H
+#define METAL__LED_H
+
+/*!
+ * @file led.h
+ * @brief API for manipulating LEDs
+ */
+
+struct metal_led;
+
+struct metal_led_vtable {
+ int (*led_exist)(struct metal_led *led, char *label);
+ void (*led_enable)(struct metal_led *led);
+ void (*led_on)(struct metal_led *led);
+ void (*led_off)(struct metal_led *led);
+ void (*led_toggle)(struct metal_led *led);
+};
+
+/*!
+ * @brief A handle for an LED
+ */
+struct metal_led {
+ const struct metal_led_vtable *vtable;
+};
+
+/*!
+ * @brief Get a handle for an LED
+ * @param label The DeviceTree label for the desired LED
+ * @return A handle to the LED, or NULL if none is found for the requested label
+ */
+struct metal_led* metal_led_get(char *label);
+
+/*!
+ * @brief Get a handle for a channel of an RGB LED
+ * @param label The DeviceTree label for the desired LED
+ * @param color The color for the LED in the DeviceTree
+ * @return A handle to the LED, or NULL if none is found for the requested label and color
+ */
+struct metal_led* metal_led_get_rgb(char *label, char *color);
+
+/*!
+ * @brief Enable an LED
+ * @param led The handle for the LED
+ */
+inline void metal_led_enable(struct metal_led *led) { led->vtable->led_enable(led); }
+
+/*!
+ * @brief Turn an LED on
+ * @param led The handle for the LED
+ */
+inline void metal_led_on(struct metal_led *led) { led->vtable->led_on(led); }
+
+/*!
+ * @brief Turn an LED off
+ * @param led The handle for the LED
+ */
+inline void metal_led_off(struct metal_led *led) { led->vtable->led_off(led); }
+
+/*!
+ * @brief Toggle the on/off state of an LED
+ * @param led The handle for the LED
+ */
+inline void metal_led_toggle(struct metal_led *led) { led->vtable->led_toggle(led); }
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/lock.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/lock.h
new file mode 100644
index 000000000..d863aa96e
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/lock.h
@@ -0,0 +1,127 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__LOCK_H
+#define METAL__LOCK_H
+
+#include <metal/memory.h>
+#include <metal/compiler.h>
+
+/*!
+ * @file lock.h
+ * @brief An API for creating and using a software lock/mutex
+ */
+
+/* TODO: How can we make the exception code platform-independant? */
+#define _METAL_STORE_AMO_ACCESS_FAULT 7
+
+/*!
+ * @def METAL_LOCK_DECLARE
+ * @brief Declare a lock
+ *
+ * Locks must be declared with METAL_LOCK_DECLARE to ensure that the lock
+ * is linked into a memory region which supports atomic memory operations.
+ */
+#define METAL_LOCK_DECLARE(name) \
+ __attribute__((section(".data.locks"))) \
+ struct metal_lock name
+
+/*!
+ * @brief A handle for a lock
+ */
+struct metal_lock {
+ int _state;
+};
+
+/*!
+ * @brief Initialize a lock
+ * @param lock The handle for a lock
+ * @return 0 if the lock is successfully initialized. A non-zero code indicates failure.
+ *
+ * If the lock cannot be initialized, attempts to take or give the lock
+ * will result in a Store/AMO access fault.
+ */
+inline int metal_lock_init(struct metal_lock *lock) {
+#ifdef __riscv_atomic
+ /* Get a handle for the memory which holds the lock state */
+ struct metal_memory *lock_mem = metal_get_memory_from_address((uintptr_t) &(lock->_state));
+ if(!lock_mem) {
+ return 1;
+ }
+
+ /* If the memory doesn't support atomics, report an error */
+ if(!metal_memory_supports_atomics(lock_mem)) {
+ return 2;
+ }
+
+ lock->_state = 0;
+
+ return 0;
+#else
+ return 3;
+#endif
+}
+
+/*!
+ * @brief Take a lock
+ * @param lock The handle for a lock
+ * @return 0 if the lock is successfully taken
+ *
+ * If the lock initialization failed, attempts to take a lock will result in
+ * a Store/AMO access fault.
+ */
+inline int metal_lock_take(struct metal_lock *lock) {
+#ifdef __riscv_atomic
+ int old = 1;
+ int new = 1;
+
+ while(old != 0) {
+ __asm__ volatile("amoswap.w.aq %[old], %[new], (%[state])"
+ : [old] "=r" (old)
+ : [new] "r" (new), [state] "r" (&(lock->_state))
+ : "memory");
+ }
+
+ return 0;
+#else
+ /* Store the memory address in mtval like a normal store/amo access fault */
+ __asm__ ("csrw mtval, %[state]"
+ :: [state] "r" (&(lock->_state)));
+
+ /* Trigger a Store/AMO access fault */
+ _metal_trap(_METAL_STORE_AMO_ACCESS_FAULT);
+
+ /* If execution returns, indicate failure */
+ return 1;
+#endif
+}
+
+/*!
+ * @brief Give back a held lock
+ * @param lock The handle for a lock
+ * @return 0 if the lock is successfully given
+ *
+ * If the lock initialization failed, attempts to give a lock will result in
+ * a Store/AMO access fault.
+ */
+inline int metal_lock_give(struct metal_lock *lock) {
+#ifdef __riscv_atomic
+ __asm__ volatile("amoswap.w.rl x0, x0, (%[state])"
+ :: [state] "r" (&(lock->_state))
+ : "memory");
+
+ return 0;
+#else
+ /* Store the memory address in mtval like a normal store/amo access fault */
+ __asm__ ("csrw mtval, %[state]"
+ :: [state] "r" (&(lock->_state)));
+
+ /* Trigger a Store/AMO access fault */
+ _metal_trap(_METAL_STORE_AMO_ACCESS_FAULT);
+
+ /* If execution returns, indicate failure */
+ return 1;
+#endif
+}
+
+#endif /* METAL__LOCK_H */
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/machine.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/machine.h
new file mode 100644
index 000000000..f76dbd632
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/machine.h
@@ -0,0 +1,872 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+/* ----------------------------------- */
+/* ----------------------------------- */
+
+#ifndef ASSEMBLY
+
+#include <metal/machine/platform.h>
+
+#ifdef __METAL_MACHINE_MACROS
+
+#ifndef MACROS_IF_SIFIVE_HIFIVE1_REVB____METAL_H
+#define MACROS_IF_SIFIVE_HIFIVE1_REVB____METAL_H
+
+#define __METAL_CLINT_NUM_PARENTS 2
+
+#ifndef __METAL_CLINT_NUM_PARENTS
+#define __METAL_CLINT_NUM_PARENTS 0
+#endif
+#define __METAL_PLIC_SUBINTERRUPTS 27
+
+#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_SIFIVE_HIFIVE1_REVB____METAL_H*/
+
+#else /* ! __METAL_MACHINE_MACROS */
+
+#ifndef MACROS_ELSE_SIFIVE_HIFIVE1_REVB____METAL_H
+#define MACROS_ELSE_SIFIVE_HIFIVE1_REVB____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 27
+
+#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_LOCAL_EXTERNAL_INTERRUPTS_0_INTERRUPTS 16
+
+#define METAL_MAX_LOCAL_EXT_INTERRUPTS 16
+
+#define METAL_MAX_GLOBAL_EXT_INTERRUPTS 0
+
+#define __METAL_GPIO_10012000_INTERRUPTS 16
+
+#define METAL_MAX_GPIO_INTERRUPTS 16
+
+#define __METAL_SERIAL_10013000_INTERRUPTS 1
+
+#define METAL_MAX_UART_INTERRUPTS 1
+
+
+#include <metal/drivers/fixed-clock.h>
+#include <metal/memory.h>
+#include <metal/drivers/riscv_clint0.h>
+#include <metal/drivers/riscv_cpu.h>
+#include <metal/drivers/riscv_plic0.h>
+#include <metal/pmp.h>
+#include <metal/drivers/sifive_local-external-interrupts0.h>
+#include <metal/drivers/sifive_gpio0.h>
+#include <metal/drivers/sifive_gpio-leds.h>
+#include <metal/drivers/sifive_spi0.h>
+#include <metal/drivers/sifive_uart0.h>
+#include <metal/drivers/sifive_fe310-g000_hfrosc.h>
+#include <metal/drivers/sifive_fe310-g000_hfxosc.h>
+#include <metal/drivers/sifive_fe310-g000_pll.h>
+#include <metal/drivers/sifive_fe310-g000_prci.h>
+
+/* From clock@0 */
+struct __metal_driver_fixed_clock __metal_dt_clock_0;
+
+/* From clock@2 */
+struct __metal_driver_fixed_clock __metal_dt_clock_2;
+
+/* From clock@5 */
+struct __metal_driver_fixed_clock __metal_dt_clock_5;
+
+struct metal_memory __metal_dt_mem_dtim_80000000;
+
+struct metal_memory __metal_dt_mem_spi_10014000;
+
+/* From clint@2000000 */
+struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000;
+
+/* From cpu@0 */
+struct __metal_driver_cpu __metal_dt_cpu_0;
+
+struct __metal_driver_riscv_cpu_intc __metal_dt_cpu_0_interrupt_controller;
+
+/* From interrupt_controller@c000000 */
+struct __metal_driver_riscv_plic0 __metal_dt_interrupt_controller_c000000;
+
+struct metal_pmp __metal_dt_pmp;
+
+/* From local_external_interrupts_0 */
+struct __metal_driver_sifive_local_external_interrupts0 __metal_dt_local_external_interrupts_0;
+
+/* From gpio@10012000 */
+struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000;
+
+/* From led@0red */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0red;
+
+/* From led@0green */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0green;
+
+/* From led@0blue */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0blue;
+
+/* From spi@10014000 */
+struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000;
+
+/* From serial@10013000 */
+struct __metal_driver_sifive_uart0 __metal_dt_serial_10013000;
+
+/* From clock@3 */
+struct __metal_driver_sifive_fe310_g000_hfrosc __metal_dt_clock_3;
+
+/* From clock@1 */
+struct __metal_driver_sifive_fe310_g000_hfxosc __metal_dt_clock_1;
+
+/* From clock@4 */
+struct __metal_driver_sifive_fe310_g000_pll __metal_dt_clock_4;
+
+/* From prci@10008000 */
+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 {
+ 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 1000000;
+ }
+ 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;
+ }
+}
+
+
+
+/* --------------------- 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 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 if (idx == 0) {
+ return 11;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+
+/* --------------------- sifive_clic0 ------------ */
+
+
+/* --------------------- sifive_local_external_interrupts0 ------------ */
+static inline struct metal_interrupt * __metal_driver_sifive_local_external_interrupts0_interrupt_parent(struct metal_interrupt *controller)
+{
+ if ((uintptr_t)controller == (uintptr_t)&__metal_dt_local_external_interrupts_0) {
+ return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller;
+ }
+ else {
+ return NULL;
+ }
+}
+
+static inline int __metal_driver_sifive_local_external_interrupts0_num_interrupts(struct metal_interrupt *controller)
+{
+ if ((uintptr_t)controller == (uintptr_t)&__metal_dt_local_external_interrupts_0) {
+ return METAL_MAX_LOCAL_EXT_INTERRUPTS;
+ }
+ else {
+ return 0;
+ }
+}
+
+static inline int __metal_driver_sifive_local_external_interrupts0_interrupt_lines(struct metal_interrupt *controller, int idx)
+{
+ if (idx == 0) {
+ return 16;
+ }
+ else if (idx == 1) {
+ return 17;
+ }
+ else if (idx == 2) {
+ return 18;
+ }
+ else if (idx == 3) {
+ return 19;
+ }
+ else if (idx == 4) {
+ return 20;
+ }
+ else if (idx == 5) {
+ return 21;
+ }
+ else if (idx == 6) {
+ return 22;
+ }
+ else if (idx == 7) {
+ return 23;
+ }
+ else if (idx == 8) {
+ return 24;
+ }
+ else if (idx == 9) {
+ return 25;
+ }
+ else if (idx == 10) {
+ return 26;
+ }
+ else if (idx == 11) {
+ return 27;
+ }
+ else if (idx == 12) {
+ return 28;
+ }
+ else if (idx == 13) {
+ return 29;
+ }
+ else if (idx == 14) {
+ return 30;
+ }
+ else if (idx == 15) {
+ return 31;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+
+/* --------------------- 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 7;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 1))) {
+ return 8;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 2))) {
+ return 9;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 3))) {
+ return 10;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 4))) {
+ return 11;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 5))) {
+ return 12;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 6))) {
+ return 13;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 7))) {
+ return 14;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 8))) {
+ return 15;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 9))) {
+ return 16;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 10))) {
+ return 17;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 11))) {
+ return 18;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 12))) {
+ return 19;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 13))) {
+ return 20;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 14))) {
+ return 21;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 15))) {
+ return 22;
+ }
+ 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_0red) {
+ return (struct metal_gpio *)&__metal_dt_gpio_10012000;
+ }
+ else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0green) {
+ return (struct metal_gpio *)&__metal_dt_gpio_10012000;
+ }
+ else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0blue) {
+ 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_0red) {
+ return 22;
+ }
+ else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0green) {
+ return 19;
+ }
+ else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0blue) {
+ return 21;
+ }
+ 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_0red) {
+ return "LD0red";
+ }
+ else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0green) {
+ return "LD0green";
+ }
+ else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0blue) {
+ return "LD0blue";
+ }
+ else {
+ return "";
+ }
+}
+
+
+
+/* --------------------- sifive_gpio_switch ------------ */
+
+
+/* --------------------- sifive_spi0 ------------ */
+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 {
+ 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 {
+ return 0;
+ }
+}
+
+static inline struct metal_clock * __metal_driver_sifive_spi0_clock(struct metal_spi *spi)
+{
+ return (struct metal_clock *)&__metal_dt_clock_4.clock;
+}
+
+static inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_spi0_pinmux(struct metal_spi *spi)
+{
+ return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000;
+}
+
+static inline unsigned long __metal_driver_sifive_spi0_pinmux_output_selector(struct metal_spi *spi)
+{
+ return 60;
+}
+
+static inline unsigned long __metal_driver_sifive_spi0_pinmux_source_selector(struct metal_spi *spi)
+{
+ return 60;
+}
+
+
+
+/* --------------------- sifive_test0 ------------ */
+
+
+/* --------------------- 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 {
+ 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 {
+ 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 {
+ 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 {
+ return NULL;
+ }
+}
+
+static inline int __metal_driver_sifive_uart0_interrupt_line(struct metal_uart *uart)
+{
+ return 5;
+}
+
+static inline struct metal_clock * __metal_driver_sifive_uart0_clock(struct metal_uart *uart)
+{
+ return (struct metal_clock *)&__metal_dt_clock_4.clock;
+}
+
+static inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uart0_pinmux(struct metal_uart *uart)
+{
+ return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000;
+}
+
+static inline unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart)
+{
+ return 196608;
+}
+
+static inline unsigned long __metal_driver_sifive_uart0_pinmux_source_selector(struct metal_uart *uart)
+{
+ return 196608;
+}
+
+
+
+/* --------------------- 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_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;
+}
+
+
+
+/* --------------------- sifive_fu540_c000_l2 ------------ */
+
+
+#define __METAL_DT_MAX_MEMORIES 2
+
+asm (".weak __metal_memory_table");
+struct metal_memory *__metal_memory_table[] = {
+ &__metal_dt_mem_dtim_80000000,
+ &__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
+
+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)
+
+/* From local_external_interrupts_0 */
+#define __METAL_DT_SIFIVE_LOCAL_EXINTR0_HANDLE (&__metal_dt_local_external_interrupts_0.irc)
+
+#define __METAL_DT_LOCAL_EXTERNAL_INTERRUPTS_0_HANDLE (&__metal_dt_local_external_interrupts_0.irc)
+
+#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 3
+
+asm (".weak __metal_led_table");
+struct __metal_driver_sifive_gpio_led *__metal_led_table[] = {
+ &__metal_dt_led_0red,
+ &__metal_dt_led_0green,
+ &__metal_dt_led_0blue};
+
+#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_SPIS 1
+
+asm (".weak __metal_spi_table");
+struct __metal_driver_sifive_spi0 *__metal_spi_table[] = {
+ &__metal_dt_spi_10014000};
+
+/* 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_SIFIVE_HIFIVE1_REVB____METAL_H*/
+
+#endif /* ! __METAL_MACHINE_MACROS */
+
+#endif /* ! ASSEMBLY */
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/machine/inline.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/machine/inline.h
new file mode 100644
index 000000000..8c0cd048b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/machine/inline.h
@@ -0,0 +1,249 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+/* ----------------------------------- */
+/* ----------------------------------- */
+
+#ifndef ASSEMBLY
+
+#ifndef SIFIVE_HIFIVE1_REVB____METAL_INLINE_H
+#define SIFIVE_HIFIVE1_REVB____METAL_INLINE_H
+
+#include <metal/machine.h>
+
+
+/* --------------------- 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);
+
+
+/* --------------------- 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);
+
+
+/* --------------------- sifive_clic0 ------------ */
+
+
+/* --------------------- sifive_local_external_interrupts0 ------------ */
+extern inline struct metal_interrupt * __metal_driver_sifive_local_external_interrupts0_interrupt_parent(struct metal_interrupt *controller);
+extern inline int __metal_driver_sifive_local_external_interrupts0_num_interrupts(struct metal_interrupt *controller);
+extern inline int __metal_driver_sifive_local_external_interrupts0_interrupt_lines(struct metal_interrupt *controller, int idx);
+
+
+/* --------------------- 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_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_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_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_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( );
+
+
+/* --------------------- sifive_fu540_c000_l2 ------------ */
+
+
+/* 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,
+};
+
+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_spi_10014000 = {
+ ._base_address = 536870912UL,
+ ._size = 500000UL,
+ ._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,
+};
+
+/* 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,
+};
+
+/* From local_external_interrupts_0 */
+struct __metal_driver_sifive_local_external_interrupts0 __metal_dt_local_external_interrupts_0 = {
+ .irc.vtable = &__metal_driver_vtable_sifive_local_external_interrupts0.local0_vtable,
+ .init_done = 0,
+};
+
+/* From gpio@10012000 */
+struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000 = {
+ .gpio.vtable = &__metal_driver_vtable_sifive_gpio0.gpio,
+};
+
+/* From led@0red */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0red = {
+ .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
+};
+
+/* From led@0green */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0green = {
+ .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
+};
+
+/* From led@0blue */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0blue = {
+ .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
+};
+
+/* From spi@10014000 */
+struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000 = {
+ .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 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@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 = {
+};
+
+
+#endif /* SIFIVE_HIFIVE1_REVB____METAL_INLINE_H*/
+#endif /* ! ASSEMBLY */
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/machine/platform.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/machine/platform.h
new file mode 100644
index 000000000..4ecd3e336
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/machine/platform.h
@@ -0,0 +1,237 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+/* ----------------------------------- */
+/* ----------------------------------- */
+
+#ifndef SIFIVE_HIFIVE1_REVB____METAL_PLATFORM_H
+#define SIFIVE_HIFIVE1_REVB____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 32000000UL
+
+#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 27UL
+#define METAL_RISCV_PLIC0_0_RISCV_NDEV 27UL
+
+#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_THRESHOLD 2097152UL
+#define METAL_RISCV_PLIC0_CLAIM 2097156UL
+
+/* 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 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@0red */
+
+/* From led@0green */
+
+/* From led@0blue */
+
+#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 local_external_interrupts_0 */
+
+#define METAL_SIFIVE_LOCAL_EXTERNAL_INTERRUPTS0
+
+/* 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
+
+#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 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
+
+#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
+
+#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
+
+#endif /* SIFIVE_HIFIVE1_REVB____METAL_PLATFORM_H*/
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/memory.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/memory.h
new file mode 100644
index 000000000..b62d8b25a
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/memory.h
@@ -0,0 +1,81 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__MEMORY_H
+#define METAL__MEMORY_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+/*!
+ * @file memory.h
+ *
+ * @brief API for enumerating memory blocks
+ */
+
+struct _metal_memory_attributes {
+ int R : 1;
+ int W : 1;
+ int X : 1;
+ int C : 1;
+ int A : 1;
+};
+
+/*!
+ * @brief A handle for a memory block
+ */
+struct metal_memory {
+ const uintptr_t _base_address;
+ const size_t _size;
+ const struct _metal_memory_attributes _attrs;
+};
+
+/*!
+ * @brief Get the memory block which services the given address
+ *
+ * Given a physical memory address, get a handle for the memory block to which
+ * that address is mapped.
+ *
+ * @param address The address to query
+ * @return The memory block handle, or NULL if the address is not mapped to a memory block
+ */
+struct metal_memory *metal_get_memory_from_address(const uintptr_t address);
+
+/*!
+ * @brief Get the base address for a memory block
+ * @param memory The handle for the memory block
+ * @return The base address of the memory block
+ */
+inline uintptr_t metal_memory_get_base_address(const struct metal_memory *memory) {
+ return memory->_base_address;
+}
+
+/*!
+ * @brief Get the size of a memory block
+ * @param memory The handle for the memory block
+ * @return The size of the memory block
+ */
+inline size_t metal_memory_get_size(const struct metal_memory *memory) {
+ return memory->_size;
+}
+
+/*!
+ * @brief Query if a memory block supports atomic operations
+ * @param memory The handle for the memory block
+ * @return nonzero if the memory block supports atomic operations
+ */
+inline int metal_memory_supports_atomics(const struct metal_memory *memory) {
+ return memory->_attrs.A;
+}
+
+/*!
+ * @brief Query if a memory block is cacheable
+ * @param memory The handle for the memory block
+ * @return nonzero if the memory block is cachable
+ */
+inline int metal_memory_is_cachable(const struct metal_memory *memory) {
+ return memory->_attrs.C;
+}
+
+#endif /* METAL__MEMORY_H */
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/pmp.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/pmp.h
new file mode 100644
index 000000000..9121b10a1
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/pmp.h
@@ -0,0 +1,204 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__PMP_H
+#define METAL__PMP_H
+
+/*!
+ * @file metal/pmp.h
+ *
+ * @brief API for Configuring Physical Memory Protection on RISC-V Cores
+ *
+ * The Physical Memory Protection (PMP) interface on RISC-V cores
+ * is a form of memory protection unit which allows for a finite number
+ * of physical memory regions to be configured with certain access
+ * permissions.
+ *
+ * Additional information about the use and configuration rules for PMPs
+ * can be found by reading the RISC-V Privileged Architecture Specification.
+ */
+
+#include <stddef.h>
+#include <metal/machine.h>
+
+struct metal_pmp;
+
+/*!
+ * @brief Set of available PMP addressing modes
+ */
+enum metal_pmp_address_mode {
+ /*! @brief Disable the PMP region */
+ METAL_PMP_OFF = 0,
+ /*! @brief Use Top-of-Range mode */
+ METAL_PMP_TOR = 1,
+ /*! @brief Use naturally-aligned 4-byte region mode */
+ METAL_PMP_NA4 = 2,
+ /*! @brief Use naturally-aligned power-of-two mode */
+ METAL_PMP_NAPOT = 3
+};
+
+/*!
+ * @brief Configuration for a PMP region
+ */
+struct metal_pmp_config {
+ /*! @brief Sets whether reads to the PMP region succeed */
+ int R : 1;
+ /*! @brief Sets whether writes to the PMP region succeed */
+ int W : 1;
+ /*! @brief Sets whether the PMP region is executable */
+ int X : 1;
+
+ /*! @brief Sets the addressing mode of the PMP region */
+ enum metal_pmp_address_mode A : 2;
+
+ int _pad : 2;
+
+ /*! @brief Sets whether the PMP region is locked */
+ enum metal_pmp_locked {
+ METAL_PMP_UNLOCKED = 0,
+ METAL_PMP_LOCKED = 1
+ } L : 1;
+};
+
+/*!
+ * @brief A handle for the PMP device
+ */
+struct metal_pmp {
+ /* The minimum granularity of the PMP region. Set by metal_pmp_init */
+ uintptr_t _granularity[METAL_MAX_CORES];
+};
+
+/*!
+ * @brief Get the PMP device handle
+ */
+struct metal_pmp *metal_pmp_get_device(void);
+
+/*!
+ * @brief Initialize the PMP
+ * @param pmp The PMP device handle to be initialized
+ *
+ * The PMP initialization routine is optional and may be called as many times
+ * as is desired. The effect of the initialization routine is to attempt to set
+ * all regions to unlocked and disabled, as well as to clear the X, W, and R
+ * bits. Only the pmp configuration of the hart which executes the routine will
+ * be affected.
+ *
+ * If any regions are fused to preset values by the implementation or locked,
+ * those PMP regions will silently remain uninitialized.
+ */
+void metal_pmp_init(struct metal_pmp *pmp);
+
+/*!
+ * @brief Configure a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to configure
+ * @param config The desired configuration of the PMP region
+ * @param address The desired address of the PMP region
+ * @return 0 upon success
+ */
+int metal_pmp_set_region(struct metal_pmp *pmp, unsigned int region, struct metal_pmp_config config, size_t address);
+
+/*!
+ * @brief Get the configuration for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to read
+ * @param config Variable to store the PMP region configuration
+ * @param address Variable to store the PMP region address
+ * @return 0 if the region is read successfully
+ */
+int metal_pmp_get_region(struct metal_pmp *pmp, unsigned int region, struct metal_pmp_config *config, size_t *address);
+
+/*!
+ * @brief Lock a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to lock
+ * @return 0 if the region is successfully locked
+ */
+int metal_pmp_lock(struct metal_pmp *pmp, unsigned int region);
+
+/*!
+ * @brief Set the address for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to set
+ * @param address The desired address of the PMP region
+ * @return 0 if the address is successfully set
+ */
+int metal_pmp_set_address(struct metal_pmp *pmp, unsigned int region, size_t address);
+
+/*!
+ * @brief Get the address of a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to read
+ * @return The address of the PMP region, or 0 if the region could not be read
+ */
+size_t metal_pmp_get_address(struct metal_pmp *pmp, unsigned int region);
+
+/*!
+ * @brief Set the addressing mode of a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to set
+ * @param mode The PMP addressing mode to set
+ * @return 0 if the addressing mode is successfully set
+ */
+int metal_pmp_set_address_mode(struct metal_pmp *pmp, unsigned int region, enum metal_pmp_address_mode mode);
+
+/*!
+ * @brief Get the addressing mode of a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to read
+ * @return The address mode of the PMP region
+ */
+enum metal_pmp_address_mode metal_pmp_get_address_mode(struct metal_pmp *pmp, unsigned int region);
+
+/*!
+ * @brief Set the executable bit for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to set
+ * @param X The desired value of the executable bit
+ * @return 0 if the executable bit is successfully set
+ */
+int metal_pmp_set_executable(struct metal_pmp *pmp, unsigned int region, int X);
+
+/*!
+ * @brief Get the executable bit for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to read
+ * @return the value of the executable bit
+ */
+int metal_pmp_get_executable(struct metal_pmp *pmp, unsigned int region);
+
+/*!
+ * @brief Set the writable bit for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to set
+ * @param W The desired value of the writable bit
+ * @return 0 if the writable bit is successfully set
+ */
+int metal_pmp_set_writeable(struct metal_pmp *pmp, unsigned int region, int W);
+
+/*!
+ * @brief Get the writable bit for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to read
+ * @return the value of the writable bit
+ */
+int metal_pmp_get_writeable(struct metal_pmp *pmp, unsigned int region);
+
+/*!
+ * @brief Set the readable bit for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to set
+ * @param R The desired value of the readable bit
+ * @return 0 if the readable bit is successfully set
+ */
+int metal_pmp_set_readable(struct metal_pmp *pmp, unsigned int region, int R);
+
+/*!
+ * @brief Set the readable bit for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to read
+ * @return the value of the readable bit
+ */
+int metal_pmp_get_readable(struct metal_pmp *pmp, unsigned int region);
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/privilege.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/privilege.h
new file mode 100644
index 000000000..c5212e5d1
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/privilege.h
@@ -0,0 +1,122 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__PRIVILEGE_H
+#define METAL__PRIVILEGE_H
+
+/*!
+ * @file metal/privilege.h
+ *
+ * @brief API for manipulating the privilege mode of a RISC-V system
+ *
+ * Additional information about privilege modes on RISC-V systems can be found
+ * by reading the RISC-V Privileged Architecture Specification v1.10.
+ */
+
+#include <stdint.h>
+
+enum metal_privilege_mode {
+ METAL_PRIVILEGE_USER = 0,
+ METAL_PRIVILEGE_SUPERVISOR = 1,
+ METAL_PRIVELEGE_MACHINE = 3,
+};
+
+#if __riscv_xlen == 32
+typedef uint32_t metal_xreg_t;
+#elif __riscv_xlen == 64
+typedef uint64_t metal_xreg_t;
+#endif
+
+#if __riscv_flen == 32
+typedef uint32_t metal_freg_t;
+#elif __riscv_flen == 64
+typedef uint64_t metal_freg_t;
+#endif
+
+struct metal_register_file {
+ metal_xreg_t ra;
+ metal_xreg_t sp;
+ metal_xreg_t gp;
+ metal_xreg_t tp;
+
+ metal_xreg_t t0;
+ metal_xreg_t t1;
+ metal_xreg_t t2;
+
+ metal_xreg_t s0;
+ metal_xreg_t s1;
+
+ metal_xreg_t a0;
+ metal_xreg_t a1;
+ metal_xreg_t a2;
+ metal_xreg_t a3;
+ metal_xreg_t a4;
+ metal_xreg_t a5;
+#ifndef __riscv_32e
+ metal_xreg_t a6;
+ metal_xreg_t a7;
+
+ metal_xreg_t s2;
+ metal_xreg_t s3;
+ metal_xreg_t s4;
+ metal_xreg_t s5;
+ metal_xreg_t s6;
+ metal_xreg_t s7;
+ metal_xreg_t s8;
+ metal_xreg_t s9;
+ metal_xreg_t s10;
+ metal_xreg_t s11;
+
+ metal_xreg_t t3;
+ metal_xreg_t t4;
+ metal_xreg_t t5;
+ metal_xreg_t t6;
+#endif /* __riscv_32e */
+
+#ifdef __riscv_flen
+ metal_freg_t ft0;
+ metal_freg_t ft1;
+ metal_freg_t ft2;
+ metal_freg_t ft3;
+ metal_freg_t ft4;
+ metal_freg_t ft5;
+ metal_freg_t ft6;
+ metal_freg_t ft7;
+
+ metal_freg_t fs0;
+ metal_freg_t fs1;
+
+ metal_freg_t fa0;
+ metal_freg_t fa1;
+ metal_freg_t fa2;
+ metal_freg_t fa3;
+ metal_freg_t fa4;
+ metal_freg_t fa5;
+ metal_freg_t fa6;
+ metal_freg_t fa7;
+
+ metal_freg_t fs2;
+ metal_freg_t fs3;
+ metal_freg_t fs4;
+ metal_freg_t fs5;
+ metal_freg_t fs6;
+ metal_freg_t fs7;
+ metal_freg_t fs8;
+ metal_freg_t fs9;
+ metal_freg_t fs10;
+ metal_freg_t fs11;
+
+ metal_freg_t ft8;
+ metal_freg_t ft9;
+ metal_freg_t ft10;
+ metal_freg_t ft11;
+#endif /* __riscv_flen */
+};
+
+typedef void (*metal_privilege_entry_point_t)();
+
+void metal_privilege_drop_to_mode(enum metal_privilege_mode mode,
+ struct metal_register_file regfile,
+ metal_privilege_entry_point_t entry_point);
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/shutdown.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/shutdown.h
new file mode 100644
index 000000000..3bebfa742
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/shutdown.h
@@ -0,0 +1,36 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__SHUTDOWN_H
+#define METAL__SHUTDOWN_H
+
+/*!
+ * @file shutdown.h
+ * @brief API for shutting down a machine
+ */
+
+struct __metal_shutdown;
+
+struct __metal_shutdown_vtable {
+ void (*exit)(const struct __metal_shutdown *sd, int code) __attribute__((noreturn));
+};
+
+struct __metal_shutdown {
+ const struct __metal_shutdown_vtable *vtable;
+};
+
+inline void __metal_shutdown_exit(const struct __metal_shutdown *sd, int code) __attribute__((noreturn));
+inline void __metal_shutdown_exit(const struct __metal_shutdown *sd, int code) { sd->vtable->exit(sd, code); }
+
+/*!
+ * @brief The public METAL shutdown interface
+ *
+ * Shuts down the machine, if the machine enables an interface for
+ * shutting down. When no interface is provided, will cause the machine
+ * to spin indefinitely.
+ *
+ * @param code The return code to set. 0 indicates program success.
+ */
+void metal_shutdown(int code) __attribute__((noreturn));
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/spi.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/spi.h
new file mode 100644
index 000000000..b011fe3ce
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/spi.h
@@ -0,0 +1,78 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__SPI_H
+#define METAL__SPI_H
+
+struct metal_spi;
+
+/*! @brief The configuration for a SPI transfer */
+struct metal_spi_config {
+ /*! @brief The protocol for the SPI transfer */
+ enum {
+ METAL_SPI_SINGLE,
+ METAL_SPI_DUAL,
+ METAL_SPI_QUAD
+ } protocol;
+
+ /*! @brief The polarity of the SPI transfer, equivalent to CPOL */
+ unsigned int polarity : 1;
+ /*! @brief The phase of the SPI transfer, equivalent to CPHA */
+ unsigned int phase : 1;
+ /*! @brief The endianness of the SPI transfer */
+ unsigned int little_endian : 1;
+ /*! @brief The active state of the chip select line */
+ unsigned int cs_active_high : 1;
+ /*! @brief The chip select ID to activate for the SPI transfer */
+ unsigned int csid;
+};
+
+struct metal_spi_vtable {
+ void (*init)(struct metal_spi *spi, int baud_rate);
+ int (*transfer)(struct metal_spi *spi, struct metal_spi_config *config, size_t len, char *tx_buf, char *rx_buf);
+ int (*get_baud_rate)(struct metal_spi *spi);
+ int (*set_baud_rate)(struct metal_spi *spi, int baud_rate);
+};
+
+/*! @brief A handle for a SPI device */
+struct metal_spi {
+ const struct metal_spi_vtable *vtable;
+};
+
+/*! @brief Get a handle for a SPI device
+ * @param device_num The index of the desired SPI device
+ * @return A handle to the SPI device, or NULL if the device does not exist*/
+struct metal_spi *metal_spi_get_device(int device_num);
+
+/*! @brief Initialize a SPI device with a certain baud rate
+ * @param spi The handle for the SPI device to initialize
+ * @param baud_rate The baud rate to set the SPI device to
+ */
+inline void metal_spi_init(struct metal_spi *spi, int baud_rate) { spi->vtable->init(spi, baud_rate); }
+
+/*! @brief Perform a SPI transfer
+ * @param spi The handle for the SPI device to perform the transfer
+ * @param config The configuration for the SPI transfer.
+ * @param len The number of bytes to transfer
+ * @param tx_buf The buffer to send over the SPI bus. Must be len bytes long. If NULL, the SPI will transfer the value 0.
+ * @param rx_buf The buffer to receive data into. Must be len bytes long. If NULL, the SPI will ignore received bytes.
+ * @return 0 if the transfer succeeds
+ */
+inline int metal_spi_transfer(struct metal_spi *spi, struct metal_spi_config *config, size_t len, char *tx_buf, char *rx_buf) {
+ return spi->vtable->transfer(spi, config, len, tx_buf, rx_buf);
+}
+
+/*! @brief Get the current baud rate of the SPI device
+ * @param spi The handle for the SPI device
+ * @return The baud rate in Hz
+ */
+inline int metal_spi_get_baud_rate(struct metal_spi *spi) { return spi->vtable->get_baud_rate(spi); }
+
+/*! @brief Set the current baud rate of the SPI device
+ * @param spi The handle for the SPI device
+ * @param baud_rate The desired baud rate of the SPI device
+ * @return 0 if the baud rate is successfully changed
+ */
+inline int metal_spi_set_baud_rate(struct metal_spi *spi, int baud_rate) { return spi->vtable->set_baud_rate(spi, baud_rate); }
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/switch.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/switch.h
new file mode 100644
index 000000000..d1c35bc93
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/switch.h
@@ -0,0 +1,51 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__SWITCH_H
+#define METAL__SWITCH_H
+
+/*!
+ * @file switch.h
+ * @brief API for reading toggle switches
+ */
+
+#include <metal/interrupt.h>
+
+struct metal_switch;
+
+struct metal_switch_vtable {
+ int (*switch_exist)(struct metal_switch *sw, char *label);
+ struct metal_interrupt* (*interrupt_controller)(struct metal_switch *sw);
+ int (*get_interrupt_id)(struct metal_switch *sw);
+};
+
+/*!
+ * @brief A handle for a switch
+ */
+struct metal_switch {
+ const struct metal_switch_vtable *vtable;
+};
+
+/*!
+ * @brief Get a handle for a switch
+ * @param label The DeviceTree label for the desired switch
+ * @return A handle to the switch, or NULL if none is found for the requested label
+ */
+struct metal_switch* metal_switch_get(char *label);
+
+/*!
+ * @brief Get the interrupt controller for a switch
+ * @param sw The handle for the switch
+ * @return The interrupt controller handle
+ */
+inline struct metal_interrupt*
+ metal_switch_interrupt_controller(struct metal_switch *sw) { return sw->vtable->interrupt_controller(sw); }
+
+/*!
+ * @brief Get the interrupt id for a switch
+ * @param sw The handle for the switch
+ * @return The interrupt ID for the switch
+ */
+inline int metal_switch_get_interrupt_id(struct metal_switch *sw) { return sw->vtable->get_interrupt_id(sw); }
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/timer.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/timer.h
new file mode 100644
index 000000000..eeae1f60b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/timer.h
@@ -0,0 +1,36 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__TIMER_H
+#define METAL__TIMER_H
+
+/*!
+ * @file timer.h
+ * @brief API for reading and manipulating the machine timer
+ */
+
+/*!
+ * @brief Read the machine cycle count
+ * @param hartid The hart ID to read the cycle count of
+ * @param cyclecount The variable to hold the value
+ * @return 0 upon success
+ */
+int metal_timer_get_cyclecount(int hartid, unsigned long long *cyclecount);
+
+/*!
+ * @brief Get the machine timebase frequency
+ * @param hartid The hart ID to read the timebase of
+ * @param timebase The variable to hold the value
+ * @return 0 upon success
+ */
+int metal_timer_get_timebase_frequency(int hartid, unsigned long long *timebase);
+
+/*!
+ * @brief Set the machine timer tick interval in seconds
+ * @param hartid The hart ID to read the timebase of
+ * @param second The number of seconds to set the tick interval to
+ * @return 0 upon success
+ */
+int metal_timer_set_tick(int hartid, int second);
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/tty.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/tty.h
new file mode 100644
index 000000000..d2583e3be
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/tty.h
@@ -0,0 +1,23 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__TTY_H
+#define METAL__TTY_H
+
+/*!
+ * @file tty.h
+ * @brief API for emulated serial teriminals
+ */
+
+/*!
+ * @brief Write a character to the default output device
+ *
+ * Write a character to the default output device, which for most
+ * targets is the UART serial port.
+ *
+ * @param c The character to write to the terminal
+ * @return 0 on success, or -1 on failure.
+ */
+int metal_tty_putc(unsigned char c);
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/uart.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/uart.h
new file mode 100644
index 000000000..611792a6c
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/install/include/metal/uart.h
@@ -0,0 +1,94 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__UART_H
+#define METAL__UART_H
+
+/*!
+ * @file uart.h
+ * @brief API for UART serial ports
+ */
+
+#include <metal/interrupt.h>
+
+struct metal_uart;
+
+struct metal_uart_vtable {
+ void (*init)(struct metal_uart *uart, int baud_rate);
+ int (*putc)(struct metal_uart *uart, unsigned char c);
+ int (*getc)(struct metal_uart *uart, unsigned char *c);
+ int (*get_baud_rate)(struct metal_uart *uart);
+ int (*set_baud_rate)(struct metal_uart *uart, int baud_rate);
+ struct metal_interrupt* (*controller_interrupt)(struct metal_uart *uart);
+ int (*get_interrupt_id)(struct metal_uart *uart);
+};
+
+/*!
+ * @brief Handle for a UART serial device
+ */
+struct metal_uart {
+ const struct metal_uart_vtable *vtable;
+};
+
+/*!
+ * @brief Initialize UART device
+
+ * Initialize the UART device described by the UART handle. This function must be called before any
+ * other method on the UART can be invoked. It is invalid to initialize a UART more than once.
+ *
+ * @param uart The UART device handle
+ * @param baud_rate the baud rate to set the UART to
+ */
+inline void metal_uart_init(struct metal_uart *uart, int baud_rate) { return uart->vtable->init(uart, baud_rate); }
+
+/*!
+ * @brief Output a character over the UART
+ * @param uart The UART device handle
+ * @param c The character to send over the UART
+ * @return 0 upon success
+ */
+inline int metal_uart_putc(struct metal_uart *uart, unsigned char c) { return uart->vtable->putc(uart, c); }
+
+/*!
+ * @brief Read a character sent over the UART
+ * @param uart The UART device handle
+ * @param c The varible to hold the read character
+ * @return 0 upon success
+ */
+inline int metal_uart_getc(struct metal_uart *uart, unsigned char *c) { return uart->vtable->getc(uart, c); }
+
+/*!
+ * @brief Get the baud rate of the UART peripheral
+ * @param uart The UART device handle
+ * @return The current baud rate of the UART
+ */
+inline int metal_uart_get_baud_rate(struct metal_uart *uart) { return uart->vtable->get_baud_rate(uart); }
+
+/*!
+ * @brief Set the baud rate of the UART peripheral
+ * @param uart The UART device handle
+ * @param baud_rate The baud rate to configure
+ * @return the new baud rate of the UART
+ */
+inline int metal_uart_set_baud_rate(struct metal_uart *uart, int baud_rate) { return uart->vtable->set_baud_rate(uart, baud_rate); }
+
+/*!
+ * @brief Get the interrupt controller of the UART peripheral
+ *
+ * Get the interrupt controller for the UART peripheral. The interrupt
+ * controller must be initialized before any interrupts can be registered
+ * or enabled with it.
+ *
+ * @param uart The UART device handle
+ * @return The handle for the UART interrupt controller
+ */
+inline struct metal_interrupt* metal_uart_interrupt_controller(struct metal_uart *uart) { return uart->vtable->controller_interrupt(uart); }
+
+/*!
+ * @brief Get the interrupt ID of the UART controller
+ * @param uart The UART device handle
+ * @return The UART interrupt id
+ */
+inline int metal_uart_get_interrupt_id(struct metal_uart *uart) { return uart->vtable->get_interrupt_id(uart); }
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal-inline.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal-inline.h
new file mode 100644
index 000000000..8c0cd048b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal-inline.h
@@ -0,0 +1,249 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+/* ----------------------------------- */
+/* ----------------------------------- */
+
+#ifndef ASSEMBLY
+
+#ifndef SIFIVE_HIFIVE1_REVB____METAL_INLINE_H
+#define SIFIVE_HIFIVE1_REVB____METAL_INLINE_H
+
+#include <metal/machine.h>
+
+
+/* --------------------- 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);
+
+
+/* --------------------- 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);
+
+
+/* --------------------- sifive_clic0 ------------ */
+
+
+/* --------------------- sifive_local_external_interrupts0 ------------ */
+extern inline struct metal_interrupt * __metal_driver_sifive_local_external_interrupts0_interrupt_parent(struct metal_interrupt *controller);
+extern inline int __metal_driver_sifive_local_external_interrupts0_num_interrupts(struct metal_interrupt *controller);
+extern inline int __metal_driver_sifive_local_external_interrupts0_interrupt_lines(struct metal_interrupt *controller, int idx);
+
+
+/* --------------------- 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_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_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_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_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( );
+
+
+/* --------------------- sifive_fu540_c000_l2 ------------ */
+
+
+/* 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,
+};
+
+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_spi_10014000 = {
+ ._base_address = 536870912UL,
+ ._size = 500000UL,
+ ._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,
+};
+
+/* 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,
+};
+
+/* From local_external_interrupts_0 */
+struct __metal_driver_sifive_local_external_interrupts0 __metal_dt_local_external_interrupts_0 = {
+ .irc.vtable = &__metal_driver_vtable_sifive_local_external_interrupts0.local0_vtable,
+ .init_done = 0,
+};
+
+/* From gpio@10012000 */
+struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000 = {
+ .gpio.vtable = &__metal_driver_vtable_sifive_gpio0.gpio,
+};
+
+/* From led@0red */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0red = {
+ .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
+};
+
+/* From led@0green */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0green = {
+ .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
+};
+
+/* From led@0blue */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0blue = {
+ .led.vtable = &__metal_driver_vtable_sifive_led.led_vtable,
+};
+
+/* From spi@10014000 */
+struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000 = {
+ .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 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@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 = {
+};
+
+
+#endif /* SIFIVE_HIFIVE1_REVB____METAL_INLINE_H*/
+#endif /* ! ASSEMBLY */
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal-platform.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal-platform.h
new file mode 100644
index 000000000..4ecd3e336
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal-platform.h
@@ -0,0 +1,237 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+/* ----------------------------------- */
+/* ----------------------------------- */
+
+#ifndef SIFIVE_HIFIVE1_REVB____METAL_PLATFORM_H
+#define SIFIVE_HIFIVE1_REVB____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 32000000UL
+
+#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 27UL
+#define METAL_RISCV_PLIC0_0_RISCV_NDEV 27UL
+
+#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_THRESHOLD 2097152UL
+#define METAL_RISCV_PLIC0_CLAIM 2097156UL
+
+/* 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 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@0red */
+
+/* From led@0green */
+
+/* From led@0blue */
+
+#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 local_external_interrupts_0 */
+
+#define METAL_SIFIVE_LOCAL_EXTERNAL_INTERRUPTS0
+
+/* 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
+
+#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 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
+
+#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
+
+#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
+
+#endif /* SIFIVE_HIFIVE1_REVB____METAL_PLATFORM_H*/
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal.default.lds b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal.default.lds
new file mode 100644
index 000000000..7070af7e8
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal.default.lds
@@ -0,0 +1,236 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+/* ----------------------------------- */
+/* ----------------------------------- */
+
+OUTPUT_ARCH("riscv")
+
+ENTRY(_enter)
+
+MEMORY
+{
+ ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 0x4000
+ flash (rxai!w) : ORIGIN = 0x20010000, LENGTH = 0x6a120
+}
+
+PHDRS
+{
+ flash PT_LOAD;
+ ram_init PT_LOAD;
+ itim_init PT_LOAD;
+ ram PT_NULL;
+ itim PT_NULL;
+}
+
+SECTIONS
+{
+ __stack_size = DEFINED(__stack_size) ? __stack_size : 0x400;
+ PROVIDE(__stack_size = __stack_size);
+ __heap_size = DEFINED(__heap_size) ? __heap_size : 0x4;
+ PROVIDE(__metal_boot_hart = 0);
+ PROVIDE(__metal_chicken_bit = 0);
+
+
+ .init :
+ {
+ KEEP (*(.text.metal.init.enter))
+ KEEP (*(SORT_NONE(.init)))
+ KEEP (*(.text.libgloss.start))
+ } >flash AT>flash :flash
+
+
+ .text :
+ {
+ *(.text.unlikely .text.unlikely.*)
+ *(.text.startup .text.startup.*)
+ *(.text .text.*)
+ *(.itim .itim.*)
+ *(.gnu.linkonce.t.*)
+ } >flash AT>flash :flash
+
+
+ .fini :
+ {
+ KEEP (*(SORT_NONE(.fini)))
+ } >flash AT>flash :flash
+
+
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+
+
+ .rodata :
+ {
+ *(.rdata)
+ *(.rodata .rodata.*)
+ *(.gnu.linkonce.r.*)
+ . = ALIGN(8);
+ *(.srodata.cst16)
+ *(.srodata.cst8)
+ *(.srodata.cst4)
+ *(.srodata.cst2)
+ *(.srodata .srodata.*)
+ } >flash AT>flash :flash
+
+
+ . = ALIGN(4);
+
+
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ } >flash AT>flash :flash
+
+
+ .init_array :
+ {
+ 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 = .);
+ } >flash AT>flash :flash
+
+
+ .fini_array :
+ {
+ 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 = .);
+ } >flash AT>flash :flash
+
+
+ .ctors :
+ {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*crtbegin?.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ } >flash AT>flash :flash
+
+
+ .dtors :
+ {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*crtbegin?.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ } >flash AT>flash :flash
+
+
+ .litimalign :
+ {
+ . = ALIGN(4);
+ PROVIDE( metal_segment_itim_source_start = . );
+ } >flash AT>flash :flash
+
+
+ .ditimalign :
+ {
+ . = ALIGN(4);
+ PROVIDE( metal_segment_itim_target_start = . );
+ } >ram AT>flash :ram_init
+
+
+ .itim :
+ {
+ *(.itim .itim.*)
+ } >flash AT>flash :flash
+
+
+ . = ALIGN(8);
+ PROVIDE( metal_segment_itim_target_end = . );
+
+
+ .lalign :
+ {
+ . = ALIGN(4);
+ PROVIDE( _data_lma = . );
+ PROVIDE( metal_segment_data_source_start = . );
+ } >flash AT>flash :flash
+
+
+ .dalign :
+ {
+ . = ALIGN(4);
+ PROVIDE( metal_segment_data_target_start = . );
+ } >ram AT>flash :ram_init
+
+
+ .data :
+ {
+ *(.data .data.*)
+ *(.gnu.linkonce.d.*)
+ . = ALIGN(8);
+ PROVIDE( __global_pointer$ = . + 0x800 );
+ *(.sdata .sdata.* .sdata2.*)
+ *(.gnu.linkonce.s.*)
+ } >ram AT>flash :ram_init
+
+
+ . = ALIGN(4);
+ PROVIDE( _edata = . );
+ PROVIDE( edata = . );
+ PROVIDE( metal_segment_data_target_end = . );
+ PROVIDE( _fbss = . );
+ PROVIDE( __bss_start = . );
+ PROVIDE( metal_segment_bss_target_start = . );
+
+
+ .bss :
+ {
+ *(.sbss*)
+ *(.gnu.linkonce.sb.*)
+ *(.bss .bss.*)
+ *(.gnu.linkonce.b.*)
+ *(COMMON)
+ . = ALIGN(4);
+ } >ram AT>ram :ram
+
+
+ . = ALIGN(8);
+ PROVIDE( _end = . );
+ PROVIDE( end = . );
+ PROVIDE( metal_segment_bss_target_end = . );
+
+ .stack :
+ {
+ . = ALIGN(16);
+ metal_segment_stack_begin = .;
+ . += __stack_size;
+ . = ALIGN(16);
+ _sp = .;
+ PROVIDE(metal_segment_stack_end = .);
+ __freertos_irq_stack_top = .;
+ } >ram AT>ram :ram
+
+
+ .heap :
+ {
+ PROVIDE( metal_segment_heap_target_start = . );
+ . = __heap_size;
+ PROVIDE( metal_segment_heap_target_end = . );
+ PROVIDE( _heap_end = . );
+ } >ram AT>ram :ram
+
+
+}
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal.h
new file mode 100644
index 000000000..f76dbd632
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/bsp/metal.h
@@ -0,0 +1,872 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+/* ----------------------------------- */
+/* ----------------------------------- */
+
+#ifndef ASSEMBLY
+
+#include <metal/machine/platform.h>
+
+#ifdef __METAL_MACHINE_MACROS
+
+#ifndef MACROS_IF_SIFIVE_HIFIVE1_REVB____METAL_H
+#define MACROS_IF_SIFIVE_HIFIVE1_REVB____METAL_H
+
+#define __METAL_CLINT_NUM_PARENTS 2
+
+#ifndef __METAL_CLINT_NUM_PARENTS
+#define __METAL_CLINT_NUM_PARENTS 0
+#endif
+#define __METAL_PLIC_SUBINTERRUPTS 27
+
+#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_SIFIVE_HIFIVE1_REVB____METAL_H*/
+
+#else /* ! __METAL_MACHINE_MACROS */
+
+#ifndef MACROS_ELSE_SIFIVE_HIFIVE1_REVB____METAL_H
+#define MACROS_ELSE_SIFIVE_HIFIVE1_REVB____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 27
+
+#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_LOCAL_EXTERNAL_INTERRUPTS_0_INTERRUPTS 16
+
+#define METAL_MAX_LOCAL_EXT_INTERRUPTS 16
+
+#define METAL_MAX_GLOBAL_EXT_INTERRUPTS 0
+
+#define __METAL_GPIO_10012000_INTERRUPTS 16
+
+#define METAL_MAX_GPIO_INTERRUPTS 16
+
+#define __METAL_SERIAL_10013000_INTERRUPTS 1
+
+#define METAL_MAX_UART_INTERRUPTS 1
+
+
+#include <metal/drivers/fixed-clock.h>
+#include <metal/memory.h>
+#include <metal/drivers/riscv_clint0.h>
+#include <metal/drivers/riscv_cpu.h>
+#include <metal/drivers/riscv_plic0.h>
+#include <metal/pmp.h>
+#include <metal/drivers/sifive_local-external-interrupts0.h>
+#include <metal/drivers/sifive_gpio0.h>
+#include <metal/drivers/sifive_gpio-leds.h>
+#include <metal/drivers/sifive_spi0.h>
+#include <metal/drivers/sifive_uart0.h>
+#include <metal/drivers/sifive_fe310-g000_hfrosc.h>
+#include <metal/drivers/sifive_fe310-g000_hfxosc.h>
+#include <metal/drivers/sifive_fe310-g000_pll.h>
+#include <metal/drivers/sifive_fe310-g000_prci.h>
+
+/* From clock@0 */
+struct __metal_driver_fixed_clock __metal_dt_clock_0;
+
+/* From clock@2 */
+struct __metal_driver_fixed_clock __metal_dt_clock_2;
+
+/* From clock@5 */
+struct __metal_driver_fixed_clock __metal_dt_clock_5;
+
+struct metal_memory __metal_dt_mem_dtim_80000000;
+
+struct metal_memory __metal_dt_mem_spi_10014000;
+
+/* From clint@2000000 */
+struct __metal_driver_riscv_clint0 __metal_dt_clint_2000000;
+
+/* From cpu@0 */
+struct __metal_driver_cpu __metal_dt_cpu_0;
+
+struct __metal_driver_riscv_cpu_intc __metal_dt_cpu_0_interrupt_controller;
+
+/* From interrupt_controller@c000000 */
+struct __metal_driver_riscv_plic0 __metal_dt_interrupt_controller_c000000;
+
+struct metal_pmp __metal_dt_pmp;
+
+/* From local_external_interrupts_0 */
+struct __metal_driver_sifive_local_external_interrupts0 __metal_dt_local_external_interrupts_0;
+
+/* From gpio@10012000 */
+struct __metal_driver_sifive_gpio0 __metal_dt_gpio_10012000;
+
+/* From led@0red */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0red;
+
+/* From led@0green */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0green;
+
+/* From led@0blue */
+struct __metal_driver_sifive_gpio_led __metal_dt_led_0blue;
+
+/* From spi@10014000 */
+struct __metal_driver_sifive_spi0 __metal_dt_spi_10014000;
+
+/* From serial@10013000 */
+struct __metal_driver_sifive_uart0 __metal_dt_serial_10013000;
+
+/* From clock@3 */
+struct __metal_driver_sifive_fe310_g000_hfrosc __metal_dt_clock_3;
+
+/* From clock@1 */
+struct __metal_driver_sifive_fe310_g000_hfxosc __metal_dt_clock_1;
+
+/* From clock@4 */
+struct __metal_driver_sifive_fe310_g000_pll __metal_dt_clock_4;
+
+/* From prci@10008000 */
+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 {
+ 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 1000000;
+ }
+ 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;
+ }
+}
+
+
+
+/* --------------------- 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 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 if (idx == 0) {
+ return 11;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+
+/* --------------------- sifive_clic0 ------------ */
+
+
+/* --------------------- sifive_local_external_interrupts0 ------------ */
+static inline struct metal_interrupt * __metal_driver_sifive_local_external_interrupts0_interrupt_parent(struct metal_interrupt *controller)
+{
+ if ((uintptr_t)controller == (uintptr_t)&__metal_dt_local_external_interrupts_0) {
+ return (struct metal_interrupt *)&__metal_dt_cpu_0_interrupt_controller.controller;
+ }
+ else {
+ return NULL;
+ }
+}
+
+static inline int __metal_driver_sifive_local_external_interrupts0_num_interrupts(struct metal_interrupt *controller)
+{
+ if ((uintptr_t)controller == (uintptr_t)&__metal_dt_local_external_interrupts_0) {
+ return METAL_MAX_LOCAL_EXT_INTERRUPTS;
+ }
+ else {
+ return 0;
+ }
+}
+
+static inline int __metal_driver_sifive_local_external_interrupts0_interrupt_lines(struct metal_interrupt *controller, int idx)
+{
+ if (idx == 0) {
+ return 16;
+ }
+ else if (idx == 1) {
+ return 17;
+ }
+ else if (idx == 2) {
+ return 18;
+ }
+ else if (idx == 3) {
+ return 19;
+ }
+ else if (idx == 4) {
+ return 20;
+ }
+ else if (idx == 5) {
+ return 21;
+ }
+ else if (idx == 6) {
+ return 22;
+ }
+ else if (idx == 7) {
+ return 23;
+ }
+ else if (idx == 8) {
+ return 24;
+ }
+ else if (idx == 9) {
+ return 25;
+ }
+ else if (idx == 10) {
+ return 26;
+ }
+ else if (idx == 11) {
+ return 27;
+ }
+ else if (idx == 12) {
+ return 28;
+ }
+ else if (idx == 13) {
+ return 29;
+ }
+ else if (idx == 14) {
+ return 30;
+ }
+ else if (idx == 15) {
+ return 31;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+
+/* --------------------- 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 7;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 1))) {
+ return 8;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 2))) {
+ return 9;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 3))) {
+ return 10;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 4))) {
+ return 11;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 5))) {
+ return 12;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 6))) {
+ return 13;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 7))) {
+ return 14;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 8))) {
+ return 15;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 9))) {
+ return 16;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 10))) {
+ return 17;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 11))) {
+ return 18;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 12))) {
+ return 19;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 13))) {
+ return 20;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 14))) {
+ return 21;
+ }
+ else if ((((uintptr_t)gpio == (uintptr_t)&__metal_dt_gpio_10012000) && (idx == 15))) {
+ return 22;
+ }
+ 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_0red) {
+ return (struct metal_gpio *)&__metal_dt_gpio_10012000;
+ }
+ else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0green) {
+ return (struct metal_gpio *)&__metal_dt_gpio_10012000;
+ }
+ else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0blue) {
+ 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_0red) {
+ return 22;
+ }
+ else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0green) {
+ return 19;
+ }
+ else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0blue) {
+ return 21;
+ }
+ 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_0red) {
+ return "LD0red";
+ }
+ else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0green) {
+ return "LD0green";
+ }
+ else if ((uintptr_t)led == (uintptr_t)&__metal_dt_led_0blue) {
+ return "LD0blue";
+ }
+ else {
+ return "";
+ }
+}
+
+
+
+/* --------------------- sifive_gpio_switch ------------ */
+
+
+/* --------------------- sifive_spi0 ------------ */
+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 {
+ 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 {
+ return 0;
+ }
+}
+
+static inline struct metal_clock * __metal_driver_sifive_spi0_clock(struct metal_spi *spi)
+{
+ return (struct metal_clock *)&__metal_dt_clock_4.clock;
+}
+
+static inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_spi0_pinmux(struct metal_spi *spi)
+{
+ return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000;
+}
+
+static inline unsigned long __metal_driver_sifive_spi0_pinmux_output_selector(struct metal_spi *spi)
+{
+ return 60;
+}
+
+static inline unsigned long __metal_driver_sifive_spi0_pinmux_source_selector(struct metal_spi *spi)
+{
+ return 60;
+}
+
+
+
+/* --------------------- sifive_test0 ------------ */
+
+
+/* --------------------- 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 {
+ 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 {
+ 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 {
+ 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 {
+ return NULL;
+ }
+}
+
+static inline int __metal_driver_sifive_uart0_interrupt_line(struct metal_uart *uart)
+{
+ return 5;
+}
+
+static inline struct metal_clock * __metal_driver_sifive_uart0_clock(struct metal_uart *uart)
+{
+ return (struct metal_clock *)&__metal_dt_clock_4.clock;
+}
+
+static inline struct __metal_driver_sifive_gpio0 * __metal_driver_sifive_uart0_pinmux(struct metal_uart *uart)
+{
+ return (struct __metal_driver_sifive_gpio0 *)&__metal_dt_gpio_10012000;
+}
+
+static inline unsigned long __metal_driver_sifive_uart0_pinmux_output_selector(struct metal_uart *uart)
+{
+ return 196608;
+}
+
+static inline unsigned long __metal_driver_sifive_uart0_pinmux_source_selector(struct metal_uart *uart)
+{
+ return 196608;
+}
+
+
+
+/* --------------------- 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_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;
+}
+
+
+
+/* --------------------- sifive_fu540_c000_l2 ------------ */
+
+
+#define __METAL_DT_MAX_MEMORIES 2
+
+asm (".weak __metal_memory_table");
+struct metal_memory *__metal_memory_table[] = {
+ &__metal_dt_mem_dtim_80000000,
+ &__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
+
+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)
+
+/* From local_external_interrupts_0 */
+#define __METAL_DT_SIFIVE_LOCAL_EXINTR0_HANDLE (&__metal_dt_local_external_interrupts_0.irc)
+
+#define __METAL_DT_LOCAL_EXTERNAL_INTERRUPTS_0_HANDLE (&__metal_dt_local_external_interrupts_0.irc)
+
+#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 3
+
+asm (".weak __metal_led_table");
+struct __metal_driver_sifive_gpio_led *__metal_led_table[] = {
+ &__metal_dt_led_0red,
+ &__metal_dt_led_0green,
+ &__metal_dt_led_0blue};
+
+#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_SPIS 1
+
+asm (".weak __metal_spi_table");
+struct __metal_driver_sifive_spi0 *__metal_spi_table[] = {
+ &__metal_dt_spi_10014000};
+
+/* 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_SIFIVE_HIFIVE1_REVB____METAL_H*/
+
+#endif /* ! __METAL_MACHINE_MACROS */
+
+#endif /* ! ASSEMBLY */
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/doc/link_to_docs_in_github.url b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/doc/link_to_docs_in_github.url
new file mode 100644
index 000000000..f59b1cedd
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/doc/link_to_docs_in_github.url
@@ -0,0 +1,5 @@
+[{000214A0-0000-0000-C000-000000000046}]
+Prop3=19,11
+[InternetShortcut]
+IDList=
+URL=https://github.com/sifive/freedom-metal-docs
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/crt0.S b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/crt0.S
new file mode 100644
index 000000000..920ee4b9f
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/crt0.S
@@ -0,0 +1,246 @@
+/* Copyright (c) 2017-2018 SiFive Inc. All rights reserved.
+
+ This copyrighted material is made available to anyone wishing to use,
+ modify, copy, or redistribute it subject to the terms and conditions
+ of the FreeBSD License. This program is distributed in the hope that
+ it will be useful, but WITHOUT ANY WARRANTY expressed or implied,
+ including the implied warranties of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. A copy of this license is available at
+ http://www.opensource.org/licenses.
+*/
+
+/* crt0.S: Entry point for RISC-V METAL programs. */
+
+.section .text.libgloss.start
+.global _start
+.type _start, @function
+
+ /* _start is defined by the METAL to have been called with the following
+ * arguments:
+ * a0: the hart ID of the currently executing hart. Harts can start at
+ * any arbitrary point, it's the C library's job to ensure the code is
+ * safe.
+ * a1: a pointer to a description of the machine on which this code is
+ * currently executing. This is probably 0 on an embedded system
+ * because they tend to not be dynamically portable. As such, newlib
+ * ignores this argument.
+ * a2: a pointer to a function that must be run after the envirnoment has
+ * been initialized, but before user code can be expected to be run.
+ * If this is 0 then there is no function to be run. */
+_start:
+.cfi_startproc
+.cfi_undefined ra
+
+ /* This is a bit funky: it's not usually sane for _start to return, but in
+ * this case we actually want to in order to signal an error to the METAL. */
+ mv s0, ra
+
+ /* Before doing anything we must initialize the global pointer, as we cannot
+ * safely perform any access that may be relaxed without GP being set. This
+ * is done with relaxation disabled to avoid relaxing the address calculation
+ * to just "addi gp, gp, 0". */
+.option push
+.option norelax
+ la gp, __global_pointer$
+.option pop
+
+ /* The METAL is designed for a bare-metal environment and therefor is expected
+ * to define its own stack pointer. We also align the stack pointer here
+ * because the only RISC-V ABI that's currently defined mandates 16-byte
+ * stack alignment. */
+ la sp, _sp
+
+ /* Increment by hartid number of stack sizes */
+ li t0, 0
+ la t1, __stack_size
+1:
+ beq t0, a0, 1f
+ add sp, sp, t1
+ addi t0, t0, 1
+ j 1b
+1:
+ andi sp, sp, -16
+
+ /* If we're not hart 0, skip the initialization work */
+ la t0, __metal_boot_hart
+ bne a0, t0, _skip_init
+
+ /* Embedded systems frequently require relocating the data segment before C
+ * code can be run -- for example, the data segment may exist in flash upon
+ * boot and then need to get relocated into a non-persistant writable memory
+ * before C code can execute. If this is the case we do so here. This step
+ * is optional: if the METAL provides an environment in which this relocation
+ * is not necessary then it must simply set metal_segment_data_source_start to
+ * be equal to metal_segment_data_target_start. */
+ la t0, metal_segment_data_source_start
+ la t1, metal_segment_data_target_start
+ la t2, metal_segment_data_target_end
+
+ beq t0, t1, 2f
+ bge t1, t2, 2f
+
+1:
+#if __riscv_xlen == 32
+ lw a0, 0(t0)
+ addi t0, t0, 4
+ sw a0, 0(t1)
+ addi t1, t1, 4
+ blt t1, t2, 1b
+#else
+ ld a0, 0(t0)
+ addi t0, t0, 8
+ sd a0, 0(t1)
+ addi t1, t1, 8
+ blt t1, t2, 1b
+#endif
+2:
+
+ /* Copy the ITIM section */
+ la t0, metal_segment_itim_source_start
+ la t1, metal_segment_itim_target_start
+ la t2, metal_segment_itim_target_end
+
+ beq t0, t1, 2f
+ bge t1, t2, 2f
+
+1:
+#if __riscv_xlen == 32
+ lw a0, 0(t0)
+ addi t0, t0, 4
+ sw a0, 0(t1)
+ addi t1, t1, 4
+ blt t1, t2, 1b
+#else
+ ld a0, 0(t0)
+ addi t0, t0, 8
+ sd a0, 0(t1)
+ addi t1, t1, 8
+ blt t1, t2, 1b
+#endif
+2:
+
+ /* Fence all subsequent instruction fetches until after the ITIM writes
+ complete */
+ fence.i
+
+ /* Zero the BSS segment. */
+ la t1, metal_segment_bss_target_start
+ la t2, metal_segment_bss_target_end
+
+ bge t1, t2, 2f
+
+1:
+#if __riscv_xlen == 32
+ sw x0, 0(t1)
+ addi t1, t1, 4
+ blt t1, t2, 1b
+#else
+ sd x0, 0(t1)
+ addi t1, t1, 8
+ blt t1, t2, 1b
+#endif
+2:
+
+ /* At this point we're in an environment that can execute C code. The first
+ * thing to do is to make the callback to the parent environment if it's been
+ * requested to do so. */
+ beqz a2, 1f
+ jalr a2
+1:
+
+ /* The RISC-V port only uses new-style constructors and destructors. */
+ la a0, __libc_fini_array
+ call atexit
+ call __libc_init_array
+
+_skip_init:
+
+ /* Synchronize harts so that secondary harts wait until hart 0 finishes
+ initializing */
+ call __metal_synchronize_harts
+
+ /* Check RISC-V isa and enable FS bits if Floating Point architecture. */
+ csrr a5, misa
+ li a4, 0x10028
+ and a5, a5, a4
+ beqz a5, 1f
+ csrr a5, mstatus
+ lui a4, 0x2
+ or a5, a5, a4
+ csrw mstatus, a5
+ csrwi fcsr, 0
+1:
+
+ /* This is a C runtime, so main() is defined to have some arguments. Since
+ * there's nothing sane the METAL can pass we don't bother with that but
+ * instead just setup as close to a NOP as we can. */
+ li a0, 1 /* argc=1 */
+ la a1, argv /* argv = {"libgloss", NULL} */
+ la a2, envp /* envp = {NULL} */
+ call secondary_main
+
+ /* Call exit to handle libc's cleanup routines. Under normal contains this
+ * shouldn't even get called, but I'm still not using a tail call here
+ * because returning to the METAL is the right thing to do in pathological
+ * situations. */
+ call exit
+
+ /* And here's where we return. Again, it's a bit odd but the METAL defines
+ * this as a bad idea (ie, as opposed to leaving it undefined) and at this
+ * point it's really the only thing left to do. */
+ mv ra, s0
+ ret
+
+.cfi_endproc
+
+/* RISC-V systems always use __libc_{init,fini}_array, but for compatibility we
+ * define _{init,fini} to do nothing. */
+.global _init
+.type _init, @function
+.global _fini
+.type _fini, @function
+_init:
+_fini:
+ ret
+.size _init, .-_init
+.size _fini, .-_fini
+
+/* By default, secondary_main will cause secondary harts to spin forever.
+ * Users can redefine secondary_main themselves to run code on secondary harts */
+.weak secondary_main
+.global secondary_main
+.type secondary_main, @function
+
+secondary_main:
+ addi sp, sp, -16
+#if __riscv_xlen == 32
+ sw ra, 4(sp)
+#else
+ sd ra, 8(sp)
+#endif
+ csrr t0, mhartid
+ la t1, __metal_boot_hart
+ beq t0, t1, 2f
+1:
+ wfi
+ j 1b
+2:
+ call main
+#if __riscv_xlen == 32
+ lw ra, 4(sp)
+#else
+ ld ra, 8(sp)
+#endif
+ addi sp, sp, 16
+ ret
+
+/* This shim allows main() to be passed a set of arguments that can satisfy the
+ * requirements of the C API. */
+.section .rodata.libgloss.start
+argv:
+.dc.a name
+envp:
+.dc.a 0
+name:
+.asciz "libgloss"
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/nanosleep.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/nanosleep.c
new file mode 100644
index 000000000..8be22104e
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/nanosleep.c
@@ -0,0 +1,9 @@
+#include <errno.h>
+#include <sys/time.h>
+
+int
+nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/synchronize_harts.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/synchronize_harts.c
new file mode 100644
index 000000000..3e857d1df
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/synchronize_harts.c
@@ -0,0 +1,59 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine.h>
+#include <metal/machine/platform.h>
+#include <metal/io.h>
+#include <metal/cpu.h>
+
+#define METAL_REG(base, offset) (((unsigned long)(base) + (offset)))
+#define METAL_REGW(base, offset) (__METAL_ACCESS_ONCE((__metal_io_u32 *)METAL_REG((base), (offset))))
+#define METAL_MSIP(base, hart) (METAL_REGW((base),4*(hart)))
+
+/*
+ * _synchronize_harts() is called by crt0.S to cause harts > 0 to wait for
+ * hart 0 to finish copying the datat section, zeroing the BSS, and running
+ * the libc contstructors.
+ */
+void _synchronize_harts() {
+#if __METAL_DT_MAX_HARTS > 1
+
+ int hart = metal_cpu_get_current_hartid();
+ uintptr_t msip_base = 0;
+
+ /* Get the base address of the MSIP registers */
+#ifdef __METAL_DT_RISCV_CLINT0_HANDLE
+ msip_base = __metal_driver_sifive_clint0_control_base(__METAL_DT_RISCV_CLINT0_HANDLE);
+ msip_base += METAL_RISCV_CLINT0_MSIP_BASE;
+#elif __METAL_DT_RISCV_CLIC0_HANDLE
+ msip_base = __metal_driver_sifive_clic0_control_base(__METAL_DT_RISCV_CLIC0_HANDLE);
+ msip_base += METAL_RISCV_CLIC0_MSIP_BASE;
+#else
+#warning No handle for CLINT or CLIC found, harts may be unsynchronized after init!
+#endif
+
+ /* Disable machine interrupts as a precaution */
+ __asm__ volatile("csrc mstatus, %0" :: "r" (METAL_MSTATUS_MIE));
+
+ if (hart == 0) {
+ /* Hart 0 waits for all harts to set their MSIP bit */
+ for (int i = 1 ; i < __METAL_DT_MAX_HARTS; i++) {
+ while (METAL_MSIP(msip_base, i) == 0) ;
+ }
+
+ /* Hart 0 clears everyone's MSIP bit */
+ for (int i = 1 ; i < __METAL_DT_MAX_HARTS; i++) {
+ METAL_MSIP(msip_base, i) = 0;
+ }
+ } else {
+ /* Other harts set their MSIP bit to indicate they're ready */
+ METAL_MSIP(msip_base, hart) = 1;
+ __asm__ volatile ("fence w,rw");
+
+ /* Wait for hart 0 to clear the MSIP bit */
+ while (METAL_MSIP(msip_base, hart) == 1) ;
+ }
+
+#endif /* __METAL_DT_MAX_HARTS > 1 */
+}
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_access.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_access.c
new file mode 100644
index 000000000..c0bc1534d
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_access.c
@@ -0,0 +1,8 @@
+#include <errno.h>
+
+int
+_access(const char *file, int mode)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_chdir.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_chdir.c
new file mode 100644
index 000000000..f33d26a44
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_chdir.c
@@ -0,0 +1,8 @@
+#include <errno.h>
+
+int
+_chdir(const char *path)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_chmod.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_chmod.c
new file mode 100644
index 000000000..67412bf7d
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_chmod.c
@@ -0,0 +1,9 @@
+#include <errno.h>
+#include <sys/types.h>
+
+int
+_chmod(const char *path, mode_t mode)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_chown.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_chown.c
new file mode 100644
index 000000000..302952eb1
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_chown.c
@@ -0,0 +1,9 @@
+#include <sys/types.h>
+#include <errno.h>
+
+int
+_chown(const char *path, uid_t owner, gid_t group)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_close.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_close.c
new file mode 100644
index 000000000..26dd6a59e
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_close.c
@@ -0,0 +1,8 @@
+#include <errno.h>
+
+int
+_close(int file)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_execve.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_execve.c
new file mode 100644
index 000000000..9ae9f7e50
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_execve.c
@@ -0,0 +1,8 @@
+#include <errno.h>
+
+int
+_execve(const char *name, char *const argv[], char *const env[])
+{
+ errno = ENOMEM;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_exit.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_exit.c
new file mode 100644
index 000000000..35f5f1a16
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_exit.c
@@ -0,0 +1,8 @@
+#include <metal/shutdown.h>
+
+void
+_exit(int exit_status)
+{
+ metal_shutdown(exit_status);
+ while (1);
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_faccessat.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_faccessat.c
new file mode 100644
index 000000000..873d52c2e
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_faccessat.c
@@ -0,0 +1,8 @@
+#include <errno.h>
+
+int
+_faccessat(int dirfd, const char *file, int mode, int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_fork.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_fork.c
new file mode 100644
index 000000000..64e67569f
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_fork.c
@@ -0,0 +1,8 @@
+#include <errno.h>
+
+int
+_fork()
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_fstat.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_fstat.c
new file mode 100644
index 000000000..fedc28977
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_fstat.c
@@ -0,0 +1,9 @@
+#include <errno.h>
+#include <sys/stat.h>
+
+int
+_fstat(int file, struct stat *st)
+{
+ errno = -ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_fstatat.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_fstatat.c
new file mode 100644
index 000000000..f2f43bd9e
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_fstatat.c
@@ -0,0 +1,9 @@
+#include <errno.h>
+#include <sys/stat.h>
+
+int
+_fstatat(int dirfd, const char *file, struct stat *st, int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_ftime.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_ftime.c
new file mode 100644
index 000000000..65c156398
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_ftime.c
@@ -0,0 +1,9 @@
+#include <errno.h>
+#include <sys/timeb.h>
+
+int
+_ftime(struct timeb *tp)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_getcwd.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_getcwd.c
new file mode 100644
index 000000000..82e8404ee
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_getcwd.c
@@ -0,0 +1,8 @@
+#include <errno.h>
+
+char *
+_getcwd(char *buf, size_t size)
+{
+ errno = -ENOSYS;
+ return NULL;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_getpid.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_getpid.c
new file mode 100644
index 000000000..589ad117c
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_getpid.c
@@ -0,0 +1,7 @@
+#include <errno.h>
+
+int
+_getpid()
+{
+ return 1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_gettimeofday.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_gettimeofday.c
new file mode 100644
index 000000000..409b2ce2f
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_gettimeofday.c
@@ -0,0 +1,21 @@
+#include <errno.h>
+#include <metal/timer.h>
+#include <sys/time.h>
+
+int
+_gettimeofday(struct timeval *tp, void *tzp)
+{
+ int rv;
+ unsigned long long mcc, timebase;
+ rv = metal_timer_get_cyclecount(0, &mcc);
+ if (rv != 0) {
+ return -1;
+ }
+ rv = metal_timer_get_timebase_frequency(0, &timebase);
+ if (rv != 0) {
+ return -1;
+ }
+ tp->tv_sec = mcc / timebase;
+ tp->tv_usec = mcc % timebase * 1000000 / timebase;
+ return 0;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_isatty.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_isatty.c
new file mode 100644
index 000000000..dd4f1461b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_isatty.c
@@ -0,0 +1,7 @@
+#include <unistd.h>
+
+int
+_isatty(int file)
+{
+ return (file == STDOUT_FILENO);
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_kill.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_kill.c
new file mode 100644
index 000000000..9003f266f
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_kill.c
@@ -0,0 +1,8 @@
+#include <errno.h>
+
+int
+_kill(int pid, int sig)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_link.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_link.c
new file mode 100644
index 000000000..40d5912bc
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_link.c
@@ -0,0 +1,7 @@
+#include <errno.h>
+
+int _link(const char *old_name, const char *new_name)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_lseek.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_lseek.c
new file mode 100644
index 000000000..d28a781f8
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_lseek.c
@@ -0,0 +1,9 @@
+#include <sys/types.h>
+#include <errno.h>
+
+off_t
+_lseek(int file, off_t ptr, int dir)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_lstat.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_lstat.c
new file mode 100644
index 000000000..97a45855f
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_lstat.c
@@ -0,0 +1,8 @@
+#include <errno.h>
+#include <sys/stat.h>
+
+int _lstat(const char *file, struct stat *st)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_open.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_open.c
new file mode 100644
index 000000000..a59f627f0
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_open.c
@@ -0,0 +1,8 @@
+#include <errno.h>
+
+int
+_open(const char *name, int flags, int mode)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_openat.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_openat.c
new file mode 100644
index 000000000..206de3bde
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_openat.c
@@ -0,0 +1,8 @@
+#include <errno.h>
+
+int
+_openat(int dirfd, const char *name, int flags, int mode)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_read.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_read.c
new file mode 100644
index 000000000..15833cabb
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_read.c
@@ -0,0 +1,9 @@
+#include <sys/types.h>
+#include <errno.h>
+
+ssize_t
+_read(int file, void *ptr, size_t len)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_sbrk.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_sbrk.c
new file mode 100644
index 000000000..cc01c8ffb
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_sbrk.c
@@ -0,0 +1,39 @@
+#include <sys/types.h>
+
+/* brk is handled entirely within the C library. This limits METAL programs that
+ * use the C library to be disallowed from dynamically allocating memory
+ * without talking to the C library, but that sounds like a sane way to go
+ * about it. Note that there is no error checking anywhere in this file, users
+ * will simply get the relevant error when actually trying to use the memory
+ * that's been allocated. */
+extern char metal_segment_heap_target_start;
+extern char metal_segment_heap_target_end;
+static char *brk = &metal_segment_heap_target_start;
+
+int
+_brk(void *addr)
+{
+ brk = addr;
+ return 0;
+}
+
+char *
+_sbrk(ptrdiff_t incr)
+{
+ char *old = brk;
+
+ /* If __heap_size == 0, we can't allocate memory on the heap */
+ if(&metal_segment_heap_target_start == &metal_segment_heap_target_end) {
+ return (void *)-1;
+ }
+
+ /* Don't move the break past the end of the heap */
+ if ((brk + incr) < &metal_segment_heap_target_end) {
+ brk += incr;
+ } else {
+ brk = &metal_segment_heap_target_end;
+ return (void *)-1;
+ }
+
+ return old;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_stat.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_stat.c
new file mode 100644
index 000000000..3c2e41910
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_stat.c
@@ -0,0 +1,9 @@
+#include <errno.h>
+#include <sys/stat.h>
+
+int
+_stat(const char *file, struct stat *st)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_sysconf.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_sysconf.c
new file mode 100644
index 000000000..452a252ae
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_sysconf.c
@@ -0,0 +1,16 @@
+#include <unistd.h>
+#include <time.h>
+
+/* Get configurable system variables. */
+
+long
+_sysconf(int name)
+{
+ switch (name)
+ {
+ case _SC_CLK_TCK:
+ return CLOCKS_PER_SEC;
+ }
+
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_times.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_times.c
new file mode 100644
index 000000000..6beedcb30
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_times.c
@@ -0,0 +1,42 @@
+#include <sys/times.h>
+#include <sys/time.h>
+#include <metal/timer.h>
+#include <errno.h>
+
+extern int _gettimeofday(struct timeval *, void *);
+
+/* Timing information for current process. From
+ newlib/libc/include/sys/times.h the tms struct fields are as follows:
+
+ - clock_t tms_utime : user clock ticks
+ - clock_t tms_stime : system clock ticks
+ - clock_t tms_cutime : children's user clock ticks
+ - clock_t tms_cstime : children's system clock ticks
+
+ Since maven does not currently support processes we set both of the
+ children's times to zero. Eventually we might want to separately
+ account for user vs system time, but for now we just return the total
+ number of cycles since starting the program. */
+clock_t
+_times(struct tms *buf)
+{
+ int rv;
+ // when called for the first time, initialize t0
+ static struct timeval t0;
+ if (t0.tv_sec == 0 && t0.tv_usec == 0)
+ _gettimeofday (&t0, 0);
+
+ struct timeval t;
+ _gettimeofday (&t, 0);
+
+ unsigned long long timebase;
+ rv = metal_timer_get_timebase_frequency(0, &timebase);
+ if (rv != 0) {
+ return -1;
+ }
+
+ long long utime = (t.tv_sec - t0.tv_sec) * 1000000 + (t.tv_usec - t0.tv_usec);
+ buf->tms_utime = utime * timebase / 1000000;
+ buf->tms_stime = buf->tms_cstime = buf->tms_cutime = 0;
+ return 0;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_unlink.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_unlink.c
new file mode 100644
index 000000000..b369d2017
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_unlink.c
@@ -0,0 +1,8 @@
+#include <errno.h>
+
+int
+_unlink(const char *name)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_utime.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_utime.c
new file mode 100644
index 000000000..33d557aa7
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_utime.c
@@ -0,0 +1,9 @@
+#include <errno.h>
+struct utimbuf;
+
+int
+_utime(const char *path, const struct utimbuf *times)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_wait.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_wait.c
new file mode 100644
index 000000000..9d459f14c
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_wait.c
@@ -0,0 +1,7 @@
+#include <errno.h>
+
+int _wait(int *status)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_write.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_write.c
new file mode 100644
index 000000000..bfcf0cb2b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/gloss/sys_write.c
@@ -0,0 +1,19 @@
+#include <metal/tty.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+
+/* Write to a file. */
+ssize_t
+_write(int file, const void *ptr, size_t len)
+{
+ if (file != STDOUT_FILENO) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ const char *bptr = ptr;
+ for (size_t i = 0; i < len; ++i)
+ metal_tty_putc(bptr[i]);
+ return 0;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/button.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/button.h
new file mode 100644
index 000000000..3ae1c143e
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/button.h
@@ -0,0 +1,59 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__BUTTON_H
+#define METAL__BUTTON_H
+
+/*!
+ * @file button.h
+ * API for interfacing with physical buttons
+ */
+
+#include <metal/interrupt.h>
+
+struct metal_button;
+
+struct metal_button_vtable {
+ int (*button_exist)(struct metal_button *button, char *label);
+ struct metal_interrupt* (*interrupt_controller)(struct metal_button *button);
+ int (*get_interrupt_id)(struct metal_button *button);
+};
+
+/*!
+ * @brief A button device handle
+ *
+ * A `struct metal_button` is an implementation-defined object which represents
+ * a button on a development board.
+ */
+struct metal_button {
+ const struct metal_button_vtable *vtable;
+};
+
+/*!
+ * @brief Get a reference to a button
+ *
+ * @param label The DeviceTree label for the button
+ * @return A handle for the button
+ */
+struct metal_button* metal_button_get(char *label);
+
+
+/*!
+ * @brief Get the interrupt controller for a button
+ *
+ * @param button The handle for the button
+ * @return A pointer to the interrupt controller responsible for handling
+ * button interrupts.
+ */
+__inline__ struct metal_interrupt*
+ metal_button_interrupt_controller(struct metal_button *button) { return button->vtable->interrupt_controller(button); }
+
+/*!
+ * @brief Get the interrupt id for a button
+ *
+ * @param button The handle for the button
+ * @return The interrupt id corresponding to a button.
+ */
+__inline__ int metal_button_get_interrupt_id(struct metal_button *button) { return button->vtable->get_interrupt_id(button); }
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/cache.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/cache.h
new file mode 100644
index 000000000..bad026480
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/cache.h
@@ -0,0 +1,96 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__CACHE_H
+#define METAL__CACHE_H
+
+/*!
+ * @file cache.h
+ *
+ * @brief API for configuring caches
+ */
+#include <stdint.h>
+
+struct metal_cache;
+
+struct __metal_cache_vtable {
+ void (*init)(struct metal_cache *cache, int ways);
+ int (*get_enabled_ways)(struct metal_cache *cache);
+ int (*set_enabled_ways)(struct metal_cache *cache, int ways);
+};
+
+/*!
+ * @brief a handle for a cache
+ */
+struct metal_cache {
+ const struct __metal_cache_vtable *vtable;
+};
+
+/*!
+ * @brief Initialize a cache
+ * @param cache The handle for the cache to initialize
+ * @param ways The number of ways to enable
+ *
+ * Initializes a cache with the requested number of ways enabled.
+ */
+__inline__ void metal_cache_init(struct metal_cache *cache, int ways) {
+ cache->vtable->init(cache, ways);
+}
+
+/*!
+ * @brief Get the current number of enabled cache ways
+ * @param cache The handle for the cache
+ * @return The current number of enabled cache ways
+ */
+__inline__ int metal_cache_get_enabled_ways(struct metal_cache *cache) {
+ return cache->vtable->get_enabled_ways(cache);
+}
+
+/*!
+ * @brief Enable the requested number of cache ways
+ * @param cache The handle for the cache
+ * @param ways The number of ways to enabled
+ * @return 0 if the ways are successfully enabled
+ */
+__inline__ int metal_cache_set_enabled_ways(struct metal_cache *cache, int ways) {
+ return cache->vtable->set_enabled_ways(cache, ways);
+}
+
+/*!
+ * @brief Check if dcache is supported on the core
+ * @param hartid The core to check
+ * @return 1 if dcache is present
+ */
+int metal_dcache_l1_available(int hartid);
+
+/*!
+ * @brief Flush dcache for L1 on the requested core with write back
+ * @param hartid The core to flush
+ * @param address The virtual address of cacheline to invalidate
+ * @return None
+ */
+void metal_dcache_l1_flush(int hartid, uintptr_t address);
+
+/*!
+ * @brief Discard dcache for L1 on the requested core with no write back
+ * @param hartid The core to discard
+ * @param address The virtual address of cacheline to invalidate
+ * @return None
+ */
+void metal_dcache_l1_discard(int hartid, uintptr_t address);
+
+/*!
+ * @brief Check if icache is supported on the core
+ * @param hartid The core to check
+ * @return 1 if icache is present
+ */
+int metal_icache_l1_available(int hartid);
+
+/*!
+ * @brief Flush icache for L1 on the requested core
+ * @param hartid The core to flush
+ * @return None
+ */
+void metal_icache_l1_flush(int hartid);
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/clock.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/clock.h
new file mode 100644
index 000000000..622fc9470
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/clock.h
@@ -0,0 +1,154 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__CLOCK_H
+#define METAL__CLOCK_H
+
+/*!
+ * @file clock.h
+ * @brief API for manipulating clock sources
+ *
+ * The clock interface allows for controlling the rate of various clocks in the system.
+ */
+
+struct metal_clock;
+
+#include <stddef.h>
+
+/* The generic interface to all clocks. */
+struct __metal_clock_vtable {
+ long (*get_rate_hz)(const struct metal_clock *clk);
+ long (*set_rate_hz)(struct metal_clock *clk, long hz);
+};
+
+/*!
+ * @brief Function signature of clock rate change callbacks
+ */
+typedef void (*metal_clock_rate_change_callback)(void *priv);
+
+struct _metal_clock_callback_t;
+struct _metal_clock_callback_t {
+ /* The callback function */
+ metal_clock_rate_change_callback callback;
+
+ /* Private data for the callback function */
+ void *priv;
+
+ struct _metal_clock_callback_t *_next;
+};
+
+/*!
+ * @brief Type for the linked list of callbacks for clock rate changes
+ */
+typedef struct _metal_clock_callback_t metal_clock_callback;
+
+/*!
+ * @brief Call all callbacks in the linked list, if any are registered
+ */
+__inline__ void _metal_clock_call_all_callbacks(const metal_clock_callback *const list) {
+ const metal_clock_callback *current = list;
+ while (current) {
+ current->callback(current->priv);
+ current = current->_next;
+ }
+}
+
+/*!
+ * @brief Append a callback to the linked list and return the head of the list
+ */
+__inline__ metal_clock_callback *_metal_clock_append_to_callbacks(metal_clock_callback *list, metal_clock_callback *const cb) {
+ cb->_next = NULL;
+
+ if (!list) {
+ return cb;
+ }
+
+ metal_clock_callback *current = list;
+
+ while ((current->_next) != NULL) {
+ current = current->_next;
+ }
+
+ current->_next = cb;
+
+ return list;
+}
+
+/*!
+ * @struct metal_clock
+ * @brief The handle for a clock
+ *
+ * Clocks are defined as a pointer to a `struct metal_clock`, the contents of which
+ * are implementation defined. Users of the clock interface must call functions
+ * which accept a `struct metal_clock *` as an argument to interract with the clock.
+ *
+ * Note that no mechanism for obtaining a pointer to a `struct metal_clock` has been
+ * defined, making it impossible to call any of these functions without invoking
+ * implementation-defined behavior.
+ */
+struct metal_clock {
+ const struct __metal_clock_vtable *vtable;
+
+ /* Pre-rate change callback linked list */
+ metal_clock_callback *_pre_rate_change_callback;
+
+ /* Post-rate change callback linked list */
+ metal_clock_callback *_post_rate_change_callback;
+};
+
+/*!
+ * @brief Returns the current rate of the given clock
+ *
+ * @param clk The handle for the clock
+ * @return The current rate of the clock in Hz
+ */
+__inline__ long metal_clock_get_rate_hz(const struct metal_clock *clk) { return clk->vtable->get_rate_hz(clk); }
+
+/*!
+ * @brief Set the current rate of a clock
+ *
+ * @param clk The handle for the clock
+ * @param hz The desired rate in Hz
+ * @return The new rate of the clock in Hz.
+ *
+ * Attempts to set the current rate of the given clock to as close as possible
+ * to the given rate in Hz. Returns the actual value that's been selected, which
+ * could be anything!
+ *
+ * Prior to and after the rate change of the clock, this will call the registered
+ * pre- and post-rate change callbacks.
+ */
+__inline__ long metal_clock_set_rate_hz(struct metal_clock *clk, long hz)
+{
+ _metal_clock_call_all_callbacks(clk->_pre_rate_change_callback);
+
+ long out = clk->vtable->set_rate_hz(clk, hz);
+
+ _metal_clock_call_all_callbacks(clk->_post_rate_change_callback);
+
+ return out;
+}
+
+/*!
+ * @brief Register a callback that must be called before a rate change
+ *
+ * @param clk The handle for the clock
+ * @param cb The callback to be registered
+ */
+__inline__ void metal_clock_register_pre_rate_change_callback(struct metal_clock *clk, metal_clock_callback *cb)
+{
+ clk->_pre_rate_change_callback = _metal_clock_append_to_callbacks(clk->_pre_rate_change_callback, cb);
+}
+
+/*!
+ * @brief Registers a callback that must be called after a rate change
+ *
+ * @param clk The handle for the clock
+ * @param cb The callback to be registered
+ */
+__inline__ void metal_clock_register_post_rate_change_callback(struct metal_clock *clk, metal_clock_callback *cb)
+{
+ clk->_post_rate_change_callback = _metal_clock_append_to_callbacks(clk->_post_rate_change_callback, cb);
+}
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/compiler.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/compiler.h
new file mode 100644
index 000000000..62c0ea975
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/compiler.h
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__COMPILER_H
+#define METAL__COMPILER_H
+
+#define __METAL_DECLARE_VTABLE(type) \
+ extern const struct type type;
+
+#define __METAL_DEFINE_VTABLE(type) \
+ const struct type type
+
+#define __METAL_GET_FIELD(reg, mask) \
+ (((reg) & (mask)) / ((mask) & ~((mask) << 1)))
+
+/* Set field with mask for a given value */
+#define __METAL_SET_FIELD(reg, mask, val) \
+ (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask)))
+
+void _metal_trap(int ecode);
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/cpu.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/cpu.h
new file mode 100644
index 000000000..dbd3dbfb5
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/cpu.h
@@ -0,0 +1,271 @@
+/* Copyright 2018 SiFive, Inc */
+
+/* SPDX-License-Identifier: Apache-2.0 */
+
+/*! @file cpu.h
+ * @brief API for accessing CPU capabilities.
+ */
+
+#ifndef METAL__CPU_H
+#define METAL__CPU_H
+
+#include <stdint.h>
+#include <metal/interrupt.h>
+
+struct metal_cpu;
+
+/*!
+ * @brief Function signature for exception handlers
+ */
+typedef void (*metal_exception_handler_t) (struct metal_cpu *cpu, int ecode);
+
+struct metal_cpu_vtable {
+ unsigned long long (*mcycle_get)(struct metal_cpu *cpu);
+ unsigned long long (*timebase_get)(struct metal_cpu *cpu);
+ unsigned long long (*mtime_get)(struct metal_cpu *cpu);
+ int (*mtimecmp_set)(struct metal_cpu *cpu, unsigned long long time);
+ struct metal_interrupt* (*tmr_controller_interrupt)(struct metal_cpu *cpu);
+ int (*get_tmr_interrupt_id)(struct metal_cpu *cpu);
+ struct metal_interrupt* (*sw_controller_interrupt)(struct metal_cpu *cpu);
+ int (*get_sw_interrupt_id)(struct metal_cpu *cpu);
+ int (*set_sw_ipi)(struct metal_cpu *cpu, int hartid);
+ int (*clear_sw_ipi)(struct metal_cpu *cpu, int hartid);
+ int (*get_msip)(struct metal_cpu *cpu, int hartid);
+ struct metal_interrupt* (*controller_interrupt)(struct metal_cpu *cpu);
+ int (*exception_register)(struct metal_cpu *cpu, int ecode, metal_exception_handler_t handler);
+ int (*get_ilen)(struct metal_cpu *cpu, uintptr_t epc);
+ uintptr_t (*get_epc)(struct metal_cpu *cpu);
+ int (*set_epc)(struct metal_cpu *cpu, uintptr_t epc);
+};
+
+/*! @brief A device handle for a CPU hart
+ */
+struct metal_cpu {
+ const struct metal_cpu_vtable *vtable;
+};
+
+/*! @brief Get a reference to a CPU hart
+ *
+ * @param hartid The ID of the desired CPU hart
+ * @return A pointer to the CPU device handle
+ */
+struct metal_cpu* metal_cpu_get(unsigned int hartid);
+
+/*! @brief Get the hartid of the CPU hart executing this function
+ *
+ * @return The hartid of the current CPU hart */
+int metal_cpu_get_current_hartid(void);
+
+/*! @brief Get the number of CPU harts
+ *
+ * @return The number of CPU harts */
+int metal_cpu_get_num_harts(void);
+
+/*! @brief Get the CPU cycle count timer value
+ *
+ * Get the value of the cycle count timer for a given CPU
+ *
+ * @param cpu The CPU device handle
+ * @return The value of the CPU cycle count timer
+ */
+__inline__ unsigned long long metal_cpu_get_timer(struct metal_cpu *cpu)
+{ return cpu->vtable->mcycle_get(cpu); }
+
+/*! @brief Get the timebase of the CPU
+ *
+ * Get the value of the timebase of the cycle count timer
+ *
+ * @param cpu The CPU device handle
+ * @return The value of the cycle count timer timebase
+ */
+__inline__ unsigned long long metal_cpu_get_timebase(struct metal_cpu *cpu)
+{ return cpu->vtable->timebase_get(cpu); }
+
+/*! @brief Get the value of the mtime RTC
+ *
+ * Get the value of the mtime real-time clock. The CPU interrupt controller
+ * must be initialized before this function is called or the return value
+ * will be 0.
+ *
+ * @param cpu The CPU device handle
+ * @return The value of mtime, or 0 if failure
+ */
+__inline__ unsigned long long metal_cpu_get_mtime(struct metal_cpu *cpu)
+{ return cpu->vtable->mtime_get(cpu); }
+
+/*! @brief Set the value of the RTC mtimecmp RTC
+ *
+ * Set the value of the mtime real-time clock compare register. The CPU
+ * interrupt controller must be initialized before this function is called
+ * or the return value will be -1;
+ *
+ * @param cpu The CPU device handle
+ * @param time The value to set the compare register to
+ * @return The value of mtimecmp or -1 if error
+ */
+__inline__ int metal_cpu_set_mtimecmp(struct metal_cpu *cpu, unsigned long long time)
+{ return cpu->vtable->mtimecmp_set(cpu, time); }
+
+/*! @brief Get a reference to RTC timer interrupt controller
+ *
+ * Get a reference to the interrupt controller for the real-time clock interrupt.
+ * The controller returned by this function must be initialized before any interrupts
+ * are registered or enabled with it.
+ *
+ * @param cpu The CPU device handle
+ * @return A pointer to the timer interrupt handle
+ */
+__inline__ struct metal_interrupt* metal_cpu_timer_interrupt_controller(struct metal_cpu *cpu)
+{ return cpu->vtable->tmr_controller_interrupt(cpu); }
+
+/*! @brief Get the RTC timer interrupt id
+ *
+ * Get the interrupt ID of the real-time clock interrupt
+ *
+ * @param cpu The CPU device handle
+ * @return The timer interrupt ID
+ */
+__inline__ int metal_cpu_timer_get_interrupt_id(struct metal_cpu *cpu)
+{ return cpu->vtable->get_tmr_interrupt_id(cpu); }
+
+/*! @brief Get a reference to the software interrupt controller
+ *
+ * Get a reference to the interrupt controller for the software/inter-process
+ * interrupt. The controller returned by this function must be initialized before
+ * any interrupts are registered or enabled with it.
+ *
+ * @param cpu The CPU device handle
+ * @return A pointer to the software interrupt handle
+ */
+__inline__ struct metal_interrupt* metal_cpu_software_interrupt_controller(struct metal_cpu *cpu)
+{ return cpu->vtable->sw_controller_interrupt(cpu); }
+
+/*! @brief Get the software interrupt id
+ *
+ * Get the interrupt ID for the software/inter-process interrupt
+ *
+ * @param cpu The CPU device handle
+ * @return the software interrupt ID
+ */
+__inline__ int metal_cpu_software_get_interrupt_id(struct metal_cpu *cpu)
+{ return cpu->vtable->get_sw_interrupt_id(cpu); }
+
+/*!
+ * @brief Set the inter-process interrupt for a hart
+ *
+ * Trigger a software/inter-process interrupt for a hart. The CPU interrupt
+ * controller for the CPU handle passed to this function must be initialized
+ * before this function is called.
+ *
+ * @param cpu The CPU device handle
+ * @param hartid The CPU hart ID to be interrupted
+ * @return 0 upon success
+ */
+__inline__ int metal_cpu_software_set_ipi(struct metal_cpu *cpu, int hartid)
+{ return cpu->vtable->set_sw_ipi(cpu, hartid); }
+
+/*!
+ * @brief Clear the inter-process interrupt for a hart
+ *
+ * Clear the software/inter-process interrupt for a hart. The CPU interrupt
+ * controller for the CPU handle passed to this function must be initialized
+ * before this function is called.
+ *
+ * @param cpu The CPU device handle
+ * @param hartid The CPU hart ID to clear
+ * @return 0 upon success
+ */
+__inline__ int metal_cpu_software_clear_ipi(struct metal_cpu *cpu, int hartid)
+{ return cpu->vtable->clear_sw_ipi(cpu, hartid); }
+
+/*!
+ * @brief Get the value of MSIP for the given hart
+ *
+ * Get the value of the machine software interrupt pending bit for
+ * the given hart. The CPU interrupt controller for the CPU handle passed
+ * as argument to this function must be initialized before this function
+ * is called.
+ *
+ * @param cpu the CPU device handle
+ * @param hartid The CPU hart to read
+ * @return 0 upon success
+ */
+__inline__ int metal_cpu_get_msip(struct metal_cpu *cpu, int hartid)
+{ return cpu->vtable->get_msip(cpu, hartid); }
+
+/*!
+ * @brief Get the interrupt controller for the CPU
+ *
+ * Get the CPU interrupt controller. The controller returned by this
+ * function must be initialized before any interrupts are registered
+ * or enabled and before any exception handlers are registered with
+ * this CPU.
+ *
+ * @param cpu The CPU device handle
+ * @return The handle for the CPU interrupt controller
+ */
+__inline__ struct metal_interrupt* metal_cpu_interrupt_controller(struct metal_cpu *cpu)
+{ return cpu->vtable->controller_interrupt(cpu); }
+
+/*!
+ * @brief Register an exception handler
+ *
+ * Register an exception handler for the CPU. The CPU interrupt controller must be initialized
+ * before this function is called.
+ *
+ * @param cpu The CPU device handle
+ * @param ecode The exception code to register a handler for
+ * @param handler Callback function for the exception handler
+ * @return 0 upon success
+ */
+__inline__ int metal_cpu_exception_register(struct metal_cpu *cpu, int ecode, metal_exception_handler_t handler)
+{ return cpu->vtable->exception_register(cpu, ecode, handler); }
+
+/*!
+ * @brief Get the length of an instruction in bytes
+ *
+ * Get the length of an instruction in bytes.
+ *
+ * On RISC-V platforms, this is useful for detecting whether an instruction is
+ * compressed (2 bytes long) or uncompressed (4 bytes long).
+ *
+ * This function is useful in conjuction with `metal_cpu_get_exception_pc()`
+ * and `metal_cpu_set_exception_pc()` in order to cause the exception handler to
+ * return execution after the faulting instruction.
+ *
+ * @param cpu The CPU device handle
+ * @param epc The address of the instruction to measure
+ * @return the length of the instruction in bytes
+ */
+__inline__ int metal_cpu_get_instruction_length(struct metal_cpu *cpu, uintptr_t epc)
+{ return cpu->vtable->get_ilen(cpu, epc); }
+
+/*!
+ * @brief Get the program counter of the current exception.
+ *
+ * This function must be called within an exception handler. The behavior is
+ * undefined outside of an exception handler.
+ *
+ * @param cpu The CPU device handle
+ * @return The value of the program counter at the time of the exception
+ */
+__inline__ uintptr_t metal_cpu_get_exception_pc(struct metal_cpu *cpu)
+{ return cpu->vtable->get_epc(cpu); }
+
+/*!
+ * @brief Set the exception program counter
+ *
+ * This function must be called within an exception handler. The behavior
+ * is undefined outside of an exception handler.
+ *
+ * This function can be used to cause an exception handler to return execution
+ * to an address other than the one that caused the exception.
+ *
+ * @param cpu the CPU device handle
+ * @param epc The address to set the exception program counter to
+ * @return 0 upon success
+ */
+__inline__ int metal_cpu_set_exception_pc(struct metal_cpu *cpu, uintptr_t epc)
+{ return cpu->vtable->set_epc(cpu, epc); }
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/fixed-clock.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/fixed-clock.h
new file mode 100644
index 000000000..2647c5981
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/fixed-clock.h
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__FIXED_CLOCK_H
+#define METAL__DRIVERS__FIXED_CLOCK_H
+
+struct __metal_driver_fixed_clock;
+
+#include <metal/compiler.h>
+#include <metal/clock.h>
+
+struct __metal_driver_vtable_fixed_clock {
+ struct __metal_clock_vtable clock;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_fixed_clock)
+
+struct __metal_driver_fixed_clock {
+ struct metal_clock clock;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/fixed-factor-clock.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/fixed-factor-clock.h
new file mode 100644
index 000000000..936ce8d77
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/fixed-factor-clock.h
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__FIXED_FACTOR_CLOCK_H
+#define METAL__DRIVERS__FIXED_FACTOR_CLOCK_H
+
+struct __metal_driver_fixed_factor_clock;
+
+#include <metal/compiler.h>
+#include <metal/clock.h>
+
+struct __metal_driver_vtable_fixed_factor_clock {
+ struct __metal_clock_vtable clock;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_fixed_factor_clock)
+
+struct __metal_driver_fixed_factor_clock {
+ struct metal_clock clock;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_clint0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_clint0.h
new file mode 100644
index 000000000..08d571e1c
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_clint0.h
@@ -0,0 +1,24 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__RISCV_CLINT0_H
+#define METAL__DRIVERS__RISCV_CLINT0_H
+
+#include <metal/compiler.h>
+#include <metal/drivers/riscv_cpu.h>
+
+struct __metal_driver_vtable_riscv_clint0 {
+ struct metal_interrupt_vtable clint_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_riscv_clint0)
+
+#define __METAL_MACHINE_MACROS
+#include <metal/machine.h>
+struct __metal_driver_riscv_clint0 {
+ struct metal_interrupt controller;
+ int init_done;
+};
+#undef __METAL_MACHINE_MACROS
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_cpu.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_cpu.h
new file mode 100644
index 000000000..ca91e0a95
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_cpu.h
@@ -0,0 +1,192 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__RISCV_CPU_H
+#define METAL__DRIVERS__RISCV_CPU_H
+
+#include <stdint.h>
+#include <metal/cpu.h>
+#include <metal/compiler.h>
+
+#define METAL_MAX_CORES 8
+#define METAL_MAX_MI 32 /* Per ISA MCause interrupts 32+ are Reserved */
+#define METAL_MAX_ME 12 /* Per ISA Exception codes 12+ are Reserved */
+#define METAL_DEFAULT_RTC_FREQ 32768
+
+#define METAL_DISABLE 0
+#define METAL_ENABLE 1
+
+#define METAL_ISA_A_EXTENSIONS 0x0001
+#define METAL_ISA_C_EXTENSIONS 0x0004
+#define METAL_ISA_D_EXTENSIONS 0x0008
+#define METAL_ISA_E_EXTENSIONS 0x0010
+#define METAL_ISA_F_EXTENSIONS 0x0020
+#define METAL_ISA_G_EXTENSIONS 0x0040
+#define METAL_ISA_I_EXTENSIONS 0x0100
+#define METAL_ISA_M_EXTENSIONS 0x1000
+#define METAL_ISA_N_EXTENSIONS 0x2000
+#define METAL_ISA_Q_EXTENSIONS 0x10000
+#define METAL_ISA_S_EXTENSIONS 0x40000
+#define METAL_ISA_U_EXTENSIONS 0x100000
+#define METAL_ISA_V_EXTENSIONS 0x200000
+#define METAL_ISA_XL32_EXTENSIONS 0x40000000UL
+#define METAL_ISA_XL64_EXTENSIONS 0x8000000000000000UL
+#define METAL_ISA_XL128_EXTENSIONS 0xC000000000000000UL
+
+#define METAL_MTVEC_DIRECT 0x00
+#define METAL_MTVEC_VECTORED 0x01
+#define METAL_MTVEC_CLIC 0x02
+#define METAL_MTVEC_CLIC_VECTORED 0x03
+#define METAL_MTVEC_CLIC_RESERVED 0x3C
+#define METAL_MTVEC_MASK 0x3F
+#if __riscv_xlen == 32
+#define METAL_MCAUSE_INTR 0x80000000UL
+#define METAL_MCAUSE_CAUSE 0x000003FFUL
+#else
+#define METAL_MCAUSE_INTR 0x8000000000000000UL
+#define METAL_MCAUSE_CAUSE 0x00000000000003FFUL
+#endif
+#define METAL_MCAUSE_MINHV 0x40000000UL
+#define METAL_MCAUSE_MPP 0x30000000UL
+#define METAL_MCAUSE_MPIE 0x08000000UL
+#define METAL_MCAUSE_MPIL 0x00FF0000UL
+#define METAL_MSTATUS_MIE 0x00000008UL
+#define METAL_MSTATUS_MPIE 0x00000080UL
+#define METAL_MSTATUS_MPP 0x00001800UL
+#define METAL_MSTATUS_FS_INIT 0x00002000UL
+#define METAL_MSTATUS_FS_CLEAN 0x00004000UL
+#define METAL_MSTATUS_FS_DIRTY 0x00006000UL
+#define METAL_MSTATUS_MPRV 0x00020000UL
+#define METAL_MSTATUS_MXR 0x00080000UL
+#define METAL_MINTSTATUS_MIL 0xFF000000UL
+#define METAL_MINTSTATUS_SIL 0x0000FF00UL
+#define METAL_MINTSTATUS_UIL 0x000000FFUL
+
+#define METAL_LOCAL_INTR(X) (16 + X)
+#define METAL_MCAUSE_EVAL(cause) (cause & METAL_MCAUSE_INTR)
+#define METAL_INTERRUPT(cause) (METAL_MCAUSE_EVAL(cause) ? 1 : 0)
+#define METAL_EXCEPTION(cause) (METAL_MCAUSE_EVAL(cause) ? 0 : 1)
+#define METAL_SW_INTR_EXCEPTION (METAL_MCAUSE_INTR + 3)
+#define METAL_TMR_INTR_EXCEPTION (METAL_MCAUSE_INTR + 7)
+#define METAL_EXT_INTR_EXCEPTION (METAL_MCAUSE_INTR + 11)
+#define METAL_LOCAL_INTR_EXCEPTION(X) (METAL_MCAUSE_INTR + METAL_LOCAL_INTR(X))
+#define METAL_LOCAL_INTR_RESERVE0 1
+#define METAL_LOCAL_INTR_RESERVE1 2
+#define METAL_LOCAL_INTR_RESERVE2 4
+#define METAL_LOCAL_INTERRUPT_SW 8 /* Bit3 0x008 */
+#define METAL_LOCAL_INTR_RESERVE4 16
+#define METAL_LOCAL_INTR_RESERVE5 32
+#define METAL_LOCAL_INTR_RESERVE6 64
+#define METAL_LOCAL_INTERRUPT_TMR 128 /* Bit7 0x080 */
+#define METAL_LOCAL_INTR_RESERVE8 256
+#define METAL_LOCAL_INTR_RESERVE9 512
+#define METAL_LOCAL_INTR_RESERVE10 1024
+#define METAL_LOCAL_INTERRUPT_EXT 2048 /* Bit11 0x800 */
+/* Bit12 to Bit15 are Reserved */
+#define METAL_LOCAL_INTERRUPT(X) (0x10000 << X) /* Bit16+ Start of Custom Local Interrupt */
+#define METAL_MIE_INTERRUPT METAL_MSTATUS_MIE
+
+#define METAL_INSN_LENGTH_MASK 3
+#define METAL_INSN_NOT_COMPRESSED 3
+
+typedef enum {
+ METAL_MACHINE_PRIVILEGE_MODE,
+ METAL_SUPERVISOR_PRIVILEGE_MODE,
+ METAL_USER_PRIVILEGE_MODE,
+} metal_privilege_mode_e;
+
+typedef enum {
+ METAL_INTERRUPT_ID_BASE,
+ METAL_INTERRUPT_ID_SW = (METAL_INTERRUPT_ID_BASE + 3),
+ METAL_INTERRUPT_ID_TMR = (METAL_INTERRUPT_ID_BASE + 7),
+ METAL_INTERRUPT_ID_EXT = (METAL_INTERRUPT_ID_BASE + 11),
+ METAL_INTERRUPT_ID_CSW = (METAL_INTERRUPT_ID_BASE + 12),
+ METAL_INTERRUPT_ID_LC0 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(0)),
+ METAL_INTERRUPT_ID_LC1 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(1)),
+ METAL_INTERRUPT_ID_LC2 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(2)),
+ METAL_INTERRUPT_ID_LC3 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(3)),
+ METAL_INTERRUPT_ID_LC4 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(4)),
+ METAL_INTERRUPT_ID_LC5 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(5)),
+ METAL_INTERRUPT_ID_LC6 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(6)),
+ METAL_INTERRUPT_ID_LC7 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(7)),
+ METAL_INTERRUPT_ID_LC8 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(8)),
+ METAL_INTERRUPT_ID_LC9 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(9)),
+ METAL_INTERRUPT_ID_LC10 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(10)),
+ METAL_INTERRUPT_ID_LC11 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(11)),
+ METAL_INTERRUPT_ID_LC12 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(12)),
+ METAL_INTERRUPT_ID_LC13 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(13)),
+ METAL_INTERRUPT_ID_LC14 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(14)),
+ METAL_INTERRUPT_ID_LC15 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(15)),
+ METAL_INTERRUPT_ID_LCMX,
+ METAL_INTERRUPT_ID_GL0 = METAL_INTERRUPT_ID_LCMX,
+ METAL_INTERRUPT_ID_GLMX = (METAL_MCAUSE_CAUSE + 1),
+} metal_interrupt_id_e;
+
+typedef enum {
+ METAL_IAM_EXCEPTION_CODE, /* Instruction address misaligned */
+ METAL_IAF_EXCEPTION_CODE, /* Instruction access faultd */
+ METAL_II_EXCEPTION_CODE, /* Illegal instruction */
+ METAL_BREAK_EXCEPTION_CODE, /* Breakpoint */
+ METAL_LAM_EXCEPTION_CODE, /* Load address misaligned */
+ METAL_LAF_EXCEPTION_CODE, /* Load access fault */
+ METAL_SAMOAM_EXCEPTION_CODE, /* Store/AMO address misaligned */
+ METAL_SAMOAF_EXCEPTION_CODE, /* Store/AMO access fault */
+ METAL_ECALL_U_EXCEPTION_CODE, /* Environment call from U-mode */
+ METAL_R9_EXCEPTION_CODE, /* Reserved */
+ METAL_R10_EXCEPTION_CODE, /* Reserved */
+ METAL_ECALL_M_EXCEPTION_CODE, /* Environment call from M-mode */
+ METAL_MAX_EXCEPTION_CODE,
+} metal_exception_code_e;
+
+typedef enum {
+ METAL_TIMER_MTIME_GET = 1,
+ METAL_SOFTWARE_IPI_CLEAR,
+ METAL_SOFTWARE_IPI_SET,
+ METAL_SOFTWARE_MSIP_GET,
+ METAL_MAX_INTERRUPT_GET,
+ METAL_INDEX_INTERRUPT_GET,
+} metal_interrup_cmd_e;
+
+typedef struct __metal_interrupt_data {
+ long long pad : 64;
+ metal_interrupt_handler_t handler;
+ void *sub_int;
+ void *exint_data;
+} __metal_interrupt_data;
+
+/* CPU interrupt controller */
+
+uintptr_t __metal_myhart_id(void);
+
+struct __metal_driver_vtable_riscv_cpu_intc {
+ struct metal_interrupt_vtable controller_vtable;
+};
+
+
+void __metal_interrupt_global_enable(void);
+void __metal_interrupt_global_disable(void);
+metal_vector_mode __metal_controller_interrupt_vector_mode(void);
+void __metal_controller_interrupt_vector(metal_vector_mode mode, void *vec_table);
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_riscv_cpu_intc)
+
+struct __metal_driver_riscv_cpu_intc {
+ struct metal_interrupt controller;
+ int init_done;
+ uintptr_t metal_mtvec_table[METAL_MAX_MI];
+ __metal_interrupt_data metal_int_table[METAL_MAX_MI];
+ metal_exception_handler_t metal_exception_table[METAL_MAX_ME];
+};
+
+/* CPU driver*/
+struct __metal_driver_vtable_cpu {
+ struct metal_cpu_vtable cpu_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_cpu)
+
+struct __metal_driver_cpu {
+ struct metal_cpu cpu;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_plic0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_plic0.h
new file mode 100644
index 000000000..159ee6d69
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_plic0.h
@@ -0,0 +1,31 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__RISCV_PLIC0_H
+#define METAL__DRIVERS__RISCV_PLIC0_H
+
+#include <metal/compiler.h>
+#include <metal/drivers/riscv_cpu.h>
+
+#define METAL_PLIC_SOURCE_MASK 0x1F
+#define METAL_PLIC_SOURCE_SHIFT 5
+#define METAL_PLIC_SOURCE_PRIORITY_SHIFT 2
+#define METAL_PLIC_SOURCE_PENDING_SHIFT 0
+
+struct __metal_driver_vtable_riscv_plic0 {
+ struct metal_interrupt_vtable plic_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_riscv_plic0)
+
+#define __METAL_MACHINE_MACROS
+#include <metal/machine.h>
+struct __metal_driver_riscv_plic0 {
+ struct metal_interrupt controller;
+ int init_done;
+ metal_interrupt_handler_t metal_exint_table[__METAL_PLIC_SUBINTERRUPTS];
+ __metal_interrupt_data metal_exdata_table[__METAL_PLIC_SUBINTERRUPTS];
+};
+#undef __METAL_MACHINE_MACROS
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_ccache0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_ccache0.h
new file mode 100644
index 000000000..2153cf384
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_ccache0.h
@@ -0,0 +1,23 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_CCACHE0_H
+#define METAL__DRIVERS__SIFIVE_CCACHE0_H
+
+#include <metal/cache.h>
+#include <metal/compiler.h>
+
+struct __metal_driver_vtable_sifive_ccache0 {
+ struct __metal_cache_vtable cache;
+};
+
+struct __metal_driver_sifive_ccache0;
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_ccache0)
+
+struct __metal_driver_sifive_ccache0 {
+ struct metal_cache cache;
+};
+
+#endif
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_clic0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_clic0.h
new file mode 100644
index 000000000..7fef38d19
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_clic0.h
@@ -0,0 +1,43 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_CLIC0_H
+#define METAL__DRIVERS__SIFIVE_CLIC0_H
+
+#include <metal/compiler.h>
+#include <metal/drivers/riscv_cpu.h>
+
+#define METAL_CLIC_MAX_NMBITS 2
+#define METAL_CLIC_MAX_NLBITS 8
+#define METAL_CLIC_MAX_NVBITS 1
+
+#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_MMODE 0x00
+#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_SMODE1 0x20
+#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_SMODE2 0x40
+#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_MASK 0x60
+#define METAL_SIFIVE_CLIC0_CLICCFG_NLBITS_MASK 0x1E
+#define METAL_SIFIVE_CLIC0_CLICCFG_NVBIT_MASK 0x01
+
+#define METAL_CLIC_ICTRL_SMODE1_MASK 0x7F /* b8 set imply M-mode */
+#define METAL_CLIC_ICTRL_SMODE2_MASK 0x3F /* b8 set M-mode, b7 clear U-mode */
+
+#define METAL_MAX_INTERRUPT_LEVEL ((1 << METAL_CLIC_MAX_NLBITS) - 1)
+
+struct __metal_driver_vtable_sifive_clic0 {
+ struct metal_interrupt_vtable clic_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_clic0)
+
+#define __METAL_MACHINE_MACROS
+#include <metal/machine.h>
+struct __metal_driver_sifive_clic0 {
+ struct metal_interrupt controller;
+ int init_done;
+ int pad[14];
+ metal_interrupt_vector_handler_t metal_mtvt_table[__METAL_CLIC_SUBINTERRUPTS];
+ __metal_interrupt_data metal_exint_table[__METAL_CLIC_SUBINTERRUPTS];
+};
+#undef __METAL_MACHINE_MACROS
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_hfrosc.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_hfrosc.h
new file mode 100644
index 000000000..d311f0cf2
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_hfrosc.h
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_HFROSC_H
+#define METAL__DRIVERS__SIFIVE_FE310_G000_HFROSC_H
+
+#include <metal/drivers/sifive_fe310-g000_prci.h>
+#include <metal/compiler.h>
+#include <metal/clock.h>
+#include <metal/io.h>
+
+struct __metal_driver_vtable_sifive_fe310_g000_hfrosc {
+ struct __metal_clock_vtable clock;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_hfrosc)
+
+struct __metal_driver_sifive_fe310_g000_hfrosc {
+ struct metal_clock clock;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_hfxosc.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_hfxosc.h
new file mode 100644
index 000000000..b86926fba
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_hfxosc.h
@@ -0,0 +1,20 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_HFXOSC_H
+#define METAL__DRIVERS__SIFIVE_FE310_G000_HFXOSC_H
+
+#include <metal/clock.h>
+#include <metal/drivers/sifive_fe310-g000_prci.h>
+
+struct __metal_driver_vtable_sifive_fe310_g000_hfxosc {
+ struct __metal_clock_vtable clock;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_hfxosc)
+
+struct __metal_driver_sifive_fe310_g000_hfxosc {
+ struct metal_clock clock;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_lfrosc.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_lfrosc.h
new file mode 100644
index 000000000..64985c6bb
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_lfrosc.h
@@ -0,0 +1,21 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_LFROSC_H
+#define METAL__DRIVERS__SIFIVE_FE310_G000_LFROSC_H
+
+#include <metal/compiler.h>
+#include <metal/clock.h>
+#include <metal/io.h>
+
+struct __metal_driver_vtable_sifive_fe310_g000_lfrosc {
+ struct __metal_clock_vtable clock;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_lfrosc)
+
+struct __metal_driver_sifive_fe310_g000_lfrosc {
+ struct metal_clock clock;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_pll.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_pll.h
new file mode 100644
index 000000000..67f818f7b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_pll.h
@@ -0,0 +1,26 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_PLL_H
+#define METAL__DRIVERS__SIFIVE_FE310_G000_PLL_H
+
+struct __metal_driver_sifive_fe310_g000_pll;
+
+#include <metal/clock.h>
+#include <metal/drivers/sifive_fe310-g000_prci.h>
+#include <metal/machine.h>
+
+struct __metal_driver_vtable_sifive_fe310_g000_pll {
+ void (*init)(struct __metal_driver_sifive_fe310_g000_pll *pll);
+ struct __metal_clock_vtable clock;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_pll)
+
+struct __metal_driver_sifive_fe310_g000_pll {
+ struct metal_clock clock;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_prci.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_prci.h
new file mode 100644
index 000000000..387130be5
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_prci.h
@@ -0,0 +1,24 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_PRCI_H
+#define METAL__DRIVERS__SIFIVE_FE310_G000_PRCI_H
+
+#include <metal/compiler.h>
+#include <metal/io.h>
+
+struct __metal_driver_sifive_fe310_g000_prci;
+
+struct __metal_driver_vtable_sifive_fe310_g000_prci {
+ long (*get_reg)(const struct __metal_driver_sifive_fe310_g000_prci *, long offset);
+ long (*set_reg)(const struct __metal_driver_sifive_fe310_g000_prci *, long offset, long value);
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_prci)
+
+struct __metal_driver_sifive_fe310_g000_prci {
+ const struct __metal_driver_vtable_sifive_fe310_g000_prci *vtable;
+};
+
+#endif
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fu540-c000_l2.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fu540-c000_l2.h
new file mode 100644
index 000000000..bb98f169e
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fu540-c000_l2.h
@@ -0,0 +1,23 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_FU540_C000_L2_H
+#define METAL__DRIVERS__SIFIVE_FU540_C000_L2_H
+
+#include <metal/cache.h>
+#include <metal/compiler.h>
+
+struct __metal_driver_vtable_sifive_fu540_c000_l2 {
+ struct __metal_cache_vtable cache;
+};
+
+struct __metal_driver_sifive_fu540_c000_l2;
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fu540_c000_l2)
+
+struct __metal_driver_sifive_fu540_c000_l2 {
+ struct metal_cache cache;
+};
+
+#endif
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_global-external-interrupts0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_global-external-interrupts0.h
new file mode 100644
index 000000000..9e6f2faf6
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_global-external-interrupts0.h
@@ -0,0 +1,21 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_GLOBAL_EXTERNAL_INTERRUPTS0_H
+#define METAL__DRIVERS__SIFIVE_GLOBAL_EXTERNAL_INTERRUPTS0_H
+
+#include <metal/compiler.h>
+#include <metal/drivers/riscv_cpu.h>
+
+struct __metal_driver_vtable_sifive_global_external_interrupts0 {
+ struct metal_interrupt_vtable global0_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_global_external_interrupts0)
+
+struct __metal_driver_sifive_global_external_interrupts0 {
+ struct metal_interrupt irc;
+ int init_done;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-buttons.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-buttons.h
new file mode 100644
index 000000000..a0caeaba8
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-buttons.h
@@ -0,0 +1,21 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_GPIO_BUTTONS_H
+#define METAL__DRIVERS__SIFIVE_GPIO_BUTTONS_H
+
+#include <string.h>
+#include <metal/button.h>
+#include <metal/compiler.h>
+
+struct __metal_driver_vtable_sifive_button {
+ struct metal_button_vtable button_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_button)
+
+struct __metal_driver_sifive_gpio_button {
+ struct metal_button button;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-leds.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-leds.h
new file mode 100644
index 000000000..a8dacf116
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-leds.h
@@ -0,0 +1,21 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_GPIO_LEDS_H
+#define METAL__DRIVERS__SIFIVE_GPIO_LEDS_H
+
+#include <metal/drivers/sifive_gpio0.h>
+#include <metal/led.h>
+#include <metal/compiler.h>
+
+struct __metal_driver_vtable_sifive_led {
+ struct metal_led_vtable led_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_led)
+
+struct __metal_driver_sifive_gpio_led {
+ struct metal_led led;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-switches.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-switches.h
new file mode 100644
index 000000000..c9c7839e9
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-switches.h
@@ -0,0 +1,21 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_GPIO_SWITCHES_H
+#define METAL__DRIVERS__SIFIVE_GPIO_SWITCHES_H
+
+#include <metal/drivers/sifive_gpio0.h>
+#include <metal/switch.h>
+#include <metal/compiler.h>
+
+struct __metal_driver_vtable_sifive_switch {
+ struct metal_switch_vtable switch_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_switch)
+
+struct __metal_driver_sifive_gpio_switch {
+ struct metal_switch flip;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio0.h
new file mode 100644
index 000000000..cc56dc722
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio0.h
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_GPIO0_H
+#define METAL__DRIVERS__SIFIVE_GPIO0_H
+
+#include <metal/compiler.h>
+#include <metal/gpio.h>
+
+struct __metal_driver_vtable_sifive_gpio0 {
+ const struct __metal_gpio_vtable gpio;
+};
+
+//struct __metal_driver_sifive_gpio0;
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_gpio0)
+
+struct __metal_driver_sifive_gpio0 {
+ struct metal_gpio gpio;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_local-external-interrupts0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_local-external-interrupts0.h
new file mode 100644
index 000000000..aa8d63078
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_local-external-interrupts0.h
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_EXTERNAL_INTERRUPTS0_H
+#define METAL__DRIVERS__SIFIVE_EXTERNAL_INTERRUPTS0_H
+
+#include <metal/compiler.h>
+#include <metal/drivers/riscv_cpu.h>
+
+struct __metal_driver_vtable_sifive_local_external_interrupts0 {
+ struct metal_interrupt_vtable local0_vtable;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_local_external_interrupts0)
+
+struct __metal_driver_sifive_local_external_interrupts0 {
+ struct metal_interrupt irc;
+ int init_done;
+};
+
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_rtc0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_rtc0.h
new file mode 100644
index 000000000..b0ed143bf
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_rtc0.h
@@ -0,0 +1,27 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_RTC0_H
+#define METAL__DRIVERS__SIFIVE_RTC0_H
+
+#include <metal/io.h>
+#include <metal/compiler.h>
+
+#include <metal/clock.h>
+#include <metal/interrupt.h>
+#include <metal/rtc.h>
+
+struct __metal_driver_vtable_sifive_rtc0 {
+ const struct metal_rtc_vtable rtc;
+};
+
+struct __metal_driver_sifive_rtc0;
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_rtc0)
+
+struct __metal_driver_sifive_rtc0 {
+ const struct metal_rtc rtc;
+};
+
+#endif
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_spi0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_spi0.h
new file mode 100644
index 000000000..c4a6848e7
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_spi0.h
@@ -0,0 +1,26 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_SPI0_H
+#define METAL__DRIVERS__SIFIVE_SPI0_H
+
+#include <metal/drivers/sifive_gpio0.h>
+#include <metal/clock.h>
+#include <metal/compiler.h>
+#include <metal/io.h>
+#include <metal/spi.h>
+
+struct __metal_driver_vtable_sifive_spi0 {
+ const struct metal_spi_vtable spi;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_spi0)
+
+struct __metal_driver_sifive_spi0 {
+ struct metal_spi spi;
+ unsigned long baud_rate;
+ metal_clock_callback pre_rate_change_callback;
+ metal_clock_callback post_rate_change_callback;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_test0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_test0.h
new file mode 100644
index 000000000..e87db2c83
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_test0.h
@@ -0,0 +1,21 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_TEST0_H
+#define METAL__DRIVERS__SIFIVE_TEST0_H
+
+#include <metal/compiler.h>
+#include <metal/shutdown.h>
+
+struct __metal_driver_vtable_sifive_test0 {
+ const struct __metal_shutdown_vtable shutdown;
+};
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_test0)
+
+struct __metal_driver_sifive_test0 {
+ struct __metal_shutdown shutdown;
+};
+
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_trace.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_trace.h
new file mode 100644
index 000000000..3c67522f4
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_trace.h
@@ -0,0 +1,23 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_TRACE_H
+#define METAL__DRIVERS__SIFIVE_TRACE_H
+
+#include <metal/compiler.h>
+#include <metal/io.h>
+#include <metal/uart.h>
+
+struct __metal_driver_vtable_sifive_trace {
+ const struct metal_uart_vtable uart;
+};
+
+struct __metal_driver_sifive_trace;
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_trace)
+
+struct __metal_driver_sifive_trace {
+ struct metal_uart uart;
+};
+
+#endif /* METAL__DRIVERS__SIFIVE_TRACE_H */
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_uart0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_uart0.h
new file mode 100644
index 000000000..5d585e783
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_uart0.h
@@ -0,0 +1,30 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_UART0_H
+#define METAL__DRIVERS__SIFIVE_UART0_H
+
+#include <metal/drivers/sifive_gpio0.h>
+#include <metal/drivers/riscv_plic0.h>
+#include <metal/clock.h>
+#include <metal/io.h>
+#include <metal/uart.h>
+#include <metal/compiler.h>
+
+struct __metal_driver_vtable_sifive_uart0 {
+ const struct metal_uart_vtable uart;
+};
+
+struct __metal_driver_sifive_uart0;
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_uart0)
+
+struct __metal_driver_sifive_uart0 {
+ struct metal_uart uart;
+ unsigned long baud_rate;
+ metal_clock_callback pre_rate_change_callback;
+ metal_clock_callback post_rate_change_callback;
+};
+
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_wdog0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_wdog0.h
new file mode 100644
index 000000000..12b143d58
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_wdog0.h
@@ -0,0 +1,26 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__DRIVERS__SIFIVE_WDOG0_H
+#define METAL__DRIVERS__SIFIVE_WDOG0_H
+
+#include <metal/io.h>
+#include <metal/compiler.h>
+
+#include <metal/watchdog.h>
+#include <metal/clock.h>
+#include <metal/interrupt.h>
+
+struct __metal_driver_vtable_sifive_wdog0 {
+ const struct metal_watchdog_vtable watchdog;
+};
+
+struct __metal_driver_sifive_wdog0;
+
+__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_wdog0)
+
+struct __metal_driver_sifive_wdog0 {
+ const struct metal_watchdog watchdog;
+};
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/gpio.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/gpio.h
new file mode 100644
index 000000000..7645494ff
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/gpio.h
@@ -0,0 +1,284 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__GPIO_H
+#define METAL__GPIO_H
+
+#include <metal/compiler.h>
+#include <metal/interrupt.h>
+
+/*!
+ * @file gpio.h
+ * @brief API for manipulating general-purpose input/output
+ */
+
+struct metal_gpio;
+
+struct __metal_gpio_vtable {
+ int (*disable_input)(struct metal_gpio *, long pins);
+ int (*enable_input)(struct metal_gpio *, long pins);
+ long (*input)(struct metal_gpio *);
+ long (*output)(struct metal_gpio *);
+ int (*disable_output)(struct metal_gpio *, long pins);
+ int (*enable_output)(struct metal_gpio *, long pins);
+ int (*output_set)(struct metal_gpio *, long value);
+ int (*output_clear)(struct metal_gpio *, long value);
+ int (*output_toggle)(struct metal_gpio *, long value);
+ int (*enable_io)(struct metal_gpio *, long pins, long dest);
+ int (*disable_io)(struct metal_gpio *, long pins);
+ int (*config_int)(struct metal_gpio *, long pins, int intr_type);
+ int (*clear_int)(struct metal_gpio *, long pins, int intr_type);
+ struct metal_interrupt* (*interrupt_controller)(struct metal_gpio *gpio);
+ int (*get_interrupt_id)(struct metal_gpio *gpio, int pin);
+};
+
+#define METAL_GPIO_INT_DISABLE 0
+#define METAL_GPIO_INT_RISING 1
+#define METAL_GPIO_INT_FALLING 2
+#define METAL_GPIO_INT_BOTH_EDGE 3
+#define METAL_GPIO_INT_LOW 4
+#define METAL_GPIO_INT_HIGH 5
+#define METAL_GPIO_INT_BOTH_LEVEL 6
+#define METAL_GPIO_INT_MAX 7
+
+/*!
+ * @struct metal_gpio
+ * @brief The handle for a GPIO interface
+ */
+struct metal_gpio {
+ const struct __metal_gpio_vtable *vtable;
+};
+
+/*!
+ * @brief Get a GPIO device handle
+ * @param device_num The GPIO device index
+ * @return The GPIO device handle, or NULL if there is no device at that index
+ */
+struct metal_gpio *metal_gpio_get_device(unsigned int device_num);
+
+/*!
+ * @brief enable input on a pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @return 0 if the input is successfully enabled
+ */
+__inline__ int metal_gpio_enable_input(struct metal_gpio *gpio, int pin) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->enable_input(gpio, (1 << pin));
+}
+
+/*!
+ * @brief Disable input on a pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @return 0 if the input is successfully disabled
+ */
+__inline__ int metal_gpio_disable_input(struct metal_gpio *gpio, int pin) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->disable_input(gpio, (1 << pin));
+}
+
+/*!
+ * @brief Enable output on a pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @return 0 if the output is successfully enabled
+ */
+__inline__ int metal_gpio_enable_output(struct metal_gpio *gpio, int pin) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->enable_output(gpio, (1 << pin));
+}
+
+/*!
+ * @brief Disable output on a pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @return 0 if the output is successfully disabled
+ */
+__inline__ int metal_gpio_disable_output(struct metal_gpio *gpio, int pin) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->disable_output(gpio, (1 << pin));
+}
+
+/*!
+ * @brief Set the output value of a GPIO pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @param value The value to set the pin to
+ * @return 0 if the output is successfully set
+ */
+__inline__ int metal_gpio_set_pin(struct metal_gpio *gpio, int pin, int value) {
+ if(!gpio) {
+ return 1;
+ }
+
+ if(value == 0) {
+ return gpio->vtable->output_clear(gpio, (1 << pin));
+ } else {
+ return gpio->vtable->output_set(gpio, (1 << pin));
+ }
+}
+
+/*!
+ * @brief Get the value of the GPIO pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @return The value of the GPIO pin
+ */
+__inline__ int metal_gpio_get_input_pin(struct metal_gpio *gpio, int pin) {
+ if(!gpio) {
+ return 0;
+ }
+
+ long value = gpio->vtable->input(gpio);
+
+ if(value & (1 << pin)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ * @brief Get the value of the GPIO pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @return The value of the GPIO pin
+ */
+__inline__ int metal_gpio_get_output_pin(struct metal_gpio *gpio, int pin) {
+ if(!gpio) {
+ return 0;
+ }
+
+ long value = gpio->vtable->output(gpio);
+
+ if(value & (1 << pin)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ * @brief Clears the value of the GPIO pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @return 0 if the pin is successfully cleared
+ */
+__inline__ int metal_gpio_clear_pin(struct metal_gpio *gpio, int pin) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->output_clear(gpio, (1 << pin));
+}
+
+/*!
+ * @brief Toggles the value of the GPIO pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The pin number indexed from 0
+ * @return 0 if the pin is successfully toggled
+ */
+__inline__ int metal_gpio_toggle_pin(struct metal_gpio *gpio, int pin) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->output_toggle(gpio, (1 << pin));
+}
+
+/*!
+ * @brief Enables and sets the pinmux for a GPIO pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The bitmask for the pin to enable pinmux on
+ * @param io_function The IO function to set
+ * @return 0 if the pinmux is successfully set
+ */
+__inline__ int metal_gpio_enable_pinmux(struct metal_gpio *gpio, int pin, int io_function) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->enable_io(gpio, (1 << pin), (io_function << pin));
+}
+
+/*!
+ * @brief Disables the pinmux for a GPIO pin
+ * @param gpio The handle for the GPIO interface
+ * @param pin The bitmask for the pin to disable pinmux on
+ * @return 0 if the pinmux is successfully set
+ */
+__inline__ int metal_gpio_disable_pinmux(struct metal_gpio *gpio, int pin) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->disable_io(gpio, (1 << pin));
+}
+
+/*!
+ * @brief Config gpio interrupt type
+ * @param gpio The handle for the GPIO interface
+ * @param pin The bitmask for the pin to enable gpio interrupt
+ * @param intr_type The interrupt type
+ * @return 0 if the interrupt mode is setup properly
+ */
+__inline__ int metal_gpio_config_interrupt(struct metal_gpio *gpio, int pin, int intr_type) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->config_int(gpio, (1 << pin), intr_type);
+}
+
+/*!
+ * @brief Clear gpio interrupt status
+ * @param gpio The handle for the GPIO interface
+ * @param pin The bitmask for the pin to clear gpio interrupt
+ * @param intr_type The interrupt type to be clear
+ * @return 0 if the interrupt is cleared
+ */
+__inline__ int metal_gpio_clear_interrupt(struct metal_gpio *gpio, int pin, int intr_type) {
+ if(!gpio) {
+ return 1;
+ }
+
+ return gpio->vtable->clear_int(gpio, (1 << pin), intr_type);
+}
+
+/*!
+ * @brief Get the interrupt controller for a gpio
+ *
+ * @param gpio The handle for the gpio
+ * @return A pointer to the interrupt controller responsible for handling
+ * gpio interrupts.
+ */
+__inline__ struct metal_interrupt*
+ metal_gpio_interrupt_controller(struct metal_gpio *gpio) {
+ return gpio->vtable->interrupt_controller(gpio);
+}
+
+/*!
+ * @brief Get the interrupt id for a gpio
+ *
+ * @param gpio The handle for the gpio
+ * @param pin The bitmask for the pin to get gpio interrupt id
+ * @return The interrupt id corresponding to a gpio.
+ */
+__inline__ int metal_gpio_get_interrupt_id(struct metal_gpio *gpio, int pin) {
+ return gpio->vtable->get_interrupt_id(gpio, pin);
+}
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/interrupt.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/interrupt.h
new file mode 100644
index 000000000..4f59bd36b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/interrupt.h
@@ -0,0 +1,461 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__INTERRUPT_H
+#define METAL__INTERRUPT_H
+
+/*! @file interrupt.h
+ * @brief API for registering and manipulating interrupts
+ */
+
+#include <stddef.h>
+
+/*!
+ * @brief Possible interrupt controllers
+ */
+typedef enum metal_interrupt_controller_ {
+ METAL_CPU_CONTROLLER = 0,
+ METAL_CLINT_CONTROLLER = 1,
+ METAL_CLIC_CONTROLLER = 2,
+ METAL_PLIC_CONTROLLER = 3
+} metal_intr_cntrl_type;
+
+/*!
+ * @brief Possible mode of interrupts to operate
+ */
+typedef enum metal_vector_mode_ {
+ METAL_DIRECT_MODE = 0,
+ METAL_VECTOR_MODE = 1,
+ METAL_SELECTIVE_NONVECTOR_MODE = 2,
+ METAL_SELECTIVE_VECTOR_MODE = 3,
+ METAL_HARDWARE_VECTOR_MODE = 4
+} metal_vector_mode;
+
+/*!
+ * @brief Possible mode of privilege interrupts to operate
+ */
+typedef enum metal_intr_priv_mode_ {
+ METAL_INTR_PRIV_M_MODE = 0,
+ METAL_INTR_PRIV_MU_MODE = 1,
+ METAL_INTR_PRIV_MSU_MODE = 2
+} metal_intr_priv_mode;
+
+/*!
+ * @brief Function signature for interrupt callback handlers
+ */
+typedef void (*metal_interrupt_handler_t) (int, void *);
+typedef void (*metal_interrupt_vector_handler_t) (void);
+
+struct metal_interrupt;
+
+struct metal_interrupt_vtable {
+ void (*interrupt_init)(struct metal_interrupt *controller);
+ int (*interrupt_set_vector_mode)(struct metal_interrupt *controller, metal_vector_mode mode);
+ metal_vector_mode (*interrupt_get_vector_mode)(struct metal_interrupt *controller);
+ int (*interrupt_set_privilege)(struct metal_interrupt *controller, metal_intr_priv_mode priv);
+ metal_intr_priv_mode (*interrupt_get_privilege)(struct metal_interrupt *controller);
+ int (*interrupt_clear)(struct metal_interrupt *controller, int id);
+ int (*interrupt_set)(struct metal_interrupt *controller, int id);
+ int (*interrupt_register)(struct metal_interrupt *controller, int id,
+ metal_interrupt_handler_t isr, void *priv_data);
+ int (*interrupt_vector_register)(struct metal_interrupt *controller, int id,
+ metal_interrupt_vector_handler_t isr, void *priv_data);
+ int (*interrupt_enable)(struct metal_interrupt *controller, int id);
+ int (*interrupt_disable)(struct metal_interrupt *controller, int id);
+ int (*interrupt_vector_enable)(struct metal_interrupt *controller, int id);
+ int (*interrupt_vector_disable)(struct metal_interrupt *controller, int id);
+ unsigned int (*interrupt_get_threshold)(struct metal_interrupt *controller);
+ int (*interrupt_set_threshold)(struct metal_interrupt *controller, unsigned int threshold);
+ unsigned int (*interrupt_get_priority)(struct metal_interrupt *controller, int id);
+ int (*interrupt_set_priority)(struct metal_interrupt *controller, int id, unsigned int priority);
+ int (*command_request)(struct metal_interrupt *controller, int cmd, void *data);
+ int (*mtimecmp_set)(struct metal_interrupt *controller, int hartid, unsigned long long time);
+};
+
+/*!
+ * @brief A handle for an interrupt
+ */
+struct metal_interrupt {
+ const struct metal_interrupt_vtable *vtable;
+};
+
+/*!
+ * @brief Initialize a given interrupt controller
+ *
+ * Initialize a given interrupt controller. This function must be called
+ * before any interrupts are registered or enabled with the handler. It
+ * is invalid to initialize an interrupt controller more than once.
+ *
+ * @param controller The handle for the interrupt controller
+ */
+__inline__ void metal_interrupt_init(struct metal_interrupt *controller)
+{
+ controller->vtable->interrupt_init(controller);
+}
+
+/*!
+ * @brief Get the handle for an given interrupt controller type
+ * @param cntrl The type ofinterrupt controller
+ * @param id The instance of the interrupt controller
+ * @return A handle to the interrupt controller (CLINT, CLIC, PLIC), or
+ * NULL if none is found for the requested label
+ */
+struct metal_interrupt* metal_interrupt_get_controller(metal_intr_cntrl_type cntrl,
+ int id);
+
+/*!
+ * @brief Configure vector mode for an interrupt controller
+ *
+ * Configure vector mode for an interrupt controller.
+ * This function must be called after initialization and before
+ * configuring individual interrupts, registering ISR.
+ *
+ * @param controller The handle for the interrupt controller
+ * @param mode The vector mode of the interrupt controller.
+ * @return 0 upon success
+ */
+__inline__ int metal_interrupt_set_vector_mode(struct metal_interrupt *controller,
+ metal_vector_mode mode)
+{
+ return controller->vtable->interrupt_set_vector_mode(controller, mode);
+}
+
+/*!
+ * @brief Get vector mode of a given an interrupt controller
+ *
+ * Configure vector mode for an interrupt controller.
+ * This function must be called after initialization and before
+ * configuring individual interrupts, registering ISR.
+ *
+ * @param controller The handle for the interrupt controller
+ * @param mode The vector mode of the interrupt controller.
+ * @return The interrupt vector mode
+ */
+__inline__ metal_vector_mode metal_interrupt_get_vector_mode(struct metal_interrupt *controller)
+{
+ return controller->vtable->interrupt_get_vector_mode(controller);
+}
+
+/*!
+ * @brief Configure privilege mode a of given interrupt controller
+ *
+ * Configure privilege mode for a given interrupt controller.
+ * This function must be called after initialization and before
+ * configuring individual interrupts, registering ISR.
+ *
+ * @param controller The handle for the interrupt controller
+ * @param privilege The privilege mode of the interrupt controller.
+ * @return 0 upon success
+ */
+__inline__ int metal_interrupt_set_privilege(struct metal_interrupt *controller,
+ metal_intr_priv_mode privilege)
+{
+ return controller->vtable->interrupt_set_privilege(controller, privilege);
+}
+
+/*!
+ * @brief Get privilege mode a of given interrupt controller
+ *
+ * Get privilege mode for a given interrupt controller.
+ * This function must be called after initialization and before
+ * configuring individual interrupts, registering ISR.
+ *
+ * @param controller The handle for the interrupt controller
+ * @return The interrupt privilege mode
+ */
+__inline__ metal_intr_priv_mode metal_interrupt_get_privilege(struct metal_interrupt *controller)
+{
+ return controller->vtable->interrupt_get_privilege(controller);
+}
+
+/*!
+ * @brief clear an interrupt
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to trigger
+ * @return 0 upon success
+ */
+__inline__ int metal_interrupt_clear(struct metal_interrupt *controller, int id)
+{
+ return controller->vtable->interrupt_clear(controller, id);
+}
+
+/*!
+ * @brief Set an interrupt
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to trigger
+ * @return 0 upon success
+ */
+__inline__ int metal_interrupt_set(struct metal_interrupt *controller, int id)
+{
+ return controller->vtable->interrupt_set(controller, id);
+}
+
+/*!
+ * @brief Register an interrupt handler
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to register
+ * @param handler The interrupt handler callback
+ * @param priv_data Private data for the interrupt handler
+ * @return 0 upon success
+ */
+__inline__ int metal_interrupt_register_handler(struct metal_interrupt *controller,
+ int id,
+ metal_interrupt_handler_t handler,
+ void *priv_data)
+{
+ return controller->vtable->interrupt_register(controller, id, handler, priv_data);
+}
+
+/*!
+ * @brief Register an interrupt vector handler
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to register
+ * @param handler The interrupt vector handler callback
+ * @param priv_data Private data for the interrupt handler
+ * @return 0 upon success
+ */
+__inline__ int metal_interrupt_register_vector_handler(struct metal_interrupt *controller,
+ int id,
+ metal_interrupt_vector_handler_t handler,
+ void *priv_data)
+{
+ return controller->vtable->interrupt_vector_register(controller, id, handler, priv_data);
+}
+
+/*!
+ * @brief Enable an interrupt
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to enable
+ * @return 0 upon success
+ */
+__inline__ int metal_interrupt_enable(struct metal_interrupt *controller, int id)
+{
+ return controller->vtable->interrupt_enable(controller, id);
+}
+
+/*!
+ * @brief Disable an interrupt
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to disable
+ * @return 0 upon success
+ */
+__inline__ int metal_interrupt_disable(struct metal_interrupt *controller, int id)
+{
+ return controller->vtable->interrupt_disable(controller, id);
+}
+
+/*!
+ * @brief Set interrupt threshold level
+ * @param controller The handle for the interrupt controller
+ * @param threshold The interrupt threshold level
+ * @return 0 upon success
+ */
+inline int metal_interrupt_set_threshold(struct metal_interrupt *controller, unsigned int level)
+{
+ return controller->vtable->interrupt_set_threshold(controller, level);
+}
+
+/*!
+ * @brief Get an interrupt threshold level
+ * @param controller The handle for the interrupt controller
+ * @return The interrupt threshold level
+ */
+inline unsigned int metal_interrupt_get_threshold(struct metal_interrupt *controller)
+{
+ return controller->vtable->interrupt_get_threshold(controller);
+}
+
+/*!
+ * @brief Set an interrupt priority level
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to enable
+ * @param priority The interrupt priority level
+ * @return 0 upon success
+ */
+inline int metal_interrupt_set_priority(struct metal_interrupt *controller,
+ int id, unsigned int priority)
+{
+ return controller->vtable->interrupt_set_priority(controller, id, priority);
+}
+
+/*!
+ * @brief Get an interrupt priority level
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to enable
+ * @return The interrupt priority level
+ */
+inline unsigned int metal_interrupt_get_priority(struct metal_interrupt *controller, int id)
+{
+ return controller->vtable->interrupt_get_priority(controller, id);
+}
+
+/*!
+ * @brief Enable an interrupt vector
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to enable
+ * @return 0 upon success
+ */
+__inline__ int metal_interrupt_vector_enable(struct metal_interrupt *controller, int id)
+{
+ return controller->vtable->interrupt_vector_enable(controller, id);
+}
+
+/*!
+ * @brief Disable an interrupt vector
+ * @param controller The handle for the interrupt controller
+ * @param id The interrupt ID to disable
+ * @return 0 upon success
+ */
+__inline__ int metal_interrupt_vector_disable(struct metal_interrupt *controller, int id)
+{
+ return controller->vtable->interrupt_vector_disable(controller, id);
+}
+
+/*!
+ * @brief Default interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Software interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_software_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Timer interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_timer_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal External interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_external_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 0 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc0_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 1 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc1_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 2 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc2_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 3 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc3_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 4 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc4_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 5 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc5_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 6 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc6_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 7 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc7_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 8 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc8_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 9 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc9_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 10 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc10_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 11 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc11_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 12 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc12_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 13 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc13_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 14 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc14_interrupt_vector_handler(void);
+
+/*!
+ * @brief Metal Local 15 interrupt vector handler, that can be overriden by user
+ * @param None
+ * @return None
+ */
+void __attribute__((weak, interrupt)) metal_lc15_interrupt_vector_handler(void);
+
+/* Utilities function to controll, manages devices via a given interrupt controller */
+__inline__ int _metal_interrupt_command_request(struct metal_interrupt *controller,
+ int cmd, void *data)
+{
+ return controller->vtable->command_request(controller, cmd, data);
+}
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/io.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/io.h
new file mode 100644
index 000000000..d55b4520a
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/io.h
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__IO_H
+#define METAL__IO_H
+
+/* This macro enforces that the compiler will not elide the given access. */
+#define __METAL_ACCESS_ONCE(x) (*(__typeof__(*x) volatile *)(x))
+
+/* Allows users to specify arbitrary fences. */
+#define __METAL_IO_FENCE(pred, succ) __asm__ volatile ("fence " #pred "," #succ ::: "memory");
+
+/* Types that explicitly describe an address as being used for memory-mapped
+ * IO. These should only be accessed via __METAL_ACCESS_ONCE. */
+typedef unsigned char __metal_io_u8;
+typedef unsigned short __metal_io_u16;
+typedef unsigned int __metal_io_u32;
+#if __riscv_xlen >= 64
+typedef unsigned long __metal_io_u64;
+#endif
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/itim.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/itim.h
new file mode 100644
index 000000000..1a2a05b8b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/itim.h
@@ -0,0 +1,21 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__ITIM_H
+#define METAL__ITIM_H
+
+/*! @file itim.h
+ *
+ * API for manipulating ITIM allocation
+ */
+
+
+/*! @def METAL_PLACE_IN_ITIM
+ * @brief Link a function into the ITIM
+ *
+ * Link a function into the ITIM (Instruction Tightly Integrated
+ * Memory) if the ITIM is present on the target device.
+ */
+#define METAL_PLACE_IN_ITIM __attribute__((section(".itim")))
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/led.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/led.h
new file mode 100644
index 000000000..f2aa39ceb
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/led.h
@@ -0,0 +1,68 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__LED_H
+#define METAL__LED_H
+
+/*!
+ * @file led.h
+ * @brief API for manipulating LEDs
+ */
+
+struct metal_led;
+
+struct metal_led_vtable {
+ int (*led_exist)(struct metal_led *led, char *label);
+ void (*led_enable)(struct metal_led *led);
+ void (*led_on)(struct metal_led *led);
+ void (*led_off)(struct metal_led *led);
+ void (*led_toggle)(struct metal_led *led);
+};
+
+/*!
+ * @brief A handle for an LED
+ */
+struct metal_led {
+ const struct metal_led_vtable *vtable;
+};
+
+/*!
+ * @brief Get a handle for an LED
+ * @param label The DeviceTree label for the desired LED
+ * @return A handle to the LED, or NULL if none is found for the requested label
+ */
+struct metal_led* metal_led_get(char *label);
+
+/*!
+ * @brief Get a handle for a channel of an RGB LED
+ * @param label The DeviceTree label for the desired LED
+ * @param color The color for the LED in the DeviceTree
+ * @return A handle to the LED, or NULL if none is found for the requested label and color
+ */
+struct metal_led* metal_led_get_rgb(char *label, char *color);
+
+/*!
+ * @brief Enable an LED
+ * @param led The handle for the LED
+ */
+__inline__ void metal_led_enable(struct metal_led *led) { led->vtable->led_enable(led); }
+
+/*!
+ * @brief Turn an LED on
+ * @param led The handle for the LED
+ */
+__inline__ void metal_led_on(struct metal_led *led) { led->vtable->led_on(led); }
+
+/*!
+ * @brief Turn an LED off
+ * @param led The handle for the LED
+ */
+__inline__ void metal_led_off(struct metal_led *led) { led->vtable->led_off(led); }
+
+/*!
+ * @brief Toggle the on/off state of an LED
+ * @param led The handle for the LED
+ */
+__inline__ void metal_led_toggle(struct metal_led *led) { led->vtable->led_toggle(led); }
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/lock.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/lock.h
new file mode 100644
index 000000000..0702cbf16
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/lock.h
@@ -0,0 +1,146 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__LOCK_H
+#define METAL__LOCK_H
+
+#include <metal/machine.h>
+#include <metal/memory.h>
+#include <metal/compiler.h>
+
+/*!
+ * @file lock.h
+ * @brief An API for creating and using a software lock/mutex
+ */
+
+/* TODO: How can we make the exception code platform-independant? */
+#define _METAL_STORE_AMO_ACCESS_FAULT 7
+
+#define METAL_LOCK_BACKOFF_CYCLES 32
+#define METAL_LOCK_BACKOFF_EXPONENT 2
+
+/*!
+ * @def METAL_LOCK_DECLARE
+ * @brief Declare a lock
+ *
+ * Locks must be declared with METAL_LOCK_DECLARE to ensure that the lock
+ * is linked into a memory region which supports atomic memory operations.
+ */
+#define METAL_LOCK_DECLARE(name) \
+ __attribute__((section(".data.locks"))) \
+ struct metal_lock name
+
+/*!
+ * @brief A handle for a lock
+ */
+struct metal_lock {
+ int _state;
+};
+
+/*!
+ * @brief Initialize a lock
+ * @param lock The handle for a lock
+ * @return 0 if the lock is successfully initialized. A non-zero code indicates failure.
+ *
+ * If the lock cannot be initialized, attempts to take or give the lock
+ * will result in a Store/AMO access fault.
+ */
+__inline__ int metal_lock_init(struct metal_lock *lock) {
+#ifdef __riscv_atomic
+ /* Get a handle for the memory which holds the lock state */
+ struct metal_memory *lock_mem = metal_get_memory_from_address((uintptr_t) &(lock->_state));
+ if(!lock_mem) {
+ return 1;
+ }
+
+ /* If the memory doesn't support atomics, report an error */
+ if(!metal_memory_supports_atomics(lock_mem)) {
+ return 2;
+ }
+
+ lock->_state = 0;
+
+ return 0;
+#else
+ return 3;
+#endif
+}
+
+/*!
+ * @brief Take a lock
+ * @param lock The handle for a lock
+ * @return 0 if the lock is successfully taken
+ *
+ * If the lock initialization failed, attempts to take a lock will result in
+ * a Store/AMO access fault.
+ */
+__inline__ int metal_lock_take(struct metal_lock *lock) {
+#ifdef __riscv_atomic
+ int old = 1;
+ int new = 1;
+
+ int backoff = 1;
+ const int max_backoff = METAL_LOCK_BACKOFF_CYCLES * METAL_MAX_CORES;
+
+ while(1) {
+ __asm__ volatile("amoswap.w.aq %[old], %[new], (%[state])"
+ : [old] "=r" (old)
+ : [new] "r" (new), [state] "r" (&(lock->_state))
+ : "memory");
+
+ if (old == 0) {
+ break;
+ }
+
+ for (int i = 0; i < backoff; i++) {
+ __asm__ volatile("");
+ }
+
+ if (backoff < max_backoff) {
+ backoff *= METAL_LOCK_BACKOFF_EXPONENT;
+ }
+ }
+
+ return 0;
+#else
+ /* Store the memory address in mtval like a normal store/amo access fault */
+ __asm__ ("csrw mtval, %[state]"
+ :: [state] "r" (&(lock->_state)));
+
+ /* Trigger a Store/AMO access fault */
+ _metal_trap(_METAL_STORE_AMO_ACCESS_FAULT);
+
+ /* If execution returns, indicate failure */
+ return 1;
+#endif
+}
+
+/*!
+ * @brief Give back a held lock
+ * @param lock The handle for a lock
+ * @return 0 if the lock is successfully given
+ *
+ * If the lock initialization failed, attempts to give a lock will result in
+ * a Store/AMO access fault.
+ */
+__inline__ int metal_lock_give(struct metal_lock *lock) {
+#ifdef __riscv_atomic
+ __asm__ volatile("amoswap.w.rl x0, x0, (%[state])"
+ :: [state] "r" (&(lock->_state))
+ : "memory");
+
+ return 0;
+#else
+ /* Store the memory address in mtval like a normal store/amo access fault */
+ __asm__ ("csrw mtval, %[state]"
+ :: [state] "r" (&(lock->_state)));
+
+ /* Trigger a Store/AMO access fault */
+ _metal_trap(_METAL_STORE_AMO_ACCESS_FAULT);
+
+ /* If execution returns, indicate failure */
+ return 1;
+#endif
+}
+
+#endif /* METAL__LOCK_H */
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/memory.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/memory.h
new file mode 100644
index 000000000..9de7d6162
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/memory.h
@@ -0,0 +1,81 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__MEMORY_H
+#define METAL__MEMORY_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+/*!
+ * @file memory.h
+ *
+ * @brief API for enumerating memory blocks
+ */
+
+struct _metal_memory_attributes {
+ unsigned int R : 1;
+ unsigned int W : 1;
+ unsigned int X : 1;
+ unsigned int C : 1;
+ unsigned int A : 1;
+};
+
+/*!
+ * @brief A handle for a memory block
+ */
+struct metal_memory {
+ const uintptr_t _base_address;
+ const size_t _size;
+ const struct _metal_memory_attributes _attrs;
+};
+
+/*!
+ * @brief Get the memory block which services the given address
+ *
+ * Given a physical memory address, get a handle for the memory block to which
+ * that address is mapped.
+ *
+ * @param address The address to query
+ * @return The memory block handle, or NULL if the address is not mapped to a memory block
+ */
+struct metal_memory *metal_get_memory_from_address(const uintptr_t address);
+
+/*!
+ * @brief Get the base address for a memory block
+ * @param memory The handle for the memory block
+ * @return The base address of the memory block
+ */
+__inline__ uintptr_t metal_memory_get_base_address(const struct metal_memory *memory) {
+ return memory->_base_address;
+}
+
+/*!
+ * @brief Get the size of a memory block
+ * @param memory The handle for the memory block
+ * @return The size of the memory block
+ */
+__inline__ size_t metal_memory_get_size(const struct metal_memory *memory) {
+ return memory->_size;
+}
+
+/*!
+ * @brief Query if a memory block supports atomic operations
+ * @param memory The handle for the memory block
+ * @return nonzero if the memory block supports atomic operations
+ */
+__inline__ int metal_memory_supports_atomics(const struct metal_memory *memory) {
+ return memory->_attrs.A;
+}
+
+/*!
+ * @brief Query if a memory block is cacheable
+ * @param memory The handle for the memory block
+ * @return nonzero if the memory block is cachable
+ */
+__inline__ int metal_memory_is_cachable(const struct metal_memory *memory) {
+ return memory->_attrs.C;
+}
+
+#endif /* METAL__MEMORY_H */
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/pmp.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/pmp.h
new file mode 100644
index 000000000..d948656c8
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/pmp.h
@@ -0,0 +1,209 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__PMP_H
+#define METAL__PMP_H
+
+/*!
+ * @file metal/pmp.h
+ *
+ * @brief API for Configuring Physical Memory Protection on RISC-V Cores
+ *
+ * The Physical Memory Protection (PMP) interface on RISC-V cores
+ * is a form of memory protection unit which allows for a finite number
+ * of physical memory regions to be configured with certain access
+ * permissions.
+ *
+ * Additional information about the use and configuration rules for PMPs
+ * can be found by reading the RISC-V Privileged Architecture Specification.
+ */
+
+#include <stddef.h>
+#include <metal/machine.h>
+
+struct metal_pmp;
+
+/*!
+ * @brief Set of available PMP addressing modes
+ */
+enum metal_pmp_address_mode {
+ /*! @brief Disable the PMP region */
+ METAL_PMP_OFF = 0,
+ /*! @brief Use Top-of-Range mode */
+ METAL_PMP_TOR = 1,
+ /*! @brief Use naturally-aligned 4-byte region mode */
+ METAL_PMP_NA4 = 2,
+ /*! @brief Use naturally-aligned power-of-two mode */
+ METAL_PMP_NAPOT = 3
+};
+
+/*!
+ * @brief Configuration for a PMP region
+ */
+struct metal_pmp_config {
+ /*! @brief Sets whether reads to the PMP region succeed */
+ unsigned int R : 1;
+ /*! @brief Sets whether writes to the PMP region succeed */
+ unsigned int W : 1;
+ /*! @brief Sets whether the PMP region is executable */
+ unsigned int X : 1;
+
+ /*! @brief Sets the addressing mode of the PMP region */
+ enum metal_pmp_address_mode A : 2;
+
+ int _pad : 2;
+
+ /*! @brief Sets whether the PMP region is locked */
+ enum metal_pmp_locked {
+ METAL_PMP_UNLOCKED = 0,
+ METAL_PMP_LOCKED = 1
+ } L : 1;
+};
+
+/*!
+ * @brief A handle for the PMP device
+ */
+struct metal_pmp {
+ /* The minimum granularity of the PMP region. Set by metal_pmp_init */
+ uintptr_t _granularity[METAL_MAX_CORES];
+};
+
+/*!
+ * @brief Get the PMP device handle
+ */
+struct metal_pmp *metal_pmp_get_device(void);
+
+/*!
+ * @brief Get the number of pmp regions for the hartid
+ */
+int metal_pmp_num_regions(int hartid);
+
+/*!
+ * @brief Initialize the PMP
+ * @param pmp The PMP device handle to be initialized
+ *
+ * The PMP initialization routine is optional and may be called as many times
+ * as is desired. The effect of the initialization routine is to attempt to set
+ * all regions to unlocked and disabled, as well as to clear the X, W, and R
+ * bits. Only the pmp configuration of the hart which executes the routine will
+ * be affected.
+ *
+ * If any regions are fused to preset values by the implementation or locked,
+ * those PMP regions will silently remain uninitialized.
+ */
+void metal_pmp_init(struct metal_pmp *pmp);
+
+/*!
+ * @brief Configure a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to configure
+ * @param config The desired configuration of the PMP region
+ * @param address The desired address of the PMP region
+ * @return 0 upon success
+ */
+int metal_pmp_set_region(struct metal_pmp *pmp, unsigned int region, struct metal_pmp_config config, size_t address);
+
+/*!
+ * @brief Get the configuration for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to read
+ * @param config Variable to store the PMP region configuration
+ * @param address Variable to store the PMP region address
+ * @return 0 if the region is read successfully
+ */
+int metal_pmp_get_region(struct metal_pmp *pmp, unsigned int region, struct metal_pmp_config *config, size_t *address);
+
+/*!
+ * @brief Lock a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to lock
+ * @return 0 if the region is successfully locked
+ */
+int metal_pmp_lock(struct metal_pmp *pmp, unsigned int region);
+
+/*!
+ * @brief Set the address for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to set
+ * @param address The desired address of the PMP region
+ * @return 0 if the address is successfully set
+ */
+int metal_pmp_set_address(struct metal_pmp *pmp, unsigned int region, size_t address);
+
+/*!
+ * @brief Get the address of a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to read
+ * @return The address of the PMP region, or 0 if the region could not be read
+ */
+size_t metal_pmp_get_address(struct metal_pmp *pmp, unsigned int region);
+
+/*!
+ * @brief Set the addressing mode of a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to set
+ * @param mode The PMP addressing mode to set
+ * @return 0 if the addressing mode is successfully set
+ */
+int metal_pmp_set_address_mode(struct metal_pmp *pmp, unsigned int region, enum metal_pmp_address_mode mode);
+
+/*!
+ * @brief Get the addressing mode of a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to read
+ * @return The address mode of the PMP region
+ */
+enum metal_pmp_address_mode metal_pmp_get_address_mode(struct metal_pmp *pmp, unsigned int region);
+
+/*!
+ * @brief Set the executable bit for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to set
+ * @param X The desired value of the executable bit
+ * @return 0 if the executable bit is successfully set
+ */
+int metal_pmp_set_executable(struct metal_pmp *pmp, unsigned int region, int X);
+
+/*!
+ * @brief Get the executable bit for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to read
+ * @return the value of the executable bit
+ */
+int metal_pmp_get_executable(struct metal_pmp *pmp, unsigned int region);
+
+/*!
+ * @brief Set the writable bit for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to set
+ * @param W The desired value of the writable bit
+ * @return 0 if the writable bit is successfully set
+ */
+int metal_pmp_set_writeable(struct metal_pmp *pmp, unsigned int region, int W);
+
+/*!
+ * @brief Get the writable bit for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to read
+ * @return the value of the writable bit
+ */
+int metal_pmp_get_writeable(struct metal_pmp *pmp, unsigned int region);
+
+/*!
+ * @brief Set the readable bit for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to set
+ * @param R The desired value of the readable bit
+ * @return 0 if the readable bit is successfully set
+ */
+int metal_pmp_set_readable(struct metal_pmp *pmp, unsigned int region, int R);
+
+/*!
+ * @brief Set the readable bit for a PMP region
+ * @param pmp The PMP device handle
+ * @param region The PMP region to read
+ * @return the value of the readable bit
+ */
+int metal_pmp_get_readable(struct metal_pmp *pmp, unsigned int region);
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/privilege.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/privilege.h
new file mode 100644
index 000000000..928a936b1
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/privilege.h
@@ -0,0 +1,122 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__PRIVILEGE_H
+#define METAL__PRIVILEGE_H
+
+/*!
+ * @file metal/privilege.h
+ *
+ * @brief API for manipulating the privilege mode of a RISC-V system
+ *
+ * Additional information about privilege modes on RISC-V systems can be found
+ * by reading the RISC-V Privileged Architecture Specification v1.10.
+ */
+
+#include <stdint.h>
+
+enum metal_privilege_mode {
+ METAL_PRIVILEGE_USER = 0,
+ METAL_PRIVILEGE_SUPERVISOR = 1,
+ METAL_PRIVILEGE_MACHINE = 3,
+};
+
+#if __riscv_xlen == 32
+typedef uint32_t metal_xreg_t;
+#elif __riscv_xlen == 64
+typedef uint64_t metal_xreg_t;
+#endif
+
+#if __riscv_flen == 32
+typedef uint32_t metal_freg_t;
+#elif __riscv_flen == 64
+typedef uint64_t metal_freg_t;
+#endif
+
+struct metal_register_file {
+ metal_xreg_t ra;
+ metal_xreg_t sp;
+ metal_xreg_t gp;
+ metal_xreg_t tp;
+
+ metal_xreg_t t0;
+ metal_xreg_t t1;
+ metal_xreg_t t2;
+
+ metal_xreg_t s0;
+ metal_xreg_t s1;
+
+ metal_xreg_t a0;
+ metal_xreg_t a1;
+ metal_xreg_t a2;
+ metal_xreg_t a3;
+ metal_xreg_t a4;
+ metal_xreg_t a5;
+#ifndef __riscv_32e
+ metal_xreg_t a6;
+ metal_xreg_t a7;
+
+ metal_xreg_t s2;
+ metal_xreg_t s3;
+ metal_xreg_t s4;
+ metal_xreg_t s5;
+ metal_xreg_t s6;
+ metal_xreg_t s7;
+ metal_xreg_t s8;
+ metal_xreg_t s9;
+ metal_xreg_t s10;
+ metal_xreg_t s11;
+
+ metal_xreg_t t3;
+ metal_xreg_t t4;
+ metal_xreg_t t5;
+ metal_xreg_t t6;
+#endif /* __riscv_32e */
+
+#ifdef __riscv_flen
+ metal_freg_t ft0;
+ metal_freg_t ft1;
+ metal_freg_t ft2;
+ metal_freg_t ft3;
+ metal_freg_t ft4;
+ metal_freg_t ft5;
+ metal_freg_t ft6;
+ metal_freg_t ft7;
+
+ metal_freg_t fs0;
+ metal_freg_t fs1;
+
+ metal_freg_t fa0;
+ metal_freg_t fa1;
+ metal_freg_t fa2;
+ metal_freg_t fa3;
+ metal_freg_t fa4;
+ metal_freg_t fa5;
+ metal_freg_t fa6;
+ metal_freg_t fa7;
+
+ metal_freg_t fs2;
+ metal_freg_t fs3;
+ metal_freg_t fs4;
+ metal_freg_t fs5;
+ metal_freg_t fs6;
+ metal_freg_t fs7;
+ metal_freg_t fs8;
+ metal_freg_t fs9;
+ metal_freg_t fs10;
+ metal_freg_t fs11;
+
+ metal_freg_t ft8;
+ metal_freg_t ft9;
+ metal_freg_t ft10;
+ metal_freg_t ft11;
+#endif /* __riscv_flen */
+};
+
+typedef void (*metal_privilege_entry_point_t)(void);
+
+void metal_privilege_drop_to_mode(enum metal_privilege_mode mode,
+ struct metal_register_file regfile,
+ metal_privilege_entry_point_t entry_point);
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/rtc.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/rtc.h
new file mode 100644
index 000000000..2e742ea38
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/rtc.h
@@ -0,0 +1,127 @@
+/* Copyright 2019 SiFive, Inc. */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__RTC_H
+#define METAL__RTC_H
+
+#include <stdint.h>
+
+/*!
+ * @file rtc.h
+ * @brief API for Real-Time Clocks
+ */
+
+struct metal_rtc;
+
+/*!
+ * @brief List of RTC run behaviors
+ */
+enum metal_rtc_run_option {
+ METAL_RTC_STOP = 0,
+ METAL_RTC_RUN,
+};
+
+struct metal_rtc_vtable {
+ uint64_t (*get_rate)(const struct metal_rtc *const rtc);
+ uint64_t (*set_rate)(const struct metal_rtc *const rtc, const uint64_t rate);
+ uint64_t (*get_compare)(const struct metal_rtc *const rtc);
+ uint64_t (*set_compare)(const struct metal_rtc *const rtc, const uint64_t compare);
+ uint64_t (*get_count)(const struct metal_rtc *const rtc);
+ uint64_t (*set_count)(const struct metal_rtc *const rtc, const uint64_t count);
+ int (*run)(const struct metal_rtc *const rtc, const enum metal_rtc_run_option option);
+ struct metal_interrupt *(*get_interrupt)(const struct metal_rtc *const rtc);
+ int (*get_interrupt_id)(const struct metal_rtc *const rtc);
+};
+
+/*!
+ * @brief Handle for a Real-Time Clock
+ */
+struct metal_rtc {
+ const struct metal_rtc_vtable *vtable;
+};
+
+/*!
+ * @brief Get the rate of the RTC
+ * @return The rate in Hz
+ */
+inline uint64_t metal_rtc_get_rate(const struct metal_rtc *const rtc) {
+ return rtc->vtable->get_rate(rtc);
+}
+
+/*!
+ * @brief Set (if possible) the rate of the RTC
+ * @return The new rate of the RTC (not guaranteed to be the same as requested)
+ */
+inline uint64_t metal_rtc_set_rate(const struct metal_rtc *const rtc, const uint64_t rate) {
+ return rtc->vtable->set_rate(rtc, rate);
+}
+
+/*!
+ * @brief Get the compare value of the RTC
+ * @return The compare value
+ */
+inline uint64_t metal_rtc_get_compare(const struct metal_rtc *const rtc) {
+ return rtc->vtable->get_compare(rtc);
+}
+
+/*!
+ * @brief Set the compare value of the RTC
+ * @return The set compare value (not guaranteed to be exactly the requested value)
+ *
+ * The RTC device might impose limits on the maximum compare value or the granularity
+ * of the compare value.
+ */
+inline uint64_t metal_rtc_set_compare(const struct metal_rtc *const rtc, const uint64_t compare) {
+ return rtc->vtable->set_compare(rtc, compare);
+}
+
+/*!
+ * @brief Get the current count of the RTC
+ * @return The count
+ */
+inline uint64_t metal_rtc_get_count(const struct metal_rtc *const rtc) {
+ return rtc->vtable->get_count(rtc);
+}
+
+/*!
+ * @brief Set the current count of the RTC
+ * @return The set value of the count (not guaranteed to be exactly the requested value)
+ *
+ * The RTC device might impose limits on the maximum value of the count
+ */
+inline uint64_t metal_rtc_set_count(const struct metal_rtc *const rtc, const uint64_t count) {
+ return rtc->vtable->set_count(rtc, count);
+}
+
+/*!
+ * @brief Start or stop the RTC
+ * @return 0 if the RTC was successfully started/stopped
+ */
+inline int metal_rtc_run(const struct metal_rtc *const rtc, const enum metal_rtc_run_option option) {
+ return rtc->vtable->run(rtc, option);
+}
+
+/*!
+ * @brief Get the interrupt handle for the RTC compare
+ * @return The interrupt handle
+ */
+inline struct metal_interrupt *metal_rtc_get_interrupt(const struct metal_rtc *const rtc) {
+ return rtc->vtable->get_interrupt(rtc);
+}
+
+/*!
+ * @brief Get the interrupt ID for the RTC compare
+ * @return The interrupt ID
+ */
+inline int metal_rtc_get_interrupt_id(const struct metal_rtc *const rtc) {
+ return rtc->vtable->get_interrupt_id(rtc);
+}
+
+/*!
+ * @brief Get the handle for an RTC by index
+ * @return The RTC handle, or NULL if none is available at that index
+ */
+struct metal_rtc *metal_rtc_get_device(int index);
+
+#endif
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/shutdown.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/shutdown.h
new file mode 100644
index 000000000..8d4020b5c
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/shutdown.h
@@ -0,0 +1,36 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__SHUTDOWN_H
+#define METAL__SHUTDOWN_H
+
+/*!
+ * @file shutdown.h
+ * @brief API for shutting down a machine
+ */
+
+struct __metal_shutdown;
+
+struct __metal_shutdown_vtable {
+ void (*exit)(const struct __metal_shutdown *sd, int code) __attribute__((noreturn));
+};
+
+struct __metal_shutdown {
+ const struct __metal_shutdown_vtable *vtable;
+};
+
+__inline__ void __metal_shutdown_exit(const struct __metal_shutdown *sd, int code) __attribute__((noreturn));
+__inline__ void __metal_shutdown_exit(const struct __metal_shutdown *sd, int code) { sd->vtable->exit(sd, code); }
+
+/*!
+ * @brief The public METAL shutdown interface
+ *
+ * Shuts down the machine, if the machine enables an interface for
+ * shutting down. When no interface is provided, will cause the machine
+ * to spin indefinitely.
+ *
+ * @param code The return code to set. 0 indicates program success.
+ */
+void metal_shutdown(int code) __attribute__((noreturn));
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/spi.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/spi.h
new file mode 100644
index 000000000..635e3c151
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/spi.h
@@ -0,0 +1,90 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__SPI_H
+#define METAL__SPI_H
+
+struct metal_spi;
+
+/*! @brief The configuration for a SPI transfer */
+struct metal_spi_config {
+ /*! @brief The protocol for the SPI transfer */
+ enum {
+ METAL_SPI_SINGLE,
+ METAL_SPI_DUAL,
+ METAL_SPI_QUAD
+ } protocol;
+
+ /*! @brief The polarity of the SPI transfer, equivalent to CPOL */
+ unsigned int polarity : 1;
+ /*! @brief The phase of the SPI transfer, equivalent to CPHA */
+ unsigned int phase : 1;
+ /*! @brief The endianness of the SPI transfer */
+ unsigned int little_endian : 1;
+ /*! @brief The active state of the chip select line */
+ unsigned int cs_active_high : 1;
+ /*! @brief The chip select ID to activate for the SPI transfer */
+ unsigned int csid;
+ /*! @brief The spi command frame number (cycles = num * frame_len) */
+ unsigned int cmd_num;
+ /*! @brief The spi address frame number */
+ unsigned int addr_num;
+ /*! @brief The spi dummy frame number */
+ unsigned int dummy_num;
+ /*! @brief The Dual/Quad spi mode selection.*/
+ enum {
+ MULTI_WIRE_ALL,
+ MULTI_WIRE_DATA_ONLY,
+ MULTI_WIRE_ADDR_DATA
+ } multi_wire;
+};
+
+struct metal_spi_vtable {
+ void (*init)(struct metal_spi *spi, int baud_rate);
+ int (*transfer)(struct metal_spi *spi, struct metal_spi_config *config, size_t len, char *tx_buf, char *rx_buf);
+ int (*get_baud_rate)(struct metal_spi *spi);
+ int (*set_baud_rate)(struct metal_spi *spi, int baud_rate);
+};
+
+/*! @brief A handle for a SPI device */
+struct metal_spi {
+ const struct metal_spi_vtable *vtable;
+};
+
+/*! @brief Get a handle for a SPI device
+ * @param device_num The index of the desired SPI device
+ * @return A handle to the SPI device, or NULL if the device does not exist*/
+struct metal_spi *metal_spi_get_device(unsigned int device_num);
+
+/*! @brief Initialize a SPI device with a certain baud rate
+ * @param spi The handle for the SPI device to initialize
+ * @param baud_rate The baud rate to set the SPI device to
+ */
+__inline__ void metal_spi_init(struct metal_spi *spi, int baud_rate) { spi->vtable->init(spi, baud_rate); }
+
+/*! @brief Perform a SPI transfer
+ * @param spi The handle for the SPI device to perform the transfer
+ * @param config The configuration for the SPI transfer.
+ * @param len The number of bytes to transfer
+ * @param tx_buf The buffer to send over the SPI bus. Must be len bytes long. If NULL, the SPI will transfer the value 0.
+ * @param rx_buf The buffer to receive data into. Must be len bytes long. If NULL, the SPI will ignore received bytes.
+ * @return 0 if the transfer succeeds
+ */
+__inline__ int metal_spi_transfer(struct metal_spi *spi, struct metal_spi_config *config, size_t len, char *tx_buf, char *rx_buf) {
+ return spi->vtable->transfer(spi, config, len, tx_buf, rx_buf);
+}
+
+/*! @brief Get the current baud rate of the SPI device
+ * @param spi The handle for the SPI device
+ * @return The baud rate in Hz
+ */
+__inline__ int metal_spi_get_baud_rate(struct metal_spi *spi) { return spi->vtable->get_baud_rate(spi); }
+
+/*! @brief Set the current baud rate of the SPI device
+ * @param spi The handle for the SPI device
+ * @param baud_rate The desired baud rate of the SPI device
+ * @return 0 if the baud rate is successfully changed
+ */
+__inline__ int metal_spi_set_baud_rate(struct metal_spi *spi, int baud_rate) { return spi->vtable->set_baud_rate(spi, baud_rate); }
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/switch.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/switch.h
new file mode 100644
index 000000000..61f0efe56
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/switch.h
@@ -0,0 +1,51 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__SWITCH_H
+#define METAL__SWITCH_H
+
+/*!
+ * @file switch.h
+ * @brief API for reading toggle switches
+ */
+
+#include <metal/interrupt.h>
+
+struct metal_switch;
+
+struct metal_switch_vtable {
+ int (*switch_exist)(struct metal_switch *sw, char *label);
+ struct metal_interrupt* (*interrupt_controller)(struct metal_switch *sw);
+ int (*get_interrupt_id)(struct metal_switch *sw);
+};
+
+/*!
+ * @brief A handle for a switch
+ */
+struct metal_switch {
+ const struct metal_switch_vtable *vtable;
+};
+
+/*!
+ * @brief Get a handle for a switch
+ * @param label The DeviceTree label for the desired switch
+ * @return A handle to the switch, or NULL if none is found for the requested label
+ */
+struct metal_switch* metal_switch_get(char *label);
+
+/*!
+ * @brief Get the interrupt controller for a switch
+ * @param sw The handle for the switch
+ * @return The interrupt controller handle
+ */
+__inline__ struct metal_interrupt*
+ metal_switch_interrupt_controller(struct metal_switch *sw) { return sw->vtable->interrupt_controller(sw); }
+
+/*!
+ * @brief Get the interrupt id for a switch
+ * @param sw The handle for the switch
+ * @return The interrupt ID for the switch
+ */
+__inline__ int metal_switch_get_interrupt_id(struct metal_switch *sw) { return sw->vtable->get_interrupt_id(sw); }
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/time.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/time.h
new file mode 100644
index 000000000..5c33b6f1b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/time.h
@@ -0,0 +1,18 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__TIME_H
+#define METAL__TIME_H
+
+#include <time.h>
+
+/*!
+ * @file time.h
+ * @brief API for dealing with time
+ */
+
+int metal_gettimeofday(struct timeval *tp, void *tzp);
+
+time_t metal_time(void);
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/timer.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/timer.h
new file mode 100644
index 000000000..eeae1f60b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/timer.h
@@ -0,0 +1,36 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__TIMER_H
+#define METAL__TIMER_H
+
+/*!
+ * @file timer.h
+ * @brief API for reading and manipulating the machine timer
+ */
+
+/*!
+ * @brief Read the machine cycle count
+ * @param hartid The hart ID to read the cycle count of
+ * @param cyclecount The variable to hold the value
+ * @return 0 upon success
+ */
+int metal_timer_get_cyclecount(int hartid, unsigned long long *cyclecount);
+
+/*!
+ * @brief Get the machine timebase frequency
+ * @param hartid The hart ID to read the timebase of
+ * @param timebase The variable to hold the value
+ * @return 0 upon success
+ */
+int metal_timer_get_timebase_frequency(int hartid, unsigned long long *timebase);
+
+/*!
+ * @brief Set the machine timer tick interval in seconds
+ * @param hartid The hart ID to read the timebase of
+ * @param second The number of seconds to set the tick interval to
+ * @return 0 upon success
+ */
+int metal_timer_set_tick(int hartid, int second);
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/tty.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/tty.h
new file mode 100644
index 000000000..fe4c000db
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/tty.h
@@ -0,0 +1,52 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__TTY_H
+#define METAL__TTY_H
+
+/*!
+ * @file tty.h
+ * @brief API for emulated serial teriminals
+ */
+
+/*!
+ * @brief Write a character to the default output device
+ *
+ * Write a character to the default output device, which for most
+ * targets is the UART serial port.
+ *
+ * putc() does CR/LF mapping.
+ * putc_raw() does not.
+ *
+ * @param c The character to write to the terminal
+ * @return 0 on success, or -1 on failure.
+ */
+int metal_tty_putc(int c);
+
+/*!
+ * @brief Write a raw character to the default output device
+ *
+ * Write a character to the default output device, which for most
+ * targets is the UART serial port.
+ *
+ * putc() does CR/LF mapping.
+ * putc_raw() does not.
+ *
+ * @param c The character to write to the terminal
+ * @return 0 on success, or -1 on failure.
+ */
+int metal_tty_putc_raw(int c);
+
+/*!
+ * @brief Get a byte from the default output device
+ *
+ * The default output device, is typically the UART serial port.
+ *
+ * This call is non-blocking, if nothing is ready c==-1
+ * if something is ready, then c=[0x00 to 0xff] byte value.
+ *
+ * @return 0 on success, or -1 on failure.
+ */
+int metal_tty_getc(int *c);
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/uart.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/uart.h
new file mode 100644
index 000000000..e9e4d0436
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/uart.h
@@ -0,0 +1,106 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__UART_H
+#define METAL__UART_H
+
+/*!
+ * @file uart.h
+ * @brief API for UART serial ports
+ */
+
+#include <metal/interrupt.h>
+
+struct metal_uart;
+#undef getc
+#undef putc
+struct metal_uart_vtable {
+ void (*init)(struct metal_uart *uart, int baud_rate);
+ int (*putc)(struct metal_uart *uart, int c);
+ int (*txready)(struct metal_uart *uart);
+ int (*getc)(struct metal_uart *uart, int *c);
+ int (*get_baud_rate)(struct metal_uart *uart);
+ int (*set_baud_rate)(struct metal_uart *uart, int baud_rate);
+ struct metal_interrupt* (*controller_interrupt)(struct metal_uart *uart);
+ int (*get_interrupt_id)(struct metal_uart *uart);
+};
+
+/*!
+ * @brief Handle for a UART serial device
+ */
+struct metal_uart {
+ const struct metal_uart_vtable *vtable;
+};
+
+/*!
+ * @brief Initialize UART device
+
+ * Initialize the UART device described by the UART handle. This function must be called before any
+ * other method on the UART can be invoked. It is invalid to initialize a UART more than once.
+ *
+ * @param uart The UART device handle
+ * @param baud_rate the baud rate to set the UART to
+ */
+__inline__ void metal_uart_init(struct metal_uart *uart, int baud_rate) { uart->vtable->init(uart, baud_rate); }
+
+/*!
+ * @brief Output a character over the UART
+ * @param uart The UART device handle
+ * @param c The character to send over the UART
+ * @return 0 upon success
+ */
+__inline__ int metal_uart_putc(struct metal_uart *uart, int c) { return uart->vtable->putc(uart, c); }
+
+/*!
+ * @brief Test, determine if tx output is blocked(full/busy)
+ * @param uart The UART device handle
+ * @return 0 not blocked
+ */
+__inline__ int metal_uart_txready(struct metal_uart *uart) { return uart->vtable->txready(uart); }
+
+/*!
+ * @brief Read a character sent over the UART
+ * @param uart The UART device handle
+ * @param c The varible to hold the read character
+ * @return 0 upon success
+ *
+ * If "c == -1" no char was ready.
+ * If "c != -1" then C == byte value (0x00 to 0xff)
+ */
+__inline__ int metal_uart_getc(struct metal_uart *uart, int *c) { return uart->vtable->getc(uart, c); }
+
+/*!
+ * @brief Get the baud rate of the UART peripheral
+ * @param uart The UART device handle
+ * @return The current baud rate of the UART
+ */
+__inline__ int metal_uart_get_baud_rate(struct metal_uart *uart) { return uart->vtable->get_baud_rate(uart); }
+
+/*!
+ * @brief Set the baud rate of the UART peripheral
+ * @param uart The UART device handle
+ * @param baud_rate The baud rate to configure
+ * @return the new baud rate of the UART
+ */
+__inline__ int metal_uart_set_baud_rate(struct metal_uart *uart, int baud_rate) { return uart->vtable->set_baud_rate(uart, baud_rate); }
+
+/*!
+ * @brief Get the interrupt controller of the UART peripheral
+ *
+ * Get the interrupt controller for the UART peripheral. The interrupt
+ * controller must be initialized before any interrupts can be registered
+ * or enabled with it.
+ *
+ * @param uart The UART device handle
+ * @return The handle for the UART interrupt controller
+ */
+__inline__ struct metal_interrupt* metal_uart_interrupt_controller(struct metal_uart *uart) { return uart->vtable->controller_interrupt(uart); }
+
+/*!
+ * @brief Get the interrupt ID of the UART controller
+ * @param uart The UART device handle
+ * @return The UART interrupt id
+ */
+__inline__ int metal_uart_get_interrupt_id(struct metal_uart *uart) { return uart->vtable->get_interrupt_id(uart); }
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/watchdog.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/watchdog.h
new file mode 100644
index 000000000..b5ff48697
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/watchdog.h
@@ -0,0 +1,163 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#ifndef METAL__WATCHDOG_H
+#define METAL__WATCHDOG_H
+
+/*!
+ * @file watchdog.h
+ *
+ * @brief API for configuring watchdog timers
+ */
+
+#include <metal/interrupt.h>
+
+struct metal_watchdog;
+
+/*!
+ * @brief List of watchdog timer count behaviors
+ */
+enum metal_watchdog_run_option {
+ METAL_WATCHDOG_STOP = 0, /*!< Stop the watchdog */
+ METAL_WATCHDOG_RUN_ALWAYS, /*!< Run the watchdog continuously, even during sleep */
+ METAL_WATCHDOG_RUN_AWAKE, /*!< Run the watchdog only while the CPU is awake */
+};
+
+/*!
+ * @brief List of behaviors when a watchdog triggers
+ */
+enum metal_watchdog_result {
+ METAL_WATCHDOG_NO_RESULT = 0, /*!< When the watchdog triggers, do nothing */
+ METAL_WATCHDOG_INTERRUPT, /*!< When the watchdog triggers, fire an interrupt */
+ METAL_WATCHDOG_FULL_RESET, /*!< When the watchdog triggers, cause a full system reset */
+};
+
+
+struct metal_watchdog_vtable {
+ int (*feed)(const struct metal_watchdog *const wdog);
+ long int (*get_rate)(const struct metal_watchdog *const wdog);
+ long int (*set_rate)(const struct metal_watchdog *const wdog, const long int rate);
+ long int (*get_timeout)(const struct metal_watchdog *const wdog);
+ long int (*set_timeout)(const struct metal_watchdog *const wdog, const long int timeout);
+ int (*set_result)(const struct metal_watchdog *const wdog,
+ const enum metal_watchdog_result result);
+ int (*run)(const struct metal_watchdog *const wdog,
+ const enum metal_watchdog_run_option option);
+ struct metal_interrupt *(*get_interrupt)(const struct metal_watchdog *const wdog);
+ int (*get_interrupt_id)(const struct metal_watchdog *const wdog);
+ int (*clear_interrupt)(const struct metal_watchdog *const wdog);
+};
+
+/*!
+ * @brief Handle for a Watchdog Timer
+ */
+struct metal_watchdog {
+ const struct metal_watchdog_vtable *vtable;
+};
+
+/*!
+ * @brief Feed the watchdog timer
+ */
+inline int metal_watchdog_feed(const struct metal_watchdog *const wdog)
+{
+ return wdog->vtable->feed(wdog);
+}
+
+/*!
+ * @brief Get the rate of the watchdog timer in Hz
+ *
+ * @return the rate of the watchdog timer
+ */
+inline long int metal_watchdog_get_rate(const struct metal_watchdog *const wdog)
+{
+ return wdog->vtable->get_rate(wdog);
+}
+
+/*!
+ * @brief Set the rate of the watchdog timer in Hz
+ *
+ * There is no guarantee that the new rate will match the requested rate.
+ *
+ * @return the new rate of the watchdog timer
+ */
+inline long int metal_watchdog_set_rate(const struct metal_watchdog *const wdog, const long int rate)
+{
+ return wdog->vtable->set_rate(wdog, rate);
+}
+
+/*!
+ * @brief Get the timeout of the watchdog timer
+ *
+ * @return the watchdog timeout value
+ */
+inline long int metal_watchdog_get_timeout(const struct metal_watchdog *const wdog)
+{
+ return wdog->vtable->get_timeout(wdog);
+}
+
+/*!
+ * @brief Set the timeout of the watchdog timer
+ *
+ * The set rate will be the minimimum of the requested and maximum supported rates.
+ *
+ * @return the new watchdog timeout value
+ */
+inline long int metal_watchdog_set_timeout(const struct metal_watchdog *const wdog, const long int timeout)
+{
+ return wdog->vtable->set_timeout(wdog, timeout);
+}
+
+/*!
+ * @brief Sets the result behavior of a watchdog timer timeout
+ *
+ * @return 0 if the requested result behavior is supported
+ */
+inline int metal_watchdog_set_result(const struct metal_watchdog *const wdog,
+ const enum metal_watchdog_result result)
+{
+ return wdog->vtable->set_result(wdog, result);
+}
+
+/*!
+ * @brief Set the run behavior of the watchdog
+ *
+ * Used to enable/disable the watchdog timer
+ *
+ * @return 0 if the watchdog was successfully started/stopped
+ */
+inline int metal_watchdog_run(const struct metal_watchdog *const wdog,
+ const enum metal_watchdog_run_option option)
+{
+ return wdog->vtable->run(wdog, option);
+}
+
+/*!
+ * @brief Get the interrupt controller for the watchdog interrupt
+ */
+inline struct metal_interrupt *metal_watchdog_get_interrupt(const struct metal_watchdog *const wdog)
+{
+ return wdog->vtable->get_interrupt(wdog);
+}
+
+/*!
+ * @Brief Get the interrupt id for the watchdog interrupt
+ */
+inline int metal_watchdog_get_interrupt_id(const struct metal_watchdog *const wdog)
+{
+ return wdog->vtable->get_interrupt_id(wdog);
+}
+
+/*!
+ * @brief Clear the watchdog interrupt
+ */
+inline int metal_watchdog_clear_interrupt(const struct metal_watchdog *const wdog)
+{
+ return wdog->vtable->clear_interrupt(wdog);
+}
+
+/*!
+ * @brief Get a watchdog handle
+ */
+struct metal_watchdog *metal_watchdog_get_device(const int index);
+
+#endif /* METAL__WATCHDOG_H */
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/button.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/button.c
new file mode 100644
index 000000000..efd645334
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/button.c
@@ -0,0 +1,27 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/button.h>
+#include <metal/machine.h>
+
+struct metal_button* metal_button_get (char *label)
+{
+ int i;
+ struct metal_button *button;
+
+ if ((__METAL_DT_MAX_BUTTONS == 0) || (label == NULL)) {
+ return NULL;
+ }
+
+ for (i = 0; i < __METAL_DT_MAX_BUTTONS; i++) {
+ button = (struct metal_button*)__metal_button_table[i];
+ if (button->vtable->button_exist(button, label)) {
+ return button;
+ }
+ }
+ return NULL;
+}
+
+extern __inline__ struct metal_interrupt*
+ metal_button_interrupt_controller(struct metal_button *button);
+extern __inline__ int metal_button_get_interrupt_id(struct metal_button *button);
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/cache.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/cache.c
new file mode 100644
index 000000000..024ba52ad
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/cache.c
@@ -0,0 +1,187 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/cache.h>
+#include <metal/machine.h>
+
+extern __inline__ void metal_cache_init(struct metal_cache *cache, int ways);
+extern __inline__ int metal_cache_get_enabled_ways(struct metal_cache *cache);
+extern __inline__ int metal_cache_set_enabled_ways(struct metal_cache *cache, int ways);
+
+int metal_dcache_l1_available(int hartid) {
+ switch (hartid) {
+ case 0:
+#ifdef __METAL_CPU_0_DCACHE_HANDLE
+ return __METAL_CPU_0_DCACHE_HANDLE;
+#endif
+ break;
+ case 1:
+#ifdef __METAL_CPU_1_DCACHE_HANDLE
+ return __METAL_CPU_1_DCACHE_HANDLE;
+#endif
+ break;
+ case 2:
+#ifdef __METAL_CPU_2_DCACHE_HANDLE
+ return __METAL_CPU_2_DCACHE_HANDLE;
+#endif
+ break;
+ case 3:
+#ifdef __METAL_CPU_3_DCACHE_HANDLE
+ return __METAL_CPU_3_DCACHE_HANDLE;
+#endif
+ break;
+ case 4:
+#ifdef __METAL_CPU_4_DCACHE_HANDLE
+ return __METAL_CPU_4_DCACHE_HANDLE;
+#endif
+ break;
+ case 5:
+#ifdef __METAL_CPU_5_DCACHE_HANDLE
+ return __METAL_CPU_5_DCACHE_HANDLE;
+#endif
+ break;
+ case 6:
+#ifdef __METAL_CPU_6_DCACHE_HANDLE
+ return __METAL_CPU_6_DCACHE_HANDLE;
+#endif
+ break;
+ case 7:
+#ifdef __METAL_CPU_7_DCACHE_HANDLE
+ return __METAL_CPU_7_DCACHE_HANDLE;
+#endif
+ break;
+ case 8:
+#ifdef __METAL_CPU_8_DCACHE_HANDLE
+ return __METAL_CPU_8_DCACHE_HANDLE;
+#endif
+ break;
+ }
+ return 0;
+}
+
+int metal_icache_l1_available(int hartid) {
+ switch (hartid) {
+ case 0:
+#ifdef __METAL_CPU_0_ICACHE_HANDLE
+ return __METAL_CPU_0_ICACHE_HANDLE;
+#endif
+ break;
+ case 1:
+#ifdef __METAL_CPU_1_ICACHE_HANDLE
+ return __METAL_CPU_1_ICACHE_HANDLE;
+#endif
+ break;
+ case 2:
+#ifdef __METAL_CPU_2_ICACHE_HANDLE
+ return __METAL_CPU_2_ICACHE_HANDLE;
+#endif
+ break;
+ case 3:
+#ifdef __METAL_CPU_3_ICACHE_HANDLE
+ return __METAL_CPU_3_ICACHE_HANDLE;
+#endif
+ break;
+ case 4:
+#ifdef __METAL_CPU_4_ICACHE_HANDLE
+ return __METAL_CPU_4_ICACHE_HANDLE;
+#endif
+ break;
+ case 5:
+#ifdef __METAL_CPU_5_ICACHE_HANDLE
+ return __METAL_CPU_5_ICACHE_HANDLE;
+#endif
+ break;
+ case 6:
+#ifdef __METAL_CPU_6_ICACHE_HANDLE
+ return __METAL_CPU_6_ICACHE_HANDLE;
+#endif
+ break;
+ case 7:
+#ifdef __METAL_CPU_7_ICACHE_HANDLE
+ return __METAL_CPU_7_ICACHE_HANDLE;
+#endif
+ break;
+ case 8:
+#ifdef __METAL_CPU_8_ICACHE_HANDLE
+ return __METAL_CPU_8_ICACHE_HANDLE;
+#endif
+ break;
+ }
+ return 0;
+}
+
+/*!
+ * @brief CFlush.D.L1 instruction is a custom instruction implemented as a
+ * state machine in L1 Data Cache (D$) with funct3=0, (for core with data caches)
+ * It is an I type: .insn i opcode, func3, rd, rs1, simm12(signed immediate 12bs)
+ * 31 28 27 24 23 20 19 16 15 12 11 8 7 4 3 0
+ * |--------|--------|--------|--------|--------|--------|--------|--------|
+ * +-------------+------------+----------+------+--------+-----------------+
+ * |sign immediate12b (simm12)| rs1 | func3| rd | opcode |
+ * |-1-1-1-1 -1-1-0-0 -0-0-0-0|-x-x-x-x-x|0-0-0-|-0-0-0-0|-0-1-1-1 -0-0-1-1|
+ * +--------------------------+----------+------+--------+-----------------+
+ * 31 -0x40 20 15 0 12 x0 7 0x73 0
+ * +--------+--------+--------+----------+------+--------+--------+--------+
+ * where,
+ * rs1 = 0x0, CFLUSH.D.L1 writes back and invalidates all lines in the L1 D$
+ * rs1 != x0, CFLUSH.D.L1 writes back and invalidates the L1 D$ line containing
+ * the virtual address in integer register rs1.
+ */
+void metal_dcache_l1_flush(int hartid, uintptr_t address)
+{
+ if (metal_dcache_l1_available(hartid)) {
+ // Using ‘.insn’ pseudo directive: '.insn i opcode, func3, rd, rs1, simm12'
+ __asm__ __volatile__ (".insn i 0x73, 0, x0, %0, -0x40" : : "r" (address));
+ __asm__ __volatile__ ("fence.i"); // FENCE
+ }
+}
+
+/*!
+ * @brief CDiscard.D.L1 instruction is a custom instruction implemented as a
+ * state machine in L1 Data Cache (D$) with funct3=0, (for core with data caches)
+ * It is an I type: .insn i opcode, func3, rd, rs1, simm12(signed immediate 12bs)
+ * 31 28 27 24 23 20 19 16 15 12 11 8 7 4 3 0
+ * |--------|--------|--------|--------|--------|--------|--------|--------|
+ * +-------------+------------+----------+------+--------+-----------------+
+ * |sign immediate12b (simm12)| rs1 | func3| rd | opcode |
+ * |-1-1-1-1 -1-1-0-0 -0-0-0-0|-x-x-x-x-x|0-0-0-|-0-0-0-0|-0-1-1-1 -0-0-1-1|
+ * +--------------------------+----------+------+--------+-----------------+
+ * 31 -0x3E 20 15 0 12 x0 7 0x73 0
+ * +--------+--------+--------+----------+------+--------+--------+--------+
+ * where,
+ * rs1 = 0x0, CDISCARD.D.L1 invalidates all lines in the L1 D$ with no writes back.
+ * rs1 != x0, CDISCARD.D.L1 invalidates the L1 D$ line containing the virtual address
+ * in integer register rs1, with no writes back.
+ */
+void metal_dcache_l1_discard(int hartid, uintptr_t address)
+{
+ if (metal_dcache_l1_available(hartid)) {
+ // Using ‘.insn’ pseudo directive: '.insn i opcode, func3, rd, rs1, simm12'
+ __asm__ __volatile__ (".insn i 0x73, 0, x0, %0, -0x3E" : : "r" (address));
+ __asm__ __volatile__ ("fence.i"); // FENCE
+ }
+}
+
+/*!
+ * @brief CFlush.I.L1 instruction is a custom instruction implemented as a state
+ * machine in L1 Instruction Cache (I$) with funct3=0, (for core with data caches)
+ * It is an I type: .insn i opcode, func3, rd, rs1, simm12(signed immediate 12bs)
+ * 31 28 27 24 23 20 19 16 15 12 11 8 7 4 3 0
+ * |--------|--------|--------|--------|--------|--------|--------|--------|
+ * +-------------+------------+----------+------+--------+-----------------+
+ * |sign immediate12b (simm12)| rs1 | func3| rd | opcode |
+ * |-1-1-1-1 -1-1-0-0 -0-0-0-0|-0-0-0-0-0|0-0-0-|-0-0-0-0|-0-1-1-1 -0-0-1-1|
+ * +--------------------------+----------+------+--------+-----------------+
+ * 31 -0x3F 20 15 0 12 x0 7 0x73 0
+ * +--------+--------+--------+----------+------+--------+--------+--------+
+ * CFLUSH.I.L1 invalidates all lines in the L1 I$.
+ */
+void metal_icache_l1_flush(int hartid)
+{
+ if (metal_icache_l1_available(hartid)) {
+ // Using ‘.insn’ pseudo directive: '.insn i opcode, func3, rd, rs1, simm12'
+ __asm__ __volatile__ (".insn i 0x73, 0, x0, x0, -0x3F" : : );
+ __asm__ __volatile__ ("fence.i"); // FENCE
+ }
+}
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/clock.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/clock.c
new file mode 100644
index 000000000..cc3f4dcf3
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/clock.c
@@ -0,0 +1,12 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/clock.h>
+
+extern __inline__ void _metal_clock_call_all_callbacks(const metal_clock_callback *const list);
+extern __inline__ metal_clock_callback *_metal_clock_append_to_callbacks(metal_clock_callback *list, metal_clock_callback *const cb);
+
+extern __inline__ long metal_clock_get_rate_hz(const struct metal_clock *clk);
+extern __inline__ long metal_clock_set_rate_hz(struct metal_clock *clk, long hz);
+extern __inline__ void metal_clock_register_post_rate_change_callback(struct metal_clock *clk, metal_clock_callback *cb);
+extern __inline__ void metal_clock_register_pre_rate_change_callback(struct metal_clock *clk, metal_clock_callback *cb);
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/cpu.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/cpu.c
new file mode 100644
index 000000000..25fda5de7
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/cpu.c
@@ -0,0 +1,59 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/cpu.h>
+#include <metal/machine.h>
+
+struct metal_cpu* metal_cpu_get(unsigned int hartid)
+{
+ if (hartid < __METAL_DT_MAX_HARTS) {
+ return (struct metal_cpu *)__metal_cpu_table[hartid];
+ }
+ return NULL;
+}
+
+int metal_cpu_get_current_hartid()
+{
+#ifdef __riscv
+ int mhartid;
+ __asm__ volatile("csrr %0, mhartid" : "=r" (mhartid));
+ return mhartid;
+#endif
+}
+
+int metal_cpu_get_num_harts()
+{
+ return __METAL_DT_MAX_HARTS;
+}
+
+extern __inline__ unsigned long long metal_cpu_get_timer(struct metal_cpu *cpu);
+
+extern __inline__ unsigned long long metal_cpu_get_timebase(struct metal_cpu *cpu);
+
+extern __inline__ unsigned long long metal_cpu_get_mtime(struct metal_cpu *cpu);
+
+extern __inline__ int metal_cpu_set_mtimecmp(struct metal_cpu *cpu, unsigned long long time);
+
+extern __inline__ struct metal_interrupt* metal_cpu_timer_interrupt_controller(struct metal_cpu *cpu);
+
+extern __inline__ int metal_cpu_timer_get_interrupt_id(struct metal_cpu *cpu);
+
+extern __inline__ struct metal_interrupt* metal_cpu_software_interrupt_controller(struct metal_cpu *cpu);
+
+extern __inline__ int metal_cpu_software_get_interrupt_id(struct metal_cpu *cpu);
+
+extern __inline__ int metal_cpu_software_set_ipi(struct metal_cpu *cpu, int hartid);
+
+extern __inline__ int metal_cpu_software_clear_ipi(struct metal_cpu *cpu, int hartid);
+
+extern __inline__ int metal_cpu_get_msip(struct metal_cpu *cpu, int hartid);
+
+extern __inline__ struct metal_interrupt* metal_cpu_interrupt_controller(struct metal_cpu *cpu);
+
+extern __inline__ int metal_cpu_exception_register(struct metal_cpu *cpu, int ecode, metal_exception_handler_t handler);
+
+extern __inline__ int metal_cpu_get_instruction_length(struct metal_cpu *cpu, uintptr_t epc);
+
+extern __inline__ uintptr_t metal_cpu_get_exception_pc(struct metal_cpu *cpu);
+
+extern __inline__ int metal_cpu_set_exception_pc(struct metal_cpu *cpu, uintptr_t epc);
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/fixed-clock.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/fixed-clock.c
new file mode 100644
index 000000000..92c61d023
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/fixed-clock.c
@@ -0,0 +1,29 @@
+/* Copyright 2018 SiFive, Inc. */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_FIXED_CLOCK
+
+#include <metal/drivers/fixed-clock.h>
+#include <stddef.h>
+#include <metal/machine.h>
+
+long __metal_driver_fixed_clock_get_rate_hz(const struct metal_clock *gclk)
+{
+ return __metal_driver_fixed_clock_rate(gclk);
+}
+
+long __metal_driver_fixed_clock_set_rate_hz(struct metal_clock *gclk, long target_hz)
+{
+ return __metal_driver_fixed_clock_get_rate_hz(gclk);
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_fixed_clock) = {
+ .clock.get_rate_hz = __metal_driver_fixed_clock_get_rate_hz,
+ .clock.set_rate_hz = __metal_driver_fixed_clock_set_rate_hz,
+};
+
+#endif /* METAL_FIXED_CLOCK */
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/fixed-factor-clock.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/fixed-factor-clock.c
new file mode 100644
index 000000000..57d83af87
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/fixed-factor-clock.c
@@ -0,0 +1,34 @@
+/* Copyright 2018 SiFive, Inc. */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_FIXED_FACTOR_CLOCK
+
+#include <metal/drivers/fixed-factor-clock.h>
+#include <stddef.h>
+#include <metal/machine.h>
+
+long __metal_driver_fixed_factor_clock_get_rate_hz(const struct metal_clock *gclk)
+{
+ struct metal_clock *parent = __metal_driver_fixed_factor_clock_parent(gclk);
+ long parent_rate = 1;
+ if(parent) {
+ parent_rate = parent->vtable->get_rate_hz(parent);
+ }
+
+ return __metal_driver_fixed_factor_clock_mult(gclk) * parent_rate / __metal_driver_fixed_factor_clock_div(gclk);
+}
+
+long __metal_driver_fixed_factor_clock_set_rate_hz(struct metal_clock *gclk, long target_hz)
+{
+ return __metal_driver_fixed_factor_clock_get_rate_hz(gclk);
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_fixed_factor_clock) = {
+ .clock.get_rate_hz = __metal_driver_fixed_factor_clock_get_rate_hz,
+ .clock.set_rate_hz = __metal_driver_fixed_factor_clock_set_rate_hz,
+};
+#endif /* METAL_FIXED_FACTOR_CLOCK */
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/inline.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/inline.c
new file mode 100644
index 000000000..50c0c5c21
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/inline.c
@@ -0,0 +1,5 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/inline.h>
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/riscv_clint0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/riscv_clint0.c
new file mode 100644
index 000000000..d0488b317
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/riscv_clint0.c
@@ -0,0 +1,283 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_RISCV_CLINT0
+
+#include <metal/io.h>
+#include <metal/cpu.h>
+#include <metal/drivers/riscv_clint0.h>
+#include <metal/machine.h>
+
+unsigned long long __metal_clint0_mtime_get (struct __metal_driver_riscv_clint0 *clint)
+{
+ __metal_io_u32 lo, hi;
+ unsigned long control_base = __metal_driver_sifive_clint0_control_base(&clint->controller);
+
+ /* Guard against rollover when reading */
+ do {
+ hi = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_RISCV_CLINT0_MTIME + 4));
+ lo = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_RISCV_CLINT0_MTIME));
+ } while (__METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_RISCV_CLINT0_MTIME + 4)) != hi);
+
+ return (((unsigned long long)hi) << 32) | lo;
+}
+
+int __metal_driver_riscv_clint0_mtimecmp_set(struct metal_interrupt *controller,
+ int hartid,
+ unsigned long long time)
+{
+ struct __metal_driver_riscv_clint0 *clint =
+ (struct __metal_driver_riscv_clint0 *)(controller);
+ unsigned long control_base = __metal_driver_sifive_clint0_control_base(&clint->controller);
+ /* Per spec, the RISC-V MTIME/MTIMECMP registers are 64 bit,
+ * and are NOT internally latched for multiword transfers.
+ * Need to be careful about sequencing to avoid triggering
+ * spurious interrupts: For that set the high word to a max
+ * value first.
+ */
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + (8 * hartid) + METAL_RISCV_CLINT0_MTIMECMP_BASE + 4)) = 0xFFFFFFFF;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + (8 * hartid) + METAL_RISCV_CLINT0_MTIMECMP_BASE)) = (__metal_io_u32)time;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + (8 * hartid) + METAL_RISCV_CLINT0_MTIMECMP_BASE + 4)) = (__metal_io_u32)(time >> 32);
+ return 0;
+}
+
+static struct metal_interrupt *_get_cpu_intc()
+{
+ int hartid = 0;
+ __asm__ volatile("csrr %[hartid], mhartid"
+ : [hartid] "=r" (hartid) :: "memory");
+
+ struct metal_cpu *cpu = metal_cpu_get(hartid);
+
+ return metal_cpu_interrupt_controller(cpu);
+}
+
+void __metal_driver_riscv_clint0_init (struct metal_interrupt *controller)
+{
+ int num_interrupts = __metal_driver_sifive_clint0_num_interrupts(controller);
+ struct __metal_driver_riscv_clint0 *clint =
+ (struct __metal_driver_riscv_clint0 *)(controller);
+
+ if ( !clint->init_done ) {
+ /* Register its interrupts with with parent controller, aka sw and timerto its default isr */
+ for (int i = 0; i < num_interrupts; i++) {
+ struct metal_interrupt *intc = __metal_driver_sifive_clint0_interrupt_parents(controller, i);
+ int line = __metal_driver_sifive_clint0_interrupt_lines(controller, i);
+ intc->vtable->interrupt_register(intc, line, NULL, controller);
+ }
+ clint->init_done = 1;
+ }
+}
+
+int __metal_driver_riscv_clint0_register (struct metal_interrupt *controller,
+ int id, metal_interrupt_handler_t isr,
+ void *priv)
+{
+ int rc = -1;
+ metal_vector_mode mode = __metal_controller_interrupt_vector_mode();
+ struct metal_interrupt *intc = NULL;
+ struct metal_interrupt *cpu_intc = _get_cpu_intc();
+ int num_interrupts = __metal_driver_sifive_clint0_num_interrupts(controller);
+
+ if ( (mode != METAL_VECTOR_MODE) && (mode != METAL_DIRECT_MODE) ) {
+ return rc;
+ }
+
+ for(int i = 0; i < num_interrupts; i++) {
+ int line = __metal_driver_sifive_clint0_interrupt_lines(controller, i);
+ intc = __metal_driver_sifive_clint0_interrupt_parents(controller, i);
+ if (cpu_intc == intc && id == line) {
+ break;
+ }
+ intc = NULL;
+ }
+
+ /* Register its interrupts with parent controller */
+ if (intc) {
+ rc = intc->vtable->interrupt_register(intc, id, isr, priv);
+ }
+ return rc;
+}
+
+int __metal_driver_riscv_clint0_vector_register (struct metal_interrupt *controller,
+ int id, metal_interrupt_vector_handler_t isr,
+ void *priv)
+{
+ /* Not supported. User can override the 'weak' handler with their own */
+ int rc = -1;
+ return rc;
+}
+
+metal_vector_mode __metal_driver_riscv_clint0_get_vector_mode (struct metal_interrupt *controller)
+{
+ return __metal_controller_interrupt_vector_mode();
+}
+
+int __metal_driver_riscv_clint0_set_vector_mode (struct metal_interrupt *controller, metal_vector_mode mode)
+{
+ int rc = -1;
+ struct metal_interrupt *intc = _get_cpu_intc();
+
+ if (intc) {
+ /* Valid vector modes are VECTOR and DIRECT, anything else is invalid (-1) */
+ switch (mode) {
+ case METAL_VECTOR_MODE:
+ case METAL_DIRECT_MODE:
+ rc = intc->vtable->interrupt_set_vector_mode(intc, mode);
+ break;
+ case METAL_HARDWARE_VECTOR_MODE:
+ case METAL_SELECTIVE_NONVECTOR_MODE:
+ case METAL_SELECTIVE_VECTOR_MODE:
+ break;
+ }
+ }
+ return rc;
+}
+
+int __metal_driver_riscv_clint0_enable (struct metal_interrupt *controller, int id)
+{
+ int rc = -1;
+
+ if ( id ) {
+ struct metal_interrupt *intc = NULL;
+ struct metal_interrupt *cpu_intc = _get_cpu_intc();
+ int num_interrupts = __metal_driver_sifive_clint0_num_interrupts(controller);
+
+ for(int i = 0; i < num_interrupts; i++) {
+ int line = __metal_driver_sifive_clint0_interrupt_lines(controller, i);
+ intc = __metal_driver_sifive_clint0_interrupt_parents(controller, i);
+ if(cpu_intc == intc && id == line) {
+ break;
+ }
+ intc = NULL;
+ }
+
+ /* Enable its interrupts with parent controller */
+ if (intc) {
+ rc = intc->vtable->interrupt_enable(intc, id);
+ }
+ }
+
+ return rc;
+}
+
+int __metal_driver_riscv_clint0_disable (struct metal_interrupt *controller, int id)
+{
+ int rc = -1;
+
+ if ( id ) {
+ struct metal_interrupt *intc = NULL;
+ struct metal_interrupt *cpu_intc = _get_cpu_intc();
+ int num_interrupts = __metal_driver_sifive_clint0_num_interrupts(controller);
+
+ for(int i = 0; i < num_interrupts; i++) {
+ int line = __metal_driver_sifive_clint0_interrupt_lines(controller, i);
+ intc = __metal_driver_sifive_clint0_interrupt_parents(controller, i);
+ if(cpu_intc == intc && id == line) {
+ break;
+ }
+ intc = NULL;
+ }
+
+ /* Disable its interrupts with parent controller */
+ if (intc) {
+ rc = intc->vtable->interrupt_disable(intc, id);
+ }
+ }
+
+ return rc;
+}
+
+int __metal_driver_riscv_clint0_command_request (struct metal_interrupt *controller,
+ int command, void *data)
+{
+ int hartid;
+ int rc = -1;
+ struct __metal_driver_riscv_clint0 *clint =
+ (struct __metal_driver_riscv_clint0 *)(controller);
+ unsigned long control_base = __metal_driver_sifive_clint0_control_base(controller);
+
+ switch (command) {
+ case METAL_TIMER_MTIME_GET:
+ if (data) {
+ *(unsigned long long *)data = __metal_clint0_mtime_get(clint);
+ rc = 0;
+ }
+ break;
+ case METAL_SOFTWARE_IPI_CLEAR:
+ if (data) {
+ hartid = *(int *)data;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ (hartid * 4))) = METAL_DISABLE;
+ rc = 0;
+ }
+ break;
+ case METAL_SOFTWARE_IPI_SET:
+ if (data) {
+ hartid = *(int *)data;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ (hartid * 4))) = METAL_ENABLE;
+ /* Callers of this function assume it's blocking, in the sense that
+ * the IPI is guarnteed to have been delivered before the function
+ * returns. We can't really guarnteed it's delivered, but we can
+ * read back the control register after writing it in at least an
+ * attempt to provide some semblence of ordering here. The fence
+ * ensures the read is order after the write -- it wouldn't be
+ * necessary under RVWMO because this is the same address, but we
+ * don't have an IO memory model so I'm being a bit overkill here.
+ */
+ __METAL_IO_FENCE(o,i);
+ rc = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ (hartid * 4)));
+ rc = 0;
+ }
+ break;
+ case METAL_SOFTWARE_MSIP_GET:
+ rc = 0;
+ if (data) {
+ hartid = *(int *)data;
+ rc = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ (hartid * 4)));
+ }
+ break;
+ default:
+ break;
+ }
+
+ return rc;
+}
+
+int __metal_driver_riscv_clint0_clear_interrupt (struct metal_interrupt *controller, int id)
+{
+ int hartid = metal_cpu_get_current_hartid();
+ return __metal_driver_riscv_clint0_command_request(controller,
+ METAL_SOFTWARE_IPI_CLEAR, &hartid);
+}
+
+int __metal_driver_riscv_clint0_set_interrupt (struct metal_interrupt *controller, int id)
+{
+ int hartid = metal_cpu_get_current_hartid();
+ return __metal_driver_riscv_clint0_command_request(controller,
+ METAL_SOFTWARE_IPI_SET, &hartid);
+}
+
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_riscv_clint0) = {
+ .clint_vtable.interrupt_init = __metal_driver_riscv_clint0_init,
+ .clint_vtable.interrupt_register = __metal_driver_riscv_clint0_register,
+ .clint_vtable.interrupt_vector_register = __metal_driver_riscv_clint0_vector_register,
+ .clint_vtable.interrupt_enable = __metal_driver_riscv_clint0_enable,
+ .clint_vtable.interrupt_disable = __metal_driver_riscv_clint0_disable,
+ .clint_vtable.interrupt_get_vector_mode = __metal_driver_riscv_clint0_get_vector_mode,
+ .clint_vtable.interrupt_set_vector_mode = __metal_driver_riscv_clint0_set_vector_mode,
+ .clint_vtable.interrupt_clear = __metal_driver_riscv_clint0_clear_interrupt,
+ .clint_vtable.interrupt_set = __metal_driver_riscv_clint0_set_interrupt,
+ .clint_vtable.command_request = __metal_driver_riscv_clint0_command_request,
+ .clint_vtable.mtimecmp_set = __metal_driver_riscv_clint0_mtimecmp_set,
+};
+
+#endif /* METAL_RISCV_CLINT0 */
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/riscv_cpu.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/riscv_cpu.c
new file mode 100644
index 000000000..b693f312a
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/riscv_cpu.c
@@ -0,0 +1,999 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <stdint.h>
+#include <metal/io.h>
+#include <metal/shutdown.h>
+#include <metal/machine.h>
+
+extern void __metal_vector_table();
+unsigned long long __metal_driver_cpu_mtime_get(struct metal_cpu *cpu);
+int __metal_driver_cpu_mtimecmp_set(struct metal_cpu *cpu, unsigned long long time);
+
+struct metal_cpu *__metal_driver_cpu_get(int hartid)
+{
+ if (hartid < __METAL_DT_MAX_HARTS) {
+ return &(__metal_cpu_table[hartid]->cpu);
+ }
+ return (struct metal_cpu *)NULL;
+}
+
+uintptr_t __metal_myhart_id (void)
+{
+ uintptr_t myhart;
+ __asm__ volatile ("csrr %0, mhartid" : "=r"(myhart));
+ return myhart;
+}
+
+void __metal_zero_memory (unsigned char *base, unsigned int size)
+{
+ volatile unsigned char *ptr;
+ for (ptr = base; ptr < (base + size); ptr++){
+ *ptr = 0;
+ }
+}
+
+void __metal_interrupt_global_enable (void) {
+ uintptr_t m;
+ __asm__ volatile ("csrrs %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT));
+}
+
+void __metal_interrupt_global_disable (void) {
+ uintptr_t m;
+ __asm__ volatile ("csrrc %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT));
+}
+
+void __metal_interrupt_software_enable (void) {
+ uintptr_t m;
+ __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_SW));
+}
+
+void __metal_interrupt_software_disable (void) {
+ uintptr_t m;
+ __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_SW));
+}
+
+void __metal_interrupt_timer_enable (void) {
+ uintptr_t m;
+ __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR));
+}
+
+void __metal_interrupt_timer_disable (void) {
+ uintptr_t m;
+ __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR));
+}
+
+void __metal_interrupt_external_enable (void) {
+ uintptr_t m;
+ __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_EXT));
+}
+
+void __metal_interrupt_external_disable (void) {
+ unsigned long m;
+ __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_EXT));
+}
+
+void __metal_interrupt_local_enable (int id) {
+ uintptr_t b = 1 << id;
+ uintptr_t m;
+ __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(b));
+}
+
+void __metal_interrupt_local_disable (int id) {
+ uintptr_t b = 1 << id;
+ uintptr_t m;
+ __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(b));
+}
+
+void __metal_default_exception_handler (struct metal_cpu *cpu, int ecode) {
+ metal_shutdown(100);
+}
+
+void __metal_default_interrupt_handler (int id, void *priv) {
+ metal_shutdown(200);
+}
+
+/* The metal_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_interrupt_vector_handler (void) {
+ metal_shutdown(300);
+}
+
+/* The metal_software_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_software_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_SW].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_SW].handler(METAL_INTERRUPT_ID_SW, priv);
+ }
+}
+
+void __metal_default_sw_handler (int id, void *priv) {
+ uintptr_t mcause;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ __asm__ volatile ("csrr %0, mcause" : "=r"(mcause));
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ intc->metal_exception_table[mcause & METAL_MCAUSE_CAUSE]((struct metal_cpu *)cpu, id);
+ }
+}
+
+/* The metal_timer_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_timer_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_TMR].handler(METAL_INTERRUPT_ID_TMR, priv);
+ }
+}
+
+void __metal_default_timer_handler (int id, void *priv) {
+ struct metal_cpu *cpu = __metal_driver_cpu_get(__metal_myhart_id());
+ unsigned long long time = __metal_driver_cpu_mtime_get(cpu);
+
+ /* Set a 10 cycle timer */
+ __metal_driver_cpu_mtimecmp_set(cpu, time + 10);
+}
+
+/* The metal_external_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_external_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_EXT].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_EXT].handler(METAL_INTERRUPT_ID_EXT, priv);
+ }
+}
+
+void __metal_exception_handler(void) __attribute__((interrupt, aligned(128)));
+void __metal_exception_handler (void) {
+ int id;
+ void *priv;
+ uintptr_t mcause, mepc, mtval, mtvec;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ __asm__ volatile ("csrr %0, mcause" : "=r"(mcause));
+ __asm__ volatile ("csrr %0, mepc" : "=r"(mepc));
+ __asm__ volatile ("csrr %0, mtval" : "=r"(mtval));
+ __asm__ volatile ("csrr %0, mtvec" : "=r"(mtvec));
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ id = mcause & METAL_MCAUSE_CAUSE;
+ if (mcause & METAL_MCAUSE_INTR) {
+ if ((id < METAL_INTERRUPT_ID_CSW) ||
+ ((mtvec & METAL_MTVEC_MASK) == METAL_MTVEC_DIRECT)) {
+ priv = intc->metal_int_table[id].exint_data;
+ intc->metal_int_table[id].handler(id, priv);
+ return;
+ }
+ if ((mtvec & METAL_MTVEC_MASK) == METAL_MTVEC_CLIC) {
+ uintptr_t mtvt;
+ metal_interrupt_handler_t mtvt_handler;
+
+ __asm__ volatile ("csrr %0, 0x307" : "=r"(mtvt));
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
+ mtvt_handler = (metal_interrupt_handler_t)*(uintptr_t *)mtvt;
+ mtvt_handler(id, priv);
+ return;
+ }
+ } else {
+ intc->metal_exception_table[id]((struct metal_cpu *)cpu, id);
+ }
+ }
+}
+
+/* The metal_lc0_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc0_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC0].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC0].handler(METAL_INTERRUPT_ID_LC0, priv);
+ }
+}
+
+/* The metal_lc1_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc1_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC1].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC1].handler(METAL_INTERRUPT_ID_LC1, priv);
+ }
+}
+
+/* The metal_lc2_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc2_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC2].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC2].handler(METAL_INTERRUPT_ID_LC2, priv);
+ }
+}
+
+/* The metal_lc3_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc3_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC3].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC3].handler(METAL_INTERRUPT_ID_LC3, priv);
+ }
+}
+
+/* The metal_lc4_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc4_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC4].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC4].handler(METAL_INTERRUPT_ID_LC4, priv);
+ }
+}
+
+/* The metal_lc5_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc5_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC5].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC5].handler(METAL_INTERRUPT_ID_LC5, priv);
+ }
+}
+
+/* The metal_lc6_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc6_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC6].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC6].handler(METAL_INTERRUPT_ID_LC6, priv);
+ }
+}
+
+/* The metal_lc7_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc7_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC7].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC7].handler(METAL_INTERRUPT_ID_LC7, priv);
+ }
+}
+
+/* The metal_lc8_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc8_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC8].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC8].handler(METAL_INTERRUPT_ID_LC8, priv);
+ }
+}
+
+/* The metal_lc9_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc9_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC9].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC9].handler(METAL_INTERRUPT_ID_LC9, priv);
+ }
+}
+
+/* The metal_lc10_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc10_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC10].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC10].handler(METAL_INTERRUPT_ID_LC10, priv);
+ }
+}
+
+/* The metal_lc11_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc11_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC11].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC11].handler(METAL_INTERRUPT_ID_LC11, priv);
+ }
+}
+
+/* The metal_lc12_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc12_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC12].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC12].handler(METAL_INTERRUPT_ID_LC12, priv);
+ }
+}
+
+/* The metal_lc13_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc13_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC13].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC13].handler(METAL_INTERRUPT_ID_LC13, priv);
+ }
+}
+
+/* The metal_lc14_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc14_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC14].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC14].handler(METAL_INTERRUPT_ID_LC14, priv);
+ }
+}
+
+/* The metal_lc15_interrupt_vector_handler() function can be redefined. */
+void __attribute__((weak, interrupt)) metal_lc15_interrupt_vector_handler (void) {
+ void *priv;
+ struct __metal_driver_riscv_cpu_intc *intc;
+ struct __metal_driver_cpu *cpu = __metal_cpu_table[__metal_myhart_id()];
+
+ if ( cpu ) {
+ intc = (struct __metal_driver_riscv_cpu_intc *)
+ __metal_driver_cpu_interrupt_controller((struct metal_cpu *)cpu);
+ priv = intc->metal_int_table[METAL_INTERRUPT_ID_LC15].exint_data;
+ intc->metal_int_table[METAL_INTERRUPT_ID_LC15].handler(METAL_INTERRUPT_ID_LC15, priv);
+ }
+}
+
+metal_vector_mode __metal_controller_interrupt_vector_mode (void)
+{
+ uintptr_t val;
+
+ asm volatile ("csrr %0, mtvec" : "=r"(val));
+ val &= METAL_MTVEC_MASK;
+
+ switch (val) {
+ case METAL_MTVEC_CLIC:
+ return METAL_SELECTIVE_VECTOR_MODE;
+ case METAL_MTVEC_CLIC_VECTORED:
+ return METAL_HARDWARE_VECTOR_MODE;
+ case METAL_MTVEC_VECTORED:
+ return METAL_VECTOR_MODE;
+ }
+ return METAL_DIRECT_MODE;
+}
+
+void __metal_controller_interrupt_vector (metal_vector_mode mode, void *vec_table)
+{
+ uintptr_t trap_entry, val;
+
+ __asm__ volatile ("csrr %0, mtvec" : "=r"(val));
+ val &= ~(METAL_MTVEC_CLIC_VECTORED | METAL_MTVEC_CLIC_RESERVED);
+ trap_entry = (uintptr_t)vec_table;
+
+ switch (mode) {
+ case METAL_SELECTIVE_NONVECTOR_MODE:
+ case METAL_SELECTIVE_VECTOR_MODE:
+ __asm__ volatile ("csrw 0x307, %0" :: "r"(trap_entry));
+ __asm__ volatile ("csrw mtvec, %0" :: "r"(val | METAL_MTVEC_CLIC));
+ break;
+ case METAL_HARDWARE_VECTOR_MODE:
+ __asm__ volatile ("csrw 0x307, %0" :: "r"(trap_entry));
+ __asm__ volatile ("csrw mtvec, %0" :: "r"(val | METAL_MTVEC_CLIC_VECTORED));
+ break;
+ case METAL_VECTOR_MODE:
+ __asm__ volatile ("csrw mtvec, %0" :: "r"(trap_entry | METAL_MTVEC_VECTORED));
+ break;
+ case METAL_DIRECT_MODE:
+ __asm__ volatile ("csrw mtvec, %0" :: "r"(trap_entry & ~METAL_MTVEC_CLIC_VECTORED));
+ break;
+ }
+}
+
+int __metal_valid_interrupt_id (int id)
+{
+ switch (id) {
+ case METAL_INTERRUPT_ID_SW:
+ case METAL_INTERRUPT_ID_TMR:
+ case METAL_INTERRUPT_ID_EXT:
+ case METAL_INTERRUPT_ID_LC0:
+ case METAL_INTERRUPT_ID_LC1:
+ case METAL_INTERRUPT_ID_LC2:
+ case METAL_INTERRUPT_ID_LC3:
+ case METAL_INTERRUPT_ID_LC4:
+ case METAL_INTERRUPT_ID_LC5:
+ case METAL_INTERRUPT_ID_LC6:
+ case METAL_INTERRUPT_ID_LC7:
+ case METAL_INTERRUPT_ID_LC8:
+ case METAL_INTERRUPT_ID_LC9:
+ case METAL_INTERRUPT_ID_LC10:
+ case METAL_INTERRUPT_ID_LC11:
+ case METAL_INTERRUPT_ID_LC12:
+ case METAL_INTERRUPT_ID_LC13:
+ case METAL_INTERRUPT_ID_LC14:
+ case METAL_INTERRUPT_ID_LC15:
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+int __metal_local_interrupt_enable (struct metal_interrupt *controller,
+ metal_interrupt_id_e id, int enable)
+{
+ int rc = 0;
+
+ if ( !controller) {
+ return -1;
+ }
+
+ switch (id) {
+ case METAL_INTERRUPT_ID_BASE:
+ if (enable) {
+ __metal_interrupt_global_enable();
+ } else {
+ __metal_interrupt_global_disable();
+ }
+ break;
+ case METAL_INTERRUPT_ID_SW:
+ if (enable) {
+ __metal_interrupt_software_enable();
+ } else {
+ __metal_interrupt_software_disable();
+ }
+ break;
+ case METAL_INTERRUPT_ID_TMR:
+ if (enable) {
+ __metal_interrupt_timer_enable();
+ } else {
+ __metal_interrupt_timer_disable();
+ }
+ break;
+ case METAL_INTERRUPT_ID_EXT:
+ if (enable) {
+ __metal_interrupt_external_enable();
+ } else {
+ __metal_interrupt_external_disable();
+ }
+ break;
+ case METAL_INTERRUPT_ID_LC0:
+ case METAL_INTERRUPT_ID_LC1:
+ case METAL_INTERRUPT_ID_LC2:
+ case METAL_INTERRUPT_ID_LC3:
+ case METAL_INTERRUPT_ID_LC4:
+ case METAL_INTERRUPT_ID_LC5:
+ case METAL_INTERRUPT_ID_LC6:
+ case METAL_INTERRUPT_ID_LC7:
+ case METAL_INTERRUPT_ID_LC8:
+ case METAL_INTERRUPT_ID_LC9:
+ case METAL_INTERRUPT_ID_LC10:
+ case METAL_INTERRUPT_ID_LC11:
+ case METAL_INTERRUPT_ID_LC12:
+ case METAL_INTERRUPT_ID_LC13:
+ case METAL_INTERRUPT_ID_LC14:
+ case METAL_INTERRUPT_ID_LC15:
+ if (enable) {
+ __metal_interrupt_local_enable(id);
+ } else {
+ __metal_interrupt_local_disable(id);
+ }
+ break;
+ default:
+ rc = -1;
+ }
+ return rc;
+}
+
+int __metal_exception_register (struct metal_interrupt *controller,
+ int ecode, metal_exception_handler_t isr)
+{
+ struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
+
+ if ((ecode < METAL_MAX_EXCEPTION_CODE) && isr) {
+ intc->metal_exception_table[ecode] = isr;
+ return 0;
+ }
+ return -1;
+}
+
+void __metal_driver_riscv_cpu_controller_interrupt_init (struct metal_interrupt *controller)
+{
+ struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
+ uintptr_t val;
+
+ if ( !intc->init_done ) {
+ /* Disable and clear all interrupt sources */
+ __asm__ volatile ("csrc mie, %0" :: "r"(-1));
+ __asm__ volatile ("csrc mip, %0" :: "r"(-1));
+
+ /* Read the misa CSR to determine if the delegation registers exist */
+ uintptr_t misa;
+ __asm__ volatile ("csrr %0, misa" : "=r" (misa));
+
+ /* The delegation CSRs exist if user mode interrupts (N extension) or
+ * supervisor mode (S extension) are supported */
+ if((misa & METAL_ISA_N_EXTENSIONS) || (misa & METAL_ISA_S_EXTENSIONS)) {
+ /* Disable interrupt and exception delegation */
+ __asm__ volatile ("csrc mideleg, %0" :: "r"(-1));
+ __asm__ volatile ("csrc medeleg, %0" :: "r"(-1));
+ }
+
+ /* The satp CSR exists if supervisor mode (S extension) is supported */
+ if(misa & METAL_ISA_S_EXTENSIONS) {
+ /* Clear the entire CSR to make sure that satp.MODE = 0 */
+ __asm__ volatile ("csrc satp, %0" :: "r"(-1));
+ }
+
+ /* Default to use direct interrupt, setup sw cb table*/
+ for (int i = 0; i < METAL_MAX_MI; i++) {
+ intc->metal_int_table[i].handler = NULL;
+ intc->metal_int_table[i].sub_int = NULL;
+ intc->metal_int_table[i].exint_data = NULL;
+ }
+ for (int i = 0; i < METAL_MAX_ME; i++) {
+ intc->metal_exception_table[i] = __metal_default_exception_handler;
+ }
+ __metal_controller_interrupt_vector(METAL_DIRECT_MODE, (void *)(uintptr_t)&__metal_exception_handler);
+ __asm__ volatile ("csrr %0, misa" : "=r"(val));
+ if (val & (METAL_ISA_D_EXTENSIONS | METAL_ISA_F_EXTENSIONS | METAL_ISA_Q_EXTENSIONS)) {
+ /* Floating point architecture, so turn on FP register saving*/
+ __asm__ volatile ("csrr %0, mstatus" : "=r"(val));
+ __asm__ volatile ("csrw mstatus, %0" :: "r"(val | METAL_MSTATUS_FS_INIT));
+ }
+ intc->init_done = 1;
+ }
+}
+
+int __metal_driver_riscv_cpu_controller_interrupt_register(struct metal_interrupt *controller,
+ int id, metal_interrupt_handler_t isr,
+ void *priv)
+{
+ int rc = 0;
+ struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
+
+ if ( !__metal_valid_interrupt_id(id) ) {
+ return -11;
+ }
+
+ if (isr) {
+ intc->metal_int_table[id].handler = isr;
+ intc->metal_int_table[id].exint_data = priv;
+ } else {
+ switch (id) {
+ case METAL_INTERRUPT_ID_SW:
+ intc->metal_int_table[id].handler = __metal_default_sw_handler;
+ intc->metal_int_table[id].sub_int = priv;
+ break;
+ case METAL_INTERRUPT_ID_TMR:
+ intc->metal_int_table[id].handler = __metal_default_timer_handler;
+ intc->metal_int_table[id].sub_int = priv;
+ break;
+ case METAL_INTERRUPT_ID_EXT:
+ case METAL_INTERRUPT_ID_LC0:
+ case METAL_INTERRUPT_ID_LC1:
+ case METAL_INTERRUPT_ID_LC2:
+ case METAL_INTERRUPT_ID_LC3:
+ case METAL_INTERRUPT_ID_LC4:
+ case METAL_INTERRUPT_ID_LC5:
+ case METAL_INTERRUPT_ID_LC6:
+ case METAL_INTERRUPT_ID_LC7:
+ case METAL_INTERRUPT_ID_LC8:
+ case METAL_INTERRUPT_ID_LC9:
+ case METAL_INTERRUPT_ID_LC10:
+ case METAL_INTERRUPT_ID_LC11:
+ case METAL_INTERRUPT_ID_LC12:
+ case METAL_INTERRUPT_ID_LC13:
+ case METAL_INTERRUPT_ID_LC14:
+ case METAL_INTERRUPT_ID_LC15:
+ intc->metal_int_table[id].handler = __metal_default_interrupt_handler;
+ intc->metal_int_table[id].sub_int = priv;
+ break;
+ default:
+ rc = -12;
+ }
+ }
+ return rc;
+}
+
+int __metal_driver_riscv_cpu_controller_interrupt_enable (struct metal_interrupt *controller,
+ int id)
+{
+ return __metal_local_interrupt_enable(controller, id, METAL_ENABLE);
+}
+
+int __metal_driver_riscv_cpu_controller_interrupt_disable (struct metal_interrupt *controller,
+ int id)
+{
+ return __metal_local_interrupt_enable(controller, id, METAL_DISABLE);
+}
+
+int __metal_driver_riscv_cpu_controller_interrupt_enable_vector(struct metal_interrupt *controller,
+ int id, metal_vector_mode mode)
+{
+ struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
+
+ if (id == METAL_INTERRUPT_ID_BASE) {
+ if (mode == METAL_DIRECT_MODE) {
+ __metal_controller_interrupt_vector(mode, (void *)(uintptr_t)&__metal_exception_handler);
+ return 0;
+ }
+ if (mode == METAL_VECTOR_MODE) {
+ __metal_controller_interrupt_vector(mode, (void *)&intc->metal_mtvec_table);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int __metal_driver_riscv_cpu_controller_interrupt_disable_vector(struct metal_interrupt *controller,
+ int id)
+{
+ if (id == METAL_INTERRUPT_ID_BASE) {
+ __metal_controller_interrupt_vector(METAL_DIRECT_MODE, (void *)(uintptr_t)&__metal_exception_handler);
+ return 0;
+ }
+ return -1;
+}
+
+metal_vector_mode __metal_driver_riscv_cpu_controller_get_vector_mode (struct metal_interrupt *controller)
+{
+ return __metal_controller_interrupt_vector_mode();
+}
+
+int __metal_driver_riscv_cpu_controller_set_vector_mode (struct metal_interrupt *controller,
+ metal_vector_mode mode)
+{
+ struct __metal_driver_riscv_cpu_intc *intc = (void *)(controller);
+ ( void ) intc;
+
+ if (mode == METAL_DIRECT_MODE) {
+ __metal_controller_interrupt_vector(mode, (void *)(uintptr_t)&__metal_exception_handler);
+ return 0;
+ }
+ if (mode == METAL_VECTOR_MODE) {
+ __metal_controller_interrupt_vector(mode, (void *)__metal_vector_table);
+ return 0;
+ }
+ return -1;
+}
+
+int __metal_driver_riscv_cpu_controller_command_request (struct metal_interrupt *controller,
+ int cmd, void *data)
+{
+ /* NOP for now, unless local interrupt lines the like of clic, clint, plic */
+ return 0;
+}
+
+/* CPU driver !!! */
+
+unsigned long long __metal_driver_cpu_mcycle_get(struct metal_cpu *cpu)
+{
+ unsigned long long val = 0;
+
+#if __riscv_xlen == 32
+ unsigned long hi, hi1, lo;
+
+ __asm__ volatile ("csrr %0, mcycleh" : "=r"(hi));
+ __asm__ volatile ("csrr %0, mcycle" : "=r"(lo));
+ __asm__ volatile ("csrr %0, mcycleh" : "=r"(hi1));
+ if (hi == hi1) {
+ val = ((unsigned long long)hi << 32) | lo;
+ }
+#else
+ __asm__ volatile ("csrr %0, mcycle" : "=r"(val));
+#endif
+
+ return val;
+}
+
+unsigned long long __metal_driver_cpu_timebase_get(struct metal_cpu *cpu)
+{
+ int timebase;
+ if (!cpu) {
+ return 0;
+ }
+
+ timebase = __metal_driver_cpu_timebase((struct metal_cpu *)cpu);
+ return timebase;
+}
+
+unsigned long long __metal_driver_cpu_mtime_get (struct metal_cpu *cpu)
+{
+ unsigned long long time = 0;
+ struct metal_interrupt *tmr_intc;
+ struct __metal_driver_riscv_cpu_intc *intc =
+ (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
+
+ if (intc) {
+ tmr_intc = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].sub_int;
+ if (tmr_intc) {
+ tmr_intc->vtable->command_request(tmr_intc,
+ METAL_TIMER_MTIME_GET, &time);
+ }
+ }
+ return time;
+}
+
+int __metal_driver_cpu_mtimecmp_set (struct metal_cpu *cpu, unsigned long long time)
+{
+ int rc = -1;
+ struct metal_interrupt *tmr_intc;
+ struct __metal_driver_riscv_cpu_intc *intc =
+ (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
+
+ if (intc) {
+ tmr_intc = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].sub_int;
+ if (tmr_intc) {
+ rc = tmr_intc->vtable->mtimecmp_set(tmr_intc,
+ __metal_driver_cpu_hartid(cpu),
+ time);
+ }
+ }
+ return rc;
+}
+
+struct metal_interrupt *
+__metal_driver_cpu_timer_controller_interrupt(struct metal_cpu *cpu)
+{
+#ifdef __METAL_DT_RISCV_CLINT0_HANDLE
+ return __METAL_DT_RISCV_CLINT0_HANDLE;
+#else
+#ifdef __METAL_DT_SIFIVE_CLIC0_HANDLE
+ return __METAL_DT_SIFIVE_CLIC0_HANDLE;
+#else
+#pragma message("There is no interrupt controller for Timer interrupt")
+ return NULL;
+#endif
+#endif
+}
+
+int __metal_driver_cpu_get_timer_interrupt_id(struct metal_cpu *cpu)
+{
+ return METAL_INTERRUPT_ID_TMR;
+}
+
+struct metal_interrupt *
+__metal_driver_cpu_sw_controller_interrupt(struct metal_cpu *cpu)
+{
+#ifdef __METAL_DT_RISCV_CLINT0_HANDLE
+ return __METAL_DT_RISCV_CLINT0_HANDLE;
+#else
+#ifdef __METAL_DT_SIFIVE_CLIC0_HANDLE
+ return __METAL_DT_SIFIVE_CLIC0_HANDLE;
+#else
+#pragma message("There is no interrupt controller for Software interrupt")
+ return NULL;
+#endif
+#endif
+}
+
+int __metal_driver_cpu_get_sw_interrupt_id(struct metal_cpu *cpu)
+{
+ return METAL_INTERRUPT_ID_SW;
+}
+
+int __metal_driver_cpu_set_sw_ipi (struct metal_cpu *cpu, int hartid)
+{
+ int rc = -1;
+ struct metal_interrupt *sw_intc;
+ struct __metal_driver_riscv_cpu_intc *intc =
+ (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
+
+ if (intc) {
+ sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
+ if (sw_intc) {
+ rc = sw_intc->vtable->command_request(sw_intc,
+ METAL_SOFTWARE_IPI_SET, &hartid);
+ }
+ }
+ return rc;
+}
+
+int __metal_driver_cpu_clear_sw_ipi (struct metal_cpu *cpu, int hartid)
+{
+ int rc = -1;
+ struct metal_interrupt *sw_intc;
+ struct __metal_driver_riscv_cpu_intc *intc =
+ (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
+
+ if (intc) {
+ sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
+ if (sw_intc) {
+ rc = sw_intc->vtable->command_request(sw_intc,
+ METAL_SOFTWARE_IPI_CLEAR, &hartid);
+ }
+ }
+ return rc;
+}
+
+int __metal_driver_cpu_get_msip (struct metal_cpu *cpu, int hartid)
+{
+ int rc = 0;
+ struct metal_interrupt *sw_intc;
+ struct __metal_driver_riscv_cpu_intc *intc =
+ (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
+
+ if (intc) {
+ sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int;
+ if (sw_intc) {
+ rc = sw_intc->vtable->command_request(sw_intc,
+ METAL_SOFTWARE_MSIP_GET, &hartid);
+ }
+ }
+ return rc;
+}
+
+struct metal_interrupt *
+__metal_driver_cpu_controller_interrupt(struct metal_cpu *cpu)
+{
+ return __metal_driver_cpu_interrupt_controller(cpu);
+}
+
+int __metal_driver_cpu_enable_interrupt(struct metal_cpu *cpu, void *priv)
+{
+ if ( __metal_driver_cpu_interrupt_controller(cpu) ) {
+ /* Only support machine mode for now */
+ __metal_interrupt_global_enable();
+ return 0;
+ }
+ return -1;
+}
+
+int __metal_driver_cpu_disable_interrupt(struct metal_cpu *cpu, void *priv)
+{
+ if ( __metal_driver_cpu_interrupt_controller(cpu) ) {
+ /* Only support machine mode for now */
+ __metal_interrupt_global_disable();
+ return 0;
+ }
+ return -1;
+}
+
+int __metal_driver_cpu_exception_register(struct metal_cpu *cpu, int ecode,
+ metal_exception_handler_t isr)
+{
+ struct __metal_driver_riscv_cpu_intc *intc =
+ (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu);
+
+ if (intc) {
+ return __metal_exception_register((struct metal_interrupt *)intc, ecode, isr);
+ }
+ return -1;
+}
+
+int __metal_driver_cpu_get_instruction_length(struct metal_cpu *cpu, uintptr_t epc)
+{
+ /**
+ * Per ISA compressed instruction has last two bits of opcode set.
+ * The encoding '00' '01' '10' are used for compressed instruction.
+ * Only enconding '11' isn't regarded as compressed instruction (>16b).
+ */
+ return ((*(unsigned short*)epc & METAL_INSN_LENGTH_MASK)
+ == METAL_INSN_NOT_COMPRESSED) ? 4 : 2;
+}
+
+uintptr_t __metal_driver_cpu_get_exception_pc(struct metal_cpu *cpu)
+{
+ uintptr_t mepc;
+ __asm__ volatile ("csrr %0, mepc" : "=r"(mepc));
+ return mepc;
+}
+
+int __metal_driver_cpu_set_exception_pc(struct metal_cpu *cpu, uintptr_t mepc)
+{
+ __asm__ volatile ("csrw mepc, %0" :: "r"(mepc));
+ return 0;
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_riscv_cpu_intc) = {
+ .controller_vtable.interrupt_init = __metal_driver_riscv_cpu_controller_interrupt_init,
+ .controller_vtable.interrupt_register = __metal_driver_riscv_cpu_controller_interrupt_register,
+ .controller_vtable.interrupt_enable = __metal_driver_riscv_cpu_controller_interrupt_enable,
+ .controller_vtable.interrupt_disable = __metal_driver_riscv_cpu_controller_interrupt_disable,
+ .controller_vtable.interrupt_get_vector_mode = __metal_driver_riscv_cpu_controller_get_vector_mode,
+ .controller_vtable.interrupt_set_vector_mode = __metal_driver_riscv_cpu_controller_set_vector_mode,
+ .controller_vtable.command_request = __metal_driver_riscv_cpu_controller_command_request,
+};
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_cpu) = {
+ .cpu_vtable.mcycle_get = __metal_driver_cpu_mcycle_get,
+ .cpu_vtable.timebase_get = __metal_driver_cpu_timebase_get,
+ .cpu_vtable.mtime_get = __metal_driver_cpu_mtime_get,
+ .cpu_vtable.mtimecmp_set = __metal_driver_cpu_mtimecmp_set,
+ .cpu_vtable.tmr_controller_interrupt = __metal_driver_cpu_timer_controller_interrupt,
+ .cpu_vtable.get_tmr_interrupt_id = __metal_driver_cpu_get_timer_interrupt_id,
+ .cpu_vtable.sw_controller_interrupt = __metal_driver_cpu_sw_controller_interrupt,
+ .cpu_vtable.get_sw_interrupt_id = __metal_driver_cpu_get_sw_interrupt_id,
+ .cpu_vtable.set_sw_ipi = __metal_driver_cpu_set_sw_ipi,
+ .cpu_vtable.clear_sw_ipi = __metal_driver_cpu_clear_sw_ipi,
+ .cpu_vtable.get_msip = __metal_driver_cpu_get_msip,
+ .cpu_vtable.controller_interrupt = __metal_driver_cpu_controller_interrupt,
+ .cpu_vtable.exception_register = __metal_driver_cpu_exception_register,
+ .cpu_vtable.get_ilen = __metal_driver_cpu_get_instruction_length,
+ .cpu_vtable.get_epc = __metal_driver_cpu_get_exception_pc,
+ .cpu_vtable.set_epc = __metal_driver_cpu_set_exception_pc,
+};
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/riscv_plic0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/riscv_plic0.c
new file mode 100644
index 000000000..3272f1c66
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/riscv_plic0.c
@@ -0,0 +1,195 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_RISCV_PLIC0
+
+#include <metal/io.h>
+#include <metal/shutdown.h>
+#include <metal/drivers/riscv_plic0.h>
+#include <metal/machine.h>
+
+unsigned int __metal_plic0_claim_interrupt (struct __metal_driver_riscv_plic0 *plic)
+{
+ unsigned long control_base = __metal_driver_sifive_plic0_control_base((struct metal_interrupt *)plic);
+ return __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ METAL_RISCV_PLIC0_CLAIM));
+}
+
+void __metal_plic0_complete_interrupt(struct __metal_driver_riscv_plic0 *plic,
+ unsigned int id)
+{
+ unsigned long control_base = __metal_driver_sifive_plic0_control_base((struct metal_interrupt *)plic);
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ METAL_RISCV_PLIC0_CLAIM)) = id;
+}
+
+int __metal_plic0_set_threshold(struct metal_interrupt *controller, unsigned int threshold)
+{
+ unsigned long control_base = __metal_driver_sifive_plic0_control_base(controller);
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ METAL_RISCV_PLIC0_THRESHOLD)) = threshold;
+ return 0;
+}
+
+unsigned int __metal_plic0_get_threshold(struct metal_interrupt *controller)
+{
+ unsigned long control_base = __metal_driver_sifive_plic0_control_base(controller);
+
+ return __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ METAL_RISCV_PLIC0_THRESHOLD));
+}
+
+int __metal_plic0_set_priority(struct metal_interrupt *controller, int id, unsigned int priority)
+{
+ unsigned long control_base = __metal_driver_sifive_plic0_control_base((struct metal_interrupt *)controller);
+ unsigned int max_priority = __metal_driver_sifive_plic0_max_priority((struct metal_interrupt *)controller);
+ if ( (max_priority) && (priority < max_priority) ) {
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ METAL_RISCV_PLIC0_PRIORITY_BASE +
+ (id << METAL_PLIC_SOURCE_PRIORITY_SHIFT))) = priority;
+ return 0;
+ }
+ return -1;
+}
+
+unsigned int __metal_plic0_get_priority(struct metal_interrupt *controller, int id)
+{
+ unsigned long control_base = __metal_driver_sifive_plic0_control_base(controller);
+
+ return __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ METAL_RISCV_PLIC0_PRIORITY_BASE +
+ (id << METAL_PLIC_SOURCE_PRIORITY_SHIFT)));
+}
+
+void __metal_plic0_enable(struct __metal_driver_riscv_plic0 *plic, int id, int enable)
+{
+ unsigned int current;
+ unsigned long control_base = __metal_driver_sifive_plic0_control_base((struct metal_interrupt *)plic);
+
+ current = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ METAL_RISCV_PLIC0_ENABLE_BASE +
+ (id >> METAL_PLIC_SOURCE_SHIFT) * 4));
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ METAL_RISCV_PLIC0_ENABLE_BASE +
+ ((id >> METAL_PLIC_SOURCE_SHIFT) * 4))) =
+ enable ? (current | (1 << (id & METAL_PLIC_SOURCE_MASK)))
+ : (current & ~(1 << (id & METAL_PLIC_SOURCE_MASK)));
+}
+
+void __metal_plic0_default_handler (int id, void *priv) {
+ metal_shutdown(300);
+}
+
+void __metal_plic0_handler (int id, void *priv)
+{
+ struct __metal_driver_riscv_plic0 *plic = priv;
+ unsigned int idx = __metal_plic0_claim_interrupt(plic);
+ unsigned int num_interrupts = __metal_driver_sifive_plic0_num_interrupts((struct metal_interrupt *)plic);
+
+ if ( (idx < num_interrupts) && (plic->metal_exint_table[idx]) ) {
+ plic->metal_exint_table[idx](idx,
+ plic->metal_exdata_table[idx].exint_data);
+ }
+
+ __metal_plic0_complete_interrupt(plic, idx);
+}
+
+void __metal_driver_riscv_plic0_init (struct metal_interrupt *controller)
+{
+ struct __metal_driver_riscv_plic0 *plic = (void *)(controller);
+
+ if ( !plic->init_done ) {
+ int num_interrupts, line;
+ struct metal_interrupt *intc;
+
+ for(int parent = 0; parent < __METAL_PLIC_NUM_PARENTS; parent++) {
+ num_interrupts = __metal_driver_sifive_plic0_num_interrupts(controller);
+ intc = __metal_driver_sifive_plic0_interrupt_parents(controller, parent);
+ line = __metal_driver_sifive_plic0_interrupt_lines(controller, parent);
+
+ /* Initialize ist parent controller, aka cpu_intc. */
+ intc->vtable->interrupt_init(intc);
+
+ for (int i = 0; i < num_interrupts; i++) {
+ __metal_plic0_enable(plic, i, METAL_DISABLE);
+ __metal_plic0_set_priority(controller, i, 0);
+ plic->metal_exint_table[i] = NULL;
+ plic->metal_exdata_table[i].sub_int = NULL;
+ plic->metal_exdata_table[i].exint_data = NULL;
+ }
+
+ __metal_plic0_set_threshold(controller, 0);
+
+ /* Register plic (ext) interrupt with with parent controller */
+ intc->vtable->interrupt_register(intc, line, NULL, plic);
+ /* Register plic handler for dispatching its device interrupts */
+ intc->vtable->interrupt_register(intc, line, __metal_plic0_handler, plic);
+ /* Enable plic (ext) interrupt with with parent controller */
+ intc->vtable->interrupt_enable(intc, line);
+ }
+ plic->init_done = 1;
+ }
+}
+
+int __metal_driver_riscv_plic0_register (struct metal_interrupt *controller,
+ int id, metal_interrupt_handler_t isr,
+ void *priv)
+{
+ struct __metal_driver_riscv_plic0 *plic = (void *)(controller);
+
+ if (id >= __metal_driver_sifive_plic0_num_interrupts(controller)) {
+ return -1;
+ }
+
+ if (isr) {
+ __metal_plic0_set_priority(controller, id, 2);
+ plic->metal_exint_table[id] = isr;
+ plic->metal_exdata_table[id].exint_data = priv;
+ } else {
+ __metal_plic0_set_priority(controller, id, 1);
+ plic->metal_exint_table[id] = __metal_plic0_default_handler;
+ plic->metal_exdata_table[id].sub_int = priv;
+ }
+
+ return 0;
+}
+
+int __metal_driver_riscv_plic0_enable (struct metal_interrupt *controller, int id)
+{
+ struct __metal_driver_riscv_plic0 *plic = (void *)(controller);
+
+ if (id >= __metal_driver_sifive_plic0_num_interrupts(controller)) {
+ return -1;
+ }
+
+ __metal_plic0_enable(plic, id, METAL_ENABLE);
+ return 0;
+}
+
+int __metal_driver_riscv_plic0_disable (struct metal_interrupt *controller, int id)
+{
+ struct __metal_driver_riscv_plic0 *plic = (void *)(controller);
+
+ if (id >= __metal_driver_sifive_plic0_num_interrupts(controller)) {
+ return -1;
+ }
+ __metal_plic0_enable(plic, id, METAL_DISABLE);
+ return 0;
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_riscv_plic0) = {
+ .plic_vtable.interrupt_init = __metal_driver_riscv_plic0_init,
+ .plic_vtable.interrupt_register = __metal_driver_riscv_plic0_register,
+ .plic_vtable.interrupt_enable = __metal_driver_riscv_plic0_enable,
+ .plic_vtable.interrupt_disable = __metal_driver_riscv_plic0_disable,
+ .plic_vtable.interrupt_get_threshold = __metal_plic0_get_threshold,
+ .plic_vtable.interrupt_set_threshold = __metal_plic0_set_threshold,
+ .plic_vtable.interrupt_get_priority = __metal_plic0_get_priority,
+ .plic_vtable.interrupt_set_priority = __metal_plic0_set_priority,
+};
+
+#endif /* METAL_RISCV_PLIC0 */
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_ccache0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_ccache0.c
new file mode 100644
index 000000000..6f8723735
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_ccache0.c
@@ -0,0 +1,84 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_CCACHE0
+
+#include <stdint.h>
+#include <metal/io.h>
+#include <metal/drivers/sifive_ccache0.h>
+#include <metal/machine.h>
+
+#define L2_CONFIG_WAYS_SHIFT 8
+#define L2_CONFIG_WAYS_MASK (0xFF << L2_CONFIG_WAYS_SHIFT)
+
+void __metal_driver_sifive_ccache0_init(struct metal_cache *l2, int ways);
+
+static void metal_driver_sifive_ccache0_init(void) __attribute__((constructor));
+static void metal_driver_sifive_ccache0_init(void)
+{
+#ifdef __METAL_DT_SIFIVE_CCACHE0_HANDLE
+ /* Get the handle for the L2 cache controller */
+ struct metal_cache *l2 = __METAL_DT_SIFIVE_CCACHE0_HANDLE;
+ if(!l2) {
+ return;
+ }
+
+ /* Get the number of available ways per bank */
+ unsigned long control_base = __metal_driver_sifive_ccache0_control_base(l2);
+ uint32_t ways = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_CCACHE0_CONFIG));
+ ways = ((ways & L2_CONFIG_WAYS_MASK) >> L2_CONFIG_WAYS_SHIFT);
+
+ /* Enable all the ways */
+ __metal_driver_sifive_ccache0_init(l2, ways);
+#endif
+}
+
+void __metal_driver_sifive_ccache0_init(struct metal_cache *l2, int ways)
+{
+ metal_cache_set_enabled_ways(l2, ways);
+}
+
+int __metal_driver_sifive_ccache0_get_enabled_ways(struct metal_cache *cache)
+{
+ unsigned long control_base = __metal_driver_sifive_ccache0_control_base(cache);
+
+ uint32_t way_enable = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_CCACHE0_WAYENABLE));
+
+ /* The stored number is the index, so add one */
+ return (0xFF & way_enable) + 1;
+}
+
+int __metal_driver_sifive_ccache0_set_enabled_ways(struct metal_cache *cache, int ways)
+{
+ unsigned long control_base = __metal_driver_sifive_ccache0_control_base(cache);
+
+ /* We can't decrease the number of enabled ways */
+ if(metal_cache_get_enabled_ways(cache) > ways) {
+ return -2;
+ }
+
+ /* The stored value is the index, so subtract one */
+ uint32_t value = 0xFF & (ways - 1);
+
+ /* Set the number of enabled ways */
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_CCACHE0_WAYENABLE)) = value;
+
+ /* Make sure the number of ways was set correctly */
+ if(metal_cache_get_enabled_ways(cache) != ways) {
+ return -3;
+ }
+
+ return 0;
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_ccache0) = {
+ .cache.init = __metal_driver_sifive_ccache0_init,
+ .cache.get_enabled_ways = __metal_driver_sifive_ccache0_get_enabled_ways,
+ .cache.set_enabled_ways = __metal_driver_sifive_ccache0_set_enabled_ways,
+};
+
+#endif
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_clic0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_clic0.c
new file mode 100644
index 000000000..12c3dac06
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_clic0.c
@@ -0,0 +1,736 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_CLIC0
+
+#include <stdint.h>
+#include <metal/io.h>
+#include <metal/shutdown.h>
+#include <metal/drivers/sifive_clic0.h>
+#include <metal/machine.h>
+
+typedef enum metal_clic_vector_{
+ METAL_CLIC_NONVECTOR = 0,
+ METAL_CLIC_VECTORED = 1
+} metal_clic_vector;
+
+struct __metal_clic_cfg {
+ unsigned char : 1,
+ nmbits : 2,
+ nlbits : 4,
+ nvbit : 1;
+};
+
+const struct __metal_clic_cfg __metal_clic_defaultcfg = {
+ .nmbits = METAL_INTR_PRIV_M_MODE,
+ .nlbits = 0,
+ .nvbit = METAL_CLIC_NONVECTOR
+ };
+
+void __metal_clic0_handler(int id, void *priv) __attribute__((aligned(64)));
+
+void __metal_clic0_default_vector_handler (void) __attribute__((interrupt, aligned(64)));
+
+struct __metal_clic_cfg __metal_clic0_configuration (struct __metal_driver_sifive_clic0 *clic,
+ struct __metal_clic_cfg *cfg)
+{
+ volatile unsigned char val;
+ struct __metal_clic_cfg cliccfg;
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+
+ if ( cfg ) {
+ val = cfg->nmbits << 5 | cfg->nlbits << 1 | cfg->nvbit;
+ __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICCFG)) = val;
+ }
+ val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICCFG));
+ cliccfg.nmbits = (val & METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_MASK) >> 5;
+ cliccfg.nlbits = (val & METAL_SIFIVE_CLIC0_CLICCFG_NLBITS_MASK) >> 1;
+ cliccfg.nvbit = val & METAL_SIFIVE_CLIC0_CLICCFG_NVBIT_MASK;
+ return cliccfg;
+}
+
+int __metal_clic0_interrupt_set_mode (struct __metal_driver_sifive_clic0 *clic, int id, int mode)
+{
+ uint8_t mask, val;
+ struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+
+ if (mode >= (cfg.nmbits << 1)) {
+ /* Do nothing, mode request same or exceed what configured in CLIC */
+ return 0;
+ }
+
+ /* Mask out nmbits and retain other values */
+ mask = ((uint8_t)(-1)) >> cfg.nmbits;
+ val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) & mask;
+ __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) = val | (mode << (8 - cfg.nmbits));
+ return 0;
+}
+
+int __metal_clic0_interrupt_set_level (struct __metal_driver_sifive_clic0 *clic, int id, unsigned int level)
+{
+ uint8_t mask, nmmask, nlmask, val;
+ struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+
+ /* Drop the LSBs that don't fit in nlbits */
+ level = level >> (METAL_CLIC_MAX_NLBITS - cfg.nlbits);
+
+ nmmask = ~( ((uint8_t)(-1)) >> (cfg.nmbits) );
+ nlmask = ((uint8_t)(-1)) >> (cfg.nmbits + cfg.nlbits);
+ mask = ~(nlmask | nmmask);
+
+ val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
+ __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) = __METAL_SET_FIELD(val, mask, level);
+ return 0;
+}
+
+unsigned int __metal_clic0_interrupt_get_level (struct __metal_driver_sifive_clic0 *clic, int id)
+{
+ int level;
+ uint8_t mask, val, freebits, nlbits;
+ struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+ int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
+
+ if ((cfg.nmbits + cfg.nlbits) >= num_intbits) {
+ nlbits = num_intbits - cfg.nmbits;
+ } else {
+ nlbits = cfg.nlbits;
+ }
+
+ mask = ((1 << nlbits) - 1) << (8 - (cfg.nmbits + nlbits));
+ freebits = ((1 << METAL_CLIC_MAX_NLBITS) - 1) >> nlbits;
+
+ if (mask == 0) {
+ level = (1 << METAL_CLIC_MAX_NLBITS) - 1;
+ } else {
+ val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
+ val = __METAL_GET_FIELD(val, mask);
+ level = (val << (METAL_CLIC_MAX_NLBITS - nlbits)) | freebits;
+ }
+
+ return level;
+}
+
+int __metal_clic0_interrupt_set_priority (struct __metal_driver_sifive_clic0 *clic, int id, int priority)
+{
+ uint8_t mask, npmask, val, npbits;
+ struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+ int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
+
+ if ((cfg.nmbits + cfg.nlbits) < num_intbits) {
+ npbits = num_intbits - (cfg.nmbits + cfg.nlbits);
+ priority = priority >> (8 - npbits);
+
+ mask = ((uint8_t)(-1)) >> (cfg.nmbits + cfg.nlbits + npbits);
+ npmask = ~(((uint8_t)(-1)) >> (cfg.nmbits + cfg.nlbits));
+ mask = ~(mask | npmask);
+
+ val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
+ __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) = __METAL_SET_FIELD(val, mask, priority);
+ }
+ return 0;
+}
+
+int __metal_clic0_interrupt_get_priority (struct __metal_driver_sifive_clic0 *clic, int id)
+{
+ int priority;
+ uint8_t mask, val, freebits, nlbits;
+ struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+ int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
+
+ if ((cfg.nmbits + cfg.nlbits) >= num_intbits) {
+ nlbits = num_intbits - cfg.nmbits;
+ } else {
+ nlbits = cfg.nlbits;
+ }
+
+ mask = ((1 << nlbits) - 1) << (8 - (cfg.nmbits + nlbits));
+ freebits = ((1 << METAL_CLIC_MAX_NLBITS) - 1) >> nlbits;
+
+ if (mask == 0) {
+ priority = (1 << METAL_CLIC_MAX_NLBITS) - 1;
+ } else {
+ val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
+ priority = __METAL_GET_FIELD(val, freebits);
+ }
+ return priority;
+}
+
+int __metal_clic0_interrupt_set_vector_mode (struct __metal_driver_sifive_clic0 *clic, int id, int enable)
+{
+ uint8_t mask, val;
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+ int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
+
+ mask = 1 << (8 - num_intbits);
+ val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
+ /* Ensure its value is 1 bit wide */
+ enable &= 0x1;
+ __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id)) = __METAL_SET_FIELD(val, mask, enable);
+ return 0;
+}
+
+int __metal_clic0_interrupt_is_vectored (struct __metal_driver_sifive_clic0 *clic, int id)
+{
+ uint8_t mask, val;
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+ int num_intbits = __metal_driver_sifive_clic0_num_intbits((struct metal_interrupt *)clic);
+
+ mask = 1 << (8 - num_intbits);
+ val = __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTCTL_BASE + id));
+ return __METAL_GET_FIELD(val, mask);
+}
+
+int __metal_clic0_interrupt_enable (struct __metal_driver_sifive_clic0 *clic, int id)
+{
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+ int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
+
+ if (id >= num_subinterrupts) {
+ return -1;
+ }
+ __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTIE_BASE + id)) = METAL_ENABLE;
+ return 0;
+}
+
+int __metal_clic0_interrupt_disable (struct __metal_driver_sifive_clic0 *clic, int id)
+{
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+ int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
+
+ if (id >= num_subinterrupts) {
+ return -1;
+ }
+ __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTIE_BASE + id)) = METAL_DISABLE;
+ return 0;
+}
+
+int __metal_clic0_interrupt_is_enabled (struct __metal_driver_sifive_clic0 *clic, int id)
+{
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+ int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
+
+ if (id >= num_subinterrupts) {
+ return 0;
+ }
+ return __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTIE_BASE + id));
+}
+
+int __metal_clic0_interrupt_is_pending (struct __metal_driver_sifive_clic0 *clic, int id)
+{
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+ int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
+
+ if (id >= num_subinterrupts) {
+ return 0;
+ }
+ return __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTIP_BASE + id));
+}
+
+int __metal_clic0_interrupt_set (struct __metal_driver_sifive_clic0 *clic, int id)
+{
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+ int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
+
+ if (id < num_subinterrupts) {
+ __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTIP_BASE + id)) = METAL_ENABLE;
+ return 0;
+ }
+ return -1;
+}
+
+int __metal_clic0_interrupt_clear (struct __metal_driver_sifive_clic0 *clic, int id)
+{
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+ int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
+
+ if (id < num_subinterrupts) {
+ __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTIP_BASE + id)) = METAL_DISABLE;
+ return 0;
+ }
+ return -1;
+}
+
+int __metal_clic0_configure_set_vector_mode (struct __metal_driver_sifive_clic0 *clic, metal_vector_mode mode)
+{
+ struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
+
+ switch (mode) {
+ case METAL_SELECTIVE_NONVECTOR_MODE:
+ cfg.nvbit = METAL_CLIC_NONVECTOR;
+ __metal_controller_interrupt_vector(mode, &clic->metal_mtvt_table);
+ break;
+ case METAL_SELECTIVE_VECTOR_MODE:
+ cfg.nvbit = METAL_CLIC_VECTORED;
+ __metal_controller_interrupt_vector(mode, &clic->metal_mtvt_table);
+ break;
+ case METAL_HARDWARE_VECTOR_MODE:
+ cfg.nvbit = METAL_CLIC_VECTORED;
+ __metal_controller_interrupt_vector(mode, &clic->metal_mtvt_table);
+ break;
+ default:
+ return -1;
+ }
+ __metal_clic0_configuration(clic, &cfg);
+ return 0;
+}
+
+metal_vector_mode __metal_clic0_configure_get_vector_mode (struct __metal_driver_sifive_clic0 *clic)
+{
+ struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
+ metal_vector_mode mode = __metal_controller_interrupt_vector_mode();
+
+ if (mode == METAL_SELECTIVE_VECTOR_MODE) {
+ if (cfg.nvbit) {
+ return METAL_SELECTIVE_VECTOR_MODE;
+ } else {
+ return METAL_SELECTIVE_NONVECTOR_MODE;
+ }
+ } else {
+ return mode;
+ }
+}
+
+int __metal_clic0_configure_set_privilege (struct __metal_driver_sifive_clic0 *clic, metal_intr_priv_mode priv)
+{
+ struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
+
+ cfg.nmbits = priv;
+ __metal_clic0_configuration(clic, &cfg);
+ return 0;
+}
+
+metal_intr_priv_mode __metal_clic0_configure_get_privilege (struct __metal_driver_sifive_clic0 *clic)
+{
+ struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
+
+ return cfg.nmbits;
+}
+
+int __metal_clic0_configure_set_level (struct __metal_driver_sifive_clic0 *clic, int level)
+{
+ struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
+
+ cfg.nlbits = level & 0xF;
+ __metal_clic0_configuration(clic, &cfg);
+ return 0;
+}
+
+int __metal_clic0_configure_get_level (struct __metal_driver_sifive_clic0 *clic)
+{
+ struct __metal_clic_cfg cfg = __metal_clic0_configuration(clic, NULL);
+
+ return cfg.nlbits;
+}
+
+unsigned long long __metal_clic0_mtime_get (struct __metal_driver_sifive_clic0 *clic)
+{
+ __metal_io_u32 lo, hi;
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+
+ /* Guard against rollover when reading */
+ do {
+ hi = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_CLIC0_MTIME + 4));
+ lo = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_CLIC0_MTIME));
+ } while (__METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_CLIC0_MTIME + 4)) != hi);
+
+ return (((unsigned long long)hi) << 32) | lo;
+}
+
+int __metal_driver_sifive_clic0_mtimecmp_set(struct metal_interrupt *controller,
+ int hartid,
+ unsigned long long time)
+{
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic);
+ /* Per spec, the RISC-V MTIME/MTIMECMP registers are 64 bit,
+ * and are NOT internally latched for multiword transfers.
+ * Need to be careful about sequencing to avoid triggering
+ * spurious interrupts: For that set the high word to a max
+ * value first.
+ */
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + (8 * hartid) + METAL_SIFIVE_CLIC0_MTIMECMP_BASE + 4)) = 0xFFFFFFFF;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + (8 * hartid) + METAL_SIFIVE_CLIC0_MTIMECMP_BASE)) = (__metal_io_u32)time;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + (8 * hartid) + METAL_SIFIVE_CLIC0_MTIMECMP_BASE + 4)) = (__metal_io_u32)(time >> 32);
+ return 0;
+}
+
+void __metal_clic0_handler (int id, void *priv)
+{
+ struct __metal_driver_sifive_clic0 *clic = priv;
+ int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic);
+
+ if ( (id < num_subinterrupts) && (clic->metal_exint_table[id].handler) ) {
+ clic->metal_exint_table[id].handler(id, clic->metal_exint_table[id].exint_data);
+ }
+}
+
+void __metal_clic0_default_handler (int id, void *priv) {
+ metal_shutdown(300);
+}
+
+void __metal_clic0_default_vector_handler (void) {
+ metal_shutdown(400);
+}
+
+void __metal_driver_sifive_clic0_init (struct metal_interrupt *controller)
+{
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+
+ if ( !clic->init_done ) {
+ int level, max_levels, line, num_interrupts, num_subinterrupts;
+ struct __metal_clic_cfg cfg = __metal_clic_defaultcfg;
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_clic0_interrupt_parent(controller);
+
+ /* Initialize ist parent controller, aka cpu_intc. */
+ intc->vtable->interrupt_init(intc);
+ __metal_controller_interrupt_vector(METAL_SELECTIVE_NONVECTOR_MODE,
+ &clic->metal_mtvt_table);
+
+ /*
+ * Register its interrupts with with parent controller,
+ * aka sw, timer and ext to its default isr
+ */
+ num_interrupts = __metal_driver_sifive_clic0_num_interrupts(controller);
+ for (int i = 0; i < num_interrupts; i++) {
+ line = __metal_driver_sifive_clic0_interrupt_lines(controller, i);
+ intc->vtable->interrupt_register(intc, line, NULL, clic);
+ }
+
+ /* Default CLIC mode to per dts */
+ max_levels = __metal_driver_sifive_clic0_max_levels(controller);
+ cfg.nlbits = (max_levels > METAL_CLIC_MAX_NLBITS) ?
+ METAL_CLIC_MAX_NLBITS : max_levels;
+ __metal_clic0_configuration(clic, &cfg);
+
+ level = (1 << cfg.nlbits) - 1;
+ num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller);
+ clic->metal_mtvt_table[0] = &__metal_clic0_handler;
+ for (int i = 1; i < num_subinterrupts; i++) {
+ clic->metal_mtvt_table[i] = NULL;
+ clic->metal_exint_table[i].handler = NULL;
+ clic->metal_exint_table[i].sub_int = NULL;
+ clic->metal_exint_table[i].exint_data = NULL;
+ __metal_clic0_interrupt_disable(clic, i);
+ __metal_clic0_interrupt_set_level(clic, i, level);
+ }
+ clic->init_done = 1;
+ }
+}
+
+int __metal_driver_sifive_clic0_register (struct metal_interrupt *controller,
+ int id, metal_interrupt_handler_t isr,
+ void *priv)
+{
+ int rc = -1;
+ int num_subinterrupts;
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_clic0_interrupt_parent(controller);
+ metal_vector_mode mode = __metal_clic0_configure_get_vector_mode(clic);
+
+ if ( ( (mode == METAL_SELECTIVE_VECTOR_MODE) &&
+ (__metal_clic0_interrupt_is_vectored(clic, id)) ) ||
+ (mode == METAL_HARDWARE_VECTOR_MODE) ||
+ (mode == METAL_VECTOR_MODE) ||
+ (mode == METAL_DIRECT_MODE) ) {
+ return rc;
+ }
+
+ /* Register its interrupts with parent controller */
+ if (id < METAL_INTERRUPT_ID_CSW) {
+ return intc->vtable->interrupt_register(intc, id, isr, priv);
+ }
+
+ /*
+ * CLIC (sub-interrupts) devices interrupts start at 16 but offset from 0
+ * Reset the IDs to reflects this.
+ */
+ num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller);
+ if (id < num_subinterrupts) {
+ if ( isr) {
+ clic->metal_exint_table[id].handler = isr;
+ clic->metal_exint_table[id].exint_data = priv;
+ } else {
+ clic->metal_exint_table[id].handler = __metal_clic0_default_handler;
+ clic->metal_exint_table[id].sub_int = priv;
+ }
+ rc = 0;
+ }
+ return rc;
+}
+
+int __metal_driver_sifive_clic0_vector_register (struct metal_interrupt *controller,
+ int id, metal_interrupt_vector_handler_t isr,
+ void *priv)
+{
+ int rc = -1;
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_clic0_interrupt_parent(controller);
+ int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller);
+ metal_vector_mode mode = __metal_clic0_configure_get_vector_mode(clic);
+
+ if ((mode != METAL_SELECTIVE_VECTOR_MODE) && (mode != METAL_HARDWARE_VECTOR_MODE)) {
+ return rc;
+ }
+ if ((mode == METAL_SELECTIVE_VECTOR_MODE) &&
+ (__metal_clic0_interrupt_is_vectored(clic, id) == 0) ) {
+ return rc;
+ }
+ if (id < num_subinterrupts) {
+ if ( isr) {
+ clic->metal_mtvt_table[id] = isr;
+ clic->metal_exint_table[id].exint_data = priv;
+ } else {
+ clic->metal_mtvt_table[id] = __metal_clic0_default_vector_handler;
+ clic->metal_exint_table[id].sub_int = priv;
+ }
+ rc = 0;
+ }
+ return rc;
+}
+
+int __metal_driver_sifive_clic0_enable (struct metal_interrupt *controller, int id)
+{
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ return __metal_clic0_interrupt_enable(clic, id);
+}
+
+int __metal_driver_sifive_clic0_disable (struct metal_interrupt *controller, int id)
+{
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ return __metal_clic0_interrupt_disable(clic, id);
+}
+
+int __metal_driver_sifive_clic0_enable_interrupt_vector(struct metal_interrupt *controller, int id)
+{
+ int rc = -1;
+ int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller);
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ metal_vector_mode mode = __metal_clic0_configure_get_vector_mode(clic);
+
+ if ((mode != METAL_SELECTIVE_VECTOR_MODE) && (mode != METAL_HARDWARE_VECTOR_MODE)) {
+ return rc;
+ }
+ if (id < num_subinterrupts) {
+ __metal_clic0_interrupt_set_vector_mode(clic, id, METAL_ENABLE);
+ return 0;
+ }
+ return -1;
+}
+
+int __metal_driver_sifive_clic0_disable_interrupt_vector(struct metal_interrupt *controller, int id)
+{
+ int num_subinterrupts;
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+
+ num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller);
+ if (id < num_subinterrupts) {
+ __metal_clic0_interrupt_set_vector_mode(clic, id, METAL_DISABLE);
+ return 0;
+ }
+ return -1;
+}
+
+metal_vector_mode __metal_driver_sifive_clic0_get_vector_mode (struct metal_interrupt *controller)
+{
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ return __metal_clic0_configure_get_vector_mode(clic);
+}
+
+int __metal_driver_sifive_clic0_set_vector_mode (struct metal_interrupt *controller, metal_vector_mode mode)
+{
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ return __metal_clic0_configure_set_vector_mode(clic, mode);
+}
+
+metal_intr_priv_mode __metal_driver_sifive_clic0_get_privilege (struct metal_interrupt *controller)
+{
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ return __metal_clic0_configure_get_privilege(clic);
+}
+
+int __metal_driver_sifive_clic0_set_privilege (struct metal_interrupt *controller, metal_intr_priv_mode priv)
+{
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ return __metal_clic0_configure_set_privilege(clic, priv);
+}
+
+unsigned int __metal_driver_sifive_clic0_get_threshold (struct metal_interrupt *controller)
+{
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ return __metal_clic0_configure_get_level(clic);
+}
+
+int __metal_driver_sifive_clic0_set_threshold (struct metal_interrupt *controller, unsigned int level)
+{
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ return __metal_clic0_configure_set_level(clic, level);
+}
+
+unsigned int __metal_driver_sifive_clic0_get_priority (struct metal_interrupt *controller, int id)
+{
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ return __metal_clic0_interrupt_get_priority(clic, id);
+}
+
+int __metal_driver_sifive_clic0_set_priority (struct metal_interrupt *controller, int id, unsigned int priority)
+{
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ return __metal_clic0_interrupt_set_priority(clic, id, priority);
+}
+
+int __metal_driver_sifive_clic0_clear_interrupt (struct metal_interrupt *controller, int id)
+{
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ return __metal_clic0_interrupt_clear(clic, id);
+}
+
+int __metal_driver_sifive_clic0_set_interrupt (struct metal_interrupt *controller, int id)
+{
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ return __metal_clic0_interrupt_set(clic, id);
+}
+
+int __metal_driver_sifive_clic0_command_request (struct metal_interrupt *controller,
+ int command, void *data)
+{
+ int hartid;
+ int rc = -1;
+ struct __metal_driver_sifive_clic0 *clic =
+ (struct __metal_driver_sifive_clic0 *)(controller);
+ unsigned long control_base = __metal_driver_sifive_clic0_control_base(controller);
+
+ switch (command) {
+ case METAL_TIMER_MTIME_GET:
+ if (data) {
+ *(unsigned long long *)data = __metal_clic0_mtime_get(clic);
+ rc = 0;
+ }
+ break;
+ case METAL_SOFTWARE_IPI_CLEAR:
+ if (data) {
+ hartid = *(int *)data;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ (hartid * 4))) = METAL_DISABLE;
+ __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTIP_BASE)) = METAL_DISABLE;
+ rc = 0;
+ }
+ break;
+ case METAL_SOFTWARE_IPI_SET:
+ if (data) {
+ hartid = *(int *)data;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ (hartid * 4))) = METAL_ENABLE;
+ __METAL_ACCESS_ONCE((__metal_io_u8 *)(control_base +
+ METAL_SIFIVE_CLIC0_MMODE_APERTURE +
+ METAL_SIFIVE_CLIC0_CLICINTIP_BASE)) = METAL_ENABLE;
+ rc = 0;
+ }
+ break;
+ case METAL_SOFTWARE_MSIP_GET:
+ rc = 0;
+ if (data) {
+ hartid = *(int *)data;
+ rc = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base +
+ (hartid * 4)));
+ }
+ break;
+ default:
+ break;
+ }
+
+ return rc;
+}
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_clic0) = {
+ .clic_vtable.interrupt_init = __metal_driver_sifive_clic0_init,
+ .clic_vtable.interrupt_register = __metal_driver_sifive_clic0_register,
+ .clic_vtable.interrupt_vector_register = __metal_driver_sifive_clic0_vector_register,
+ .clic_vtable.interrupt_enable = __metal_driver_sifive_clic0_enable,
+ .clic_vtable.interrupt_disable = __metal_driver_sifive_clic0_disable,
+ .clic_vtable.interrupt_vector_enable = __metal_driver_sifive_clic0_enable_interrupt_vector,
+ .clic_vtable.interrupt_vector_disable = __metal_driver_sifive_clic0_disable_interrupt_vector,
+ .clic_vtable.interrupt_get_vector_mode = __metal_driver_sifive_clic0_get_vector_mode,
+ .clic_vtable.interrupt_set_vector_mode = __metal_driver_sifive_clic0_set_vector_mode,
+ .clic_vtable.interrupt_get_privilege = __metal_driver_sifive_clic0_get_privilege,
+ .clic_vtable.interrupt_set_privilege = __metal_driver_sifive_clic0_set_privilege,
+ .clic_vtable.interrupt_get_threshold = __metal_driver_sifive_clic0_get_threshold,
+ .clic_vtable.interrupt_set_threshold = __metal_driver_sifive_clic0_set_threshold,
+ .clic_vtable.interrupt_get_priority = __metal_driver_sifive_clic0_get_priority,
+ .clic_vtable.interrupt_set_priority = __metal_driver_sifive_clic0_set_priority,
+ .clic_vtable.interrupt_clear = __metal_driver_sifive_clic0_clear_interrupt,
+ .clic_vtable.interrupt_set = __metal_driver_sifive_clic0_set_interrupt,
+ .clic_vtable.command_request = __metal_driver_sifive_clic0_command_request,
+ .clic_vtable.mtimecmp_set = __metal_driver_sifive_clic0_mtimecmp_set,
+};
+
+#endif /* METAL_SIFIVE_CLIC0 */
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfrosc.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfrosc.c
new file mode 100644
index 000000000..61af8d314
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfrosc.c
@@ -0,0 +1,44 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_FE310_G000_HFROSC
+
+#include <metal/drivers/sifive_fe310-g000_hfrosc.h>
+#include <metal/machine.h>
+
+#define CONFIG_DIVIDER 0x0000003FUL
+#define CONFIG_TRIM 0x001F0000UL
+#define CONFIG_ENABLE 0x40000000UL
+#define CONFIG_READY 0x80000000UL
+
+long __metal_driver_sifive_fe310_g000_hfrosc_get_rate_hz(const struct metal_clock *clock)
+{
+ struct metal_clock *ref = __metal_driver_sifive_fe310_g000_hfrosc_ref(clock);
+ long config_offset = __metal_driver_sifive_fe310_g000_hfrosc_config_offset(clock);
+ struct __metal_driver_sifive_fe310_g000_prci *config_base =
+ __metal_driver_sifive_fe310_g000_hfrosc_config_base(clock);
+ const struct __metal_driver_vtable_sifive_fe310_g000_prci *vtable =
+ __metal_driver_sifive_fe310_g000_prci_vtable();
+ long cfg = vtable->get_reg(config_base, config_offset);
+
+ if ((cfg & CONFIG_ENABLE) == 0)
+ return -1;
+ if ((cfg & CONFIG_READY) == 0)
+ return -1;
+ return metal_clock_get_rate_hz(ref) / ((cfg & CONFIG_DIVIDER) + 1);
+}
+
+long __metal_driver_sifive_fe310_g000_hfrosc_set_rate_hz(struct metal_clock *clock, long rate)
+{
+ return __metal_driver_sifive_fe310_g000_hfrosc_get_rate_hz(clock);
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_hfrosc) = {
+ .clock.get_rate_hz = &__metal_driver_sifive_fe310_g000_hfrosc_get_rate_hz,
+ .clock.set_rate_hz = &__metal_driver_sifive_fe310_g000_hfrosc_set_rate_hz,
+};
+#endif /* METAL_SIFIVE_FE310_G000_HFROSC */
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfxosc.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfxosc.c
new file mode 100644
index 000000000..9ed7a0bf3
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfxosc.c
@@ -0,0 +1,43 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_FE310_G000_HFXOSC
+
+#include <metal/drivers/sifive_fe310-g000_hfxosc.h>
+#include <metal/machine.h>
+
+#define CONFIG_ENABLE 0x40000000UL
+#define CONFIG_READY 0x80000000UL
+
+long __metal_driver_sifive_fe310_g000_hfxosc_get_rate_hz(const struct metal_clock *clock)
+{
+ struct metal_clock *ref = __metal_driver_sifive_fe310_g000_hfxosc_ref(clock);
+ long config_offset = __metal_driver_sifive_fe310_g000_hfxosc_config_offset(clock);
+ struct __metal_driver_sifive_fe310_g000_prci *config_base =
+ __metal_driver_sifive_fe310_g000_hfxosc_config_base(clock);
+ const struct __metal_driver_vtable_sifive_fe310_g000_prci *vtable =
+ __metal_driver_sifive_fe310_g000_prci_vtable();
+ long cfg = vtable->get_reg(config_base, config_offset);
+
+ if ((cfg & CONFIG_ENABLE) == 0)
+ return -1;
+ if ((cfg & CONFIG_READY) == 0)
+ return -1;
+ return metal_clock_get_rate_hz(ref);
+}
+
+long __metal_driver_sifive_fe310_g000_hfxosc_set_rate_hz(struct metal_clock *clock, long rate)
+{
+ return __metal_driver_sifive_fe310_g000_hfxosc_get_rate_hz(clock);
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_hfxosc) = {
+ .clock.get_rate_hz = __metal_driver_sifive_fe310_g000_hfxosc_get_rate_hz,
+ .clock.set_rate_hz = __metal_driver_sifive_fe310_g000_hfxosc_set_rate_hz,
+};
+
+#endif /* METAL_SIFIVE_FE310_G000_HFXOSC */
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_lfrosc.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_lfrosc.c
new file mode 100644
index 000000000..324382b9d
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_lfrosc.c
@@ -0,0 +1,53 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_FE310_G000_LFROSC
+
+#include <metal/drivers/sifive_fe310-g000_lfrosc.h>
+#include <metal/machine.h>
+
+/* LFROSCCFG */
+#define METAL_LFROSCCFG_DIV_MASK 0x3F
+#define METAL_LFROSCCFG_TRIM_SHIFT 16
+#define METAL_LFROSCCFG_TRIM_MASK (0x1F << METAL_LFROSCCFG_TRIM_SHIFT)
+#define METAL_LFROSCCFG_EN (1 << 30)
+#define METAL_LFROSCCFG_RDY (1 << 31)
+
+/* LFCLKMUX */
+#define METAL_LFCLKMUX_SEL 1
+#define METAL_LFCLKMUX_EXT_MUX_STATUS (1 << 31)
+
+#define LFROSC_REGW(addr) (__METAL_ACCESS_ONCE((__metal_io_u32 *)addr))
+
+long __metal_driver_sifive_fe310_g000_lfrosc_get_rate_hz(const struct metal_clock *clock)
+{
+ struct metal_clock *internal_ref = __metal_driver_sifive_fe310_g000_lfrosc_lfrosc(clock);
+ struct metal_clock *external_ref = __metal_driver_sifive_fe310_g000_lfrosc_psdlfaltclk(clock);
+
+ unsigned long int cfg_reg = __metal_driver_sifive_fe310_g000_lfrosc_config_reg(clock);
+ unsigned long int mux_reg = __metal_driver_sifive_fe310_g000_lfrosc_mux_reg(clock);
+
+ if(LFROSC_REGW(mux_reg) & METAL_LFCLKMUX_EXT_MUX_STATUS) {
+ return metal_clock_get_rate_hz(external_ref);
+ }
+
+ const unsigned long int div = (LFROSC_REGW(cfg_reg) & METAL_LFROSCCFG_DIV_MASK) + 1;
+
+ return metal_clock_get_rate_hz(internal_ref) / div;
+}
+
+long __metal_driver_sifive_fe310_g000_lfrosc_set_rate_hz(struct metal_clock *clock, long rate)
+{
+ return __metal_driver_sifive_fe310_g000_lfrosc_get_rate_hz(clock);
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_lfrosc) = {
+ .clock.get_rate_hz = &__metal_driver_sifive_fe310_g000_lfrosc_get_rate_hz,
+ .clock.set_rate_hz = &__metal_driver_sifive_fe310_g000_lfrosc_set_rate_hz,
+};
+#endif /* METAL_SIFIVE_FE310_G000_LFROSC */
+
+typedef int no_empty_translation_units;
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_pll.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_pll.c
new file mode 100644
index 000000000..2ca468f43
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_pll.c
@@ -0,0 +1,360 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_FE310_G000_PLL
+
+#include <stdio.h>
+#include <limits.h>
+
+#include <metal/machine.h>
+#include <metal/drivers/sifive_fe310-g000_pll.h>
+#include <stdlib.h>
+
+#define PLL_R 0x00000007UL
+#define PLL_F 0x000003F0UL
+#define PLL_Q 0x00000C00UL
+#define PLL_SEL 0x00010000UL
+#define PLL_REFSEL 0x00020000UL
+#define PLL_BYPASS 0x00040000UL
+#define PLL_LOCK 0x80000000UL
+
+#define DIV_DIV 0x0000003FUL
+#define DIV_1 0x00000100UL
+
+#define PLL_R_SHIFT(r) ((r << 0) & PLL_R)
+#define PLL_F_SHIFT(f) ((f << 4) & PLL_F)
+#define PLL_Q_SHIFT(q) ((q << 10) & PLL_Q)
+#define PLL_DIV_SHIFT(d) ((d << 0) & DIV_DIV)
+
+struct pll_config_t {
+ unsigned long multiplier;
+ unsigned long divisor;
+ unsigned long min_input_rate;
+ unsigned long max_input_rate;
+ unsigned long r;
+ unsigned long f;
+ unsigned long q;
+ long d; /* < 0 if disabled */
+};
+
+static const struct pll_config_t pll_configs[] = {
+ /*
+ * multiplier
+ * ^ divisor
+ * | ^ min_input_rate
+ * | | ^ max_input_rate
+ * | | | ^ r
+ * | | | | ^ f
+ * | | | | | ^ q
+ * | | | | | | ^ d
+ * | | | | | | | ^
+ * | | | | | | | | */
+ { 1, 32, 12000000, 24000000, 1, 31, 3, 63},
+ { 1, 32, 24000000, 48000000, 3, 31, 2, 63},
+ { 1, 16, 6000000, 12000000, 0, 31, 3, 63},
+ { 1, 16, 12000000, 24000000, 1, 31, 2, 63},
+ { 1, 16, 24000000, 48000000, 3, 31, 2, 31},
+ { 1, 8, 6000000, 12000000, 0, 31, 3, 31},
+ { 1, 8, 12000000, 24000000, 1, 31, 2, 31},
+ { 1, 8, 24000000, 48000000, 3, 31, 2, 15},
+ { 1, 4, 6000000, 12000000, 0, 31, 3, 15},
+ { 1, 4, 12000000, 24000000, 1, 31, 2, 15},
+ { 1, 4, 24000000, 48000000, 3, 31, 2, 7},
+ { 1, 2, 6000000, 12000000, 0, 31, 2, 15},
+ { 1, 2, 12000000, 24000000, 1, 31, 1, 15},
+ { 1, 2, 24000000, 48000000, 3, 31, 1, 7},
+ { 2, 1, 6000000, 12000000, 0, 31, 1, 7},
+ { 2, 1, 12000000, 24000000, 1, 31, 1, 3},
+ { 2, 1, 24000000, 48000000, 3, 31, 3, -1},
+ { 4, 1, 6000000, 12000000, 0, 31, 3, 0},
+ { 4, 1, 12000000, 24000000, 1, 31, 3, -1},
+ { 4, 1, 24000000, 48000000, 3, 31, 2, -1},
+ { 6, 1, 6000000, 10666666, 0, 35, 1, 2},
+ { 6, 1, 10666666, 12000000, 0, 23, 3, -1},
+ { 6, 1, 12000000, 16000000, 1, 47, 3, -1},
+ { 6, 1, 16000000, 18000000, 1, 23, 2, -1},
+ { 6, 1, 18000000, 21333333, 2, 35, 2, -1},
+ { 8, 1, 6000000, 12000000, 0, 31, 3, -1},
+ { 8, 1, 12000000, 24000000, 1, 31, 2, -1},
+ { 8, 1, 24000000, 48000000, 3, 31, 1, -1},
+ {10, 1, 6000000, 9600000, 0, 39, 3, -1},
+ {10, 1, 9600000, 12000000, 0, 19, 2, -1},
+ {10, 1, 12000000, 19200000, 1, 39, 2, -1},
+ {10, 1, 19200000, 24000000, 1, 19, 1, -1},
+ {10, 1, 24000000, 38400000, 3, 39, 1, -1},
+ {12, 1, 6000000, 8000000, 0, 47, 3, -1},
+ {12, 1, 8000000, 12000000, 0, 23, 2, -1},
+ {12, 1, 12000000, 16000000, 1, 47, 2, -1},
+ {12, 1, 16000000, 24000000, 1, 23, 1, -1},
+ {12, 1, 24000000, 30000000, 3, 47, 1, -1},
+ {12, 1, 30000000, 32000000, 3, 47, 1, -1},
+ {14, 1, 6000000, 6857142, 0, 55, 3, -1},
+ {14, 1, 6857143, 12000000, 0, 27, 2, -1},
+ {14, 1, 12000000, 13714285, 1, 55, 2, -1},
+ {14, 1, 13714286, 24000000, 1, 27, 1, -1},
+ {14, 1, 24000000, 27428571, 3, 55, 1, -1},
+ {16, 1, 6000000, 12000000, 0, 31, 2, -1},
+ {16, 1, 12000000, 24000000, 1, 31, 1, -1},
+ {18, 1, 6000000, 10666666, 0, 35, 2, -1},
+ {18, 1, 10666667, 12000000, 0, 17, 1, -1},
+ {18, 1, 12000000, 21333333, 1, 35, 1, -1},
+ {20, 1, 6000000, 9600000, 0, 39, 2, -1},
+ {20, 1, 9600000, 12000000, 0, 19, 1, -1},
+ {20, 1, 12000000, 19200000, 1, 39, 1, -1},
+ {22, 1, 6000000, 8727272, 0, 43, 2, -1},
+ {22, 1, 8727273, 12000000, 0, 21, 1, -1},
+ {22, 1, 12000000, 17454545, 1, 43, 1, -1},
+ {24, 1, 6000000, 8000000, 0, 47, 2, -1},
+ {24, 1, 8000000, 12000000, 0, 23, 1, -1},
+ {24, 1, 12000000, 16000000, 1, 47, 1, -1},
+ {26, 1, 6000000, 7384615, 0, 51, 2, -1},
+ {26, 1, 7384616, 12000000, 0, 25, 1, -1},
+ {26, 1, 12000000, 14768230, 1, 51, 1, -1},
+ {28, 1, 6000000, 6857142, 0, 55, 2, -1},
+ {28, 1, 6857143, 12000000, 0, 27, 1, -1},
+ {28, 1, 12000000, 13714285, 1, 55, 1, -1},
+ {30, 1, 6000000, 6400000, 0, 59, 2, -1},
+ {30, 1, 6400000, 12000000, 0, 29, 1, -1},
+ {30, 1, 12000000, 12800000, 1, 59, 1, -1},
+ {32, 1, 6000000, 12000000, 0, 31, 1, -1}
+};
+
+#define PLL_CONFIG_NOT_VALID -1
+
+void __metal_driver_sifive_fe310_g000_pll_init(struct __metal_driver_sifive_fe310_g000_pll *pll);
+
+/* Given the rate of the PLL input frequency and a PLL configuration, what
+ * will the resulting PLL output frequency be?
+ * Arguments:
+ * - pll_input_rate the PLL input frequency in hertz
+ * - config the PLL configuration
+ * Returns:
+ * - PLL_CONFIG_NOT_VALID if the configuration is not valid for the input frequency
+ * - the output frequency, in hertz */
+static long get_pll_config_freq(unsigned long pll_input_rate, const struct pll_config_t *config)
+{
+ if(pll_input_rate < config->min_input_rate || pll_input_rate > config->max_input_rate)
+ return PLL_CONFIG_NOT_VALID;
+
+ return pll_input_rate * config->multiplier / config->divisor;
+}
+
+#ifdef __METAL_DT_SIFIVE_FE310_G000_PLL_HANDLE
+
+static void metal_sifive_fe310_g000_pll_init(void) __attribute__((constructor));
+static void metal_sifive_fe310_g000_pll_init(void) {
+ long init_rate = __metal_driver_sifive_fe310_g000_pll_init_rate();
+ /* If the PLL init_rate is zero, don't initialize the PLL */
+ if(init_rate != 0)
+ __metal_driver_sifive_fe310_g000_pll_init(__METAL_DT_SIFIVE_FE310_G000_PLL_HANDLE);
+}
+
+#endif /* __METAL_DT_SIFIVE_FE310_G000__PLL_HANDLE */
+
+void __metal_driver_sifive_fe310_g000_pll_init(struct __metal_driver_sifive_fe310_g000_pll *pll) {
+ struct metal_clock *pllref = __metal_driver_sifive_fe310_g000_pll_pllref(&(pll->clock));
+ long init_rate = __metal_driver_sifive_fe310_g000_pll_init_rate();
+ long config_offset = __metal_driver_sifive_fe310_g000_pll_config_offset();
+ long base = __metal_driver_sifive_fe310_g000_prci_base();
+
+ __metal_io_u32 *pllcfg = (__metal_io_u32 *) (base + config_offset);
+
+ /* If the PLL clock has had a _pre_rate_change_callback configured, call it */
+ _metal_clock_call_all_callbacks(pll->clock._pre_rate_change_callback);
+
+ /* If we're running off of the PLL, switch off before we start configuring it*/
+ if((__METAL_ACCESS_ONCE(pllcfg) & PLL_SEL) == 0)
+ __METAL_ACCESS_ONCE(pllcfg) &= ~(PLL_SEL);
+
+ /* Make sure we're running off of the external oscillator for stability */
+ if(pllref != NULL)
+ __METAL_ACCESS_ONCE(pllcfg) |= PLL_REFSEL;
+
+ /* Configure the PLL to run at the requested init frequency.
+ * Using the vtable instead of the user API because we want to control
+ * when the callbacks occur. */
+ pll->clock.vtable->set_rate_hz(&(pll->clock), init_rate);
+
+ /* If the PLL clock has had a rate_change_callback configured, call it */
+ _metal_clock_call_all_callbacks(pll->clock._post_rate_change_callback);
+}
+
+long __metal_driver_sifive_fe310_g000_pll_get_rate_hz(const struct metal_clock *clock)
+{
+ struct metal_clock *pllref = __metal_driver_sifive_fe310_g000_pll_pllref(clock);
+ struct metal_clock *pllsel0 = __metal_driver_sifive_fe310_g000_pll_pllsel0(clock);
+ long config_offset = __metal_driver_sifive_fe310_g000_pll_config_offset(clock);
+ struct __metal_driver_sifive_fe310_g000_prci *config_base =
+ __metal_driver_sifive_fe310_g000_pll_config_base(clock);
+ long divider_offset = __metal_driver_sifive_fe310_g000_pll_divider_offset(clock);
+ struct __metal_driver_sifive_fe310_g000_prci *divider_base =
+ __metal_driver_sifive_fe310_g000_pll_divider_base(clock);
+ const struct __metal_driver_vtable_sifive_fe310_g000_prci *vtable =
+ __metal_driver_sifive_fe310_g000_prci_vtable();
+
+ long cfg = vtable->get_reg(config_base, config_offset);
+ long div = vtable->get_reg(divider_base, divider_offset);
+
+ /* At the end of the PLL there's one big mux: it either selects the HFROSC
+ * (bypassing the PLL entirely) or uses the PLL. */
+ if (__METAL_GET_FIELD(cfg, PLL_SEL) == 0)
+ return metal_clock_get_rate_hz(pllsel0);
+
+ /* There's a clock mux before the PLL that selects between the HFROSC adn
+ * the HFXOSC as the PLL's input clock. */
+ long ref_hz = metal_clock_get_rate_hz(__METAL_GET_FIELD(cfg, PLL_REFSEL) ? pllref : pllsel0);
+
+ /* It's possible to bypass the PLL, which is an internal bpyass. This
+ * still obays the PLL's input clock mu. */
+ if (__METAL_GET_FIELD(cfg, PLL_BYPASS))
+ return ref_hz;
+
+ /* Logically the PLL is a three stage div-mul-div. */
+ long div_r = __METAL_GET_FIELD(cfg, PLL_R) + 1;
+ long mul_f = 2 * (__METAL_GET_FIELD(cfg, PLL_F) + 1);
+ if (__METAL_GET_FIELD(cfg, PLL_Q) == 0)
+ return -1;
+ long div_q = 1 << __METAL_GET_FIELD(cfg, PLL_Q);
+
+ /* In addition to the dividers inherent in the PLL, there's an additional
+ * clock divider that lives after the PLL and lets us pick a more
+ * interesting range of frequencies. */
+ long pllout = (((ref_hz / div_r) * mul_f) / div_q);
+ if (__METAL_GET_FIELD(div, DIV_1))
+ return pllout;
+
+ return pllout / (2 * (__METAL_GET_FIELD(div, DIV_DIV) + 1));
+}
+
+/* Find a valid configuration for the PLL which is closest to the desired
+ * output frequency.
+ * Arguments:
+ * - ref_hz PLL input frequency
+ * - rate desired PLL output frequency
+ * Returns:
+ * -1 if no valid configuration is available
+ * the index into pll_configs of a valid configuration */
+static int find_closest_config(long ref_hz, long rate)
+{
+ int closest_index = -1;
+ long closest_diff = LONG_MAX;
+
+ /* We're probably trying for a fast output frequency, so start from
+ * the high end of the configs. */
+ for(int i = (sizeof(pll_configs) / sizeof(pll_configs[0])) - 1; i >= 0; i--)
+ {
+ long config_freq = get_pll_config_freq(ref_hz, &(pll_configs[i]));
+ if(config_freq != PLL_CONFIG_NOT_VALID)
+ {
+ long freq_diff = abs(config_freq - rate);
+ if(freq_diff < closest_diff)
+ {
+ closest_index = i;
+ closest_diff = freq_diff;
+ }
+ }
+ }
+
+ return closest_index;
+}
+
+/* Configure the PLL and wait for it to lock */
+static void configure_pll(__metal_io_u32 *pllcfg, __metal_io_u32 *plloutdiv, const struct pll_config_t *config)
+{
+ __METAL_ACCESS_ONCE(pllcfg) &= ~(PLL_R);
+ __METAL_ACCESS_ONCE(pllcfg) |= PLL_R_SHIFT(config->r);
+
+ __METAL_ACCESS_ONCE(pllcfg) &= ~(PLL_F);
+ __METAL_ACCESS_ONCE(pllcfg) |= PLL_F_SHIFT(config->f);
+
+ __METAL_ACCESS_ONCE(pllcfg) &= ~(PLL_Q);
+ __METAL_ACCESS_ONCE(pllcfg) |= PLL_Q_SHIFT(config->q);
+
+ if(config->d < 0)
+ {
+ /* disable final divider */
+ __METAL_ACCESS_ONCE(plloutdiv) |= DIV_1;
+
+ __METAL_ACCESS_ONCE(plloutdiv) &= ~(DIV_DIV);
+ __METAL_ACCESS_ONCE(plloutdiv) |= PLL_DIV_SHIFT(1);
+ }
+ else
+ {
+ __METAL_ACCESS_ONCE(plloutdiv) &= ~(DIV_1);
+
+ __METAL_ACCESS_ONCE(plloutdiv) &= ~(DIV_DIV);
+ __METAL_ACCESS_ONCE(plloutdiv) |= PLL_DIV_SHIFT(config->d);
+ }
+
+ __METAL_ACCESS_ONCE(pllcfg) &= ~(PLL_BYPASS);
+
+ /* Wait for PLL to lock */
+ while((__METAL_ACCESS_ONCE(pllcfg) & PLL_LOCK) == 0) ;
+}
+
+long __metal_driver_sifive_fe310_g000_pll_set_rate_hz(struct metal_clock *clock, long rate)
+{
+ struct metal_clock *pllref = __metal_driver_sifive_fe310_g000_pll_pllref(clock);
+ struct metal_clock *pllsel0 = __metal_driver_sifive_fe310_g000_pll_pllsel0(clock);
+ long config_offset = __metal_driver_sifive_fe310_g000_pll_config_offset(clock);
+ long divider_offset = __metal_driver_sifive_fe310_g000_pll_divider_offset(clock);
+ long base = __metal_driver_sifive_fe310_g000_prci_base();
+
+ __metal_io_u32 *pllcfg = (__metal_io_u32 *) (base + config_offset);
+ __metal_io_u32 *plloutdiv = (__metal_io_u32 *) (base + divider_offset);
+
+ /* We can't modify the PLL if coreclk is driven by it, so switch it off */
+ if (__METAL_ACCESS_ONCE(pllcfg) & PLL_SEL)
+ __METAL_ACCESS_ONCE(pllcfg) &= ~(PLL_SEL);
+
+ /* There's a clock mux before the PLL that selects between the HFROSC and
+ * the HFXOSC as the PLL's input clock. */
+ long ref_hz = metal_clock_get_rate_hz(__METAL_ACCESS_ONCE(pllcfg) & PLL_REFSEL ? pllref : pllsel0);
+
+ /* if the desired rate is within 75%-125% of the input clock, bypass the PLL */
+ if((ref_hz * 3 / 4) <= rate && (ref_hz * 5 / 4) >= rate)
+ {
+ __METAL_ACCESS_ONCE(pllcfg) |= PLL_BYPASS;
+ }
+ else
+ {
+ int config_index = find_closest_config(ref_hz, rate);
+ if(config_index != -1)
+ {
+ configure_pll(pllcfg, plloutdiv, &(pll_configs[config_index]));
+ }
+ else
+ {
+ /* unable to find a valid configuration */
+ __METAL_ACCESS_ONCE(pllcfg) |= PLL_BYPASS;
+ }
+ }
+
+ /* Enable the PLL */
+ __METAL_ACCESS_ONCE(pllcfg) |= PLL_SEL;
+
+ return __metal_driver_sifive_fe310_g000_pll_get_rate_hz(clock);
+}
+
+#ifdef __METAL_DT_SIFIVE_FE310_G000_PLL_HANDLE
+static void use_hfxosc(void) __attribute__((constructor));
+static void use_hfxosc(void)
+{
+ long init_rate = __metal_driver_sifive_fe310_g000_pll_init_rate();
+ metal_clock_set_rate_hz(
+ &__METAL_DT_SIFIVE_FE310_G000_PLL_HANDLE->clock, init_rate
+ );
+}
+#endif
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_pll) = {
+ .init = __metal_driver_sifive_fe310_g000_pll_init,
+ .clock.get_rate_hz = __metal_driver_sifive_fe310_g000_pll_get_rate_hz,
+ .clock.set_rate_hz = __metal_driver_sifive_fe310_g000_pll_set_rate_hz,
+};
+
+#endif /* METAL_SIFIVE_FE310_G000_PLL */
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_prci.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_prci.c
new file mode 100644
index 000000000..1236eca3b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_prci.c
@@ -0,0 +1,28 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_FE310_G000_PRCI
+
+#include <metal/drivers/sifive_fe310-g000_prci.h>
+#include <metal/machine.h>
+
+long __metal_driver_sifive_fe310_g000_prci_get_reg(const struct __metal_driver_sifive_fe310_g000_prci *prci, long offset) {
+ unsigned long base = __metal_driver_sifive_fe310_g000_prci_base();
+ return __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + offset));
+}
+
+long __metal_driver_sifive_fe310_g000_prci_set_reg(const struct __metal_driver_sifive_fe310_g000_prci *prci, long offset, long value) {
+ unsigned long base = __metal_driver_sifive_fe310_g000_prci_base();
+ return __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + offset)) = value;
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_prci) = {
+ .get_reg = __metal_driver_sifive_fe310_g000_prci_get_reg,
+ .set_reg = __metal_driver_sifive_fe310_g000_prci_set_reg,
+};
+
+#endif /* METAL_SIFIVE_FE310_G000_PRCI */
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fu540-c000_l2.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fu540-c000_l2.c
new file mode 100644
index 000000000..aafc6e5e3
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_fu540-c000_l2.c
@@ -0,0 +1,84 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_FU540_C000_L2
+
+#include <stdint.h>
+#include <metal/io.h>
+#include <metal/drivers/sifive_fu540-c000_l2.h>
+#include <metal/machine.h>
+
+#define L2_CONFIG_WAYS_SHIFT 8
+#define L2_CONFIG_WAYS_MASK (0xFF << L2_CONFIG_WAYS_SHIFT)
+
+void __metal_driver_sifive_fu540_c000_l2_init(struct metal_cache *l2, int ways);
+
+static void metal_driver_sifive_fu540_c000_l2_init(void) __attribute__((constructor));
+static void metal_driver_sifive_fu540_c000_l2_init(void)
+{
+#ifdef __METAL_DT_SIFIVE_FU540_C000_L2_HANDLE
+ /* Get the handle for the L2 cache controller */
+ struct metal_cache *l2 = __METAL_DT_SIFIVE_FU540_C000_L2_HANDLE;
+ if(!l2) {
+ return;
+ }
+
+ /* Get the number of available ways per bank */
+ unsigned long control_base = __metal_driver_sifive_fu540_c000_l2_control_base(l2);
+ uint32_t ways = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_FU540_C000_L2_CONFIG));
+ ways = ((ways & L2_CONFIG_WAYS_MASK) >> L2_CONFIG_WAYS_SHIFT);
+
+ /* Enable all the ways */
+ __metal_driver_sifive_fu540_c000_l2_init(l2, ways);
+#endif
+}
+
+void __metal_driver_sifive_fu540_c000_l2_init(struct metal_cache *l2, int ways)
+{
+ metal_cache_set_enabled_ways(l2, ways);
+}
+
+int __metal_driver_sifive_fu540_c000_l2_get_enabled_ways(struct metal_cache *cache)
+{
+ unsigned long control_base = __metal_driver_sifive_fu540_c000_l2_control_base(cache);
+
+ uint32_t way_enable = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_FU540_C000_L2_WAYENABLE));
+
+ /* The stored number is the index, so add one */
+ return (0xFF & way_enable) + 1;
+}
+
+int __metal_driver_sifive_fu540_c000_l2_set_enabled_ways(struct metal_cache *cache, int ways)
+{
+ unsigned long control_base = __metal_driver_sifive_fu540_c000_l2_control_base(cache);
+
+ /* We can't decrease the number of enabled ways */
+ if(metal_cache_get_enabled_ways(cache) > ways) {
+ return -2;
+ }
+
+ /* The stored value is the index, so subtract one */
+ uint32_t value = 0xFF & (ways - 1);
+
+ /* Set the number of enabled ways */
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + METAL_SIFIVE_FU540_C000_L2_WAYENABLE)) = value;
+
+ /* Make sure the number of ways was set correctly */
+ if(metal_cache_get_enabled_ways(cache) != ways) {
+ return -3;
+ }
+
+ return 0;
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_fu540_c000_l2) = {
+ .cache.init = __metal_driver_sifive_fu540_c000_l2_init,
+ .cache.get_enabled_ways = __metal_driver_sifive_fu540_c000_l2_get_enabled_ways,
+ .cache.set_enabled_ways = __metal_driver_sifive_fu540_c000_l2_set_enabled_ways,
+};
+
+#endif
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_global-external-interrupts0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_global-external-interrupts0.c
new file mode 100644
index 000000000..0d56bafef
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_global-external-interrupts0.c
@@ -0,0 +1,169 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_GLOBAL_EXTERNAL_INTERRUPTS0
+
+#include <metal/io.h>
+#include <metal/shutdown.h>
+#include <metal/drivers/sifive_global-external-interrupts0.h>
+#include <metal/machine.h>
+
+void __metal_driver_sifive_global_external_interrupt_init(struct metal_interrupt *controller)
+{
+ struct __metal_driver_sifive_global_external_interrupts0 *global0;
+
+ global0 = (struct __metal_driver_sifive_global_external_interrupts0 *)(controller);
+ if ( !global0->init_done ) {
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_global_external_interrupts0_interrupt_parent(controller);
+
+ if (intc) {
+ intc->vtable->interrupt_init(intc);
+ /* Register its interrupts with with parent controller */
+ for (int i = 0;
+ i < __metal_driver_sifive_global_external_interrupts0_num_interrupts(controller);
+ i++) {
+ intc->vtable->interrupt_register(intc,
+ __metal_driver_sifive_global_external_interrupts0_interrupt_lines(controller, i),
+ NULL, controller);
+ }
+ global0->init_done = 1;
+ }
+ }
+}
+
+int __metal_driver_sifive_global_external_interrupt_register(struct metal_interrupt *controller,
+ int id, metal_interrupt_handler_t isr,
+ void *priv)
+{
+ int rc = -1;
+
+ if (id != 0) {
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_global_external_interrupts0_interrupt_parent(controller);
+
+ /* Enable its interrupts with parent controller */
+ if (intc) {
+ rc = intc->vtable->interrupt_register(intc, id, isr, priv);
+ }
+ }
+ return rc;
+}
+
+int __metal_driver_sifive_global_external_interrupt_enable(struct metal_interrupt *controller, int id)
+{
+ int rc = -1;
+
+ if (id != 0) {
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_global_external_interrupts0_interrupt_parent(controller);
+
+ /* Enable its interrupts with parent controller */
+ if (intc) {
+ rc = intc->vtable->interrupt_enable(intc, id);
+ }
+ }
+ return rc;
+}
+
+int __metal_driver_sifive_global_external_interrupt_disable(struct metal_interrupt *controller, int id)
+{
+ int rc = -1;
+
+ if (id != 0) {
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_global_external_interrupts0_interrupt_parent(controller);
+
+ /* Enable its interrupts with parent controller */
+ if (intc) {
+ rc = intc->vtable->interrupt_disable(intc, id);
+ }
+ }
+ return rc;
+}
+
+int __metal_driver_sifive_global_external_interrupt_set_threshold(struct metal_interrupt *controller,
+ unsigned int threshold)
+{
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_global_external_interrupts0_interrupt_parent(controller);
+ if (intc) {
+ return intc->vtable->interrupt_set_threshold(intc, threshold);
+ }
+ return -1;
+}
+
+unsigned int __metal_driver_sifive_global_external_interrupt_get_threshold(struct metal_interrupt *controller)
+{
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_global_external_interrupts0_interrupt_parent(controller);
+
+ if (intc) {
+ return intc->vtable->interrupt_get_threshold(intc);
+ }
+ return 0;
+}
+
+int __metal_driver_sifive_global_external_interrupt_set_priority(struct metal_interrupt *controller,
+ int id, unsigned int priority)
+{
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_global_external_interrupts0_interrupt_parent(controller);
+ if (intc) {
+ return intc->vtable->interrupt_set_priority(intc, id, priority);
+ }
+ return -1;
+}
+
+unsigned int __metal_driver_sifive_global_external_interrupt_get_priority(struct metal_interrupt *controller, int id)
+{
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_global_external_interrupts0_interrupt_parent(controller);
+
+ if (intc) {
+ return intc->vtable->interrupt_get_priority(intc, id);
+ }
+ return 0;
+}
+
+int __metal_driver_sifive_global_external_command_request (struct metal_interrupt *controller,
+ int command, void *data)
+{
+ int idx;
+ int rc = -1;
+
+ switch (command) {
+ case METAL_MAX_INTERRUPT_GET:
+ rc = __metal_driver_sifive_global_external_interrupts0_num_interrupts(controller);
+ break;
+ case METAL_INDEX_INTERRUPT_GET:
+ rc = 0;
+ if (data) {
+ idx = *(int *)data;
+ rc = __metal_driver_sifive_global_external_interrupts0_interrupt_lines(controller, idx);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return rc;
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_global_external_interrupts0) = {
+ .global0_vtable.interrupt_init = __metal_driver_sifive_global_external_interrupt_init,
+ .global0_vtable.interrupt_register = __metal_driver_sifive_global_external_interrupt_register,
+ .global0_vtable.interrupt_enable = __metal_driver_sifive_global_external_interrupt_enable,
+ .global0_vtable.interrupt_disable = __metal_driver_sifive_global_external_interrupt_disable,
+ .global0_vtable.interrupt_get_threshold = __metal_driver_sifive_global_external_interrupt_get_threshold,
+ .global0_vtable.interrupt_set_threshold = __metal_driver_sifive_global_external_interrupt_set_threshold,
+ .global0_vtable.interrupt_get_priority = __metal_driver_sifive_global_external_interrupt_get_priority,
+ .global0_vtable.interrupt_set_priority = __metal_driver_sifive_global_external_interrupt_set_priority,
+ .global0_vtable.command_request = __metal_driver_sifive_global_external_command_request,
+};
+
+#endif
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-buttons.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-buttons.c
new file mode 100644
index 000000000..923fe2711
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-buttons.c
@@ -0,0 +1,57 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_GPIO_BUTTONS
+
+#include <string.h>
+#include <metal/drivers/riscv_cpu.h>
+#include <metal/drivers/sifive_gpio-buttons.h>
+#include <metal/machine.h>
+
+int __metal_driver_button_exist (struct metal_button *button, char *label)
+{
+ if (strcmp(__metal_driver_sifive_gpio_button_label(button), label) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+struct metal_interrupt *
+__metal_driver_button_interrupt_controller(struct metal_button *button)
+{
+ return __metal_driver_sifive_gpio_button_interrupt_controller(button);
+}
+
+int __metal_driver_button_get_interrupt_id(struct metal_button *button)
+{
+ int irq, max_irq;
+ struct metal_interrupt *irc;
+
+ irq = __metal_driver_sifive_gpio_button_interrupt_line(button);
+ irc = __metal_driver_sifive_gpio_button_interrupt_controller(button);
+
+ if (irc != NULL) {
+ max_irq = _metal_interrupt_command_request(irc,
+ METAL_MAX_INTERRUPT_GET,
+ NULL);
+
+ if (irq < max_irq) {
+ return _metal_interrupt_command_request(irc,
+ METAL_INDEX_INTERRUPT_GET,
+ (void *)&irq);
+ }
+ }
+ return METAL_INTERRUPT_ID_LCMX;
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_button) = {
+ .button_vtable.button_exist = __metal_driver_button_exist,
+ .button_vtable.interrupt_controller = __metal_driver_button_interrupt_controller,
+ .button_vtable.get_interrupt_id = __metal_driver_button_get_interrupt_id,
+};
+
+#endif
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-leds.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-leds.c
new file mode 100644
index 000000000..a6b627458
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-leds.c
@@ -0,0 +1,85 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_GPIO_LEDS
+
+#include <string.h>
+#include <metal/gpio.h>
+#include <metal/drivers/sifive_gpio-leds.h>
+#include <metal/machine.h>
+
+int __metal_driver_led_exist (struct metal_led *led, char *label)
+{
+ if (strcmp(__metal_driver_sifive_gpio_led_label(led), label) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+void __metal_driver_led_enable (struct metal_led *led)
+{
+ int pin;
+ struct metal_gpio *gpio;
+
+ pin = __metal_driver_sifive_gpio_led_pin(led);
+ gpio = __metal_driver_sifive_gpio_led_gpio(led);
+
+ if (gpio != NULL) {
+ /* Configure LED as output */
+ metal_gpio_disable_input((struct metal_gpio *) gpio, pin);
+ metal_gpio_enable_output((struct metal_gpio *) gpio, pin);
+ }
+}
+
+void __metal_driver_led_on (struct metal_led *led)
+{
+ int pin;
+ struct metal_gpio *gpio;
+
+ pin = __metal_driver_sifive_gpio_led_pin(led);
+ gpio = __metal_driver_sifive_gpio_led_gpio(led);
+
+ if (gpio != NULL) {
+ metal_gpio_set_pin((struct metal_gpio *) gpio, pin, 1);
+ }
+}
+
+void __metal_driver_led_off (struct metal_led *led)
+{
+ int pin;
+ struct metal_gpio *gpio;
+
+ pin = __metal_driver_sifive_gpio_led_pin(led);
+ gpio = __metal_driver_sifive_gpio_led_gpio(led);
+
+ if (gpio != NULL) {
+ metal_gpio_set_pin((struct metal_gpio *) gpio, pin, 0);
+ }
+}
+
+void __metal_driver_led_toggle (struct metal_led *led)
+{
+ int pin;
+ struct metal_gpio *gpio;
+
+ pin = __metal_driver_sifive_gpio_led_pin(led);
+ gpio = __metal_driver_sifive_gpio_led_gpio(led);
+
+ if (gpio != NULL) {
+ metal_gpio_toggle_pin((struct metal_gpio *) gpio, pin);
+ }
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_led) = {
+ .led_vtable.led_exist = __metal_driver_led_exist,
+ .led_vtable.led_enable = __metal_driver_led_enable,
+ .led_vtable.led_on = __metal_driver_led_on,
+ .led_vtable.led_off = __metal_driver_led_off,
+ .led_vtable.led_toggle = __metal_driver_led_toggle,
+};
+
+#endif
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-switches.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-switches.c
new file mode 100644
index 000000000..fa0a819f1
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-switches.c
@@ -0,0 +1,56 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_GPIO_SWITCHES
+
+#include <string.h>
+#include <metal/drivers/riscv_cpu.h>
+#include <metal/drivers/sifive_gpio-switches.h>
+#include <metal/machine.h>
+
+int __metal_driver_switch_exist (struct metal_switch *flip, char *label)
+{
+ if (strcmp(__metal_driver_sifive_gpio_switch_label(flip), label) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+struct metal_interrupt *
+__metal_driver_switch_interrupt_controller(struct metal_switch *flip)
+{
+ return __metal_driver_sifive_gpio_switch_interrupt_controller(flip);
+}
+
+int __metal_driver_switch_get_interrupt_id(struct metal_switch *flip)
+{
+ int irq, max_irq;
+ struct metal_interrupt *irc;
+
+ irq = __metal_driver_sifive_gpio_switch_interrupt_line(flip);
+ irc = __metal_driver_sifive_gpio_switch_interrupt_controller(flip);
+ if (irc != NULL) {
+ max_irq = _metal_interrupt_command_request(irc,
+ METAL_MAX_INTERRUPT_GET,
+ NULL);
+
+ if (irq < max_irq) {
+ return _metal_interrupt_command_request(irc,
+ METAL_INDEX_INTERRUPT_GET,
+ (void *)&irq);
+ }
+ }
+ return METAL_INTERRUPT_ID_LCMX;
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_switch) = {
+ .switch_vtable.switch_exist = __metal_driver_switch_exist,
+ .switch_vtable.interrupt_controller = __metal_driver_switch_interrupt_controller,
+ .switch_vtable.get_interrupt_id = __metal_driver_switch_get_interrupt_id,
+};
+
+#endif
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio0.c
new file mode 100644
index 000000000..9ebbea03c
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_gpio0.c
@@ -0,0 +1,221 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_GPIO0
+
+#include <metal/drivers/sifive_gpio0.h>
+#include <metal/io.h>
+#include <metal/machine.h>
+
+int __metal_driver_sifive_gpio0_enable_input(struct metal_gpio *ggpio, long source)
+{
+ long base = __metal_driver_sifive_gpio0_base(ggpio);
+
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_INPUT_EN)) |= source;
+
+ return 0;
+}
+
+int __metal_driver_sifive_gpio0_disable_input(struct metal_gpio *ggpio, long source)
+{
+ long base = __metal_driver_sifive_gpio0_base(ggpio);
+
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_INPUT_EN)) &= ~source;
+
+ return 0;
+}
+
+long __metal_driver_sifive_gpio0_input(struct metal_gpio *ggpio)
+{
+ long base = __metal_driver_sifive_gpio0_base(ggpio);
+
+ return __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_VALUE));
+}
+
+long __metal_driver_sifive_gpio0_output(struct metal_gpio *ggpio)
+{
+ long base = __metal_driver_sifive_gpio0_base(ggpio);
+
+ return __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_PORT));
+}
+
+
+int __metal_driver_sifive_gpio0_disable_output(struct metal_gpio *ggpio, long source)
+{
+ long base = __metal_driver_sifive_gpio0_base(ggpio);
+
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_OUTPUT_EN)) &= ~source;
+
+ return 0;
+}
+
+int __metal_driver_sifive_gpio0_enable_output(struct metal_gpio *ggpio, long source)
+{
+ long base = __metal_driver_sifive_gpio0_base(ggpio);
+
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_OUTPUT_EN)) |= source;
+
+ return 0;
+}
+
+int __metal_driver_sifive_gpio0_output_set(struct metal_gpio *ggpio, long value)
+{
+ long base = __metal_driver_sifive_gpio0_base(ggpio);
+
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_PORT)) |= value;
+
+ return 0;
+}
+
+int __metal_driver_sifive_gpio0_output_clear(struct metal_gpio *ggpio, long value)
+{
+ long base = __metal_driver_sifive_gpio0_base(ggpio);
+
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_PORT)) &= ~value;
+
+ return 0;
+}
+
+int __metal_driver_sifive_gpio0_output_toggle(struct metal_gpio *ggpio, long value)
+{
+ long base = __metal_driver_sifive_gpio0_base(ggpio);
+
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_PORT)) =
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_PORT)) ^ value;
+
+ return 0;
+}
+
+int __metal_driver_sifive_gpio0_enable_io(struct metal_gpio *ggpio, long source, long dest)
+{
+ long base = __metal_driver_sifive_gpio0_base(ggpio);
+
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_IOF_SEL)) &= ~source;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_IOF_EN)) |= dest;
+
+ return 0;
+}
+
+int __metal_driver_sifive_gpio0_disable_io(struct metal_gpio *ggpio, long source)
+{
+ long base = __metal_driver_sifive_gpio0_base(ggpio);
+
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_IOF_EN)) &= ~source;
+
+ return 0;
+}
+
+int __metal_driver_sifive_gpio0_config_int(struct metal_gpio *ggpio, long source, int intr_type)
+{
+ long base = __metal_driver_sifive_gpio0_base(ggpio);
+
+ switch (intr_type)
+ {
+ case METAL_GPIO_INT_DISABLE:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_RISE_IE)) &= ~source;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_FALL_IE)) &= ~source;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_HIGH_IE)) &= ~source;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_LOW_IE)) &= ~source;
+ break;
+ case METAL_GPIO_INT_RISING:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_RISE_IE)) |= source;
+ break;
+ case METAL_GPIO_INT_FALLING:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_FALL_IE)) |= source;
+ break;
+ case METAL_GPIO_INT_BOTH_EDGE:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_RISE_IE)) |= source;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_FALL_IE)) |= source;
+ break;
+ case METAL_GPIO_INT_HIGH:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_HIGH_IE)) |= source;
+ break;
+ case METAL_GPIO_INT_LOW:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_LOW_IE)) |= source;
+ break;
+ case METAL_GPIO_INT_BOTH_LEVEL:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_HIGH_IE)) |= source;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_LOW_IE)) |= source;
+ break;
+ case METAL_GPIO_INT_MAX:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_RISE_IE)) |= source;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_FALL_IE)) |= source;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_HIGH_IE)) |= source;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_LOW_IE)) |= source;
+ break;
+ }
+ return 0;
+}
+
+int __metal_driver_sifive_gpio0_clear_int(struct metal_gpio *ggpio, long source, int intr_type)
+{
+ long base = __metal_driver_sifive_gpio0_base(ggpio);
+
+ switch (intr_type)
+ {
+ case METAL_GPIO_INT_RISING:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_RISE_IP)) |= source;
+ break;
+ case METAL_GPIO_INT_FALLING:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_FALL_IP)) |= source;
+ break;
+ case METAL_GPIO_INT_BOTH_EDGE:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_RISE_IP)) |= source;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_FALL_IP)) |= source;
+ break;
+ case METAL_GPIO_INT_HIGH:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_HIGH_IP)) |= source;
+ break;
+ case METAL_GPIO_INT_LOW:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_LOW_IP)) |= source;
+ break;
+ case METAL_GPIO_INT_BOTH_LEVEL:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_HIGH_IP)) |= source;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_LOW_IP)) |= source;
+ break;
+ case METAL_GPIO_INT_MAX:
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_RISE_IP)) |= source;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_FALL_IP)) |= source;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_HIGH_IP)) |= source;
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_GPIO0_LOW_IP)) |= source;
+ break;
+ }
+ return 0;
+}
+
+struct metal_interrupt *
+__metal_driver_gpio_interrupt_controller(struct metal_gpio *gpio)
+{
+ return __metal_driver_sifive_gpio0_interrupt_parent(gpio);
+}
+
+int __metal_driver_gpio_get_interrupt_id(struct metal_gpio *gpio, int pin)
+{
+ int irq;
+ irq = __metal_driver_sifive_gpio0_interrupt_lines(gpio, pin);
+ return irq;
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_gpio0) = {
+ .gpio.disable_input = __metal_driver_sifive_gpio0_disable_input,
+ .gpio.enable_input = __metal_driver_sifive_gpio0_enable_input,
+ .gpio.input = __metal_driver_sifive_gpio0_input,
+ .gpio.output = __metal_driver_sifive_gpio0_output,
+ .gpio.disable_output = __metal_driver_sifive_gpio0_disable_output,
+ .gpio.enable_output = __metal_driver_sifive_gpio0_enable_output,
+ .gpio.output_set = __metal_driver_sifive_gpio0_output_set,
+ .gpio.output_clear = __metal_driver_sifive_gpio0_output_clear,
+ .gpio.output_toggle = __metal_driver_sifive_gpio0_output_toggle,
+ .gpio.enable_io = __metal_driver_sifive_gpio0_enable_io,
+ .gpio.disable_io = __metal_driver_sifive_gpio0_disable_io,
+ .gpio.config_int = __metal_driver_sifive_gpio0_config_int,
+ .gpio.clear_int = __metal_driver_sifive_gpio0_clear_int,
+ .gpio.interrupt_controller = __metal_driver_gpio_interrupt_controller,
+ .gpio.get_interrupt_id = __metal_driver_gpio_get_interrupt_id,
+};
+
+#endif /* METAL_SIFIVE_GPIO0 */
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_local-external-interrupts0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_local-external-interrupts0.c
new file mode 100644
index 000000000..1c34ca447
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_local-external-interrupts0.c
@@ -0,0 +1,151 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_LOCAL_EXTERNAL_INTERRUPTS0
+
+#include <metal/io.h>
+#include <metal/drivers/sifive_local-external-interrupts0.h>
+#include <metal/machine.h>
+
+void __metal_driver_sifive_local_external_interrupt_init(struct metal_interrupt *controller)
+{
+ struct __metal_driver_sifive_local_external_interrupts0 *local0;
+
+ local0 = (struct __metal_driver_sifive_local_external_interrupts0 *)(controller);
+ if ( !local0->init_done ) {
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_local_external_interrupts0_interrupt_parent(controller);
+
+ if (intc) {
+ /* Register its interruptswith with parent controller, aka all external to default isr */
+ for (int i = 0;
+ i < __metal_driver_sifive_local_external_interrupts0_num_interrupts(controller);
+ i++) {
+ intc->vtable->interrupt_register(intc,
+ __metal_driver_sifive_local_external_interrupts0_interrupt_lines(controller, i),
+ NULL, controller);
+ }
+ local0->init_done = 1;
+ }
+ }
+}
+
+int __metal_driver_sifive_local_external_interrupt_register(struct metal_interrupt *controller,
+ int id, metal_interrupt_handler_t isr,
+ void *priv)
+{
+ int rc = -1;
+
+ if (id != 0) {
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_local_external_interrupts0_interrupt_parent(controller);
+
+ /* Enable its interrupts with parent controller */
+ if (intc) {
+ rc = intc->vtable->interrupt_register(intc, id, isr, priv);
+ }
+ }
+ return rc;
+}
+
+int __metal_driver_sifive_local_external_interrupt_enable(struct metal_interrupt *controller, int id)
+{
+ int rc = -1;
+
+ if (id != 0) {
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_local_external_interrupts0_interrupt_parent(controller);
+
+ /* Enable its interrupts with parent controller */
+ if (intc) {
+ rc = intc->vtable->interrupt_enable(intc, id);
+ }
+ }
+ return rc;
+}
+
+int __metal_driver_sifive_local_external_interrupt_disable(struct metal_interrupt *controller, int id)
+{
+ int rc = -1;
+
+ if (id != 0) {
+ struct metal_interrupt *intc =
+ __metal_driver_sifive_local_external_interrupts0_interrupt_parent(controller);
+
+ /* Enable its interrupts with parent controller */
+ if (intc) {
+ rc = intc->vtable->interrupt_disable(intc, id);
+ }
+ }
+ return rc;
+}
+
+int __metal_driver_sifive_local_external_interrupt_set_threshold(struct metal_interrupt *controller,
+ unsigned int threshold)
+{
+ /* Core controller does not support threshold configuration */
+ return -1;
+}
+
+unsigned int __metal_driver_sifive_local_external_interrupt_get_threshold(struct metal_interrupt *controller)
+{
+ /* Core controller does not support threshold configuration */
+ return 0;
+}
+
+
+int __metal_driver_sifive_local_external_interrupt_set_priority(struct metal_interrupt *controller,
+ int id, unsigned int priority)
+{
+ /* Core controller does not support priority configuration */
+ return -1;
+}
+
+unsigned int __metal_driver_sifive_local_external_interrupt_get_priority(struct metal_interrupt *controller, int id)
+{
+ /* Core controller does not support priority configuration */
+ return 0;
+}
+
+int __metal_driver_sifive_local_external_command_request (struct metal_interrupt *controller,
+ int command, void *data)
+{
+ int idx;
+ int rc = -1;
+
+ switch (command) {
+ case METAL_MAX_INTERRUPT_GET:
+ rc = __metal_driver_sifive_local_external_interrupts0_num_interrupts(controller);
+ break;
+ case METAL_INDEX_INTERRUPT_GET:
+ rc = 0;
+ if (data) {
+ idx = *(int *)data;
+ rc = __metal_driver_sifive_local_external_interrupts0_interrupt_lines(controller, idx);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return rc;
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_local_external_interrupts0) = {
+ .local0_vtable.interrupt_init = __metal_driver_sifive_local_external_interrupt_init,
+ .local0_vtable.interrupt_register = __metal_driver_sifive_local_external_interrupt_register,
+ .local0_vtable.interrupt_enable = __metal_driver_sifive_local_external_interrupt_enable,
+ .local0_vtable.interrupt_disable = __metal_driver_sifive_local_external_interrupt_disable,
+ .local0_vtable.interrupt_get_threshold = __metal_driver_sifive_local_external_interrupt_get_threshold,
+ .local0_vtable.interrupt_set_threshold = __metal_driver_sifive_local_external_interrupt_set_threshold,
+ .local0_vtable.interrupt_get_priority = __metal_driver_sifive_local_external_interrupt_get_priority,
+ .local0_vtable.interrupt_set_priority = __metal_driver_sifive_local_external_interrupt_set_priority,
+ .local0_vtable.command_request = __metal_driver_sifive_local_external_command_request,
+};
+
+#endif
+
+typedef int no_empty_translation_units;
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_rtc0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_rtc0.c
new file mode 100644
index 000000000..79b81e7bf
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_rtc0.c
@@ -0,0 +1,121 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_RTC0
+
+#include <metal/drivers/sifive_rtc0.h>
+#include <metal/machine.h>
+
+#include <limits.h>
+
+/* RTCCFG */
+#define METAL_RTCCFG_RTCSCALE_MASK 0xF
+#define METAL_RTCCFG_ENALWAYS (1 << 12)
+#define METAL_RTCCFG_IP0 (1 << 28)
+
+/* RTCCMP0 */
+#define METAL_RTCCMP0_MAX UINT32_MAX
+
+#define RTC_REG(base, offset) (((unsigned long)base + offset))
+#define RTC_REGW(base, offset) (__METAL_ACCESS_ONCE((__metal_io_u32 *)RTC_REG(base, offset)))
+
+uint64_t __metal_driver_sifive_rtc0_get_rate(const struct metal_rtc *const rtc) {
+ const struct metal_clock *const clock = __metal_driver_sifive_rtc0_clock(rtc);
+ return metal_clock_get_rate_hz(clock);
+}
+
+uint64_t __metal_driver_sifive_rtc0_set_rate(const struct metal_rtc *const rtc, const uint64_t rate) {
+ const struct metal_clock *const clock = __metal_driver_sifive_rtc0_clock(rtc);
+ return metal_clock_get_rate_hz(clock);
+}
+
+uint64_t __metal_driver_sifive_rtc0_get_compare(const struct metal_rtc *const rtc) {
+ const uint64_t base = __metal_driver_sifive_rtc0_control_base(rtc);
+
+ const uint32_t shift = RTC_REGW(base, METAL_SIFIVE_RTC0_RTCCFG) & METAL_RTCCFG_RTCSCALE_MASK;
+
+ return ((uint64_t)RTC_REGW(base, METAL_SIFIVE_RTC0_RTCCMP0) << shift);
+}
+
+uint64_t __metal_driver_sifive_rtc0_set_compare(const struct metal_rtc *const rtc, const uint64_t compare) {
+ const uint64_t base = __metal_driver_sifive_rtc0_control_base(rtc);
+
+ /* Determine the bit shift and shifted value to store in rtccmp0/rtccfg.scale */
+ uint32_t shift = 0;
+ uint64_t comp_shifted = compare;
+ while (comp_shifted > METAL_RTCCMP0_MAX) {
+ shift += 1;
+ comp_shifted = comp_shifted >> shift;
+ }
+
+ /* Set the value of rtccfg.scale */
+ uint32_t cfg = RTC_REGW(base, METAL_SIFIVE_RTC0_RTCCFG);
+ cfg &= ~(METAL_RTCCFG_RTCSCALE_MASK);
+ cfg |= (METAL_RTCCFG_RTCSCALE_MASK & shift);
+ RTC_REGW(base, METAL_SIFIVE_RTC0_RTCCFG) = cfg;
+
+ /* Set the value of rtccmp0 */
+ RTC_REGW(base, METAL_SIFIVE_RTC0_RTCCMP0) = (uint32_t) comp_shifted;
+
+ return __metal_driver_sifive_rtc0_get_compare(rtc);
+}
+
+uint64_t __metal_driver_sifive_rtc0_get_count(const struct metal_rtc *const rtc) {
+ const uint64_t base = __metal_driver_sifive_rtc0_control_base(rtc);
+
+ uint64_t count = RTC_REGW(base, METAL_SIFIVE_RTC0_RTCCOUNTHI);
+ count <<= 32;
+ count |= RTC_REGW(base, METAL_SIFIVE_RTC0_RTCCOUNTLO);
+
+ return count;
+}
+
+uint64_t __metal_driver_sifive_rtc0_set_count(const struct metal_rtc *const rtc, const uint64_t count) {
+ const uint64_t base = __metal_driver_sifive_rtc0_control_base(rtc);
+
+ RTC_REGW(base, METAL_SIFIVE_RTC0_RTCCOUNTHI) = (UINT_MAX & (count >> 32));
+ RTC_REGW(base, METAL_SIFIVE_RTC0_RTCCOUNTLO) = (UINT_MAX & count);
+
+ return __metal_driver_sifive_rtc0_get_count(rtc);
+}
+
+int __metal_driver_sifive_rtc0_run(const struct metal_rtc *const rtc, const enum metal_rtc_run_option option) {
+ const uint64_t base = __metal_driver_sifive_rtc0_control_base(rtc);
+
+ switch (option) {
+ default:
+ case METAL_RTC_STOP:
+ RTC_REGW(base, METAL_SIFIVE_RTC0_RTCCFG) &= ~(METAL_RTCCFG_ENALWAYS);
+ break;
+ case METAL_RTC_RUN:
+ RTC_REGW(base, METAL_SIFIVE_RTC0_RTCCFG) |= METAL_RTCCFG_ENALWAYS;
+ break;
+ }
+
+ return 0;
+}
+
+struct metal_interrupt *__metal_driver_sifive_rtc0_get_interrupt(const struct metal_rtc *const rtc) {
+ return __metal_driver_sifive_rtc0_interrupt_parent(rtc);
+}
+
+int __metal_driver_sifive_rtc0_get_interrupt_id(const struct metal_rtc *const rtc) {
+ return __metal_driver_sifive_rtc0_interrupt_line(rtc);
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_rtc0) = {
+ .rtc.get_rate = __metal_driver_sifive_rtc0_get_rate,
+ .rtc.set_rate = __metal_driver_sifive_rtc0_set_rate,
+ .rtc.get_compare = __metal_driver_sifive_rtc0_get_compare,
+ .rtc.set_compare = __metal_driver_sifive_rtc0_set_compare,
+ .rtc.get_count = __metal_driver_sifive_rtc0_get_count,
+ .rtc.set_count = __metal_driver_sifive_rtc0_set_count,
+ .rtc.run = __metal_driver_sifive_rtc0_run,
+ .rtc.get_interrupt = __metal_driver_sifive_rtc0_get_interrupt,
+ .rtc.get_interrupt_id = __metal_driver_sifive_rtc0_get_interrupt_id,
+};
+
+#endif
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_spi0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_spi0.c
new file mode 100644
index 000000000..2a346354f
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_spi0.c
@@ -0,0 +1,405 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_SPI0
+#include <metal/drivers/sifive_spi0.h>
+#include <metal/io.h>
+#include <metal/machine.h>
+#include <metal/time.h>
+#include <time.h>
+
+/* Register fields */
+#define METAL_SPI_SCKDIV_MASK 0xFFF
+
+#define METAL_SPI_SCKMODE_PHA_SHIFT 0
+#define METAL_SPI_SCKMODE_POL_SHIFT 1
+
+#define METAL_SPI_CSMODE_MASK 3
+#define METAL_SPI_CSMODE_AUTO 0
+#define METAL_SPI_CSMODE_HOLD 2
+#define METAL_SPI_CSMODE_OFF 3
+
+#define METAL_SPI_PROTO_MASK 3
+#define METAL_SPI_PROTO_SINGLE 0
+#define METAL_SPI_PROTO_DUAL 1
+#define METAL_SPI_PROTO_QUAD 2
+
+#define METAL_SPI_ENDIAN_LSB 4
+
+#define METAL_SPI_DISABLE_RX 8
+
+#define METAL_SPI_FRAME_LEN_SHIFT 16
+#define METAL_SPI_FRAME_LEN_MASK (0xF << METAL_SPI_FRAME_LEN_SHIFT)
+
+#define METAL_SPI_TXDATA_FULL (1 << 31)
+#define METAL_SPI_RXDATA_EMPTY (1 << 31)
+#define METAL_SPI_TXMARK_MASK 7
+#define METAL_SPI_TXWM 1
+#define METAL_SPI_TXRXDATA_MASK (0xFF)
+
+#define METAL_SPI_INTERVAL_SHIFT 16
+
+#define METAL_SPI_CONTROL_IO 0
+#define METAL_SPI_CONTROL_MAPPED 1
+
+#define METAL_SPI_REG(offset) (((unsigned long)control_base + offset))
+#define METAL_SPI_REGB(offset) (__METAL_ACCESS_ONCE((__metal_io_u8 *)METAL_SPI_REG(offset)))
+#define METAL_SPI_REGW(offset) (__METAL_ACCESS_ONCE((__metal_io_u32 *)METAL_SPI_REG(offset)))
+
+#define METAL_SPI_RXDATA_TIMEOUT 1
+
+static int configure_spi(struct __metal_driver_sifive_spi0 *spi, struct metal_spi_config *config)
+{
+ long control_base = __metal_driver_sifive_spi0_control_base((struct metal_spi *)spi);
+ /* Set protocol */
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) &= ~(METAL_SPI_PROTO_MASK);
+ switch (config->protocol) {
+ case METAL_SPI_SINGLE:
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) |= METAL_SPI_PROTO_SINGLE;
+ break;
+ case METAL_SPI_DUAL:
+ if (config->multi_wire == MULTI_WIRE_ALL)
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) |= METAL_SPI_PROTO_DUAL;
+ else
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) |= METAL_SPI_PROTO_SINGLE;
+ break;
+ case METAL_SPI_QUAD:
+ if (config->multi_wire == MULTI_WIRE_ALL)
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) |= METAL_SPI_PROTO_QUAD;
+ else
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) |= METAL_SPI_PROTO_SINGLE;
+ break;
+ default:
+ /* Unsupported value */
+ return -1;
+ }
+
+ /* Set Polarity */
+ if(config->polarity) {
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_SCKMODE) |= (1 << METAL_SPI_SCKMODE_PHA_SHIFT);
+ } else {
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_SCKMODE) &= ~(1 << METAL_SPI_SCKMODE_PHA_SHIFT);
+ }
+
+ /* Set Phase */
+ if(config->phase) {
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_SCKMODE) |= (1 << METAL_SPI_SCKMODE_POL_SHIFT);
+ } else {
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_SCKMODE) &= ~(1 << METAL_SPI_SCKMODE_POL_SHIFT);
+ }
+
+ /* Set Endianness */
+ if(config->little_endian) {
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) |= METAL_SPI_ENDIAN_LSB;
+ } else {
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) &= ~(METAL_SPI_ENDIAN_LSB);
+ }
+
+ /* Always populate receive FIFO */
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) &= ~(METAL_SPI_DISABLE_RX);
+
+ /* Set CS Active */
+ if(config->cs_active_high) {
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_CSDEF) = 0;
+ } else {
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_CSDEF) = 1;
+ }
+
+ /* Set frame length */
+ if((METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) & METAL_SPI_FRAME_LEN_MASK) != (8 << METAL_SPI_FRAME_LEN_SHIFT)) {
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) &= ~(METAL_SPI_FRAME_LEN_MASK);
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) |= (8 << METAL_SPI_FRAME_LEN_SHIFT);
+ }
+
+ /* Set CS line */
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_CSID) = 1 << (config->csid);
+
+ /* Toggle off memory-mapped SPI flash mode, toggle on programmable IO mode
+ * It seems that with this line uncommented, the debugger cannot have access
+ * to the chip at all because it assumes the chip is in memory-mapped mode.
+ * I have to compile the code with this line commented and launch gdb,
+ * reset cores, reset $pc, set *((int *) 0x20004060) = 0, (set the flash
+ * interface control register to programmable I/O mode) and then continue
+ * Alternative, comment out the "flash" line in openocd.cfg */
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FCTRL) = METAL_SPI_CONTROL_IO;
+
+ return 0;
+}
+
+static void spi_mode_switch(struct __metal_driver_sifive_spi0 *spi,
+ struct metal_spi_config *config,
+ unsigned int trans_stage) {
+ long control_base =
+ __metal_driver_sifive_spi0_control_base((struct metal_spi *)spi);
+
+ if (config->multi_wire == trans_stage) {
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) &= ~(METAL_SPI_PROTO_MASK);
+ switch (config->protocol) {
+ case METAL_SPI_DUAL:
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) |= METAL_SPI_PROTO_DUAL;
+ break;
+ case METAL_SPI_QUAD:
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) |= METAL_SPI_PROTO_QUAD;
+ break;
+ default:
+ /* Unsupported value */
+ return;
+ }
+ }
+}
+
+int __metal_driver_sifive_spi0_transfer(struct metal_spi *gspi,
+ struct metal_spi_config *config,
+ size_t len,
+ char *tx_buf,
+ char *rx_buf)
+{
+ struct __metal_driver_sifive_spi0 *spi = (void *)gspi;
+ long control_base = __metal_driver_sifive_spi0_control_base(gspi);
+ int rc = 0;
+ size_t i = 0;
+
+ rc = configure_spi(spi, config);
+ if(rc != 0) {
+ return rc;
+ }
+
+ /* Hold the chip select line for all len transferred */
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_CSMODE) &= ~(METAL_SPI_CSMODE_MASK);
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_CSMODE) |= METAL_SPI_CSMODE_HOLD;
+
+ unsigned long rxdata;
+
+ /* Declare time_t variables to break out of infinite while loop */
+ time_t endwait;
+
+ for (i = 0; i < config->cmd_num; i++) {
+
+ while (METAL_SPI_REGW(METAL_SIFIVE_SPI0_TXDATA) & METAL_SPI_TXDATA_FULL)
+ ;
+
+ if (tx_buf) {
+ METAL_SPI_REGB(METAL_SIFIVE_SPI0_TXDATA) = tx_buf[i];
+ } else {
+ METAL_SPI_REGB(METAL_SIFIVE_SPI0_TXDATA) = 0;
+ }
+
+ endwait = metal_time() + METAL_SPI_RXDATA_TIMEOUT;
+
+ while ((rxdata = METAL_SPI_REGW(METAL_SIFIVE_SPI0_RXDATA)) &
+ METAL_SPI_RXDATA_EMPTY) {
+ if (metal_time() > endwait) {
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_CSMODE) &=
+ ~(METAL_SPI_CSMODE_MASK);
+
+ return 1;
+ }
+ }
+
+ if (rx_buf) {
+ rx_buf[i] = (char)(rxdata & METAL_SPI_TXRXDATA_MASK);
+ }
+ }
+
+ /* switch to Dual/Quad mode */
+ spi_mode_switch(spi, config, MULTI_WIRE_ADDR_DATA);
+
+ /* Send Addr data */
+ for (; i < (config->cmd_num + config->addr_num); i++) {
+
+ while (METAL_SPI_REGW(METAL_SIFIVE_SPI0_TXDATA) & METAL_SPI_TXDATA_FULL)
+ ;
+
+ if (tx_buf) {
+ METAL_SPI_REGB(METAL_SIFIVE_SPI0_TXDATA) = tx_buf[i];
+ } else {
+ METAL_SPI_REGB(METAL_SIFIVE_SPI0_TXDATA) = 0;
+ }
+
+ endwait = metal_time() + METAL_SPI_RXDATA_TIMEOUT;
+
+ while ((rxdata = METAL_SPI_REGW(METAL_SIFIVE_SPI0_RXDATA)) &
+ METAL_SPI_RXDATA_EMPTY) {
+ if (metal_time() > endwait) {
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_CSMODE) &=
+ ~(METAL_SPI_CSMODE_MASK);
+
+ return 1;
+ }
+ }
+
+ if (rx_buf) {
+ rx_buf[i] = (char)(rxdata & METAL_SPI_TXRXDATA_MASK);
+ }
+ }
+
+ /* Send Dummy data */
+ for (; i < (config->cmd_num + config->addr_num + config->dummy_num); i++) {
+
+ while (METAL_SPI_REGW(METAL_SIFIVE_SPI0_TXDATA) & METAL_SPI_TXDATA_FULL)
+ ;
+
+ if (tx_buf) {
+ METAL_SPI_REGB(METAL_SIFIVE_SPI0_TXDATA) = tx_buf[i];
+ } else {
+ METAL_SPI_REGB(METAL_SIFIVE_SPI0_TXDATA) = 0;
+ }
+
+ endwait = metal_time() + METAL_SPI_RXDATA_TIMEOUT;
+
+ while ((rxdata = METAL_SPI_REGW(METAL_SIFIVE_SPI0_RXDATA)) &
+ METAL_SPI_RXDATA_EMPTY) {
+ if (metal_time() > endwait) {
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_CSMODE) &=
+ ~(METAL_SPI_CSMODE_MASK);
+ return 1;
+ }
+ }
+ if (rx_buf) {
+ rx_buf[i] = (char)(rxdata & METAL_SPI_TXRXDATA_MASK);
+ }
+ }
+
+ /* switch to Dual/Quad mode */
+ spi_mode_switch(spi, config, MULTI_WIRE_DATA_ONLY);
+
+ for (; i < len; i++) {
+ /* Master send bytes to the slave */
+
+ /* Wait for TXFIFO to not be full */
+ while (METAL_SPI_REGW(METAL_SIFIVE_SPI0_TXDATA) & METAL_SPI_TXDATA_FULL);
+
+ /* Transfer byte by modifying the least significant byte in the TXDATA register */
+ if (tx_buf) {
+ METAL_SPI_REGB(METAL_SIFIVE_SPI0_TXDATA) = tx_buf[i];
+ } else {
+ /* Transfer a 0 byte if the sending buffer is NULL */
+ METAL_SPI_REGB(METAL_SIFIVE_SPI0_TXDATA) = 0;
+ }
+
+ /* Master receives bytes from the RX FIFO */
+
+ /* Wait for RXFIFO to not be empty, but break the nested loops if timeout
+ * this timeout method needs refining, preferably taking into account
+ * the device specs */
+ endwait = metal_time() + METAL_SPI_RXDATA_TIMEOUT;
+
+ while ((rxdata = METAL_SPI_REGW(METAL_SIFIVE_SPI0_RXDATA)) & METAL_SPI_RXDATA_EMPTY) {
+ if (metal_time() > endwait) {
+ /* If timeout, deassert the CS */
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_CSMODE) &= ~(METAL_SPI_CSMODE_MASK);
+
+ /* If timeout, return error code 1 immediately */
+ return 1;
+ }
+ }
+
+ /* Only store the dequeued byte if the receive_buffer is not NULL */
+ if (rx_buf) {
+ rx_buf[i] = (char) (rxdata & METAL_SPI_TXRXDATA_MASK);
+ }
+ }
+
+ /* On the last byte, set CSMODE to auto so that the chip select transitions back to high
+ * The reason that CS pin is not deasserted after transmitting out the byte buffer is timing.
+ * The code on the host side likely executes faster than the ability of FIFO to send out bytes.
+ * After the host iterates through the array, fifo is likely not cleared yet. If host deasserts
+ * the CS pin immediately, the following bytes in the output FIFO will not be sent consecutively.
+ * There needs to be a better way to handle this. */
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_CSMODE) &= ~(METAL_SPI_CSMODE_MASK);
+
+ return 0;
+}
+
+int __metal_driver_sifive_spi0_get_baud_rate(struct metal_spi *gspi)
+{
+ struct __metal_driver_sifive_spi0 *spi = (void *)gspi;
+ return spi->baud_rate;
+}
+
+int __metal_driver_sifive_spi0_set_baud_rate(struct metal_spi *gspi, int baud_rate)
+{
+ long control_base = __metal_driver_sifive_spi0_control_base(gspi);
+ struct metal_clock *clock = __metal_driver_sifive_spi0_clock(gspi);
+ struct __metal_driver_sifive_spi0 *spi = (void *)gspi;
+
+ spi->baud_rate = baud_rate;
+
+ if (clock != NULL) {
+ long clock_rate = clock->vtable->get_rate_hz(clock);
+
+ /* Calculate divider */
+ long div = (clock_rate / (2 * baud_rate)) - 1;
+
+ if(div > METAL_SPI_SCKDIV_MASK) {
+ /* The requested baud rate is lower than we can support at
+ * the current clock rate */
+ return -1;
+ }
+
+ /* Set divider */
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_SCKDIV) &= ~METAL_SPI_SCKDIV_MASK;
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_SCKDIV) |= (div & METAL_SPI_SCKDIV_MASK);
+ }
+
+ return 0;
+}
+
+static void pre_rate_change_callback_func(void *priv)
+{
+ long control_base = __metal_driver_sifive_spi0_control_base((struct metal_spi *)priv);
+
+ /* Detect when the TXDATA is empty by setting the transmit watermark count
+ * to one and waiting until an interrupt is pending (indicating an empty TXFIFO) */
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_TXMARK) &= ~(METAL_SPI_TXMARK_MASK);
+ METAL_SPI_REGW(METAL_SIFIVE_SPI0_TXMARK) |= (METAL_SPI_TXMARK_MASK & 1);
+
+ while((METAL_SPI_REGW(METAL_SIFIVE_SPI0_IP) & METAL_SPI_TXWM) == 0) ;
+}
+
+static void post_rate_change_callback_func(void *priv)
+{
+ struct __metal_driver_sifive_spi0 *spi = priv;
+ metal_spi_set_baud_rate(&spi->spi, spi->baud_rate);
+}
+
+void __metal_driver_sifive_spi0_init(struct metal_spi *gspi, int baud_rate)
+{
+ struct __metal_driver_sifive_spi0 *spi = (void *)(gspi);
+ struct metal_clock *clock = __metal_driver_sifive_spi0_clock(gspi);
+ struct __metal_driver_sifive_gpio0 *pinmux = __metal_driver_sifive_spi0_pinmux(gspi);
+
+ if(clock != NULL) {
+ spi->pre_rate_change_callback.callback = &pre_rate_change_callback_func;
+ spi->pre_rate_change_callback.priv = spi;
+ metal_clock_register_pre_rate_change_callback(clock, &(spi->pre_rate_change_callback));
+
+ spi->post_rate_change_callback.callback = &post_rate_change_callback_func;
+ spi->post_rate_change_callback.priv = spi;
+ metal_clock_register_post_rate_change_callback(clock, &(spi->post_rate_change_callback));
+ }
+
+ metal_spi_set_baud_rate(&(spi->spi), baud_rate);
+
+ if (pinmux != NULL) {
+ long pinmux_output_selector = __metal_driver_sifive_spi0_pinmux_output_selector(gspi);
+ long pinmux_source_selector = __metal_driver_sifive_spi0_pinmux_source_selector(gspi);
+ pinmux->gpio.vtable->enable_io(
+ (struct metal_gpio *) pinmux,
+ pinmux_output_selector,
+ pinmux_source_selector
+ );
+ }
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_spi0) = {
+ .spi.init = __metal_driver_sifive_spi0_init,
+ .spi.transfer = __metal_driver_sifive_spi0_transfer,
+ .spi.get_baud_rate = __metal_driver_sifive_spi0_get_baud_rate,
+ .spi.set_baud_rate = __metal_driver_sifive_spi0_set_baud_rate,
+};
+#endif /* METAL_SIFIVE_SPI0 */
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_test0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_test0.c
new file mode 100644
index 000000000..79deebbf5
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_test0.c
@@ -0,0 +1,30 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_TEST0
+
+#include <metal/machine.h>
+
+#include <stdint.h>
+
+#include <metal/drivers/sifive_test0.h>
+#include <metal/io.h>
+
+void __metal_driver_sifive_test0_exit(const struct __metal_shutdown *sd, int code) __attribute__((noreturn));
+void __metal_driver_sifive_test0_exit(const struct __metal_shutdown *sd, int code)
+{
+ long base = __metal_driver_sifive_test0_base(sd);
+ uint32_t out = (code << 16) + (code == 0 ? 0x5555 : 0x3333);
+ while (1) {
+ __METAL_ACCESS_ONCE((__metal_io_u32 *)(base + METAL_SIFIVE_TEST0_FINISHER_OFFSET)) = out;
+ }
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_test0) = {
+ .shutdown.exit = &__metal_driver_sifive_test0_exit,
+};
+#endif /* METAL_SIFIVE_TEST0 */
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_trace.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_trace.c
new file mode 100644
index 000000000..8b63fbd28
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_trace.c
@@ -0,0 +1,95 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_TRACE
+
+#include <metal/drivers/sifive_trace.h>
+#include <metal/machine.h>
+
+#define TRACE_REG(offset) (((unsigned long)base + (offset)))
+#define TRACE_REG8(offset) \
+ (__METAL_ACCESS_ONCE((__metal_io_u8 *)TRACE_REG(offset)))
+#define TRACE_REG16(offset) \
+ (__METAL_ACCESS_ONCE((__metal_io_u16 *)TRACE_REG(offset)))
+#define TRACE_REG32(offset) \
+ (__METAL_ACCESS_ONCE((__metal_io_u32 *)TRACE_REG(offset)))
+
+static void write_itc_uint32(struct metal_uart *trace, uint32_t data) {
+ long base = __metal_driver_sifive_trace_base(trace);
+
+ TRACE_REG32(METAL_SIFIVE_TRACE_ITCSTIMULUS) = data;
+}
+
+static void write_itc_uint16(struct metal_uart *trace, uint16_t data) {
+ long base = __metal_driver_sifive_trace_base(trace);
+
+ TRACE_REG16(METAL_SIFIVE_TRACE_ITCSTIMULUS + 2) = data;
+}
+
+static void write_itc_uint8(struct metal_uart *trace, uint8_t data) {
+ long base = __metal_driver_sifive_trace_base(trace);
+
+ TRACE_REG8(METAL_SIFIVE_TRACE_ITCSTIMULUS + 3) = data;
+}
+
+int __metal_driver_sifive_trace_putc(struct metal_uart *trace,
+ unsigned char c) {
+ static uint32_t buffer = 0;
+ static int bytes_in_buffer = 0;
+
+ buffer |= (((uint32_t)c) << (bytes_in_buffer * 8));
+
+ bytes_in_buffer += 1;
+
+ if (bytes_in_buffer >= 4) {
+ write_itc_uint32(trace, buffer);
+
+ buffer = 0;
+ bytes_in_buffer = 0;
+ } else if ((c == '\n') || (c == '\r')) { // partial write
+ switch (bytes_in_buffer) {
+ case 3: // do a full word write
+ write_itc_uint16(trace, (uint16_t)(buffer));
+ write_itc_uint8(trace, (uint8_t)(buffer >> 16));
+ break;
+ case 2: // do a 16 bit write
+ write_itc_uint16(trace, (uint16_t)buffer);
+ break;
+ case 1: // do a 1 byte write
+ write_itc_uint8(trace, (uint8_t)buffer);
+ break;
+ }
+
+ buffer = 0;
+ bytes_in_buffer = 0;
+ }
+
+ return (int)c;
+}
+
+void __metal_driver_sifive_trace_init(struct metal_uart *trace, int baud_rate) {
+ // The only init we do here is to make sure ITC 0 is enabled. It is up to
+ // Freedom Studio or other mechanisms to make sure tracing is enabled. If we
+ // try to enable tracing here, it will likely conflict with Freedom Studio,
+ // and they will just fight with each other.
+
+ long base = __metal_driver_sifive_trace_base(trace);
+
+ TRACE_REG32(METAL_SIFIVE_TRACE_ITCTRACEENABLE) |= 0x00000001;
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_trace) = {
+ .uart.init = __metal_driver_sifive_trace_init,
+ .uart.putc = __metal_driver_sifive_trace_putc,
+ .uart.getc = NULL,
+
+ .uart.get_baud_rate = NULL,
+ .uart.set_baud_rate = NULL,
+
+ .uart.controller_interrupt = NULL,
+ .uart.get_interrupt_id = NULL,
+};
+
+#endif /* METAL_SIFIVE_TRACE */
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_uart0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_uart0.c
new file mode 100644
index 000000000..2e8098aa7
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_uart0.c
@@ -0,0 +1,173 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_UART0
+
+#include <metal/drivers/sifive_uart0.h>
+#include <metal/machine.h>
+
+/* TXDATA Fields */
+#define UART_TXEN (1 << 0)
+#define UART_TXFULL (1 << 31)
+
+/* RXDATA Fields */
+#define UART_RXEN (1 << 0)
+#define UART_RXEMPTY (1 << 31)
+
+/* TXCTRL Fields */
+#define UART_NSTOP (1 << 1)
+#define UART_TXCNT(count) ((0x7 & count) << 16)
+
+/* IP Fields */
+#define UART_TXWM (1 << 0)
+
+#define UART_REG(offset) (((unsigned long)control_base + offset))
+#define UART_REGB(offset) (__METAL_ACCESS_ONCE((__metal_io_u8 *)UART_REG(offset)))
+#define UART_REGW(offset) (__METAL_ACCESS_ONCE((__metal_io_u32 *)UART_REG(offset)))
+
+struct metal_interrupt *
+__metal_driver_sifive_uart0_interrupt_controller(struct metal_uart *uart)
+{
+ return __metal_driver_sifive_uart0_interrupt_parent(uart);
+}
+
+int __metal_driver_sifive_uart0_get_interrupt_id(struct metal_uart *uart)
+{
+ return (__metal_driver_sifive_uart0_interrupt_line(uart) + METAL_INTERRUPT_ID_GL0);
+}
+
+
+int __metal_driver_sifive_uart0_txready(struct metal_uart *uart)
+{
+ long control_base = __metal_driver_sifive_uart0_control_base(uart);
+
+ return !((UART_REGW(METAL_SIFIVE_UART0_TXDATA) & UART_TXFULL));
+}
+
+
+int __metal_driver_sifive_uart0_putc(struct metal_uart *uart, int c)
+{
+ long control_base = __metal_driver_sifive_uart0_control_base(uart);
+
+ while (!__metal_driver_sifive_uart0_txready(uart)) {
+ /* wait */
+ }
+ UART_REGW(METAL_SIFIVE_UART0_TXDATA) = c;
+ return 0;
+}
+
+
+int __metal_driver_sifive_uart0_getc(struct metal_uart *uart, int *c)
+{
+ uint32_t ch;
+ long control_base = __metal_driver_sifive_uart0_control_base(uart);
+ /* No seperate status register, we get status and the byte at same time */
+ ch = UART_REGW(METAL_SIFIVE_UART0_RXDATA);;
+ if( ch & UART_RXEMPTY ){
+ *c = -1; /* aka: EOF in most of the world */
+ } else {
+ *c = ch & 0x0ff;
+ }
+ return 0;
+}
+
+
+int __metal_driver_sifive_uart0_get_baud_rate(struct metal_uart *guart)
+{
+ struct __metal_driver_sifive_uart0 *uart = (void *)guart;
+ return uart->baud_rate;
+}
+
+int __metal_driver_sifive_uart0_set_baud_rate(struct metal_uart *guart, int baud_rate)
+{
+ struct __metal_driver_sifive_uart0 *uart = (void *)guart;
+ long control_base = __metal_driver_sifive_uart0_control_base(guart);
+ struct metal_clock *clock = __metal_driver_sifive_uart0_clock(guart);
+
+ uart->baud_rate = baud_rate;
+
+ if (clock != NULL) {
+ long clock_rate = clock->vtable->get_rate_hz(clock);
+ UART_REGW(METAL_SIFIVE_UART0_DIV) = clock_rate / baud_rate - 1;
+ UART_REGW(METAL_SIFIVE_UART0_TXCTRL) |= UART_TXEN;
+ UART_REGW(METAL_SIFIVE_UART0_RXCTRL) |= UART_RXEN;
+ }
+ return 0;
+}
+
+static void pre_rate_change_callback_func(void *priv)
+{
+ struct __metal_driver_sifive_uart0 *uart = priv;
+ long control_base = __metal_driver_sifive_uart0_control_base((struct metal_uart *)priv);
+ struct metal_clock *clock = __metal_driver_sifive_uart0_clock((struct metal_uart *)priv);
+
+ /* Detect when the TXDATA is empty by setting the transmit watermark count
+ * to one and waiting until an interrupt is pending */
+
+ UART_REGW(METAL_SIFIVE_UART0_TXCTRL) &= ~(UART_TXCNT(0x7));
+ UART_REGW(METAL_SIFIVE_UART0_TXCTRL) |= UART_TXCNT(1);
+
+ while((UART_REGW(METAL_SIFIVE_UART0_IP) & UART_TXWM) == 0) ;
+
+ /* When the TXDATA clears, the UART is still shifting out the last byte.
+ * Calculate the time we must drain to finish transmitting and then wait
+ * that long. */
+
+ long bits_per_symbol = (UART_REGW(METAL_SIFIVE_UART0_TXCTRL) & (1 << 1)) ? 9 : 10;
+ long clk_freq = clock->vtable->get_rate_hz(clock);
+ long cycles_to_wait = bits_per_symbol * clk_freq / uart->baud_rate;
+
+ for(volatile long x = 0; x < cycles_to_wait; x++)
+ __asm__("nop");
+}
+
+static void post_rate_change_callback_func(void *priv)
+{
+ struct __metal_driver_sifive_uart0 *uart = priv;
+ metal_uart_set_baud_rate(&uart->uart, uart->baud_rate);
+}
+
+void __metal_driver_sifive_uart0_init(struct metal_uart *guart, int baud_rate)
+{
+ struct __metal_driver_sifive_uart0 *uart = (void *)(guart);
+ struct metal_clock *clock = __metal_driver_sifive_uart0_clock(guart);
+ struct __metal_driver_sifive_gpio0 *pinmux = __metal_driver_sifive_uart0_pinmux(guart);
+
+ if(clock != NULL) {
+ uart->pre_rate_change_callback.callback = &pre_rate_change_callback_func;
+ uart->pre_rate_change_callback.priv = guart;
+ metal_clock_register_pre_rate_change_callback(clock, &(uart->pre_rate_change_callback));
+
+ uart->post_rate_change_callback.callback = &post_rate_change_callback_func;
+ uart->post_rate_change_callback.priv = guart;
+ metal_clock_register_post_rate_change_callback(clock, &(uart->post_rate_change_callback));
+ }
+
+ metal_uart_set_baud_rate(&(uart->uart), baud_rate);
+
+ if (pinmux != NULL) {
+ long pinmux_output_selector = __metal_driver_sifive_uart0_pinmux_output_selector(guart);
+ long pinmux_source_selector = __metal_driver_sifive_uart0_pinmux_source_selector(guart);
+ pinmux->gpio.vtable->enable_io(
+ (struct metal_gpio *) pinmux,
+ pinmux_output_selector,
+ pinmux_source_selector
+ );
+ }
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_uart0) = {
+ .uart.init = __metal_driver_sifive_uart0_init,
+ .uart.putc = __metal_driver_sifive_uart0_putc,
+ .uart.getc = __metal_driver_sifive_uart0_getc,
+ .uart.get_baud_rate = __metal_driver_sifive_uart0_get_baud_rate,
+ .uart.set_baud_rate = __metal_driver_sifive_uart0_set_baud_rate,
+ .uart.controller_interrupt = __metal_driver_sifive_uart0_interrupt_controller,
+ .uart.get_interrupt_id = __metal_driver_sifive_uart0_get_interrupt_id,
+};
+
+#endif /* METAL_SIFIVE_UART0 */
+
+typedef int no_empty_translation_units;
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_wdog0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_wdog0.c
new file mode 100644
index 000000000..1a6cf362e
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/drivers/sifive_wdog0.c
@@ -0,0 +1,213 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine/platform.h>
+
+#ifdef METAL_SIFIVE_WDOG0
+
+#include <metal/drivers/sifive_uart0.h>
+#include <metal/machine.h>
+
+#include <limits.h>
+
+/* WDOGCFG */
+#define METAL_WDOGCFG_SCALE_MASK 7
+#define METAL_WDOGCFG_RSTEN (1 << 8)
+#define METAL_WDOGCFG_ZEROCMP (1 << 9)
+#define METAL_WDOGCFG_ENALWAYS (1 << 12)
+#define METAL_WDOGCFG_COREAWAKE (1 << 13)
+#define METAL_WDOGCFG_IP (1 << 28)
+
+/* WDOGCMP */
+#define METAL_WDOGCMP_MASK 0xFFFF
+
+#define WDOG_REG(base, offset) (((unsigned long)base + offset))
+#define WDOG_REGB(base, offset) (__METAL_ACCESS_ONCE((__metal_io_u8 *)WDOG_REG(base, offset)))
+#define WDOG_REGW(base, offset) (__METAL_ACCESS_ONCE((__metal_io_u32 *)WDOG_REG(base, offset)))
+
+/* All writes to watchdog registers must be precedded by a write of
+ * a magic number to WDOGKEY */
+#define WDOG_UNLOCK(base) (WDOG_REGW(base, METAL_SIFIVE_WDOG0_WDOGKEY) = METAL_SIFIVE_WDOG0_MAGIC_KEY)
+
+/* Unlock the watchdog and then perform a register access */
+#define WDOG_UNLOCK_REGW(base, offset) \
+ WDOG_UNLOCK(base);\
+ WDOG_REGW(base, offset)
+
+int __metal_driver_sifive_wdog0_feed(const struct metal_watchdog *const wdog)
+{
+ const uintptr_t base = (uintptr_t)__metal_driver_sifive_wdog0_control_base(wdog);
+
+ WDOG_UNLOCK_REGW(base, METAL_SIFIVE_WDOG0_WDOGFEED) = METAL_SIFIVE_WDOG0_MAGIC_FOOD;
+
+ return 0;
+}
+
+long int __metal_driver_sifive_wdog0_get_rate(const struct metal_watchdog *const wdog)
+{
+ const uintptr_t base = (uintptr_t)__metal_driver_sifive_wdog0_control_base(wdog);
+ const struct metal_clock *const clock = __metal_driver_sifive_wdog0_clock(wdog);
+
+ const long int clock_rate = metal_clock_get_rate_hz(clock);
+
+ if (clock_rate == 0)
+ return -1;
+
+ const unsigned int scale = (WDOG_REGW(base, METAL_SIFIVE_WDOG0_WDOGCFG) & METAL_WDOGCFG_SCALE_MASK);
+
+ return clock_rate / (1 << scale);
+}
+
+long int __metal_driver_sifive_wdog0_set_rate(const struct metal_watchdog *const wdog, const long int rate)
+{
+ const uintptr_t base = (uintptr_t)__metal_driver_sifive_wdog0_control_base(wdog);
+ const struct metal_clock *const clock = __metal_driver_sifive_wdog0_clock(wdog);
+
+ const long int clock_rate = metal_clock_get_rate_hz(clock);
+
+ if (rate >= clock_rate) {
+ /* We can't scale the rate above the driving clock. Clear the scale
+ * field and return the driving clock rate */
+ WDOG_UNLOCK_REGW(base, METAL_SIFIVE_WDOG0_WDOGCFG) &= ~(METAL_WDOGCFG_SCALE_MASK);
+ return clock_rate;
+ }
+
+ /* Look for the closest scale value */
+ long min_diff = LONG_MAX;
+ unsigned int min_scale = 0;
+ for (int i = 0; i < METAL_WDOGCFG_SCALE_MASK; i++) {
+ const long int new_rate = clock_rate / (1 << i);
+
+ long int diff = rate - new_rate;
+ if (diff < 0)
+ diff *= -1;
+
+ if (diff < min_diff) {
+ min_diff = diff;
+ min_scale = i;
+ }
+ }
+
+ WDOG_UNLOCK_REGW(base, METAL_SIFIVE_WDOG0_WDOGCFG) &= ~(METAL_WDOGCFG_SCALE_MASK);
+ WDOG_UNLOCK_REGW(base, METAL_SIFIVE_WDOG0_WDOGCFG) |= (METAL_WDOGCFG_SCALE_MASK & min_scale);
+
+ return clock_rate / (1 << min_scale);
+}
+
+long int __metal_driver_sifive_wdog0_get_timeout(const struct metal_watchdog *const wdog)
+{
+ const uintptr_t base = (uintptr_t)__metal_driver_sifive_wdog0_control_base(wdog);
+
+ return (WDOG_REGW(base, METAL_SIFIVE_WDOG0_WDOGCMP) & METAL_WDOGCMP_MASK);
+}
+
+long int __metal_driver_sifive_wdog0_set_timeout(const struct metal_watchdog *const wdog, const long int timeout)
+{
+ const uintptr_t base = (uintptr_t)__metal_driver_sifive_wdog0_control_base(wdog);
+
+ /* Cap the timeout at the max value */
+ const long int set_timeout = timeout > METAL_WDOGCMP_MASK ? METAL_WDOGCMP_MASK : timeout;
+
+ /* If we edit the timeout value in-place by masking the compare value to 0 and
+ * then writing it, we cause a spurious interrupt because the compare value
+ * is temporarily 0. Instead, read the value into a local variable, modify it
+ * there, and then write the whole register back */
+ uint32_t wdogcmp = WDOG_REGW(base, METAL_SIFIVE_WDOG0_WDOGCMP);
+
+ wdogcmp &= ~(METAL_WDOGCMP_MASK);
+ wdogcmp |= set_timeout;
+
+ WDOG_UNLOCK_REGW(base, METAL_SIFIVE_WDOG0_WDOGCMP) = wdogcmp;
+
+ return set_timeout;
+}
+
+int __metal_driver_sifive_wdog0_set_result(const struct metal_watchdog *const wdog,
+ const enum metal_watchdog_result result)
+{
+ const uintptr_t base = (uintptr_t)__metal_driver_sifive_wdog0_control_base(wdog);
+
+ /* Turn off reset enable and counter reset */
+ WDOG_UNLOCK_REGW(base, METAL_SIFIVE_WDOG0_WDOGCFG) &= ~(METAL_WDOGCFG_RSTEN | METAL_WDOGCFG_ZEROCMP);
+
+ switch (result) {
+ default:
+ case METAL_WATCHDOG_NO_RESULT:
+ break;
+ case METAL_WATCHDOG_INTERRUPT:
+ /* Reset counter to zero after match */
+ WDOG_UNLOCK_REGW(base, METAL_SIFIVE_WDOG0_WDOGCFG) |= METAL_WDOGCFG_ZEROCMP;
+ break;
+ case METAL_WATCHDOG_FULL_RESET:
+ WDOG_UNLOCK_REGW(base, METAL_SIFIVE_WDOG0_WDOGCFG) |= METAL_WDOGCFG_RSTEN;
+ break;
+ }
+
+ return 0;
+}
+
+int __metal_driver_sifive_wdog0_run(const struct metal_watchdog *const wdog,
+ const enum metal_watchdog_run_option option)
+{
+ const uintptr_t base = (uintptr_t)__metal_driver_sifive_wdog0_control_base(wdog);
+
+ WDOG_UNLOCK_REGW(base, METAL_SIFIVE_WDOG0_WDOGCFG) &= ~(METAL_WDOGCFG_ENALWAYS | METAL_WDOGCFG_COREAWAKE);
+
+ switch (option) {
+ default:
+ case METAL_WATCHDOG_STOP:
+ break;
+ case METAL_WATCHDOG_RUN_ALWAYS:
+ /* Feed the watchdog before starting to reset counter */
+ __metal_driver_sifive_wdog0_feed(wdog);
+
+ WDOG_UNLOCK_REGW(base, METAL_SIFIVE_WDOG0_WDOGCFG) |= METAL_WDOGCFG_ENALWAYS;
+ break;
+ case METAL_WATCHDOG_RUN_AWAKE:
+ /* Feed the watchdog before starting to reset counter */
+ __metal_driver_sifive_wdog0_feed(wdog);
+
+ WDOG_UNLOCK_REGW(base, METAL_SIFIVE_WDOG0_WDOGCFG) |= METAL_WDOGCFG_COREAWAKE;
+ break;
+ }
+
+ return 0;
+}
+
+struct metal_interrupt *__metal_driver_sifive_wdog0_get_interrupt(const struct metal_watchdog *const wdog)
+{
+ return __metal_driver_sifive_wdog0_interrupt_parent(wdog);
+}
+
+int __metal_driver_sifive_wdog0_get_interrupt_id(const struct metal_watchdog *const wdog)
+{
+ return __metal_driver_sifive_wdog0_interrupt_line(wdog);
+}
+
+int __metal_driver_sifive_wdog0_clear_interrupt(const struct metal_watchdog *const wdog)
+{
+ const uintptr_t base = (uintptr_t)__metal_driver_sifive_wdog0_control_base(wdog);
+
+ /* Clear the interrupt pending bit */
+ WDOG_UNLOCK_REGW(base, METAL_SIFIVE_WDOG0_WDOGCFG) &= ~(METAL_WDOGCFG_IP);
+
+ return 0;
+}
+
+__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_wdog0) = {
+ .watchdog.feed = __metal_driver_sifive_wdog0_feed,
+ .watchdog.get_rate = __metal_driver_sifive_wdog0_get_rate,
+ .watchdog.set_rate = __metal_driver_sifive_wdog0_set_rate,
+ .watchdog.get_timeout = __metal_driver_sifive_wdog0_get_timeout,
+ .watchdog.set_timeout = __metal_driver_sifive_wdog0_set_timeout,
+ .watchdog.set_result = __metal_driver_sifive_wdog0_set_result,
+ .watchdog.run = __metal_driver_sifive_wdog0_run,
+ .watchdog.get_interrupt = __metal_driver_sifive_wdog0_get_interrupt,
+ .watchdog.get_interrupt_id = __metal_driver_sifive_wdog0_get_interrupt_id,
+ .watchdog.clear_interrupt = __metal_driver_sifive_wdog0_clear_interrupt,
+};
+
+#endif /* METAL_SIFIVE_WDOG0 */
+
+typedef int no_empty_translation_units;
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/entry.S b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/entry.S
new file mode 100644
index 000000000..97da3fd33
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/entry.S
@@ -0,0 +1,106 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+/* This code executes before _start, which is contained inside the C library.
+ * In embedded systems we want to ensure that _enter, which contains the first
+ * code to be executed, can be loaded at a specific address. To enable this
+ * feature we provide the '.text.metal.init.enter' section, which is
+ * defined to have the first address being where execution should start. */
+.section .text.metal.init.enter
+.global _enter
+_enter:
+ .cfi_startproc
+
+ /* Inform the debugger that there is nowhere to backtrace past _enter. */
+ .cfi_undefined ra
+
+ /* The absolute first thing that must happen is configuring the global
+ * pointer register, which must be done with relaxation disabled because
+ * it's not valid to obtain the address of any symbol without GP
+ * configured. The C environment might go ahead and do this again, but
+ * that's safe as it's a fixed register. */
+.option push
+.option norelax
+ la gp, __global_pointer$
+.option pop
+
+ /* Set up a simple trap vector to catch anything that goes wrong early in
+ * the boot process. */
+ la t0, early_trap_vector
+ csrw mtvec, t0
+ /* enable chicken bit if core is bullet series*/
+ la t0, __metal_chicken_bit
+ beqz t0, 1f
+ csrwi 0x7C1, 0
+1:
+
+ /* There may be pre-initialization routines inside the MBI code that run in
+ * C, so here we set up a C environment. First we set up a stack pointer,
+ * which is left as a weak reference in order to allow initialization
+ * routines that do not need a stack to be set up to transparently be
+ * called. */
+ .weak __metal_stack_pointer
+ la sp, __metal_stack_pointer
+
+ /* Check for an initialization routine and call it if one exists, otherwise
+ * just skip over the call entirely. Note that __metal_initialize isn't
+ * actually a full C function, as it doesn't end up with the .bss or .data
+ * segments having been initialized. This is done to avoid putting a
+ * burden on systems that can be initialized without having a C environment
+ * set up. */
+ .weak __metal_before_start
+ la ra, __metal_before_start
+ beqz ra, 1f
+ jalr ra
+1:
+
+ /* At this point we can enter the C runtime's startup file. The arguments
+ * to this function are designed to match those provided to the SEE, just
+ * so we don't have to write another ABI. */
+ csrr a0, mhartid
+ li a1, 0
+ li a2, 0
+ call _start
+
+ /* If we've made it back here then there's probably something wrong. We
+ * allow the METAL to register a handler here. */
+ .weak __metal_after_main
+ la ra, __metal_after_main
+ beqz ra, 1f
+ jalr ra
+1:
+
+ /* If that handler returns then there's not a whole lot we can do. Just
+ * try to make some noise. */
+ la t0, 1f
+ csrw mtvec, t0
+1:
+ lw t1, 0(x0)
+ j 1b
+
+ .cfi_endproc
+
+/* For sanity's sake we set up an early trap vector that just does nothing. If
+ * you end up here then there's a bug in the early boot code somewhere. */
+.section .text.metal.init.trapvec
+.align 2
+early_trap_vector:
+ .cfi_startproc
+ csrr t0, mcause
+ csrr t1, mepc
+ csrr t2, mtval
+ j early_trap_vector
+ .cfi_endproc
+
+/* The GCC port might not emit a __register_frame_info symbol, which eventually
+ * results in a weak undefined reference that eventually causes crash when it
+ * is dereference early in boot. We really shouldn't need to put this here,
+ * but to deal with what I think is probably a bug in the linker script I'm
+ * going to leave this in for now. At least it's fairly cheap :) */
+.weak __register_frame_info
+.global __register_frame_info
+.section .text.metal.init.__register_frame_info
+__register_frame_info:
+ .cfi_startproc
+ ret
+ .cfi_endproc
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/gpio.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/gpio.c
new file mode 100644
index 000000000..504526eb3
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/gpio.c
@@ -0,0 +1,30 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine.h>
+#include <metal/gpio.h>
+
+extern __inline__ int metal_gpio_disable_input(struct metal_gpio *gpio, int pin);
+extern __inline__ int metal_gpio_enable_input(struct metal_gpio *gpio, int pin);
+extern __inline__ int metal_gpio_enable_output(struct metal_gpio *gpio, int pin);
+extern __inline__ int metal_gpio_disable_output(struct metal_gpio *gpio, int pin);
+extern __inline__ int metal_gpio_get_output_pin(struct metal_gpio *gpio, int pin);
+extern __inline__ int metal_gpio_get_input_pin(struct metal_gpio *gpio, int pin);
+extern __inline__ int metal_gpio_set_pin(struct metal_gpio *, int pin, int value);
+extern __inline__ int metal_gpio_clear_pin(struct metal_gpio *, int pin);
+extern __inline__ int metal_gpio_toggle_pin(struct metal_gpio *, int pin);
+extern __inline__ int metal_gpio_enable_pinmux(struct metal_gpio *, int pin, int io_function);
+extern __inline__ int metal_gpio_disable_pinmux(struct metal_gpio *, int pin);
+extern __inline__ struct metal_interrupt* metal_gpio_interrupt_controller(struct metal_gpio *gpio);
+extern __inline__ int metal_gpio_get_interrupt_id(struct metal_gpio *gpio, int pin);
+extern __inline__ int metal_gpio_config_interrupt(struct metal_gpio *gpio, int pin, int intr_type);
+extern __inline__ int metal_gpio_clear_interrupt(struct metal_gpio *gpio, int pin, int intr_type);
+
+struct metal_gpio *metal_gpio_get_device(unsigned int device_num)
+{
+ if(device_num > __MEE_DT_MAX_GPIOS) {
+ return NULL;
+ }
+
+ return (struct metal_gpio *) __metal_gpio_table[device_num];
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/interrupt.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/interrupt.c
new file mode 100644
index 000000000..eeb88b26f
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/interrupt.c
@@ -0,0 +1,82 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <string.h>
+#include <metal/interrupt.h>
+#include <metal/machine.h>
+
+struct metal_interrupt* metal_interrupt_get_controller (metal_intr_cntrl_type cntrl,
+ int id)
+{
+ switch (cntrl) {
+ case METAL_CPU_CONTROLLER:
+ break;
+ case METAL_CLINT_CONTROLLER:
+#ifdef __METAL_DT_RISCV_CLINT0_HANDLE
+ return __METAL_DT_RISCV_CLINT0_HANDLE;
+#endif
+ break;
+ case METAL_CLIC_CONTROLLER:
+#ifdef __METAL_DT_SIFIVE_CLIC0_HANDLE
+ return __METAL_DT_SIFIVE_CLIC0_HANDLE;
+#endif
+ break;
+ case METAL_PLIC_CONTROLLER:
+#ifdef __METAL_DT_RISCV_PLIC0_HANDLE
+ return __METAL_DT_RISCV_PLIC0_HANDLE;
+#endif
+ break;
+ }
+ return NULL;
+}
+
+extern __inline__ void metal_interrupt_init(struct metal_interrupt *controller);
+
+extern __inline__ int metal_interrupt_set_vector_mode(struct metal_interrupt *controller,
+ metal_vector_mode mode);
+extern __inline__ metal_vector_mode metal_interrupt_get_vector_mode(struct metal_interrupt *controller);
+
+extern __inline__ int metal_interrupt_set_privilege(struct metal_interrupt *controller,
+ metal_intr_priv_mode mode);
+extern __inline__ metal_intr_priv_mode metal_interrupt_get_privilege(struct metal_interrupt *controller);
+
+extern __inline__ int metal_interrupt_set_threshold(struct metal_interrupt *controller,
+ unsigned int level);
+extern __inline__ unsigned int metal_interrupt_get_threshold(struct metal_interrupt *controller);
+
+extern __inline__ unsigned int metal_interrupt_get_priority(struct metal_interrupt *controller, int id);
+
+extern __inline__ int metal_interrupt_set_priority(struct metal_interrupt *controller, int id, unsigned int priority);
+
+extern __inline__ int metal_interrupt_clear(struct metal_interrupt *controller, int id);
+
+extern __inline__ int metal_interrupt_set(struct metal_interrupt *controller, int id);
+
+extern __inline__ int metal_interrupt_register_handler(struct metal_interrupt *controller,
+ int id,
+ metal_interrupt_handler_t handler,
+ void *priv);
+
+extern __inline__ int metal_interrupt_register_vector_handler(struct metal_interrupt *controller,
+ int id,
+ metal_interrupt_vector_handler_t handler,
+ void *priv_data);
+
+extern __inline__ int metal_interrupt_enable(struct metal_interrupt *controller, int id);
+
+extern __inline__ int metal_interrupt_disable(struct metal_interrupt *controller, int id);
+
+extern __inline__ unsigned int metal_interrupt_get_threshold(struct metal_interrupt *controller);
+
+extern __inline__ int metal_interrupt_set_threshold(struct metal_interrupt *controller, unsigned int threshold);
+
+extern __inline__ unsigned int metal_interrupt_get_priority(struct metal_interrupt *controller, int id);
+
+extern __inline__ int metal_interrupt_set_priority(struct metal_interrupt *controller, int id, unsigned int priority);
+
+extern __inline__ int metal_interrupt_vector_enable(struct metal_interrupt *controller, int id);
+
+extern __inline__ int metal_interrupt_vector_disable(struct metal_interrupt *controller, int id);
+
+extern __inline__ int _metal_interrupt_command_request(struct metal_interrupt *controller,
+ int cmd, void *data);
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/led.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/led.c
new file mode 100644
index 000000000..91b74dbde
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/led.c
@@ -0,0 +1,38 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <string.h>
+#include <metal/led.h>
+#include <metal/machine.h>
+
+struct metal_led* metal_led_get_rgb (char *label, char *color)
+{
+ int i;
+ struct metal_led *led;
+ char led_label[100];
+
+ if ((__METAL_DT_MAX_LEDS == 0) ||
+ (label == NULL) || (color == NULL)) {
+ return NULL;
+ }
+
+ strcpy(led_label, label);
+ strcat(led_label, color);
+ for (i = 0; i < __METAL_DT_MAX_LEDS; i++) {
+ led = (struct metal_led*)__metal_led_table[i];
+ if (led->vtable->led_exist(led, led_label)) {
+ return led;
+ }
+ }
+ return NULL;
+}
+
+struct metal_led* metal_led_get (char *label)
+{
+ return metal_led_get_rgb(label, "");
+}
+
+extern __inline__ void metal_led_enable(struct metal_led *led);
+extern __inline__ void metal_led_on(struct metal_led *led);
+extern __inline__ void metal_led_off(struct metal_led *led);
+extern __inline__ void metal_led_toggle(struct metal_led *led);
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/lock.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/lock.c
new file mode 100644
index 000000000..9e04230a3
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/lock.c
@@ -0,0 +1,8 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/lock.h>
+
+extern __inline__ int metal_lock_init(struct metal_lock *lock);
+extern __inline__ int metal_lock_take(struct metal_lock *lock);
+extern __inline__ int metal_lock_give(struct metal_lock *lock);
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/memory.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/memory.c
new file mode 100644
index 000000000..05ab7ead2
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/memory.c
@@ -0,0 +1,26 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine.h>
+#include <metal/memory.h>
+
+struct metal_memory *metal_get_memory_from_address(const uintptr_t address) {
+ for(int i = 0; i < __METAL_DT_MAX_MEMORIES; i++) {
+ struct metal_memory *mem = __metal_memory_table[i];
+
+ uintptr_t lower_bound = metal_memory_get_base_address(mem);
+ uintptr_t upper_bound = lower_bound + metal_memory_get_size(mem);
+
+ if((address >= lower_bound) && (address < upper_bound)) {
+ return mem;
+ }
+ }
+
+ return NULL;
+}
+
+extern __inline__ uintptr_t metal_memory_get_base_address(const struct metal_memory *memory);
+extern __inline__ size_t metal_memory_get_size(const struct metal_memory *memory);
+extern __inline__ int metal_memory_supports_atomics(const struct metal_memory *memory);
+extern __inline__ int metal_memory_is_cachable(const struct metal_memory *memory);
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/pmp.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/pmp.c
new file mode 100644
index 000000000..5c2f68ada
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/pmp.c
@@ -0,0 +1,586 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine.h>
+#include <metal/pmp.h>
+#include <metal/cpu.h>
+
+#define CONFIG_TO_INT(_config) (*((char *) &(_config)))
+#define INT_TO_CONFIG(_int) (*((struct metal_pmp_config *)(char *) &(_int)))
+
+struct metal_pmp *metal_pmp_get_device(void)
+{
+#ifdef __METAL_DT_PMP_HANDLE
+ return __METAL_DT_PMP_HANDLE;
+#else
+ return NULL;
+#endif
+}
+
+/* This function calculates the minimum granularity from the address
+ * that pmpaddr takes on after writing all ones to pmpaddr when pmpcfg = 0.
+ *
+ * Detect the address granularity based on the position of the
+ * least-significant 1 set in the address.
+ *
+ * For example, if the value read from pmpaddr is 0x3ffffc00, the
+ * least-significant set bit is in bit 10 (counting from 0), resulting
+ * in a detected granularity of 2^(10 + 2) = 4096.
+ */
+static uintptr_t _get_detected_granularity(uintptr_t address) {
+ if(address == 0) {
+ return (uintptr_t) -1;
+ }
+
+ /* Get the index of the least significant set bit */
+ int index = 0;
+ while(((address >> index) & 0x1) == 0) {
+ index += 1;
+ }
+
+ /* The granularity is equal to 2^(index + 2) bytes */
+ return (1 << (index + 2));
+}
+
+/* This function calculates the granularity requested by the user's provided
+ * value for pmpaddr.
+ *
+ * Calculate the requested granularity based on the position of the
+ * least-significant unset bit.
+ *
+ * For example, if the requested address is 0x20009ff, the least-significant
+ * unset bit is at index 9 (counting from 0), resulting in a requested
+ * granularity of 2^(9 + 3) = 4096.
+ */
+static uintptr_t _get_pmpaddr_granularity(uintptr_t address) {
+ /* Get the index of the least significant unset bit */
+ int index = 0;
+ while(((address >> index) & 0x1) == 1) {
+ index += 1;
+ }
+
+ /* The granularity is equal to 2^(index + 3) bytes */
+ return (1 << (index + 3));
+}
+
+/* Get the number of pmp regions for the given hart */
+int metal_pmp_num_regions(int hartid)
+{
+ struct metal_cpu *cpu = metal_cpu_get(hartid);
+
+ return __metal_driver_cpu_num_pmp_regions(cpu);
+}
+
+/* Get the number of pmp regions for the current hart */
+static unsigned int _pmp_regions() {
+ return metal_pmp_num_regions(metal_cpu_get_current_hartid());
+}
+
+void metal_pmp_init(struct metal_pmp *pmp) {
+ if(!pmp) {
+ return;
+ }
+
+ struct metal_pmp_config init_config = {
+ .L = METAL_PMP_UNLOCKED,
+ .A = METAL_PMP_OFF,
+ .X = 0,
+ .W = 0,
+ .R = 0,
+ };
+
+ for(unsigned int i = 0; i < _pmp_regions(); i++) {
+ metal_pmp_set_region(pmp, i, init_config, 0);
+ }
+
+ /* Detect the region granularity by writing all 1s to pmpaddr0 while
+ * pmpcfg0 = 0. */
+ if(metal_pmp_set_address(pmp, 0, -1) != 0) {
+ /* Failed to detect granularity */
+ return;
+ }
+
+ /* Calculate the granularity based on the value that pmpaddr0 takes on */
+ pmp->_granularity[metal_cpu_get_current_hartid()] = _get_detected_granularity(metal_pmp_get_address(pmp, 0));
+
+ /* Clear pmpaddr0 */
+ metal_pmp_set_address(pmp, 0, 0);
+}
+
+int metal_pmp_set_region(struct metal_pmp *pmp,
+ unsigned int region,
+ struct metal_pmp_config config,
+ size_t address)
+{
+ struct metal_pmp_config old_config;
+ size_t old_address;
+ size_t cfgmask;
+ size_t pmpcfg;
+ int rc = 0;
+
+ if(!pmp) {
+ /* Device handle cannot be NULL */
+ return 1;
+ }
+
+ if(region > _pmp_regions()) {
+ /* Region outside of supported range */
+ return 2;
+ }
+
+ if(config.A == METAL_PMP_NA4 && pmp->_granularity[metal_cpu_get_current_hartid()] > 4) {
+ /* The requested granularity is too small */
+ return 3;
+ }
+
+ if(config.A == METAL_PMP_NAPOT &&
+ pmp->_granularity[metal_cpu_get_current_hartid()] > _get_pmpaddr_granularity(address))
+ {
+ /* The requested granularity is too small */
+ return 3;
+ }
+
+ rc = metal_pmp_get_region(pmp, region, &old_config, &old_address);
+ if(rc) {
+ /* Error reading region */
+ return rc;
+ }
+
+ if(old_config.L == METAL_PMP_LOCKED) {
+ /* Cannot modify locked region */
+ return 4;
+ }
+
+ /* Update the address first, because if the region is being locked we won't
+ * be able to modify it after we set the config */
+ if(old_address != address) {
+ switch(region) {
+ case 0:
+ __asm__("csrw pmpaddr0, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 1:
+ __asm__("csrw pmpaddr1, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 2:
+ __asm__("csrw pmpaddr2, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 3:
+ __asm__("csrw pmpaddr3, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 4:
+ __asm__("csrw pmpaddr4, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 5:
+ __asm__("csrw pmpaddr5, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 6:
+ __asm__("csrw pmpaddr6, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 7:
+ __asm__("csrw pmpaddr7, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 8:
+ __asm__("csrw pmpaddr8, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 9:
+ __asm__("csrw pmpaddr9, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 10:
+ __asm__("csrw pmpaddr10, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 11:
+ __asm__("csrw pmpaddr11, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 12:
+ __asm__("csrw pmpaddr12, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 13:
+ __asm__("csrw pmpaddr13, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 14:
+ __asm__("csrw pmpaddr14, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ case 15:
+ __asm__("csrw pmpaddr15, %[addr]"
+ :: [addr] "r" (address) :);
+ break;
+ }
+ }
+
+#if __riscv_xlen==32
+ if(CONFIG_TO_INT(old_config) != CONFIG_TO_INT(config)) {
+ /* Mask to clear old pmpcfg */
+ cfgmask = (0xFF << (8 * (region % 4)) );
+ pmpcfg = (CONFIG_TO_INT(config) << (8 * (region % 4)) );
+
+ switch(region / 4) {
+ case 0:
+ __asm__("csrc pmpcfg0, %[mask]"
+ :: [mask] "r" (cfgmask) :);
+
+ __asm__("csrs pmpcfg0, %[cfg]"
+ :: [cfg] "r" (pmpcfg) :);
+ break;
+ case 1:
+ __asm__("csrc pmpcfg1, %[mask]"
+ :: [mask] "r" (cfgmask) :);
+
+ __asm__("csrs pmpcfg1, %[cfg]"
+ :: [cfg] "r" (pmpcfg) :);
+ break;
+ case 2:
+ __asm__("csrc pmpcfg2, %[mask]"
+ :: [mask] "r" (cfgmask) :);
+
+ __asm__("csrs pmpcfg2, %[cfg]"
+ :: [cfg] "r" (pmpcfg) :);
+ break;
+ case 3:
+ __asm__("csrc pmpcfg3, %[mask]"
+ :: [mask] "r" (cfgmask) :);
+
+ __asm__("csrs pmpcfg3, %[cfg]"
+ :: [cfg] "r" (pmpcfg) :);
+ break;
+ }
+ }
+#elif __riscv_xlen==64
+ if(CONFIG_TO_INT(old_config) != CONFIG_TO_INT(config)) {
+ /* Mask to clear old pmpcfg */
+ cfgmask = (0xFF << (8 * (region % 8)) );
+ pmpcfg = (CONFIG_TO_INT(config) << (8 * (region % 8)) );
+
+ switch(region / 8) {
+ case 0:
+ __asm__("csrc pmpcfg0, %[mask]"
+ :: [mask] "r" (cfgmask) :);
+
+ __asm__("csrs pmpcfg0, %[cfg]"
+ :: [cfg] "r" (pmpcfg) :);
+ break;
+ case 1:
+ __asm__("csrc pmpcfg2, %[mask]"
+ :: [mask] "r" (cfgmask) :);
+
+ __asm__("csrs pmpcfg2, %[cfg]"
+ :: [cfg] "r" (pmpcfg) :);
+ break;
+ }
+ }
+#else
+#error XLEN is not set to supported value for PMP driver
+#endif
+
+ return 0;
+}
+
+int metal_pmp_get_region(struct metal_pmp *pmp,
+ unsigned int region,
+ struct metal_pmp_config *config,
+ size_t *address)
+{
+ size_t pmpcfg = 0;
+ char *pmpcfg_convert = (char *)&pmpcfg;
+
+ if(!pmp || !config || !address) {
+ /* NULL pointers are invalid arguments */
+ return 1;
+ }
+
+ if(region > _pmp_regions()) {
+ /* Region outside of supported range */
+ return 2;
+ }
+
+#if __riscv_xlen==32
+ switch(region / 4) {
+ case 0:
+ __asm__("csrr %[cfg], pmpcfg0"
+ : [cfg] "=r" (pmpcfg) ::);
+ break;
+ case 1:
+ __asm__("csrr %[cfg], pmpcfg1"
+ : [cfg] "=r" (pmpcfg) ::);
+ break;
+ case 2:
+ __asm__("csrr %[cfg], pmpcfg2"
+ : [cfg] "=r" (pmpcfg) ::);
+ break;
+ case 3:
+ __asm__("csrr %[cfg], pmpcfg3"
+ : [cfg] "=r" (pmpcfg) ::);
+ break;
+ }
+
+ pmpcfg = (0xFF & (pmpcfg >> (8 * (region % 4)) ) );
+
+#elif __riscv_xlen==64
+ switch(region / 8) {
+ case 0:
+ __asm__("csrr %[cfg], pmpcfg0"
+ : [cfg] "=r" (pmpcfg) ::);
+ break;
+ case 1:
+ __asm__("csrr %[cfg], pmpcfg2"
+ : [cfg] "=r" (pmpcfg) ::);
+ break;
+ }
+
+ pmpcfg = (0xFF & (pmpcfg >> (8 * (region % 8)) ) );
+
+#else
+#error XLEN is not set to supported value for PMP driver
+#endif
+
+ *config = INT_TO_CONFIG(*pmpcfg_convert);
+
+ switch(region) {
+ case 0:
+ __asm__("csrr %[addr], pmpaddr0"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 1:
+ __asm__("csrr %[addr], pmpaddr1"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 2:
+ __asm__("csrr %[addr], pmpaddr2"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 3:
+ __asm__("csrr %[addr], pmpaddr3"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 4:
+ __asm__("csrr %[addr], pmpaddr4"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 5:
+ __asm__("csrr %[addr], pmpaddr5"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 6:
+ __asm__("csrr %[addr], pmpaddr6"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 7:
+ __asm__("csrr %[addr], pmpaddr7"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 8:
+ __asm__("csrr %[addr], pmpaddr8"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 9:
+ __asm__("csrr %[addr], pmpaddr9"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 10:
+ __asm__("csrr %[addr], pmpaddr10"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 11:
+ __asm__("csrr %[addr], pmpaddr11"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 12:
+ __asm__("csrr %[addr], pmpaddr12"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 13:
+ __asm__("csrr %[addr], pmpaddr13"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 14:
+ __asm__("csrr %[addr], pmpaddr14"
+ : [addr] "=r" (*address) ::);
+ break;
+ case 15:
+ __asm__("csrr %[addr], pmpaddr15"
+ : [addr] "=r" (*address) ::);
+ break;
+ }
+
+ return 0;
+}
+
+int metal_pmp_lock(struct metal_pmp *pmp, unsigned int region)
+{
+ struct metal_pmp_config config;
+ size_t address;
+ int rc = 0;
+
+ rc = metal_pmp_get_region(pmp, region, &config, &address);
+ if(rc) {
+ return rc;
+ }
+
+ if(config.L == METAL_PMP_LOCKED) {
+ return 0;
+ }
+
+ config.L = METAL_PMP_LOCKED;
+
+ rc = metal_pmp_set_region(pmp, region, config, address);
+
+ return rc;
+}
+
+
+int metal_pmp_set_address(struct metal_pmp *pmp, unsigned int region, size_t address)
+{
+ struct metal_pmp_config config;
+ size_t old_address;
+ int rc = 0;
+
+ rc = metal_pmp_get_region(pmp, region, &config, &old_address);
+ if(rc) {
+ return rc;
+ }
+
+ rc = metal_pmp_set_region(pmp, region, config, address);
+
+ return rc;
+}
+
+size_t metal_pmp_get_address(struct metal_pmp *pmp, unsigned int region)
+{
+ struct metal_pmp_config config;
+ size_t address = 0;
+
+ metal_pmp_get_region(pmp, region, &config, &address);
+
+ return address;
+}
+
+
+int metal_pmp_set_address_mode(struct metal_pmp *pmp, unsigned int region, enum metal_pmp_address_mode mode)
+{
+ struct metal_pmp_config config;
+ size_t address;
+ int rc = 0;
+
+ rc = metal_pmp_get_region(pmp, region, &config, &address);
+ if(rc) {
+ return rc;
+ }
+
+ config.A = mode;
+
+ rc = metal_pmp_set_region(pmp, region, config, address);
+
+ return rc;
+}
+
+enum metal_pmp_address_mode metal_pmp_get_address_mode(struct metal_pmp *pmp, unsigned int region)
+{
+ struct metal_pmp_config config;
+ size_t address = 0;
+
+ metal_pmp_get_region(pmp, region, &config, &address);
+
+ return config.A;
+}
+
+
+int metal_pmp_set_executable(struct metal_pmp *pmp, unsigned int region, int X)
+{
+ struct metal_pmp_config config;
+ size_t address;
+ int rc = 0;
+
+ rc = metal_pmp_get_region(pmp, region, &config, &address);
+ if(rc) {
+ return rc;
+ }
+
+ config.X = X;
+
+ rc = metal_pmp_set_region(pmp, region, config, address);
+
+ return rc;
+}
+
+int metal_pmp_get_executable(struct metal_pmp *pmp, unsigned int region)
+{
+ struct metal_pmp_config config;
+ size_t address = 0;
+
+ metal_pmp_get_region(pmp, region, &config, &address);
+
+ return config.X;
+}
+
+
+int metal_pmp_set_writeable(struct metal_pmp *pmp, unsigned int region, int W)
+{
+ struct metal_pmp_config config;
+ size_t address;
+ int rc = 0;
+
+ rc = metal_pmp_get_region(pmp, region, &config, &address);
+ if(rc) {
+ return rc;
+ }
+
+ config.W = W;
+
+ rc = metal_pmp_set_region(pmp, region, config, address);
+
+ return rc;
+}
+
+int metal_pmp_get_writeable(struct metal_pmp *pmp, unsigned int region)
+{
+ struct metal_pmp_config config;
+ size_t address = 0;
+
+ metal_pmp_get_region(pmp, region, &config, &address);
+
+ return config.W;
+}
+
+
+int metal_pmp_set_readable(struct metal_pmp *pmp, unsigned int region, int R)
+{
+ struct metal_pmp_config config;
+ size_t address;
+ int rc = 0;
+
+ rc = metal_pmp_get_region(pmp, region, &config, &address);
+ if(rc) {
+ return rc;
+ }
+
+ config.R = R;
+
+ rc = metal_pmp_set_region(pmp, region, config, address);
+
+ return rc;
+}
+
+int metal_pmp_get_readable(struct metal_pmp *pmp, unsigned int region)
+{
+ struct metal_pmp_config config;
+ size_t address = 0;
+
+ metal_pmp_get_region(pmp, region, &config, &address);
+
+ return config.R;
+}
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/privilege.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/privilege.c
new file mode 100644
index 000000000..54bfcfc2c
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/privilege.c
@@ -0,0 +1,57 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <stddef.h>
+
+#include <metal/privilege.h>
+
+#define METAL_MSTATUS_MIE_OFFSET 3
+#define METAL_MSTATUS_MPIE_OFFSET 7
+#define METAL_MSTATUS_SIE_OFFSET 1
+#define METAL_MSTATUS_SPIE_OFFSET 5
+#define METAL_MSTATUS_UIE_OFFSET 0
+#define METAL_MSTATUS_UPIE_OFFSET 4
+
+#define METAL_MSTATUS_MPP_OFFSET 11
+#define METAL_MSTATUS_MPP_MASK 3
+
+void metal_privilege_drop_to_mode(enum metal_privilege_mode mode,
+ struct metal_register_file regfile,
+ metal_privilege_entry_point_t entry_point)
+{
+ uintptr_t mstatus;
+ __asm__ volatile("csrr %0, mstatus" : "=r" (mstatus));
+
+ /* Set xPIE bits based on current xIE bits */
+ if(mstatus && (1 << METAL_MSTATUS_MIE_OFFSET)) {
+ mstatus |= (1 << METAL_MSTATUS_MPIE_OFFSET);
+ } else {
+ mstatus &= ~(1 << METAL_MSTATUS_MPIE_OFFSET);
+ }
+ if(mstatus && (1 << METAL_MSTATUS_SIE_OFFSET)) {
+ mstatus |= (1 << METAL_MSTATUS_SPIE_OFFSET);
+ } else {
+ mstatus &= ~(1 << METAL_MSTATUS_SPIE_OFFSET);
+ }
+ if(mstatus && (1 << METAL_MSTATUS_UIE_OFFSET)) {
+ mstatus |= (1 << METAL_MSTATUS_UPIE_OFFSET);
+ } else {
+ mstatus &= ~(1 << METAL_MSTATUS_UPIE_OFFSET);
+ }
+
+ /* Set MPP to the requested privilege mode */
+ mstatus &= ~(METAL_MSTATUS_MPP_MASK << METAL_MSTATUS_MPP_OFFSET);
+ mstatus |= (mode << METAL_MSTATUS_MPP_OFFSET);
+
+ __asm__ volatile("csrw mstatus, %0" :: "r" (mstatus));
+
+ /* Set the entry point in MEPC */
+ __asm__ volatile("csrw mepc, %0" :: "r" (entry_point));
+
+ /* Set the register file */
+ __asm__ volatile("mv ra, %0" :: "r" (regfile.ra));
+ __asm__ volatile("mv sp, %0" :: "r" (regfile.sp));
+
+ __asm__ volatile("mret");
+}
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/rtc.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/rtc.c
new file mode 100644
index 000000000..8b79892df
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/rtc.c
@@ -0,0 +1,27 @@
+/* Copyright 2019 SiFive, Inc. */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine.h>
+#include <metal/rtc.h>
+
+#include <stddef.h>
+
+extern inline uint64_t metal_rtc_get_rate(const struct metal_rtc *const rtc);
+extern inline uint64_t metal_rtc_set_rate(const struct metal_rtc *const rtc, const uint64_t rate);
+extern inline uint64_t metal_rtc_get_compare(const struct metal_rtc *const rtc);
+extern inline uint64_t metal_rtc_set_compare(const struct metal_rtc *const rtc, const uint64_t compare);
+extern inline uint64_t metal_rtc_get_count(const struct metal_rtc *const rtc);
+extern inline uint64_t metal_rtc_set_count(const struct metal_rtc *const rtc, const uint64_t count);
+extern inline int metal_rtc_run(const struct metal_rtc *const rtc, const enum metal_rtc_run_option option);
+extern inline struct metal_interrupt *metal_rtc_get_interrupt(const struct metal_rtc *const rtc);
+extern inline int metal_rtc_get_interrupt_id(const struct metal_rtc *const rtc);
+
+struct metal_rtc *metal_rtc_get_device(int index) {
+#ifdef __METAL_DT_MAX_RTCS
+ if (index < __METAL_DT_MAX_RTCS) {
+ return (struct metal_rtc *) __metal_rtc_table[index];
+ }
+#endif
+ return NULL;
+}
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/shutdown.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/shutdown.c
new file mode 100644
index 000000000..c3b5255a7
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/shutdown.c
@@ -0,0 +1,22 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine.h>
+#include <metal/shutdown.h>
+
+extern __inline__ void __metal_shutdown_exit(const struct __metal_shutdown *sd, int code);
+
+#if defined(__METAL_DT_SHUTDOWN_HANDLE)
+void metal_shutdown(int code)
+{
+ __metal_shutdown_exit(__METAL_DT_SHUTDOWN_HANDLE, code);
+}
+#else
+#pragma message("There is no defined shutdown mechanism, metal_shutdown() will spin.")
+void metal_shutdown(int code)
+{
+ while (1) {
+ __asm__ volatile ("nop");
+ }
+}
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/spi.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/spi.c
new file mode 100644
index 000000000..de8cda737
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/spi.c
@@ -0,0 +1,21 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine.h>
+#include <metal/spi.h>
+
+extern __inline__ void metal_spi_init(struct metal_spi *spi, int baud_rate);
+extern __inline__ int metal_spi_transfer(struct metal_spi *spi, struct metal_spi_config *config, size_t len, char *tx_buf, char *rx_buf);
+extern __inline__ int metal_spi_get_baud_rate(struct metal_spi *spi);
+extern __inline__ int metal_spi_set_baud_rate(struct metal_spi *spi, int baud_rate);
+
+struct metal_spi *metal_spi_get_device(unsigned int device_num)
+{
+#if __METAL_DT_MAX_SPIS > 0
+ if (device_num < __METAL_DT_MAX_SPIS) {
+ return (struct metal_spi *) __metal_spi_table[device_num];
+ }
+#endif
+
+ return NULL;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/switch.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/switch.c
new file mode 100644
index 000000000..4f17229c7
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/switch.c
@@ -0,0 +1,27 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/switch.h>
+#include <metal/machine.h>
+
+struct metal_switch* metal_switch_get (char *label)
+{
+ int i;
+ struct metal_switch *flip;
+
+ if ((__METAL_DT_MAX_BUTTONS == 0) || (label == NULL)) {
+ return NULL;
+ }
+
+ for (i = 0; i < __METAL_DT_MAX_BUTTONS; i++) {
+ flip = (struct metal_switch*)__metal_switch_table[i];
+ if (flip->vtable->switch_exist(flip, label)) {
+ return flip;
+ }
+ }
+ return NULL;
+}
+
+extern __inline__ struct metal_interrupt*
+ metal_switch_interrupt_controller(struct metal_switch *flip);
+extern __inline__ int metal_switch_get_interrupt_id(struct metal_switch *flip);
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/synchronize_harts.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/synchronize_harts.c
new file mode 100644
index 000000000..a5338e942
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/synchronize_harts.c
@@ -0,0 +1,62 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/machine.h>
+#include <metal/machine/platform.h>
+#include <metal/io.h>
+#include <metal/cpu.h>
+
+#define METAL_REG(base, offset) (((unsigned long)(base) + (offset)))
+#define METAL_REGW(base, offset) (__METAL_ACCESS_ONCE((__metal_io_u32 *)METAL_REG((base), (offset))))
+#define METAL_MSIP(base, hart) (METAL_REGW((base),4*(hart)))
+
+/*
+ * _synchronize_harts() is called by crt0.S to cause harts > 0 to wait for
+ * hart 0 to finish copying the datat section, zeroing the BSS, and running
+ * the libc contstructors.
+ */
+__attribute__((section(".init")))
+void __metal_synchronize_harts() {
+#if __METAL_DT_MAX_HARTS > 1
+
+ int hart;
+ __asm__ volatile("csrr %0, mhartid" : "=r" (hart) ::);
+
+ uintptr_t msip_base = 0;
+
+ /* Get the base address of the MSIP registers */
+#ifdef __METAL_DT_RISCV_CLINT0_HANDLE
+ msip_base = __metal_driver_sifive_clint0_control_base(__METAL_DT_RISCV_CLINT0_HANDLE);
+ msip_base += METAL_RISCV_CLINT0_MSIP_BASE;
+#elif __METAL_DT_RISCV_CLIC0_HANDLE
+ msip_base = __metal_driver_sifive_clic0_control_base(__METAL_DT_RISCV_CLIC0_HANDLE);
+ msip_base += METAL_RISCV_CLIC0_MSIP_BASE;
+#else
+#pragma message(No handle for CLINT or CLIC found, harts may be unsynchronized after init!)
+#endif
+
+ /* Disable machine interrupts as a precaution */
+ __asm__ volatile("csrc mstatus, %0" :: "r" (METAL_MSTATUS_MIE));
+
+ if (hart == 0) {
+ /* Hart 0 waits for all harts to set their MSIP bit */
+ for (int i = 1 ; i < __METAL_DT_MAX_HARTS; i++) {
+ while (METAL_MSIP(msip_base, i) == 0) ;
+ }
+
+ /* Hart 0 clears everyone's MSIP bit */
+ for (int i = 1 ; i < __METAL_DT_MAX_HARTS; i++) {
+ METAL_MSIP(msip_base, i) = 0;
+ }
+ } else {
+ /* Other harts set their MSIP bit to indicate they're ready */
+ METAL_MSIP(msip_base, hart) = 1;
+ __asm__ volatile ("fence w,rw");
+
+ /* Wait for hart 0 to clear the MSIP bit */
+ while (METAL_MSIP(msip_base, hart) == 1) ;
+ }
+
+#endif /* __METAL_DT_MAX_HARTS > 1 */
+}
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/time.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/time.c
new file mode 100644
index 000000000..529f8bd56
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/time.c
@@ -0,0 +1,30 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/time.h>
+#include <metal/timer.h>
+
+int metal_gettimeofday(struct timeval *tp, void *tzp)
+{
+ int rv;
+ unsigned long long mcc, timebase;
+ if ((rv = metal_timer_get_cyclecount(0, &mcc))) {
+ return -1;
+ }
+ if ((rv = metal_timer_get_timebase_frequency(0, &timebase))) {
+ return -1;
+ }
+ tp->tv_sec = mcc / timebase;
+ tp->tv_usec = mcc % timebase * 1000000 / timebase;
+ return 0;
+}
+
+time_t metal_time (void)
+{
+ struct timeval now;
+
+ if (metal_gettimeofday(&now, NULL) < 0)
+ now.tv_sec = (time_t) -1;
+
+ return now.tv_sec;
+}
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/timer.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/timer.c
new file mode 100644
index 000000000..f58413321
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/timer.c
@@ -0,0 +1,80 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <sys/time.h>
+#include <sys/times.h>
+#include <metal/cpu.h>
+#include <metal/timer.h>
+#include <metal/machine.h>
+
+#if defined(__METAL_DT_MAX_HARTS)
+/* This implementation serves as a small shim that interfaces with the first
+ * timer on a system. */
+int metal_timer_get_cyclecount(int hartid, unsigned long long *mcc)
+{
+ struct metal_cpu *cpu = metal_cpu_get(hartid);
+
+ if ( cpu ) {
+ *mcc = metal_cpu_get_timer(cpu);
+ return 0;
+ }
+ return -1;
+}
+
+int metal_timer_get_timebase_frequency(int hartid, unsigned long long *timebase)
+{
+ struct metal_cpu *cpu = metal_cpu_get(hartid);
+
+ if ( cpu ) {
+ *timebase = metal_cpu_get_timebase(cpu);
+ return 0;
+ }
+ return -1;
+}
+
+int metal_timer_get_machine_time(int hartid)
+{
+ struct metal_cpu *cpu = metal_cpu_get(hartid);
+
+ if ( cpu ) {
+ return metal_cpu_get_mtime(cpu);
+ }
+ return 0;
+}
+
+int metal_timer_set_machine_time(int hartid, unsigned long long time)
+{
+ struct metal_cpu *cpu = metal_cpu_get(hartid);
+
+ if ( cpu ) {
+ return metal_cpu_set_mtimecmp(cpu, time);
+ }
+ return -1;
+}
+
+#else
+
+/* This implementation of gettimeofday doesn't actually do anything, it's just there to
+ * provide a shim and return 0 so we can ensure that everything can link to _gettimeofday.
+ */
+int nop_cyclecount(int id, unsigned long long *c) __attribute__((section(".text.metal.nop.cyclecount")));
+int nop_cyclecount(int id, unsigned long long *c) { return -1; }
+int nop_timebase(unsigned long long *t) __attribute__((section(".text.metal.nop.timebase")));
+int nop_timebase(unsigned long long *t) { return -1; }
+int nop_tick(int second) __attribute__((section(".text.metal.nop.tick")));
+int nop_tick(int second) { return -1; }
+int metal_timer_get_cyclecount(int hartid, unsigned long long *c) __attribute__((weak, alias("nop_cyclecount")))
+{
+#pragma message("There is no default timer device, metal_timer_get_cyclecount() will always return cyclecount -1.")
+}
+int metal_timer_get_timebase_frequency(unsigned long long *t) __attribute__((weak, alias("nop_timebase")))
+{
+#pragma message("There is no default timer device, metal_timer_get_timebase_frequency() will always return timebase -1.")
+}
+int metal_timer_set_tick(int second) __attribute__((weak, alias("nop_tick")))
+{
+#pragma message("There is no default timer device, metal_timer_set_tick) will always return -1.")
+}
+
+#endif
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/trap.S b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/trap.S
new file mode 100644
index 000000000..b55b6656a
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/trap.S
@@ -0,0 +1,53 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#define METAL_MSTATUS_MIE_SHIFT 8
+#define METAL_MSTATUS_MPP_M 3
+#define METAL_MSTATUS_MPP_SHIFT 11
+
+#define METAL_MTVEC_MODE_MASK 3
+
+/* void _metal_trap(int ecode)
+ *
+ * Trigger a machine-mode trap with exception code ecode
+ */
+.global _metal_trap
+.type _metal_trap, @function
+
+_metal_trap:
+
+ /* Store the instruction which called _metal_trap in mepc */
+ addi t0, ra, -1
+ csrw mepc, t0
+
+ /* Set mcause to the desired exception code */
+ csrw mcause, a0
+
+ /* Read mstatus */
+ csrr t0, mstatus
+
+ /* Set MIE=0 */
+ li t1, -1
+ xori t1, t1, METAL_MSTATUS_MIE_SHIFT
+ and t0, t0, t1
+
+ /* Set MPP=M */
+ li t1, METAL_MSTATUS_MPP_M
+ slli t1, t1, METAL_MSTATUS_MPP_SHIFT
+ or t0, t0, t1
+
+ /* Write mstatus */
+ csrw mstatus, t0
+
+ /* Read mtvec */
+ csrr t0, mtvec
+
+ /*
+ * Mask the mtvec MODE bits
+ * Exceptions always jump to mtvec.BASE regradless of the vectoring mode.
+ */
+ andi t0, t0, METAL_MTVEC_MODE_MASK
+
+ /* Jump to mtvec */
+ jr t0
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/tty.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/tty.c
new file mode 100644
index 000000000..306192451
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/tty.c
@@ -0,0 +1,51 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/uart.h>
+#include <metal/tty.h>
+#include <metal/machine.h>
+
+#if defined(__METAL_DT_STDOUT_UART_HANDLE)
+/* This implementation serves as a small shim that interfaces with the first
+ * UART on a system. */
+int metal_tty_putc(int c)
+{
+ if (c == '\n') {
+ metal_tty_putc_raw( '\r' );
+ }
+ return metal_tty_putc_raw( c );
+}
+
+int metal_tty_putc_raw(int c)
+{
+ return metal_uart_putc(__METAL_DT_STDOUT_UART_HANDLE, c);
+}
+
+int metal_tty_getc(int *c)
+{
+ do {
+ metal_uart_getc( __METAL_DT_STDOUT_UART_HANDLE, c );
+ /* -1 means no key pressed, getc waits */
+ } while( -1 == *c )
+ ;
+ return 0;
+}
+
+#ifndef __METAL_DT_STDOUT_UART_BAUD
+#define __METAL_DT_STDOUT_UART_BAUD 115200
+#endif
+
+static void metal_tty_init(void) __attribute__((constructor));
+static void metal_tty_init(void)
+{
+ metal_uart_init(__METAL_DT_STDOUT_UART_HANDLE, __METAL_DT_STDOUT_UART_BAUD);
+}
+#else
+/* This implementation of putc doesn't actually do anything, it's just there to
+ * provide a shim that eats all the characters so we can ensure that everything
+ * can link to metal_tty_putc. */
+int nop_putc(int c) __attribute__((section(".text.metal.nop.putc")));
+int nop_putc(int c) { return -1; }
+int metal_tty_putc(int c) __attribute__((weak, alias("nop_putc")));
+#pragma message("There is no default output device, metal_tty_putc() will throw away all input.")
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/uart.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/uart.c
new file mode 100644
index 000000000..8981eb8d3
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/uart.c
@@ -0,0 +1,11 @@
+/* Copyright 2018 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <metal/uart.h>
+
+extern __inline__ void metal_uart_init(struct metal_uart *uart, int baud_rate);
+extern __inline__ int metal_uart_putc(struct metal_uart *uart, int c);
+extern __inline__ int metal_uart_txready(struct metal_uart *uart);
+extern __inline__ int metal_uart_getc(struct metal_uart *uart, int *c);
+extern __inline__ int metal_uart_get_baud_rate(struct metal_uart *uart);
+extern __inline__ int metal_uart_set_baud_rate(struct metal_uart *uart, int baud_rate);
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/vector.S b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/vector.S
new file mode 100644
index 000000000..1da52d2df
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/vector.S
@@ -0,0 +1,160 @@
+/* Copyright 2019 SiFive, Inc */
+/* SPDX-License-Identifier: Apache-2.0 */
+
+/*
+ * Jump table for CLINT vectored mode
+ */
+.weak metal_interrupt_vector_handler
+.balign 4, 0
+.global metal_interrupt_vector_handler
+
+.weak metal_software_interrupt_vector_handler
+.balign 4, 0
+.global metal_software_interrupt_vector_handler
+
+.weak metal_timer_interrupt_vector_handler
+.balign 4, 0
+.global metal_timer_interrupt_vector_handler
+
+.weak metal_external_interrupt_vector_handler
+.balign 4, 0
+.global metal_external_interrupt_vector_handler
+
+.weak metal_lc0_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc0_interrupt_vector_handler
+
+.weak metal_lc1_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc1_interrupt_vector_handler
+
+.weak metal_lc2_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc2_interrupt_vector_handler
+
+.weak metal_lc3_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc3_interrupt_vector_handler
+
+.weak metal_lc4_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc4_interrupt_vector_handler
+
+.weak metal_lc5_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc5_interrupt_vector_handler
+
+.weak metal_lc6_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc6_interrupt_vector_handler
+
+.weak metal_lc7_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc7_interrupt_vector_handler
+
+.weak metal_lc8_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc8_interrupt_vector_handler
+
+.weak metal_lc9_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc9_interrupt_vector_handler
+
+.weak metal_lc10_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc10_interrupt_vector_handler
+
+.weak metal_lc11_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc11_interrupt_vector_handler
+
+.weak metal_lc12_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc12_interrupt_vector_handler
+
+.weak metal_lc13_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc13_interrupt_vector_handler
+
+.weak metal_lc14_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc14_interrupt_vector_handler
+
+.weak metal_lc15_interrupt_vector_handler
+.balign 4, 0
+.global metal_lc15_interrupt_vector_handler
+
+#if __riscv_xlen == 32
+.balign 128, 0
+#else
+.balign 256, 0
+#endif
+.option norvc
+.global __metal_vector_table
+__metal_vector_table:
+IRQ_0:
+ j metal_interrupt_vector_handler
+IRQ_1:
+ j metal_interrupt_vector_handler
+IRQ_2:
+ j metal_interrupt_vector_handler
+IRQ_3:
+ j metal_software_interrupt_vector_handler
+IRQ_4:
+ j metal_interrupt_vector_handler
+IRQ_5:
+ j metal_interrupt_vector_handler
+IRQ_6:
+ j metal_interrupt_vector_handler
+IRQ_7:
+ j metal_timer_interrupt_vector_handler
+IRQ_8:
+ j metal_interrupt_vector_handler
+IRQ_9:
+ j metal_interrupt_vector_handler
+IRQ_10:
+ j metal_interrupt_vector_handler
+IRQ_11:
+ j metal_interrupt_vector_handler
+IRQ_12:
+ j metal_interrupt_vector_handler
+IRQ_13:
+ j metal_interrupt_vector_handler
+IRQ_14:
+ j metal_interrupt_vector_handler
+IRQ_15:
+ j metal_interrupt_vector_handler
+IRQ_LC0:
+ j metal_lc0_interrupt_vector_handler
+IRQ_LC1:
+ j metal_lc1_interrupt_vector_handler
+IRQ_LC2:
+ j metal_lc2_interrupt_vector_handler
+IRQ_LC3:
+ j metal_lc3_interrupt_vector_handler
+IRQ_LC4:
+ j metal_lc4_interrupt_vector_handler
+IRQ_LC5:
+ j metal_lc5_interrupt_vector_handler
+IRQ_LC6:
+ j metal_lc6_interrupt_vector_handler
+IRQ_LC7:
+ j metal_lc7_interrupt_vector_handler
+IRQ_LC8:
+ j metal_lc8_interrupt_vector_handler
+IRQ_LC9:
+ j metal_lc9_interrupt_vector_handler
+IRQ_LC10:
+ j metal_lc10_interrupt_vector_handler
+IRQ_LC11:
+ j metal_lc11_interrupt_vector_handler
+IRQ_LC12:
+ j metal_lc12_interrupt_vector_handler
+IRQ_LC13:
+ j metal_lc13_interrupt_vector_handler
+IRQ_LC14:
+ j metal_lc14_interrupt_vector_handler
+IRQ_LC15:
+ j metal_lc15_interrupt_vector_handler
+
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/full_demo/RegTest.S b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/full_demo/RegTest.S
new file mode 100644
index 000000000..f2602c430
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/full_demo/RegTest.S
@@ -0,0 +1,266 @@
+/*
+ * FreeRTOS Kernel V10.2.1
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+
+ .extern ulRegTest1LoopCounter
+ .extern ulRegTest2LoopCounter
+
+ .global vRegTest1Implementation
+ .global vRegTest2Implementation
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The register check tasks are described in the comments at the top of
+ * main_full.c.
+ */
+
+.align( 4 )
+vRegTest1Implementation:
+
+ /* Fill the core registers with known values. */
+ li x5, 0x5
+ li x6, 0x6
+ li x7, 0x7
+ li x8, 0x8
+ li x9, 0x9
+ li x10, 0xa
+ li x11, 0xb
+ li x12, 0xc
+ li x13, 0xd
+ li x14, 0xe
+ li x15, 0xf
+ li x16, 0x10
+ li x17, 0x11
+ li x18, 0x12
+ li x19, 0x13
+ li x20, 0x14
+ li x21, 0x15
+ li x22, 0x16
+ li x23, 0x17
+ li x24, 0x18
+ li x25, 0x19
+ li x26, 0x1a
+ li x27, 0x1b
+ li x28, 0x1c
+ li x29, 0x1d
+ li x30, 0x1e
+
+reg1_loop:
+
+ /* Check each register still contains the expected known value.
+ vRegTest1Implementation uses x31 as the temporary, vRegTest2Implementation
+ uses x5 as the temporary. */
+ li x31, 0x5
+ bne x31, x5, reg1_error_loop
+ li x31, 0x6
+ bne x31, x6, reg1_error_loop
+ li x31, 0x7
+ bne x31, x7, reg1_error_loop
+ li x31, 0x8
+ bne x31, x8, reg1_error_loop
+ li x31, 0x9
+ bne x31, x9, reg1_error_loop
+ li x31, 0xa
+ bne x31, x10, reg1_error_loop
+ li x31, 0xb
+ bne x31, x11, reg1_error_loop
+ li x31, 0xc
+ bne x31, x12, reg1_error_loop
+ li x31, 0xd
+ bne x31, x13, reg1_error_loop
+ li x31, 0xe
+ bne x31, x14, reg1_error_loop
+ li x31, 0xf
+ bne x31, x15, reg1_error_loop
+ li x31, 0x10
+ bne x31, x16, reg1_error_loop
+ li x31, 0x11
+ bne x31, x17, reg1_error_loop
+ li x31, 0x12
+ bne x31, x18, reg1_error_loop
+ li x31, 0x13
+ bne x31, x19, reg1_error_loop
+ li x31, 0x14
+ bne x31, x20, reg1_error_loop
+ li x31, 0x15
+ bne x31, x21, reg1_error_loop
+ li x31, 0x16
+ bne x31, x22, reg1_error_loop
+ li x31, 0x17
+ bne x31, x23, reg1_error_loop
+ li x31, 0x18
+ bne x31, x24, reg1_error_loop
+ li x31, 0x19
+ bne x31, x25, reg1_error_loop
+ li x31, 0x1a
+ bne x31, x26, reg1_error_loop
+ li x31, 0x1b
+ bne x31, x27, reg1_error_loop
+ li x31, 0x1c
+ bne x31, x28, reg1_error_loop
+ li x31, 0x1d
+ bne x31, x29, reg1_error_loop
+ li x31, 0x1e
+ bne x31, x30, reg1_error_loop
+
+ /* Everything passed, increment the loop counter. */
+ lw x31, ulRegTest1LoopCounterConst
+ lw x30, 0(x31)
+ addi x30, x30, 1
+ sw x30, 0(x31)
+
+ /* Restore clobbered register reading for next loop. */
+ li x30, 0x1e
+
+ /* Yield to increase code coverage. */
+ ecall
+
+ /* Start again. */
+ jal reg1_loop
+
+reg1_error_loop:
+ /* Jump here if a register contains an uxpected value. This stops the loop
+ counter being incremented so the check task knows an error was found. */
+ ebreak
+ jal reg1_error_loop
+
+.align( 4 )
+ulRegTest1LoopCounterConst: .word ulRegTest1LoopCounter
+
+/*-----------------------------------------------------------*/
+
+.align( 4 )
+vRegTest2Implementation:
+
+ /* Fill the core registers with known values. */
+ li x6, 0x61
+ li x7, 0x71
+ li x8, 0x81
+ li x9, 0x91
+ li x10, 0xa1
+ li x11, 0xb1
+ li x12, 0xc1
+ li x13, 0xd1
+ li x14, 0xe1
+ li x15, 0xf1
+ li x16, 0x20
+ li x17, 0x21
+ li x18, 0x22
+ li x19, 0x23
+ li x20, 0x24
+ li x21, 0x25
+ li x22, 0x26
+ li x23, 0x27
+ li x24, 0x28
+ li x25, 0x29
+ li x26, 0x2a
+ li x27, 0x2b
+ li x28, 0x2c
+ li x29, 0x2d
+ li x30, 0x2e
+ li x31, 0x2f
+
+Reg2_loop:
+
+ /* Check each register still contains the expected known value.
+ vRegTest2Implementation uses x5 as the temporary, vRegTest1Implementation
+ uses x31 as the temporary. */
+ li x5, 0x61
+ bne x5, x6, reg2_error_loop
+ li x5, 0x71
+ bne x5, x7, reg2_error_loop
+ li x5, 0x81
+ bne x5, x8, reg2_error_loop
+ li x5, 0x91
+ bne x5, x9, reg2_error_loop
+ li x5, 0xa1
+ bne x5, x10, reg2_error_loop
+ li x5, 0xb1
+ bne x5, x11, reg2_error_loop
+ li x5, 0xc1
+ bne x5, x12, reg2_error_loop
+ li x5, 0xd1
+ bne x5, x13, reg2_error_loop
+ li x5, 0xe1
+ bne x5, x14, reg2_error_loop
+ li x5, 0xf1
+ bne x5, x15, reg2_error_loop
+ li x5, 0x20
+ bne x5, x16, reg2_error_loop
+ li x5, 0x21
+ bne x5, x17, reg2_error_loop
+ li x5, 0x22
+ bne x5, x18, reg2_error_loop
+ li x5, 0x23
+ bne x5, x19, reg2_error_loop
+ li x5, 0x24
+ bne x5, x20, reg2_error_loop
+ li x5, 0x25
+ bne x5, x21, reg2_error_loop
+ li x5, 0x26
+ bne x5, x22, reg2_error_loop
+ li x5, 0x27
+ bne x5, x23, reg2_error_loop
+ li x5, 0x28
+ bne x5, x24, reg2_error_loop
+ li x5, 0x29
+ bne x5, x25, reg2_error_loop
+ li x5, 0x2a
+ bne x5, x26, reg2_error_loop
+ li x5, 0x2b
+ bne x5, x27, reg2_error_loop
+ li x5, 0x2c
+ bne x5, x28, reg2_error_loop
+ li x5, 0x2d
+ bne x5, x29, reg2_error_loop
+ li x5, 0x2e
+ bne x5, x30, reg2_error_loop
+ li x5, 0x2f
+ bne x5, x31, reg2_error_loop
+
+ /* Everything passed, increment the loop counter. */
+ lw x5, ulRegTest2LoopCounterConst
+ lw x6, 0(x5)
+ addi x6, x6, 1
+ sw x6, 0(x5)
+
+ /* Restore clobbered register reading for next loop. */
+ li x6, 0x61
+
+ /* Start again. */
+ jal Reg2_loop
+
+reg2_error_loop:
+ /* Jump here if a register contains an uxpected value. This stops the loop
+ counter being incremented so the check task knows an error was found. */
+ ebreak
+ jal reg2_error_loop
+
+.align( 4 )
+ulRegTest2LoopCounterConst: .word ulRegTest2LoopCounter
+
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/full_demo/main_full.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/full_demo/main_full.c
new file mode 100644
index 000000000..1f25b0174
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/full_demo/main_full.c
@@ -0,0 +1,306 @@
+/*
+ * FreeRTOS Kernel V10.2.1
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+
+/******************************************************************************
+ * NOTE 1: This project provides two demo applications. A simple blinky style
+ * project, and a more comprehensive test and demo application. The
+ * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select
+ * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY
+ * in main.c. This file implements the comprehensive test and demo version.
+ *
+ * NOTE 2: This file only contains the source code that is specific to the
+ * full demo. Generic functions, such FreeRTOS hook functions, and functions
+ * required to configure the hardware, are defined in main.c.
+ *
+ ******************************************************************************
+ *
+ * main_full() creates all the demo application tasks and software timers, then
+ * starts the scheduler. The web documentation provides more details of the
+ * standard demo application tasks, which provide no particular functionality,
+ * but do provide a good example of how to use the FreeRTOS API.
+ *
+ * In addition to the standard demo tasks, the following tasks and tests are
+ * defined and/or created within this file:
+ *
+ * "Reg test" tasks - These fill both the core registers with known values, then
+ * check that each register maintains its expected value for the lifetime of the
+ * task. Each task uses a different set of values. The reg test tasks execute
+ * with a very low priority, so get preempted very frequently. A register
+ * containing an unexpected value is indicative of an error in the context
+ * switching mechanism.
+ *
+ * "Check" task - The check executes every three seconds. It checks that all
+ * the standard demo tasks, and the register check tasks, are not only still
+ * executing, but are executing without reporting any errors. The check task
+ * toggles the LED every three seconds if all the standard demo tasks are
+ * executing as expected, or every 500ms if a potential error is discovered in
+ * any task.
+ */
+
+/* Standard includes. */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Kernel includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "timers.h"
+#include "semphr.h"
+
+/* Standard demo application includes. */
+#include "dynamic.h"
+#include "blocktim.h"
+#include "TimerDemo.h"
+#include "TaskNotify.h"
+
+/* Priorities for the demo application tasks. */
+#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
+
+/* The period of the check task, in ms, converted to ticks using the
+pdMS_TO_TICKS() macro. mainNO_ERROR_CHECK_TASK_PERIOD is used if no errors have
+been found, mainERROR_CHECK_TASK_PERIOD is used if an error has been found. */
+#define mainNO_ERROR_CHECK_TASK_PERIOD pdMS_TO_TICKS( 3000UL )
+#define mainERROR_CHECK_TASK_PERIOD pdMS_TO_TICKS( 500UL )
+
+/* Parameters that are passed into the register check tasks solely for the
+purpose of ensuring parameters are passed into tasks correctly. */
+#define mainREG_TEST_TASK_1_PARAMETER ( ( void * ) 0x12345678 )
+#define mainREG_TEST_TASK_2_PARAMETER ( ( void * ) 0x87654321 )
+
+/* The base period used by the timer test tasks. */
+#define mainTIMER_TEST_PERIOD ( 50 )
+
+/* The size of the stack allocated to the check task (as described in the
+comments at the top of this file. */
+#define mainCHECK_TASK_STACK_SIZE_WORDS 160
+
+/* Size of the stacks to allocated for the register check tasks. */
+#define mainREG_TEST_STACK_SIZE_WORDS 90
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Called by main() to run the full demo (as opposed to the blinky demo) when
+ * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0.
+ */
+void main_full( void );
+
+/*
+ * The check task, as described at the top of this file.
+ */
+static void prvCheckTask( void *pvParameters );
+
+/*
+ * Register check tasks as described at the top of this file. The nature of
+ * these files necessitates that they are written in an assembly file, but the
+ * entry points are kept in the C file for the convenience of checking the task
+ * parameter.
+ */
+static void prvRegTestTaskEntry1( void *pvParameters );
+extern void vRegTest1Implementation( void );
+static void prvRegTestTaskEntry2( void *pvParameters );
+extern void vRegTest2Implementation( void );
+
+/*
+ * Tick hook used by the full demo, which includes code that interacts with
+ * some of the tests.
+ */
+void vFullDemoTickHook( void );
+
+/*-----------------------------------------------------------*/
+
+/* The following two variables are used to communicate the status of the
+register check tasks to the check task. If the variables keep incrementing,
+then the register check tasks have not discovered any errors. If a variable
+stops incrementing, then an error has been found. */
+uint32_t ulRegTest1LoopCounter = 0UL, ulRegTest2LoopCounter = 0UL;
+volatile uint32_t *pulRegTest1LoopCounter = &ulRegTest1LoopCounter;
+volatile uint32_t *pulRegTest2LoopCounter = &ulRegTest2LoopCounter;
+/*-----------------------------------------------------------*/
+
+void main_full( void )
+{
+ /* Start all the other standard demo/test tasks. They have no particular
+ functionality, but do demonstrate how to use the FreeRTOS API and test the
+ kernel port. */
+ vCreateBlockTimeTasks();
+ vStartTimerDemoTask( mainTIMER_TEST_PERIOD );
+ vStartDynamicPriorityTasks();
+ vStartTaskNotifyTask();
+
+ /* Create the register check tasks, as described at the top of this file.
+ Use xTaskCreateStatic() to create a task using only statically allocated
+ memory. */
+ xTaskCreate( prvRegTestTaskEntry1, /* The function that implements the task. */
+ "Reg1", /* The name of the task. */
+ mainREG_TEST_STACK_SIZE_WORDS, /* Size of stack to allocate for the task - in words not bytes!. */
+ mainREG_TEST_TASK_1_PARAMETER, /* Parameter passed into the task. */
+ tskIDLE_PRIORITY, /* Priority of the task. */
+ NULL ); /* Can be used to pass out a handle to the created task. */
+ xTaskCreate( prvRegTestTaskEntry2, "Reg2", mainREG_TEST_STACK_SIZE_WORDS, mainREG_TEST_TASK_2_PARAMETER, tskIDLE_PRIORITY, NULL );
+
+ /* Create the task that performs the 'check' functionality, as described at
+ the top of this file. */
+ xTaskCreate( prvCheckTask, "Check", mainCHECK_TASK_STACK_SIZE_WORDS, NULL, mainCHECK_TASK_PRIORITY, NULL );
+
+ /* Start the scheduler. */
+ vTaskStartScheduler();
+
+ /* If all is well, the scheduler will now be running, and the following
+ line will never be reached. If the following line does execute, then
+ there was insufficient FreeRTOS heap memory available for the Idle and/or
+ timer tasks to be created. See the memory management section on the
+ FreeRTOS web site for more details on the FreeRTOS heap
+ http://www.freertos.org/a00111.html. */
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+static void prvCheckTask( void *pvParameters )
+{
+TickType_t xDelayPeriod = mainNO_ERROR_CHECK_TASK_PERIOD;
+TickType_t xLastExecutionTime;
+uint32_t ulLastRegTest1Value = 0, ulLastRegTest2Value = 0;
+char * const pcPassMessage = ".";
+char * pcStatusMessage = pcPassMessage;
+extern void vToggleLED( void );
+
+ /* Just to stop compiler warnings. */
+ ( void ) pvParameters;
+
+ /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil()
+ works correctly. */
+ xLastExecutionTime = xTaskGetTickCount();
+
+ /* Cycle for ever, delaying then checking all the other tasks are still
+ operating without error. The onboard LED is toggled on each iteration.
+ If an error is detected then the delay period is decreased from
+ mainNO_ERROR_CHECK_TASK_PERIOD to mainERROR_CHECK_TASK_PERIOD. This has the
+ effect of increasing the rate at which the onboard LED toggles, and in so
+ doing gives visual feedback of the system status. */
+ for( ;; )
+ {
+ /* Delay until it is time to execute again. */
+ vTaskDelayUntil( &xLastExecutionTime, xDelayPeriod );
+
+ /* Check all the demo tasks (other than the flash tasks) to ensure
+ that they are all still running, and that none have detected an error. */
+ if( xAreDynamicPriorityTasksStillRunning() == pdFALSE )
+ {
+ pcStatusMessage = "ERROR: Dynamic priority demo/tests.\r\n";
+ }
+
+ if( xAreBlockTimeTestTasksStillRunning() == pdFALSE )
+ {
+ pcStatusMessage = "ERROR: Block time demo/tests.\r\n";
+ }
+
+ if( xAreTimerDemoTasksStillRunning( ( TickType_t ) xDelayPeriod ) == pdFALSE )
+ {
+ pcStatusMessage = "ERROR: Timer demo/tests.\r\n";
+ }
+
+ if( xAreTaskNotificationTasksStillRunning() == pdFALSE )
+ {
+ pcStatusMessage = "ERROR: Task notification demo/tests.\r\n";
+ }
+
+ /* Check that the register test 1 task is still running. */
+ if( ulLastRegTest1Value == ulRegTest1LoopCounter )
+ {
+ pcStatusMessage = "ERROR: Register test 1.\r\n";
+ }
+ ulLastRegTest1Value = ulRegTest1LoopCounter;
+
+ /* Check that the register test 2 task is still running. */
+ if( ulLastRegTest2Value == ulRegTest2LoopCounter )
+ {
+ pcStatusMessage = "ERROR: Register test 2.\r\n";
+ }
+ ulLastRegTest2Value = ulRegTest2LoopCounter;
+
+ /* Write the status message to the UART and toggle the LED to show the
+ system status if the UART is not connected. */
+ vToggleLED();
+
+ /* If an error has been found then increase the LED toggle rate by
+ increasing the cycle frequency. */
+ if( pcStatusMessage != pcPassMessage )
+ {
+ xDelayPeriod = mainERROR_CHECK_TASK_PERIOD;
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvRegTestTaskEntry1( void *pvParameters )
+{
+ /* Although the regtest task is written in assembler, its entry point is
+ written in C for convenience of checking the task parameter is being passed
+ in correctly. */
+ if( pvParameters == mainREG_TEST_TASK_1_PARAMETER )
+ {
+ /* Start the part of the test that is written in assembler. */
+ vRegTest1Implementation();
+ }
+
+ /* The following line will only execute if the task parameter is found to
+ be incorrect. The check task will detect that the regtest loop counter is
+ not being incremented and flag an error. */
+ vTaskDelete( NULL );
+}
+/*-----------------------------------------------------------*/
+
+static void prvRegTestTaskEntry2( void *pvParameters )
+{
+ /* Although the regtest task is written in assembler, its entry point is
+ written in C for convenience of checking the task parameter is being passed
+ in correctly. */
+ if( pvParameters == mainREG_TEST_TASK_2_PARAMETER )
+ {
+ /* Start the part of the test that is written in assembler. */
+ vRegTest2Implementation();
+ }
+
+ /* The following line will only execute if the task parameter is found to
+ be incorrect. The check task will detect that the regtest loop counter is
+ not being incremented and flag an error. */
+ vTaskDelete( NULL );
+}
+/*-----------------------------------------------------------*/
+
+void vFullDemoTickHook( void )
+{
+ /* Called from vApplicationTickHook() when the project is configured to
+ build the full test/demo applications. */
+
+ /* Use task notifications from an interrupt. */
+ xNotifyTaskFromISR();
+}
+/*-----------------------------------------------------------*/
+
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/main.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/main.c
new file mode 100644
index 000000000..de03b623b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/main.c
@@ -0,0 +1,275 @@
+/*
+ * FreeRTOS Kernel V10.2.1
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+
+/******************************************************************************
+ * This project provides two demo applications. A simple blinky style project,
+ * and a more comprehensive test and demo application. The
+ * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting (defined in this file) is used to
+ * select between the two. The simply blinky demo is implemented and described
+ * in main_blinky.c. The more comprehensive test and demo application is
+ * implemented and described in main_full.c.
+ *
+ * This file implements the code that is not demo specific, including the
+ * hardware setup and standard FreeRTOS hook functions.
+ *
+ * When running on the HiFive Rev B hardware:
+ * When executing correctly the blue LED will toggle every three seconds. If
+ * the blue LED toggles every 500ms then one of the self-monitoring test tasks
+ * discovered a potential issue. If the red led toggles rapidly then a hardware
+ * exception occurred.
+ *
+ * ENSURE TO READ THE DOCUMENTATION PAGE FOR THIS PORT AND DEMO APPLICATION ON
+ * THE http://www.FreeRTOS.org WEB SITE FOR FULL INFORMATION ON USING THIS DEMO
+ * APPLICATION, AND ITS ASSOCIATE FreeRTOS ARCHITECTURE PORT!
+ *
+ */
+
+/* FreeRTOS kernel includes. */
+#include <FreeRTOS.h>
+#include <task.h>
+
+/* Freedom metal driver includes. */
+#include <metal/cpu.h>
+#include <metal/led.h>
+
+/* Set mainCREATE_SIMPLE_BLINKY_DEMO_ONLY to one to run the simple blinky demo,
+or 0 to run the more comprehensive test and demo application. */
+#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 0
+
+/* Index to first HART (there is only one). */
+#define mainHART_0 0
+
+/* Registers used to initialise the PLIC. */
+#define mainPLIC_PENDING_0 ( * ( ( volatile uint32_t * ) 0x0C001000UL ) )
+#define mainPLIC_PENDING_1 ( * ( ( volatile uint32_t * ) 0x0C001004UL ) )
+#define mainPLIC_ENABLE_0 ( * ( ( volatile uint32_t * ) 0x0C002000UL ) )
+#define mainPLIC_ENABLE_1 ( * ( ( volatile uint32_t * ) 0x0C002004UL ) )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * main_blinky() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1.
+ * main_full() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0.
+ */
+#if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1
+ extern void main_blinky( void );
+#else
+ extern void main_full( void );
+#endif /* #if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 */
+
+/*
+ * Prototypes for the standard FreeRTOS callback/hook functions implemented
+ * within this file. See https://www.freertos.org/a00016.html
+ */
+void vApplicationMallocFailedHook( void );
+void vApplicationIdleHook( void );
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );
+void vApplicationTickHook( void );
+
+/*
+ * Setup the hardware to run this demo.
+ */
+static void prvSetupHardware( void );
+
+/*
+ * Used by the Freedom Metal drivers.
+ */
+static struct metal_led *pxBlueLED = NULL;
+
+/*-----------------------------------------------------------*/
+
+int main( void )
+{
+ prvSetupHardware();
+
+ /* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top
+ of this file. */
+ #if( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 )
+ {
+ main_blinky();
+ }
+ #else
+ {
+ main_full();
+ }
+ #endif
+}
+/*-----------------------------------------------------------*/
+
+static void prvSetupHardware( void )
+{
+struct metal_cpu *pxCPU;
+struct metal_interrupt *pxInterruptController;
+
+ /* Initialise the blue LED. */
+ pxBlueLED = metal_led_get_rgb( "LD0", "blue" );
+ configASSERT( pxBlueLED );
+ metal_led_enable( pxBlueLED );
+ metal_led_off( pxBlueLED );
+
+ /* Initialise the interrupt controller. */
+ pxCPU = metal_cpu_get( mainHART_0 );
+ configASSERT( pxCPU );
+ pxInterruptController = metal_cpu_interrupt_controller( pxCPU );
+ configASSERT( pxInterruptController );
+ metal_interrupt_init( pxInterruptController );
+
+ /* Set all interrupt enable bits to 0. */
+ mainPLIC_ENABLE_0 = 0UL;
+ mainPLIC_ENABLE_1 = 0UL;
+
+ /* Clear all pending interrupts. */
+ mainPLIC_PENDING_0 = 0UL;
+ mainPLIC_PENDING_1 = 0UL;
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationMallocFailedHook( void )
+{
+ /* vApplicationMallocFailedHook() will only be called if
+ configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
+ function that will get called if a call to pvPortMalloc() fails.
+ pvPortMalloc() is called internally by the kernel whenever a task, queue,
+ timer or semaphore is created. It is also called by various parts of the
+ demo application. If heap_1.c or heap_2.c are used, then the size of the
+ heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
+ FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
+ to query the size of free heap space that remains (although it does not
+ provide information on how the remaining heap might be fragmented). */
+ taskDISABLE_INTERRUPTS();
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationIdleHook( void )
+{
+ /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
+ to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
+ task. It is essential that code added to this hook function never attempts
+ to block in any way (for example, call xQueueReceive() with a block time
+ specified, or call vTaskDelay()). If the application makes use of the
+ vTaskDelete() API function (as this demo application does) then it is also
+ important that vApplicationIdleHook() is permitted to return to its calling
+ function, because it is the responsibility of the idle task to clean up
+ memory allocated by the kernel to any task that has since been deleted. */
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
+{
+ ( void ) pcTaskName;
+ ( void ) pxTask;
+
+ /* Run time stack overflow checking is performed if
+ configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
+ function is called if a stack overflow is detected. */
+ taskDISABLE_INTERRUPTS();
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationTickHook( void )
+{
+ /* The tests in the full demo expect some interaction with interrupts. */
+ #if( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 )
+ {
+ extern void vFullDemoTickHook( void );
+ vFullDemoTickHook();
+ }
+ #endif
+}
+/*-----------------------------------------------------------*/
+
+void vAssertCalled( void )
+{
+static struct metal_led *pxRedLED = NULL;
+volatile uint32_t ul;
+const uint32_t ulNullLoopDelay = 0x1ffffUL;
+
+ taskDISABLE_INTERRUPTS();
+
+ /* Initialise the red LED. */
+ pxRedLED = metal_led_get_rgb( "LD0", "red" );
+ configASSERT( pxRedLED );
+ metal_led_enable( pxRedLED );
+ metal_led_off( pxRedLED );
+
+ /* Flash the red LED to indicate that assert was hit - interrupts are off
+ here to prevent any further tick interrupts or context switches, so the
+ delay is implemented as a crude loop instead of a peripheral timer. */
+ for( ;; )
+ {
+ for( ul = 0; ul < ulNullLoopDelay; ul++ )
+ {
+ __asm volatile( "nop" );
+ }
+ metal_led_toggle( pxRedLED );
+ }
+}
+/*-----------------------------------------------------------*/
+
+void handle_trap( void )
+{
+volatile uint32_t ulMEPC = 0UL, ulMCAUSE = 0UL, ulPLICPending0Register = 0UL, ulPLICPending1Register = 0UL;
+
+ /* Store a few register values that might be useful when determining why this
+ function was called. */
+ __asm volatile( "csrr %0, mepc" : "=r"( ulMEPC ) );
+ __asm volatile( "csrr %0, mcause" : "=r"( ulMCAUSE ) );
+ ulPLICPending0Register = mainPLIC_PENDING_0;
+ ulPLICPending1Register = mainPLIC_PENDING_1;
+
+ /* Prevent compiler warnings about unused variables. */
+ ( void ) ulPLICPending0Register;
+ ( void ) ulPLICPending1Register;
+
+ /* Force an assert as this function has not been implemented as the demo
+ does not use external interrupts. */
+ configASSERT( metal_cpu_get( mainHART_0 ) == 0x00 );
+}
+/*-----------------------------------------------------------*/
+
+void vToggleLED( void )
+{
+ metal_led_toggle( pxBlueLED );
+}
+/*-----------------------------------------------------------*/
+
+void *malloc( size_t xSize )
+{
+ /* The linker script does not define a heap so artificially force an assert()
+ if something unexpectedly uses the C library heap. See
+ https://www.freertos.org/a00111.html for more information. */
+ configASSERT( metal_cpu_get( mainHART_0 ) == 0x00 );
+
+ /* Remove warnings about unused parameter. */
+ ( void ) xSize;
+ return NULL;
+}
+/*-----------------------------------------------------------*/
+
+