diff options
Diffstat (limited to 'FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_util.c')
-rw-r--r-- | FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_util.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_util.c b/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_util.c new file mode 100644 index 000000000..cb706149d --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_RV64_PolarFire_SoftConsole/polarfire_hal/platform/mpfs_hal/common/mss_util.c @@ -0,0 +1,226 @@ +/******************************************************************************* + * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions. + * + * SPDX-License-Identifier: MIT + * + * MPFS HAL Embedded Software + * + */ + +/*************************************************************************** + * @file mss_util.c + * @author Microchip-FPGA Embedded Systems Solutions + * @brief Utility functions + * + */ +#include <stddef.h> +#include <stdbool.h> +#include "mpfs_hal/mss_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*------------------------------------------------------------------------------ + * + */ +void enable_interrupts(void) { + __enable_irq(); +} + +/*------------------------------------------------------------------------------ + * + */ +uint64_t disable_interrupts(void) { + uint64_t psr; + psr = read_csr(mstatus); + __disable_irq(); + return(psr); +} + +/*------------------------------------------------------------------------------ + * + */ +void restore_interrupts(uint64_t saved_psr) { + write_csr(mstatus, saved_psr); +} + +/*------------------------------------------------------------------------------ + * Disable all interrupts. + */ +void __disable_irq(void) +{ + clear_csr(mstatus, MSTATUS_MIE); + clear_csr(mstatus, MSTATUS_MPIE); +} + +void __disable_all_irqs(void) +{ + __disable_irq(); + write_csr(mie, 0x00U); + write_csr(mip, 0x00); +} + +/*------------------------------------------------------------------------------ + * Enable all interrupts. + */ +void __enable_irq(void) +{ + set_csr(mstatus, MSTATUS_MIE); /* mstatus Register- Machine Interrupt Enable */ +} + +/*------------------------------------------------------------------------------ + * Enable particular local interrupt + */ +void __enable_local_irq(uint8_t local_interrupt) +{ + if((local_interrupt > (int8_t)0) && (local_interrupt <= LOCAL_INT_MAX)) + { + set_csr(mie, (0x1LLU << (int8_t)(local_interrupt + 16U))); /* mie Register- Machine Interrupt Enable Register */ + } +} + +/*------------------------------------------------------------------------------ + * Disable particular local interrupt + */ +void __disable_local_irq(uint8_t local_interrupt) +{ + if((local_interrupt > (int8_t)0) && (local_interrupt <= LOCAL_INT_MAX)) + { + clear_csr(mie, (0x1LLU << (int8_t)(local_interrupt + 16U))); /* mie Register- Machine Interrupt Enable Register */ + } +} + +/** + * readmcycle(void) + * @return returns the mcycle count from hart CSR + */ +uint64_t readmcycle(void) +{ + return (read_csr(mcycle)); +} + +void sleep_ms(uint64_t msecs) +{ + uint64_t starttime = readmtime(); + volatile uint64_t endtime = 0U; + + while(endtime < (starttime+msecs)) { + endtime = readmtime(); + } +} + +/** + * sleep_cycles(uint64_t ncycles) + * @param number of cycles to sleep + */ +void sleep_cycles(uint64_t ncycles) +{ + uint64_t starttime = readmcycle(); + volatile uint64_t endtime = 0U; + + while(endtime < (starttime + ncycles)) { + endtime = readmcycle(); + } +} + +/** + * get_program_counter(void) + * @return returns the program counter + */ +__attribute__((aligned(16))) uint64_t get_program_counter(void) +{ + uint64_t prog_counter; + asm volatile ("auipc %0, 0" : "=r"(prog_counter)); + return (prog_counter); +} + +/** + * get_stack_pointer(void) + * @return Return the stack pointer + */ +uint64_t get_stack_pointer(void) +{ + uint64_t stack_pointer; + asm volatile ("addi %0, sp, 0" : "=r"(stack_pointer)); + return (stack_pointer); +} + +/** + * Return the tp register + * The tp register holds the value of the Hart Common memory HLS once not in an + * interrupt. If the tp value is used in an interrupt, it is saved first and + * restored on exit. This conforms to OpenSBI implementation. + * + * @return returns the tp register value + */ +uint64_t get_tp_reg(void) +{ + uint64_t tp_reg_val; + asm volatile ("addi %0, tp, 0" : "=r"(tp_reg_val)); + return (tp_reg_val); +} + +/** + * mpfs_sync_bool_compare_and_swap() + * this works on the E51 / U54s, and operates equivalently to the + * __sync_bool_compare_and_swap() intrinsic. + * @param ptr + * @param oldval + * @param newval + * @return + */ +bool mpfs_sync_bool_compare_and_swap(volatile long *ptr, long oldval, long newval) +{ + static long lock = 0; + bool result = false; + + if (!__sync_lock_test_and_set(&lock, 1)) { // amoswap.d.aq + if (*ptr == oldval) { + *ptr = newval; + } + + __sync_lock_release(&lock); // fence iorw,ow; ampswap.d + result = true; + } + + return result; +} + +/** + * mpfs_sync_val_compare_and_swap() + * this works on the E51 / U54s, and operates equivalently to the + * __sync_val_compare_and_swap() intrinsic. It works by using a separate + * static lock, and then emulating the behaviour of the lr.w.aq instruction + * Required as lr/sr instructions are not supported on the E51 and are only + * supported on L1 cached back memory types. These limitations are not present + * with this function. + * @param ptr + * @param oldval + * @param newval + */ +long mpfs_sync_val_compare_and_swap(volatile long *ptr, long oldval, long newval) +{ + long result = *ptr; + + (void)mpfs_sync_bool_compare_and_swap(ptr, oldval, newval); + + return result; +} + +#ifdef PRINTF_DEBUG_SUPPORTED +void display_address_of_interest(uint64_t * address_of_interest, int nb_locations) { + uint64_t * p_addr_of_interest = address_of_interest; + int inc; + mpfs_printf(" Displaying address of interest: 0x%lx\n", p_addr_of_interest); + + for (inc = 0U; inc < nb_locations; ++inc) { + mpfs_printf(" address of interest: 0x%lx: 0x%lx\n", p_addr_of_interest, *p_addr_of_interest); + p_addr_of_interest = p_addr_of_interest + 8; + } +} +#endif + +#ifdef __cplusplus +} +#endif |