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 64 to Rev 65
- ↔ Reverse comparison
Rev 64 → Rev 65
/neorv32_cpu.c
354,9 → 354,9
uint32_t i = 0; |
|
// try setting R bit in all PMPCFG CSRs |
const uint32_t tmp = 0x01010101; |
const uint32_t mask = 0x01010101; |
for (i=0; i<16; i++) { |
__neorv32_cpu_pmp_cfg_write(i, tmp); |
__neorv32_cpu_pmp_cfg_write(i, mask); |
} |
|
// sum up all written ones (only available PMPCFG* CSRs/entries will return =! 0) |
367,7 → 367,7
|
cnt.uint32 = 0; |
for (i=0; i<16; i++) { |
cnt.uint32 += __neorv32_cpu_pmp_cfg_read(i); |
cnt.uint32 += __neorv32_cpu_pmp_cfg_read(i) & mask; |
} |
|
// sum up bytes |
/neorv32_rte.c
51,6 → 51,7
static void __attribute__((__interrupt__)) __neorv32_rte_core(void) __attribute__((aligned(16))); |
static void __neorv32_rte_debug_exc_handler(void); |
static void __neorv32_rte_print_true_false(int state); |
static void __neorv32_rte_print_checkbox(int state); |
static void __neorv32_rte_print_hex_word(uint32_t num); |
|
|
204,7 → 205,7
char tmp; |
|
// intro |
neorv32_uart_print("<RTE> "); |
neorv32_uart0_print("<RTE> "); |
|
// cause |
register uint32_t trap_cause = neorv32_cpu_csr_read(CSR_MCAUSE); |
216,19 → 217,19
tmp = '0' + tmp; |
} |
switch (trap_cause) { |
case TRAP_CODE_I_MISALIGNED: neorv32_uart_print("Instruction address misaligned"); break; |
case TRAP_CODE_I_ACCESS: neorv32_uart_print("Instruction access fault"); break; |
case TRAP_CODE_I_ILLEGAL: neorv32_uart_print("Illegal instruction"); break; |
case TRAP_CODE_BREAKPOINT: neorv32_uart_print("Breakpoint"); break; |
case TRAP_CODE_L_MISALIGNED: neorv32_uart_print("Load address misaligned"); break; |
case TRAP_CODE_L_ACCESS: neorv32_uart_print("Load access fault"); break; |
case TRAP_CODE_S_MISALIGNED: neorv32_uart_print("Store address misaligned"); break; |
case TRAP_CODE_S_ACCESS: neorv32_uart_print("Store access fault"); break; |
case TRAP_CODE_UENV_CALL: neorv32_uart_print("Environment call from U-mode"); break; |
case TRAP_CODE_MENV_CALL: neorv32_uart_print("Environment call from M-mode"); break; |
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_I_MISALIGNED: neorv32_uart0_print("Instruction address misaligned"); break; |
case TRAP_CODE_I_ACCESS: neorv32_uart0_print("Instruction access fault"); break; |
case TRAP_CODE_I_ILLEGAL: neorv32_uart0_print("Illegal instruction"); break; |
case TRAP_CODE_BREAKPOINT: neorv32_uart0_print("Breakpoint"); break; |
case TRAP_CODE_L_MISALIGNED: neorv32_uart0_print("Load address misaligned"); break; |
case TRAP_CODE_L_ACCESS: neorv32_uart0_print("Load access fault"); break; |
case TRAP_CODE_S_MISALIGNED: neorv32_uart0_print("Store address misaligned"); break; |
case TRAP_CODE_S_ACCESS: neorv32_uart0_print("Store access fault"); break; |
case TRAP_CODE_UENV_CALL: neorv32_uart0_print("Environment call from U-mode"); break; |
case TRAP_CODE_MENV_CALL: neorv32_uart0_print("Environment call from M-mode"); break; |
case TRAP_CODE_MSI: neorv32_uart0_print("Machine software interrupt"); break; |
case TRAP_CODE_MTI: neorv32_uart0_print("Machine timer interrupt"); break; |
case TRAP_CODE_MEI: neorv32_uart0_print("Machine external interrupt"); break; |
case TRAP_CODE_FIRQ_0: |
case TRAP_CODE_FIRQ_1: |
case TRAP_CODE_FIRQ_2: |
244,18 → 245,18
case TRAP_CODE_FIRQ_12: |
case TRAP_CODE_FIRQ_13: |
case TRAP_CODE_FIRQ_14: |
case TRAP_CODE_FIRQ_15: neorv32_uart_print("Fast interrupt "); neorv32_uart_putc(tmp); break; |
default: neorv32_uart_print("Unknown trap cause: "); __neorv32_rte_print_hex_word(trap_cause); break; |
case TRAP_CODE_FIRQ_15: neorv32_uart0_print("Fast interrupt "); neorv32_uart0_putc(tmp); break; |
default: neorv32_uart0_print("Unknown trap cause: "); __neorv32_rte_print_hex_word(trap_cause); break; |
} |
|
// instruction address |
neorv32_uart_print(" @ PC="); |
neorv32_uart0_print(" @ PC="); |
__neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MSCRATCH)); // rte core stores actual mepc to mscratch |
|
// additional info |
neorv32_uart_print(", MTVAL="); |
neorv32_uart0_print(", MTVAL="); |
__neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MTVAL)); |
neorv32_uart_print(" </RTE>"); |
neorv32_uart0_print(" </RTE>"); |
} |
|
|
272,25 → 273,15
int i; |
char c; |
|
neorv32_uart_printf("\n\n<<< Processor Configuration Overview >>>\n"); |
neorv32_uart0_printf("\n\n<<< Processor Configuration Overview >>>\n"); |
|
// Processor - general stuff |
neorv32_uart0_printf("\n=== << General >> ===\n" |
"Clock speed: %u Hz\n", NEORV32_SYSINFO.CLK); |
neorv32_uart0_printf("Full HW reset: "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_HW_RESET)); |
neorv32_uart0_printf("Boot Config.: Boot "); |
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_BOOTLOADER)) { |
neorv32_uart0_printf("via Bootloader\n"); |
} |
else { |
neorv32_uart0_printf("from memory (@ 0x%x)\n", NEORV32_SYSINFO.ISPACE_BASE); |
} |
neorv32_uart0_printf("On-chip debug: "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_OCD)); |
|
|
// CPU configuration |
neorv32_uart0_printf("\n=== << CPU >> ===\n"); |
|
// general |
neorv32_uart0_printf("Clock speed: %u Hz\n", NEORV32_SYSINFO.CLK); |
neorv32_uart0_printf("Full HW reset: "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_HW_RESET)); |
neorv32_uart0_printf("On-chip debugger: "); __neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_OCD)); |
// ID |
neorv32_uart0_printf("Hart ID: 0x%x\n" |
"Vendor ID: 0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID), neorv32_cpu_csr_read(CSR_MVENDORID)); |
378,8 → 369,16
|
|
// Memory configuration |
neorv32_uart0_printf("\n=== << Memory Configuration >> ===\n"); |
neorv32_uart0_printf("\n=== << Memory System >> ===\n"); |
|
neorv32_uart0_printf("Boot Config.: Boot "); |
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_BOOTLOADER)) { |
neorv32_uart0_printf("via Bootloader\n"); |
} |
else { |
neorv32_uart0_printf("from memory (@ 0x%x)\n", NEORV32_SYSINFO.ISPACE_BASE); |
} |
|
neorv32_uart0_printf("Instr. base address: 0x%x\n", NEORV32_SYSINFO.ISPACE_BASE); |
|
// IMEM |
394,14 → 393,17
// DMEM |
neorv32_uart0_printf("Data base address: 0x%x\n", NEORV32_SYSINFO.DSPACE_BASE); |
neorv32_uart0_printf("Internal DMEM: "); |
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_DMEM)) { neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.DMEM_SIZE); } |
else { neorv32_uart0_printf("no\n"); } |
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_INT_DMEM)) { |
neorv32_uart0_printf("yes, %u bytes\n", NEORV32_SYSINFO.DMEM_SIZE); |
} |
else { |
neorv32_uart0_printf("no\n"); |
} |
|
// i-cache |
neorv32_uart0_printf("Internal i-cache: "); |
__neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_ICACHE)); |
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_ICACHE)) { |
neorv32_uart0_printf("- "); |
neorv32_uart0_printf("yes, "); |
|
uint32_t ic_block_size = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_BLOCK_SIZE_0) & 0x0F; |
if (ic_block_size) { |
422,7 → 424,7
uint32_t ic_associativity = (NEORV32_SYSINFO.CACHE >> SYSINFO_CACHE_IC_ASSOCIATIVITY_0) & 0x0F; |
ic_associativity = 1 << ic_associativity; |
|
neorv32_uart0_printf("%u bytes: %u set(s), %u block(s) per set, %u bytes per block", ic_associativity*ic_num_blocks*ic_block_size, ic_associativity, ic_num_blocks, ic_block_size); |
neorv32_uart0_printf("%u bytes, %u set(s), %u block(s) per set, %u bytes per block", ic_associativity*ic_num_blocks*ic_block_size, ic_associativity, ic_num_blocks, ic_block_size); |
if (ic_associativity == 1) { |
neorv32_uart0_printf(" (direct-mapped)\n"); |
} |
433,6 → 435,9
neorv32_uart0_printf("\n"); |
} |
} |
else { |
neorv32_uart0_printf("no\n"); |
} |
|
neorv32_uart0_printf("Ext. bus interface: "); |
__neorv32_rte_print_true_false(NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT)); |
448,19 → 453,19
neorv32_uart0_printf("\n=== << Peripherals >> ===\n"); |
|
tmp = NEORV32_SYSINFO.SOC; |
neorv32_uart0_printf("GPIO - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_GPIO)); |
neorv32_uart0_printf("MTIME - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_MTIME)); |
neorv32_uart0_printf("UART0 - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_UART0)); |
neorv32_uart0_printf("UART1 - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_UART1)); |
neorv32_uart0_printf("SPI - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_SPI)); |
neorv32_uart0_printf("TWI - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_TWI)); |
neorv32_uart0_printf("PWM - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_PWM)); |
neorv32_uart0_printf("WDT - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_WDT)); |
neorv32_uart0_printf("TRNG - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_TRNG)); |
neorv32_uart0_printf("CFS - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_CFS)); |
neorv32_uart0_printf("SLINK - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_SLINK)); |
neorv32_uart0_printf("NEOLED - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_NEOLED)); |
neorv32_uart0_printf("XIRQ - "); __neorv32_rte_print_true_false(tmp & (1 << SYSINFO_SOC_IO_XIRQ)); |
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_GPIO)); neorv32_uart0_printf(" GPIO\n"); |
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_MTIME)); neorv32_uart0_printf(" MTIME\n"); |
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_UART0)); neorv32_uart0_printf(" UART0\n"); |
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_UART1)); neorv32_uart0_printf(" UART1\n"); |
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_SPI)); neorv32_uart0_printf(" SPI\n"); |
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_TWI)); neorv32_uart0_printf(" TWI\n"); |
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_PWM)); neorv32_uart0_printf(" PWM\n"); |
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_WDT)); neorv32_uart0_printf(" WDT\n"); |
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_TRNG)); neorv32_uart0_printf(" TRNG\n"); |
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_CFS)); neorv32_uart0_printf(" CFS\n"); |
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_SLINK)); neorv32_uart0_printf(" SLINK\n"); |
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_NEOLED)); neorv32_uart0_printf(" NEOLED\n"); |
__neorv32_rte_print_checkbox(tmp & (1 << SYSINFO_SOC_IO_XIRQ)); neorv32_uart0_printf(" XIRQ\n"); |
} |
|
|
468,7 → 473,7
* NEORV32 runtime environment: Private function to print yes or no. |
* @note This function is used by neorv32_rte_print_hw_config(void) only. |
* |
* @param[in] state Print 'yes' when !=0, print '0' when 0 |
* @param[in] state Print 'yes' when !=0, print 'no' when 0 |
**************************************************************************/ |
static void __neorv32_rte_print_true_false(int state) { |
|
482,6 → 487,25
|
|
/**********************************************************************//** |
* NEORV32 runtime environment: Private function to print [x] or [ ]. |
* @note This function is used by neorv32_rte_print_hw_config(void) only. |
* |
* @param[in] state Print '[x]' when !=0, print '[ ]' when 0 |
**************************************************************************/ |
static void __neorv32_rte_print_checkbox(int state) { |
|
neorv32_uart0_putc('['); |
if (state) { |
neorv32_uart0_putc('x'); |
} |
else { |
neorv32_uart0_putc(' '); |
} |
neorv32_uart0_putc(']'); |
} |
|
|
/**********************************************************************//** |
* NEORV32 runtime environment: Private function to print 32-bit number |
* as 8-digit hexadecimal value (with "0x" suffix). |
* |
606,7 → 630,7
return; // cannot output anything if UART0 is not implemented |
} |
|
neorv32_uart_print( |
neorv32_uart0_print( |
"\n" |
"BSD 3-Clause License\n" |
"\n" |
712,7 → 736,7
} |
else { |
if ((silent == 0) || (neorv32_uart0_available() == 0)) { |
neorv32_uart_printf("\nWARNING! SW_ISA (features required) vs HW_ISA (features available) mismatch!\n" |
neorv32_uart0_printf("\nWARNING! SW_ISA (features required) vs HW_ISA (features available) mismatch!\n" |
"SW_ISA = 0x%x (compiler flags)\n" |
"HW_ISA = 0x%x (misa csr)\n\n", misa_sw, misa_hw); |
} |
/neorv32_slink.c
80,6 → 80,72
|
|
/**********************************************************************//** |
* Configure SLINK RX interrupt. |
* |
* @param[in] link_id Link id (0..7). |
* @param[in] irq_en Link's IRQ enable (#NEORV32_SLINK_IRQ_EN_enum) |
* @param[in] irq_type Link's IRQ type (#NEORV32_SLINK_IRQ_RX_TYPE_enum) |
**************************************************************************/ |
void neorv32_slink_rx_irq_config(int link_id, int irq_en, int irq_type) { |
|
link_id = link_id & 7; |
|
uint32_t slink_irq_conf = NEORV32_SLINK.IRQ; |
|
// enable IRQ |
if (irq_en) { |
slink_irq_conf |= (1 << (SLINK_IRQ_RX_EN_LSB + link_id)); |
} |
else { |
slink_irq_conf &= ~(1 << (SLINK_IRQ_RX_EN_LSB + link_id)); |
} |
|
// configure type |
if (irq_type) { |
slink_irq_conf |= (1 << (SLINK_IRQ_RX_MODE_LSB + link_id)); |
} |
else { |
slink_irq_conf &= ~(1 << (SLINK_IRQ_RX_MODE_LSB + link_id)); |
} |
|
NEORV32_SLINK.IRQ = slink_irq_conf; |
} |
|
|
/**********************************************************************//** |
* Configure SLINK TX interrupt. |
* |
* @param[in] link_id Link id (0..7). |
* @param[in] irq_en Link's IRQ enable (#NEORV32_SLINK_IRQ_EN_enum) |
* @param[in] irq_type Link's IRQ type (#NEORV32_SLINK_IRQ_TX_TYPE_enum) |
**************************************************************************/ |
void neorv32_slink_tx_irq_config(int link_id, int irq_en, int irq_type) { |
|
link_id = link_id & 7; |
|
uint32_t slink_irq_conf = NEORV32_SLINK.IRQ; |
|
// enable IRQ |
if (irq_en) { |
slink_irq_conf |= (1 << (SLINK_IRQ_TX_EN_LSB + link_id)); |
} |
else { |
slink_irq_conf &= ~(1 << (SLINK_IRQ_TX_EN_LSB + link_id)); |
} |
|
// configure type |
if (irq_type) { |
slink_irq_conf |= (1 << (SLINK_IRQ_TX_MODE_LSB + link_id)); |
} |
else { |
slink_irq_conf &= ~(1 << (SLINK_IRQ_TX_MODE_LSB + link_id)); |
} |
|
NEORV32_SLINK.IRQ = slink_irq_conf; |
} |
|
|
/**********************************************************************//** |
* Get number of implemented RX links |
* |
* @return Number of implemented RX link (0..8). |
/neorv32_spi.c
65,10 → 65,11
* Enable and configure SPI controller. The SPI control register bits are listed in #NEORV32_SPI_CTRL_enum. |
* |
* @param[in] prsc Clock prescaler select (0..7). See #NEORV32_CLOCK_PRSC_enum. |
* @param[in] clk_polarity Idle clock polarity (0, 1). |
* @param[in] clk_phase Clock phase (0=sample on rising edge, 1=sample on falling edge). |
* @param[in] clk_polarity Clock polarity (when idle). |
* @param[in] data_size Data transfer size (0: 8-bit, 1: 16-bit, 2: 24-bit, 3: 32-bit). |
**************************************************************************/ |
void neorv32_spi_setup(uint8_t prsc, uint8_t clk_polarity, uint8_t data_size) { |
void neorv32_spi_setup(uint8_t prsc, uint8_t clk_phase, uint8_t clk_polarity, uint8_t data_size) { |
|
NEORV32_SPI.CTRL = 0; // reset |
|
78,13 → 79,16
uint32_t ct_prsc = (uint32_t)(prsc & 0x07); |
ct_prsc = ct_prsc << SPI_CTRL_PRSC0; |
|
uint32_t ct_phase = (uint32_t)(clk_phase & 0x01); |
ct_phase = ct_phase << SPI_CTRL_CPHA; |
|
uint32_t ct_polarity = (uint32_t)(clk_polarity & 0x01); |
ct_polarity = ct_polarity << SPI_CTRL_CPHA; |
ct_polarity = ct_polarity << SPI_CTRL_CPOL; |
|
uint32_t ct_size = (uint32_t)(data_size & 0x03); |
ct_size = ct_size << SPI_CTRL_SIZE0; |
|
NEORV32_SPI.CTRL = ct_enable | ct_prsc | ct_polarity | ct_size; |
NEORV32_SPI.CTRL = ct_enable | ct_prsc | ct_phase | ct_polarity | ct_size; |
} |
|
|
158,8 → 162,6
/**********************************************************************//** |
* Check if SPI transceiver is busy. |
* |
* @note This function is blocking. |
* |
* @return 0 if idle, 1 if busy |
**************************************************************************/ |
int neorv32_spi_busy(void) { |
167,5 → 169,7
if ((NEORV32_SPI.CTRL & (1<<SPI_CTRL_BUSY)) != 0) { |
return 1; |
} |
return 0; |
else { |
return 0; |
} |
} |
/neorv32_uart.c
50,8 → 50,8
|
/// \cond |
// Private functions |
static void __neorv32_uart_itoa(uint32_t x, char *res) __attribute__((unused)); // GCC: do not ouput a warning when this variable is unused |
static void __neorv32_uart_tohex(uint32_t x, char *res) __attribute__((unused)); // GCC: do not ouput a warning when this variable is unused |
static void __neorv32_uart_itoa(uint32_t x, char *res) __attribute__((unused)); // GCC: do not output a warning when this variable is unused |
static void __neorv32_uart_tohex(uint32_t x, char *res) __attribute__((unused)); // GCC: do not output a warning when this variable is unused |
/// \endcond |
|
|
336,13 → 336,13
void neorv32_uart0_putc(char c) { |
|
// wait for previous transfer to finish |
while ((NEORV32_UART0.CTRL & (1<<UART_CTRL_TX_BUSY)) != 0); |
while ((NEORV32_UART0.CTRL & (1<<UART_CTRL_TX_FULL)) != 0); // wait for space in TX FIFO |
NEORV32_UART0.DATA = ((uint32_t)c) << UART_DATA_LSB; |
} |
|
|
/**********************************************************************//** |
* Check if UART0 TX is busy. |
* Check if UART0 TX is busy (transmitter busy or data left in TX buffer). |
* |
* @note This function is blocking. |
* |
350,7 → 350,10
**************************************************************************/ |
int neorv32_uart0_tx_busy(void) { |
|
if ((NEORV32_UART0.CTRL & (1<<UART_CTRL_TX_BUSY)) != 0) { |
uint32_t ctrl = NEORV32_UART0.CTRL; |
|
if (((ctrl & (1<<UART_CTRL_TX_BUSY)) != 0) || // TX engine busy |
((ctrl & (1<<UART_CTRL_TX_EMPTY)) == 0)) { // TX buffer not empty |
return 1; |
} |
return 0; |
382,37 → 385,41
* @note This function is non-blocking and checks for frame and parity errors. |
* |
* @param[in,out] data Received char. |
* @return Status code (0=nothing received, 1: char received without errors; -1: char received with frame error; -2: char received with parity error; -3 char received with frame & parity error). |
* @return Status code: |
* 0 = char received without errors |
* -1 = nothing received |
* -2 = char received with frame error |
* -3 = char received with parity error |
* -4 = char received with overrun error. |
**************************************************************************/ |
int neorv32_uart0_getc_safe(char *data) { |
|
uint32_t uart_rx = NEORV32_UART0.DATA; |
if (uart_rx & (1<<UART_DATA_AVAIL)) { // char available at all? |
|
int status = 0; |
// get received byte (if there is any) |
*data = (char)uart_rx; |
|
// check for frame error |
if (uart_rx & (1<<UART_DATA_FERR)) { |
status -= 1; |
} |
// check if no data available at all |
if ((uart_rx & (1<<UART_DATA_AVAIL)) == 0) { |
return -1; |
} |
|
// check for parity error |
if (uart_rx & (1<<UART_DATA_PERR)) { |
status -= 2; |
} |
// check for frame error |
if (uart_rx & (1<<UART_DATA_FERR)) { |
return -2; |
} |
|
if (status == 0) { |
status = 1; |
} |
// check for parity error |
if (uart_rx & (1<<UART_DATA_PERR)) { |
return -3; |
} |
|
// get received byte |
*data = (char)uart_rx; |
// check for overrun error |
if (uart_rx & (1<<UART_DATA_OVERR)) { |
return -4; |
} |
|
return status; |
} |
else { |
return 0; |
} |
return 0; // all fine |
} |
|
|
696,13 → 703,13
void neorv32_uart1_putc(char c) { |
|
// wait for previous transfer to finish |
while ((NEORV32_UART1.CTRL & (1<<UART_CTRL_TX_BUSY)) != 0); |
while ((NEORV32_UART1.CTRL & (1<<UART_CTRL_TX_FULL)) != 0); // wait for space in TX FIFO |
NEORV32_UART1.DATA = ((uint32_t)c) << UART_DATA_LSB; |
} |
|
|
/**********************************************************************//** |
* Check if UART1 TX is busy. |
* Check if UART1 TX is busy (transmitter busy or data left in TX buffer). |
* |
* @note This function is blocking. |
* |
710,7 → 717,10
**************************************************************************/ |
int neorv32_uart1_tx_busy(void) { |
|
if ((NEORV32_UART1.CTRL & (1<<UART_CTRL_TX_BUSY)) != 0) { |
uint32_t ctrl = NEORV32_UART1.CTRL; |
|
if (((ctrl & (1<<UART_CTRL_TX_BUSY)) != 0) || // TX engine busy |
((ctrl & (1<<UART_CTRL_TX_EMPTY)) == 0)) { // TX buffer not empty |
return 1; |
} |
return 0; |
742,37 → 752,41
* @note This function is non-blocking and checks for frame and parity errors. |
* |
* @param[in,out] data Received char. |
* @return Status code (0=nothing received, 1: char received without errors; -1: char received with frame error; -2: char received with parity error; -3 char received with frame & parity error). |
* @return Status code: |
* 0 = char received without errors |
* -1 = nothing received |
* -2 = char received with frame error |
* -3 = char received with parity error |
* -4 = char received with overrun error. |
**************************************************************************/ |
int neorv32_uart1_getc_safe(char *data) { |
|
uint32_t uart_rx = NEORV32_UART1.DATA; |
if (uart_rx & (1<<UART_DATA_AVAIL)) { // char available at all? |
|
int status = 0; |
// get received byte (if there is any) |
*data = (char)uart_rx; |
|
// check for frame error |
if (uart_rx & (1<<UART_DATA_FERR)) { |
status -= 1; |
} |
// check if no data available at all |
if ((uart_rx & (1<<UART_DATA_AVAIL)) == 0) { |
return -1; |
} |
|
// check for parity error |
if (uart_rx & (1<<UART_DATA_PERR)) { |
status -= 2; |
} |
// check for frame error |
if (uart_rx & (1<<UART_DATA_FERR)) { |
return -2; |
} |
|
if (status == 0) { |
status = 1; |
} |
// check for parity error |
if (uart_rx & (1<<UART_DATA_PERR)) { |
return -3; |
} |
|
// get received byte |
*data = (char)uart_rx; |
// check for overrun error |
if (uart_rx & (1<<UART_DATA_OVERR)) { |
return -4; |
} |
|
return status; |
} |
else { |
return 0; |
} |
return 0; // all fine |
} |
|
|