diff options
Diffstat (limited to 'FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal')
31 files changed, 1172 insertions, 139 deletions
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 <stdint.h> 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 <metal/cache.h> +#include <metal/compiler.h> + +struct __metal_driver_vtable_sifive_ccache0 { + struct __metal_cache_vtable cache; +}; + +struct __metal_driver_sifive_ccache0; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_ccache0) + +struct __metal_driver_sifive_ccache0 { + struct metal_cache cache; +}; + +#endif + diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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 <metal/compiler.h> +#include <metal/clock.h> +#include <metal/io.h> + +struct __metal_driver_vtable_sifive_fe310_g000_lfrosc { + struct __metal_clock_vtable clock; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_lfrosc) + +struct __metal_driver_sifive_fe310_g000_lfrosc { + struct metal_clock clock; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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 <stdint.h> #include <metal/cache.h> +#include <metal/compiler.h> 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 <metal/io.h> +#include <metal/compiler.h> + +#include <metal/clock.h> +#include <metal/interrupt.h> +#include <metal/rtc.h> + +struct __metal_driver_vtable_sifive_rtc0 { + const struct metal_rtc_vtable rtc; +}; + +struct __metal_driver_sifive_rtc0; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_rtc0) + +struct __metal_driver_sifive_rtc0 { + const struct metal_rtc rtc; +}; + +#endif + diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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 <metal/compiler.h> +#include <metal/io.h> +#include <metal/uart.h> + +struct __metal_driver_vtable_sifive_trace { + const struct metal_uart_vtable uart; +}; + +struct __metal_driver_sifive_trace; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_trace) + +struct __metal_driver_sifive_trace { + struct metal_uart uart; +}; + +#endif /* METAL__DRIVERS__SIFIVE_TRACE_H */ diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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 <metal/io.h> +#include <metal/compiler.h> + +#include <metal/watchdog.h> +#include <metal/clock.h> +#include <metal/interrupt.h> + +struct __metal_driver_vtable_sifive_wdog0 { + const struct metal_watchdog_vtable watchdog; +}; + +struct __metal_driver_sifive_wdog0; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_wdog0) + +struct __metal_driver_sifive_wdog0 { + const struct metal_watchdog watchdog; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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 <metal/compiler.h> +#include <metal/interrupt.h> /*! * @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; } @@ -67,13 +99,27 @@ inline int metal_gpio_enable_output(struct metal_gpio *gpio, int pin) { } /*! + * @brief Disable output on a pin + * @param gpio The handle for the GPIO interface + * @param pin The pin number indexed from 0 + * @return 0 if the output is successfully disabled + */ +__inline__ int metal_gpio_disable_output(struct metal_gpio *gpio, int pin) { + if(!gpio) { + return 1; + } + + return gpio->vtable->disable_output(gpio, (1 << pin)); +} + +/*! * @brief Set the output value of a GPIO pin * @param gpio The handle for the GPIO interface * @param pin The pin number indexed from 0 * @param value The value to set the pin to * @return 0 if the output is successfully set */ -inline int metal_gpio_set_pin(struct metal_gpio *gpio, int pin, int value) { +__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 @@ -11,31 +11,63 @@ #include <stddef.h> /*! + * @brief Possible interrupt controllers + */ +typedef enum metal_interrupt_controller_ { + METAL_CPU_CONTROLLER = 0, + METAL_CLINT_CONTROLLER = 1, + METAL_CLIC_CONTROLLER = 2, + METAL_PLIC_CONTROLLER = 3 +} metal_intr_cntrl_type; + +/*! * @brief Possible mode of interrupts to operate */ typedef enum metal_vector_mode_ { METAL_DIRECT_MODE = 0, METAL_VECTOR_MODE = 1, - METAL_SELECTIVE_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) @@ -79,12 +207,28 @@ inline int metal_interrupt_register_handler(struct metal_interrupt *controller, } /*! + * @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 <metal/machine.h> #include <metal/memory.h> #include <metal/compiler.h> @@ -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; @@ -74,6 +74,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 <stdint.h> + +/*! + * @file rtc.h + * @brief API for Real-Time Clocks + */ + +struct metal_rtc; + +/*! + * @brief List of RTC run behaviors + */ +enum metal_rtc_run_option { + METAL_RTC_STOP = 0, + METAL_RTC_RUN, +}; + +struct metal_rtc_vtable { + uint64_t (*get_rate)(const struct metal_rtc *const rtc); + uint64_t (*set_rate)(const struct metal_rtc *const rtc, const uint64_t rate); + uint64_t (*get_compare)(const struct metal_rtc *const rtc); + uint64_t (*set_compare)(const struct metal_rtc *const rtc, const uint64_t compare); + uint64_t (*get_count)(const struct metal_rtc *const rtc); + uint64_t (*set_count)(const struct metal_rtc *const rtc, const uint64_t count); + int (*run)(const struct metal_rtc *const rtc, const enum metal_rtc_run_option option); + struct metal_interrupt *(*get_interrupt)(const struct metal_rtc *const rtc); + int (*get_interrupt_id)(const struct metal_rtc *const rtc); +}; + +/*! + * @brief Handle for a Real-Time Clock + */ +struct metal_rtc { + const struct metal_rtc_vtable *vtable; +}; + +/*! + * @brief Get the rate of the RTC + * @return The rate in Hz + */ +inline uint64_t metal_rtc_get_rate(const struct metal_rtc *const rtc) { + return rtc->vtable->get_rate(rtc); +} + +/*! + * @brief Set (if possible) the rate of the RTC + * @return The new rate of the RTC (not guaranteed to be the same as requested) + */ +inline uint64_t metal_rtc_set_rate(const struct metal_rtc *const rtc, const uint64_t rate) { + return rtc->vtable->set_rate(rtc, rate); +} + +/*! + * @brief Get the compare value of the RTC + * @return The compare value + */ +inline uint64_t metal_rtc_get_compare(const struct metal_rtc *const rtc) { + return rtc->vtable->get_compare(rtc); +} + +/*! + * @brief Set the compare value of the RTC + * @return The set compare value (not guaranteed to be exactly the requested value) + * + * The RTC device might impose limits on the maximum compare value or the granularity + * of the compare value. + */ +inline uint64_t metal_rtc_set_compare(const struct metal_rtc *const rtc, const uint64_t compare) { + return rtc->vtable->set_compare(rtc, compare); +} + +/*! + * @brief Get the current count of the RTC + * @return The count + */ +inline uint64_t metal_rtc_get_count(const struct metal_rtc *const rtc) { + return rtc->vtable->get_count(rtc); +} + +/*! + * @brief Set the current count of the RTC + * @return The set value of the count (not guaranteed to be exactly the requested value) + * + * The RTC device might impose limits on the maximum value of the count + */ +inline uint64_t metal_rtc_set_count(const struct metal_rtc *const rtc, const uint64_t count) { + return rtc->vtable->set_count(rtc, count); +} + +/*! + * @brief Start or stop the RTC + * @return 0 if the RTC was successfully started/stopped + */ +inline int metal_rtc_run(const struct metal_rtc *const rtc, const enum metal_rtc_run_option option) { + return rtc->vtable->run(rtc, option); +} + +/*! + * @brief Get the interrupt handle for the RTC compare + * @return The interrupt handle + */ +inline struct metal_interrupt *metal_rtc_get_interrupt(const struct metal_rtc *const rtc) { + return rtc->vtable->get_interrupt(rtc); +} + +/*! + * @brief Get the interrupt ID for the RTC compare + * @return The interrupt ID + */ +inline int metal_rtc_get_interrupt_id(const struct metal_rtc *const rtc) { + return rtc->vtable->get_interrupt_id(rtc); +} + +/*! + * @brief Get the handle for an RTC by index + * @return The RTC handle, or NULL if none is available at that index + */ +struct metal_rtc *metal_rtc_get_device(int index); + +#endif + diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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 <time.h> + +/*! + * @file time.h + * @brief API for dealing with time + */ + +int metal_gettimeofday(struct timeval *tp, void *tzp); + +time_t metal_time(void); + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_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 <metal/interrupt.h> struct metal_uart; - +#undef getc +#undef putc struct metal_uart_vtable { void (*init)(struct metal_uart *uart, int baud_rate); - int (*putc)(struct metal_uart *uart, 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 <metal/interrupt.h> + +struct metal_watchdog; + +/*! + * @brief List of watchdog timer count behaviors + */ +enum metal_watchdog_run_option { + METAL_WATCHDOG_STOP = 0, /*!< Stop the watchdog */ + METAL_WATCHDOG_RUN_ALWAYS, /*!< Run the watchdog continuously, even during sleep */ + METAL_WATCHDOG_RUN_AWAKE, /*!< Run the watchdog only while the CPU is awake */ +}; + +/*! + * @brief List of behaviors when a watchdog triggers + */ +enum metal_watchdog_result { + METAL_WATCHDOG_NO_RESULT = 0, /*!< When the watchdog triggers, do nothing */ + METAL_WATCHDOG_INTERRUPT, /*!< When the watchdog triggers, fire an interrupt */ + METAL_WATCHDOG_FULL_RESET, /*!< When the watchdog triggers, cause a full system reset */ +}; + + +struct metal_watchdog_vtable { + int (*feed)(const struct metal_watchdog *const wdog); + long int (*get_rate)(const struct metal_watchdog *const wdog); + long int (*set_rate)(const struct metal_watchdog *const wdog, const long int rate); + long int (*get_timeout)(const struct metal_watchdog *const wdog); + long int (*set_timeout)(const struct metal_watchdog *const wdog, const long int timeout); + int (*set_result)(const struct metal_watchdog *const wdog, + const enum metal_watchdog_result result); + int (*run)(const struct metal_watchdog *const wdog, + const enum metal_watchdog_run_option option); + struct metal_interrupt *(*get_interrupt)(const struct metal_watchdog *const wdog); + int (*get_interrupt_id)(const struct metal_watchdog *const wdog); + int (*clear_interrupt)(const struct metal_watchdog *const wdog); +}; + +/*! + * @brief Handle for a Watchdog Timer + */ +struct metal_watchdog { + const struct metal_watchdog_vtable *vtable; +}; + +/*! + * @brief Feed the watchdog timer + */ +inline int metal_watchdog_feed(const struct metal_watchdog *const wdog) +{ + return wdog->vtable->feed(wdog); +} + +/*! + * @brief Get the rate of the watchdog timer in Hz + * + * @return the rate of the watchdog timer + */ +inline long int metal_watchdog_get_rate(const struct metal_watchdog *const wdog) +{ + return wdog->vtable->get_rate(wdog); +} + +/*! + * @brief Set the rate of the watchdog timer in Hz + * + * There is no guarantee that the new rate will match the requested rate. + * + * @return the new rate of the watchdog timer + */ +inline long int metal_watchdog_set_rate(const struct metal_watchdog *const wdog, const long int rate) +{ + return wdog->vtable->set_rate(wdog, rate); +} + +/*! + * @brief Get the timeout of the watchdog timer + * + * @return the watchdog timeout value + */ +inline long int metal_watchdog_get_timeout(const struct metal_watchdog *const wdog) +{ + return wdog->vtable->get_timeout(wdog); +} + +/*! + * @brief Set the timeout of the watchdog timer + * + * The set rate will be the minimimum of the requested and maximum supported rates. + * + * @return the new watchdog timeout value + */ +inline long int metal_watchdog_set_timeout(const struct metal_watchdog *const wdog, const long int timeout) +{ + return wdog->vtable->set_timeout(wdog, timeout); +} + +/*! + * @brief Sets the result behavior of a watchdog timer timeout + * + * @return 0 if the requested result behavior is supported + */ +inline int metal_watchdog_set_result(const struct metal_watchdog *const wdog, + const enum metal_watchdog_result result) +{ + return wdog->vtable->set_result(wdog, result); +} + +/*! + * @brief Set the run behavior of the watchdog + * + * Used to enable/disable the watchdog timer + * + * @return 0 if the watchdog was successfully started/stopped + */ +inline int metal_watchdog_run(const struct metal_watchdog *const wdog, + const enum metal_watchdog_run_option option) +{ + return wdog->vtable->run(wdog, option); +} + +/*! + * @brief Get the interrupt controller for the watchdog interrupt + */ +inline struct metal_interrupt *metal_watchdog_get_interrupt(const struct metal_watchdog *const wdog) +{ + return wdog->vtable->get_interrupt(wdog); +} + +/*! + * @Brief Get the interrupt id for the watchdog interrupt + */ +inline int metal_watchdog_get_interrupt_id(const struct metal_watchdog *const wdog) +{ + return wdog->vtable->get_interrupt_id(wdog); +} + +/*! + * @brief Clear the watchdog interrupt + */ +inline int metal_watchdog_clear_interrupt(const struct metal_watchdog *const wdog) +{ + return wdog->vtable->clear_interrupt(wdog); +} + +/*! + * @brief Get a watchdog handle + */ +struct metal_watchdog *metal_watchdog_get_device(const int index); + +#endif /* METAL__WATCHDOG_H */ |