From 3bcd0c8a9d1b399c59475115322cbb93484e66d2 Mon Sep 17 00:00:00 2001 From: rtel Date: Wed, 1 Jan 2020 22:02:06 +0000 Subject: [PATCH] Update RISCC-V-RV32-SiFive_HiFive1_FreedomStudio project to latest tools and metal library versions. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2789 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../.cproject | 256 ++++++---- .../.settings/language.settings.xml | 34 +- .../freedom-metal/gloss/crt0.S | 28 +- .../freedom-metal/gloss/sys_gettimeofday.c | 6 +- .../freedom-metal/gloss/sys_sbrk.c | 3 +- .../freedom-metal/gloss/sys_times.c | 3 +- .../freedom-metal/metal/button.h | 4 +- .../freedom-metal/metal/cache.h | 46 +- .../freedom-metal/metal/clock.h | 83 +++- .../freedom-metal/metal/cpu.h | 42 +- .../freedom-metal/metal/drivers/riscv_cpu.h | 21 +- .../metal/drivers/sifive_ccache0.h | 23 + .../metal/drivers/sifive_clic0.h | 3 +- .../metal/drivers/sifive_fe310-g000_lfrosc.h | 21 + .../metal/drivers/sifive_fe310-g000_prci.h | 1 + .../metal/drivers/sifive_fu540-c000_l2.h | 8 +- .../freedom-metal/metal/drivers/sifive_rtc0.h | 27 ++ .../freedom-metal/metal/drivers/sifive_spi0.h | 2 + .../metal/drivers/sifive_trace.h | 23 + .../metal/drivers/sifive_uart0.h | 2 + .../metal/drivers/sifive_wdog0.h | 26 ++ .../freedom-metal/metal/gpio.h | 149 +++++- .../freedom-metal/metal/interrupt.h | 357 +++++++++++++- .../freedom-metal/metal/io.h | 2 +- .../freedom-metal/metal/led.h | 8 +- .../freedom-metal/metal/lock.h | 27 +- .../freedom-metal/metal/memory.h | 18 +- .../freedom-metal/metal/pmp.h | 11 +- .../freedom-metal/metal/privilege.h | 4 +- .../freedom-metal/metal/rtc.h | 127 +++++ .../freedom-metal/metal/shutdown.h | 4 +- .../freedom-metal/metal/spi.h | 22 +- .../freedom-metal/metal/switch.h | 4 +- .../freedom-metal/metal/time.h | 18 + .../freedom-metal/metal/tty.h | 33 +- .../freedom-metal/metal/uart.h | 32 +- .../freedom-metal/metal/watchdog.h | 163 +++++++ .../freedom-metal/src/button.c | 4 +- .../freedom-metal/src/cache.c | 185 +++++++- .../freedom-metal/src/clock.c | 11 +- .../freedom-metal/src/cpu.c | 36 +- .../freedom-metal/src/drivers/fixed-clock.c | 2 + .../src/drivers/fixed-factor-clock.c | 2 + .../freedom-metal/src/drivers/riscv_clint0.c | 67 ++- .../freedom-metal/src/drivers/riscv_cpu.c | 437 +++++++++++++++--- .../freedom-metal/src/drivers/riscv_plic0.c | 49 +- .../src/drivers/sifive_ccache0.c | 84 ++++ .../freedom-metal/src/drivers/sifive_clic0.c | 294 +++++++++--- .../src/drivers/sifive_fe310-g000_hfrosc.c | 6 +- .../src/drivers/sifive_fe310-g000_hfxosc.c | 6 +- .../src/drivers/sifive_fe310-g000_lfrosc.c | 53 +++ .../src/drivers/sifive_fe310-g000_pll.c | 10 +- .../src/drivers/sifive_fe310-g000_prci.c | 2 + .../src/drivers/sifive_fu540-c000_l2.c | 29 +- .../sifive_global-external-interrupts0.c | 49 ++ .../src/drivers/sifive_gpio-buttons.c | 2 + .../src/drivers/sifive_gpio-leds.c | 2 + .../src/drivers/sifive_gpio-switches.c | 2 + .../freedom-metal/src/drivers/sifive_gpio0.c | 150 +++++- .../sifive_local-external-interrupts0.c | 34 ++ .../freedom-metal/src/drivers/sifive_rtc0.c | 121 +++++ .../freedom-metal/src/drivers/sifive_spi0.c | 168 ++++++- .../freedom-metal/src/drivers/sifive_test0.c | 10 +- .../freedom-metal/src/drivers/sifive_trace.c | 95 ++++ .../freedom-metal/src/drivers/sifive_uart0.c | 48 +- .../freedom-metal/src/drivers/sifive_wdog0.c | 213 +++++++++ .../freedom-metal/src/entry.S | 1 - .../freedom-metal/src/gpio.c | 24 +- .../freedom-metal/src/interrupt.c | 74 ++- .../freedom-metal/src/led.c | 8 +- .../freedom-metal/src/lock.c | 6 +- .../freedom-metal/src/memory.c | 8 +- .../freedom-metal/src/pmp.c | 120 ++--- .../freedom-metal/src/privilege.c | 12 +- .../freedom-metal/src/rtc.c | 27 ++ .../freedom-metal/src/shutdown.c | 4 +- .../freedom-metal/src/spi.c | 18 +- .../freedom-metal/src/switch.c | 4 +- .../freedom-metal/src/synchronize_harts.c | 62 +++ .../freedom-metal/src/time.c | 30 ++ .../freedom-metal/src/timer.c | 6 +- .../freedom-metal/src/tty.c | 30 +- .../freedom-metal/src/uart.c | 11 +- .../freedom-metal/src/vector.S | 160 +++++++ .../main.c | 5 +- 85 files changed, 3831 insertions(+), 591 deletions(-) create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_ccache0.h create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_lfrosc.h create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_rtc0.h create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_trace.h create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_wdog0.h create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/rtc.h create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/time.h create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/watchdog.h create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_ccache0.c create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_lfrosc.c create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_rtc0.c create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_trace.c create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_wdog0.c create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/rtc.c create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/synchronize_harts.c create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/time.c create mode 100644 FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/vector.S diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/.cproject b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/.cproject index 472b5006f..8efeeeefd 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/.cproject +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/.cproject @@ -1,88 +1,174 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/.settings/language.settings.xml b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/.settings/language.settings.xml index 569805cb5..b0d04ea76 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/.settings/language.settings.xml +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/.settings/language.settings.xml @@ -1,14 +1,26 @@ - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/crt0.S b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/crt0.S index 2141915ea..920ee4b9f 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/crt0.S +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/crt0.S @@ -80,11 +80,19 @@ _start: 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 */ @@ -96,13 +104,25 @@ _start: 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 @@ -110,9 +130,15 @@ _start: 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 @@ -131,7 +157,7 @@ _skip_init: /* Synchronize harts so that secondary harts wait until hart 0 finishes initializing */ - call _synchronize_harts + call __metal_synchronize_harts /* Check RISC-V isa and enable FS bits if Floating Point architecture. */ csrr a5, misa diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/sys_gettimeofday.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/sys_gettimeofday.c index 3f867e4eb..409b2ce2f 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/sys_gettimeofday.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/sys_gettimeofday.c @@ -7,10 +7,12 @@ _gettimeofday(struct timeval *tp, void *tzp) { int rv; unsigned long long mcc, timebase; - if (rv = metal_timer_get_cyclecount(0, &mcc)) { + rv = metal_timer_get_cyclecount(0, &mcc); + if (rv != 0) { return -1; } - if (rv = metal_timer_get_timebase_frequency(0, &timebase)) { + rv = metal_timer_get_timebase_frequency(0, &timebase); + if (rv != 0) { return -1; } tp->tv_sec = mcc / timebase; diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/sys_sbrk.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/sys_sbrk.c index 34ef77ff5..cc01c8ffb 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/sys_sbrk.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/sys_sbrk.c @@ -24,7 +24,7 @@ _sbrk(ptrdiff_t incr) /* If __heap_size == 0, we can't allocate memory on the heap */ if(&metal_segment_heap_target_start == &metal_segment_heap_target_end) { - return NULL; + return (void *)-1; } /* Don't move the break past the end of the heap */ @@ -32,6 +32,7 @@ _sbrk(ptrdiff_t incr) brk += incr; } else { brk = &metal_segment_heap_target_end; + return (void *)-1; } return old; diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/sys_times.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/sys_times.c index 40d1f4e3f..6beedcb30 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/sys_times.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/gloss/sys_times.c @@ -30,7 +30,8 @@ _times(struct tms *buf) _gettimeofday (&t, 0); unsigned long long timebase; - if (rv = metal_timer_get_timebase_frequency(0, &timebase)) { + rv = metal_timer_get_timebase_frequency(0, &timebase); + if (rv != 0) { return -1; } diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/button.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/button.h index 0c26f435a..3ae1c143e 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/button.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/button.h @@ -45,7 +45,7 @@ struct metal_button* metal_button_get(char *label); * @return A pointer to the interrupt controller responsible for handling * button interrupts. */ -inline struct metal_interrupt* +__inline__ struct metal_interrupt* metal_button_interrupt_controller(struct metal_button *button) { return button->vtable->interrupt_controller(button); } /*! @@ -54,6 +54,6 @@ inline struct metal_interrupt* * @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); } +__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_FreedomStudio/freedom-metal/metal/cache.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/cache.h index a8a60ada6..bad026480 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/cache.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/cache.h @@ -9,6 +9,7 @@ * * @brief API for configuring caches */ +#include struct metal_cache; @@ -32,8 +33,8 @@ struct metal_cache { * * 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); +__inline__ void metal_cache_init(struct metal_cache *cache, int ways) { + cache->vtable->init(cache, ways); } /*! @@ -41,7 +42,7 @@ inline void metal_cache_init(struct metal_cache *cache, int 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) { +__inline__ int metal_cache_get_enabled_ways(struct metal_cache *cache) { return cache->vtable->get_enabled_ways(cache); } @@ -51,8 +52,45 @@ inline int metal_cache_get_enabled_ways(struct metal_cache *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) { +__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_FreedomStudio/freedom-metal/metal/clock.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/clock.h index 277841e01..622fc9470 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/clock.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/clock.h @@ -22,14 +22,57 @@ struct __metal_clock_vtable { }; /*! - * @brief Function signature of clock pre-rate change callbacks + * @brief Function signature of clock rate change callbacks */ -typedef void (*metal_clock_pre_rate_change_callback)(void *priv); +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 Function signature of clock post-rate change callbacks + * @brief Type for the linked list of callbacks for clock rate changes */ -typedef void (*metal_clock_post_rate_change_callback)(void *priv); +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 @@ -46,13 +89,11 @@ typedef void (*metal_clock_post_rate_change_callback)(void *priv); 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; + /* Pre-rate change callback linked list */ + metal_clock_callback *_pre_rate_change_callback; - /* Post-rate change callback */ - metal_clock_post_rate_change_callback _post_rate_change_callback; - void *_post_rate_change_callback_priv; + /* Post-rate change callback linked list */ + metal_clock_callback *_post_rate_change_callback; }; /*! @@ -61,7 +102,7 @@ struct metal_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); } +__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 @@ -77,15 +118,13 @@ inline long metal_clock_get_rate_hz(const struct metal_clock *clk) { return clk- * 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) +__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); + _metal_clock_call_all_callbacks(clk->_pre_rate_change_callback); 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); + _metal_clock_call_all_callbacks(clk->_post_rate_change_callback); return out; } @@ -95,12 +134,10 @@ inline long metal_clock_set_rate_hz(struct metal_clock *clk, long hz) * * @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) +__inline__ void metal_clock_register_pre_rate_change_callback(struct metal_clock *clk, metal_clock_callback *cb) { - clk->_pre_rate_change_callback = cb; - clk->_pre_rate_change_callback_priv = priv; + clk->_pre_rate_change_callback = _metal_clock_append_to_callbacks(clk->_pre_rate_change_callback, cb); } /*! @@ -108,12 +145,10 @@ inline void metal_clock_register_pre_rate_change_callback(struct metal_clock *cl * * @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) +__inline__ void metal_clock_register_post_rate_change_callback(struct metal_clock *clk, metal_clock_callback *cb) { - clk->_post_rate_change_callback = cb; - clk->_post_rate_change_callback_priv = priv; + 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_FreedomStudio/freedom-metal/metal/cpu.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/cpu.h index 453bd12de..dbd3dbfb5 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/cpu.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/cpu.h @@ -20,7 +20,7 @@ struct metal_cpu; 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 (*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); @@ -49,17 +49,17 @@ struct metal_cpu { * @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); +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(); +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(); +int metal_cpu_get_num_harts(void); /*! @brief Get the CPU cycle count timer value * @@ -68,8 +68,8 @@ int metal_cpu_get_num_harts(); * @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); } +__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 * @@ -78,7 +78,7 @@ inline unsigned long long metal_cpu_get_timer(struct metal_cpu *cpu) * @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) +__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 @@ -90,7 +90,7 @@ inline unsigned long long metal_cpu_get_timebase(struct metal_cpu *cpu) * @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) +__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 @@ -103,7 +103,7 @@ inline unsigned long long metal_cpu_get_mtime(struct metal_cpu *cpu) * @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) +__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 @@ -115,7 +115,7 @@ inline int metal_cpu_set_mtimecmp(struct metal_cpu *cpu, unsigned long long time * @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) +__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 @@ -125,7 +125,7 @@ inline struct metal_interrupt* metal_cpu_timer_interrupt_controller(struct metal * @param cpu The CPU device handle * @return The timer interrupt ID */ -inline int metal_cpu_timer_get_interrupt_id(struct metal_cpu *cpu) +__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 @@ -137,7 +137,7 @@ inline int metal_cpu_timer_get_interrupt_id(struct metal_cpu *cpu) * @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) +__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 @@ -147,7 +147,7 @@ inline struct metal_interrupt* metal_cpu_software_interrupt_controller(struct me * @param cpu The CPU device handle * @return the software interrupt ID */ -inline int metal_cpu_software_get_interrupt_id(struct metal_cpu *cpu) +__inline__ int metal_cpu_software_get_interrupt_id(struct metal_cpu *cpu) { return cpu->vtable->get_sw_interrupt_id(cpu); } /*! @@ -161,7 +161,7 @@ inline int metal_cpu_software_get_interrupt_id(struct metal_cpu *cpu) * @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) +__inline__ int metal_cpu_software_set_ipi(struct metal_cpu *cpu, int hartid) { return cpu->vtable->set_sw_ipi(cpu, hartid); } /*! @@ -175,7 +175,7 @@ inline int metal_cpu_software_set_ipi(struct metal_cpu *cpu, int hartid) * @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) +__inline__ int metal_cpu_software_clear_ipi(struct metal_cpu *cpu, int hartid) { return cpu->vtable->clear_sw_ipi(cpu, hartid); } /*! @@ -190,7 +190,7 @@ inline int metal_cpu_software_clear_ipi(struct metal_cpu *cpu, int hartid) * @param hartid The CPU hart to read * @return 0 upon success */ -inline int metal_cpu_get_msip(struct metal_cpu *cpu, int hartid) +__inline__ int metal_cpu_get_msip(struct metal_cpu *cpu, int hartid) { return cpu->vtable->get_msip(cpu, hartid); } /*! @@ -204,7 +204,7 @@ inline int metal_cpu_get_msip(struct metal_cpu *cpu, int hartid) * @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) +__inline__ struct metal_interrupt* metal_cpu_interrupt_controller(struct metal_cpu *cpu) { return cpu->vtable->controller_interrupt(cpu); } /*! @@ -218,7 +218,7 @@ inline struct metal_interrupt* metal_cpu_interrupt_controller(struct metal_cpu * * @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) +__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); } /*! @@ -237,7 +237,7 @@ inline int metal_cpu_exception_register(struct metal_cpu *cpu, int ecode, metal_ * @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) +__inline__ int metal_cpu_get_instruction_length(struct metal_cpu *cpu, uintptr_t epc) { return cpu->vtable->get_ilen(cpu, epc); } /*! @@ -249,7 +249,7 @@ inline int metal_cpu_get_instruction_length(struct metal_cpu *cpu, uintptr_t epc * @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) +__inline__ uintptr_t metal_cpu_get_exception_pc(struct metal_cpu *cpu) { return cpu->vtable->get_epc(cpu); } /*! @@ -265,7 +265,7 @@ inline uintptr_t metal_cpu_get_exception_pc(struct metal_cpu *cpu) * @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) +__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_FreedomStudio/freedom-metal/metal/drivers/riscv_cpu.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/riscv_cpu.h index eb1e5b8ca..ca91e0a95 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/riscv_cpu.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/riscv_cpu.h @@ -86,6 +86,9 @@ #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, @@ -97,6 +100,7 @@ typedef enum { 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)), @@ -154,15 +158,6 @@ typedef struct __metal_interrupt_data { 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; }; @@ -170,14 +165,8 @@ struct __metal_driver_vtable_riscv_cpu_intc { 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); -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) diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_ccache0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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_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 +#include + +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_FreedomStudio/freedom-metal/metal/drivers/sifive_clic0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_clic0.h index db9674625..7fef38d19 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_clic0.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_clic0.h @@ -34,7 +34,8 @@ __METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_clic0) struct __metal_driver_sifive_clic0 { struct metal_interrupt controller; int init_done; - metal_interrupt_handler_t metal_mtvt_table[__METAL_CLIC_SUBINTERRUPTS]; + 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 diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_lfrosc.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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_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 +#include +#include + +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_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_prci.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_prci.h index 87c9ca985..387130be5 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_prci.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_prci.h @@ -17,6 +17,7 @@ struct __metal_driver_vtable_sifive_fe310_g000_prci { __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_FreedomStudio/freedom-metal/metal/drivers/sifive_fu540-c000_l2.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_fu540-c000_l2.h index d338c2964..bb98f169e 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_fu540-c000_l2.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_fu540-c000_l2.h @@ -4,16 +4,16 @@ #ifndef METAL__DRIVERS__SIFIVE_FU540_C000_L2_H #define METAL__DRIVERS__SIFIVE_FU540_C000_L2_H -struct __metal_driver_sifive_fu540_c000_l2; - -#include #include +#include struct __metal_driver_vtable_sifive_fu540_c000_l2 { struct __metal_cache_vtable cache; }; -//_RB___METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fu540_c000_l2) +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; diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_rtc0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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_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 +#include + +#include +#include +#include + +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_FreedomStudio/freedom-metal/metal/drivers/sifive_spi0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_spi0.h index 90d4c831e..c4a6848e7 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_spi0.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_spi0.h @@ -19,6 +19,8 @@ __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_FreedomStudio/freedom-metal/metal/drivers/sifive_trace.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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_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 +#include +#include + +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_FreedomStudio/freedom-metal/metal/drivers/sifive_uart0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_uart0.h index 11d954002..5d585e783 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_uart0.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_uart0.h @@ -22,6 +22,8 @@ __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; }; diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_wdog0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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_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 +#include + +#include +#include +#include + +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_FreedomStudio/freedom-metal/metal/gpio.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/gpio.h index 513687dd7..7645494ff 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/gpio.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/gpio.h @@ -5,6 +5,7 @@ #define METAL__GPIO_H #include +#include /*! * @file gpio.h @@ -15,14 +16,31 @@ 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 @@ -36,7 +54,21 @@ struct metal_gpio { * @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); +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 @@ -44,7 +76,7 @@ struct metal_gpio *metal_gpio_get_device(int device_num); * @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) { +__inline__ int metal_gpio_disable_input(struct metal_gpio *gpio, int pin) { if(!gpio) { return 1; } @@ -58,7 +90,7 @@ inline int metal_gpio_disable_input(struct metal_gpio *gpio, int pin) { * @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) { +__inline__ int metal_gpio_enable_output(struct metal_gpio *gpio, int pin) { if(!gpio) { return 1; } @@ -66,6 +98,20 @@ inline int metal_gpio_enable_output(struct metal_gpio *gpio, int pin) { 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 @@ -73,7 +119,7 @@ inline int metal_gpio_enable_output(struct metal_gpio *gpio, int pin) { * @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) { +__inline__ int metal_gpio_set_pin(struct metal_gpio *gpio, int pin, int value) { if(!gpio) { return 1; } @@ -91,7 +137,27 @@ inline int metal_gpio_set_pin(struct metal_gpio *gpio, int pin, int value) { * @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) { +__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; } @@ -111,7 +177,7 @@ inline int metal_gpio_get_pin(struct metal_gpio *gpio, int pin) { * @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) { +__inline__ int metal_gpio_clear_pin(struct metal_gpio *gpio, int pin) { if(!gpio) { return 1; } @@ -125,7 +191,7 @@ inline int metal_gpio_clear_pin(struct metal_gpio *gpio, int pin) { * @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) { +__inline__ int metal_gpio_toggle_pin(struct metal_gpio *gpio, int pin) { if(!gpio) { return 1; } @@ -140,7 +206,7 @@ inline int metal_gpio_toggle_pin(struct metal_gpio *gpio, int pin) { * @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) { +__inline__ int metal_gpio_enable_pinmux(struct metal_gpio *gpio, int pin, int io_function) { if(!gpio) { return 1; } @@ -148,4 +214,71 @@ inline int metal_gpio_enable_pinmux(struct metal_gpio *gpio, int pin, int io_fun 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_FreedomStudio/freedom-metal/metal/interrupt.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/interrupt.h index 43f587aca..4f59bd36b 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/interrupt.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/interrupt.h @@ -10,32 +10,64 @@ #include +/*! + * @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_VECTOR_MODE = 2, - METAL_HARDWARE_VECTOR_MODE = 3 + 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, metal_vector_mode mode); + 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); }; @@ -56,11 +88,107 @@ struct metal_interrupt { * * @param controller The handle for the interrupt controller */ -inline void metal_interrupt_init(struct metal_interrupt *controller) +__inline__ void metal_interrupt_init(struct metal_interrupt *controller) { - return controller->vtable->interrupt_init(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 @@ -70,7 +198,7 @@ inline void metal_interrupt_init(struct metal_interrupt *controller) * @param priv_data Private data for the interrupt handler * @return 0 upon success */ -inline int metal_interrupt_register_handler(struct metal_interrupt *controller, +__inline__ int metal_interrupt_register_handler(struct metal_interrupt *controller, int id, metal_interrupt_handler_t handler, void *priv_data) @@ -78,13 +206,29 @@ inline int metal_interrupt_register_handler(struct metal_interrupt *controller, 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) +__inline__ int metal_interrupt_enable(struct metal_interrupt *controller, int id) { return controller->vtable->interrupt_enable(controller, id); } @@ -95,22 +239,65 @@ inline int metal_interrupt_enable(struct metal_interrupt *controller, int id) * @param id The interrupt ID to disable * @return 0 upon success */ -inline int metal_interrupt_disable(struct metal_interrupt *controller, int id) +__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 - * @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) +__inline__ int metal_interrupt_vector_enable(struct metal_interrupt *controller, int id) { - return controller->vtable->interrupt_vector_enable(controller, id, mode); + return controller->vtable->interrupt_vector_enable(controller, id); } /*! @@ -119,13 +306,153 @@ inline int metal_interrupt_vector_enable(struct metal_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) +__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, +__inline__ int _metal_interrupt_command_request(struct metal_interrupt *controller, int cmd, void *data) { return controller->vtable->command_request(controller, cmd, data); diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/io.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/io.h index 450054142..d55b4520a 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/io.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/io.h @@ -5,7 +5,7 @@ #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)) +#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"); diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/led.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/led.h index a430b84c2..f2aa39ceb 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/led.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/led.h @@ -45,24 +45,24 @@ 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); } +__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); } +__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); } +__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); } +__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_FreedomStudio/freedom-metal/metal/lock.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/lock.h index d863aa96e..0702cbf16 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/lock.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/lock.h @@ -4,6 +4,7 @@ #ifndef METAL__LOCK_H #define METAL__LOCK_H +#include #include #include @@ -15,6 +16,9 @@ /* 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 @@ -41,7 +45,7 @@ struct metal_lock { * 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) { +__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)); @@ -70,16 +74,31 @@ inline int metal_lock_init(struct metal_lock *lock) { * 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) { +__inline__ int metal_lock_take(struct metal_lock *lock) { #ifdef __riscv_atomic int old = 1; int new = 1; - while(old != 0) { + 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; @@ -104,7 +123,7 @@ inline int metal_lock_take(struct metal_lock *lock) { * 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) { +__inline__ int metal_lock_give(struct metal_lock *lock) { #ifdef __riscv_atomic __asm__ volatile("amoswap.w.rl x0, x0, (%[state])" :: [state] "r" (&(lock->_state)) diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/memory.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/memory.h index b62d8b25a..9de7d6162 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/memory.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/memory.h @@ -14,11 +14,11 @@ */ struct _metal_memory_attributes { - int R : 1; - int W : 1; - int X : 1; - int C : 1; - int A : 1; + unsigned int R : 1; + unsigned int W : 1; + unsigned int X : 1; + unsigned int C : 1; + unsigned int A : 1; }; /*! @@ -46,7 +46,7 @@ struct metal_memory *metal_get_memory_from_address(const uintptr_t address); * @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) { +__inline__ uintptr_t metal_memory_get_base_address(const struct metal_memory *memory) { return memory->_base_address; } @@ -55,7 +55,7 @@ inline uintptr_t metal_memory_get_base_address(const struct metal_memory *memory * @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) { +__inline__ size_t metal_memory_get_size(const struct metal_memory *memory) { return memory->_size; } @@ -64,7 +64,7 @@ inline size_t metal_memory_get_size(const struct metal_memory *memory) { * @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) { +__inline__ int metal_memory_supports_atomics(const struct metal_memory *memory) { return memory->_attrs.A; } @@ -73,7 +73,7 @@ inline int metal_memory_supports_atomics(const struct metal_memory *memory) { * @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) { +__inline__ int metal_memory_is_cachable(const struct metal_memory *memory) { return memory->_attrs.C; } diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/pmp.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/pmp.h index 9121b10a1..d948656c8 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/pmp.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/pmp.h @@ -42,11 +42,11 @@ enum metal_pmp_address_mode { */ struct metal_pmp_config { /*! @brief Sets whether reads to the PMP region succeed */ - int R : 1; + unsigned int R : 1; /*! @brief Sets whether writes to the PMP region succeed */ - int W : 1; + unsigned int W : 1; /*! @brief Sets whether the PMP region is executable */ - int X : 1; + unsigned int X : 1; /*! @brief Sets the addressing mode of the PMP region */ enum metal_pmp_address_mode A : 2; @@ -73,6 +73,11 @@ struct metal_pmp { */ 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 diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/privilege.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/privilege.h index c5212e5d1..928a936b1 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/privilege.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/privilege.h @@ -18,7 +18,7 @@ enum metal_privilege_mode { METAL_PRIVILEGE_USER = 0, METAL_PRIVILEGE_SUPERVISOR = 1, - METAL_PRIVELEGE_MACHINE = 3, + METAL_PRIVILEGE_MACHINE = 3, }; #if __riscv_xlen == 32 @@ -113,7 +113,7 @@ struct metal_register_file { #endif /* __riscv_flen */ }; -typedef void (*metal_privilege_entry_point_t)(); +typedef void (*metal_privilege_entry_point_t)(void); void metal_privilege_drop_to_mode(enum metal_privilege_mode mode, struct metal_register_file regfile, diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/rtc.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/rtc.h new file mode 100644 index 000000000..2e742ea38 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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 + +/*! + * @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_FreedomStudio/freedom-metal/metal/shutdown.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/shutdown.h index 3bebfa742..8d4020b5c 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/shutdown.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/shutdown.h @@ -19,8 +19,8 @@ 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); } +__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 diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/spi.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/spi.h index b011fe3ce..635e3c151 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/spi.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/spi.h @@ -25,6 +25,18 @@ struct metal_spi_config { 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 { @@ -42,13 +54,13 @@ struct metal_spi { /*! @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); +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); } +__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 @@ -58,7 +70,7 @@ inline void metal_spi_init(struct metal_spi *spi, int baud_rate) { spi->vtable-> * @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) { +__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); } @@ -66,13 +78,13 @@ inline int metal_spi_transfer(struct metal_spi *spi, struct metal_spi_config *co * @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); } +__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); } +__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_FreedomStudio/freedom-metal/metal/switch.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/switch.h index d1c35bc93..61f0efe56 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/switch.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/switch.h @@ -38,7 +38,7 @@ struct metal_switch* metal_switch_get(char *label); * @param sw The handle for the switch * @return The interrupt controller handle */ -inline struct metal_interrupt* +__inline__ struct metal_interrupt* metal_switch_interrupt_controller(struct metal_switch *sw) { return sw->vtable->interrupt_controller(sw); } /*! @@ -46,6 +46,6 @@ inline struct metal_interrupt* * @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); } +__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_FreedomStudio/freedom-metal/metal/time.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/time.h new file mode 100644 index 000000000..5c33b6f1b --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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 + +/*! + * @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_FreedomStudio/freedom-metal/metal/tty.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/tty.h index d2583e3be..fe4c000db 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/tty.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/tty.h @@ -14,10 +14,39 @@ * * 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(unsigned char c); +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_FreedomStudio/freedom-metal/metal/uart.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/uart.h index 611792a6c..e9e4d0436 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/uart.h +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/uart.h @@ -12,11 +12,13 @@ #include 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, unsigned char c); - int (*getc)(struct metal_uart *uart, unsigned char *c); + 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); @@ -39,7 +41,7 @@ struct metal_uart { * @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); } +__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 @@ -47,22 +49,32 @@ inline void metal_uart_init(struct metal_uart *uart, int baud_rate) { return uar * @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); } +__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, unsigned char *c) { return uart->vtable->getc(uart, c); } +__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); } +__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 @@ -70,7 +82,7 @@ inline int metal_uart_get_baud_rate(struct metal_uart *uart) { return uart->vtab * @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); } +__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 @@ -82,13 +94,13 @@ inline int metal_uart_set_baud_rate(struct metal_uart *uart, int baud_rate) { re * @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); } +__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); } +__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_FreedomStudio/freedom-metal/metal/watchdog.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/watchdog.h new file mode 100644 index 000000000..b5ff48697 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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 + +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_FreedomStudio/freedom-metal/src/button.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/button.c index 649388b3c..efd645334 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/button.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/button.c @@ -22,6 +22,6 @@ struct metal_button* metal_button_get (char *label) return NULL; } -extern inline struct metal_interrupt* +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); +extern __inline__ int metal_button_get_interrupt_id(struct metal_button *button); diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/cache.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/cache.c index 2f0c9fa69..024ba52ad 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/cache.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/cache.c @@ -2,7 +2,186 @@ /* SPDX-License-Identifier: Apache-2.0 */ #include +#include + +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 + } +} -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); diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/clock.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/clock.c index 3b6b8a751..cc3f4dcf3 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/clock.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/clock.c @@ -3,7 +3,10 @@ #include -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_post_rate_change_callback cb, void *priv); -extern inline void metal_clock_register_pre_rate_change_callback(struct metal_clock *clk, metal_clock_pre_rate_change_callback cb, void *priv); +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_FreedomStudio/freedom-metal/src/cpu.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/cpu.c index 2c415a846..25fda5de7 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/cpu.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/cpu.c @@ -4,7 +4,7 @@ #include #include -struct metal_cpu* metal_cpu_get(int hartid) +struct metal_cpu* metal_cpu_get(unsigned int hartid) { if (hartid < __METAL_DT_MAX_HARTS) { return (struct metal_cpu *)__metal_cpu_table[hartid]; @@ -16,7 +16,7 @@ int metal_cpu_get_current_hartid() { #ifdef __riscv int mhartid; - asm volatile("csrr %0, mhartid" : "=r" (mhartid)); + __asm__ volatile("csrr %0, mhartid" : "=r" (mhartid)); return mhartid; #endif } @@ -26,34 +26,34 @@ 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_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_timebase(struct metal_cpu *cpu); -extern inline unsigned long long metal_cpu_get_mtime(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__ 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__ 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__ 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__ 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_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_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_software_clear_ipi(struct metal_cpu *cpu, int hartid); -extern inline int metal_cpu_get_msip(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__ 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_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__ 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__ 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); +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_FreedomStudio/freedom-metal/src/drivers/fixed-clock.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/fixed-clock.c index a1219e01e..92c61d023 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/fixed-clock.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/fixed-clock.c @@ -25,3 +25,5 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_fixed_clock) = { }; #endif /* METAL_FIXED_CLOCK */ + +typedef int no_empty_translation_units; diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/fixed-factor-clock.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/fixed-factor-clock.c index 2e0624652..57d83af87 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/fixed-factor-clock.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/fixed-factor-clock.c @@ -30,3 +30,5 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_fixed_factor_clock) = { .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_FreedomStudio/freedom-metal/src/drivers/riscv_clint0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/riscv_clint0.c index f1814d365..d0488b317 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/riscv_clint0.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/riscv_clint0.c @@ -76,11 +76,15 @@ int __metal_driver_riscv_clint0_register (struct metal_interrupt *controller, 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); @@ -97,6 +101,41 @@ int __metal_driver_riscv_clint0_register (struct metal_interrupt *controller, 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; @@ -120,6 +159,8 @@ int __metal_driver_riscv_clint0_enable (struct metal_interrupt *controller, int rc = intc->vtable->interrupt_enable(intc, id); } } + + return rc; } int __metal_driver_riscv_clint0_disable (struct metal_interrupt *controller, int id) @@ -145,6 +186,8 @@ int __metal_driver_riscv_clint0_disable (struct metal_interrupt *controller, int rc = intc->vtable->interrupt_disable(intc, id); } } + + return rc; } int __metal_driver_riscv_clint0_command_request (struct metal_interrupt *controller, @@ -206,13 +249,35 @@ int __metal_driver_riscv_clint0_command_request (struct metal_interrupt *control 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_FreedomStudio/freedom-metal/src/drivers/riscv_cpu.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/riscv_cpu.c index 88175eb18..b693f312a 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/riscv_cpu.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/riscv_cpu.c @@ -6,6 +6,7 @@ #include #include +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); @@ -20,7 +21,7 @@ struct metal_cpu *__metal_driver_cpu_get(int hartid) uintptr_t __metal_myhart_id (void) { uintptr_t myhart; - asm volatile ("csrr %0, mhartid" : "=r"(myhart)); + __asm__ volatile ("csrr %0, mhartid" : "=r"(myhart)); return myhart; } @@ -34,54 +35,54 @@ void __metal_zero_memory (unsigned char *base, unsigned int size) void __metal_interrupt_global_enable (void) { uintptr_t m; - asm volatile ("csrrs %0, mstatus, %1" : "=r"(m) : "r"(METAL_MIE_INTERRUPT)); + __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)); + __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)); + __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)); + __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)); + __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)); + __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)); + __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)); + __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)); + __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)); + __asm__ volatile ("csrrc %0, mie, %1" : "=r"(m) : "r"(b)); } void __metal_default_exception_handler (struct metal_cpu *cpu, int ecode) { @@ -92,12 +93,31 @@ 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)); + __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); @@ -105,6 +125,20 @@ void __metal_default_sw_handler (int id, void *priv) { } } +/* 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); @@ -113,6 +147,20 @@ void __metal_default_timer_handler (int id, void *priv) { __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; @@ -121,17 +169,17 @@ void __metal_exception_handler (void) { 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)); + __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_LC0) || + 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); @@ -141,9 +189,9 @@ void __metal_exception_handler (void) { uintptr_t mtvt; metal_interrupt_handler_t mtvt_handler; - asm volatile ("csrr %0, mtvt" : "=r"(mtvt)); + __asm__ volatile ("csrr %0, 0x307" : "=r"(mtvt)); priv = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int; - mtvt_handler = (metal_interrupt_handler_t)mtvt; + mtvt_handler = (metal_interrupt_handler_t)*(uintptr_t *)mtvt; mtvt_handler(id, priv); return; } @@ -153,28 +201,271 @@ void __metal_exception_handler (void) { } } +/* 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)); + __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 mtvt, %0" :: "r"(trap_entry | METAL_MTVEC_CLIC)); - asm volatile ("csrw mtvec, %0" :: "r"(val | METAL_MTVEC_CLIC)); + __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 mtvt, %0" :: "r"(trap_entry | METAL_MTVEC_CLIC_VECTORED)); - asm volatile ("csrw mtvec, %0" :: "r"(val | METAL_MTVEC_CLIC_VECTORED)); + __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)); + __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)); + __asm__ volatile ("csrw mtvec, %0" :: "r"(trap_entry & ~METAL_MTVEC_CLIC_VECTORED)); break; } } @@ -270,7 +561,7 @@ int __metal_local_interrupt_enable (struct metal_interrupt *controller, __metal_interrupt_local_disable(id); } break; - defaut: + default: rc = -1; } return rc; @@ -295,25 +586,25 @@ void __metal_driver_riscv_cpu_controller_interrupt_init (struct metal_interrupt if ( !intc->init_done ) { /* Disable and clear all interrupt sources */ - asm volatile ("csrc mie, %0" :: "r"(-1)); - asm volatile ("csrc mip, %0" :: "r"(-1)); + __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)); + __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)); + __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)); + __asm__ volatile ("csrc satp, %0" :: "r"(-1)); } /* Default to use direct interrupt, setup sw cb table*/ @@ -325,12 +616,12 @@ void __metal_driver_riscv_cpu_controller_interrupt_init (struct metal_interrupt 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, &__metal_exception_handler); - asm volatile ("csrr %0, misa" : "=r"(val)); + __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)); + __asm__ volatile ("csrr %0, mstatus" : "=r"(val)); + __asm__ volatile ("csrw mstatus, %0" :: "r"(val | METAL_MSTATUS_FS_INIT)); } intc->init_done = 1; } @@ -380,7 +671,7 @@ int __metal_driver_riscv_cpu_controller_interrupt_register(struct metal_interrup intc->metal_int_table[id].handler = __metal_default_interrupt_handler; intc->metal_int_table[id].sub_int = priv; break; - defaut: + default: rc = -12; } } @@ -406,11 +697,11 @@ int __metal_driver_riscv_cpu_controller_interrupt_enable_vector(struct metal_int if (id == METAL_INTERRUPT_ID_BASE) { if (mode == METAL_DIRECT_MODE) { - __metal_controller_interrupt_vector(mode, &__metal_exception_handler); + __metal_controller_interrupt_vector(mode, (void *)(uintptr_t)&__metal_exception_handler); return 0; } if (mode == METAL_VECTOR_MODE) { - __metal_controller_interrupt_vector(mode, &intc->metal_mtvec_table); + __metal_controller_interrupt_vector(mode, (void *)&intc->metal_mtvec_table); return 0; } } @@ -420,10 +711,30 @@ int __metal_driver_riscv_cpu_controller_interrupt_enable_vector(struct metal_int 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 (id == METAL_INTERRUPT_ID_BASE) { - __metal_controller_interrupt_vector(METAL_DIRECT_MODE, &__metal_exception_handler); + 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; @@ -436,25 +747,23 @@ int __metal_driver_riscv_cpu_controller_command_request (struct metal_interrupt return 0; } -extern inline int __metal_controller_interrupt_is_selective_vectored(void); - /* CPU driver !!! */ -unsigned long long __metal_driver_cpu_timer_get(struct metal_cpu *cpu) +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)); + __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)); + __asm__ volatile ("csrr %0, mcycle" : "=r"(val)); #endif return val; @@ -477,7 +786,6 @@ unsigned long long __metal_driver_cpu_mtime_get (struct metal_cpu *cpu) struct metal_interrupt *tmr_intc; struct __metal_driver_riscv_cpu_intc *intc = (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu); - struct __metal_driver_cpu *_cpu = (void *)cpu; if (intc) { tmr_intc = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].sub_int; @@ -495,7 +803,6 @@ int __metal_driver_cpu_mtimecmp_set (struct metal_cpu *cpu, unsigned long long t struct metal_interrupt *tmr_intc; struct __metal_driver_riscv_cpu_intc *intc = (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu); - struct __metal_driver_cpu *_cpu = (void *)cpu; if (intc) { tmr_intc = intc->metal_int_table[METAL_INTERRUPT_ID_TMR].sub_int; @@ -517,7 +824,7 @@ __metal_driver_cpu_timer_controller_interrupt(struct metal_cpu *cpu) #ifdef __METAL_DT_SIFIVE_CLIC0_HANDLE return __METAL_DT_SIFIVE_CLIC0_HANDLE; #else -#warning "There is no interrupt controller for Timer interrupt" +#pragma message("There is no interrupt controller for Timer interrupt") return NULL; #endif #endif @@ -537,7 +844,7 @@ __metal_driver_cpu_sw_controller_interrupt(struct metal_cpu *cpu) #ifdef __METAL_DT_SIFIVE_CLIC0_HANDLE return __METAL_DT_SIFIVE_CLIC0_HANDLE; #else -#warning "There is no interrupt controller for Software interrupt" +#pragma message("There is no interrupt controller for Software interrupt") return NULL; #endif #endif @@ -554,7 +861,6 @@ int __metal_driver_cpu_set_sw_ipi (struct metal_cpu *cpu, int hartid) struct metal_interrupt *sw_intc; struct __metal_driver_riscv_cpu_intc *intc = (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu); - struct __metal_driver_cpu *_cpu = (void *)cpu; if (intc) { sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int; @@ -572,7 +878,6 @@ int __metal_driver_cpu_clear_sw_ipi (struct metal_cpu *cpu, int hartid) struct metal_interrupt *sw_intc; struct __metal_driver_riscv_cpu_intc *intc = (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu); - struct __metal_driver_cpu *_cpu = (void *)cpu; if (intc) { sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int; @@ -590,7 +895,6 @@ int __metal_driver_cpu_get_msip (struct metal_cpu *cpu, int hartid) struct metal_interrupt *sw_intc; struct __metal_driver_riscv_cpu_intc *intc = (struct __metal_driver_riscv_cpu_intc *)__metal_driver_cpu_interrupt_controller(cpu); - struct __metal_driver_cpu *_cpu = (void *)cpu; if (intc) { sw_intc = intc->metal_int_table[METAL_INTERRUPT_ID_SW].sub_int; @@ -642,35 +946,40 @@ int __metal_driver_cpu_exception_register(struct metal_cpu *cpu, int ecode, 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 */ - return (*(unsigned short*)epc & 3) ? 4 : 2; + /** + * 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)); + __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)); + __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_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_vector_enable = __metal_driver_riscv_cpu_controller_interrupt_enable_vector, - .controller_vtable.interrupt_vector_disable = __metal_driver_riscv_cpu_controller_interrupt_disable_vector, + .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.timer_get = __metal_driver_cpu_timer_get, + .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, diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/riscv_plic0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/riscv_plic0.c index ed9782450..3272f1c66 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/riscv_plic0.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/riscv_plic0.c @@ -25,30 +25,47 @@ void __metal_plic0_complete_interrupt(struct __metal_driver_riscv_plic0 *plic, METAL_RISCV_PLIC0_CLAIM)) = id; } -void __metal_plic0_set_threshold(struct __metal_driver_riscv_plic0 *plic, - unsigned int threshold) +int __metal_plic0_set_threshold(struct metal_interrupt *controller, unsigned int threshold) { - unsigned long control_base = __metal_driver_sifive_plic0_control_base((struct metal_interrupt *)plic); + 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; } -void __metal_plic0_set_priority(struct __metal_driver_riscv_plic0 *plic, - int id, unsigned int priority) +unsigned int __metal_plic0_get_threshold(struct metal_interrupt *controller) { - unsigned long control_base = __metal_driver_sifive_plic0_control_base((struct metal_interrupt *)plic); - int max_priority = __metal_driver_sifive_plic0_max_priority((struct metal_interrupt *)plic); + 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 hartid = __metal_myhart_id(); unsigned long control_base = __metal_driver_sifive_plic0_control_base((struct metal_interrupt *)plic); current = __METAL_ACCESS_ONCE((__metal_io_u32 *)(control_base + @@ -69,7 +86,7 @@ void __metal_plic0_handler (int id, void *priv) { struct __metal_driver_riscv_plic0 *plic = priv; unsigned int idx = __metal_plic0_claim_interrupt(plic); - int num_interrupts = __metal_driver_sifive_plic0_num_interrupts((struct metal_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, @@ -97,13 +114,13 @@ void __metal_driver_riscv_plic0_init (struct metal_interrupt *controller) for (int i = 0; i < num_interrupts; i++) { __metal_plic0_enable(plic, i, METAL_DISABLE); - __metal_plic0_set_priority(plic, i, 0); + __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(plic, 0); + __metal_plic0_set_threshold(controller, 0); /* Register plic (ext) interrupt with with parent controller */ intc->vtable->interrupt_register(intc, line, NULL, plic); @@ -127,11 +144,11 @@ int __metal_driver_riscv_plic0_register (struct metal_interrupt *controller, } if (isr) { - __metal_plic0_set_priority(plic ,id, 2); + __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(plic, id, 1); + __metal_plic0_set_priority(controller, id, 1); plic->metal_exint_table[id] = __metal_plic0_default_handler; plic->metal_exdata_table[id].sub_int = priv; } @@ -167,6 +184,12 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_riscv_plic0) = { .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_FreedomStudio/freedom-metal/src/drivers/sifive_ccache0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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_FreedomStudio/freedom-metal/src/drivers/sifive_ccache0.c @@ -0,0 +1,84 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + +#ifdef METAL_SIFIVE_CCACHE0 + +#include +#include +#include +#include + +#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_FreedomStudio/freedom-metal/src/drivers/sifive_clic0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_clic0.c index 3f213847d..12c3dac06 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_clic0.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_clic0.c @@ -11,12 +11,6 @@ #include #include -typedef enum metal_priv_mode_ { - METAL_PRIV_M_MODE = 0, - METAL_PRIV_MU_MODE = 1, - METAL_PRIV_MSU_MODE = 2 -} metal_priv_mode; - typedef enum metal_clic_vector_{ METAL_CLIC_NONVECTOR = 0, METAL_CLIC_VECTORED = 1 @@ -30,17 +24,20 @@ struct __metal_clic_cfg { }; const struct __metal_clic_cfg __metal_clic_defaultcfg = { - .nmbits = METAL_PRIV_M_MODE, + .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; - uintptr_t hartid = __metal_myhart_id(); unsigned long control_base = __metal_driver_sifive_clic0_control_base((struct metal_interrupt *)clic); if ( cfg ) { @@ -80,7 +77,7 @@ int __metal_clic0_interrupt_set_mode (struct __metal_driver_sifive_clic0 *clic, return 0; } -int __metal_clic0_interrupt_set_level (struct __metal_driver_sifive_clic0 *clic, int id, int level) +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); @@ -102,7 +99,7 @@ int __metal_clic0_interrupt_set_level (struct __metal_driver_sifive_clic0 *clic, return 0; } -int __metal_clic0_interrupt_get_level (struct __metal_driver_sifive_clic0 *clic, int id) +unsigned int __metal_clic0_interrupt_get_level (struct __metal_driver_sifive_clic0 *clic, int id) { int level; uint8_t mask, val, freebits, nlbits; @@ -185,7 +182,7 @@ int __metal_clic0_interrupt_get_priority (struct __metal_driver_sifive_clic0 *cl return priority; } -int __metal_clic0_interrupt_set_vector (struct __metal_driver_sifive_clic0 *clic, int id, int enable) +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); @@ -272,36 +269,102 @@ int __metal_clic0_interrupt_is_pending (struct __metal_driver_sifive_clic0 *clic 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 >= METAL_INTERRUPT_ID_LC0) && (id < num_subinterrupts)) { + 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 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 >= METAL_INTERRUPT_ID_LC0) && (id < num_subinterrupts)) { + 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; } -void __metal_clic0_configure_privilege (struct __metal_driver_sifive_clic0 *clic, metal_priv_mode priv) +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; } -void __metal_clic0_configure_level (struct __metal_driver_sifive_clic0 *clic, int level) +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); - cfg.nlbits = level; + 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) @@ -338,16 +401,13 @@ int __metal_driver_sifive_clic0_mtimecmp_set(struct metal_interrupt *controller, return 0; } -void __metal_clic0_handler(int id, void *priv) __attribute__((aligned(64))); void __metal_clic0_handler (int id, void *priv) { - int idx; struct __metal_driver_sifive_clic0 *clic = priv; int num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts((struct metal_interrupt *)clic); - idx = id - METAL_INTERRUPT_ID_LC0; - if ( (idx < num_subinterrupts) && (clic->metal_mtvt_table[idx]) ) { - clic->metal_mtvt_table[idx](id, clic->metal_exint_table[idx].exint_data); + if ( (id < num_subinterrupts) && (clic->metal_exint_table[id].handler) ) { + clic->metal_exint_table[id].handler(id, clic->metal_exint_table[id].exint_data); } } @@ -355,6 +415,10 @@ 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 = @@ -368,8 +432,8 @@ void __metal_driver_sifive_clic0_init (struct metal_interrupt *controller) /* Initialize ist parent controller, aka cpu_intc. */ intc->vtable->interrupt_init(intc); - __metal_controller_interrupt_vector(METAL_SELECTIVE_VECTOR_MODE, - &__metal_clic0_handler); + __metal_controller_interrupt_vector(METAL_SELECTIVE_NONVECTOR_MODE, + &clic->metal_mtvt_table); /* * Register its interrupts with with parent controller, @@ -389,8 +453,10 @@ void __metal_driver_sifive_clic0_init (struct metal_interrupt *controller) level = (1 << cfg.nlbits) - 1; num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller); - for (int i = 0; i < num_subinterrupts; i++) { + 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); @@ -403,31 +469,71 @@ void __metal_driver_sifive_clic0_init (struct metal_interrupt *controller) 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_LC0) { + 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. + * Reset the IDs to reflects this. */ - id -= METAL_INTERRUPT_ID_LC0; 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_handler; + clic->metal_mtvt_table[id] = __metal_clic0_default_vector_handler; clic->metal_exint_table[id].sub_int = priv; } rc = 0; @@ -449,31 +555,20 @@ int __metal_driver_sifive_clic0_disable (struct metal_interrupt *controller, int return __metal_clic0_interrupt_disable(clic, id); } -int __metal_driver_sifive_clic0_enable_interrupt_vector(struct metal_interrupt *controller, - int id, metal_vector_mode mode) +int __metal_driver_sifive_clic0_enable_interrupt_vector(struct metal_interrupt *controller, int id) { - int num_subinterrupts; + 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 (id == METAL_INTERRUPT_ID_BASE) { - if (mode == METAL_SELECTIVE_VECTOR_MODE) { - __metal_controller_interrupt_vector(mode, &__metal_clic0_handler); - return 0; - } - if (mode == METAL_HARDWARE_VECTOR_MODE) { - __metal_controller_interrupt_vector(mode, &clic->metal_mtvt_table); - return 0; - } + if ((mode != METAL_SELECTIVE_VECTOR_MODE) && (mode != METAL_HARDWARE_VECTOR_MODE)) { + return rc; } - num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller); - if ((id >= METAL_INTERRUPT_ID_LC0) && (id < num_subinterrupts)) { - if ((mode == METAL_SELECTIVE_VECTOR_MODE) && - __metal_controller_interrupt_is_selective_vectored()) { - __metal_clic0_interrupt_set_vector(clic, id, METAL_ENABLE); - return 0; - } - + if (id < num_subinterrupts) { + __metal_clic0_interrupt_set_vector_mode(clic, id, METAL_ENABLE); + return 0; } return -1; } @@ -484,20 +579,84 @@ int __metal_driver_sifive_clic0_disable_interrupt_vector(struct metal_interrupt struct __metal_driver_sifive_clic0 *clic = (struct __metal_driver_sifive_clic0 *)(controller); - if (id == METAL_INTERRUPT_ID_BASE) { - __metal_controller_interrupt_vector(METAL_SELECTIVE_VECTOR_MODE, &__metal_clic0_handler); - return 0; - } num_subinterrupts = __metal_driver_sifive_clic0_num_subinterrupts(controller); - if ((id >= METAL_INTERRUPT_ID_LC0) && (id < num_subinterrupts)) { - if (__metal_controller_interrupt_is_selective_vectored()) { - __metal_clic0_interrupt_set_vector(clic, id, METAL_DISABLE); - return 0; - } + 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) { @@ -553,12 +712,25 @@ int __metal_driver_sifive_clic0_command_request (struct metal_interrupt *control __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_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfrosc.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfrosc.c index 14ce2fae6..61af8d314 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfrosc.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfrosc.c @@ -23,9 +23,9 @@ long __metal_driver_sifive_fe310_g000_hfrosc_get_rate_hz(const struct metal_cloc __metal_driver_sifive_fe310_g000_prci_vtable(); long cfg = vtable->get_reg(config_base, config_offset); - if (cfg & CONFIG_ENABLE == 0) + if ((cfg & CONFIG_ENABLE) == 0) return -1; - if (cfg & CONFIG_READY == 0) + if ((cfg & CONFIG_READY) == 0) return -1; return metal_clock_get_rate_hz(ref) / ((cfg & CONFIG_DIVIDER) + 1); } @@ -40,3 +40,5 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_hfrosc) = { .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_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfxosc.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfxosc.c index dbe467487..9ed7a0bf3 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfxosc.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_hfxosc.c @@ -21,9 +21,9 @@ long __metal_driver_sifive_fe310_g000_hfxosc_get_rate_hz(const struct metal_cloc __metal_driver_sifive_fe310_g000_prci_vtable(); long cfg = vtable->get_reg(config_base, config_offset); - if (cfg & CONFIG_ENABLE == 0) + if ((cfg & CONFIG_ENABLE) == 0) return -1; - if (cfg & CONFIG_READY == 0) + if ((cfg & CONFIG_READY) == 0) return -1; return metal_clock_get_rate_hz(ref); } @@ -39,3 +39,5 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_hfxosc) = { }; #endif /* METAL_SIFIVE_FE310_G000_HFXOSC */ + +typedef int no_empty_translation_units; diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_lfrosc.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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_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 + +#ifdef METAL_SIFIVE_FE310_G000_LFROSC + +#include +#include + +/* 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_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_pll.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_pll.c index c91328565..2ca468f43 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_pll.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_pll.c @@ -133,7 +133,7 @@ void __metal_driver_sifive_fe310_g000_pll_init(struct __metal_driver_sifive_fe31 * 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(long pll_input_rate, const struct pll_config_t *config) +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; @@ -162,8 +162,7 @@ void __metal_driver_sifive_fe310_g000_pll_init(struct __metal_driver_sifive_fe31 __metal_io_u32 *pllcfg = (__metal_io_u32 *) (base + config_offset); /* If the PLL clock has had a _pre_rate_change_callback configured, call it */ - if(pll->clock._pre_rate_change_callback != NULL) - pll->clock._pre_rate_change_callback(pll->clock._pre_rate_change_callback_priv); + _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) @@ -179,8 +178,7 @@ void __metal_driver_sifive_fe310_g000_pll_init(struct __metal_driver_sifive_fe31 pll->clock.vtable->set_rate_hz(&(pll->clock), init_rate); /* If the PLL clock has had a rate_change_callback configured, call it */ - if(pll->clock._post_rate_change_callback != NULL) - pll->clock._post_rate_change_callback(pll->clock._post_rate_change_callback_priv); + _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) @@ -358,3 +356,5 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_pll) = { }; #endif /* METAL_SIFIVE_FE310_G000_PLL */ + +typedef int no_empty_translation_units; diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_prci.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_prci.c index 4b402a27a..1236eca3b 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_prci.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fe310-g000_prci.c @@ -24,3 +24,5 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_prci) = { }; #endif /* METAL_SIFIVE_FE310_G000_PRCI */ + +typedef int no_empty_translation_units; diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fu540-c000_l2.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fu540-c000_l2.c index 5e66b6cda..aafc6e5e3 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fu540-c000_l2.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_fu540-c000_l2.c @@ -2,25 +2,32 @@ /* SPDX-License-Identifier: Apache-2.0 */ #include + +#ifdef METAL_SIFIVE_FU540_C000_L2 + +#include +#include #include +#include #define L2_CONFIG_WAYS_SHIFT 8 #define L2_CONFIG_WAYS_MASK (0xFF << L2_CONFIG_WAYS_SHIFT) -#ifdef CONFIG_SIFIVE_FU540_C000_L2 +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_driver_sifive_fu540_c000_l2 *l2 = __METAL_DT_SIFIVE_FU540_C000_L2_HANDLE; + struct metal_cache *l2 = __METAL_DT_SIFIVE_FU540_C000_L2_HANDLE; if(!l2) { return; } /* Get the number of available ways per bank */ - uint32_t ways = __METAL_ACCESS_ONCE((__metal_io_u32 *)(l2->control_base + SIFIVE_FU540_C000_L2_CONFIG)); + 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 */ @@ -35,12 +42,9 @@ void __metal_driver_sifive_fu540_c000_l2_init(struct metal_cache *l2, int ways) int __metal_driver_sifive_fu540_c000_l2_get_enabled_ways(struct metal_cache *cache) { - struct __metal_driver_sifive_fu540_c000_l2 *l2 = (struct __metal_driver_sifive_fu540_c000_l2 *) cache; - if(!l2) { - return -1; - } + unsigned long control_base = __metal_driver_sifive_fu540_c000_l2_control_base(cache); - uint32_t way_enable = __METAL_ACCESS_ONCE((__metal_io_u32 *)(l2->control_base + SIFIVE_FU540_C000_L2_WAYENABLE)); + 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; @@ -48,10 +52,7 @@ int __metal_driver_sifive_fu540_c000_l2_get_enabled_ways(struct metal_cache *cac int __metal_driver_sifive_fu540_c000_l2_set_enabled_ways(struct metal_cache *cache, int ways) { - struct __metal_driver_sifive_fu540_c000_l2 *l2 = (struct __metal_driver_sifive_fu540_c000_l2 *) cache; - if(!l2) { - return -1; - } + 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) { @@ -62,7 +63,7 @@ int __metal_driver_sifive_fu540_c000_l2_set_enabled_ways(struct metal_cache *cac uint32_t value = 0xFF & (ways - 1); /* Set the number of enabled ways */ - __METAL_ACCESS_ONCE((__metal_io_u32 *)(l2->control_base + SIFIVE_FU540_C000_L2_WAYENABLE)) = value; + __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) { @@ -79,3 +80,5 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_fu540_c000_l2) = { }; #endif + +typedef int no_empty_translation_units; diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_global-external-interrupts0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_global-external-interrupts0.c index 59f6fbe48..0d56bafef 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_global-external-interrupts0.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_global-external-interrupts0.c @@ -84,6 +84,50 @@ int __metal_driver_sifive_global_external_interrupt_disable(struct metal_interru 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) { @@ -113,8 +157,13 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_global_external_interrupts0) .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_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-buttons.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-buttons.c index fbb6c92a7..923fe2711 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-buttons.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-buttons.c @@ -53,3 +53,5 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_button) = { }; #endif + +typedef int no_empty_translation_units; diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-leds.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-leds.c index 68f72d5bd..a6b627458 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-leds.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-leds.c @@ -81,3 +81,5 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_led) = { }; #endif + +typedef int no_empty_translation_units; diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-switches.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-switches.c index b9302529d..fa0a819f1 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-switches.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio-switches.c @@ -52,3 +52,5 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_switch) = { }; #endif + +typedef int no_empty_translation_units; diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio0.c index 55ff458bf..9ebbea03c 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio0.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_gpio0.c @@ -9,6 +9,15 @@ #include #include +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); @@ -18,6 +27,13 @@ int __metal_driver_sifive_gpio0_disable_input(struct metal_gpio *ggpio, long sou 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); @@ -25,6 +41,16 @@ long __metal_driver_sifive_gpio0_output(struct metal_gpio *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); @@ -72,14 +98,124 @@ int __metal_driver_sifive_gpio0_enable_io(struct metal_gpio *ggpio, long source, 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.output = __metal_driver_sifive_gpio0_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_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_FreedomStudio/freedom-metal/src/drivers/sifive_local-external-interrupts0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_local-external-interrupts0.c index d205957ad..1c34ca447 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_local-external-interrupts0.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_local-external-interrupts0.c @@ -82,6 +82,33 @@ int __metal_driver_sifive_local_external_interrupt_disable(struct metal_interrup 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) { @@ -111,7 +138,14 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_local_external_interrupts0) = .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_FreedomStudio/freedom-metal/src/drivers/sifive_rtc0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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_FreedomStudio/freedom-metal/src/drivers/sifive_rtc0.c @@ -0,0 +1,121 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + +#ifdef METAL_SIFIVE_RTC0 + +#include +#include + +#include + +/* 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_FreedomStudio/freedom-metal/src/drivers/sifive_spi0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_spi0.c index fd9bc5e91..2a346354f 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_spi0.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_spi0.c @@ -7,6 +7,7 @@ #include #include #include +#include #include /* Register fields */ @@ -54,19 +55,25 @@ static int configure_spi(struct __metal_driver_sifive_spi0 *spi, struct metal_sp 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: + 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; - break; - case METAL_SPI_QUAD: + 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; - break; - default: - /* Unsupported value */ - return -1; + else + METAL_SPI_REGW(METAL_SIFIVE_SPI0_FMT) |= METAL_SPI_PROTO_SINGLE; + break; + default: + /* Unsupported value */ + return -1; } /* Set Polarity */ @@ -107,7 +114,7 @@ static int configure_spi(struct __metal_driver_sifive_spi0 *spi, struct metal_sp } /* Set CS line */ - METAL_SPI_REGW(METAL_SIFIVE_SPI0_CSID) = config->csid; + 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 @@ -121,6 +128,28 @@ static int configure_spi(struct __metal_driver_sifive_spi0 *spi, struct metal_sp 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, @@ -130,6 +159,7 @@ int __metal_driver_sifive_spi0_transfer(struct metal_spi *gspi, 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) { @@ -145,7 +175,97 @@ int __metal_driver_sifive_spi0_transfer(struct metal_spi *gspi, /* Declare time_t variables to break out of infinite while loop */ time_t endwait; - for(int i = 0; i < len; i++) { + 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 */ @@ -164,10 +284,10 @@ int __metal_driver_sifive_spi0_transfer(struct metal_spi *gspi, /* 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 = time(NULL) + METAL_SPI_RXDATA_TIMEOUT; + endwait = metal_time() + METAL_SPI_RXDATA_TIMEOUT; while ((rxdata = METAL_SPI_REGW(METAL_SIFIVE_SPI0_RXDATA)) & METAL_SPI_RXDATA_EMPTY) { - if (time(NULL) > endwait) { + if (metal_time() > endwait) { /* If timeout, deassert the CS */ METAL_SPI_REGW(METAL_SIFIVE_SPI0_CSMODE) &= ~(METAL_SPI_CSMODE_MASK); @@ -227,18 +347,19 @@ int __metal_driver_sifive_spi0_set_baud_rate(struct metal_spi *gspi, int baud_ra return 0; } -static void pre_rate_change_callback(void *priv) +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 zero and waiting until an interrupt is pending */ + * 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(void *priv) +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); @@ -251,8 +372,13 @@ void __metal_driver_sifive_spi0_init(struct metal_spi *gspi, int baud_rate) struct __metal_driver_sifive_gpio0 *pinmux = __metal_driver_sifive_spi0_pinmux(gspi); if(clock != NULL) { - metal_clock_register_pre_rate_change_callback(clock, &pre_rate_change_callback, spi); - metal_clock_register_post_rate_change_callback(clock, &post_rate_change_callback, spi); + 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); @@ -275,3 +401,5 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_spi0) = { .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_FreedomStudio/freedom-metal/src/drivers/sifive_test0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_test0.c index 4ef0aa861..79deebbf5 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_test0.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_test0.c @@ -5,15 +5,17 @@ #ifdef METAL_SIFIVE_TEST0 +#include + +#include + #include #include -#include -#include 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(); + 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; @@ -24,3 +26,5 @@ __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_FreedomStudio/freedom-metal/src/drivers/sifive_trace.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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_FreedomStudio/freedom-metal/src/drivers/sifive_trace.c @@ -0,0 +1,95 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + +#ifdef METAL_SIFIVE_TRACE + +#include +#include + +#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_FreedomStudio/freedom-metal/src/drivers/sifive_uart0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_uart0.c index 46971ec79..2e8098aa7 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_uart0.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_uart0.c @@ -38,27 +38,42 @@ 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_putc(struct metal_uart *uart, unsigned char c) + +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 ((UART_REGW(METAL_SIFIVE_UART0_TXDATA) & UART_TXFULL) != 0) { } + 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, unsigned char *c) + +int __metal_driver_sifive_uart0_getc(struct metal_uart *uart, int *c) { - uint32_t ch = UART_RXEMPTY; + uint32_t ch; long control_base = __metal_driver_sifive_uart0_control_base(uart); - - while (ch & UART_RXEMPTY) { - ch = UART_REGW(METAL_SIFIVE_UART0_RXDATA); + /* 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; } - *c = ch & 0xff; return 0; } + int __metal_driver_sifive_uart0_get_baud_rate(struct metal_uart *guart) { struct __metal_driver_sifive_uart0 *uart = (void *)guart; @@ -82,7 +97,7 @@ int __metal_driver_sifive_uart0_set_baud_rate(struct metal_uart *guart, int baud return 0; } -static void pre_rate_change_callback(void *priv) +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); @@ -105,10 +120,10 @@ static void pre_rate_change_callback(void *priv) long cycles_to_wait = bits_per_symbol * clk_freq / uart->baud_rate; for(volatile long x = 0; x < cycles_to_wait; x++) - asm("nop"); + __asm__("nop"); } -static void post_rate_change_callback(void *priv) +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); @@ -121,8 +136,13 @@ void __metal_driver_sifive_uart0_init(struct metal_uart *guart, int baud_rate) struct __metal_driver_sifive_gpio0 *pinmux = __metal_driver_sifive_uart0_pinmux(guart); if(clock != NULL) { - metal_clock_register_pre_rate_change_callback(clock, &pre_rate_change_callback, guart); - metal_clock_register_post_rate_change_callback(clock, &post_rate_change_callback, guart); + 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); @@ -149,3 +169,5 @@ __METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_uart0) = { }; #endif /* METAL_SIFIVE_UART0 */ + +typedef int no_empty_translation_units; diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/drivers/sifive_wdog0.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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_FreedomStudio/freedom-metal/src/drivers/sifive_wdog0.c @@ -0,0 +1,213 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + +#ifdef METAL_SIFIVE_WDOG0 + +#include +#include + +#include + +/* 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_FreedomStudio/freedom-metal/src/entry.S b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/entry.S index 460735532..97da3fd33 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/entry.S +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/entry.S @@ -8,7 +8,6 @@ * defined to have the first address being where execution should start. */ .section .text.metal.init.enter .global _enter - _enter: .cfi_startproc diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/gpio.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/gpio.c index 02a6582c9..504526eb3 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/gpio.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/gpio.c @@ -4,15 +4,23 @@ #include #include -extern inline int metal_gpio_disable_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_set_pin(struct metal_gpio *, int pin, int value); -extern inline int metal_gpio_get_pin(struct metal_gpio *, int pin); -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_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(int device_num) +struct metal_gpio *metal_gpio_get_device(unsigned int device_num) { if(device_num > __MEE_DT_MAX_GPIOS) { return NULL; diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/interrupt.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/interrupt.c index 1b3c6b8de..eeb88b26f 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/interrupt.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/interrupt.c @@ -1,24 +1,82 @@ /* Copyright 2018 SiFive, Inc */ /* SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -extern inline void metal_interrupt_init(struct metal_interrupt *controller); +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 int metal_interrupt_register_handler(struct metal_interrupt *controller, +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_enable(struct metal_interrupt *controller, int id); +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_disable(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, metal_vector_mode mode); +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_vector_disable(struct metal_interrupt *controller, int id); -extern inline int _metal_interrupt_command_request(struct metal_interrupt *controller, +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_FreedomStudio/freedom-metal/src/led.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/led.c index f28d22b81..91b74dbde 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/led.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/led.c @@ -32,7 +32,7 @@ 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); +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_FreedomStudio/freedom-metal/src/lock.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/lock.c index 0df162aa4..9e04230a3 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/lock.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/lock.c @@ -3,6 +3,6 @@ #include -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); +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_FreedomStudio/freedom-metal/src/memory.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/memory.c index 43ca6b810..05ab7ead2 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/memory.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/memory.c @@ -19,8 +19,8 @@ struct metal_memory *metal_get_memory_from_address(const uintptr_t address) { 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); +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_FreedomStudio/freedom-metal/src/pmp.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/pmp.c index ab78cdeba..5c2f68ada 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/pmp.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/pmp.c @@ -5,8 +5,8 @@ #include #include -#define CONFIG_TO_INT(_config) (*((size_t *) &(_config))) -#define INT_TO_CONFIG(_int) (*((struct metal_pmp_config *) &(_int))) +#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) { @@ -63,13 +63,18 @@ static uintptr_t _get_pmpaddr_granularity(uintptr_t address) { return (1 << (index + 3)); } -/* Get the number of pmp regions for the current hart */ -static int _pmp_regions() { - struct metal_cpu *current_cpu = metal_cpu_get(metal_cpu_get_current_hartid()); +/* 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(current_cpu); + 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) { @@ -151,67 +156,67 @@ int metal_pmp_set_region(struct metal_pmp *pmp, if(old_address != address) { switch(region) { case 0: - asm("csrw pmpaddr0, %[addr]" + __asm__("csrw pmpaddr0, %[addr]" :: [addr] "r" (address) :); break; case 1: - asm("csrw pmpaddr1, %[addr]" + __asm__("csrw pmpaddr1, %[addr]" :: [addr] "r" (address) :); break; case 2: - asm("csrw pmpaddr2, %[addr]" + __asm__("csrw pmpaddr2, %[addr]" :: [addr] "r" (address) :); break; case 3: - asm("csrw pmpaddr3, %[addr]" + __asm__("csrw pmpaddr3, %[addr]" :: [addr] "r" (address) :); break; case 4: - asm("csrw pmpaddr4, %[addr]" + __asm__("csrw pmpaddr4, %[addr]" :: [addr] "r" (address) :); break; case 5: - asm("csrw pmpaddr5, %[addr]" + __asm__("csrw pmpaddr5, %[addr]" :: [addr] "r" (address) :); break; case 6: - asm("csrw pmpaddr6, %[addr]" + __asm__("csrw pmpaddr6, %[addr]" :: [addr] "r" (address) :); break; case 7: - asm("csrw pmpaddr7, %[addr]" + __asm__("csrw pmpaddr7, %[addr]" :: [addr] "r" (address) :); break; case 8: - asm("csrw pmpaddr8, %[addr]" + __asm__("csrw pmpaddr8, %[addr]" :: [addr] "r" (address) :); break; case 9: - asm("csrw pmpaddr9, %[addr]" + __asm__("csrw pmpaddr9, %[addr]" :: [addr] "r" (address) :); break; case 10: - asm("csrw pmpaddr10, %[addr]" + __asm__("csrw pmpaddr10, %[addr]" :: [addr] "r" (address) :); break; case 11: - asm("csrw pmpaddr11, %[addr]" + __asm__("csrw pmpaddr11, %[addr]" :: [addr] "r" (address) :); break; case 12: - asm("csrw pmpaddr12, %[addr]" + __asm__("csrw pmpaddr12, %[addr]" :: [addr] "r" (address) :); break; case 13: - asm("csrw pmpaddr13, %[addr]" + __asm__("csrw pmpaddr13, %[addr]" :: [addr] "r" (address) :); break; case 14: - asm("csrw pmpaddr14, %[addr]" + __asm__("csrw pmpaddr14, %[addr]" :: [addr] "r" (address) :); break; case 15: - asm("csrw pmpaddr15, %[addr]" + __asm__("csrw pmpaddr15, %[addr]" :: [addr] "r" (address) :); break; } @@ -225,31 +230,31 @@ int metal_pmp_set_region(struct metal_pmp *pmp, switch(region / 4) { case 0: - asm("csrc pmpcfg0, %[mask]" + __asm__("csrc pmpcfg0, %[mask]" :: [mask] "r" (cfgmask) :); - asm("csrs pmpcfg0, %[cfg]" + __asm__("csrs pmpcfg0, %[cfg]" :: [cfg] "r" (pmpcfg) :); break; case 1: - asm("csrc pmpcfg1, %[mask]" + __asm__("csrc pmpcfg1, %[mask]" :: [mask] "r" (cfgmask) :); - asm("csrs pmpcfg1, %[cfg]" + __asm__("csrs pmpcfg1, %[cfg]" :: [cfg] "r" (pmpcfg) :); break; case 2: - asm("csrc pmpcfg2, %[mask]" + __asm__("csrc pmpcfg2, %[mask]" :: [mask] "r" (cfgmask) :); - asm("csrs pmpcfg2, %[cfg]" + __asm__("csrs pmpcfg2, %[cfg]" :: [cfg] "r" (pmpcfg) :); break; case 3: - asm("csrc pmpcfg3, %[mask]" + __asm__("csrc pmpcfg3, %[mask]" :: [mask] "r" (cfgmask) :); - asm("csrs pmpcfg3, %[cfg]" + __asm__("csrs pmpcfg3, %[cfg]" :: [cfg] "r" (pmpcfg) :); break; } @@ -262,17 +267,17 @@ int metal_pmp_set_region(struct metal_pmp *pmp, switch(region / 8) { case 0: - asm("csrc pmpcfg0, %[mask]" + __asm__("csrc pmpcfg0, %[mask]" :: [mask] "r" (cfgmask) :); - asm("csrs pmpcfg0, %[cfg]" + __asm__("csrs pmpcfg0, %[cfg]" :: [cfg] "r" (pmpcfg) :); break; case 1: - asm("csrc pmpcfg2, %[mask]" + __asm__("csrc pmpcfg2, %[mask]" :: [mask] "r" (cfgmask) :); - asm("csrs pmpcfg2, %[cfg]" + __asm__("csrs pmpcfg2, %[cfg]" :: [cfg] "r" (pmpcfg) :); break; } @@ -290,6 +295,7 @@ int metal_pmp_get_region(struct metal_pmp *pmp, size_t *address) { size_t pmpcfg = 0; + char *pmpcfg_convert = (char *)&pmpcfg; if(!pmp || !config || !address) { /* NULL pointers are invalid arguments */ @@ -304,19 +310,19 @@ int metal_pmp_get_region(struct metal_pmp *pmp, #if __riscv_xlen==32 switch(region / 4) { case 0: - asm("csrr %[cfg], pmpcfg0" + __asm__("csrr %[cfg], pmpcfg0" : [cfg] "=r" (pmpcfg) ::); break; case 1: - asm("csrr %[cfg], pmpcfg1" + __asm__("csrr %[cfg], pmpcfg1" : [cfg] "=r" (pmpcfg) ::); break; case 2: - asm("csrr %[cfg], pmpcfg2" + __asm__("csrr %[cfg], pmpcfg2" : [cfg] "=r" (pmpcfg) ::); break; case 3: - asm("csrr %[cfg], pmpcfg3" + __asm__("csrr %[cfg], pmpcfg3" : [cfg] "=r" (pmpcfg) ::); break; } @@ -326,11 +332,11 @@ int metal_pmp_get_region(struct metal_pmp *pmp, #elif __riscv_xlen==64 switch(region / 8) { case 0: - asm("csrr %[cfg], pmpcfg0" + __asm__("csrr %[cfg], pmpcfg0" : [cfg] "=r" (pmpcfg) ::); break; case 1: - asm("csrr %[cfg], pmpcfg2" + __asm__("csrr %[cfg], pmpcfg2" : [cfg] "=r" (pmpcfg) ::); break; } @@ -341,71 +347,71 @@ int metal_pmp_get_region(struct metal_pmp *pmp, #error XLEN is not set to supported value for PMP driver #endif - *config = INT_TO_CONFIG(pmpcfg); + *config = INT_TO_CONFIG(*pmpcfg_convert); switch(region) { case 0: - asm("csrr %[addr], pmpaddr0" + __asm__("csrr %[addr], pmpaddr0" : [addr] "=r" (*address) ::); break; case 1: - asm("csrr %[addr], pmpaddr1" + __asm__("csrr %[addr], pmpaddr1" : [addr] "=r" (*address) ::); break; case 2: - asm("csrr %[addr], pmpaddr2" + __asm__("csrr %[addr], pmpaddr2" : [addr] "=r" (*address) ::); break; case 3: - asm("csrr %[addr], pmpaddr3" + __asm__("csrr %[addr], pmpaddr3" : [addr] "=r" (*address) ::); break; case 4: - asm("csrr %[addr], pmpaddr4" + __asm__("csrr %[addr], pmpaddr4" : [addr] "=r" (*address) ::); break; case 5: - asm("csrr %[addr], pmpaddr5" + __asm__("csrr %[addr], pmpaddr5" : [addr] "=r" (*address) ::); break; case 6: - asm("csrr %[addr], pmpaddr6" + __asm__("csrr %[addr], pmpaddr6" : [addr] "=r" (*address) ::); break; case 7: - asm("csrr %[addr], pmpaddr7" + __asm__("csrr %[addr], pmpaddr7" : [addr] "=r" (*address) ::); break; case 8: - asm("csrr %[addr], pmpaddr8" + __asm__("csrr %[addr], pmpaddr8" : [addr] "=r" (*address) ::); break; case 9: - asm("csrr %[addr], pmpaddr9" + __asm__("csrr %[addr], pmpaddr9" : [addr] "=r" (*address) ::); break; case 10: - asm("csrr %[addr], pmpaddr10" + __asm__("csrr %[addr], pmpaddr10" : [addr] "=r" (*address) ::); break; case 11: - asm("csrr %[addr], pmpaddr11" + __asm__("csrr %[addr], pmpaddr11" : [addr] "=r" (*address) ::); break; case 12: - asm("csrr %[addr], pmpaddr12" + __asm__("csrr %[addr], pmpaddr12" : [addr] "=r" (*address) ::); break; case 13: - asm("csrr %[addr], pmpaddr13" + __asm__("csrr %[addr], pmpaddr13" : [addr] "=r" (*address) ::); break; case 14: - asm("csrr %[addr], pmpaddr14" + __asm__("csrr %[addr], pmpaddr14" : [addr] "=r" (*address) ::); break; case 15: - asm("csrr %[addr], pmpaddr15" + __asm__("csrr %[addr], pmpaddr15" : [addr] "=r" (*address) ::); break; } diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/privilege.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/privilege.c index 42bdf6e0d..54bfcfc2c 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/privilege.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/privilege.c @@ -20,7 +20,7 @@ void metal_privilege_drop_to_mode(enum metal_privilege_mode mode, metal_privilege_entry_point_t entry_point) { uintptr_t mstatus; - asm volatile("csrr %0, mstatus" : "=r" (mstatus)); + __asm__ volatile("csrr %0, mstatus" : "=r" (mstatus)); /* Set xPIE bits based on current xIE bits */ if(mstatus && (1 << METAL_MSTATUS_MIE_OFFSET)) { @@ -43,15 +43,15 @@ void metal_privilege_drop_to_mode(enum metal_privilege_mode mode, mstatus &= ~(METAL_MSTATUS_MPP_MASK << METAL_MSTATUS_MPP_OFFSET); mstatus |= (mode << METAL_MSTATUS_MPP_OFFSET); - asm volatile("csrw mstatus, %0" :: "r" (mstatus)); + __asm__ volatile("csrw mstatus, %0" :: "r" (mstatus)); /* Set the entry point in MEPC */ - asm volatile("csrw mepc, %0" :: "r" (entry_point)); + __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("mv ra, %0" :: "r" (regfile.ra)); + __asm__ volatile("mv sp, %0" :: "r" (regfile.sp)); - asm volatile("mret"); + __asm__ volatile("mret"); } diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/rtc.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/rtc.c new file mode 100644 index 000000000..8b79892df --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/rtc.c @@ -0,0 +1,27 @@ +/* Copyright 2019 SiFive, Inc. */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include + +#include + +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_FreedomStudio/freedom-metal/src/shutdown.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/shutdown.c index 0e530b605..c3b5255a7 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/shutdown.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/shutdown.c @@ -4,7 +4,7 @@ #include #include -extern inline void __metal_shutdown_exit(const struct __metal_shutdown *sd, int code); +extern __inline__ void __metal_shutdown_exit(const struct __metal_shutdown *sd, int code); #if defined(__METAL_DT_SHUTDOWN_HANDLE) void metal_shutdown(int code) @@ -12,7 +12,7 @@ void metal_shutdown(int code) __metal_shutdown_exit(__METAL_DT_SHUTDOWN_HANDLE, code); } #else -# warning "There is no defined shutdown mechanism, metal_shutdown() will spin." +#pragma message("There is no defined shutdown mechanism, metal_shutdown() will spin.") void metal_shutdown(int code) { while (1) { diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/spi.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/spi.c index d344e095f..de8cda737 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/spi.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/spi.c @@ -4,16 +4,18 @@ #include #include -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); +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(int device_num) +struct metal_spi *metal_spi_get_device(unsigned int device_num) { - if(device_num >= __METAL_DT_MAX_SPIS) { - return NULL; +#if __METAL_DT_MAX_SPIS > 0 + if (device_num < __METAL_DT_MAX_SPIS) { + return (struct metal_spi *) __metal_spi_table[device_num]; } +#endif - return (struct metal_spi *) __metal_spi_table[device_num]; + return NULL; } diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/switch.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/switch.c index f101537ac..4f17229c7 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/switch.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/switch.c @@ -22,6 +22,6 @@ struct metal_switch* metal_switch_get (char *label) return NULL; } -extern inline struct metal_interrupt* +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); +extern __inline__ int metal_switch_get_interrupt_id(struct metal_switch *flip); diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/synchronize_harts.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/synchronize_harts.c new file mode 100644 index 000000000..a5338e942 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/synchronize_harts.c @@ -0,0 +1,62 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include +#include +#include + +#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_FreedomStudio/freedom-metal/src/time.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/time.c new file mode 100644 index 000000000..529f8bd56 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/time.c @@ -0,0 +1,30 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include +#include + +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_FreedomStudio/freedom-metal/src/timer.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/timer.c index 243b5cff0..f58413321 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/timer.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/timer.c @@ -65,15 +65,15 @@ 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"))) { -#warning "There is no default timer device, metal_timer_get_cyclecount() will always return cyclecount -1." +#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"))) { -#warning "There is no default timer device, metal_timer_get_timebase_frequency() will always return timebase -1." +#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"))) { -#warning "There is no default timer device, metal_timer_set_tick) will always return -1." +#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_FreedomStudio/freedom-metal/src/tty.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/tty.c index c47cc44fd..306192451 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/tty.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/tty.c @@ -2,21 +2,35 @@ /* SPDX-License-Identifier: Apache-2.0 */ #include +#include #include #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(unsigned char c) +int metal_tty_putc(int c) { if (c == '\n') { - int out = metal_uart_putc(__METAL_DT_STDOUT_UART_HANDLE, '\r'); - if (out != 0) - return out; + 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 @@ -30,8 +44,8 @@ static void metal_tty_init(void) /* 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(unsigned char c) __attribute__((section(".text.metal.nop.putc"))); -int nop_putc(unsigned char c) { return -1; } -int metal_tty_putc(unsigned char c) __attribute__((weak, alias("nop_putc"))); -#warning "There is no default output device, metal_tty_putc() will throw away all input." +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_FreedomStudio/freedom-metal/src/uart.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/uart.c index daab33ab0..8981eb8d3 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/uart.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/uart.c @@ -3,8 +3,9 @@ #include -extern inline void metal_uart_init(struct metal_uart *uart, int baud_rate); -extern inline int metal_uart_putc(struct metal_uart *uart, unsigned char c); -extern inline int metal_uart_getc(struct metal_uart *uart, unsigned char *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); +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_FreedomStudio/freedom-metal/src/vector.S b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/src/vector.S new file mode 100644 index 000000000..1da52d2df --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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_FreedomStudio/main.c b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/main.c index 267ac2841..de03b623b 100644 --- a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/main.c +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/main.c @@ -58,7 +58,7 @@ /* 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 1 +#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 0 /* Index to first HART (there is only one). */ #define mainHART_0 0 @@ -265,6 +265,9 @@ void *malloc( size_t xSize ) 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; } /*-----------------------------------------------------------*/ -- 2.39.2