@@ -80,6 +80,8 @@ static atomic_t ipc_atomic_sem = ATOMIC_INIT(0);
8080#if defined(CONFIG_SDP_MSPI_FAULT_TIMER )
8181static 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
8486static 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+
516607int 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 }
0 commit comments