| 
									
										
										
										
											2024-09-28 14:24:04 +08:00
										 |  |  | /****************************************************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT | 
					
						
							|  |  |  |  * be copied by any method or incorporated into another program without | 
					
						
							|  |  |  |  * the express written consent of Aerospace C.Power. This Information or any portion | 
					
						
							|  |  |  |  * thereof remains the property of Aerospace C.Power. The Information contained herein | 
					
						
							|  |  |  |  * is believed to be accurate and Aerospace C.Power assumes no responsibility or | 
					
						
							|  |  |  |  * liability for its use in any way and conveys no license or title under | 
					
						
							|  |  |  |  * any patent or copyright and makes no representation or warranty that this | 
					
						
							|  |  |  |  * Information is free from patent or copyright infringement. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ****************************************************************************/ | 
					
						
							|  |  |  | /* os shim includes */ | 
					
						
							|  |  |  | #include "os_types.h"
 | 
					
						
							|  |  |  | #include "iot_irq.h"
 | 
					
						
							|  |  |  | #include "iot_wdg.h"
 | 
					
						
							|  |  |  | #include "os_mem.h"
 | 
					
						
							|  |  |  | #include "efuse.h"
 | 
					
						
							|  |  |  | #include "iot_system.h"
 | 
					
						
							|  |  |  | #include "iot_io.h"
 | 
					
						
							|  |  |  | #include "cpu.h"
 | 
					
						
							|  |  |  | #include "dbg_io.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "platform.h"
 | 
					
						
							|  |  |  | #include "encoding.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "iot_string_api.h"
 | 
					
						
							|  |  |  | #include "iot_dbglog.h"
 | 
					
						
							|  |  |  | #include "iot_string.h"
 | 
					
						
							|  |  |  | #include "iot_cli_type_definition.h"
 | 
					
						
							|  |  |  | #include "iot_version.h"
 | 
					
						
							|  |  |  | #include "iot_mtd.h"
 | 
					
						
							|  |  |  | #include "cpu.h"
 | 
					
						
							|  |  |  | #include "bb_cpu_utils.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define FILENAME(x) iot_strrchr(x, '/') ? iot_strrchr(x, '/') + 1 : x
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern void def_trap_entry_2(); | 
					
						
							|  |  |  | extern void intc_handler(uint32_t cpu); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | cpu_state g_bbcpu_state; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern uint32_t _sp; | 
					
						
							|  |  |  | extern unsigned int _heap_end; | 
					
						
							|  |  |  | extern uint32_t _start_2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char g_dbg_msg[80]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if (IOT_DTEST_ONLY_SUPPORT == 1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void print_error_msg(const char *err_msg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |    while(*err_msg != '\0'){ | 
					
						
							|  |  |  |       dbg_putchar(*err_msg); | 
					
						
							|  |  |  |       ++err_msg; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else /*(IOT_DTEST_ONLY_SUPPORT == 1) */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define print_error_msg(err_msg) while(!bb_cpu_exception_printf("%s", err_msg))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /*(IOT_DTEST_ONLY_SUPPORT == 1) */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define DUMP_DEEP_LEN 10
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     uint32_t ra[DUMP_DEEP_LEN]; | 
					
						
							|  |  |  |     uint32_t s0[DUMP_DEEP_LEN]; | 
					
						
							|  |  |  | } exception_dump_t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | exception_dump_t g_exception_dump = {0}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void iot_illegal_instruct(uintptr_t epc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t *pc = (uint32_t *) (epc & 0xFFFFFFF0); | 
					
						
							|  |  |  |     uint32_t i = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < 8; i++) { | 
					
						
							|  |  |  |         iot_sprintf(g_dbg_msg, "0x%08x, value: 0x%08x\n", pc+i, *(pc+i)); | 
					
						
							|  |  |  |         print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int iot_backtrace(uintptr_t epc, saved_registers *regs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t s0 = 0; | 
					
						
							|  |  |  |     volatile uint32_t deep_len = 0; | 
					
						
							|  |  |  |     uint32_t ret_fun = 0; | 
					
						
							|  |  |  |     uint32_t frame_start = 0; | 
					
						
							|  |  |  |     uint8_t cnt = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s0 = regs->fp; | 
					
						
							|  |  |  |     g_exception_dump.ra[deep_len] = epc; | 
					
						
							|  |  |  |     g_exception_dump.s0[deep_len] = s0; | 
					
						
							|  |  |  |     frame_start = s0; | 
					
						
							|  |  |  |     deep_len++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while( s0 <= frame_start && deep_len < DUMP_DEEP_LEN) { | 
					
						
							|  |  |  |         s0 = frame_start; | 
					
						
							|  |  |  |         if ((s0 >= (uint32_t)&_sp)||(s0 <= (uint32_t)&_data)){ | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         uint32_t *tmp = (uint32_t *) s0; | 
					
						
							|  |  |  |         uint32_t text_s = (uint32_t)&_start_2; | 
					
						
							|  |  |  |         uint32_t text_e = (uint32_t)&_etext; | 
					
						
							|  |  |  |         uint32_t iram_s = (uint32_t)&_iram_start; | 
					
						
							|  |  |  |         uint32_t iram_e = (uint32_t)&_iram_end;; | 
					
						
							|  |  |  |         ret_fun = *(tmp-1); | 
					
						
							|  |  |  |         if (((ret_fun > text_s) && (ret_fun < text_e)) || | 
					
						
							|  |  |  |             ((ret_fun > iram_s) && (ret_fun < iram_e)) ){ | 
					
						
							|  |  |  |             frame_start = *(tmp-2); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             frame_start = *(tmp-1); | 
					
						
							|  |  |  |             ret_fun = regs->ra; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         g_exception_dump.ra[deep_len] = ret_fun; | 
					
						
							|  |  |  |         g_exception_dump.s0[deep_len] = s0; | 
					
						
							|  |  |  |         deep_len++; | 
					
						
							|  |  |  |         cnt++; | 
					
						
							|  |  |  |         iot_sprintf(g_dbg_msg, "func: 0x%08x, so: 0x%08x, stack: 0x%08x\n", | 
					
						
							|  |  |  |                 ret_fun, s0, frame_start); | 
					
						
							|  |  |  |         print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void exception_reg_dump(saved_registers *regs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int i = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iot_sprintf(g_dbg_msg, "exception registers dump\n"); | 
					
						
							|  |  |  |     print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |     iot_sprintf(g_dbg_msg, "ra = 0x%08x\n", regs->ra); | 
					
						
							|  |  |  |     print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |     iot_sprintf(g_dbg_msg, "sp = 0x%08x\n", regs->sp); | 
					
						
							|  |  |  |     print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |     iot_sprintf(g_dbg_msg, "gp = 0x%08x\n", regs->gp); | 
					
						
							|  |  |  |     print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |     iot_sprintf(g_dbg_msg, "tp = 0x%08x\n", regs->tp); | 
					
						
							|  |  |  |     print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |     for(i=0; i<3; i++) { | 
					
						
							|  |  |  |         iot_sprintf(g_dbg_msg, "t%d = 0x%08x\n", i, regs->t0_2[i]); | 
					
						
							|  |  |  |         print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iot_sprintf(g_dbg_msg, "fp = 0x%08x\n", regs->fp); | 
					
						
							|  |  |  |     print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |     iot_sprintf(g_dbg_msg, "s1 = 0x%08x\n", regs->s1); | 
					
						
							|  |  |  |     print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |     for(i=0; i<8; i++) { | 
					
						
							|  |  |  |         iot_sprintf(g_dbg_msg, "a%d = 0x%08x\n", i, regs->a0_7[i]); | 
					
						
							|  |  |  |         print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for(i=2; i<12; i++) { | 
					
						
							|  |  |  |         iot_sprintf(g_dbg_msg, "s%d = 0x%08x\n", i, regs->s2_11[i-2]); | 
					
						
							|  |  |  |         print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for(i=3; i<5; i++) { | 
					
						
							|  |  |  |         iot_sprintf(g_dbg_msg, "t%d = 0x%08x\n", i, regs->t3_4[i-3]); | 
					
						
							|  |  |  |         print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     iot_sprintf(g_dbg_msg, "t5 = 0x%08x\n", regs->t5); | 
					
						
							|  |  |  |     print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iot_sprintf(g_dbg_msg, "t6 = 0x%08x\n", regs->t6); | 
					
						
							|  |  |  |     print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void exception_handler_2(uintptr_t mcause, uintptr_t epc, saved_registers *reg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t mbadaddr = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      /* save cpu1's crash state */ | 
					
						
							|  |  |  |      g_bbcpu_state.crash = 1; | 
					
						
							|  |  |  |      g_bbcpu_state.mcause = mcause; | 
					
						
							|  |  |  |      g_bbcpu_state.mepc = epc; | 
					
						
							|  |  |  |      g_bbcpu_state.trap_frame  = reg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      // disable iot_printf
 | 
					
						
							|  |  |  |     iot_print_config(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // dump exception registers
 | 
					
						
							|  |  |  |     exception_reg_dump(reg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //disble global interrupt;
 | 
					
						
							|  |  |  |     __asm volatile  ( "csrc mstatus,8" ); | 
					
						
							| 
									
										
										
										
											2024-11-03 11:22:45 +08:00
										 |  |  |     // 在mbadaddr寄存器写入值 gcc 15 中这个寄存器名称改了
 | 
					
						
							|  |  |  |     #if __GNUC__ <= 10
 | 
					
						
							| 
									
										
										
										
											2024-09-28 14:24:04 +08:00
										 |  |  |     __asm volatile  ( "csrr %0, mbadaddr" : "=r"(mbadaddr)); | 
					
						
							| 
									
										
										
										
											2024-11-03 11:22:45 +08:00
										 |  |  |     #else
 | 
					
						
							|  |  |  |     __asm volatile  ( "csrr %0, mtval" : "=r"(mbadaddr)); | 
					
						
							|  |  |  |     #endif
 | 
					
						
							| 
									
										
										
										
											2024-09-28 14:24:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     switch(mcause) { | 
					
						
							|  |  |  |         case 0x0: | 
					
						
							|  |  |  |             iot_sprintf(g_dbg_msg, "mcause: 0x%02x[Instruction address misaligned]\n", | 
					
						
							|  |  |  |                 mcause); | 
					
						
							|  |  |  |             print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 0x1: | 
					
						
							|  |  |  |             iot_sprintf(g_dbg_msg, "mcause: 0x%02x[Instruction access fault]\n", | 
					
						
							|  |  |  |                 mcause); | 
					
						
							|  |  |  |             print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 0x2: | 
					
						
							|  |  |  |             iot_sprintf(g_dbg_msg, "mcause: 0x%02x[Illegal instruction]\n", mcause); | 
					
						
							|  |  |  |             print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |             iot_illegal_instruct(epc); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 0x3: | 
					
						
							|  |  |  |             iot_sprintf(g_dbg_msg, "mcause: 0x%02x[Breakpoint]\n", mcause); | 
					
						
							|  |  |  |             print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 0x4: | 
					
						
							|  |  |  |             iot_sprintf(g_dbg_msg, "mcause: 0x%02x[Load address misaligned]\n", | 
					
						
							|  |  |  |                 mcause); | 
					
						
							|  |  |  |             print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 0x5: | 
					
						
							|  |  |  |             iot_sprintf(g_dbg_msg, "mcause: 0x%02x[Load access fault]\n", mcause); | 
					
						
							|  |  |  |             print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 0x6: | 
					
						
							|  |  |  |             iot_sprintf(g_dbg_msg, "mcause: 0x%02x[Store address misaligned]\n", | 
					
						
							|  |  |  |                 mcause); | 
					
						
							|  |  |  |             print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 0x7: | 
					
						
							|  |  |  |             iot_sprintf(g_dbg_msg, "mcase: 0x%02x[Store access fault]\n", mcause); | 
					
						
							|  |  |  |             print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             iot_sprintf(g_dbg_msg, "mcause: 0x%02x\n", mcause); | 
					
						
							|  |  |  |             print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iot_sprintf(g_dbg_msg, "mepc: 0x%08x, mbadaddr: 0x%08x, core:%d\n", epc, | 
					
						
							|  |  |  |         mbadaddr, cpu_get_mhartid()); | 
					
						
							|  |  |  |     print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iot_backtrace(epc, reg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while(1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uintptr_t handle_trap_2(uintptr_t mcause, uintptr_t epc, saved_registers *reg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT) { | 
					
						
							|  |  |  |         intc_handler(cpu_get_mhartid()); | 
					
						
							|  |  |  |     }else { | 
					
						
							|  |  |  |         exception_handler_2(mcause, epc, reg); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return epc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void _init_2() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     write_csr(mtvec, &def_trap_entry_2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     clear_csr(mie, MIP_MEIP); | 
					
						
							|  |  |  |     clear_csr(mie, MIP_MTIP); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iot_interrupt_init(cpu_get_mhartid()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set_csr(mie, MIP_MEIP); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Enable interrupts in general.
 | 
					
						
							|  |  |  |     set_csr(mstatus, MSTATUS_MIE); | 
					
						
							|  |  |  |     wdg_deinit(cpu_get_mhartid()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     g_bbcpu_state.flags = CPU_FLAG_RUNNING; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void _fini() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void assert_failed( unsigned char *pucFile, unsigned long ulLine ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ( void ) pucFile; | 
					
						
							|  |  |  |     ( void ) ulLine; | 
					
						
							|  |  |  |     char *filename; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //disble global interrupt;
 | 
					
						
							|  |  |  |     __asm volatile  ( "csrc mstatus,8" ); | 
					
						
							|  |  |  |     uint32_t ast_ra = 0; | 
					
						
							|  |  |  |     __asm volatile ("mv %0, ra" : "=r"(ast_ra)); | 
					
						
							|  |  |  |     // disable iot_printf
 | 
					
						
							|  |  |  |     iot_print_config(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     g_bbcpu_state.assert_failed = 1; | 
					
						
							|  |  |  |     if (pucFile && (filename = FILENAME((char*)pucFile))) { | 
					
						
							|  |  |  |         os_mem_cpy(g_bbcpu_state.assert_info.file, filename, 32); | 
					
						
							|  |  |  |         iot_sprintf(g_dbg_msg, "%s:%d ra:0x%08x Asserted!\n", | 
					
						
							|  |  |  |             filename, ulLine, ast_ra); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         os_mem_set(g_bbcpu_state.assert_info.file, 0, 32); | 
					
						
							|  |  |  |         iot_sprintf(g_dbg_msg, "NULL:%d ra:0x%08x Asserted!\n", | 
					
						
							|  |  |  |             ulLine, ast_ra); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  |     g_bbcpu_state.assert_info.line = ulLine; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iot_sprintf(g_dbg_msg, "bbcpu: mcause: 0x%08x, mepc: 0x%08x\n", | 
					
						
							|  |  |  |         g_bbcpu_state.mcause, g_bbcpu_state.mepc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* do a breakpoint exception */ | 
					
						
							|  |  |  |     asm volatile("ebreak"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void assert_failed_simple() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     g_bbcpu_state.assert_failed = 1; | 
					
						
							|  |  |  |     os_mem_set(g_bbcpu_state.assert_info.file, 0, 32); | 
					
						
							|  |  |  |     g_bbcpu_state.assert_info.line = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //disble global interrupt;
 | 
					
						
							|  |  |  |     __asm volatile  ( "csrc mstatus,8" ); | 
					
						
							|  |  |  |     // disable iot_printf
 | 
					
						
							|  |  |  |     iot_print_config(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iot_sprintf(g_dbg_msg, "NULL:0 Asserted!\n"); | 
					
						
							|  |  |  |     print_error_msg(g_dbg_msg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* do a breakpoint exception */ | 
					
						
							|  |  |  |     asm volatile("ebreak"); | 
					
						
							|  |  |  | } |