diff --git a/sw/lib/include/neorv32.h b/sw/lib/include/neorv32.h index 73df342b..85a9fd12 100644 --- a/sw/lib/include/neorv32.h +++ b/sw/lib/include/neorv32.h @@ -175,16 +175,18 @@ extern "C" { /**********************************************************************//** - * @name Export linker script symbols + * @name NEORV32 linker symbols **************************************************************************/ /**@{*/ extern char __heap_start[]; /**< heap start address */ extern char __heap_end[]; /**< heap last address */ extern char __crt0_max_heap[]; /**< heap size in bytes */ +extern char __crt0_entry[]; /**< crt0 entry point */ // aliases #define NEORV32_HEAP_BEGIN ((uint32_t)&__heap_start[0]) #define NEORV32_HEAP_END ((uint32_t)&__heap_end[0]) #define NEORV32_HEAP_SIZE ((uint32_t)&__crt0_max_heap[0]) +#define NEORV32_CRT0_ENTRY ((uint32_t)&__crt0_entry[0]) /**@}*/ diff --git a/sw/lib/include/neorv32_cpu.h b/sw/lib/include/neorv32_cpu.h index 5fa03f2f..80ce16a4 100644 --- a/sw/lib/include/neorv32_cpu.h +++ b/sw/lib/include/neorv32_cpu.h @@ -33,6 +33,20 @@ uint32_t neorv32_cpu_hpm_get_size(void); /**@}*/ +/**********************************************************************//** + * Restart CPU core (jump to boot address). + * + * @warning This is just a "software reset" that uses the in-code reset/boot/entry address linked at compile time. + **************************************************************************/ +inline void __attribute__ ((always_inline)) neorv32_cpu_soft_restart(void) { + + uint32_t sw_boot_addr = NEORV32_CRT0_ENTRY; // linker symbol + asm volatile ("jalr x0, 0(%[dst])" : : [dst] "r" (sw_boot_addr)); + __builtin_unreachable(); + while(1); // should never be reached +} + + /**********************************************************************//** * Store unsigned word to address space. * diff --git a/sw/lib/include/neorv32_wdt.h b/sw/lib/include/neorv32_wdt.h index 552ec7d5..27e92512 100644 --- a/sw/lib/include/neorv32_wdt.h +++ b/sw/lib/include/neorv32_wdt.h @@ -69,6 +69,7 @@ int neorv32_wdt_available(void); void neorv32_wdt_setup(uint32_t timeout, int lock, int strict); int neorv32_wdt_disable(void); void neorv32_wdt_feed(uint32_t password); +void neorv32_wdt_force_hwreset(void); int neorv32_wdt_get_cause(void); /**@}*/ diff --git a/sw/lib/source/neorv32_wdt.c b/sw/lib/source/neorv32_wdt.c index af807dbb..47e7b85f 100644 --- a/sw/lib/source/neorv32_wdt.c +++ b/sw/lib/source/neorv32_wdt.c @@ -90,6 +90,21 @@ void neorv32_wdt_feed(uint32_t password) { } +/**********************************************************************//** + * Force a hardware reset triggered by the watchdog. + **************************************************************************/ +void neorv32_wdt_force_hwreset(void) { + + // enable strict mode; if strict mode is already enabled and the WDT + // is locked this will already trigger a hardware reset + NEORV32_WDT->CTRL |= (uint32_t)(1 << WDT_CTRL_STRICT); + + // try to reset the WDT using an incorrect password; + // this will finally trigger a hardware reset + NEORV32_WDT->RESET = 0; +} + + /**********************************************************************//** * Get cause of last system reset. *