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/example
    from Rev 34 to Rev 35
    Reverse comparison

Rev 34 → Rev 35

/cpu_test/main.c
49,8 → 49,6
/**@{*/
/** UART BAUD rate */
#define BAUD_RATE 19200
//** Set 1 to run external memory test */
#define EXT_MEM_TEST 1
//** Reachable unaligned address */
#define ADDR_UNALIGNED 0x00000002
//** Unreachable aligned address */
60,15 → 58,6
/**@}*/
 
 
/**********************************************************************//**
* @name Exception handler acknowledges
**************************************************************************/
/**@{*/
/** Global volatile variable to store exception handler answer */
volatile uint32_t exception_handler_answer;
/**@}*/
 
 
// Prototypes
void global_trap_handler(void);
void test_ok(void);
97,8 → 86,8
**************************************************************************/
int main() {
 
register uint32_t tmp_a;
uint32_t i;
register uint32_t tmp_a, tmp_b, tmp_c;
uint32_t i, j;
volatile uint32_t dummy_dst __attribute__((unused));
 
union {
115,7 → 104,7
 
neorv32_mtime_set_time(0);
// set CMP of machine system timer MTIME to max to prevent an IRQ
uint64_t mtime_cmp_max = 0xFFFFFFFFFFFFFFFFL;
uint64_t mtime_cmp_max = 0xFFFFFFFFFFFFFFFFUL;
neorv32_mtime_set_timecmp(mtime_cmp_max);
 
// intro
176,84 → 165,13
// intro2
neorv32_uart_printf("\n\nStarting tests...\n\n");
 
 
// enable global interrupts
neorv32_cpu_eint();
 
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
 
// ----------------------------------------------------------
// Instruction memory test
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_uart_printf("[%i] Processor-internal IMEM test: ", cnt_test);
 
if ((UART_CT & (1 << UART_CT_SIM_MODE)) == 0) { // check if this is a simulation
cnt_test++;
 
register uint32_t dmem_probe_addr = SYSINFO_ISPACE_BASE;
uint32_t dmem_probe_cnt = 0;
 
while(1) {
asm volatile ("lb zero, 0(%[input_j])" : : [input_j] "r" (dmem_probe_addr));
if (exception_handler_answer == TRAP_CODE_L_ACCESS) {
break;
}
dmem_probe_addr++;
dmem_probe_cnt++;
}
neorv32_uart_printf("%u bytes (should be %u bytes) ", dmem_probe_cnt, SYSINFO_IMEM_SIZE);
neorv32_uart_printf("@ 0x%x ", SYSINFO_ISPACE_BASE);
if (dmem_probe_cnt == SYSINFO_IMEM_SIZE) {
test_ok();
}
else {
test_fail();
}
}
else {
neorv32_uart_printf("skipped (disabled for simulation)\n");
}
 
 
// ----------------------------------------------------------
// Data memory test
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_uart_printf("[%i] Processor-internal DMEM test: ", cnt_test);
 
if ((UART_CT & (1 << UART_CT_SIM_MODE)) == 0) { // check if this is a simulation
cnt_test++;
 
register uint32_t imem_probe_addr = SYSINFO_DSPACE_BASE;
uint32_t imem_probe_cnt = 0;
 
while(1) {
asm volatile ("lb zero, 0(%[input_j])" : : [input_j] "r" (imem_probe_addr));
if (exception_handler_answer == TRAP_CODE_L_ACCESS) {
break;
}
imem_probe_addr++;
imem_probe_cnt++;
}
neorv32_uart_printf("%u bytes (should be %u bytes) ", imem_probe_cnt, SYSINFO_DMEM_SIZE);
neorv32_uart_printf("@ 0x%x ", SYSINFO_DSPACE_BASE);
if (imem_probe_cnt == SYSINFO_DMEM_SIZE) {
test_ok();
}
else {
test_fail();
}
}
else {
neorv32_uart_printf("skipped (disabled for simulation)\n");
}
 
 
// ----------------------------------------------------------
// List all accessible CSRs
// ----------------------------------------------------------
neorv32_uart_printf("[%i] List all accessible CSRs: ", cnt_test);
279,7 → 197,7
 
// iterate through full 12-bit CSR address space
for (csr_addr_cnt=0x000; csr_addr_cnt<=0xfff; csr_addr_cnt++) {
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
// construct and store new CSR access instruction
// 0x00006073 = csrrsi, 0x000, 0
292,8 → 210,8
asm volatile ("jalr ra, %[input_i]" : : [input_i] "r" (tmp_a));
 
// check for access exception
if (exception_handler_answer == 0xFFFFFFFF) { // no exception -> access ok -> CSR exists
neorv32_uart_printf(" + 0x%x\n", csr_addr_cnt);
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { // no exception -> access ok -> CSR exists
neorv32_uart_printf(" + 0x%x\n", csr_addr_cnt);
i++;
}
}
312,7 → 230,7
// ----------------------------------------------------------
// CFU0 test (default HW)
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Default CFU0 access test: ", cnt_test);
 
// cfu0 implemented?
327,7 → 245,7
 
if ((CFU0_REG_0 == 0x01234567) && (CFU0_REG_1 == 0x76543210) &&
(CFU0_REG_2 == 0xABCDABCD) && (CFU0_REG_3 == 0xFFAAFFAA) && // correct read-back
(exception_handler_answer == 0xFFFFFFFF)) { // no exception
(neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { // no exception
test_ok();
}
else {
335,7 → 253,7
}
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
neorv32_uart_printf("skipped (CFU0 not implemented)\n");
}
 
 
342,7 → 260,7
// ----------------------------------------------------------
// CFU1 test (default HW)
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Default CFU1 access test: ", cnt_test);
 
// cfu0 implemented?
357,7 → 275,7
 
if ((CFU1_REG_0 == 0x22334455) && (CFU1_REG_1 == 0x44782931) &&
(CFU1_REG_2 == 0xDDAABBFF) && (CFU1_REG_3 == 0xA0B0D0C0) && // correct read-back
(exception_handler_answer == 0xFFFFFFFF)) { // no exception
(neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { // no exception
test_ok();
}
else {
365,7 → 283,7
}
}
else {
neorv32_uart_printf("skipped (not implemented)\n");
neorv32_uart_printf("skipped (CFU1 not implemented)\n");
}
 
 
372,7 → 290,7
// ----------------------------------------------------------
// Bus timeout latency estimation
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Estimate bus time-out latency: ", cnt_test);
 
// start timing
380,11 → 298,11
 
// this will timeout
MMR_UNREACHABLE = 0;
tmp_a = neorv32_cpu_csr_read(CSR_CYCLE) - tmp_a;
 
// wait for timeout
while (exception_handler_answer == 0xFFFFFFFF);
while (neorv32_cpu_csr_read(CSR_MCAUSE) == 0);
 
tmp_a = neorv32_cpu_csr_read(CSR_CYCLE) - tmp_a;
tmp_a = tmp_a / 4; // divide by average CPI
neorv32_uart_printf("~%u cycles\n", tmp_a);
 
392,42 → 310,49
// ----------------------------------------------------------
// External memory interface test
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_uart_printf("[%i] External memory access test: ", cnt_test);
#if (EXT_MEM_TEST == 1)
cnt_test++;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] External memory access (@ 0x%x) test: ", cnt_test, (uint32_t)EXT_MEM_BASE);
 
// create test program in RAM
static const uint32_t dummy_ext_program[2] __attribute__((aligned(8))) = {
0x3407D073, // csrwi mscratch, 15
0x00008067 // ret (32-bit)
};
if (UART_CT & (1 << UART_CT_SIM_MODE)) { // check if this is a simulation
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT)) {
cnt_test++;
 
// copy to external memory
if (memcpy((void*)EXT_MEM_BASE, (void*)&dummy_ext_program, (size_t)sizeof(dummy_ext_program)) == NULL) {
test_fail();
}
else {
// create test program in RAM
static const uint32_t dummy_ext_program[2] __attribute__((aligned(8))) = {
0x3407D073, // csrwi mscratch, 15
0x00008067 // ret (32-bit)
};
 
// execute program
tmp_a = (uint32_t)EXT_MEM_BASE; // call the dummy sub program
asm volatile ("jalr ra, %[input_i]" : : [input_i] "r" (tmp_a));
if (exception_handler_answer == 0xFFFFFFFF) { // make sure there was no exception
if (neorv32_cpu_csr_read(CSR_MSCRATCH) == 15) { // make sure the program was executed in the right way
test_ok();
// copy to external memory
if (memcpy((void*)EXT_MEM_BASE, (void*)&dummy_ext_program, (size_t)sizeof(dummy_ext_program)) == NULL) {
test_fail();
}
else {
test_fail();
 
// execute program
tmp_a = (uint32_t)EXT_MEM_BASE; // call the dummy sub program
asm volatile ("jalr ra, %[input_i]" : : [input_i] "r" (tmp_a));
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { // make sure there was no exception
if (neorv32_cpu_csr_read(CSR_MSCRATCH) == 15) { // make sure the program was executed in the right way
test_ok();
}
else {
test_fail();
}
}
else {
test_fail();
}
}
}
else {
test_fail();
neorv32_uart_printf("skipped (external memory interface not implemented)\n");
}
}
#else
neorv32_uart_printf("skipped (disabled)\n");
#endif
else {
neorv32_uart_printf("skipped (on real hardware)\n");
}
 
 
// ----------------------------------------------------------
453,12 → 378,12
// ----------------------------------------------------------
// Test fence instructions - make sure CPU does not crash here and throws no exception
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FENCE instruction test: ", cnt_test);
cnt_test++;
asm volatile ("fence");
 
if (exception_handler_answer != 0xFFFFFFFF) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) != 0) {
test_fail();
}
else {
470,18 → 395,18
// Test fencei instructions - make sure CPU does not crash here and throws no exception
// a more complex test is provided by the RISC-V compliance test
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FENCE.I instruction test: ", cnt_test);
asm volatile ("fence.i");
 
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
neorv32_uart_printf("skipped (not implemented)\n");
}
else {
cnt_test++;
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
asm volatile ("fence.i");
if (exception_handler_answer == 0xFFFFFFFF) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
test_ok();
}
else {
493,7 → 418,7
// ----------------------------------------------------------
// Illegal CSR access (CSR not implemented)
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Illegal CSR (0xfff) access test: ", cnt_test);
 
cnt_test++;
500,7 → 425,7
 
neorv32_cpu_csr_read(0xfff); // CSR 0xfff not implemented
 
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
test_ok();
}
else {
511,7 → 436,7
// ----------------------------------------------------------
// Write-access to read-only CSR
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Read-only CSR (time) write access test: ", cnt_test);
 
cnt_test++;
518,7 → 443,7
 
neorv32_cpu_csr_write(CSR_TIME, 0); // time CSR is read-only
 
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
test_ok();
}
else {
529,7 → 454,7
// ----------------------------------------------------------
// No "real" CSR write access (because rs1 = r0)
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Read-only CSR (time) no-write (rs1=0) access test: ", cnt_test);
 
cnt_test++;
538,7 → 463,7
// -> should cause no exception
asm volatile("csrrs zero, time, zero");
 
if (exception_handler_answer == 0xFFFFFFFF) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
test_ok();
}
else {
549,7 → 474,7
// ----------------------------------------------------------
// Unaligned instruction address
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] I_ALIGN (instruction alignment) exception test: ", cnt_test);
 
// skip if C-mode is implemented
560,7 → 485,7
// call unaligned address
((void (*)(void))ADDR_UNALIGNED)();
 
if (exception_handler_answer == TRAP_CODE_I_MISALIGNED) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_MISALIGNED) {
neorv32_uart_printf("ok\n");
cnt_ok++;
}
577,7 → 502,7
// ----------------------------------------------------------
// Instruction access fault
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] I_ACC (instruction bus access) exception test: ", cnt_test);
cnt_test++;
 
584,7 → 509,7
// call unreachable aligned address
((void (*)(void))ADDR_UNREACHABLE)();
 
if (exception_handler_answer == TRAP_CODE_I_ACCESS) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ACCESS) {
test_ok();
}
else {
595,7 → 520,7
// ----------------------------------------------------------
// Illegal instruction
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] I_ILLEG (illegal instruction) exception test: ", cnt_test);
 
cnt_test++;
603,7 → 528,7
asm volatile ("csrrw zero, 0xfff, zero"); // = 0xfff01073 : CSR 0xfff not implemented -> illegal instruction
 
// make sure this has cause an illegal exception
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
// make sure this is really the instruction that caused the exception
// for illegal instructions mtval contains the actual instruction word
if (neorv32_cpu_csr_read(CSR_MTVAL) == 0xfff01073) {
621,7 → 546,7
// ----------------------------------------------------------
// Illegal compressed instruction
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] CI_ILLEG (illegal compressed instruction) exception test: ", cnt_test);
 
// skip if C-mode is not implemented
638,7 → 563,7
tmp_a = (uint32_t)&dummy_sub_program_ci; // call the dummy sub program
asm volatile ("jalr ra, %[input_i]" : : [input_i] "r" (tmp_a));
 
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
test_ok();
}
else {
653,13 → 578,13
// ----------------------------------------------------------
// Breakpoint instruction
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] BREAK (break instruction) exception test: ", cnt_test);
cnt_test++;
 
asm volatile("EBREAK");
 
if (exception_handler_answer == TRAP_CODE_BREAKPOINT) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_BREAKPOINT) {
test_ok();
}
else {
670,7 → 595,7
// ----------------------------------------------------------
// Unaligned load address
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] L_ALIGN (load address alignment) exception test: ", cnt_test);
cnt_test++;
 
677,7 → 602,7
// load from unaligned address
asm volatile ("lw zero, %[input_i](zero)" : : [input_i] "i" (ADDR_UNALIGNED));
 
if (exception_handler_answer == TRAP_CODE_L_MISALIGNED) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_MISALIGNED) {
test_ok();
}
else {
688,7 → 613,7
// ----------------------------------------------------------
// Load access fault
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] L_ACC (load bus access) exception test: ", cnt_test);
cnt_test++;
 
695,7 → 620,7
// load from unreachable aligned address
dummy_dst = MMR_UNREACHABLE;
 
if (exception_handler_answer == TRAP_CODE_L_ACCESS) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_ACCESS) {
test_ok();
}
else {
706,7 → 631,7
// ----------------------------------------------------------
// Unaligned store address
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] S_ALIGN (store address alignment) exception test: ", cnt_test);
cnt_test++;
 
713,7 → 638,7
// store to unaligned address
asm volatile ("sw zero, %[input_i](zero)" : : [input_i] "i" (ADDR_UNALIGNED));
 
if (exception_handler_answer == TRAP_CODE_S_MISALIGNED) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_MISALIGNED) {
test_ok();
}
else {
724,7 → 649,7
// ----------------------------------------------------------
// Store access fault
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] S_ACC (store bus access) exception test: ", cnt_test);
cnt_test++;
 
731,7 → 656,7
// store to unreachable aligned address
MMR_UNREACHABLE = 0;
 
if (exception_handler_answer == TRAP_CODE_S_ACCESS) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_ACCESS) {
test_ok();
}
else {
742,13 → 667,13
// ----------------------------------------------------------
// Environment call
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] ENVCALL (ecall instruction) exception test: ", cnt_test);
cnt_test++;
 
asm volatile("ECALL");
 
if (exception_handler_answer == TRAP_CODE_MENV_CALL) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MENV_CALL) {
test_ok();
}
else {
759,7 → 684,7
// ----------------------------------------------------------
// Machine timer interrupt (MTIME)
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] MTI (machine timer) interrupt test: ", cnt_test);
 
if (neorv32_mtime_available()) {
776,7 → 701,7
asm volatile("nop");
asm volatile("nop");
 
if (exception_handler_answer == TRAP_CODE_MTI) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MTI) {
test_ok();
}
else {
794,7 → 719,7
// ----------------------------------------------------------
// Fast interrupt channel 0 (WDT)
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FIRQ0 (fast IRQ0) interrupt test (via WDT): ", cnt_test);
 
if (neorv32_wdt_available()) {
813,7 → 738,7
asm volatile("nop");
asm volatile("nop");
 
if (exception_handler_answer == TRAP_CODE_FIRQ_0) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_0) {
test_ok();
}
else {
831,53 → 756,57
// ----------------------------------------------------------
// Fast interrupt channel 1 (GPIO)
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FIRQ1 (fast IRQ1) interrupt test (via GPIO): ", cnt_test);
 
if (neorv32_gpio_available()) {
cnt_test++;
if (UART_CT & (1 << UART_CT_SIM_MODE)) { // check if this is a simulation
if (neorv32_gpio_available()) {
cnt_test++;
 
// clear output port
neorv32_gpio_port_set(0);
// clear output port
neorv32_gpio_port_set(0);
 
// configure GPIO.in(31) for pin-change IRQ
neorv32_gpio_pin_change_config(0x80000000);
// configure GPIO.in(31) for pin-change IRQ
neorv32_gpio_pin_change_config(0x80000000);
 
// trigger pin-change IRQ by setting GPIO.out(31)
// the testbench connects GPIO.out => GPIO.in
neorv32_gpio_pin_set(31);
// trigger pin-change IRQ by setting GPIO.out(31)
// the testbench connects GPIO.out => GPIO.in
neorv32_gpio_pin_set(31);
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
 
if (exception_handler_answer == TRAP_CODE_FIRQ_1) {
test_ok();
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_1) {
test_ok();
}
else {
test_fail();
}
 
// disable GPIO pin-change IRQ
neorv32_gpio_pin_change_config(0);
 
// clear output port
neorv32_gpio_port_set(0);
}
else {
test_fail();
neorv32_uart_printf("skipped (GPIO not implemented)\n");
}
 
// disable GPIO pin-change IRQ
neorv32_gpio_pin_change_config(0);
 
// clear output port
neorv32_gpio_port_set(0);
}
else {
neorv32_uart_printf("skipped (GPIO not implemented)\n");
neorv32_uart_printf("skipped (on real hardware)\n");
}
 
 
 
// ----------------------------------------------------------
// Fast interrupt channel 2 (UART)
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FIRQ2 (fast IRQ2) interrupt test (via UART): ", cnt_test);
 
if (neorv32_uart_available()) {
915,7 → 844,7
// re-enable UART sim_mode if it was enabled and disable UART TX done IRQ
UART_CT = uart_ct_backup;
 
if (exception_handler_answer == TRAP_CODE_FIRQ_2) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_2) {
test_ok();
}
else {
931,7 → 860,7
// ----------------------------------------------------------
// Fast interrupt channel 3 (SPI)
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FIRQ3 (fast IRQ3) interrupt test (via SPI): ", cnt_test);
 
if (neorv32_spi_available()) {
952,7 → 881,7
asm volatile("nop");
asm volatile("nop");
 
if (exception_handler_answer == TRAP_CODE_FIRQ_3) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_3) {
test_ok();
}
else {
970,16 → 899,17
// ----------------------------------------------------------
// Fast interrupt channel 3 (TWI)
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] FIRQ3 (fast IRQ3) interrupt test (via TWI): ", cnt_test);
 
if (neorv32_twi_available()) {
cnt_test++;
 
// configure TWI, fastest clock, transfer-done IRQ enable
neorv32_twi_setup(CLK_PRSC_2, 1);
// configure TWI, fastest clock, transfer-done IRQ enable, disable peripheral clock stretching
neorv32_twi_setup(CLK_PRSC_2, 1, 0);
 
// trigger TWI IRQ
neorv32_twi_generate_start();
neorv32_twi_trans(0);
neorv32_twi_generate_stop();
 
991,7 → 921,7
asm volatile("nop");
asm volatile("nop");
 
if (exception_handler_answer == TRAP_CODE_FIRQ_3) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_3) {
test_ok();
}
else {
1009,7 → 939,7
// ----------------------------------------------------------
// Test WFI ("sleep") instructions, wakeup via MTIME
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] WFI (wait for interrupt / sleep instruction) test (wake-up via MTIME): ", cnt_test);
 
if (neorv32_mtime_available()) {
1021,7 → 951,7
// put CPU into sleep mode
asm volatile ("wfi");
 
if (exception_handler_answer != TRAP_CODE_MTI) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_MTI) {
test_fail();
}
else {
1039,7 → 969,7
// ----------------------------------------------------------
// Test invalid CSR access in user mode
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] Invalid CSR access (mstatus) from user mode test: ", cnt_test);
 
// skip if U-mode is not implemented
1054,7 → 984,7
neorv32_cpu_csr_read(CSR_MSTATUS);
}
 
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
test_ok();
}
else {
1070,7 → 1000,7
// ----------------------------------------------------------
// Test RTE debug handler
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
neorv32_uart_printf("[%i] RTE (runtime environment) debug trap handler test: ", cnt_test);
 
cnt_test++;
1082,12 → 1012,12
neorv32_cpu_csr_read(0xfff); // CSR not available
 
neorv32_uart_printf(" ");
if (exception_handler_answer == 0xFFFFFFFF) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) != 0) {
test_ok();
}
else {
test_fail();
neorv32_uart_printf("answer: 0x%x", exception_handler_answer);
neorv32_uart_printf("answer: 0x%x", neorv32_cpu_csr_read(CSR_MCAUSE));
}
 
// restore original handler
1097,7 → 1027,6
// ----------------------------------------------------------
// Test physical memory protection
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_uart_printf("[%i] Physical memory protection (PMP): ", cnt_test);
 
// check if PMP is implemented
1105,13 → 1034,37
 
// Test access to protected region
// ---------------------------------------------
neorv32_uart_printf("Creating protected page (NAPOT, 64kB) @ 0xFFFFA000, [!x, !w, r]... ");
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
cnt_test++;
 
neorv32_cpu_csr_write(CSR_PMPADDR0, 0xffffdfff); // 64k area @ 0xFFFFA000
neorv32_cpu_csr_write(CSR_PMPCFG0, 0b00011001); // NAPOT, read permission, NO write and NO execute permissions
// check min granulartiy
neorv32_cpu_csr_write(CSR_PMPCFG0, 0);
neorv32_cpu_csr_write(CSR_PMPADDR0, 0xffffffff);
tmp_a = neorv32_cpu_csr_read(0x3b0);
 
if ((neorv32_cpu_csr_read(CSR_PMPADDR0) == 0xffffdfff) && (neorv32_cpu_csr_read(CSR_PMPCFG0) == 0b00011001)) {
// find least-significat set bit
for (i=31; i!=0; i--) {
if (((tmp_a >> i) & 1) == 0) {
break;
}
}
 
tmp_a = SYSINFO_DSPACE_BASE; // base address of protected region
 
tmp_b = 0;
for (j=i; j!=0; j--) {
tmp_b = tmp_b << 1;
tmp_b = tmp_b | 1;
}
tmp_c = tmp_a & (~tmp_b); // clear LSBs in base address
tmp_c = tmp_c | tmp_b; // set region size config
 
neorv32_uart_printf("Creating protected page (NAPOT, [!X,!W,R], %u bytes) @ 0x%x (PMPADDR = 0x%x): ", (uint32_t)(1 << (i+1+2)), tmp_a, tmp_c);
 
neorv32_cpu_csr_write(CSR_PMPADDR0, tmp_c); // 64k area @ 0xFFFFA000
neorv32_cpu_csr_write(CSR_PMPCFG0, 0b00011001); // NAPOT, read permission, NO write and NO execute permissions
 
if ((neorv32_cpu_csr_read(CSR_PMPADDR0) == tmp_c) && (neorv32_cpu_csr_read(CSR_PMPCFG0) == 0b00011001) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
test_ok();
}
else {
1119,18 → 1072,43
}
 
 
// ------ EXECUTE: should fail ------
neorv32_uart_printf("[%i] - PMP: U-mode [!X,!W,R] execute test: ", cnt_test);
cnt_test++;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
{
asm volatile ("jalr ra, %[input_i]" : : [input_i] "r" (tmp_a)); // call address to execute -> should fail
}
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
// switch back to machine mode (if not allready)
asm volatile ("ecall");
 
test_fail();
}
else {
// switch back to machine mode (if not allready)
asm volatile ("ecall");
 
test_ok();
}
 
 
// ------ LOAD: should work ------
neorv32_uart_printf("[%i] PMP: U-mode [!X,!W,R] load test: ", cnt_test);
neorv32_uart_printf("[%i] - PMP: U-mode [!X,!W,R] read test: ", cnt_test);
cnt_test++;
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
{
asm volatile ("lw zero, 0xFFFFFF90(zero)"); // MTIME load access, should work
asm volatile ("lw zero, 0(%[input_i])" : : [input_i] "r" (tmp_a)); // load access -> should work
}
 
if (exception_handler_answer == 0xFFFFFFFF) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
// switch back to machine mode (if not allready)
asm volatile ("ecall");
 
1145,17 → 1123,17
 
 
// ------ STORE: should fail ------
neorv32_uart_printf("[%i] PMP: U-mode [!X,!W,R] store test: ", cnt_test);
neorv32_uart_printf("[%i] - PMP: U-mode [!X,!W,R] write test: ", cnt_test);
cnt_test++;
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
{
asm volatile ("sw zero, 0xFFFFFF90(zero)"); // MTIME store access, should fail
asm volatile ("sw zero, 0(%[input_i])" : : [input_i] "r" (tmp_a)); // store access -> should fail
}
 
if (exception_handler_answer == TRAP_CODE_S_ACCESS) {
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_ACCESS) {
// switch back to machine mode (if not allready)
asm volatile ("ecall");
 
1169,18 → 1147,18
}
 
 
// ------ Lock test ------
neorv32_uart_printf("[%i] PMP: Locking pmpcfg0 [mode=off]: ", cnt_test);
// ------ Lock test - pmpcfg0.0 ------
neorv32_uart_printf("[%i] - PMP: pmpcfg0.0 [mode=off] lock test: ", cnt_test);
cnt_test++;
exception_handler_answer = 0xFFFFFFFF;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
neorv32_cpu_csr_write(CSR_PMPCFG0, 0b10000001); // locked but entry is deactivated (mode = off)
neorv32_cpu_csr_write(CSR_PMPCFG0, 0b10000001); // locked, but entry is deactivated (mode = off)
 
// make sure a locked cfg cannot be written
tmp_a = neorv32_cpu_csr_read(CSR_PMPCFG0);
neorv32_cpu_csr_write(CSR_PMPCFG0, 0b00011001); // try to re-write CFG content
 
if ((tmp_a != neorv32_cpu_csr_read(CSR_PMPCFG0)) || (exception_handler_answer != 0xFFFFFFFF)) {
if ((tmp_a != neorv32_cpu_csr_read(CSR_PMPCFG0)) || (neorv32_cpu_csr_read(CSR_MCAUSE) != 0)) {
test_fail();
}
else {
1187,6 → 1165,25
test_ok();
}
 
 
// ------ Lock test - pmpaddr0 ------
neorv32_uart_printf("[%i] - PMP: pmpaddr0 [mode=off] lock test: ", cnt_test);
cnt_test++;
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
neorv32_cpu_csr_write(CSR_PMPCFG0, 0b10000001); // locked, but entry is deactivated (mode = off)
 
// make sure a locked cfg cannot be written
tmp_a = neorv32_cpu_csr_read(CSR_PMPADDR0);
neorv32_cpu_csr_write(CSR_PMPADDR0, 0xABABCDCD); // try to re-write ADDR content
 
if ((tmp_a != neorv32_cpu_csr_read(CSR_PMPADDR0)) || (neorv32_cpu_csr_read(CSR_MCAUSE) != 0)) {
test_fail();
}
else {
test_ok();
}
 
}
else {
neorv32_uart_printf("not implemented\n");
1196,17 → 1193,17
// ----------------------------------------------------------
// Final test reports
// ----------------------------------------------------------
neorv32_uart_printf("\n\nExecuted instructions: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_INSTRET));
neorv32_uart_printf( "Required clock cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_CYCLE));
neorv32_uart_printf("\nExecuted instructions: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_INSTRET));
neorv32_uart_printf( "Required clock cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_CYCLE));
 
neorv32_uart_printf("\nTest results:\nOK: %i/%i\nFAILED: %i/%i\n\n", cnt_ok, cnt_test, cnt_fail, cnt_test);
 
// final result
if (cnt_fail == 0) {
neorv32_uart_printf("%c[1mTEST OK!%c[0m\n", 27, 27);
neorv32_uart_printf("%c[1m[TEST OK!]%c[0m\n", 27, 27);
}
else {
neorv32_uart_printf("%c[1mTEST FAILED!%c[0m\n", 27, 27);
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27);
}
 
return 0;
1218,8 → 1215,6
**************************************************************************/
void global_trap_handler(void) {
 
exception_handler_answer = neorv32_cpu_csr_read(CSR_MCAUSE);
 
// hack: always come back in MACHINE MODE
register uint32_t mask = (1<<CPU_MSTATUS_MPP_H) | (1<<CPU_MSTATUS_MPP_L);
asm volatile ("csrrs zero, mstatus, %[input_j]" : : [input_j] "r" (mask));
/demo_twi/main.c
60,9 → 60,9
 
 
/**********************************************************************//**
* This program generates a simple dimming sequence for PWM channel 0,1,2.
* This program provides an interactive console to communicate with TWI devices.
*
* @note This program requires the UART and the TWI to be synthesized.
* @note This program requires the UART and the PWM to be synthesized.
*
* @return Irrelevant.
**************************************************************************/
101,8 → 101,8
neorv32_uart_printf("This program allows to create TWI transfers by hand.\n"
"Type 'help' to see the help menu.\n\n");
 
// configure TWI, second slowest clock, no IRQ
neorv32_twi_setup(CLK_PRSC_2048, 0);
// configure TWI, second slowest clock, no IRQ, no clock-stretching
neorv32_twi_setup(CLK_PRSC_2048, 0, 0);
 
// no active bus session yet
bus_claimed = 0;
/hex_viewer/main.c
0,0 → 1,271
// #################################################################################################
// # << NEORV32 - Hex Viewer - Memory Inspector >> #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2020, 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 hex_viewer/main.c
* @author Stephan Nolting
* @brief Interactive memory inspector.
**************************************************************************/
 
#include <neorv32.h>
#include <string.h>
 
 
/**********************************************************************//**
* @name User configuration
**************************************************************************/
/**@{*/
/** UART BAUD rate */
#define BAUD_RATE 19200
/**@}*/
 
 
// Prototypes
void read_memory(void);
void write_memory(void);
void dump_memory(void);
uint32_t hexstr_to_uint(char *buffer, uint8_t length);
 
 
/**********************************************************************//**
* This program provides an interactive console to read/write memory.
*
* @note This program requires the UART to be synthesized.
*
* @return Irrelevant.
**************************************************************************/
int main() {
 
char buffer[8];
int length = 0;
 
// check if UART unit is implemented at all
if (neorv32_uart_available() == 0) {
return 0;
}
 
 
// capture all exceptions and give debug info via UART
neorv32_rte_setup();
 
 
// init UART at default baud rate, no rx interrupt, no tx interrupt
neorv32_uart_setup(BAUD_RATE, 0, 0);
 
// intro
neorv32_uart_printf("\n--- Hex Viewer ---\n\n");
 
// info
neorv32_uart_printf("This program allows to read/write/dump memory locations by hand.\n"
"Type 'help' to see the help menu.\n\n");
 
// Main menu
for (;;) {
neorv32_uart_printf("HEX_VIEWER:> ");
length = neorv32_uart_scan(buffer, 8, 1);
neorv32_uart_printf("\n");
 
if (!length) // nothing to be done
continue;
 
// decode input and execute command
if (!strcmp(buffer, "help")) {
neorv32_uart_printf("Available commands:\n"
" help - show this text\n"
" read - read single word from address\n"
" write - write single word to address\n"
" dump - dumpe several words from base address\n\n");
}
 
else if (!strcmp(buffer, "read")) {
read_memory();
}
 
else if (!strcmp(buffer, "write")) {
write_memory();
}
 
else if (!strcmp(buffer, "dump")) {
dump_memory();
}
 
else {
neorv32_uart_printf("Invalid command. Type 'help' to see all commands.\n");
}
}
 
return 0;
}
 
 
/**********************************************************************//**
* Read word from memory address
**************************************************************************/
void read_memory(void) {
 
char terminal_buffer[16];
 
// enter address
neorv32_uart_printf("Enter address (8 hex chars): ");
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
register uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
mem_address = mem_address & 0xFFFFFFFCUL; // align to 32-bit boundary
 
// perform read access
neorv32_uart_printf("\n[0x%x] = ", mem_address);
 
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
register uint32_t mem_data = 0;
 
asm volatile ("lw %[rdata], 0(%[raddr])" : [rdata] "=r" (mem_data) : [raddr] "r" (mem_address));
 
// show memory content if there was no exception
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
neorv32_uart_printf("0x%x", mem_data);
}
 
neorv32_uart_printf("\n");
}
 
 
/**********************************************************************//**
* Write word tp memory address
**************************************************************************/
void write_memory(void) {
 
char terminal_buffer[16];
 
// enter address
neorv32_uart_printf("Enter address (8 hex chars): ");
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
register uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
mem_address = mem_address & 0xFFFFFFFCUL; // align to 32-bit boundary
 
// enter data
neorv32_uart_printf("\nEnter data (8 hex chars): ");
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
register uint32_t mem_data = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
 
// perform write access
neorv32_uart_printf("\n[0x%x] = ", mem_address);
 
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
asm volatile ("sw %[wdata], 0(%[waddr])" : : [wdata] "r" (mem_data), [waddr] "r" (mem_address));
asm volatile ("nop");
 
// show memory content if there was no exception
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
neorv32_uart_printf("0x%x", mem_data);
}
 
neorv32_uart_printf("\n");
}
 
 
/**********************************************************************//**
* Read several words from memory base address
**************************************************************************/
void dump_memory(void) {
 
char terminal_buffer[16];
 
// enter base address
neorv32_uart_printf("Enter base address (8 hex chars): ");
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0'
register uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
mem_address = mem_address & 0xFFFFFFFCUL; // align to 32-bit boundary
 
neorv32_uart_printf("\nPress key to start dumping. Press any key to abort.\n");
 
neorv32_uart_getc(); // wait for key
 
// perform read accesses
register uint32_t mem_data = 0;
while(neorv32_uart_char_received() == 0) {
 
neorv32_uart_printf("[0x%x] = ", mem_address);
 
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
asm volatile ("lw %[rdata], 0(%[raddr])" : [rdata] "=r" (mem_data) : [raddr] "r" (mem_address));
asm volatile ("nop");
 
// show memory content if there was no exception
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
neorv32_uart_printf("0x%x\n", mem_data);
}
else {
break;
}
 
mem_address = mem_address + 4;
 
}
neorv32_uart_char_received_get(); // clear UART rx buffer
neorv32_uart_printf("\n");
}
 
 
/**********************************************************************//**
* Helper function to convert N hex chars string into uint32_T
*
* @param[in,out] buffer Pointer to array of chars to convert into number.
* @param[in,out] length Length of the conversion string.
* @return Converted number.
**************************************************************************/
uint32_t hexstr_to_uint(char *buffer, uint8_t length) {
 
uint32_t res = 0, d = 0;
char c = 0;
 
while (length--) {
c = *buffer++;
 
if ((c >= '0') && (c <= '9'))
d = (uint32_t)(c - '0');
else if ((c >= 'a') && (c <= 'f'))
d = (uint32_t)((c - 'a') + 10);
else if ((c >= 'A') && (c <= 'F'))
d = (uint32_t)((c - 'A') + 10);
else
d = 0;
 
res = res + (d << (length*4));
}
 
return res;
}
/hex_viewer/makefile
0,0 → 1,338
#################################################################################################
# << NEORV32 - Application Makefile >> #
# ********************************************************************************************* #
# Make sure to add the riscv GCC compiler's bin folder to your PATH environment variable. #
# ********************************************************************************************* #
# BSD 3-Clause License #
# #
# Copyright (c) 2020, 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 #
#################################################################################################
 
 
# *****************************************************************************
# USER CONFIGURATION
# *****************************************************************************
# User's application sources (*.c, *.cpp, *.s, *.S); add additional files here
APP_SRC ?= $(wildcard ./*.c) $(wildcard ./*.s) $(wildcard ./*.cpp) $(wildcard ./*.S)
 
# User's application include folders (don't forget the '-I' before each entry)
APP_INC ?= -I .
# User's application include folders - for assembly files only (don't forget the '-I' before each entry)
ASM_INC ?= -I .
 
# Optimization
EFFORT ?= -Os
 
# Compiler toolchain
RISCV_TOOLCHAIN ?= riscv32-unknown-elf
 
# CPU architecture and ABI
MARCH ?= -march=rv32i
MABI ?= -mabi=ilp32
 
# User flags for additional configuration (will be added to compiler flags)
USER_FLAGS ?=
 
# Serial port for executable upload via bootloer
COM_PORT ?= /dev/ttyUSB0
 
# Relative or absolute path to the NEORV32 home folder
NEORV32_HOME ?= ../../..
# *****************************************************************************
 
 
 
# -----------------------------------------------------------------------------
# NEORV32 framework
# -----------------------------------------------------------------------------
# Path to NEORV32 linker script and startup file
NEORV32_COM_PATH = $(NEORV32_HOME)/sw/common
# Path to main NEORV32 library include files
NEORV32_INC_PATH = $(NEORV32_HOME)/sw/lib/include
# Path to main NEORV32 library source files
NEORV32_SRC_PATH = $(NEORV32_HOME)/sw/lib/source
# Path to NEORV32 executable generator
NEORV32_EXG_PATH = $(NEORV32_HOME)/sw/image_gen
# Path to NEORV32 core rtl folder
NEORV32_RTL_PATH = $(NEORV32_HOME)/rtl/core
# Marker file to check for NEORV32 home folder
NEORV32_HOME_MARKER = $(NEORV32_INC_PATH)/neorv32.h
 
# Core libraries (peripheral and CPU drivers)
CORE_SRC = $(wildcard $(NEORV32_SRC_PATH)/*.c)
# Application start-up code
CORE_SRC += $(NEORV32_COM_PATH)/crt0.S
 
# Linker script
LD_SCRIPT = $(NEORV32_COM_PATH)/neorv32.ld
 
# Main output files
APP_EXE = neorv32_exe.bin
APP_ASM = main.asm
APP_IMG = neorv32_application_image.vhd
BOOT_IMG = neorv32_bootloader_image.vhd
 
 
# -----------------------------------------------------------------------------
# Sources and objects
# -----------------------------------------------------------------------------
# Define all sources
SRC = $(APP_SRC)
SRC += $(CORE_SRC)
 
# Define all object files
OBJ = $(SRC:%=%.o)
 
 
# -----------------------------------------------------------------------------
# Tools and flags
# -----------------------------------------------------------------------------
# Compiler tools
CC = $(RISCV_TOOLCHAIN)-gcc
OBJDUMP = $(RISCV_TOOLCHAIN)-objdump
OBJCOPY = $(RISCV_TOOLCHAIN)-objcopy
SIZE = $(RISCV_TOOLCHAIN)-size
 
# Host native compiler
CC_X86 = gcc -Wall -O -g
 
# NEORV32 executable image generator
IMAGE_GEN = $(NEORV32_EXG_PATH)/image_gen
 
# Compiler & linker flags
CC_OPTS = $(MARCH) $(MABI) $(EFFORT) -Wall -ffunction-sections -fdata-sections -nostartfiles
CC_OPTS += -Wl,--gc-sections -lm -lc -lgcc -lc
# This accelerates instruction fetch after branches when C extension is enabled (irrelevant when C extension is disabled)
CC_OPTS += -falign-functions=4 -falign-labels=4 -falign-loops=4 -falign-jumps=4
CC_OPTS += $(USER_FLAGS)
 
 
# -----------------------------------------------------------------------------
# Application output definitions
# -----------------------------------------------------------------------------
.PHONY: check info help elf_info clean clean_all bootloader
.DEFAULT_GOAL := help
 
# 'compile' is still here for compatibility
exe: $(APP_ASM) $(APP_EXE)
compile: $(APP_ASM) $(APP_EXE)
install: $(APP_ASM) $(APP_IMG)
all: $(APP_ASM) $(APP_EXE) $(APP_IMG)
 
# Check if making bootloader
# Use different base address and legth for instruction memory/"rom" (BOOTMEM instead of IMEM)
# Also define "make_bootloader" for crt0.S
target bootloader: CC_OPTS += -Wl,--defsym=make_bootloader=1 -Dmake_bootloader
 
 
# -----------------------------------------------------------------------------
# Image generator targets
# -----------------------------------------------------------------------------
# install/compile tools
$(IMAGE_GEN): $(NEORV32_EXG_PATH)/image_gen.cpp
@echo Compiling $(IMAGE_GEN)
@$(CC_X86) $< -o $(IMAGE_GEN)
 
 
# -----------------------------------------------------------------------------
# General targets: Assemble, compile, link, dump
# -----------------------------------------------------------------------------
# Compile app *.s sources (assembly)
%.s.o: %.s
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(ASM_INC) $< -o $@
 
# Compile app *.S sources (assembly + C pre-processor)
%.S.o: %.S
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(ASM_INC) $< -o $@
 
# Compile app *.c sources
%.c.o: %.c
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(APP_INC) $< -o $@
 
# Compile app *.cpp sources
%.cpp.o: %.cpp
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(APP_INC) $< -o $@
 
# Link object files and show memory utilization
main.elf: $(OBJ)
@$(CC) $(CC_OPTS) -T $(LD_SCRIPT) $(OBJ) -o $@
@echo "Memory utilization:"
@$(SIZE) main.elf
 
# Assembly listing file (for debugging)
$(APP_ASM): main.elf
@$(OBJDUMP) -D -S -z $< > $@
 
# Generate final executable from .text + .rodata + .data (in THIS order!)
main.bin: main.elf $(APP_ASM)
@$(OBJCOPY) -I elf32-little $< -j .text -O binary text.bin
@$(OBJCOPY) -I elf32-little $< -j .rodata -O binary rodata.bin
@$(OBJCOPY) -I elf32-little $< -j .data -O binary data.bin
@cat text.bin rodata.bin data.bin > $@
@rm -f text.bin rodata.bin data.bin
 
 
# -----------------------------------------------------------------------------
# Application targets: Generate binary executable, install (as VHDL file)
# -----------------------------------------------------------------------------
# Generate NEORV32 executable image for upload via bootloader
$(APP_EXE): main.bin $(IMAGE_GEN)
@set -e
@$(IMAGE_GEN) -app_bin $< $@ $(shell basename $(CURDIR))
@echo "Executable ($(APP_EXE)) size in bytes:"
@wc -c < $(APP_EXE)
 
# Generate NEORV32 executable VHDL boot image
$(APP_IMG): main.bin $(IMAGE_GEN)
@set -e
@$(IMAGE_GEN) -app_img $< $@ $(shell basename $(CURDIR))
@echo "Installing application image to $(NEORV32_RTL_PATH)/$(APP_IMG)"
@cp $(APP_IMG) $(NEORV32_RTL_PATH)/.
 
 
# -----------------------------------------------------------------------------
# Bootloader targets
# -----------------------------------------------------------------------------
# Create and install bootloader VHDL init image
$(BOOT_IMG): main.bin $(IMAGE_GEN)
@set -e
@$(IMAGE_GEN) -bld_img $< $(BOOT_IMG) $(shell basename $(CURDIR))
@echo "Installing bootloader image to $(NEORV32_RTL_PATH)/$(BOOT_IMG)"
@cp $(BOOT_IMG) $(NEORV32_RTL_PATH)/.
 
# Just an alias that
bootloader: $(BOOT_IMG)
 
 
# -----------------------------------------------------------------------------
# Check toolchain
# -----------------------------------------------------------------------------
check: $(IMAGE_GEN)
@echo "---------------- Check: NEORV32_HOME folder ----------------"
ifneq ($(shell [ -e $(NEORV32_HOME_MARKER) ] && echo 1 || echo 0 ), 1)
$(error NEORV32_HOME folder not found!)
endif
@echo "NEORV32_HOME: $(NEORV32_HOME)"
@echo "---------------- Check: $(CC) ----------------"
@$(CC) -v
@echo "---------------- Check: $(OBJDUMP) ----------------"
@$(OBJDUMP) -V
@echo "---------------- Check: $(OBJCOPY) ----------------"
@$(OBJCOPY) -V
@echo "---------------- Check: $(SIZE) ----------------"
@$(SIZE) -V
@echo "---------------- Check: NEORV32 image_gen ----------------"
@$(IMAGE_GEN) -help
@echo "---------------- Check: Native GCC ----------------"
@$(CC_X86) -v
@echo
@echo "Toolchain check OK"
 
 
# -----------------------------------------------------------------------------
# Upload executable via serial port to bootloader
# -----------------------------------------------------------------------------
upload: $(APP_EXE)
@sh $(NEORV32_EXG_PATH)/uart_upload.sh $(COM_PORT) $(APP_EXE)
 
 
# -----------------------------------------------------------------------------
# Show configuration
# -----------------------------------------------------------------------------
info:
@echo "---------------- Info: Project ----------------"
@echo "Project folder: $(shell basename $(CURDIR))"
@echo "Source files: $(APP_SRC)"
@echo "Include folder(s): $(APP_INC)"
@echo "ASM include folder(s): $(ASM_INC)"
@echo "---------------- Info: NEORV32 ----------------"
@echo "NEORV32 home folder (NEORV32_HOME): $(NEORV32_HOME)"
@echo "IMAGE_GEN: $(IMAGE_GEN)"
@echo "Core source files:"
@echo "$(CORE_SRC)"
@echo "Core include folder:"
@echo "$(NEORV32_INC_PATH)"
@echo "---------------- Info: Objects ----------------"
@echo "Project object files:"
@echo "$(OBJ)"
@echo "---------------- Info: RISC-V CPU ----------------"
@echo "MARCH: $(MARCH)"
@echo "MABI: $(MABI)"
@echo "---------------- Info: Toolchain ----------------"
@echo "Toolchain: $(RISCV_TOLLCHAIN)"
@echo "CC: $(CC)"
@echo "OBJDUMP: $(OBJDUMP)"
@echo "OBJCOPY: $(OBJCOPY)"
@echo "SIZE: $(SIZE)"
@echo "---------------- Info: Compiler Libraries ----------------"
@echo "LIBGCC:"
@$(CC) -print-libgcc-file-name
@echo "SEARCH-DIRS:"
@$(CC) -print-search-dirs
@echo "---------------- Info: Flags ----------------"
@echo "USER_FLAGS: $(USER_FLAGS)"
@echo "CC_OPTS: $(CC_OPTS)"
@echo "---------------- Info: Host Native GCC Flags ----------------"
@echo "CC_X86: $(CC_X86)"
 
 
# -----------------------------------------------------------------------------
# Show final ELF details (just for debugging)
# -----------------------------------------------------------------------------
elf_info: main.elf
@$(OBJDUMP) -x main.elf
 
 
# -----------------------------------------------------------------------------
# Help
# -----------------------------------------------------------------------------
help:
@echo "<<< NEORV32 Application Makefile >>>"
@echo "Make sure to add the bin folder of RISC-V GCC to your PATH variable."
@echo "Targets:"
@echo " help - show this text"
@echo " check - check toolchain"
@echo " info - show makefile/toolchain configuration"
@echo " exe - compile and generate <neorv32_exe.bin> executable for upload via bootloader"
@echo " install - compile, generate and install VHDL IMEM boot image (for application)"
@echo " all - compile and generate <neorv32_exe.bin> executable for upload via bootloader and generate and install VHDL IMEM boot image (for application)"
@echo " clean - clean up project"
@echo " clean_all - clean up project, core libraries and image generator"
@echo " bootloader - compile, generate and install VHDL BOOTROM boot image (for bootloader only!)"
@echo " upload - upload <neorv32_exe.bin> executable via serial port <COM_PORT> to bootloader"
 
 
# -----------------------------------------------------------------------------
# Clean up
# -----------------------------------------------------------------------------
clean:
@rm -f *.elf *.o *.bin *.out *.asm *.vhd
 
clean_all: clean
@rm -f $(OBJ) $(IMAGE_GEN)

powered by: WebSVN 2.1.0

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