summaryrefslogtreecommitdiff
path: root/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal')
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/button.h4
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/cache.h46
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/clock.h83
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/cpu.h42
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/riscv_cpu.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_ccache0.h23
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_clic0.h3
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_lfrosc.h21
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_prci.h1
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_fu540-c000_l2.h8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_rtc0.h27
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_spi0.h2
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_trace.h23
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_uart0.h2
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/drivers/sifive_wdog0.h26
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/gpio.h149
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/interrupt.h357
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/io.h2
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/led.h8
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/lock.h27
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/memory.h18
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/pmp.h11
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/privilege.h4
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/rtc.h127
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/shutdown.h4
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/spi.h22
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/switch.h4
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/time.h18
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/tty.h33
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/uart.h32
-rw-r--r--FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1_FreedomStudio/freedom-metal/metal/watchdog.h163
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 */