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 41 to Rev 42
- ↔ Reverse comparison
Rev 41 → Rev 42
/neorv32_cpu.c
3,7 → 3,7
// # ********************************************************************************************* # |
// # BSD 3-Clause License # |
// # # |
// # Copyright (c) 2020, Stephan Nolting. All rights reserved. # |
// # 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: # |
48,13 → 48,13
* |
* @note Interrupts have to be globally enabled via neorv32_cpu_eint(void), too. |
* |
* @param[in] irq_sel CPU interrupt select. See #NEORV32_CPU_MIE_enum. |
* @param[in] irq_sel CPU interrupt select. See #NEORV32_CSR_MIE_enum. |
* @return 0 if success, 1 if error (invalid irq_sel). |
**************************************************************************/ |
int neorv32_cpu_irq_enable(uint8_t irq_sel) { |
|
if ((irq_sel != CPU_MIE_MSIE) && (irq_sel != CPU_MIE_MTIE) && (irq_sel != CPU_MIE_MEIE) && |
(irq_sel != CPU_MIE_FIRQ0E) && (irq_sel != CPU_MIE_FIRQ1E) && (irq_sel != CPU_MIE_FIRQ2E) && (irq_sel != CPU_MIE_FIRQ3E)) { |
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)) { |
return 1; |
} |
|
67,13 → 67,13
/**********************************************************************//** |
* Disable specific CPU interrupt. |
* |
* @param[in] irq_sel CPU interrupt select. See #NEORV32_CPU_MIE_enum. |
* @param[in] irq_sel CPU interrupt select. See #NEORV32_CSR_MIE_enum. |
* @return 0 if success, 1 if error (invalid irq_sel). |
**************************************************************************/ |
int neorv32_cpu_irq_disable(uint8_t irq_sel) { |
|
if ((irq_sel != CPU_MIE_MSIE) && (irq_sel != CPU_MIE_MTIE) && (irq_sel != CPU_MIE_MEIE) && |
(irq_sel != CPU_MIE_FIRQ0E) && (irq_sel != CPU_MIE_FIRQ1E) && (irq_sel != CPU_MIE_FIRQ2E) && (irq_sel != CPU_MIE_FIRQ3E)) { |
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)) { |
return 1; |
} |
|
254,7 → 254,7
"li ra, %[input_imm] \n\t" // bit mask to clear the two MPP bits |
"csrrc zero, mstatus, ra \n\t" // clear MPP bits -> MPP=u-mode |
"mret \n\t" // return and switch to user mode |
: : [input_imm] "i" ((1<<CPU_MSTATUS_MPP_H) | (1<<CPU_MSTATUS_MPP_L))); |
: : [input_imm] "i" ((1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L))); |
} |
|
|
298,20 → 298,78
|
|
/**********************************************************************//** |
* Physical memory protection (PMP): Get number of available regions. |
* |
* @warning This function overrides all available PMPCFG* CSRs. |
* @warning This function requires the PMP CPU extension. |
* |
* @return Returns number of available PMP regions. |
**************************************************************************/ |
uint32_t neorv32_cpu_pmp_get_num_regions(void) { |
|
// try setting R bit in all PMPCFG CSRs |
neorv32_cpu_csr_write(CSR_PMPCFG0, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG1, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG2, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG3, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG4, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG5, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG6, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG7, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG8, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG9, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG10, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG11, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG12, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG13, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG14, 0x01010101); |
neorv32_cpu_csr_write(CSR_PMPCFG15, 0x01010101); |
|
// sum up all written ones (only available PMPCFG* CSRs/entries will return =! 0) |
union { |
uint32_t uint32; |
uint8_t uint8[sizeof(uint32_t)/sizeof(uint8_t)]; |
} cnt; |
|
cnt.uint32 = 0; |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG0); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG1); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG2); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG3); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG4); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG5); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG6); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG7); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG8); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG9); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG10); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG11); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG12); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG13); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG14); |
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG15); |
|
// sum up bytes |
uint32_t num_regions = 0; |
num_regions += (uint32_t)cnt.uint8[0]; |
num_regions += (uint32_t)cnt.uint8[1]; |
num_regions += (uint32_t)cnt.uint8[2]; |
num_regions += (uint32_t)cnt.uint8[3]; |
|
return num_regions; |
} |
|
|
/**********************************************************************//** |
* Physical memory protection (PMP): Get minimal region size (granularity). |
* |
* @warning This function overrides PMPCFG0[0] and PMPADDR0 CSRs. |
* |
* @warning This function requires the PMP CPU extension. |
* |
* @return Returns minimal region size in bytes; Returns 0 on failure. |
* @return Returns minimal region size in bytes. |
**************************************************************************/ |
uint32_t neorv32_cpu_pmp_get_granularity(void) { |
|
if ((neorv32_cpu_csr_read(CSR_MZEXT) & (1<<CPU_MZEXT_PMP)) == 0) { |
return 0; // PMP not implemented |
} |
|
// check min granulartiy |
uint32_t tmp = neorv32_cpu_csr_read(CSR_PMPCFG0); |
tmp &= 0xffffff00; // disable entry 0 |
338,8 → 396,9
* @note Using NAPOT mode - page base address has to be naturally aligned. |
* |
* @warning This function requires the PMP CPU extension. |
* @warning Only use available PMP regions. Check before using neorv32_cpu_pmp_get_regions(void). |
* |
* @param[in] index Region number (index, 0..max_regions-1). |
* @param[in] index Region number (index, 0..PMP_NUM_REGIONS-1). |
* @param[in] base Region base address (has to be naturally aligned!). |
* @param[in] size Region size, has to be a power of 2 (min 8 bytes or according to HW's PMP.granularity configuration). |
* @param[in] config Region configuration (attributes) byte (for PMPCFGx). |
347,10 → 406,6
**************************************************************************/ |
int neorv32_cpu_pmp_configure_region(uint32_t index, uint32_t base, uint32_t size, uint8_t config) { |
|
if ((neorv32_cpu_csr_read(CSR_MZEXT) & (1<<CPU_MZEXT_PMP)) == 0) { |
return 1; // PMP not implemented |
} |
|
if (size < 8) { |
return 1; // minimal region size is 8 bytes |
} |
366,16 → 421,25
config_mask = ~config_mask; |
|
// clear old configuration |
if (index < 3) { |
tmp = neorv32_cpu_csr_read(CSR_PMPCFG0); |
tmp &= config_mask; // clear old config |
neorv32_cpu_csr_write(CSR_PMPCFG0, tmp); |
switch(index & 15) { |
case 0: neorv32_cpu_csr_write(CSR_PMPCFG0, neorv32_cpu_csr_read(CSR_PMPCFG0) & config_mask); break; |
case 1: neorv32_cpu_csr_write(CSR_PMPCFG1, neorv32_cpu_csr_read(CSR_PMPCFG1) & config_mask); break; |
case 2: neorv32_cpu_csr_write(CSR_PMPCFG2, neorv32_cpu_csr_read(CSR_PMPCFG2) & config_mask); break; |
case 3: neorv32_cpu_csr_write(CSR_PMPCFG3, neorv32_cpu_csr_read(CSR_PMPCFG3) & config_mask); break; |
case 4: neorv32_cpu_csr_write(CSR_PMPCFG4, neorv32_cpu_csr_read(CSR_PMPCFG4) & config_mask); break; |
case 5: neorv32_cpu_csr_write(CSR_PMPCFG5, neorv32_cpu_csr_read(CSR_PMPCFG5) & config_mask); break; |
case 6: neorv32_cpu_csr_write(CSR_PMPCFG6, neorv32_cpu_csr_read(CSR_PMPCFG6) & config_mask); break; |
case 7: neorv32_cpu_csr_write(CSR_PMPCFG7, neorv32_cpu_csr_read(CSR_PMPCFG7) & config_mask); break; |
case 8: neorv32_cpu_csr_write(CSR_PMPCFG8, neorv32_cpu_csr_read(CSR_PMPCFG8) & config_mask); break; |
case 9: neorv32_cpu_csr_write(CSR_PMPCFG9, neorv32_cpu_csr_read(CSR_PMPCFG9) & config_mask); break; |
case 10: neorv32_cpu_csr_write(CSR_PMPCFG10, neorv32_cpu_csr_read(CSR_PMPCFG10) & config_mask); break; |
case 11: neorv32_cpu_csr_write(CSR_PMPCFG11, neorv32_cpu_csr_read(CSR_PMPCFG11) & config_mask); break; |
case 12: neorv32_cpu_csr_write(CSR_PMPCFG12, neorv32_cpu_csr_read(CSR_PMPCFG12) & config_mask); break; |
case 13: neorv32_cpu_csr_write(CSR_PMPCFG13, neorv32_cpu_csr_read(CSR_PMPCFG13) & config_mask); break; |
case 14: neorv32_cpu_csr_write(CSR_PMPCFG14, neorv32_cpu_csr_read(CSR_PMPCFG14) & config_mask); break; |
case 15: neorv32_cpu_csr_write(CSR_PMPCFG15, neorv32_cpu_csr_read(CSR_PMPCFG15) & config_mask); break; |
default: break; |
} |
else { |
tmp = neorv32_cpu_csr_read(CSR_PMPCFG1); |
tmp &= config_mask; // clear old config |
neorv32_cpu_csr_write(CSR_PMPCFG1, tmp); |
} |
|
// set base address and region size |
uint32_t addr_mask = ~((size - 1) >> 2); |
384,34 → 448,172
tmp = base & addr_mask; |
tmp = tmp | size_mask; |
|
switch(index & 7) { |
case 0: neorv32_cpu_csr_write(CSR_PMPADDR0, tmp); break; |
case 1: neorv32_cpu_csr_write(CSR_PMPADDR1, tmp); break; |
case 2: neorv32_cpu_csr_write(CSR_PMPADDR2, tmp); break; |
case 3: neorv32_cpu_csr_write(CSR_PMPADDR3, tmp); break; |
case 4: neorv32_cpu_csr_write(CSR_PMPADDR4, tmp); break; |
case 5: neorv32_cpu_csr_write(CSR_PMPADDR5, tmp); break; |
case 6: neorv32_cpu_csr_write(CSR_PMPADDR6, tmp); break; |
case 7: neorv32_cpu_csr_write(CSR_PMPADDR7, tmp); break; |
switch(index & 63) { |
case 0: neorv32_cpu_csr_write(CSR_PMPADDR0, tmp); break; |
case 1: neorv32_cpu_csr_write(CSR_PMPADDR1, tmp); break; |
case 2: neorv32_cpu_csr_write(CSR_PMPADDR2, tmp); break; |
case 3: neorv32_cpu_csr_write(CSR_PMPADDR3, tmp); break; |
case 4: neorv32_cpu_csr_write(CSR_PMPADDR4, tmp); break; |
case 5: neorv32_cpu_csr_write(CSR_PMPADDR5, tmp); break; |
case 6: neorv32_cpu_csr_write(CSR_PMPADDR6, tmp); break; |
case 7: neorv32_cpu_csr_write(CSR_PMPADDR7, tmp); break; |
case 8: neorv32_cpu_csr_write(CSR_PMPADDR8, tmp); break; |
case 9: neorv32_cpu_csr_write(CSR_PMPADDR9, tmp); break; |
case 10: neorv32_cpu_csr_write(CSR_PMPADDR10, tmp); break; |
case 11: neorv32_cpu_csr_write(CSR_PMPADDR11, tmp); break; |
case 12: neorv32_cpu_csr_write(CSR_PMPADDR12, tmp); break; |
case 13: neorv32_cpu_csr_write(CSR_PMPADDR13, tmp); break; |
case 14: neorv32_cpu_csr_write(CSR_PMPADDR14, tmp); break; |
case 15: neorv32_cpu_csr_write(CSR_PMPADDR15, tmp); break; |
case 16: neorv32_cpu_csr_write(CSR_PMPADDR16, tmp); break; |
case 17: neorv32_cpu_csr_write(CSR_PMPADDR17, tmp); break; |
case 18: neorv32_cpu_csr_write(CSR_PMPADDR18, tmp); break; |
case 19: neorv32_cpu_csr_write(CSR_PMPADDR19, tmp); break; |
case 20: neorv32_cpu_csr_write(CSR_PMPADDR20, tmp); break; |
case 21: neorv32_cpu_csr_write(CSR_PMPADDR21, tmp); break; |
case 22: neorv32_cpu_csr_write(CSR_PMPADDR22, tmp); break; |
case 23: neorv32_cpu_csr_write(CSR_PMPADDR23, tmp); break; |
case 24: neorv32_cpu_csr_write(CSR_PMPADDR24, tmp); break; |
case 25: neorv32_cpu_csr_write(CSR_PMPADDR25, tmp); break; |
case 26: neorv32_cpu_csr_write(CSR_PMPADDR26, tmp); break; |
case 27: neorv32_cpu_csr_write(CSR_PMPADDR27, tmp); break; |
case 28: neorv32_cpu_csr_write(CSR_PMPADDR28, tmp); break; |
case 29: neorv32_cpu_csr_write(CSR_PMPADDR29, tmp); break; |
case 30: neorv32_cpu_csr_write(CSR_PMPADDR30, tmp); break; |
case 31: neorv32_cpu_csr_write(CSR_PMPADDR31, tmp); break; |
case 32: neorv32_cpu_csr_write(CSR_PMPADDR32, tmp); break; |
case 33: neorv32_cpu_csr_write(CSR_PMPADDR33, tmp); break; |
case 34: neorv32_cpu_csr_write(CSR_PMPADDR34, tmp); break; |
case 35: neorv32_cpu_csr_write(CSR_PMPADDR35, tmp); break; |
case 36: neorv32_cpu_csr_write(CSR_PMPADDR36, tmp); break; |
case 37: neorv32_cpu_csr_write(CSR_PMPADDR37, tmp); break; |
case 38: neorv32_cpu_csr_write(CSR_PMPADDR38, tmp); break; |
case 39: neorv32_cpu_csr_write(CSR_PMPADDR39, tmp); break; |
case 40: neorv32_cpu_csr_write(CSR_PMPADDR40, tmp); break; |
case 41: neorv32_cpu_csr_write(CSR_PMPADDR41, tmp); break; |
case 42: neorv32_cpu_csr_write(CSR_PMPADDR42, tmp); break; |
case 43: neorv32_cpu_csr_write(CSR_PMPADDR43, tmp); break; |
case 44: neorv32_cpu_csr_write(CSR_PMPADDR44, tmp); break; |
case 45: neorv32_cpu_csr_write(CSR_PMPADDR45, tmp); break; |
case 46: neorv32_cpu_csr_write(CSR_PMPADDR46, tmp); break; |
case 47: neorv32_cpu_csr_write(CSR_PMPADDR47, tmp); break; |
case 48: neorv32_cpu_csr_write(CSR_PMPADDR48, tmp); break; |
case 49: neorv32_cpu_csr_write(CSR_PMPADDR49, tmp); break; |
case 50: neorv32_cpu_csr_write(CSR_PMPADDR50, tmp); break; |
case 51: neorv32_cpu_csr_write(CSR_PMPADDR51, tmp); break; |
case 52: neorv32_cpu_csr_write(CSR_PMPADDR52, tmp); break; |
case 53: neorv32_cpu_csr_write(CSR_PMPADDR53, tmp); break; |
case 54: neorv32_cpu_csr_write(CSR_PMPADDR54, tmp); break; |
case 55: neorv32_cpu_csr_write(CSR_PMPADDR55, tmp); break; |
case 56: neorv32_cpu_csr_write(CSR_PMPADDR56, tmp); break; |
case 57: neorv32_cpu_csr_write(CSR_PMPADDR57, tmp); break; |
case 58: neorv32_cpu_csr_write(CSR_PMPADDR58, tmp); break; |
case 59: neorv32_cpu_csr_write(CSR_PMPADDR59, tmp); break; |
case 60: neorv32_cpu_csr_write(CSR_PMPADDR60, tmp); break; |
case 61: neorv32_cpu_csr_write(CSR_PMPADDR61, tmp); break; |
case 62: neorv32_cpu_csr_write(CSR_PMPADDR62, tmp); break; |
case 63: neorv32_cpu_csr_write(CSR_PMPADDR63, tmp); break; |
default: break; |
} |
|
// wait for HW to computer PMP-internal stuff (address masks) |
// wait for HW to compute PMP-internal stuff (address masks) |
for (tmp=0; tmp<16; tmp++) { |
asm volatile ("nop"); |
} |
|
// set new configuration |
if (index < 3) { |
tmp = neorv32_cpu_csr_read(CSR_PMPCFG0); |
tmp |= config_int; // set new config |
neorv32_cpu_csr_write(CSR_PMPCFG0, tmp); |
switch(index & 15) { |
case 0: neorv32_cpu_csr_write(CSR_PMPCFG0, neorv32_cpu_csr_read(CSR_PMPCFG0) | config_int); break; |
case 1: neorv32_cpu_csr_write(CSR_PMPCFG1, neorv32_cpu_csr_read(CSR_PMPCFG1) | config_int); break; |
case 2: neorv32_cpu_csr_write(CSR_PMPCFG2, neorv32_cpu_csr_read(CSR_PMPCFG2) | config_int); break; |
case 3: neorv32_cpu_csr_write(CSR_PMPCFG3, neorv32_cpu_csr_read(CSR_PMPCFG3) | config_int); break; |
case 4: neorv32_cpu_csr_write(CSR_PMPCFG4, neorv32_cpu_csr_read(CSR_PMPCFG4) | config_int); break; |
case 5: neorv32_cpu_csr_write(CSR_PMPCFG5, neorv32_cpu_csr_read(CSR_PMPCFG5) | config_int); break; |
case 6: neorv32_cpu_csr_write(CSR_PMPCFG6, neorv32_cpu_csr_read(CSR_PMPCFG6) | config_int); break; |
case 7: neorv32_cpu_csr_write(CSR_PMPCFG7, neorv32_cpu_csr_read(CSR_PMPCFG7) | config_int); break; |
case 8: neorv32_cpu_csr_write(CSR_PMPCFG8, neorv32_cpu_csr_read(CSR_PMPCFG8) | config_int); break; |
case 9: neorv32_cpu_csr_write(CSR_PMPCFG9, neorv32_cpu_csr_read(CSR_PMPCFG9) | config_int); break; |
case 10: neorv32_cpu_csr_write(CSR_PMPCFG10, neorv32_cpu_csr_read(CSR_PMPCFG10) | config_int); break; |
case 11: neorv32_cpu_csr_write(CSR_PMPCFG11, neorv32_cpu_csr_read(CSR_PMPCFG11) | config_int); break; |
case 12: neorv32_cpu_csr_write(CSR_PMPCFG12, neorv32_cpu_csr_read(CSR_PMPCFG12) | config_int); break; |
case 13: neorv32_cpu_csr_write(CSR_PMPCFG13, neorv32_cpu_csr_read(CSR_PMPCFG13) | config_int); break; |
case 14: neorv32_cpu_csr_write(CSR_PMPCFG14, neorv32_cpu_csr_read(CSR_PMPCFG14) | config_int); break; |
case 15: neorv32_cpu_csr_write(CSR_PMPCFG15, neorv32_cpu_csr_read(CSR_PMPCFG15) | config_int); break; |
default: break; |
} |
else { |
tmp = neorv32_cpu_csr_read(CSR_PMPCFG1); |
tmp |= config_int; // set new config |
neorv32_cpu_csr_write(CSR_PMPCFG1, tmp); |
} |
|
return 0; |
} |
|
|
/**********************************************************************//** |
* Hardware performance monitors (HPM): Get number of available HPM counters. |
* |
* @warning This function overrides all available mhpmcounter* CSRs. |
* |
* @return Returns number of available HPM counters (..29). |
**************************************************************************/ |
uint32_t neorv32_cpu_hpm_get_counters(void) { |
|
// try setting all mhpmcounter* CSRs to 1 |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER3, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER4, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER5, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER6, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER7, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER8, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER9, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER10, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER11, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER12, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER13, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER14, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER15, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER16, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER17, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER18, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER19, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER20, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER21, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER22, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER23, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER24, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER25, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER26, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER27, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER28, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER29, 1); |
|
// sum up all written ones (only available PMPCFG* CSRs/entries will return =! 0) |
uint32_t num_hpm_cnts = 0; |
|
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER3); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER4); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER5); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER6); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER7); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER8); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER9); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER10); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER11); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER12); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER13); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER14); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER15); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER16); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER17); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER18); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER19); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER20); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER21); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER22); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER23); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER24); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER25); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER26); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER27); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER28); |
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER29); |
|
return num_hpm_cnts; |
} |
/neorv32_rte.c
3,7 → 3,7
// # ********************************************************************************************* # |
// # BSD 3-Clause License # |
// # # |
// # Copyright (c) 2020, Stephan Nolting. All rights reserved. # |
// # 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: # |
288,7 → 288,7
|
// CPU extensions |
neorv32_uart_printf("\nEndianness: "); |
if (neorv32_cpu_csr_read(CSR_MSTATUSH) & (1<<CPU_MSTATUSH_MBE)) { |
if (neorv32_cpu_csr_read(CSR_MSTATUSH) & (1<<CSR_MSTATUSH_MBE)) { |
neorv32_uart_printf("big\n"); |
} |
else { |
296,7 → 296,7
} |
|
// CPU extensions |
neorv32_uart_printf("\nExtensions: "); |
neorv32_uart_printf("Extensions: "); |
tmp = neorv32_cpu_csr_read(CSR_MISA); |
for (i=0; i<26; i++) { |
if (tmp & (1 << i)) { |
308,60 → 308,31
|
// Z* CPU extensions (from custom "mzext" CSR) |
tmp = neorv32_cpu_csr_read(CSR_MZEXT); |
if (tmp & (1<<CPU_MZEXT_ZICSR)) { |
if (tmp & (1<<CSR_MZEXT_ZICSR)) { |
neorv32_uart_printf("Zicsr "); |
} |
if (tmp & (1<<CPU_MZEXT_ZIFENCEI)) { |
if (tmp & (1<<CSR_MZEXT_ZIFENCEI)) { |
neorv32_uart_printf("Zifencei "); |
} |
if (tmp & (1<<CPU_MZEXT_PMP)) { |
neorv32_uart_printf("PMP "); |
} |
|
|
// check physical memory protection |
neorv32_uart_printf("\n\nPhysical memory protection: "); |
if (neorv32_cpu_csr_read(CSR_MZEXT) & (1<<CPU_MZEXT_PMP)) { |
neorv32_uart_printf("\nPMP: "); |
uint32_t pmp_num_regions = neorv32_cpu_pmp_get_num_regions(); |
if (pmp_num_regions != 0) { |
// get number of available regions |
neorv32_uart_printf("\n- Available regions: %u\n", pmp_num_regions); |
|
// get minimal region siz (granulartiy) |
neorv32_uart_printf("\n- Minimal granularity: %u bytes per region\n", neorv32_cpu_pmp_get_granularity()); |
|
// test available modes |
neorv32_uart_printf("- Mode TOR: "); |
neorv32_cpu_csr_write(CSR_PMPCFG0, 0x08); |
if ((neorv32_cpu_csr_read(CSR_PMPCFG0) & 0xFF) == 0x08) { |
neorv32_uart_printf("available\n"); |
} |
else { |
neorv32_uart_printf("not implemented\n"); |
} |
|
neorv32_uart_printf("- Mode NA4: "); |
neorv32_cpu_csr_write(CSR_PMPCFG0, 0x10); |
if ((neorv32_cpu_csr_read(CSR_PMPCFG0) & 0xFF) == 0x10) { |
neorv32_uart_printf("available\n"); |
} |
else { |
neorv32_uart_printf("not implemented\n"); |
} |
|
neorv32_uart_printf("- Mode NAPOT: "); |
neorv32_cpu_csr_write(CSR_PMPCFG0, 0x18); |
if ((neorv32_cpu_csr_read(CSR_PMPCFG0) & 0xFF) == 0x18) { |
neorv32_uart_printf("available\n"); |
} |
else { |
neorv32_uart_printf("not implemented\n"); |
} |
|
// deactivate entry |
neorv32_cpu_csr_write(CSR_PMPCFG0, 0); |
// get minimal region size (granulartiy) |
neorv32_uart_printf("- Minimal granularity: %u bytes per region\n", neorv32_cpu_pmp_get_granularity()); |
} |
else { |
neorv32_uart_printf("not implemented\n"); |
} |
|
// check physical memory protection |
neorv32_uart_printf("HPM Counters: %u\n", neorv32_cpu_hpm_get_counters()); |
|
|
// Misc - system |
neorv32_uart_printf("\n\n---- Processor - General ----\n"); |
neorv32_uart_printf("Clock: %u Hz\n", SYSINFO_CLK); |
378,12 → 349,12
neorv32_uart_printf("Internal IMEM as ROM: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM)); |
|
neorv32_uart_printf("\nData base address: 0x%x\n", SYSINFO_DSPACE_BASE); |
neorv32_uart_printf("Data base address: 0x%x\n", SYSINFO_DSPACE_BASE); |
neorv32_uart_printf("Internal DMEM: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_DMEM)); |
neorv32_uart_printf("DMEM size: %u bytes\n", SYSINFO_DMEM_SIZE); |
|
neorv32_uart_printf("\nInternal i-cache: "); |
neorv32_uart_printf("Internal i-cache: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_ICACHE)); |
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_ICACHE)) { |
neorv32_uart_printf("- "); |
419,12 → 390,12
} |
} |
|
neorv32_uart_printf("\nBootloader: "); |
neorv32_uart_printf("Bootloader: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_BOOTLOADER)); |
|
neorv32_uart_printf("\nExternal memory bus interface: "); |
neorv32_uart_printf("Ext. bus interface: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT)); |
neorv32_uart_printf("External memory bus Endianness: "); |
neorv32_uart_printf("Ext. bus Endianness: "); |
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT_ENDIAN)) { |
neorv32_uart_printf("big\n"); |
} |
542,7 → 513,9
**************************************************************************/ |
void neorv32_rte_print_credits(void) { |
|
neorv32_uart_print("The NEORV32 Processor Project by Stephan Nolting\n" |
neorv32_uart_print("The NEORV32 Processor Project\n" |
"Copyright 2021, Stephan Nolting\n" |
"BSD 3-Clause License\n" |
"https://github.com/stnolting/neorv32\n\n"); |
} |
|
597,7 → 570,7
"\n" |
"BSD 3-Clause License\n" |
"\n" |
"Copyright (c) 2020, Stephan Nolting. All rights reserved.\n" |
"Copyright (c) 2021, Stephan Nolting. All rights reserved.\n" |
"\n" |
"Redistribution and use in source and binary forms, with or without modification, are\n" |
"permitted provided that the following conditions are met:\n" |
/neorv32_uart.c
75,10 → 75,11
* @warning To enable simulation mode add <USER_FLAGS+=-DUART_SIM_MODE> when compiling. |
* |
* @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. |
* @param[in] tx_irq Enable TX interrupt (transmission done) when 1. |
**************************************************************************/ |
void neorv32_uart_setup(uint32_t baudrate, uint8_t rx_irq, uint8_t tx_irq) { |
void neorv32_uart_setup(uint32_t baudrate, uint8_t parity, uint8_t rx_irq, uint8_t tx_irq) { |
|
UART_CT = 0; // reset |
|
116,6 → 117,9
uint32_t uart_en = 1; |
uart_en = uart_en << UART_CT_EN; |
|
uint32_t parity_config = (uint32_t)(parity & 3); |
parity_config = parity_config << UART_CT_PMODE0; |
|
uint32_t rx_irq_en = (uint32_t)(rx_irq & 1); |
rx_irq_en = rx_irq_en << UART_CT_RX_IRQ; |
|
123,7 → 127,7
tx_irq_en = tx_irq_en << UART_CT_TX_IRQ; |
|
/* Enable the UART for SIM mode. */ |
/* Only use this for simulation! */ |
/* USE THIS ONLY FOR SIMULATION! */ |
#ifdef UART_SIM_MODE |
#warning UART_SIM_MODE enabled! Sending all UART.TX data to text.io simulation output instead of real UART transmitter. Use this for simulations only! |
uint32_t sim_mode = 1 << UART_CT_SIM_MODE; |
131,7 → 135,7
uint32_t sim_mode = 0; |
#endif |
|
UART_CT = prsc | baud | uart_en | rx_irq_en | tx_irq_en | sim_mode; |
UART_CT = prsc | baud | uart_en | parity_config | rx_irq_en | tx_irq_en | sim_mode; |
} |
|
|
182,7 → 186,7
/**********************************************************************//** |
* Get char from UART. |
* |
* @note This function is blocking. |
* @note This function is blocking and does not check for UART frame/parity errors. |
* |
* @return Received char. |
**************************************************************************/ |
199,8 → 203,48
|
|
/**********************************************************************//** |
* Check if UARt has received a char. |
* Get char from UART (and check errors). |
* |
* @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). |
**************************************************************************/ |
int neorv32_uart_getc_secure(char *data) { |
|
uint32_t uart_rx = UART_DATA; |
if (uart_rx & (1<<UART_DATA_AVAIL)) { // char available at all? |
|
int status = 0; |
|
// check for frame error |
if (uart_rx & (1<<UART_DATA_FERR)) { |
status -= 1; |
} |
|
// check for parity error |
if (uart_rx & (1<<UART_DATA_PERR)) { |
status -= 2; |
} |
|
if (status == 0) { |
status = 1; |
} |
|
// get received byte |
*data = (char)uart_rx; |
|
return status; |
} |
else { |
return 0; |
} |
} |
|
|
/**********************************************************************//** |
* Check if UART has received a char. |
* |
* @note This function is non-blocking. |
* @note Use neorv32_uart_char_received_get(void) to get the char. |
* |