322 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			322 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /****************************************************************************
 | |
|  *
 | |
|  * 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 "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_string.h"
 | |
| #include "iot_version.h"
 | |
| #include "cpu.h"
 | |
| 
 | |
| #define FILENAME(x) iot_strrchr(x, '/') ? iot_strrchr(x, '/') + 1 : x
 | |
| 
 | |
| #define DUMP_DEEP_LEN 10
 | |
| 
 | |
| typedef struct {
 | |
|     uint32_t ra[DUMP_DEEP_LEN];
 | |
|     uint32_t s0[DUMP_DEEP_LEN];
 | |
| } exception_dump_t;
 | |
| 
 | |
| extern void def_trap_entry_3();
 | |
| extern void intc_handler(uint32_t cpu);
 | |
| 
 | |
| cpu_state g_sec_cpu_state;
 | |
| 
 | |
| extern uint32_t _sp;
 | |
| extern unsigned int _heap_end;
 | |
| extern uint32_t _start_3;
 | |
| 
 | |
| static exception_dump_t g_exception_dump = {0};
 | |
| 
 | |
| static char g_dbg_msg[80];
 | |
| 
 | |
| static void print_error_msg(const char *err_msg)
 | |
| {
 | |
|     (void)err_msg;
 | |
|     //TODO: add code
 | |
| }
 | |
| 
 | |
| 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);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static 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_3;
 | |
|         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;
 | |
| }
 | |
| 
 | |
| static 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_3(uintptr_t mcause, uintptr_t epc, saved_registers *reg)
 | |
| {
 | |
|     uint32_t mbadaddr = 0;
 | |
| 
 | |
|      /* save cpu1's crash state */
 | |
|      g_sec_cpu_state.crash = 1;
 | |
|      g_sec_cpu_state.mcause = mcause;
 | |
|      g_sec_cpu_state.mepc = epc;
 | |
|      g_sec_cpu_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" );
 | |
|     __asm volatile  ( "csrr %0, mbadaddr" : "=r"(mbadaddr));
 | |
| 
 | |
|     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_3(uintptr_t mcause, uintptr_t epc, saved_registers *reg)
 | |
| {
 | |
|     if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT) {
 | |
|         intc_handler(cpu_get_mhartid());
 | |
|     }else {
 | |
|         exception_handler_3(mcause, epc, reg);
 | |
|     }
 | |
| 
 | |
|     return epc;
 | |
| }
 | |
| 
 | |
| void _init_3()
 | |
| {
 | |
|     write_csr(mtvec, &def_trap_entry_3);
 | |
| 
 | |
|     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_sec_cpu_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_sec_cpu_state.assert_failed = 1;
 | |
|     if (pucFile && (filename = FILENAME((char*)pucFile))) {
 | |
|         os_mem_cpy(g_sec_cpu_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_sec_cpu_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_sec_cpu_state.assert_info.line = ulLine;
 | |
| 
 | |
|     iot_sprintf(g_dbg_msg, "seccpu: mcause: 0x%08x, mepc: 0x%08x\n",
 | |
|         g_sec_cpu_state.mcause, g_sec_cpu_state.mepc);
 | |
| 
 | |
|     print_error_msg(g_dbg_msg);
 | |
| 
 | |
|     /* do a breakpoint exception */
 | |
|     asm volatile("ebreak");
 | |
| }
 | |
| 
 | |
| void assert_failed_simple()
 | |
| {
 | |
|     g_sec_cpu_state.assert_failed = 1;
 | |
|     os_mem_set(g_sec_cpu_state.assert_info.file, 0, 32);
 | |
|     g_sec_cpu_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");
 | |
| }
 |