OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /neorv32/trunk/sw/lib/source
    from Rev 45 to Rev 47
    Reverse comparison

Rev 45 → Rev 47

/neorv32_cfu.c File deleted
/neorv32_cfs.c
0,0 → 1,65
// #################################################################################################
// # << NEORV32: neorv32_cfs.c - Custom Functions Subsystem (CFS) HW Driver (stub) >> #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
// # #
// # 1. Redistributions of source code must retain the above copyright notice, this list of #
// # conditions and the following disclaimer. #
// # #
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
// # conditions and the following disclaimer in the documentation and/or other materials #
// # provided with the distribution. #
// # #
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
// # endorse or promote products derived from this software without specific prior written #
// # permission. #
// # #
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
// # OF THE POSSIBILITY OF SUCH DAMAGE. #
// # ********************************************************************************************* #
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
// #################################################################################################
 
 
/**********************************************************************//**
* @file neorv32_cfs.c
* @author Stephan Nolting
* @brief Custom Functions Subsystem (CFS) HW driver source file.
*
* @warning There are no "real" CFS driver functions available here, because these functions are defined by the actual hardware.
* @warning Hence, the CFS designer has to provide the actual driver functions.
*
* @note These functions should only be used if the CFS was synthesized (IO_CFS_EN = true).
**************************************************************************/
 
#include "neorv32.h"
#include "neorv32_cfs.h"
 
 
/**********************************************************************//**
* Check if custom functions unit 0 was synthesized.
*
* @return 0 if CFS was not synthesized, 1 if CFS is available.
**************************************************************************/
int neorv32_cfs_available(void) {
 
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_IO_CFS)) {
return 1;
}
else {
return 0;
}
}
 
/neorv32_cpu.c
47,11 → 47,31
/**********************************************************************//**
* >Private< helper functions.
**************************************************************************/
static int __neorv32_cpu_irq_id_check(uint8_t irq_sel);
static uint32_t __neorv32_cpu_pmp_cfg_read(uint32_t index);
static void __neorv32_cpu_pmp_cfg_write(uint32_t index, uint32_t data);
 
 
/**********************************************************************//**
* Private function: Check IRQ id.
*
* @param[in] irq_sel CPU interrupt select. See #NEORV32_CSR_MIE_enum.
* @return 0 if success, 1 if error (invalid irq_sel).
**************************************************************************/
static int __neorv32_cpu_irq_id_check(uint8_t irq_sel) {
 
if ((irq_sel == CSR_MIE_MSIE) || (irq_sel == CSR_MIE_MTIE) || (irq_sel == CSR_MIE_MEIE) ||
(irq_sel == CSR_MIE_FIRQ0E) || (irq_sel == CSR_MIE_FIRQ1E) || (irq_sel == CSR_MIE_FIRQ2E) || (irq_sel == CSR_MIE_FIRQ3E) ||
(irq_sel == CSR_MIE_FIRQ4E) || (irq_sel == CSR_MIE_FIRQ5E) || (irq_sel == CSR_MIE_FIRQ6E) || (irq_sel == CSR_MIE_FIRQ7E)) {
return 0;
}
else {
return 1;
}
}
 
 
/**********************************************************************//**
* Enable specific CPU interrupt.
*
* @note Interrupts have to be globally enabled via neorv32_cpu_eint(void), too.
61,8 → 81,8
**************************************************************************/
int neorv32_cpu_irq_enable(uint8_t irq_sel) {
 
if ((irq_sel != CSR_MIE_MSIE) && (irq_sel != CSR_MIE_MTIE) && (irq_sel != CSR_MIE_MEIE) &&
(irq_sel != CSR_MIE_FIRQ0E) && (irq_sel != CSR_MIE_FIRQ1E) && (irq_sel != CSR_MIE_FIRQ2E) && (irq_sel != CSR_MIE_FIRQ3E)) {
// check IRQ id
if (__neorv32_cpu_irq_id_check(irq_sel)) {
return 1;
}
 
80,8 → 100,8
**************************************************************************/
int neorv32_cpu_irq_disable(uint8_t irq_sel) {
 
if ((irq_sel != CSR_MIE_MSIE) && (irq_sel != CSR_MIE_MTIE) && (irq_sel != CSR_MIE_MEIE) &&
(irq_sel != CSR_MIE_FIRQ0E) && (irq_sel != CSR_MIE_FIRQ1E) && (irq_sel != CSR_MIE_FIRQ2E) && (irq_sel != CSR_MIE_FIRQ3E)) {
// check IRQ id
if (__neorv32_cpu_irq_id_check(irq_sel)) {
return 1;
}
 
/neorv32_rte.c
45,7 → 45,7
/**********************************************************************//**
* The >private< trap vector look-up table of the NEORV32 RTE.
**************************************************************************/
static uint32_t __neorv32_rte_vector_lut[17] __attribute__((unused)); // trap handler vector table
static uint32_t __neorv32_rte_vector_lut[21] __attribute__((unused)); // trap handler vector table
 
// private functions
static void __attribute__((__interrupt__)) __neorv32_rte_core(void) __attribute__((aligned(16))) __attribute__((unused));
52,6 → 52,7
static void __neorv32_rte_debug_exc_handler(void) __attribute__((unused));
static void __neorv32_rte_print_true_false(int state) __attribute__((unused));
static void __neorv32_rte_print_hex_word(uint32_t num);
static int __neorv32_rte_check_exc_id(uint32_t id);
 
 
/**********************************************************************//**
93,14 → 94,8
int neorv32_rte_exception_install(uint8_t id, void (*handler)(void)) {
 
// id valid?
if ((id == RTE_TRAP_I_MISALIGNED) || (id == RTE_TRAP_I_ACCESS) || (id == RTE_TRAP_I_ILLEGAL) ||
(id == RTE_TRAP_BREAKPOINT) || (id == RTE_TRAP_L_MISALIGNED) || (id == RTE_TRAP_L_ACCESS) ||
(id == RTE_TRAP_S_MISALIGNED) || (id == RTE_TRAP_S_ACCESS) || (id == RTE_TRAP_MENV_CALL) || (id == RTE_TRAP_UENV_CALL) ||
(id == RTE_TRAP_MSI) || (id == RTE_TRAP_MTI) || (id == RTE_TRAP_MEI) ||
(id == RTE_TRAP_FIRQ_0) || (id == RTE_TRAP_FIRQ_1) || (id == RTE_TRAP_FIRQ_2) || (id == RTE_TRAP_FIRQ_3)) {
 
if (__neorv32_rte_check_exc_id(id) == 0) {
__neorv32_rte_vector_lut[id] = (uint32_t)handler; // install handler
 
return 0;
}
return 1;
120,14 → 115,8
int neorv32_rte_exception_uninstall(uint8_t id) {
 
// id valid?
if ((id == RTE_TRAP_I_MISALIGNED) || (id == RTE_TRAP_I_ACCESS) || (id == RTE_TRAP_I_ILLEGAL) ||
(id == RTE_TRAP_BREAKPOINT) || (id == RTE_TRAP_L_MISALIGNED) || (id == RTE_TRAP_L_ACCESS) ||
(id == RTE_TRAP_S_MISALIGNED) || (id == RTE_TRAP_S_ACCESS) || (id == RTE_TRAP_MENV_CALL) || (id == RTE_TRAP_UENV_CALL) ||
(id == RTE_TRAP_MSI) || (id == RTE_TRAP_MTI) || (id == RTE_TRAP_MEI) ||
(id == RTE_TRAP_FIRQ_0) || (id == RTE_TRAP_FIRQ_1) || (id == RTE_TRAP_FIRQ_2) || (id == RTE_TRAP_FIRQ_3)) {
 
if (__neorv32_rte_check_exc_id(id) == 0) {
__neorv32_rte_vector_lut[id] = (uint32_t)(&__neorv32_rte_debug_exc_handler); // use dummy handler in case the exception is accidently triggered
 
return 0;
}
return 1;
186,6 → 175,10
case TRAP_CODE_FIRQ_1: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_1]; break;
case TRAP_CODE_FIRQ_2: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_2]; break;
case TRAP_CODE_FIRQ_3: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_3]; break;
case TRAP_CODE_FIRQ_4: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_4]; break;
case TRAP_CODE_FIRQ_5: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_5]; break;
case TRAP_CODE_FIRQ_6: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_6]; break;
case TRAP_CODE_FIRQ_7: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_FIRQ_7]; break;
default: break;
}
 
221,10 → 214,14
case TRAP_CODE_MSI: neorv32_uart_print("Machine software interrupt"); break;
case TRAP_CODE_MTI: neorv32_uart_print("Machine timer interrupt"); break;
case TRAP_CODE_MEI: neorv32_uart_print("Machine external interrupt"); break;
case TRAP_CODE_FIRQ_0: neorv32_uart_print("Fast interrupt 0"); break;
case TRAP_CODE_FIRQ_1: neorv32_uart_print("Fast interrupt 1"); break;
case TRAP_CODE_FIRQ_2: neorv32_uart_print("Fast interrupt 2"); break;
case TRAP_CODE_FIRQ_3: neorv32_uart_print("Fast interrupt 3"); break;
case TRAP_CODE_FIRQ_0:
case TRAP_CODE_FIRQ_1:
case TRAP_CODE_FIRQ_2:
case TRAP_CODE_FIRQ_3:
case TRAP_CODE_FIRQ_4:
case TRAP_CODE_FIRQ_5:
case TRAP_CODE_FIRQ_6:
case TRAP_CODE_FIRQ_7: neorv32_uart_print("Fast interrupt "); neorv32_uart_putc((char)('0' + (trap_cause & 0x7))); break;
default: neorv32_uart_print("Unknown trap cause: "); __neorv32_rte_print_hex_word(trap_cause); break;
}
 
431,11 → 428,8
neorv32_uart_printf("TRNG - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_TRNG));
 
neorv32_uart_printf("CFU0 - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_CFU0));
 
neorv32_uart_printf("CFU1 - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_CFU1));
neorv32_uart_printf("CFS - ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_CFS));
}
 
 
476,7 → 470,31
}
 
 
/**********************************************************************//**
* NEORV32 runtime environment: Private function to check exception id
* as 8-digit hexadecimal value (with "0x" suffix).
*
* @param[in] id Exception id (#NEORV32_RTE_TRAP_enum).
* @return Return 0 if id is valid
**************************************************************************/
static int __neorv32_rte_check_exc_id(uint32_t id) {
 
// id valid?
if ((id == RTE_TRAP_I_MISALIGNED) || (id == RTE_TRAP_I_ACCESS) || (id == RTE_TRAP_I_ILLEGAL) ||
(id == RTE_TRAP_BREAKPOINT) || (id == RTE_TRAP_L_MISALIGNED) || (id == RTE_TRAP_L_ACCESS) ||
(id == RTE_TRAP_S_MISALIGNED) || (id == RTE_TRAP_S_ACCESS) || (id == RTE_TRAP_MENV_CALL) || (id == RTE_TRAP_UENV_CALL) ||
(id == RTE_TRAP_MSI) || (id == RTE_TRAP_MTI) || (id == RTE_TRAP_MEI) ||
(id == RTE_TRAP_FIRQ_0) || (id == RTE_TRAP_FIRQ_1) || (id == RTE_TRAP_FIRQ_2) || (id == RTE_TRAP_FIRQ_3) ||
(id == RTE_TRAP_FIRQ_4) || (id == RTE_TRAP_FIRQ_5) || (id == RTE_TRAP_FIRQ_6) || (id == RTE_TRAP_FIRQ_7)) {
return 0;
}
else {
return 1;
}
}
 
 
 
/**********************************************************************//**
* NEORV32 runtime environment: Print the processor version in human-readable format.
**************************************************************************/
547,12 → 565,13
for (v=0; v<4; v++) {
tmp = logo_data_c[u][v];
for (w=0; w<32; w++){
if (tmp & (1 << (31-w))) {
if (tmp & 0x80000000UL) { // check MSB
neorv32_uart_putc('#');
}
else {
neorv32_uart_putc(' ');
}
tmp <<= 1;
}
}
}
/neorv32_trng.c
70,13 → 70,13
 
TRNG_CT = 0; // reset
 
for (i=0; i<1000; i++) {
for (i=0; i<256; i++) {
asm volatile ("nop");
}
 
TRNG_CT = 1 << TRNG_CT_EN; // activate
 
for (i=0; i<1000; i++) {
for (i=0; i<256; i++) {
asm volatile ("nop");
}
}
87,37 → 87,32
**************************************************************************/
void neorv32_trng_disable(void) {
 
TRNG_CT &= ~((uint32_t)(1 << TRNG_CT_EN));
TRNG_CT = 0;
}
 
 
/**********************************************************************//**
* Get random data from TRNG.
* Get random data byte from TRNG.
*
* @note The TRNG is automatically reset if a stuck-at-one/stuck-at-zero error is detected.
*
* @param[in,out] data uint8_t pointer for storing random data word
* @return Data is valid when 0, stuck-at-zero error when 1, stuck-at-one error when 2, data not (yet) valid when 3
* @param[in,out] data uint8_t pointer for storing random data byte.
* @return Data is valid when 0 and invalid otherwise.
**************************************************************************/
int neorv32_trng_get(uint8_t *data) {
 
uint32_t trng_ct_reg = TRNG_CT;
const int retries = 3;
int i;
uint32_t ct_reg;
 
if (trng_ct_reg & (1<<TRNG_CT_ERROR_0)) { // stuck at zero error
neorv32_trng_enable(); // reset TRNG
return 1;
}
for (i=0; i<retries; i++) {
ct_reg = TRNG_CT;
 
if (trng_ct_reg & (1<<TRNG_CT_ERROR_1)) { // stuck at one error
neorv32_trng_enable(); // reset TRNG
return 2;
}
if ((ct_reg & (1<<TRNG_CT_VALID)) == 0) { // output data valid?
continue;
}
 
if ((trng_ct_reg & (1<<TRNG_CT_VALID)) == 0) { // output data valid (yet)?
return 3;
*data = (uint8_t)(ct_reg >> TRNG_CT_DATA_LSB);
return 0; // valid data
}
 
*data = (uint8_t)(trng_ct_reg >> TRNG_CT_DATA_LSB);
return 0; // valid data
return -1; // no valid data available
}
 
/neorv32_uart.c
71,9 → 71,11
/**********************************************************************//**
* Enable and configure UART.
*
* @warning The 'UART_SIM_MODE' compiler flag will configure UART for simulation mode: all UART TX data will be redirected to simulation output. Use this for simulations only!
* @warning To enable simulation mode add <USER_FLAGS+=-DUART_SIM_MODE> when compiling.
* @note The 'UART_SIM_MODE' compiler flag will configure UART for simulation mode: all UART TX data will be redirected to simulation output. Use this for simulations only!
* @note To enable simulation mode add <USER_FLAGS+=-DUART_SIM_MODE> when compiling.
*
* @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
*
* @param[in] baudrate Targeted BAUD rate (e.g. 9600).
* @param[in] parity PArity configuration (00=off, 10=even, 11=odd).
* @param[in] rx_irq Enable RX interrupt (data received) when 1.
99,7 → 101,7
}
#endif
 
// find clock prsc
// find baud prescaler (12-bit wide))
while (i >= 0x0fff) {
if ((p == 2) || (p == 4))
i >>= 3;
108,11 → 110,12
p++;
}
 
uint32_t prsc = (uint32_t)p;
prsc = prsc << UART_CT_PRSC0;
uint32_t clk_prsc = (uint32_t)p;
clk_prsc = clk_prsc << UART_CT_PRSC0;
 
uint32_t baud = (uint32_t)i;
baud = baud << UART_CT_BAUD00;
uint32_t baud_prsc = (uint32_t)i;
baud_prsc = baud_prsc - 1;
baud_prsc = baud_prsc << UART_CT_BAUD00;
 
uint32_t uart_en = 1;
uart_en = uart_en << UART_CT_EN;
135,7 → 138,7
uint32_t sim_mode = 0;
#endif
 
UART_CT = prsc | baud | uart_en | parity_config | rx_irq_en | tx_irq_en | sim_mode;
UART_CT = clk_prsc | baud_prsc | uart_en | parity_config | rx_irq_en | tx_irq_en | sim_mode;
}
 
 
/neorv32_wdt.c
62,34 → 62,48
 
 
/**********************************************************************//**
* Enable and configure watchdog timer. The WDT control register bits are listed in #NEORV32_WDT_CT_enum.
* Configure and enable watchdog timer. The WDT control register bits are listed in #NEORV32_WDT_CT_enum.
*
* @param[in] clk_prsc Clock prescaler to selet timeout interval. See #NEORV32_CLOCK_PRSC_enum.
* @param[in] timeout_mode Trigger system reset on timeout when 1, trigger interrupt on timeout when 0.
* @param[in] prsc Clock prescaler to selet timeout interval. See #NEORV32_CLOCK_PRSC_enum.
* @param[in] mode Trigger system reset on timeout when 1, trigger interrupt on timeout when 0.
* @param[in] lock Control register will be locked when 1 (unitl next reset).
**************************************************************************/
void neorv32_wdt_setup(uint8_t clk_prsc, uint8_t timeout_mode) {
void neorv32_wdt_setup(uint8_t prsc, uint8_t mode, uint8_t lock) {
 
uint32_t prsc = (uint32_t)(clk_prsc & 0x07);
prsc = prsc << WDT_CT_CLK_SEL0;
WDT_CT = (1 << WDT_CT_RESET); // reset WDT counter
 
uint32_t mode = (uint32_t)(timeout_mode & 0x01);
mode = mode << WDT_CT_MODE;
uint32_t prsc_int = (uint32_t)(prsc & 0x07);
prsc_int = prsc_int << WDT_CT_CLK_SEL0;
 
uint32_t password = (uint32_t)(WDT_PASSWORD);
password = password << WDT_CT_PASSWORD_LSB;
uint32_t mode_int = (uint32_t)(mode & 0x01);
mode_int = mode_int << WDT_CT_MODE;
 
uint32_t enable = (uint32_t)(1 << WDT_CT_EN);
uint32_t lock_int = (uint32_t)(lock & 0x01);
lock_int = lock_int << WDT_CT_LOCK;
 
WDT_CT = password | enable | mode | prsc;
const uint32_t enable = (uint32_t)(1 << WDT_CT_EN);
 
// update WDT control register
WDT_CT = enable | mode_int | prsc_int | lock_int;
}
 
 
/**********************************************************************//**
* Disable watchdog timer.
*
* @return Returns 0 if WDT is really deativated, -1 otherwise.
**************************************************************************/
void neorv32_wdt_disable(void) {
int neorv32_wdt_disable(void) {
WDT_CT = 0;
 
WDT_CT = ((uint32_t)(WDT_PASSWORD << WDT_CT_PASSWORD_LSB)) | ((uint32_t)(0 << WDT_CT_EN));
// check if wdt is really off
if (WDT_CT & (1 << WDT_CT_EN)) {
return -1; // WDT still active
}
else {
return 0;
}
}
 
 
98,38 → 112,30
**************************************************************************/
void neorv32_wdt_reset(void) {
 
WDT_CT = WDT_CT | ((uint32_t)(WDT_PASSWORD << WDT_CT_PASSWORD_LSB));
WDT_CT = (1 << WDT_CT_RESET);
}
 
 
/**********************************************************************//**
* Get cause of last watchdog action.
* Get cause of last system reset.
*
* @return Cause of last reset/IRQ (0: undefined, 1: external reset, 2: watchdog timeout, 3: watchdog access error (wrong password)).
* @return Cause of last reset/IRQ (0: external reset, 1: watchdog timeout).
**************************************************************************/
uint8_t neorv32_wdt_get_cause(void) {
int neorv32_wdt_get_cause(void) {
 
uint8_t cause = 0;
uint32_t ctrl = WDT_CT;
if (ctrl & (1 << WDT_CT_CAUSE)) { // reset/IRQ casued by watchdog
if (ctrl & (1 << WDT_CT_PWFAIL)) { // reset/IRQ due to wrong password
cause = 3;
}
else { // reset/IRQ due to timeout
cause = 2;
}
if (WDT_CT & (1 << WDT_CT_RCAUSE)) { // reset caused by watchdog
return 1;
}
else { // external reset
cause = 1;
return 0;
}
return cause;
}
 
 
/**********************************************************************//**
* Force watchdog action (reset/IRQ) via wrong-password access.
* Force immediate watchdog action (reset/IRQ).
**************************************************************************/
void neorv32_wdt_force(void) {
 
WDT_CT = 0; // invalid access
WDT_CT = WDT_CT | (1 << WDT_CT_FORCE);
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.