diff options
Diffstat (limited to 'FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal')
48 files changed, 3469 insertions, 0 deletions
diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/button.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/button.h new file mode 100644 index 000000000..3ae1c143e --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/button.h @@ -0,0 +1,59 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__BUTTON_H +#define METAL__BUTTON_H + +/*! + * @file button.h + * API for interfacing with physical buttons + */ + +#include <metal/interrupt.h> + +struct metal_button; + +struct metal_button_vtable { + int (*button_exist)(struct metal_button *button, char *label); + struct metal_interrupt* (*interrupt_controller)(struct metal_button *button); + int (*get_interrupt_id)(struct metal_button *button); +}; + +/*! + * @brief A button device handle + * + * A `struct metal_button` is an implementation-defined object which represents + * a button on a development board. + */ +struct metal_button { + const struct metal_button_vtable *vtable; +}; + +/*! + * @brief Get a reference to a button + * + * @param label The DeviceTree label for the button + * @return A handle for the button + */ +struct metal_button* metal_button_get(char *label); + + +/*! + * @brief Get the interrupt controller for a button + * + * @param button The handle for the button + * @return A pointer to the interrupt controller responsible for handling + * button interrupts. + */ +__inline__ struct metal_interrupt* + metal_button_interrupt_controller(struct metal_button *button) { return button->vtable->interrupt_controller(button); } + +/*! + * @brief Get the interrupt id for a button + * + * @param button The handle for the button + * @return The interrupt id corresponding to a button. + */ +__inline__ int metal_button_get_interrupt_id(struct metal_button *button) { return button->vtable->get_interrupt_id(button); } + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/cache.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/cache.h new file mode 100644 index 000000000..bad026480 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/cache.h @@ -0,0 +1,96 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__CACHE_H +#define METAL__CACHE_H + +/*! + * @file cache.h + * + * @brief API for configuring caches + */ +#include <stdint.h> + +struct metal_cache; + +struct __metal_cache_vtable { + void (*init)(struct metal_cache *cache, int ways); + int (*get_enabled_ways)(struct metal_cache *cache); + int (*set_enabled_ways)(struct metal_cache *cache, int ways); +}; + +/*! + * @brief a handle for a cache + */ +struct metal_cache { + const struct __metal_cache_vtable *vtable; +}; + +/*! + * @brief Initialize a cache + * @param cache The handle for the cache to initialize + * @param ways The number of ways to enable + * + * Initializes a cache with the requested number of ways enabled. + */ +__inline__ void metal_cache_init(struct metal_cache *cache, int ways) { + cache->vtable->init(cache, ways); +} + +/*! + * @brief Get the current number of enabled cache ways + * @param cache The handle for the cache + * @return The current number of enabled cache ways + */ +__inline__ int metal_cache_get_enabled_ways(struct metal_cache *cache) { + return cache->vtable->get_enabled_ways(cache); +} + +/*! + * @brief Enable the requested number of cache ways + * @param cache The handle for the cache + * @param ways The number of ways to enabled + * @return 0 if the ways are successfully enabled + */ +__inline__ int metal_cache_set_enabled_ways(struct metal_cache *cache, int ways) { + return cache->vtable->set_enabled_ways(cache, ways); +} + +/*! + * @brief Check if dcache is supported on the core + * @param hartid The core to check + * @return 1 if dcache is present + */ +int metal_dcache_l1_available(int hartid); + +/*! + * @brief Flush dcache for L1 on the requested core with write back + * @param hartid The core to flush + * @param address The virtual address of cacheline to invalidate + * @return None + */ +void metal_dcache_l1_flush(int hartid, uintptr_t address); + +/*! + * @brief Discard dcache for L1 on the requested core with no write back + * @param hartid The core to discard + * @param address The virtual address of cacheline to invalidate + * @return None + */ +void metal_dcache_l1_discard(int hartid, uintptr_t address); + +/*! + * @brief Check if icache is supported on the core + * @param hartid The core to check + * @return 1 if icache is present + */ +int metal_icache_l1_available(int hartid); + +/*! + * @brief Flush icache for L1 on the requested core + * @param hartid The core to flush + * @return None + */ +void metal_icache_l1_flush(int hartid); + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/clock.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/clock.h new file mode 100644 index 000000000..622fc9470 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/clock.h @@ -0,0 +1,154 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__CLOCK_H +#define METAL__CLOCK_H + +/*! + * @file clock.h + * @brief API for manipulating clock sources + * + * The clock interface allows for controlling the rate of various clocks in the system. + */ + +struct metal_clock; + +#include <stddef.h> + +/* The generic interface to all clocks. */ +struct __metal_clock_vtable { + long (*get_rate_hz)(const struct metal_clock *clk); + long (*set_rate_hz)(struct metal_clock *clk, long hz); +}; + +/*! + * @brief Function signature of clock rate change callbacks + */ +typedef void (*metal_clock_rate_change_callback)(void *priv); + +struct _metal_clock_callback_t; +struct _metal_clock_callback_t { + /* The callback function */ + metal_clock_rate_change_callback callback; + + /* Private data for the callback function */ + void *priv; + + struct _metal_clock_callback_t *_next; +}; + +/*! + * @brief Type for the linked list of callbacks for clock rate changes + */ +typedef struct _metal_clock_callback_t metal_clock_callback; + +/*! + * @brief Call all callbacks in the linked list, if any are registered + */ +__inline__ void _metal_clock_call_all_callbacks(const metal_clock_callback *const list) { + const metal_clock_callback *current = list; + while (current) { + current->callback(current->priv); + current = current->_next; + } +} + +/*! + * @brief Append a callback to the linked list and return the head of the list + */ +__inline__ metal_clock_callback *_metal_clock_append_to_callbacks(metal_clock_callback *list, metal_clock_callback *const cb) { + cb->_next = NULL; + + if (!list) { + return cb; + } + + metal_clock_callback *current = list; + + while ((current->_next) != NULL) { + current = current->_next; + } + + current->_next = cb; + + return list; +} + +/*! + * @struct metal_clock + * @brief The handle for a clock + * + * Clocks are defined as a pointer to a `struct metal_clock`, the contents of which + * are implementation defined. Users of the clock interface must call functions + * which accept a `struct metal_clock *` as an argument to interract with the clock. + * + * Note that no mechanism for obtaining a pointer to a `struct metal_clock` has been + * defined, making it impossible to call any of these functions without invoking + * implementation-defined behavior. + */ +struct metal_clock { + const struct __metal_clock_vtable *vtable; + + /* Pre-rate change callback linked list */ + metal_clock_callback *_pre_rate_change_callback; + + /* Post-rate change callback linked list */ + metal_clock_callback *_post_rate_change_callback; +}; + +/*! + * @brief Returns the current rate of the given clock + * + * @param clk The handle for the clock + * @return The current rate of the clock in Hz + */ +__inline__ long metal_clock_get_rate_hz(const struct metal_clock *clk) { return clk->vtable->get_rate_hz(clk); } + +/*! + * @brief Set the current rate of a clock + * + * @param clk The handle for the clock + * @param hz The desired rate in Hz + * @return The new rate of the clock in Hz. + * + * Attempts to set the current rate of the given clock to as close as possible + * to the given rate in Hz. Returns the actual value that's been selected, which + * could be anything! + * + * Prior to and after the rate change of the clock, this will call the registered + * pre- and post-rate change callbacks. + */ +__inline__ long metal_clock_set_rate_hz(struct metal_clock *clk, long hz) +{ + _metal_clock_call_all_callbacks(clk->_pre_rate_change_callback); + + long out = clk->vtable->set_rate_hz(clk, hz); + + _metal_clock_call_all_callbacks(clk->_post_rate_change_callback); + + return out; +} + +/*! + * @brief Register a callback that must be called before a rate change + * + * @param clk The handle for the clock + * @param cb The callback to be registered + */ +__inline__ void metal_clock_register_pre_rate_change_callback(struct metal_clock *clk, metal_clock_callback *cb) +{ + clk->_pre_rate_change_callback = _metal_clock_append_to_callbacks(clk->_pre_rate_change_callback, cb); +} + +/*! + * @brief Registers a callback that must be called after a rate change + * + * @param clk The handle for the clock + * @param cb The callback to be registered + */ +__inline__ void metal_clock_register_post_rate_change_callback(struct metal_clock *clk, metal_clock_callback *cb) +{ + clk->_post_rate_change_callback = _metal_clock_append_to_callbacks(clk->_post_rate_change_callback, cb); +} + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/compiler.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/compiler.h new file mode 100644 index 000000000..62c0ea975 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/compiler.h @@ -0,0 +1,22 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__COMPILER_H +#define METAL__COMPILER_H + +#define __METAL_DECLARE_VTABLE(type) \ + extern const struct type type; + +#define __METAL_DEFINE_VTABLE(type) \ + const struct type type + +#define __METAL_GET_FIELD(reg, mask) \ + (((reg) & (mask)) / ((mask) & ~((mask) << 1))) + +/* Set field with mask for a given value */ +#define __METAL_SET_FIELD(reg, mask, val) \ + (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask))) + +void _metal_trap(int ecode); + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/cpu.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/cpu.h new file mode 100644 index 000000000..dbd3dbfb5 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/cpu.h @@ -0,0 +1,271 @@ +/* Copyright 2018 SiFive, Inc */ + +/* SPDX-License-Identifier: Apache-2.0 */ + +/*! @file cpu.h + * @brief API for accessing CPU capabilities. + */ + +#ifndef METAL__CPU_H +#define METAL__CPU_H + +#include <stdint.h> +#include <metal/interrupt.h> + +struct metal_cpu; + +/*! + * @brief Function signature for exception handlers + */ +typedef void (*metal_exception_handler_t) (struct metal_cpu *cpu, int ecode); + +struct metal_cpu_vtable { + unsigned long long (*mcycle_get)(struct metal_cpu *cpu); + unsigned long long (*timebase_get)(struct metal_cpu *cpu); + unsigned long long (*mtime_get)(struct metal_cpu *cpu); + int (*mtimecmp_set)(struct metal_cpu *cpu, unsigned long long time); + struct metal_interrupt* (*tmr_controller_interrupt)(struct metal_cpu *cpu); + int (*get_tmr_interrupt_id)(struct metal_cpu *cpu); + struct metal_interrupt* (*sw_controller_interrupt)(struct metal_cpu *cpu); + int (*get_sw_interrupt_id)(struct metal_cpu *cpu); + int (*set_sw_ipi)(struct metal_cpu *cpu, int hartid); + int (*clear_sw_ipi)(struct metal_cpu *cpu, int hartid); + int (*get_msip)(struct metal_cpu *cpu, int hartid); + struct metal_interrupt* (*controller_interrupt)(struct metal_cpu *cpu); + int (*exception_register)(struct metal_cpu *cpu, int ecode, metal_exception_handler_t handler); + int (*get_ilen)(struct metal_cpu *cpu, uintptr_t epc); + uintptr_t (*get_epc)(struct metal_cpu *cpu); + int (*set_epc)(struct metal_cpu *cpu, uintptr_t epc); +}; + +/*! @brief A device handle for a CPU hart + */ +struct metal_cpu { + const struct metal_cpu_vtable *vtable; +}; + +/*! @brief Get a reference to a CPU hart + * + * @param hartid The ID of the desired CPU hart + * @return A pointer to the CPU device handle + */ +struct metal_cpu* metal_cpu_get(unsigned int hartid); + +/*! @brief Get the hartid of the CPU hart executing this function + * + * @return The hartid of the current CPU hart */ +int metal_cpu_get_current_hartid(void); + +/*! @brief Get the number of CPU harts + * + * @return The number of CPU harts */ +int metal_cpu_get_num_harts(void); + +/*! @brief Get the CPU cycle count timer value + * + * Get the value of the cycle count timer for a given CPU + * + * @param cpu The CPU device handle + * @return The value of the CPU cycle count timer + */ +__inline__ unsigned long long metal_cpu_get_timer(struct metal_cpu *cpu) +{ return cpu->vtable->mcycle_get(cpu); } + +/*! @brief Get the timebase of the CPU + * + * Get the value of the timebase of the cycle count timer + * + * @param cpu The CPU device handle + * @return The value of the cycle count timer timebase + */ +__inline__ unsigned long long metal_cpu_get_timebase(struct metal_cpu *cpu) +{ return cpu->vtable->timebase_get(cpu); } + +/*! @brief Get the value of the mtime RTC + * + * Get the value of the mtime real-time clock. The CPU interrupt controller + * must be initialized before this function is called or the return value + * will be 0. + * + * @param cpu The CPU device handle + * @return The value of mtime, or 0 if failure + */ +__inline__ unsigned long long metal_cpu_get_mtime(struct metal_cpu *cpu) +{ return cpu->vtable->mtime_get(cpu); } + +/*! @brief Set the value of the RTC mtimecmp RTC + * + * Set the value of the mtime real-time clock compare register. The CPU + * interrupt controller must be initialized before this function is called + * or the return value will be -1; + * + * @param cpu The CPU device handle + * @param time The value to set the compare register to + * @return The value of mtimecmp or -1 if error + */ +__inline__ int metal_cpu_set_mtimecmp(struct metal_cpu *cpu, unsigned long long time) +{ return cpu->vtable->mtimecmp_set(cpu, time); } + +/*! @brief Get a reference to RTC timer interrupt controller + * + * Get a reference to the interrupt controller for the real-time clock interrupt. + * The controller returned by this function must be initialized before any interrupts + * are registered or enabled with it. + * + * @param cpu The CPU device handle + * @return A pointer to the timer interrupt handle + */ +__inline__ struct metal_interrupt* metal_cpu_timer_interrupt_controller(struct metal_cpu *cpu) +{ return cpu->vtable->tmr_controller_interrupt(cpu); } + +/*! @brief Get the RTC timer interrupt id + * + * Get the interrupt ID of the real-time clock interrupt + * + * @param cpu The CPU device handle + * @return The timer interrupt ID + */ +__inline__ int metal_cpu_timer_get_interrupt_id(struct metal_cpu *cpu) +{ return cpu->vtable->get_tmr_interrupt_id(cpu); } + +/*! @brief Get a reference to the software interrupt controller + * + * Get a reference to the interrupt controller for the software/inter-process + * interrupt. The controller returned by this function must be initialized before + * any interrupts are registered or enabled with it. + * + * @param cpu The CPU device handle + * @return A pointer to the software interrupt handle + */ +__inline__ struct metal_interrupt* metal_cpu_software_interrupt_controller(struct metal_cpu *cpu) +{ return cpu->vtable->sw_controller_interrupt(cpu); } + +/*! @brief Get the software interrupt id + * + * Get the interrupt ID for the software/inter-process interrupt + * + * @param cpu The CPU device handle + * @return the software interrupt ID + */ +__inline__ int metal_cpu_software_get_interrupt_id(struct metal_cpu *cpu) +{ return cpu->vtable->get_sw_interrupt_id(cpu); } + +/*! + * @brief Set the inter-process interrupt for a hart + * + * Trigger a software/inter-process interrupt for a hart. The CPU interrupt + * controller for the CPU handle passed to this function must be initialized + * before this function is called. + * + * @param cpu The CPU device handle + * @param hartid The CPU hart ID to be interrupted + * @return 0 upon success + */ +__inline__ int metal_cpu_software_set_ipi(struct metal_cpu *cpu, int hartid) +{ return cpu->vtable->set_sw_ipi(cpu, hartid); } + +/*! + * @brief Clear the inter-process interrupt for a hart + * + * Clear the software/inter-process interrupt for a hart. The CPU interrupt + * controller for the CPU handle passed to this function must be initialized + * before this function is called. + * + * @param cpu The CPU device handle + * @param hartid The CPU hart ID to clear + * @return 0 upon success + */ +__inline__ int metal_cpu_software_clear_ipi(struct metal_cpu *cpu, int hartid) +{ return cpu->vtable->clear_sw_ipi(cpu, hartid); } + +/*! + * @brief Get the value of MSIP for the given hart + * + * Get the value of the machine software interrupt pending bit for + * the given hart. The CPU interrupt controller for the CPU handle passed + * as argument to this function must be initialized before this function + * is called. + * + * @param cpu the CPU device handle + * @param hartid The CPU hart to read + * @return 0 upon success + */ +__inline__ int metal_cpu_get_msip(struct metal_cpu *cpu, int hartid) +{ return cpu->vtable->get_msip(cpu, hartid); } + +/*! + * @brief Get the interrupt controller for the CPU + * + * Get the CPU interrupt controller. The controller returned by this + * function must be initialized before any interrupts are registered + * or enabled and before any exception handlers are registered with + * this CPU. + * + * @param cpu The CPU device handle + * @return The handle for the CPU interrupt controller + */ +__inline__ struct metal_interrupt* metal_cpu_interrupt_controller(struct metal_cpu *cpu) +{ return cpu->vtable->controller_interrupt(cpu); } + +/*! + * @brief Register an exception handler + * + * Register an exception handler for the CPU. The CPU interrupt controller must be initialized + * before this function is called. + * + * @param cpu The CPU device handle + * @param ecode The exception code to register a handler for + * @param handler Callback function for the exception handler + * @return 0 upon success + */ +__inline__ int metal_cpu_exception_register(struct metal_cpu *cpu, int ecode, metal_exception_handler_t handler) +{ return cpu->vtable->exception_register(cpu, ecode, handler); } + +/*! + * @brief Get the length of an instruction in bytes + * + * Get the length of an instruction in bytes. + * + * On RISC-V platforms, this is useful for detecting whether an instruction is + * compressed (2 bytes long) or uncompressed (4 bytes long). + * + * This function is useful in conjuction with `metal_cpu_get_exception_pc()` + * and `metal_cpu_set_exception_pc()` in order to cause the exception handler to + * return execution after the faulting instruction. + * + * @param cpu The CPU device handle + * @param epc The address of the instruction to measure + * @return the length of the instruction in bytes + */ +__inline__ int metal_cpu_get_instruction_length(struct metal_cpu *cpu, uintptr_t epc) +{ return cpu->vtable->get_ilen(cpu, epc); } + +/*! + * @brief Get the program counter of the current exception. + * + * This function must be called within an exception handler. The behavior is + * undefined outside of an exception handler. + * + * @param cpu The CPU device handle + * @return The value of the program counter at the time of the exception + */ +__inline__ uintptr_t metal_cpu_get_exception_pc(struct metal_cpu *cpu) +{ return cpu->vtable->get_epc(cpu); } + +/*! + * @brief Set the exception program counter + * + * This function must be called within an exception handler. The behavior + * is undefined outside of an exception handler. + * + * This function can be used to cause an exception handler to return execution + * to an address other than the one that caused the exception. + * + * @param cpu the CPU device handle + * @param epc The address to set the exception program counter to + * @return 0 upon success + */ +__inline__ int metal_cpu_set_exception_pc(struct metal_cpu *cpu, uintptr_t epc) +{ return cpu->vtable->set_epc(cpu, epc); } + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/fixed-clock.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/fixed-clock.h new file mode 100644 index 000000000..2647c5981 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/fixed-clock.h @@ -0,0 +1,22 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__FIXED_CLOCK_H +#define METAL__DRIVERS__FIXED_CLOCK_H + +struct __metal_driver_fixed_clock; + +#include <metal/compiler.h> +#include <metal/clock.h> + +struct __metal_driver_vtable_fixed_clock { + struct __metal_clock_vtable clock; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_fixed_clock) + +struct __metal_driver_fixed_clock { + struct metal_clock clock; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/fixed-factor-clock.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/fixed-factor-clock.h new file mode 100644 index 000000000..936ce8d77 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/fixed-factor-clock.h @@ -0,0 +1,22 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__FIXED_FACTOR_CLOCK_H +#define METAL__DRIVERS__FIXED_FACTOR_CLOCK_H + +struct __metal_driver_fixed_factor_clock; + +#include <metal/compiler.h> +#include <metal/clock.h> + +struct __metal_driver_vtable_fixed_factor_clock { + struct __metal_clock_vtable clock; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_fixed_factor_clock) + +struct __metal_driver_fixed_factor_clock { + struct metal_clock clock; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_clint0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_clint0.h new file mode 100644 index 000000000..08d571e1c --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_clint0.h @@ -0,0 +1,24 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__RISCV_CLINT0_H +#define METAL__DRIVERS__RISCV_CLINT0_H + +#include <metal/compiler.h> +#include <metal/drivers/riscv_cpu.h> + +struct __metal_driver_vtable_riscv_clint0 { + struct metal_interrupt_vtable clint_vtable; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_riscv_clint0) + +#define __METAL_MACHINE_MACROS +#include <metal/machine.h> +struct __metal_driver_riscv_clint0 { + struct metal_interrupt controller; + int init_done; +}; +#undef __METAL_MACHINE_MACROS + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_cpu.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_cpu.h new file mode 100644 index 000000000..ca91e0a95 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_cpu.h @@ -0,0 +1,192 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__RISCV_CPU_H +#define METAL__DRIVERS__RISCV_CPU_H + +#include <stdint.h> +#include <metal/cpu.h> +#include <metal/compiler.h> + +#define METAL_MAX_CORES 8 +#define METAL_MAX_MI 32 /* Per ISA MCause interrupts 32+ are Reserved */ +#define METAL_MAX_ME 12 /* Per ISA Exception codes 12+ are Reserved */ +#define METAL_DEFAULT_RTC_FREQ 32768 + +#define METAL_DISABLE 0 +#define METAL_ENABLE 1 + +#define METAL_ISA_A_EXTENSIONS 0x0001 +#define METAL_ISA_C_EXTENSIONS 0x0004 +#define METAL_ISA_D_EXTENSIONS 0x0008 +#define METAL_ISA_E_EXTENSIONS 0x0010 +#define METAL_ISA_F_EXTENSIONS 0x0020 +#define METAL_ISA_G_EXTENSIONS 0x0040 +#define METAL_ISA_I_EXTENSIONS 0x0100 +#define METAL_ISA_M_EXTENSIONS 0x1000 +#define METAL_ISA_N_EXTENSIONS 0x2000 +#define METAL_ISA_Q_EXTENSIONS 0x10000 +#define METAL_ISA_S_EXTENSIONS 0x40000 +#define METAL_ISA_U_EXTENSIONS 0x100000 +#define METAL_ISA_V_EXTENSIONS 0x200000 +#define METAL_ISA_XL32_EXTENSIONS 0x40000000UL +#define METAL_ISA_XL64_EXTENSIONS 0x8000000000000000UL +#define METAL_ISA_XL128_EXTENSIONS 0xC000000000000000UL + +#define METAL_MTVEC_DIRECT 0x00 +#define METAL_MTVEC_VECTORED 0x01 +#define METAL_MTVEC_CLIC 0x02 +#define METAL_MTVEC_CLIC_VECTORED 0x03 +#define METAL_MTVEC_CLIC_RESERVED 0x3C +#define METAL_MTVEC_MASK 0x3F +#if __riscv_xlen == 32 +#define METAL_MCAUSE_INTR 0x80000000UL +#define METAL_MCAUSE_CAUSE 0x000003FFUL +#else +#define METAL_MCAUSE_INTR 0x8000000000000000UL +#define METAL_MCAUSE_CAUSE 0x00000000000003FFUL +#endif +#define METAL_MCAUSE_MINHV 0x40000000UL +#define METAL_MCAUSE_MPP 0x30000000UL +#define METAL_MCAUSE_MPIE 0x08000000UL +#define METAL_MCAUSE_MPIL 0x00FF0000UL +#define METAL_MSTATUS_MIE 0x00000008UL +#define METAL_MSTATUS_MPIE 0x00000080UL +#define METAL_MSTATUS_MPP 0x00001800UL +#define METAL_MSTATUS_FS_INIT 0x00002000UL +#define METAL_MSTATUS_FS_CLEAN 0x00004000UL +#define METAL_MSTATUS_FS_DIRTY 0x00006000UL +#define METAL_MSTATUS_MPRV 0x00020000UL +#define METAL_MSTATUS_MXR 0x00080000UL +#define METAL_MINTSTATUS_MIL 0xFF000000UL +#define METAL_MINTSTATUS_SIL 0x0000FF00UL +#define METAL_MINTSTATUS_UIL 0x000000FFUL + +#define METAL_LOCAL_INTR(X) (16 + X) +#define METAL_MCAUSE_EVAL(cause) (cause & METAL_MCAUSE_INTR) +#define METAL_INTERRUPT(cause) (METAL_MCAUSE_EVAL(cause) ? 1 : 0) +#define METAL_EXCEPTION(cause) (METAL_MCAUSE_EVAL(cause) ? 0 : 1) +#define METAL_SW_INTR_EXCEPTION (METAL_MCAUSE_INTR + 3) +#define METAL_TMR_INTR_EXCEPTION (METAL_MCAUSE_INTR + 7) +#define METAL_EXT_INTR_EXCEPTION (METAL_MCAUSE_INTR + 11) +#define METAL_LOCAL_INTR_EXCEPTION(X) (METAL_MCAUSE_INTR + METAL_LOCAL_INTR(X)) +#define METAL_LOCAL_INTR_RESERVE0 1 +#define METAL_LOCAL_INTR_RESERVE1 2 +#define METAL_LOCAL_INTR_RESERVE2 4 +#define METAL_LOCAL_INTERRUPT_SW 8 /* Bit3 0x008 */ +#define METAL_LOCAL_INTR_RESERVE4 16 +#define METAL_LOCAL_INTR_RESERVE5 32 +#define METAL_LOCAL_INTR_RESERVE6 64 +#define METAL_LOCAL_INTERRUPT_TMR 128 /* Bit7 0x080 */ +#define METAL_LOCAL_INTR_RESERVE8 256 +#define METAL_LOCAL_INTR_RESERVE9 512 +#define METAL_LOCAL_INTR_RESERVE10 1024 +#define METAL_LOCAL_INTERRUPT_EXT 2048 /* Bit11 0x800 */ +/* Bit12 to Bit15 are Reserved */ +#define METAL_LOCAL_INTERRUPT(X) (0x10000 << X) /* Bit16+ Start of Custom Local Interrupt */ +#define METAL_MIE_INTERRUPT METAL_MSTATUS_MIE + +#define METAL_INSN_LENGTH_MASK 3 +#define METAL_INSN_NOT_COMPRESSED 3 + +typedef enum { + METAL_MACHINE_PRIVILEGE_MODE, + METAL_SUPERVISOR_PRIVILEGE_MODE, + METAL_USER_PRIVILEGE_MODE, +} metal_privilege_mode_e; + +typedef enum { + METAL_INTERRUPT_ID_BASE, + METAL_INTERRUPT_ID_SW = (METAL_INTERRUPT_ID_BASE + 3), + METAL_INTERRUPT_ID_TMR = (METAL_INTERRUPT_ID_BASE + 7), + METAL_INTERRUPT_ID_EXT = (METAL_INTERRUPT_ID_BASE + 11), + METAL_INTERRUPT_ID_CSW = (METAL_INTERRUPT_ID_BASE + 12), + METAL_INTERRUPT_ID_LC0 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(0)), + METAL_INTERRUPT_ID_LC1 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(1)), + METAL_INTERRUPT_ID_LC2 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(2)), + METAL_INTERRUPT_ID_LC3 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(3)), + METAL_INTERRUPT_ID_LC4 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(4)), + METAL_INTERRUPT_ID_LC5 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(5)), + METAL_INTERRUPT_ID_LC6 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(6)), + METAL_INTERRUPT_ID_LC7 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(7)), + METAL_INTERRUPT_ID_LC8 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(8)), + METAL_INTERRUPT_ID_LC9 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(9)), + METAL_INTERRUPT_ID_LC10 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(10)), + METAL_INTERRUPT_ID_LC11 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(11)), + METAL_INTERRUPT_ID_LC12 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(12)), + METAL_INTERRUPT_ID_LC13 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(13)), + METAL_INTERRUPT_ID_LC14 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(14)), + METAL_INTERRUPT_ID_LC15 = (METAL_INTERRUPT_ID_BASE + METAL_LOCAL_INTR(15)), + METAL_INTERRUPT_ID_LCMX, + METAL_INTERRUPT_ID_GL0 = METAL_INTERRUPT_ID_LCMX, + METAL_INTERRUPT_ID_GLMX = (METAL_MCAUSE_CAUSE + 1), +} metal_interrupt_id_e; + +typedef enum { + METAL_IAM_EXCEPTION_CODE, /* Instruction address misaligned */ + METAL_IAF_EXCEPTION_CODE, /* Instruction access faultd */ + METAL_II_EXCEPTION_CODE, /* Illegal instruction */ + METAL_BREAK_EXCEPTION_CODE, /* Breakpoint */ + METAL_LAM_EXCEPTION_CODE, /* Load address misaligned */ + METAL_LAF_EXCEPTION_CODE, /* Load access fault */ + METAL_SAMOAM_EXCEPTION_CODE, /* Store/AMO address misaligned */ + METAL_SAMOAF_EXCEPTION_CODE, /* Store/AMO access fault */ + METAL_ECALL_U_EXCEPTION_CODE, /* Environment call from U-mode */ + METAL_R9_EXCEPTION_CODE, /* Reserved */ + METAL_R10_EXCEPTION_CODE, /* Reserved */ + METAL_ECALL_M_EXCEPTION_CODE, /* Environment call from M-mode */ + METAL_MAX_EXCEPTION_CODE, +} metal_exception_code_e; + +typedef enum { + METAL_TIMER_MTIME_GET = 1, + METAL_SOFTWARE_IPI_CLEAR, + METAL_SOFTWARE_IPI_SET, + METAL_SOFTWARE_MSIP_GET, + METAL_MAX_INTERRUPT_GET, + METAL_INDEX_INTERRUPT_GET, +} metal_interrup_cmd_e; + +typedef struct __metal_interrupt_data { + long long pad : 64; + metal_interrupt_handler_t handler; + void *sub_int; + void *exint_data; +} __metal_interrupt_data; + +/* CPU interrupt controller */ + +uintptr_t __metal_myhart_id(void); + +struct __metal_driver_vtable_riscv_cpu_intc { + struct metal_interrupt_vtable controller_vtable; +}; + + +void __metal_interrupt_global_enable(void); +void __metal_interrupt_global_disable(void); +metal_vector_mode __metal_controller_interrupt_vector_mode(void); +void __metal_controller_interrupt_vector(metal_vector_mode mode, void *vec_table); + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_riscv_cpu_intc) + +struct __metal_driver_riscv_cpu_intc { + struct metal_interrupt controller; + int init_done; + uintptr_t metal_mtvec_table[METAL_MAX_MI]; + __metal_interrupt_data metal_int_table[METAL_MAX_MI]; + metal_exception_handler_t metal_exception_table[METAL_MAX_ME]; +}; + +/* CPU driver*/ +struct __metal_driver_vtable_cpu { + struct metal_cpu_vtable cpu_vtable; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_cpu) + +struct __metal_driver_cpu { + struct metal_cpu cpu; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_plic0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_plic0.h new file mode 100644 index 000000000..159ee6d69 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/riscv_plic0.h @@ -0,0 +1,31 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__RISCV_PLIC0_H +#define METAL__DRIVERS__RISCV_PLIC0_H + +#include <metal/compiler.h> +#include <metal/drivers/riscv_cpu.h> + +#define METAL_PLIC_SOURCE_MASK 0x1F +#define METAL_PLIC_SOURCE_SHIFT 5 +#define METAL_PLIC_SOURCE_PRIORITY_SHIFT 2 +#define METAL_PLIC_SOURCE_PENDING_SHIFT 0 + +struct __metal_driver_vtable_riscv_plic0 { + struct metal_interrupt_vtable plic_vtable; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_riscv_plic0) + +#define __METAL_MACHINE_MACROS +#include <metal/machine.h> +struct __metal_driver_riscv_plic0 { + struct metal_interrupt controller; + int init_done; + metal_interrupt_handler_t metal_exint_table[__METAL_PLIC_SUBINTERRUPTS]; + __metal_interrupt_data metal_exdata_table[__METAL_PLIC_SUBINTERRUPTS]; +}; +#undef __METAL_MACHINE_MACROS + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_ccache0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_ccache0.h new file mode 100644 index 000000000..2153cf384 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_ccache0.h @@ -0,0 +1,23 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_CCACHE0_H +#define METAL__DRIVERS__SIFIVE_CCACHE0_H + +#include <metal/cache.h> +#include <metal/compiler.h> + +struct __metal_driver_vtable_sifive_ccache0 { + struct __metal_cache_vtable cache; +}; + +struct __metal_driver_sifive_ccache0; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_ccache0) + +struct __metal_driver_sifive_ccache0 { + struct metal_cache cache; +}; + +#endif + diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_clic0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_clic0.h new file mode 100644 index 000000000..7fef38d19 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_clic0.h @@ -0,0 +1,43 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_CLIC0_H +#define METAL__DRIVERS__SIFIVE_CLIC0_H + +#include <metal/compiler.h> +#include <metal/drivers/riscv_cpu.h> + +#define METAL_CLIC_MAX_NMBITS 2 +#define METAL_CLIC_MAX_NLBITS 8 +#define METAL_CLIC_MAX_NVBITS 1 + +#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_MMODE 0x00 +#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_SMODE1 0x20 +#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_SMODE2 0x40 +#define METAL_SIFIVE_CLIC0_CLICCFG_NMBITS_MASK 0x60 +#define METAL_SIFIVE_CLIC0_CLICCFG_NLBITS_MASK 0x1E +#define METAL_SIFIVE_CLIC0_CLICCFG_NVBIT_MASK 0x01 + +#define METAL_CLIC_ICTRL_SMODE1_MASK 0x7F /* b8 set imply M-mode */ +#define METAL_CLIC_ICTRL_SMODE2_MASK 0x3F /* b8 set M-mode, b7 clear U-mode */ + +#define METAL_MAX_INTERRUPT_LEVEL ((1 << METAL_CLIC_MAX_NLBITS) - 1) + +struct __metal_driver_vtable_sifive_clic0 { + struct metal_interrupt_vtable clic_vtable; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_clic0) + +#define __METAL_MACHINE_MACROS +#include <metal/machine.h> +struct __metal_driver_sifive_clic0 { + struct metal_interrupt controller; + int init_done; + int pad[14]; + metal_interrupt_vector_handler_t metal_mtvt_table[__METAL_CLIC_SUBINTERRUPTS]; + __metal_interrupt_data metal_exint_table[__METAL_CLIC_SUBINTERRUPTS]; +}; +#undef __METAL_MACHINE_MACROS + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_hfrosc.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_hfrosc.h new file mode 100644 index 000000000..d311f0cf2 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_hfrosc.h @@ -0,0 +1,22 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_HFROSC_H +#define METAL__DRIVERS__SIFIVE_FE310_G000_HFROSC_H + +#include <metal/drivers/sifive_fe310-g000_prci.h> +#include <metal/compiler.h> +#include <metal/clock.h> +#include <metal/io.h> + +struct __metal_driver_vtable_sifive_fe310_g000_hfrosc { + struct __metal_clock_vtable clock; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_hfrosc) + +struct __metal_driver_sifive_fe310_g000_hfrosc { + struct metal_clock clock; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_hfxosc.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_hfxosc.h new file mode 100644 index 000000000..b86926fba --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_hfxosc.h @@ -0,0 +1,20 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_HFXOSC_H +#define METAL__DRIVERS__SIFIVE_FE310_G000_HFXOSC_H + +#include <metal/clock.h> +#include <metal/drivers/sifive_fe310-g000_prci.h> + +struct __metal_driver_vtable_sifive_fe310_g000_hfxosc { + struct __metal_clock_vtable clock; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_hfxosc) + +struct __metal_driver_sifive_fe310_g000_hfxosc { + struct metal_clock clock; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_lfrosc.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_lfrosc.h new file mode 100644 index 000000000..64985c6bb --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_lfrosc.h @@ -0,0 +1,21 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_LFROSC_H +#define METAL__DRIVERS__SIFIVE_FE310_G000_LFROSC_H + +#include <metal/compiler.h> +#include <metal/clock.h> +#include <metal/io.h> + +struct __metal_driver_vtable_sifive_fe310_g000_lfrosc { + struct __metal_clock_vtable clock; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_lfrosc) + +struct __metal_driver_sifive_fe310_g000_lfrosc { + struct metal_clock clock; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_pll.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_pll.h new file mode 100644 index 000000000..67f818f7b --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_pll.h @@ -0,0 +1,26 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include <metal/machine/platform.h> + +#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_PLL_H +#define METAL__DRIVERS__SIFIVE_FE310_G000_PLL_H + +struct __metal_driver_sifive_fe310_g000_pll; + +#include <metal/clock.h> +#include <metal/drivers/sifive_fe310-g000_prci.h> +#include <metal/machine.h> + +struct __metal_driver_vtable_sifive_fe310_g000_pll { + void (*init)(struct __metal_driver_sifive_fe310_g000_pll *pll); + struct __metal_clock_vtable clock; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_pll) + +struct __metal_driver_sifive_fe310_g000_pll { + struct metal_clock clock; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_prci.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_prci.h new file mode 100644 index 000000000..387130be5 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fe310-g000_prci.h @@ -0,0 +1,24 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_FE310_G000_PRCI_H +#define METAL__DRIVERS__SIFIVE_FE310_G000_PRCI_H + +#include <metal/compiler.h> +#include <metal/io.h> + +struct __metal_driver_sifive_fe310_g000_prci; + +struct __metal_driver_vtable_sifive_fe310_g000_prci { + long (*get_reg)(const struct __metal_driver_sifive_fe310_g000_prci *, long offset); + long (*set_reg)(const struct __metal_driver_sifive_fe310_g000_prci *, long offset, long value); +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fe310_g000_prci) + +struct __metal_driver_sifive_fe310_g000_prci { + const struct __metal_driver_vtable_sifive_fe310_g000_prci *vtable; +}; + +#endif + diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fu540-c000_l2.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fu540-c000_l2.h new file mode 100644 index 000000000..bb98f169e --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_fu540-c000_l2.h @@ -0,0 +1,23 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_FU540_C000_L2_H +#define METAL__DRIVERS__SIFIVE_FU540_C000_L2_H + +#include <metal/cache.h> +#include <metal/compiler.h> + +struct __metal_driver_vtable_sifive_fu540_c000_l2 { + struct __metal_cache_vtable cache; +}; + +struct __metal_driver_sifive_fu540_c000_l2; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_fu540_c000_l2) + +struct __metal_driver_sifive_fu540_c000_l2 { + struct metal_cache cache; +}; + +#endif + diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_global-external-interrupts0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_global-external-interrupts0.h new file mode 100644 index 000000000..9e6f2faf6 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_global-external-interrupts0.h @@ -0,0 +1,21 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_GLOBAL_EXTERNAL_INTERRUPTS0_H +#define METAL__DRIVERS__SIFIVE_GLOBAL_EXTERNAL_INTERRUPTS0_H + +#include <metal/compiler.h> +#include <metal/drivers/riscv_cpu.h> + +struct __metal_driver_vtable_sifive_global_external_interrupts0 { + struct metal_interrupt_vtable global0_vtable; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_global_external_interrupts0) + +struct __metal_driver_sifive_global_external_interrupts0 { + struct metal_interrupt irc; + int init_done; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-buttons.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-buttons.h new file mode 100644 index 000000000..a0caeaba8 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-buttons.h @@ -0,0 +1,21 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_GPIO_BUTTONS_H +#define METAL__DRIVERS__SIFIVE_GPIO_BUTTONS_H + +#include <string.h> +#include <metal/button.h> +#include <metal/compiler.h> + +struct __metal_driver_vtable_sifive_button { + struct metal_button_vtable button_vtable; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_button) + +struct __metal_driver_sifive_gpio_button { + struct metal_button button; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-leds.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-leds.h new file mode 100644 index 000000000..a8dacf116 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-leds.h @@ -0,0 +1,21 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_GPIO_LEDS_H +#define METAL__DRIVERS__SIFIVE_GPIO_LEDS_H + +#include <metal/drivers/sifive_gpio0.h> +#include <metal/led.h> +#include <metal/compiler.h> + +struct __metal_driver_vtable_sifive_led { + struct metal_led_vtable led_vtable; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_led) + +struct __metal_driver_sifive_gpio_led { + struct metal_led led; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-switches.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-switches.h new file mode 100644 index 000000000..c9c7839e9 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio-switches.h @@ -0,0 +1,21 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_GPIO_SWITCHES_H +#define METAL__DRIVERS__SIFIVE_GPIO_SWITCHES_H + +#include <metal/drivers/sifive_gpio0.h> +#include <metal/switch.h> +#include <metal/compiler.h> + +struct __metal_driver_vtable_sifive_switch { + struct metal_switch_vtable switch_vtable; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_switch) + +struct __metal_driver_sifive_gpio_switch { + struct metal_switch flip; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio0.h new file mode 100644 index 000000000..cc56dc722 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_gpio0.h @@ -0,0 +1,22 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_GPIO0_H +#define METAL__DRIVERS__SIFIVE_GPIO0_H + +#include <metal/compiler.h> +#include <metal/gpio.h> + +struct __metal_driver_vtable_sifive_gpio0 { + const struct __metal_gpio_vtable gpio; +}; + +//struct __metal_driver_sifive_gpio0; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_gpio0) + +struct __metal_driver_sifive_gpio0 { + struct metal_gpio gpio; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_local-external-interrupts0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_local-external-interrupts0.h new file mode 100644 index 000000000..aa8d63078 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_local-external-interrupts0.h @@ -0,0 +1,22 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_EXTERNAL_INTERRUPTS0_H +#define METAL__DRIVERS__SIFIVE_EXTERNAL_INTERRUPTS0_H + +#include <metal/compiler.h> +#include <metal/drivers/riscv_cpu.h> + +struct __metal_driver_vtable_sifive_local_external_interrupts0 { + struct metal_interrupt_vtable local0_vtable; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_local_external_interrupts0) + +struct __metal_driver_sifive_local_external_interrupts0 { + struct metal_interrupt irc; + int init_done; +}; + + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_rtc0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_rtc0.h new file mode 100644 index 000000000..b0ed143bf --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_rtc0.h @@ -0,0 +1,27 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_RTC0_H +#define METAL__DRIVERS__SIFIVE_RTC0_H + +#include <metal/io.h> +#include <metal/compiler.h> + +#include <metal/clock.h> +#include <metal/interrupt.h> +#include <metal/rtc.h> + +struct __metal_driver_vtable_sifive_rtc0 { + const struct metal_rtc_vtable rtc; +}; + +struct __metal_driver_sifive_rtc0; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_rtc0) + +struct __metal_driver_sifive_rtc0 { + const struct metal_rtc rtc; +}; + +#endif + diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_spi0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_spi0.h new file mode 100644 index 000000000..c4a6848e7 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_spi0.h @@ -0,0 +1,26 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_SPI0_H +#define METAL__DRIVERS__SIFIVE_SPI0_H + +#include <metal/drivers/sifive_gpio0.h> +#include <metal/clock.h> +#include <metal/compiler.h> +#include <metal/io.h> +#include <metal/spi.h> + +struct __metal_driver_vtable_sifive_spi0 { + const struct metal_spi_vtable spi; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_spi0) + +struct __metal_driver_sifive_spi0 { + struct metal_spi spi; + unsigned long baud_rate; + metal_clock_callback pre_rate_change_callback; + metal_clock_callback post_rate_change_callback; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_test0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_test0.h new file mode 100644 index 000000000..e87db2c83 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_test0.h @@ -0,0 +1,21 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_TEST0_H +#define METAL__DRIVERS__SIFIVE_TEST0_H + +#include <metal/compiler.h> +#include <metal/shutdown.h> + +struct __metal_driver_vtable_sifive_test0 { + const struct __metal_shutdown_vtable shutdown; +}; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_test0) + +struct __metal_driver_sifive_test0 { + struct __metal_shutdown shutdown; +}; + + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_trace.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_trace.h new file mode 100644 index 000000000..3c67522f4 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_trace.h @@ -0,0 +1,23 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_TRACE_H +#define METAL__DRIVERS__SIFIVE_TRACE_H + +#include <metal/compiler.h> +#include <metal/io.h> +#include <metal/uart.h> + +struct __metal_driver_vtable_sifive_trace { + const struct metal_uart_vtable uart; +}; + +struct __metal_driver_sifive_trace; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_trace) + +struct __metal_driver_sifive_trace { + struct metal_uart uart; +}; + +#endif /* METAL__DRIVERS__SIFIVE_TRACE_H */ diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_uart0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_uart0.h new file mode 100644 index 000000000..5d585e783 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_uart0.h @@ -0,0 +1,30 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_UART0_H +#define METAL__DRIVERS__SIFIVE_UART0_H + +#include <metal/drivers/sifive_gpio0.h> +#include <metal/drivers/riscv_plic0.h> +#include <metal/clock.h> +#include <metal/io.h> +#include <metal/uart.h> +#include <metal/compiler.h> + +struct __metal_driver_vtable_sifive_uart0 { + const struct metal_uart_vtable uart; +}; + +struct __metal_driver_sifive_uart0; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_uart0) + +struct __metal_driver_sifive_uart0 { + struct metal_uart uart; + unsigned long baud_rate; + metal_clock_callback pre_rate_change_callback; + metal_clock_callback post_rate_change_callback; +}; + + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_wdog0.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_wdog0.h new file mode 100644 index 000000000..12b143d58 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/drivers/sifive_wdog0.h @@ -0,0 +1,26 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_WDOG0_H +#define METAL__DRIVERS__SIFIVE_WDOG0_H + +#include <metal/io.h> +#include <metal/compiler.h> + +#include <metal/watchdog.h> +#include <metal/clock.h> +#include <metal/interrupt.h> + +struct __metal_driver_vtable_sifive_wdog0 { + const struct metal_watchdog_vtable watchdog; +}; + +struct __metal_driver_sifive_wdog0; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_wdog0) + +struct __metal_driver_sifive_wdog0 { + const struct metal_watchdog watchdog; +}; + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/gpio.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/gpio.h new file mode 100644 index 000000000..7645494ff --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/gpio.h @@ -0,0 +1,284 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__GPIO_H +#define METAL__GPIO_H + +#include <metal/compiler.h> +#include <metal/interrupt.h> + +/*! + * @file gpio.h + * @brief API for manipulating general-purpose input/output + */ + +struct metal_gpio; + +struct __metal_gpio_vtable { + int (*disable_input)(struct metal_gpio *, long pins); + int (*enable_input)(struct metal_gpio *, long pins); + long (*input)(struct metal_gpio *); + long (*output)(struct metal_gpio *); + int (*disable_output)(struct metal_gpio *, long pins); + int (*enable_output)(struct metal_gpio *, long pins); + int (*output_set)(struct metal_gpio *, long value); + int (*output_clear)(struct metal_gpio *, long value); + int (*output_toggle)(struct metal_gpio *, long value); + int (*enable_io)(struct metal_gpio *, long pins, long dest); + int (*disable_io)(struct metal_gpio *, long pins); + int (*config_int)(struct metal_gpio *, long pins, int intr_type); + int (*clear_int)(struct metal_gpio *, long pins, int intr_type); + struct metal_interrupt* (*interrupt_controller)(struct metal_gpio *gpio); + int (*get_interrupt_id)(struct metal_gpio *gpio, int pin); +}; + +#define METAL_GPIO_INT_DISABLE 0 +#define METAL_GPIO_INT_RISING 1 +#define METAL_GPIO_INT_FALLING 2 +#define METAL_GPIO_INT_BOTH_EDGE 3 +#define METAL_GPIO_INT_LOW 4 +#define METAL_GPIO_INT_HIGH 5 +#define METAL_GPIO_INT_BOTH_LEVEL 6 +#define METAL_GPIO_INT_MAX 7 + +/*! + * @struct metal_gpio + * @brief The handle for a GPIO interface + */ +struct metal_gpio { + const struct __metal_gpio_vtable *vtable; +}; + +/*! + * @brief Get a GPIO device handle + * @param device_num The GPIO device index + * @return The GPIO device handle, or NULL if there is no device at that index + */ +struct metal_gpio *metal_gpio_get_device(unsigned int device_num); + +/*! + * @brief enable input on a pin + * @param gpio The handle for the GPIO interface + * @param pin The pin number indexed from 0 + * @return 0 if the input is successfully enabled + */ +__inline__ int metal_gpio_enable_input(struct metal_gpio *gpio, int pin) { + if(!gpio) { + return 1; + } + + return gpio->vtable->enable_input(gpio, (1 << pin)); +} + +/*! + * @brief Disable input on a pin + * @param gpio The handle for the GPIO interface + * @param pin The pin number indexed from 0 + * @return 0 if the input is successfully disabled + */ +__inline__ int metal_gpio_disable_input(struct metal_gpio *gpio, int pin) { + if(!gpio) { + return 1; + } + + return gpio->vtable->disable_input(gpio, (1 << pin)); +} + +/*! + * @brief Enable output on a pin + * @param gpio The handle for the GPIO interface + * @param pin The pin number indexed from 0 + * @return 0 if the output is successfully enabled + */ +__inline__ int metal_gpio_enable_output(struct metal_gpio *gpio, int pin) { + if(!gpio) { + return 1; + } + + return gpio->vtable->enable_output(gpio, (1 << pin)); +} + +/*! + * @brief Disable output on a pin + * @param gpio The handle for the GPIO interface + * @param pin The pin number indexed from 0 + * @return 0 if the output is successfully disabled + */ +__inline__ int metal_gpio_disable_output(struct metal_gpio *gpio, int pin) { + if(!gpio) { + return 1; + } + + return gpio->vtable->disable_output(gpio, (1 << pin)); +} + +/*! + * @brief Set the output value of a GPIO pin + * @param gpio The handle for the GPIO interface + * @param pin The pin number indexed from 0 + * @param value The value to set the pin to + * @return 0 if the output is successfully set + */ +__inline__ int metal_gpio_set_pin(struct metal_gpio *gpio, int pin, int value) { + if(!gpio) { + return 1; + } + + if(value == 0) { + return gpio->vtable->output_clear(gpio, (1 << pin)); + } else { + return gpio->vtable->output_set(gpio, (1 << pin)); + } +} + +/*! + * @brief Get the value of the GPIO pin + * @param gpio The handle for the GPIO interface + * @param pin The pin number indexed from 0 + * @return The value of the GPIO pin + */ +__inline__ int metal_gpio_get_input_pin(struct metal_gpio *gpio, int pin) { + if(!gpio) { + return 0; + } + + long value = gpio->vtable->input(gpio); + + if(value & (1 << pin)) { + return 1; + } else { + return 0; + } +} + +/*! + * @brief Get the value of the GPIO pin + * @param gpio The handle for the GPIO interface + * @param pin The pin number indexed from 0 + * @return The value of the GPIO pin + */ +__inline__ int metal_gpio_get_output_pin(struct metal_gpio *gpio, int pin) { + if(!gpio) { + return 0; + } + + long value = gpio->vtable->output(gpio); + + if(value & (1 << pin)) { + return 1; + } else { + return 0; + } +} + +/*! + * @brief Clears the value of the GPIO pin + * @param gpio The handle for the GPIO interface + * @param pin The pin number indexed from 0 + * @return 0 if the pin is successfully cleared + */ +__inline__ int metal_gpio_clear_pin(struct metal_gpio *gpio, int pin) { + if(!gpio) { + return 1; + } + + return gpio->vtable->output_clear(gpio, (1 << pin)); +} + +/*! + * @brief Toggles the value of the GPIO pin + * @param gpio The handle for the GPIO interface + * @param pin The pin number indexed from 0 + * @return 0 if the pin is successfully toggled + */ +__inline__ int metal_gpio_toggle_pin(struct metal_gpio *gpio, int pin) { + if(!gpio) { + return 1; + } + + return gpio->vtable->output_toggle(gpio, (1 << pin)); +} + +/*! + * @brief Enables and sets the pinmux for a GPIO pin + * @param gpio The handle for the GPIO interface + * @param pin The bitmask for the pin to enable pinmux on + * @param io_function The IO function to set + * @return 0 if the pinmux is successfully set + */ +__inline__ int metal_gpio_enable_pinmux(struct metal_gpio *gpio, int pin, int io_function) { + if(!gpio) { + return 1; + } + + return gpio->vtable->enable_io(gpio, (1 << pin), (io_function << pin)); +} + +/*! + * @brief Disables the pinmux for a GPIO pin + * @param gpio The handle for the GPIO interface + * @param pin The bitmask for the pin to disable pinmux on + * @return 0 if the pinmux is successfully set + */ +__inline__ int metal_gpio_disable_pinmux(struct metal_gpio *gpio, int pin) { + if(!gpio) { + return 1; + } + + return gpio->vtable->disable_io(gpio, (1 << pin)); +} + +/*! + * @brief Config gpio interrupt type + * @param gpio The handle for the GPIO interface + * @param pin The bitmask for the pin to enable gpio interrupt + * @param intr_type The interrupt type + * @return 0 if the interrupt mode is setup properly + */ +__inline__ int metal_gpio_config_interrupt(struct metal_gpio *gpio, int pin, int intr_type) { + if(!gpio) { + return 1; + } + + return gpio->vtable->config_int(gpio, (1 << pin), intr_type); +} + +/*! + * @brief Clear gpio interrupt status + * @param gpio The handle for the GPIO interface + * @param pin The bitmask for the pin to clear gpio interrupt + * @param intr_type The interrupt type to be clear + * @return 0 if the interrupt is cleared + */ +__inline__ int metal_gpio_clear_interrupt(struct metal_gpio *gpio, int pin, int intr_type) { + if(!gpio) { + return 1; + } + + return gpio->vtable->clear_int(gpio, (1 << pin), intr_type); +} + +/*! + * @brief Get the interrupt controller for a gpio + * + * @param gpio The handle for the gpio + * @return A pointer to the interrupt controller responsible for handling + * gpio interrupts. + */ +__inline__ struct metal_interrupt* + metal_gpio_interrupt_controller(struct metal_gpio *gpio) { + return gpio->vtable->interrupt_controller(gpio); +} + +/*! + * @brief Get the interrupt id for a gpio + * + * @param gpio The handle for the gpio + * @param pin The bitmask for the pin to get gpio interrupt id + * @return The interrupt id corresponding to a gpio. + */ +__inline__ int metal_gpio_get_interrupt_id(struct metal_gpio *gpio, int pin) { + return gpio->vtable->get_interrupt_id(gpio, pin); +} + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/interrupt.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/interrupt.h new file mode 100644 index 000000000..4f59bd36b --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/interrupt.h @@ -0,0 +1,461 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__INTERRUPT_H +#define METAL__INTERRUPT_H + +/*! @file interrupt.h + * @brief API for registering and manipulating interrupts + */ + +#include <stddef.h> + +/*! + * @brief Possible interrupt controllers + */ +typedef enum metal_interrupt_controller_ { + METAL_CPU_CONTROLLER = 0, + METAL_CLINT_CONTROLLER = 1, + METAL_CLIC_CONTROLLER = 2, + METAL_PLIC_CONTROLLER = 3 +} metal_intr_cntrl_type; + +/*! + * @brief Possible mode of interrupts to operate + */ +typedef enum metal_vector_mode_ { + METAL_DIRECT_MODE = 0, + METAL_VECTOR_MODE = 1, + METAL_SELECTIVE_NONVECTOR_MODE = 2, + METAL_SELECTIVE_VECTOR_MODE = 3, + METAL_HARDWARE_VECTOR_MODE = 4 +} metal_vector_mode; + +/*! + * @brief Possible mode of privilege interrupts to operate + */ +typedef enum metal_intr_priv_mode_ { + METAL_INTR_PRIV_M_MODE = 0, + METAL_INTR_PRIV_MU_MODE = 1, + METAL_INTR_PRIV_MSU_MODE = 2 +} metal_intr_priv_mode; + +/*! + * @brief Function signature for interrupt callback handlers + */ +typedef void (*metal_interrupt_handler_t) (int, void *); +typedef void (*metal_interrupt_vector_handler_t) (void); + +struct metal_interrupt; + +struct metal_interrupt_vtable { + void (*interrupt_init)(struct metal_interrupt *controller); + int (*interrupt_set_vector_mode)(struct metal_interrupt *controller, metal_vector_mode mode); + metal_vector_mode (*interrupt_get_vector_mode)(struct metal_interrupt *controller); + int (*interrupt_set_privilege)(struct metal_interrupt *controller, metal_intr_priv_mode priv); + metal_intr_priv_mode (*interrupt_get_privilege)(struct metal_interrupt *controller); + int (*interrupt_clear)(struct metal_interrupt *controller, int id); + int (*interrupt_set)(struct metal_interrupt *controller, int id); + int (*interrupt_register)(struct metal_interrupt *controller, int id, + metal_interrupt_handler_t isr, void *priv_data); + int (*interrupt_vector_register)(struct metal_interrupt *controller, int id, + metal_interrupt_vector_handler_t isr, void *priv_data); + int (*interrupt_enable)(struct metal_interrupt *controller, int id); + int (*interrupt_disable)(struct metal_interrupt *controller, int id); + int (*interrupt_vector_enable)(struct metal_interrupt *controller, int id); + int (*interrupt_vector_disable)(struct metal_interrupt *controller, int id); + unsigned int (*interrupt_get_threshold)(struct metal_interrupt *controller); + int (*interrupt_set_threshold)(struct metal_interrupt *controller, unsigned int threshold); + unsigned int (*interrupt_get_priority)(struct metal_interrupt *controller, int id); + int (*interrupt_set_priority)(struct metal_interrupt *controller, int id, unsigned int priority); + int (*command_request)(struct metal_interrupt *controller, int cmd, void *data); + int (*mtimecmp_set)(struct metal_interrupt *controller, int hartid, unsigned long long time); +}; + +/*! + * @brief A handle for an interrupt + */ +struct metal_interrupt { + const struct metal_interrupt_vtable *vtable; +}; + +/*! + * @brief Initialize a given interrupt controller + * + * Initialize a given interrupt controller. This function must be called + * before any interrupts are registered or enabled with the handler. It + * is invalid to initialize an interrupt controller more than once. + * + * @param controller The handle for the interrupt controller + */ +__inline__ void metal_interrupt_init(struct metal_interrupt *controller) +{ + controller->vtable->interrupt_init(controller); +} + +/*! + * @brief Get the handle for an given interrupt controller type + * @param cntrl The type ofinterrupt controller + * @param id The instance of the interrupt controller + * @return A handle to the interrupt controller (CLINT, CLIC, PLIC), or + * NULL if none is found for the requested label + */ +struct metal_interrupt* metal_interrupt_get_controller(metal_intr_cntrl_type cntrl, + int id); + +/*! + * @brief Configure vector mode for an interrupt controller + * + * Configure vector mode for an interrupt controller. + * This function must be called after initialization and before + * configuring individual interrupts, registering ISR. + * + * @param controller The handle for the interrupt controller + * @param mode The vector mode of the interrupt controller. + * @return 0 upon success + */ +__inline__ int metal_interrupt_set_vector_mode(struct metal_interrupt *controller, + metal_vector_mode mode) +{ + return controller->vtable->interrupt_set_vector_mode(controller, mode); +} + +/*! + * @brief Get vector mode of a given an interrupt controller + * + * Configure vector mode for an interrupt controller. + * This function must be called after initialization and before + * configuring individual interrupts, registering ISR. + * + * @param controller The handle for the interrupt controller + * @param mode The vector mode of the interrupt controller. + * @return The interrupt vector mode + */ +__inline__ metal_vector_mode metal_interrupt_get_vector_mode(struct metal_interrupt *controller) +{ + return controller->vtable->interrupt_get_vector_mode(controller); +} + +/*! + * @brief Configure privilege mode a of given interrupt controller + * + * Configure privilege mode for a given interrupt controller. + * This function must be called after initialization and before + * configuring individual interrupts, registering ISR. + * + * @param controller The handle for the interrupt controller + * @param privilege The privilege mode of the interrupt controller. + * @return 0 upon success + */ +__inline__ int metal_interrupt_set_privilege(struct metal_interrupt *controller, + metal_intr_priv_mode privilege) +{ + return controller->vtable->interrupt_set_privilege(controller, privilege); +} + +/*! + * @brief Get privilege mode a of given interrupt controller + * + * Get privilege mode for a given interrupt controller. + * This function must be called after initialization and before + * configuring individual interrupts, registering ISR. + * + * @param controller The handle for the interrupt controller + * @return The interrupt privilege mode + */ +__inline__ metal_intr_priv_mode metal_interrupt_get_privilege(struct metal_interrupt *controller) +{ + return controller->vtable->interrupt_get_privilege(controller); +} + +/*! + * @brief clear an interrupt + * @param controller The handle for the interrupt controller + * @param id The interrupt ID to trigger + * @return 0 upon success + */ +__inline__ int metal_interrupt_clear(struct metal_interrupt *controller, int id) +{ + return controller->vtable->interrupt_clear(controller, id); +} + +/*! + * @brief Set an interrupt + * @param controller The handle for the interrupt controller + * @param id The interrupt ID to trigger + * @return 0 upon success + */ +__inline__ int metal_interrupt_set(struct metal_interrupt *controller, int id) +{ + return controller->vtable->interrupt_set(controller, id); +} + +/*! + * @brief Register an interrupt handler + * @param controller The handle for the interrupt controller + * @param id The interrupt ID to register + * @param handler The interrupt handler callback + * @param priv_data Private data for the interrupt handler + * @return 0 upon success + */ +__inline__ int metal_interrupt_register_handler(struct metal_interrupt *controller, + int id, + metal_interrupt_handler_t handler, + void *priv_data) +{ + return controller->vtable->interrupt_register(controller, id, handler, priv_data); +} + +/*! + * @brief Register an interrupt vector handler + * @param controller The handle for the interrupt controller + * @param id The interrupt ID to register + * @param handler The interrupt vector handler callback + * @param priv_data Private data for the interrupt handler + * @return 0 upon success + */ +__inline__ int metal_interrupt_register_vector_handler(struct metal_interrupt *controller, + int id, + metal_interrupt_vector_handler_t handler, + void *priv_data) +{ + return controller->vtable->interrupt_vector_register(controller, id, handler, priv_data); +} + +/*! + * @brief Enable an interrupt + * @param controller The handle for the interrupt controller + * @param id The interrupt ID to enable + * @return 0 upon success + */ +__inline__ int metal_interrupt_enable(struct metal_interrupt *controller, int id) +{ + return controller->vtable->interrupt_enable(controller, id); +} + +/*! + * @brief Disable an interrupt + * @param controller The handle for the interrupt controller + * @param id The interrupt ID to disable + * @return 0 upon success + */ +__inline__ int metal_interrupt_disable(struct metal_interrupt *controller, int id) +{ + return controller->vtable->interrupt_disable(controller, id); +} + +/*! + * @brief Set interrupt threshold level + * @param controller The handle for the interrupt controller + * @param threshold The interrupt threshold level + * @return 0 upon success + */ +inline int metal_interrupt_set_threshold(struct metal_interrupt *controller, unsigned int level) +{ + return controller->vtable->interrupt_set_threshold(controller, level); +} + +/*! + * @brief Get an interrupt threshold level + * @param controller The handle for the interrupt controller + * @return The interrupt threshold level + */ +inline unsigned int metal_interrupt_get_threshold(struct metal_interrupt *controller) +{ + return controller->vtable->interrupt_get_threshold(controller); +} + +/*! + * @brief Set an interrupt priority level + * @param controller The handle for the interrupt controller + * @param id The interrupt ID to enable + * @param priority The interrupt priority level + * @return 0 upon success + */ +inline int metal_interrupt_set_priority(struct metal_interrupt *controller, + int id, unsigned int priority) +{ + return controller->vtable->interrupt_set_priority(controller, id, priority); +} + +/*! + * @brief Get an interrupt priority level + * @param controller The handle for the interrupt controller + * @param id The interrupt ID to enable + * @return The interrupt priority level + */ +inline unsigned int metal_interrupt_get_priority(struct metal_interrupt *controller, int id) +{ + return controller->vtable->interrupt_get_priority(controller, id); +} + +/*! + * @brief Enable an interrupt vector + * @param controller The handle for the interrupt controller + * @param id The interrupt ID to enable + * @return 0 upon success + */ +__inline__ int metal_interrupt_vector_enable(struct metal_interrupt *controller, int id) +{ + return controller->vtable->interrupt_vector_enable(controller, id); +} + +/*! + * @brief Disable an interrupt vector + * @param controller The handle for the interrupt controller + * @param id The interrupt ID to disable + * @return 0 upon success + */ +__inline__ int metal_interrupt_vector_disable(struct metal_interrupt *controller, int id) +{ + return controller->vtable->interrupt_vector_disable(controller, id); +} + +/*! + * @brief Default interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_interrupt_vector_handler(void); + +/*! + * @brief Metal Software interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_software_interrupt_vector_handler(void); + +/*! + * @brief Metal Timer interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_timer_interrupt_vector_handler(void); + +/*! + * @brief Metal External interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_external_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 0 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc0_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 1 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc1_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 2 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc2_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 3 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc3_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 4 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc4_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 5 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc5_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 6 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc6_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 7 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc7_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 8 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc8_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 9 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc9_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 10 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc10_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 11 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc11_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 12 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc12_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 13 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc13_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 14 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc14_interrupt_vector_handler(void); + +/*! + * @brief Metal Local 15 interrupt vector handler, that can be overriden by user + * @param None + * @return None + */ +void __attribute__((weak, interrupt)) metal_lc15_interrupt_vector_handler(void); + +/* Utilities function to controll, manages devices via a given interrupt controller */ +__inline__ int _metal_interrupt_command_request(struct metal_interrupt *controller, + int cmd, void *data) +{ + return controller->vtable->command_request(controller, cmd, data); +} + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/io.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/io.h new file mode 100644 index 000000000..d55b4520a --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/io.h @@ -0,0 +1,22 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__IO_H +#define METAL__IO_H + +/* This macro enforces that the compiler will not elide the given access. */ +#define __METAL_ACCESS_ONCE(x) (*(__typeof__(*x) volatile *)(x)) + +/* Allows users to specify arbitrary fences. */ +#define __METAL_IO_FENCE(pred, succ) __asm__ volatile ("fence " #pred "," #succ ::: "memory"); + +/* Types that explicitly describe an address as being used for memory-mapped + * IO. These should only be accessed via __METAL_ACCESS_ONCE. */ +typedef unsigned char __metal_io_u8; +typedef unsigned short __metal_io_u16; +typedef unsigned int __metal_io_u32; +#if __riscv_xlen >= 64 +typedef unsigned long __metal_io_u64; +#endif + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/itim.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/itim.h new file mode 100644 index 000000000..1a2a05b8b --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/itim.h @@ -0,0 +1,21 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__ITIM_H +#define METAL__ITIM_H + +/*! @file itim.h + * + * API for manipulating ITIM allocation + */ + + +/*! @def METAL_PLACE_IN_ITIM + * @brief Link a function into the ITIM + * + * Link a function into the ITIM (Instruction Tightly Integrated + * Memory) if the ITIM is present on the target device. + */ +#define METAL_PLACE_IN_ITIM __attribute__((section(".itim"))) + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/led.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/led.h new file mode 100644 index 000000000..f2aa39ceb --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/led.h @@ -0,0 +1,68 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__LED_H +#define METAL__LED_H + +/*! + * @file led.h + * @brief API for manipulating LEDs + */ + +struct metal_led; + +struct metal_led_vtable { + int (*led_exist)(struct metal_led *led, char *label); + void (*led_enable)(struct metal_led *led); + void (*led_on)(struct metal_led *led); + void (*led_off)(struct metal_led *led); + void (*led_toggle)(struct metal_led *led); +}; + +/*! + * @brief A handle for an LED + */ +struct metal_led { + const struct metal_led_vtable *vtable; +}; + +/*! + * @brief Get a handle for an LED + * @param label The DeviceTree label for the desired LED + * @return A handle to the LED, or NULL if none is found for the requested label + */ +struct metal_led* metal_led_get(char *label); + +/*! + * @brief Get a handle for a channel of an RGB LED + * @param label The DeviceTree label for the desired LED + * @param color The color for the LED in the DeviceTree + * @return A handle to the LED, or NULL if none is found for the requested label and color + */ +struct metal_led* metal_led_get_rgb(char *label, char *color); + +/*! + * @brief Enable an LED + * @param led The handle for the LED + */ +__inline__ void metal_led_enable(struct metal_led *led) { led->vtable->led_enable(led); } + +/*! + * @brief Turn an LED on + * @param led The handle for the LED + */ +__inline__ void metal_led_on(struct metal_led *led) { led->vtable->led_on(led); } + +/*! + * @brief Turn an LED off + * @param led The handle for the LED + */ +__inline__ void metal_led_off(struct metal_led *led) { led->vtable->led_off(led); } + +/*! + * @brief Toggle the on/off state of an LED + * @param led The handle for the LED + */ +__inline__ void metal_led_toggle(struct metal_led *led) { led->vtable->led_toggle(led); } + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/lock.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/lock.h new file mode 100644 index 000000000..0702cbf16 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/lock.h @@ -0,0 +1,146 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__LOCK_H +#define METAL__LOCK_H + +#include <metal/machine.h> +#include <metal/memory.h> +#include <metal/compiler.h> + +/*! + * @file lock.h + * @brief An API for creating and using a software lock/mutex + */ + +/* TODO: How can we make the exception code platform-independant? */ +#define _METAL_STORE_AMO_ACCESS_FAULT 7 + +#define METAL_LOCK_BACKOFF_CYCLES 32 +#define METAL_LOCK_BACKOFF_EXPONENT 2 + +/*! + * @def METAL_LOCK_DECLARE + * @brief Declare a lock + * + * Locks must be declared with METAL_LOCK_DECLARE to ensure that the lock + * is linked into a memory region which supports atomic memory operations. + */ +#define METAL_LOCK_DECLARE(name) \ + __attribute__((section(".data.locks"))) \ + struct metal_lock name + +/*! + * @brief A handle for a lock + */ +struct metal_lock { + int _state; +}; + +/*! + * @brief Initialize a lock + * @param lock The handle for a lock + * @return 0 if the lock is successfully initialized. A non-zero code indicates failure. + * + * If the lock cannot be initialized, attempts to take or give the lock + * will result in a Store/AMO access fault. + */ +__inline__ int metal_lock_init(struct metal_lock *lock) { +#ifdef __riscv_atomic + /* Get a handle for the memory which holds the lock state */ + struct metal_memory *lock_mem = metal_get_memory_from_address((uintptr_t) &(lock->_state)); + if(!lock_mem) { + return 1; + } + + /* If the memory doesn't support atomics, report an error */ + if(!metal_memory_supports_atomics(lock_mem)) { + return 2; + } + + lock->_state = 0; + + return 0; +#else + return 3; +#endif +} + +/*! + * @brief Take a lock + * @param lock The handle for a lock + * @return 0 if the lock is successfully taken + * + * If the lock initialization failed, attempts to take a lock will result in + * a Store/AMO access fault. + */ +__inline__ int metal_lock_take(struct metal_lock *lock) { +#ifdef __riscv_atomic + int old = 1; + int new = 1; + + int backoff = 1; + const int max_backoff = METAL_LOCK_BACKOFF_CYCLES * METAL_MAX_CORES; + + while(1) { + __asm__ volatile("amoswap.w.aq %[old], %[new], (%[state])" + : [old] "=r" (old) + : [new] "r" (new), [state] "r" (&(lock->_state)) + : "memory"); + + if (old == 0) { + break; + } + + for (int i = 0; i < backoff; i++) { + __asm__ volatile(""); + } + + if (backoff < max_backoff) { + backoff *= METAL_LOCK_BACKOFF_EXPONENT; + } + } + + return 0; +#else + /* Store the memory address in mtval like a normal store/amo access fault */ + __asm__ ("csrw mtval, %[state]" + :: [state] "r" (&(lock->_state))); + + /* Trigger a Store/AMO access fault */ + _metal_trap(_METAL_STORE_AMO_ACCESS_FAULT); + + /* If execution returns, indicate failure */ + return 1; +#endif +} + +/*! + * @brief Give back a held lock + * @param lock The handle for a lock + * @return 0 if the lock is successfully given + * + * If the lock initialization failed, attempts to give a lock will result in + * a Store/AMO access fault. + */ +__inline__ int metal_lock_give(struct metal_lock *lock) { +#ifdef __riscv_atomic + __asm__ volatile("amoswap.w.rl x0, x0, (%[state])" + :: [state] "r" (&(lock->_state)) + : "memory"); + + return 0; +#else + /* Store the memory address in mtval like a normal store/amo access fault */ + __asm__ ("csrw mtval, %[state]" + :: [state] "r" (&(lock->_state))); + + /* Trigger a Store/AMO access fault */ + _metal_trap(_METAL_STORE_AMO_ACCESS_FAULT); + + /* If execution returns, indicate failure */ + return 1; +#endif +} + +#endif /* METAL__LOCK_H */ diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/memory.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/memory.h new file mode 100644 index 000000000..9de7d6162 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/memory.h @@ -0,0 +1,81 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__MEMORY_H +#define METAL__MEMORY_H + +#include <stdint.h> +#include <stddef.h> + +/*! + * @file memory.h + * + * @brief API for enumerating memory blocks + */ + +struct _metal_memory_attributes { + unsigned int R : 1; + unsigned int W : 1; + unsigned int X : 1; + unsigned int C : 1; + unsigned int A : 1; +}; + +/*! + * @brief A handle for a memory block + */ +struct metal_memory { + const uintptr_t _base_address; + const size_t _size; + const struct _metal_memory_attributes _attrs; +}; + +/*! + * @brief Get the memory block which services the given address + * + * Given a physical memory address, get a handle for the memory block to which + * that address is mapped. + * + * @param address The address to query + * @return The memory block handle, or NULL if the address is not mapped to a memory block + */ +struct metal_memory *metal_get_memory_from_address(const uintptr_t address); + +/*! + * @brief Get the base address for a memory block + * @param memory The handle for the memory block + * @return The base address of the memory block + */ +__inline__ uintptr_t metal_memory_get_base_address(const struct metal_memory *memory) { + return memory->_base_address; +} + +/*! + * @brief Get the size of a memory block + * @param memory The handle for the memory block + * @return The size of the memory block + */ +__inline__ size_t metal_memory_get_size(const struct metal_memory *memory) { + return memory->_size; +} + +/*! + * @brief Query if a memory block supports atomic operations + * @param memory The handle for the memory block + * @return nonzero if the memory block supports atomic operations + */ +__inline__ int metal_memory_supports_atomics(const struct metal_memory *memory) { + return memory->_attrs.A; +} + +/*! + * @brief Query if a memory block is cacheable + * @param memory The handle for the memory block + * @return nonzero if the memory block is cachable + */ +__inline__ int metal_memory_is_cachable(const struct metal_memory *memory) { + return memory->_attrs.C; +} + +#endif /* METAL__MEMORY_H */ + diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/pmp.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/pmp.h new file mode 100644 index 000000000..d948656c8 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/pmp.h @@ -0,0 +1,209 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__PMP_H +#define METAL__PMP_H + +/*! + * @file metal/pmp.h + * + * @brief API for Configuring Physical Memory Protection on RISC-V Cores + * + * The Physical Memory Protection (PMP) interface on RISC-V cores + * is a form of memory protection unit which allows for a finite number + * of physical memory regions to be configured with certain access + * permissions. + * + * Additional information about the use and configuration rules for PMPs + * can be found by reading the RISC-V Privileged Architecture Specification. + */ + +#include <stddef.h> +#include <metal/machine.h> + +struct metal_pmp; + +/*! + * @brief Set of available PMP addressing modes + */ +enum metal_pmp_address_mode { + /*! @brief Disable the PMP region */ + METAL_PMP_OFF = 0, + /*! @brief Use Top-of-Range mode */ + METAL_PMP_TOR = 1, + /*! @brief Use naturally-aligned 4-byte region mode */ + METAL_PMP_NA4 = 2, + /*! @brief Use naturally-aligned power-of-two mode */ + METAL_PMP_NAPOT = 3 +}; + +/*! + * @brief Configuration for a PMP region + */ +struct metal_pmp_config { + /*! @brief Sets whether reads to the PMP region succeed */ + unsigned int R : 1; + /*! @brief Sets whether writes to the PMP region succeed */ + unsigned int W : 1; + /*! @brief Sets whether the PMP region is executable */ + unsigned int X : 1; + + /*! @brief Sets the addressing mode of the PMP region */ + enum metal_pmp_address_mode A : 2; + + int _pad : 2; + + /*! @brief Sets whether the PMP region is locked */ + enum metal_pmp_locked { + METAL_PMP_UNLOCKED = 0, + METAL_PMP_LOCKED = 1 + } L : 1; +}; + +/*! + * @brief A handle for the PMP device + */ +struct metal_pmp { + /* The minimum granularity of the PMP region. Set by metal_pmp_init */ + uintptr_t _granularity[METAL_MAX_CORES]; +}; + +/*! + * @brief Get the PMP device handle + */ +struct metal_pmp *metal_pmp_get_device(void); + +/*! + * @brief Get the number of pmp regions for the hartid + */ +int metal_pmp_num_regions(int hartid); + +/*! + * @brief Initialize the PMP + * @param pmp The PMP device handle to be initialized + * + * The PMP initialization routine is optional and may be called as many times + * as is desired. The effect of the initialization routine is to attempt to set + * all regions to unlocked and disabled, as well as to clear the X, W, and R + * bits. Only the pmp configuration of the hart which executes the routine will + * be affected. + * + * If any regions are fused to preset values by the implementation or locked, + * those PMP regions will silently remain uninitialized. + */ +void metal_pmp_init(struct metal_pmp *pmp); + +/*! + * @brief Configure a PMP region + * @param pmp The PMP device handle + * @param region The PMP region to configure + * @param config The desired configuration of the PMP region + * @param address The desired address of the PMP region + * @return 0 upon success + */ +int metal_pmp_set_region(struct metal_pmp *pmp, unsigned int region, struct metal_pmp_config config, size_t address); + +/*! + * @brief Get the configuration for a PMP region + * @param pmp The PMP device handle + * @param region The PMP region to read + * @param config Variable to store the PMP region configuration + * @param address Variable to store the PMP region address + * @return 0 if the region is read successfully + */ +int metal_pmp_get_region(struct metal_pmp *pmp, unsigned int region, struct metal_pmp_config *config, size_t *address); + +/*! + * @brief Lock a PMP region + * @param pmp The PMP device handle + * @param region The PMP region to lock + * @return 0 if the region is successfully locked + */ +int metal_pmp_lock(struct metal_pmp *pmp, unsigned int region); + +/*! + * @brief Set the address for a PMP region + * @param pmp The PMP device handle + * @param region The PMP region to set + * @param address The desired address of the PMP region + * @return 0 if the address is successfully set + */ +int metal_pmp_set_address(struct metal_pmp *pmp, unsigned int region, size_t address); + +/*! + * @brief Get the address of a PMP region + * @param pmp The PMP device handle + * @param region The PMP region to read + * @return The address of the PMP region, or 0 if the region could not be read + */ +size_t metal_pmp_get_address(struct metal_pmp *pmp, unsigned int region); + +/*! + * @brief Set the addressing mode of a PMP region + * @param pmp The PMP device handle + * @param region The PMP region to set + * @param mode The PMP addressing mode to set + * @return 0 if the addressing mode is successfully set + */ +int metal_pmp_set_address_mode(struct metal_pmp *pmp, unsigned int region, enum metal_pmp_address_mode mode); + +/*! + * @brief Get the addressing mode of a PMP region + * @param pmp The PMP device handle + * @param region The PMP region to read + * @return The address mode of the PMP region + */ +enum metal_pmp_address_mode metal_pmp_get_address_mode(struct metal_pmp *pmp, unsigned int region); + +/*! + * @brief Set the executable bit for a PMP region + * @param pmp The PMP device handle + * @param region The PMP region to set + * @param X The desired value of the executable bit + * @return 0 if the executable bit is successfully set + */ +int metal_pmp_set_executable(struct metal_pmp *pmp, unsigned int region, int X); + +/*! + * @brief Get the executable bit for a PMP region + * @param pmp The PMP device handle + * @param region The PMP region to read + * @return the value of the executable bit + */ +int metal_pmp_get_executable(struct metal_pmp *pmp, unsigned int region); + +/*! + * @brief Set the writable bit for a PMP region + * @param pmp The PMP device handle + * @param region The PMP region to set + * @param W The desired value of the writable bit + * @return 0 if the writable bit is successfully set + */ +int metal_pmp_set_writeable(struct metal_pmp *pmp, unsigned int region, int W); + +/*! + * @brief Get the writable bit for a PMP region + * @param pmp The PMP device handle + * @param region The PMP region to read + * @return the value of the writable bit + */ +int metal_pmp_get_writeable(struct metal_pmp *pmp, unsigned int region); + +/*! + * @brief Set the readable bit for a PMP region + * @param pmp The PMP device handle + * @param region The PMP region to set + * @param R The desired value of the readable bit + * @return 0 if the readable bit is successfully set + */ +int metal_pmp_set_readable(struct metal_pmp *pmp, unsigned int region, int R); + +/*! + * @brief Set the readable bit for a PMP region + * @param pmp The PMP device handle + * @param region The PMP region to read + * @return the value of the readable bit + */ +int metal_pmp_get_readable(struct metal_pmp *pmp, unsigned int region); + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/privilege.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/privilege.h new file mode 100644 index 000000000..928a936b1 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/privilege.h @@ -0,0 +1,122 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__PRIVILEGE_H +#define METAL__PRIVILEGE_H + +/*! + * @file metal/privilege.h + * + * @brief API for manipulating the privilege mode of a RISC-V system + * + * Additional information about privilege modes on RISC-V systems can be found + * by reading the RISC-V Privileged Architecture Specification v1.10. + */ + +#include <stdint.h> + +enum metal_privilege_mode { + METAL_PRIVILEGE_USER = 0, + METAL_PRIVILEGE_SUPERVISOR = 1, + METAL_PRIVILEGE_MACHINE = 3, +}; + +#if __riscv_xlen == 32 +typedef uint32_t metal_xreg_t; +#elif __riscv_xlen == 64 +typedef uint64_t metal_xreg_t; +#endif + +#if __riscv_flen == 32 +typedef uint32_t metal_freg_t; +#elif __riscv_flen == 64 +typedef uint64_t metal_freg_t; +#endif + +struct metal_register_file { + metal_xreg_t ra; + metal_xreg_t sp; + metal_xreg_t gp; + metal_xreg_t tp; + + metal_xreg_t t0; + metal_xreg_t t1; + metal_xreg_t t2; + + metal_xreg_t s0; + metal_xreg_t s1; + + metal_xreg_t a0; + metal_xreg_t a1; + metal_xreg_t a2; + metal_xreg_t a3; + metal_xreg_t a4; + metal_xreg_t a5; +#ifndef __riscv_32e + metal_xreg_t a6; + metal_xreg_t a7; + + metal_xreg_t s2; + metal_xreg_t s3; + metal_xreg_t s4; + metal_xreg_t s5; + metal_xreg_t s6; + metal_xreg_t s7; + metal_xreg_t s8; + metal_xreg_t s9; + metal_xreg_t s10; + metal_xreg_t s11; + + metal_xreg_t t3; + metal_xreg_t t4; + metal_xreg_t t5; + metal_xreg_t t6; +#endif /* __riscv_32e */ + +#ifdef __riscv_flen + metal_freg_t ft0; + metal_freg_t ft1; + metal_freg_t ft2; + metal_freg_t ft3; + metal_freg_t ft4; + metal_freg_t ft5; + metal_freg_t ft6; + metal_freg_t ft7; + + metal_freg_t fs0; + metal_freg_t fs1; + + metal_freg_t fa0; + metal_freg_t fa1; + metal_freg_t fa2; + metal_freg_t fa3; + metal_freg_t fa4; + metal_freg_t fa5; + metal_freg_t fa6; + metal_freg_t fa7; + + metal_freg_t fs2; + metal_freg_t fs3; + metal_freg_t fs4; + metal_freg_t fs5; + metal_freg_t fs6; + metal_freg_t fs7; + metal_freg_t fs8; + metal_freg_t fs9; + metal_freg_t fs10; + metal_freg_t fs11; + + metal_freg_t ft8; + metal_freg_t ft9; + metal_freg_t ft10; + metal_freg_t ft11; +#endif /* __riscv_flen */ +}; + +typedef void (*metal_privilege_entry_point_t)(void); + +void metal_privilege_drop_to_mode(enum metal_privilege_mode mode, + struct metal_register_file regfile, + metal_privilege_entry_point_t entry_point); + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/rtc.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/rtc.h new file mode 100644 index 000000000..2e742ea38 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/rtc.h @@ -0,0 +1,127 @@ +/* Copyright 2019 SiFive, Inc. */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__RTC_H +#define METAL__RTC_H + +#include <stdint.h> + +/*! + * @file rtc.h + * @brief API for Real-Time Clocks + */ + +struct metal_rtc; + +/*! + * @brief List of RTC run behaviors + */ +enum metal_rtc_run_option { + METAL_RTC_STOP = 0, + METAL_RTC_RUN, +}; + +struct metal_rtc_vtable { + uint64_t (*get_rate)(const struct metal_rtc *const rtc); + uint64_t (*set_rate)(const struct metal_rtc *const rtc, const uint64_t rate); + uint64_t (*get_compare)(const struct metal_rtc *const rtc); + uint64_t (*set_compare)(const struct metal_rtc *const rtc, const uint64_t compare); + uint64_t (*get_count)(const struct metal_rtc *const rtc); + uint64_t (*set_count)(const struct metal_rtc *const rtc, const uint64_t count); + int (*run)(const struct metal_rtc *const rtc, const enum metal_rtc_run_option option); + struct metal_interrupt *(*get_interrupt)(const struct metal_rtc *const rtc); + int (*get_interrupt_id)(const struct metal_rtc *const rtc); +}; + +/*! + * @brief Handle for a Real-Time Clock + */ +struct metal_rtc { + const struct metal_rtc_vtable *vtable; +}; + +/*! + * @brief Get the rate of the RTC + * @return The rate in Hz + */ +inline uint64_t metal_rtc_get_rate(const struct metal_rtc *const rtc) { + return rtc->vtable->get_rate(rtc); +} + +/*! + * @brief Set (if possible) the rate of the RTC + * @return The new rate of the RTC (not guaranteed to be the same as requested) + */ +inline uint64_t metal_rtc_set_rate(const struct metal_rtc *const rtc, const uint64_t rate) { + return rtc->vtable->set_rate(rtc, rate); +} + +/*! + * @brief Get the compare value of the RTC + * @return The compare value + */ +inline uint64_t metal_rtc_get_compare(const struct metal_rtc *const rtc) { + return rtc->vtable->get_compare(rtc); +} + +/*! + * @brief Set the compare value of the RTC + * @return The set compare value (not guaranteed to be exactly the requested value) + * + * The RTC device might impose limits on the maximum compare value or the granularity + * of the compare value. + */ +inline uint64_t metal_rtc_set_compare(const struct metal_rtc *const rtc, const uint64_t compare) { + return rtc->vtable->set_compare(rtc, compare); +} + +/*! + * @brief Get the current count of the RTC + * @return The count + */ +inline uint64_t metal_rtc_get_count(const struct metal_rtc *const rtc) { + return rtc->vtable->get_count(rtc); +} + +/*! + * @brief Set the current count of the RTC + * @return The set value of the count (not guaranteed to be exactly the requested value) + * + * The RTC device might impose limits on the maximum value of the count + */ +inline uint64_t metal_rtc_set_count(const struct metal_rtc *const rtc, const uint64_t count) { + return rtc->vtable->set_count(rtc, count); +} + +/*! + * @brief Start or stop the RTC + * @return 0 if the RTC was successfully started/stopped + */ +inline int metal_rtc_run(const struct metal_rtc *const rtc, const enum metal_rtc_run_option option) { + return rtc->vtable->run(rtc, option); +} + +/*! + * @brief Get the interrupt handle for the RTC compare + * @return The interrupt handle + */ +inline struct metal_interrupt *metal_rtc_get_interrupt(const struct metal_rtc *const rtc) { + return rtc->vtable->get_interrupt(rtc); +} + +/*! + * @brief Get the interrupt ID for the RTC compare + * @return The interrupt ID + */ +inline int metal_rtc_get_interrupt_id(const struct metal_rtc *const rtc) { + return rtc->vtable->get_interrupt_id(rtc); +} + +/*! + * @brief Get the handle for an RTC by index + * @return The RTC handle, or NULL if none is available at that index + */ +struct metal_rtc *metal_rtc_get_device(int index); + +#endif + diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/shutdown.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/shutdown.h new file mode 100644 index 000000000..8d4020b5c --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/shutdown.h @@ -0,0 +1,36 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__SHUTDOWN_H +#define METAL__SHUTDOWN_H + +/*! + * @file shutdown.h + * @brief API for shutting down a machine + */ + +struct __metal_shutdown; + +struct __metal_shutdown_vtable { + void (*exit)(const struct __metal_shutdown *sd, int code) __attribute__((noreturn)); +}; + +struct __metal_shutdown { + const struct __metal_shutdown_vtable *vtable; +}; + +__inline__ void __metal_shutdown_exit(const struct __metal_shutdown *sd, int code) __attribute__((noreturn)); +__inline__ void __metal_shutdown_exit(const struct __metal_shutdown *sd, int code) { sd->vtable->exit(sd, code); } + +/*! + * @brief The public METAL shutdown interface + * + * Shuts down the machine, if the machine enables an interface for + * shutting down. When no interface is provided, will cause the machine + * to spin indefinitely. + * + * @param code The return code to set. 0 indicates program success. + */ +void metal_shutdown(int code) __attribute__((noreturn)); + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/spi.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/spi.h new file mode 100644 index 000000000..635e3c151 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/spi.h @@ -0,0 +1,90 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__SPI_H +#define METAL__SPI_H + +struct metal_spi; + +/*! @brief The configuration for a SPI transfer */ +struct metal_spi_config { + /*! @brief The protocol for the SPI transfer */ + enum { + METAL_SPI_SINGLE, + METAL_SPI_DUAL, + METAL_SPI_QUAD + } protocol; + + /*! @brief The polarity of the SPI transfer, equivalent to CPOL */ + unsigned int polarity : 1; + /*! @brief The phase of the SPI transfer, equivalent to CPHA */ + unsigned int phase : 1; + /*! @brief The endianness of the SPI transfer */ + unsigned int little_endian : 1; + /*! @brief The active state of the chip select line */ + unsigned int cs_active_high : 1; + /*! @brief The chip select ID to activate for the SPI transfer */ + unsigned int csid; + /*! @brief The spi command frame number (cycles = num * frame_len) */ + unsigned int cmd_num; + /*! @brief The spi address frame number */ + unsigned int addr_num; + /*! @brief The spi dummy frame number */ + unsigned int dummy_num; + /*! @brief The Dual/Quad spi mode selection.*/ + enum { + MULTI_WIRE_ALL, + MULTI_WIRE_DATA_ONLY, + MULTI_WIRE_ADDR_DATA + } multi_wire; +}; + +struct metal_spi_vtable { + void (*init)(struct metal_spi *spi, int baud_rate); + int (*transfer)(struct metal_spi *spi, struct metal_spi_config *config, size_t len, char *tx_buf, char *rx_buf); + int (*get_baud_rate)(struct metal_spi *spi); + int (*set_baud_rate)(struct metal_spi *spi, int baud_rate); +}; + +/*! @brief A handle for a SPI device */ +struct metal_spi { + const struct metal_spi_vtable *vtable; +}; + +/*! @brief Get a handle for a SPI device + * @param device_num The index of the desired SPI device + * @return A handle to the SPI device, or NULL if the device does not exist*/ +struct metal_spi *metal_spi_get_device(unsigned int device_num); + +/*! @brief Initialize a SPI device with a certain baud rate + * @param spi The handle for the SPI device to initialize + * @param baud_rate The baud rate to set the SPI device to + */ +__inline__ void metal_spi_init(struct metal_spi *spi, int baud_rate) { spi->vtable->init(spi, baud_rate); } + +/*! @brief Perform a SPI transfer + * @param spi The handle for the SPI device to perform the transfer + * @param config The configuration for the SPI transfer. + * @param len The number of bytes to transfer + * @param tx_buf The buffer to send over the SPI bus. Must be len bytes long. If NULL, the SPI will transfer the value 0. + * @param rx_buf The buffer to receive data into. Must be len bytes long. If NULL, the SPI will ignore received bytes. + * @return 0 if the transfer succeeds + */ +__inline__ int metal_spi_transfer(struct metal_spi *spi, struct metal_spi_config *config, size_t len, char *tx_buf, char *rx_buf) { + return spi->vtable->transfer(spi, config, len, tx_buf, rx_buf); +} + +/*! @brief Get the current baud rate of the SPI device + * @param spi The handle for the SPI device + * @return The baud rate in Hz + */ +__inline__ int metal_spi_get_baud_rate(struct metal_spi *spi) { return spi->vtable->get_baud_rate(spi); } + +/*! @brief Set the current baud rate of the SPI device + * @param spi The handle for the SPI device + * @param baud_rate The desired baud rate of the SPI device + * @return 0 if the baud rate is successfully changed + */ +__inline__ int metal_spi_set_baud_rate(struct metal_spi *spi, int baud_rate) { return spi->vtable->set_baud_rate(spi, baud_rate); } + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/switch.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/switch.h new file mode 100644 index 000000000..61f0efe56 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/switch.h @@ -0,0 +1,51 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__SWITCH_H +#define METAL__SWITCH_H + +/*! + * @file switch.h + * @brief API for reading toggle switches + */ + +#include <metal/interrupt.h> + +struct metal_switch; + +struct metal_switch_vtable { + int (*switch_exist)(struct metal_switch *sw, char *label); + struct metal_interrupt* (*interrupt_controller)(struct metal_switch *sw); + int (*get_interrupt_id)(struct metal_switch *sw); +}; + +/*! + * @brief A handle for a switch + */ +struct metal_switch { + const struct metal_switch_vtable *vtable; +}; + +/*! + * @brief Get a handle for a switch + * @param label The DeviceTree label for the desired switch + * @return A handle to the switch, or NULL if none is found for the requested label + */ +struct metal_switch* metal_switch_get(char *label); + +/*! + * @brief Get the interrupt controller for a switch + * @param sw The handle for the switch + * @return The interrupt controller handle + */ +__inline__ struct metal_interrupt* + metal_switch_interrupt_controller(struct metal_switch *sw) { return sw->vtable->interrupt_controller(sw); } + +/*! + * @brief Get the interrupt id for a switch + * @param sw The handle for the switch + * @return The interrupt ID for the switch + */ +__inline__ int metal_switch_get_interrupt_id(struct metal_switch *sw) { return sw->vtable->get_interrupt_id(sw); } + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/time.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/time.h new file mode 100644 index 000000000..5c33b6f1b --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/time.h @@ -0,0 +1,18 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__TIME_H +#define METAL__TIME_H + +#include <time.h> + +/*! + * @file time.h + * @brief API for dealing with time + */ + +int metal_gettimeofday(struct timeval *tp, void *tzp); + +time_t metal_time(void); + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/timer.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/timer.h new file mode 100644 index 000000000..eeae1f60b --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/timer.h @@ -0,0 +1,36 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__TIMER_H +#define METAL__TIMER_H + +/*! + * @file timer.h + * @brief API for reading and manipulating the machine timer + */ + +/*! + * @brief Read the machine cycle count + * @param hartid The hart ID to read the cycle count of + * @param cyclecount The variable to hold the value + * @return 0 upon success + */ +int metal_timer_get_cyclecount(int hartid, unsigned long long *cyclecount); + +/*! + * @brief Get the machine timebase frequency + * @param hartid The hart ID to read the timebase of + * @param timebase The variable to hold the value + * @return 0 upon success + */ +int metal_timer_get_timebase_frequency(int hartid, unsigned long long *timebase); + +/*! + * @brief Set the machine timer tick interval in seconds + * @param hartid The hart ID to read the timebase of + * @param second The number of seconds to set the tick interval to + * @return 0 upon success + */ +int metal_timer_set_tick(int hartid, int second); + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/tty.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/tty.h new file mode 100644 index 000000000..fe4c000db --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/tty.h @@ -0,0 +1,52 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__TTY_H +#define METAL__TTY_H + +/*! + * @file tty.h + * @brief API for emulated serial teriminals + */ + +/*! + * @brief Write a character to the default output device + * + * Write a character to the default output device, which for most + * targets is the UART serial port. + * + * putc() does CR/LF mapping. + * putc_raw() does not. + * + * @param c The character to write to the terminal + * @return 0 on success, or -1 on failure. + */ +int metal_tty_putc(int c); + +/*! + * @brief Write a raw character to the default output device + * + * Write a character to the default output device, which for most + * targets is the UART serial port. + * + * putc() does CR/LF mapping. + * putc_raw() does not. + * + * @param c The character to write to the terminal + * @return 0 on success, or -1 on failure. + */ +int metal_tty_putc_raw(int c); + +/*! + * @brief Get a byte from the default output device + * + * The default output device, is typically the UART serial port. + * + * This call is non-blocking, if nothing is ready c==-1 + * if something is ready, then c=[0x00 to 0xff] byte value. + * + * @return 0 on success, or -1 on failure. + */ +int metal_tty_getc(int *c); + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/uart.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/uart.h new file mode 100644 index 000000000..e9e4d0436 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/uart.h @@ -0,0 +1,106 @@ +/* Copyright 2018 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__UART_H +#define METAL__UART_H + +/*! + * @file uart.h + * @brief API for UART serial ports + */ + +#include <metal/interrupt.h> + +struct metal_uart; +#undef getc +#undef putc +struct metal_uart_vtable { + void (*init)(struct metal_uart *uart, int baud_rate); + int (*putc)(struct metal_uart *uart, int c); + int (*txready)(struct metal_uart *uart); + int (*getc)(struct metal_uart *uart, int *c); + int (*get_baud_rate)(struct metal_uart *uart); + int (*set_baud_rate)(struct metal_uart *uart, int baud_rate); + struct metal_interrupt* (*controller_interrupt)(struct metal_uart *uart); + int (*get_interrupt_id)(struct metal_uart *uart); +}; + +/*! + * @brief Handle for a UART serial device + */ +struct metal_uart { + const struct metal_uart_vtable *vtable; +}; + +/*! + * @brief Initialize UART device + + * Initialize the UART device described by the UART handle. This function must be called before any + * other method on the UART can be invoked. It is invalid to initialize a UART more than once. + * + * @param uart The UART device handle + * @param baud_rate the baud rate to set the UART to + */ +__inline__ void metal_uart_init(struct metal_uart *uart, int baud_rate) { uart->vtable->init(uart, baud_rate); } + +/*! + * @brief Output a character over the UART + * @param uart The UART device handle + * @param c The character to send over the UART + * @return 0 upon success + */ +__inline__ int metal_uart_putc(struct metal_uart *uart, int c) { return uart->vtable->putc(uart, c); } + +/*! + * @brief Test, determine if tx output is blocked(full/busy) + * @param uart The UART device handle + * @return 0 not blocked + */ +__inline__ int metal_uart_txready(struct metal_uart *uart) { return uart->vtable->txready(uart); } + +/*! + * @brief Read a character sent over the UART + * @param uart The UART device handle + * @param c The varible to hold the read character + * @return 0 upon success + * + * If "c == -1" no char was ready. + * If "c != -1" then C == byte value (0x00 to 0xff) + */ +__inline__ int metal_uart_getc(struct metal_uart *uart, int *c) { return uart->vtable->getc(uart, c); } + +/*! + * @brief Get the baud rate of the UART peripheral + * @param uart The UART device handle + * @return The current baud rate of the UART + */ +__inline__ int metal_uart_get_baud_rate(struct metal_uart *uart) { return uart->vtable->get_baud_rate(uart); } + +/*! + * @brief Set the baud rate of the UART peripheral + * @param uart The UART device handle + * @param baud_rate The baud rate to configure + * @return the new baud rate of the UART + */ +__inline__ int metal_uart_set_baud_rate(struct metal_uart *uart, int baud_rate) { return uart->vtable->set_baud_rate(uart, baud_rate); } + +/*! + * @brief Get the interrupt controller of the UART peripheral + * + * Get the interrupt controller for the UART peripheral. The interrupt + * controller must be initialized before any interrupts can be registered + * or enabled with it. + * + * @param uart The UART device handle + * @return The handle for the UART interrupt controller + */ +__inline__ struct metal_interrupt* metal_uart_interrupt_controller(struct metal_uart *uart) { return uart->vtable->controller_interrupt(uart); } + +/*! + * @brief Get the interrupt ID of the UART controller + * @param uart The UART device handle + * @return The UART interrupt id + */ +__inline__ int metal_uart_get_interrupt_id(struct metal_uart *uart) { return uart->vtable->get_interrupt_id(uart); } + +#endif diff --git a/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/watchdog.h b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/watchdog.h new file mode 100644 index 000000000..b5ff48697 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/metal/watchdog.h @@ -0,0 +1,163 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__WATCHDOG_H +#define METAL__WATCHDOG_H + +/*! + * @file watchdog.h + * + * @brief API for configuring watchdog timers + */ + +#include <metal/interrupt.h> + +struct metal_watchdog; + +/*! + * @brief List of watchdog timer count behaviors + */ +enum metal_watchdog_run_option { + METAL_WATCHDOG_STOP = 0, /*!< Stop the watchdog */ + METAL_WATCHDOG_RUN_ALWAYS, /*!< Run the watchdog continuously, even during sleep */ + METAL_WATCHDOG_RUN_AWAKE, /*!< Run the watchdog only while the CPU is awake */ +}; + +/*! + * @brief List of behaviors when a watchdog triggers + */ +enum metal_watchdog_result { + METAL_WATCHDOG_NO_RESULT = 0, /*!< When the watchdog triggers, do nothing */ + METAL_WATCHDOG_INTERRUPT, /*!< When the watchdog triggers, fire an interrupt */ + METAL_WATCHDOG_FULL_RESET, /*!< When the watchdog triggers, cause a full system reset */ +}; + + +struct metal_watchdog_vtable { + int (*feed)(const struct metal_watchdog *const wdog); + long int (*get_rate)(const struct metal_watchdog *const wdog); + long int (*set_rate)(const struct metal_watchdog *const wdog, const long int rate); + long int (*get_timeout)(const struct metal_watchdog *const wdog); + long int (*set_timeout)(const struct metal_watchdog *const wdog, const long int timeout); + int (*set_result)(const struct metal_watchdog *const wdog, + const enum metal_watchdog_result result); + int (*run)(const struct metal_watchdog *const wdog, + const enum metal_watchdog_run_option option); + struct metal_interrupt *(*get_interrupt)(const struct metal_watchdog *const wdog); + int (*get_interrupt_id)(const struct metal_watchdog *const wdog); + int (*clear_interrupt)(const struct metal_watchdog *const wdog); +}; + +/*! + * @brief Handle for a Watchdog Timer + */ +struct metal_watchdog { + const struct metal_watchdog_vtable *vtable; +}; + +/*! + * @brief Feed the watchdog timer + */ +inline int metal_watchdog_feed(const struct metal_watchdog *const wdog) +{ + return wdog->vtable->feed(wdog); +} + +/*! + * @brief Get the rate of the watchdog timer in Hz + * + * @return the rate of the watchdog timer + */ +inline long int metal_watchdog_get_rate(const struct metal_watchdog *const wdog) +{ + return wdog->vtable->get_rate(wdog); +} + +/*! + * @brief Set the rate of the watchdog timer in Hz + * + * There is no guarantee that the new rate will match the requested rate. + * + * @return the new rate of the watchdog timer + */ +inline long int metal_watchdog_set_rate(const struct metal_watchdog *const wdog, const long int rate) +{ + return wdog->vtable->set_rate(wdog, rate); +} + +/*! + * @brief Get the timeout of the watchdog timer + * + * @return the watchdog timeout value + */ +inline long int metal_watchdog_get_timeout(const struct metal_watchdog *const wdog) +{ + return wdog->vtable->get_timeout(wdog); +} + +/*! + * @brief Set the timeout of the watchdog timer + * + * The set rate will be the minimimum of the requested and maximum supported rates. + * + * @return the new watchdog timeout value + */ +inline long int metal_watchdog_set_timeout(const struct metal_watchdog *const wdog, const long int timeout) +{ + return wdog->vtable->set_timeout(wdog, timeout); +} + +/*! + * @brief Sets the result behavior of a watchdog timer timeout + * + * @return 0 if the requested result behavior is supported + */ +inline int metal_watchdog_set_result(const struct metal_watchdog *const wdog, + const enum metal_watchdog_result result) +{ + return wdog->vtable->set_result(wdog, result); +} + +/*! + * @brief Set the run behavior of the watchdog + * + * Used to enable/disable the watchdog timer + * + * @return 0 if the watchdog was successfully started/stopped + */ +inline int metal_watchdog_run(const struct metal_watchdog *const wdog, + const enum metal_watchdog_run_option option) +{ + return wdog->vtable->run(wdog, option); +} + +/*! + * @brief Get the interrupt controller for the watchdog interrupt + */ +inline struct metal_interrupt *metal_watchdog_get_interrupt(const struct metal_watchdog *const wdog) +{ + return wdog->vtable->get_interrupt(wdog); +} + +/*! + * @Brief Get the interrupt id for the watchdog interrupt + */ +inline int metal_watchdog_get_interrupt_id(const struct metal_watchdog *const wdog) +{ + return wdog->vtable->get_interrupt_id(wdog); +} + +/*! + * @brief Clear the watchdog interrupt + */ +inline int metal_watchdog_clear_interrupt(const struct metal_watchdog *const wdog) +{ + return wdog->vtable->clear_interrupt(wdog); +} + +/*! + * @brief Get a watchdog handle + */ +struct metal_watchdog *metal_watchdog_get_device(const int index); + +#endif /* METAL__WATCHDOG_H */ |