Skip to content

Commit a5db2e6

Browse files
jaz1-nordiccarlescufi
authored andcommitted
applications: sdp: mspi: add trap handler for SDP app
Implementation of trap handler. Signals status to host and sends dump of most important registers at the time of error. Signed-off-by: Jakub Zymelka <[email protected]>
1 parent e86a306 commit a5db2e6

File tree

5 files changed

+129
-10
lines changed

5 files changed

+129
-10
lines changed

applications/sdp/mspi/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@
1111
#size-cells = <1>;
1212

1313
sram_tx: memory@2003c000 {
14-
reg = <0x2003c000 0x0800>;
14+
reg = <0x2003c000 0x07f0>;
1515
};
1616

17-
sram_rx: memory@2003c800 {
18-
reg = <0x2003c800 0x0800>;
17+
sram_rx: memory@2003c7f0 {
18+
reg = <0x2003c7f0 0x07f0>;
19+
};
20+
21+
cpuflpr_error_code: memory@2003cfe0 {
22+
reg = <0x2003cfe0 0x0020>; /* 32bytes */
1923
};
2024
};
2125
};

applications/sdp/mspi/src/main.c

Lines changed: 97 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ static atomic_t ipc_atomic_sem = ATOMIC_INIT(0);
8080
#if defined(CONFIG_SDP_MSPI_FAULT_TIMER)
8181
static NRF_TIMER_Type *fault_timer;
8282
#endif
83+
static volatile uint32_t *cpuflpr_error_ctx_ptr =
84+
(uint32_t *)DT_REG_ADDR(DT_NODELABEL(cpuflpr_error_code));
8385

8486
static void adjust_tail(volatile hrt_xfer_data_t *xfer_data, uint16_t frame_width,
8587
uint32_t data_length)
@@ -368,15 +370,14 @@ static void ep_recv(const void *data, size_t len, void *priv)
368370

369371
(void)priv;
370372
(void)len;
371-
nrfe_mspi_flpr_response_msg_t response;
372373
uint8_t opcode = *(uint8_t *)data;
373374
uint32_t num_bytes = 0;
375+
374376
#if defined(CONFIG_SDP_MSPI_FAULT_TIMER)
375377
if (fault_timer != NULL) {
376378
nrf_timer_task_trigger(fault_timer, NRF_TIMER_TASK_START);
377379
}
378380
#endif
379-
response.opcode = opcode;
380381

381382
switch (opcode) {
382383
#if defined(CONFIG_SDP_MSPI_FAULT_TIMER)
@@ -513,10 +514,103 @@ __attribute__((interrupt)) void hrt_handler_write(void)
513514
hrt_write((hrt_xfer_t *)&xfer_params);
514515
}
515516

517+
/**
518+
* @brief Trap handler for SDP application.
519+
*
520+
* @details
521+
* This function is called on unhandled CPU exceptions. It's a good place to
522+
* handle critical errors and notify the core that the SDP application has
523+
* crashed.
524+
*
525+
* @param mcause - cause of the exception (from mcause register)
526+
* @param mepc - address of the instruction that caused the exception (from mepc register)
527+
* @param mtval - additional value (e.g. bad address)
528+
* @param context - pointer to the saved context (only some registers are saved - ra, t0, t1, t2)
529+
*/
530+
void trap_handler(uint32_t mcause, uint32_t mepc, uint32_t mtval, void *context)
531+
{
532+
const uint8_t fault_opcode = NRFE_MSPI_SDP_APP_HARD_FAULT;
533+
534+
/* It can be distinguish whether the exception was caused by an interrupt or an error:
535+
* On RV32, bit 31 of the mcause register indicates whether the event is an interrupt.
536+
*/
537+
if (mcause & 0x80000000) {
538+
/* Interrupt – can be handled or ignored */
539+
} else {
540+
/* Exception – critical error */
541+
}
542+
543+
cpuflpr_error_ctx_ptr[0] = mcause;
544+
cpuflpr_error_ctx_ptr[1] = mepc;
545+
cpuflpr_error_ctx_ptr[2] = mtval;
546+
cpuflpr_error_ctx_ptr[3] = (uint32_t)context;
547+
548+
ipc_service_send(&ep, &fault_opcode, sizeof(fault_opcode));
549+
550+
while (1) {
551+
/* Loop forever */
552+
}
553+
}
554+
555+
/* The trap_entry function is the entry point for exception handling.
556+
* The naked attribute prevents the compiler from generating an automatic prologue/epilogue.
557+
*/
558+
__attribute__((naked)) void trap_entry(void)
559+
{
560+
__asm__ volatile(
561+
/* Reserve space on the stack:
562+
* 16 bytes for 4 registers context (ra, t0, t1, t2).
563+
*/
564+
"addi sp, sp, -16\n"
565+
"sw ra, 12(sp)\n"
566+
"sw t0, 8(sp)\n"
567+
"sw t1, 4(sp)\n"
568+
"sw t2, 0(sp)\n"
569+
570+
/* Read CSR: mcause, mepc, mtval */
571+
"csrr t0, mcause\n" /* t0 = mcause */
572+
"csrr t1, mepc\n" /* t1 = mepc */
573+
"csrr t2, mtval\n" /* t2 = mtval */
574+
575+
/* Prepare arguments for trap_handler function:
576+
* a0 = mcause (t0), a1 = mepc (t1), a2 = mtval (t2), a3 = sp (pointer on context).
577+
*/
578+
"mv a0, t0\n"
579+
"mv a1, t1\n"
580+
"mv a2, t2\n"
581+
"mv a3, sp\n"
582+
583+
"call trap_handler\n"
584+
585+
/* Restore registers values */
586+
"lw ra, 12(sp)\n"
587+
"lw t0, 8(sp)\n"
588+
"lw t1, 4(sp)\n"
589+
"lw t2, 0(sp)\n"
590+
"addi sp, sp, 16\n"
591+
592+
"mret\n");
593+
}
594+
595+
void init_trap_handler(void)
596+
{
597+
/* Write the address of the trap_entry function into the mtvec CSR.
598+
* Note: On RV32, the address must be aligned to 4 bytes.
599+
*/
600+
uintptr_t trap_entry_addr = (uintptr_t)&trap_entry;
601+
602+
__asm__ volatile("csrw mtvec, %0\n"
603+
: /* no outs */
604+
: "r"(trap_entry_addr));
605+
}
606+
516607
int main(void)
517608
{
518-
int ret = backend_init();
609+
int ret = 0;
610+
611+
init_trap_handler();
519612

613+
ret = backend_init();
520614
if (ret < 0) {
521615
return 0;
522616
}

drivers/mspi/mspi_nrfe.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ SDP_MSPI_PINCTRL_DT_DEFINE(MSPI_NRFE_NODE);
4545
static struct ipc_ept ep;
4646
static size_t ipc_received;
4747
static uint8_t *ipc_receive_buffer;
48+
static volatile uint32_t *cpuflpr_error_ctx_ptr =
49+
(uint32_t *)DT_REG_ADDR(DT_NODELABEL(cpuflpr_error_code));
4850

4951
#if defined(CONFIG_MULTITHREADING)
5052
static K_SEM_DEFINE(ipc_sem, 0, 1);
@@ -168,6 +170,21 @@ static void ep_recv(const void *data, size_t len, void *priv)
168170
#endif
169171
break;
170172
}
173+
case NRFE_MSPI_SDP_APP_HARD_FAULT: {
174+
175+
volatile uint32_t cause = cpuflpr_error_ctx_ptr[0];
176+
volatile uint32_t pc = cpuflpr_error_ctx_ptr[1];
177+
volatile uint32_t bad_addr = cpuflpr_error_ctx_ptr[2];
178+
volatile uint32_t *ctx = (volatile uint32_t *)cpuflpr_error_ctx_ptr[3];
179+
180+
LOG_ERR(">>> SDP APP FATAL ERROR");
181+
LOG_ERR("Faulting instruction address (mepc): 0x%08x", pc);
182+
LOG_ERR("mcause: 0x%08x, mtval: 0x%08x, ra: 0x%08x", cause, bad_addr, ctx[0]);
183+
LOG_ERR(" t0: 0x%08x, t1: 0x%08x, t2: 0x%08x", ctx[1], ctx[2], ctx[3]);
184+
185+
LOG_ERR("SDP application halted...");
186+
break;
187+
}
171188
default: {
172189
LOG_ERR("Invalid response opcode: %d", response->opcode);
173190
break;

include/drivers/mspi/nrfe_mspi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ typedef enum {
3939
NRFE_MSPI_CONFIG_XFER, /* nrfe_mspi_xfer_config_msg_t */
4040
NRFE_MSPI_TX, /* nrfe_mspi_xfer_packet_msg_t + data buffer at the end */
4141
NRFE_MSPI_TXRX,
42+
NRFE_MSPI_SDP_APP_HARD_FAULT,
4243
NRFE_MSPI_WRONG_OPCODE,
4344
NRFE_MSPI_ALL_OPCODES = NRFE_MSPI_WRONG_OPCODE,
4445
} nrfe_mspi_opcode_t;

snippets/sdp/mspi/soc/nrf54l15_cpuapp.overlay

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@
1515
};
1616

1717
sram_rx: memory@2003c000 {
18-
reg = <0x2003c000 0x0800>;
18+
reg = <0x2003c000 0x07f0>;
1919
};
2020

21-
sram_tx: memory@2003c800 {
22-
reg = <0x2003c800 0x0800>;
21+
sram_tx: memory@2003c7f0 {
22+
reg = <0x2003c7f0 0x07f0>;
2323
};
24-
};
2524

25+
cpuflpr_error_code: memory@2003cfe0 {
26+
reg = <0x2003cfe0 0x0020>; /* 32bytes */
27+
};
28+
};
2629

2730
cpuflpr_sram_code_data: memory@2003d000 {
2831
compatible = "mmio-sram";

0 commit comments

Comments
 (0)