Line 41... |
Line 41... |
|
|
#include "neorv32.h"
|
#include "neorv32.h"
|
#include "neorv32_cpu.h"
|
#include "neorv32_cpu.h"
|
|
|
|
|
|
|
|
/**********************************************************************//**
|
|
* >Private< helper functions.
|
|
**************************************************************************/
|
|
static uint32_t __neorv32_cpu_pmp_cfg_read(uint32_t index);
|
|
static void __neorv32_cpu_pmp_cfg_write(uint32_t index, uint32_t data);
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Enable specific CPU interrupt.
|
* Enable specific CPU interrupt.
|
*
|
*
|
* @note Interrupts have to be globally enabled via neorv32_cpu_eint(void), too.
|
* @note Interrupts have to be globally enabled via neorv32_cpu_eint(void), too.
|
*
|
*
|
Line 290... |
Line 298... |
return 1;
|
return 1;
|
}
|
}
|
|
|
return 0;
|
return 0;
|
#else
|
#else
|
return 1; // A extension not implemented -Y always fail
|
return 1; // A extension not implemented - function always fails
|
#endif
|
#endif
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
Line 305... |
Line 313... |
*
|
*
|
* @return Returns number of available PMP regions.
|
* @return Returns number of available PMP regions.
|
**************************************************************************/
|
**************************************************************************/
|
uint32_t neorv32_cpu_pmp_get_num_regions(void) {
|
uint32_t neorv32_cpu_pmp_get_num_regions(void) {
|
|
|
|
uint32_t i = 0;
|
|
|
// try setting R bit in all PMPCFG CSRs
|
// try setting R bit in all PMPCFG CSRs
|
neorv32_cpu_csr_write(CSR_PMPCFG0, 0x01010101);
|
const uint32_t tmp = 0x01010101;
|
neorv32_cpu_csr_write(CSR_PMPCFG1, 0x01010101);
|
for (i=0; i<16; i++) {
|
neorv32_cpu_csr_write(CSR_PMPCFG2, 0x01010101);
|
__neorv32_cpu_pmp_cfg_write(i, tmp);
|
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)
|
// sum up all written ones (only available PMPCFG* CSRs/entries will return =! 0)
|
union {
|
union {
|
uint32_t uint32;
|
uint32_t uint32;
|
uint8_t uint8[sizeof(uint32_t)/sizeof(uint8_t)];
|
uint8_t uint8[sizeof(uint32_t)/sizeof(uint8_t)];
|
} cnt;
|
} cnt;
|
|
|
cnt.uint32 = 0;
|
cnt.uint32 = 0;
|
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG0);
|
for (i=0; i<16; i++) {
|
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG1);
|
cnt.uint32 += __neorv32_cpu_pmp_cfg_read(i);
|
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
|
// sum up bytes
|
uint32_t num_regions = 0;
|
uint32_t num_regions = 0;
|
num_regions += (uint32_t)cnt.uint8[0];
|
num_regions += (uint32_t)cnt.uint8[0];
|
num_regions += (uint32_t)cnt.uint8[1];
|
num_regions += (uint32_t)cnt.uint8[1];
|
Line 412... |
Line 397... |
|
|
if ((size & (size - 1)) != 0) {
|
if ((size & (size - 1)) != 0) {
|
return 1; // region size is not a power of two
|
return 1; // region size is not a power of two
|
}
|
}
|
|
|
|
// pmpcfg register index
|
|
uint32_t pmpcfg_index = index >> 4; // 4 entries per pmpcfg csr
|
|
|
// setup configuration
|
// setup configuration
|
uint32_t tmp;
|
uint32_t tmp;
|
uint32_t config_int = ((uint32_t)config) << ((index%4)*8);
|
uint32_t config_int = ((uint32_t)config) << ((index%4)*8);
|
uint32_t config_mask = ((uint32_t)0xFF) << ((index%4)*8);
|
uint32_t config_mask = ((uint32_t)0xFF) << ((index%4)*8);
|
config_mask = ~config_mask;
|
config_mask = ~config_mask;
|
|
|
// clear old configuration
|
// clear old configuration
|
switch(index & 15) {
|
__neorv32_cpu_pmp_cfg_write(pmpcfg_index, __neorv32_cpu_pmp_cfg_read(pmpcfg_index) & config_mask);
|
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;
|
|
}
|
|
|
|
// set base address and region size
|
// set base address and region size
|
uint32_t addr_mask = ~((size - 1) >> 2);
|
uint32_t addr_mask = ~((size - 1) >> 2);
|
uint32_t size_mask = (size - 1) >> 3;
|
uint32_t size_mask = (size - 1) >> 3;
|
|
|
Line 520... |
Line 491... |
for (tmp=0; tmp<16; tmp++) {
|
for (tmp=0; tmp<16; tmp++) {
|
asm volatile ("nop");
|
asm volatile ("nop");
|
}
|
}
|
|
|
// set new configuration
|
// set new configuration
|
|
__neorv32_cpu_pmp_cfg_write(pmpcfg_index, __neorv32_cpu_pmp_cfg_read(pmpcfg_index) | config_int);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Internal helper function: Read PMP configuration register 0..15
|
|
*
|
|
* @warning This function requires the PMP CPU extension.
|
|
*
|
|
* @param[in] index PMP CFG configuration register ID (0..15).
|
|
* @return PMP CFG read data.
|
|
**************************************************************************/
|
|
static uint32_t __neorv32_cpu_pmp_cfg_read(uint32_t index) {
|
|
|
|
uint32_t tmp = 0;
|
switch(index & 15) {
|
switch(index & 15) {
|
case 0: neorv32_cpu_csr_write(CSR_PMPCFG0, neorv32_cpu_csr_read(CSR_PMPCFG0) | config_int); break;
|
case 0: tmp = neorv32_cpu_csr_read(CSR_PMPCFG0); break;
|
case 1: neorv32_cpu_csr_write(CSR_PMPCFG1, neorv32_cpu_csr_read(CSR_PMPCFG1) | config_int); break;
|
case 1: tmp = neorv32_cpu_csr_read(CSR_PMPCFG1); break;
|
case 2: neorv32_cpu_csr_write(CSR_PMPCFG2, neorv32_cpu_csr_read(CSR_PMPCFG2) | config_int); break;
|
case 2: tmp = neorv32_cpu_csr_read(CSR_PMPCFG2); break;
|
case 3: neorv32_cpu_csr_write(CSR_PMPCFG3, neorv32_cpu_csr_read(CSR_PMPCFG3) | config_int); break;
|
case 3: tmp = neorv32_cpu_csr_read(CSR_PMPCFG3); break;
|
case 4: neorv32_cpu_csr_write(CSR_PMPCFG4, neorv32_cpu_csr_read(CSR_PMPCFG4) | config_int); break;
|
case 4: tmp = neorv32_cpu_csr_read(CSR_PMPCFG4); break;
|
case 5: neorv32_cpu_csr_write(CSR_PMPCFG5, neorv32_cpu_csr_read(CSR_PMPCFG5) | config_int); break;
|
case 5: tmp = neorv32_cpu_csr_read(CSR_PMPCFG5); break;
|
case 6: neorv32_cpu_csr_write(CSR_PMPCFG6, neorv32_cpu_csr_read(CSR_PMPCFG6) | config_int); break;
|
case 6: tmp = neorv32_cpu_csr_read(CSR_PMPCFG6); break;
|
case 7: neorv32_cpu_csr_write(CSR_PMPCFG7, neorv32_cpu_csr_read(CSR_PMPCFG7) | config_int); break;
|
case 7: tmp = neorv32_cpu_csr_read(CSR_PMPCFG7); break;
|
case 8: neorv32_cpu_csr_write(CSR_PMPCFG8, neorv32_cpu_csr_read(CSR_PMPCFG8) | config_int); break;
|
case 8: tmp = neorv32_cpu_csr_read(CSR_PMPCFG8); break;
|
case 9: neorv32_cpu_csr_write(CSR_PMPCFG9, neorv32_cpu_csr_read(CSR_PMPCFG9) | config_int); break;
|
case 9: tmp = neorv32_cpu_csr_read(CSR_PMPCFG9); break;
|
case 10: neorv32_cpu_csr_write(CSR_PMPCFG10, neorv32_cpu_csr_read(CSR_PMPCFG10) | config_int); break;
|
case 10: tmp = neorv32_cpu_csr_read(CSR_PMPCFG10); break;
|
case 11: neorv32_cpu_csr_write(CSR_PMPCFG11, neorv32_cpu_csr_read(CSR_PMPCFG11) | config_int); break;
|
case 11: tmp = neorv32_cpu_csr_read(CSR_PMPCFG11); break;
|
case 12: neorv32_cpu_csr_write(CSR_PMPCFG12, neorv32_cpu_csr_read(CSR_PMPCFG12) | config_int); break;
|
case 12: tmp = neorv32_cpu_csr_read(CSR_PMPCFG12); break;
|
case 13: neorv32_cpu_csr_write(CSR_PMPCFG13, neorv32_cpu_csr_read(CSR_PMPCFG13) | config_int); break;
|
case 13: tmp = neorv32_cpu_csr_read(CSR_PMPCFG13); break;
|
case 14: neorv32_cpu_csr_write(CSR_PMPCFG14, neorv32_cpu_csr_read(CSR_PMPCFG14) | config_int); break;
|
case 14: tmp = neorv32_cpu_csr_read(CSR_PMPCFG14); break;
|
case 15: neorv32_cpu_csr_write(CSR_PMPCFG15, neorv32_cpu_csr_read(CSR_PMPCFG15) | config_int); break;
|
case 15: tmp = neorv32_cpu_csr_read(CSR_PMPCFG15); break;
|
default: break;
|
default: break;
|
}
|
}
|
|
|
return 0;
|
return tmp;
|
|
}
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Internal helper function: Write PMP configuration register 0..15
|
|
*
|
|
* @warning This function requires the PMP CPU extension.
|
|
*
|
|
* @param[in] index PMP CFG configuration register ID (0..15).
|
|
* @param[in] data PMP CFG write data.
|
|
**************************************************************************/
|
|
static void __neorv32_cpu_pmp_cfg_write(uint32_t index, uint32_t data) {
|
|
|
|
switch(index & 15) {
|
|
case 0: neorv32_cpu_csr_write(CSR_PMPCFG0, data); break;
|
|
case 1: neorv32_cpu_csr_write(CSR_PMPCFG1, data); break;
|
|
case 2: neorv32_cpu_csr_write(CSR_PMPCFG2, data); break;
|
|
case 3: neorv32_cpu_csr_write(CSR_PMPCFG3, data); break;
|
|
case 4: neorv32_cpu_csr_write(CSR_PMPCFG4, data); break;
|
|
case 5: neorv32_cpu_csr_write(CSR_PMPCFG5, data); break;
|
|
case 6: neorv32_cpu_csr_write(CSR_PMPCFG6, data); break;
|
|
case 7: neorv32_cpu_csr_write(CSR_PMPCFG7, data); break;
|
|
case 8: neorv32_cpu_csr_write(CSR_PMPCFG8, data); break;
|
|
case 9: neorv32_cpu_csr_write(CSR_PMPCFG9, data); break;
|
|
case 10: neorv32_cpu_csr_write(CSR_PMPCFG10, data); break;
|
|
case 11: neorv32_cpu_csr_write(CSR_PMPCFG11, data); break;
|
|
case 12: neorv32_cpu_csr_write(CSR_PMPCFG12, data); break;
|
|
case 13: neorv32_cpu_csr_write(CSR_PMPCFG13, data); break;
|
|
case 14: neorv32_cpu_csr_write(CSR_PMPCFG14, data); break;
|
|
case 15: neorv32_cpu_csr_write(CSR_PMPCFG15, data); break;
|
|
default: break;
|
|
}
|
}
|
}
|
|
|
|
|
/**********************************************************************//**
|
/**********************************************************************//**
|
* Hardware performance monitors (HPM): Get number of available HPM counters.
|
* Hardware performance monitors (HPM): Get number of available HPM counters.
|