399 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			399 lines
		
	
	
		
			9.1 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 "os_task.h"
 | ||
|  | #include "os_utils.h"
 | ||
|  | 
 | ||
|  | /* common includes */ | ||
|  | #include "iot_io.h"
 | ||
|  | #include "iot_bitops.h"
 | ||
|  | #include "iot_config.h"
 | ||
|  | 
 | ||
|  | /* driver includes */ | ||
|  | #include "iot_clock.h"
 | ||
|  | #include "iot_uart.h"
 | ||
|  | 
 | ||
|  | #include "iot_system.h"
 | ||
|  | 
 | ||
|  | /* cli includes */ | ||
|  | #include "iot_uart_h.h"
 | ||
|  | 
 | ||
|  | /* debug includes*/ | ||
|  | #include "dbg_io.h"
 | ||
|  | 
 | ||
|  | #include "platform.h"
 | ||
|  | 
 | ||
|  | #include "apb_dma.h"
 | ||
|  | #include "cpu.h"
 | ||
|  | #include "encoding.h"
 | ||
|  | #include "hw_reg_api.h"
 | ||
|  | #include "ahb_rf.h"
 | ||
|  | #include "ahb.h"
 | ||
|  | #include "trace.h"
 | ||
|  | #include "dtest_printf.h"
 | ||
|  | #include "iot_errno_api.h"
 | ||
|  | #include "ahb.h"
 | ||
|  | #include "rtc.h"
 | ||
|  | 
 | ||
|  | os_task_h exception_test_handle; | ||
|  | /* the mcause code will be test */ | ||
|  | volatile uintptr_t g_mcause_set = 0; | ||
|  | /* the mcause code get from exception handler */ | ||
|  | volatile uintptr_t g_mcause_get = 0; | ||
|  | /* set 1 if exception occer */ | ||
|  | volatile int exception_occer = 0; | ||
|  | uint32_t mcause_test_bit_map = 0xFE; | ||
|  | 
 | ||
|  | extern void kl3_trap_entry(); | ||
|  | extern int platform_init(); | ||
|  | extern void intc_handler(uint32_t cpu); | ||
|  | extern uintptr_t kl3_handle_trap(uintptr_t mcause, uintptr_t epc, saved_registers *reg); | ||
|  | extern int uart_e_getc(int port); | ||
|  | 
 | ||
|  | 
 | ||
|  | void kl3_exception_handler(uintptr_t mcause) | ||
|  | { | ||
|  |     uint32_t mbadaddr = 0; | ||
|  | 
 | ||
|  |     //disble global interrupt;
 | ||
|  |     __asm volatile  ( "csrc mstatus,8" ); | ||
|  |     __asm volatile  ( "csrr %0, mbadaddr" : "=r"(mbadaddr)); | ||
|  | 
 | ||
|  |     switch(mcause) { | ||
|  |         case 0x0: | ||
|  |             dprintf("mcause: 0x%02x[Instruction address misaligned]\n", | ||
|  |                 mcause); | ||
|  |             break; | ||
|  |         case 0x1: | ||
|  |             dprintf("mcause: 0x%02x[Instruction access fault]\n", | ||
|  |                 mcause); | ||
|  |             break; | ||
|  |         case 0x2: | ||
|  |             dprintf("mcause: 0x%02x[Illegal instruction]\n", mcause); | ||
|  |             break; | ||
|  |         case 0x3: | ||
|  |             dprintf("mcause: 0x%02x[Breakpoint]\n", mcause); | ||
|  |             break; | ||
|  |         case 0x4: | ||
|  |             dprintf("mcause: 0x%02x[Load address misaligned]\n", | ||
|  |                 mcause); | ||
|  |             break; | ||
|  |         case 0x5: | ||
|  |             dprintf("mcause: 0x%02x[Load access fault]\n", mcause); | ||
|  |             break; | ||
|  |         case 0x6: | ||
|  |             dprintf("mcause: 0x%02x[Store address misaligned]\n", | ||
|  |                 mcause); | ||
|  |             break; | ||
|  |         case 0x7: | ||
|  |             dprintf("mcase: 0x%02x[Store access fault]\n", mcause); | ||
|  |             break; | ||
|  |         default: | ||
|  |             dprintf("mcause: 0x%02x\n", mcause); | ||
|  |             break; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | uintptr_t kl3_handle_trap(uintptr_t mcause, | ||
|  |         uintptr_t epc, saved_registers *reg) | ||
|  | { | ||
|  |     if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT) { | ||
|  |         intc_handler(cpu_get_mhartid()); | ||
|  |     } else { | ||
|  |         //extern void exception_reg_dump(saved_registers *regs);
 | ||
|  |         //exception_reg_dump(reg);
 | ||
|  |         exception_occer = 1; | ||
|  |         g_mcause_get = mcause; | ||
|  |         void exception_test_loop(void); | ||
|  |         void (*pgm_start)(void) = (void*) exception_test_loop; | ||
|  |         pgm_start(); | ||
|  |     } | ||
|  | 
 | ||
|  |     return epc; | ||
|  | } | ||
|  | 
 | ||
|  | void div_zero() | ||
|  | { | ||
|  |     uint32_t a = 0; | ||
|  |     uint32_t b = 1; | ||
|  |     uint32_t c = 0; | ||
|  | 
 | ||
|  |     c = b/a; | ||
|  |     dprintf("div zero : c=%d\r\n", c); | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * mcause: 0x00[Instruction address misaligned] | ||
|  |  */ | ||
|  | void instruction_address_misaligned(void) | ||
|  | { | ||
|  |     void (*pgm_start)(void) = (void*) 0x1002ffd1; | ||
|  |     pgm_start(); | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * mcause: 0x01[Instruction access fault] | ||
|  |  */ | ||
|  | void instruction_access_fault(void) | ||
|  | { | ||
|  |     void (*pgm_start)(void) = (void*) 0x1002ffd0; | ||
|  |     pgm_start(); | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * mcause: 0x02[Illegal instruction]非法指令 | ||
|  |  */ | ||
|  | void illegal_instruction(void) | ||
|  | { | ||
|  |     asm volatile("csrw sscratch, 0"); | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * mcause: 0x03[Breakpoint] | ||
|  |  */ | ||
|  | void break_point_fault(void) | ||
|  | { | ||
|  |     uint32_t *p = (uint32_t *)0x00000000; | ||
|  |     dprintf("*p = %d\n",*p); | ||
|  | } | ||
|  | /*
 | ||
|  |  * 条件断点测试,产生0x03[Breakpoint],注意测试的变量尽量为全局的 | ||
|  |  */ | ||
|  | uint32_t test; | ||
|  | int trace_test_run(void) | ||
|  | { | ||
|  | 
 | ||
|  |     //int ret = iot_trigger_watch_val_range((void *)&test, 1234,IOT_TRACE_MATCH_LESS);
 | ||
|  |     int ret = iot_trigger_watch_detect((void *)&test); | ||
|  |     if (ret != ERR_OK) | ||
|  |         return 0; | ||
|  | 
 | ||
|  |     test = 1233; | ||
|  | 
 | ||
|  | 
 | ||
|  |     return 1; | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * mcause: 4,load address misaligned | ||
|  |  */ | ||
|  | void load_instruction_address_misaligned(void) | ||
|  | { | ||
|  |     uint32_t *p = (uint32_t*) 0x1002ffd1; | ||
|  |     dprintf("align test p: %08x\r\n", *(p)); | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * mcause: 5, load address fault | ||
|  |  */ | ||
|  | void load_instruction_access_fault (void) | ||
|  | { | ||
|  |     uint32_t *p = (uint32_t *) 0xffffff40; | ||
|  |     dprintf("align test p: %08x\r\n", *(p)); | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * mcause: 6,store address misaligned | ||
|  |  */ | ||
|  | void store_instruction_addr_misaligned(void) | ||
|  | { | ||
|  |     uint32_t *p = (uint32_t *)0x1002ffd1; | ||
|  |     *p = 0xaabbccdd; | ||
|  |     dprintf("align test p: %08x\r\n", *(p)); | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * mcause:7,store address fault | ||
|  |  */ | ||
|  | void store_instruction_addr_fault(void) | ||
|  | { | ||
|  |     uint32_t *p = (uint32_t *)0xffffff40; | ||
|  |     *p = 0xaabbccdd; | ||
|  |     dprintf("align test p: %08x\r\n", *(p)); | ||
|  | } | ||
|  | void exception_test(uintptr_t mcause) | ||
|  | { | ||
|  |     switch(mcause) { | ||
|  |         case 0x0: | ||
|  |             dprintf("Test [Instruction address misaligned]\n"); | ||
|  |             break; | ||
|  |         case 0x1: | ||
|  |             dprintf("Test [invalid_instruction_access]\n"); | ||
|  |             instruction_access_fault(); | ||
|  |             break; | ||
|  |         case 0x2: | ||
|  |             dprintf("Test [instruction_illegal]\n"); | ||
|  |             illegal_instruction(); | ||
|  |             break; | ||
|  |         case 0x3: | ||
|  |             dprintf("Test [breakpoint fault]\n"); | ||
|  |             trace_test_run(); | ||
|  |             //break_point_fault();
 | ||
|  |             break; | ||
|  |         case 0x4: | ||
|  |             dprintf("Test [misalign_access]\n"); | ||
|  |             load_instruction_address_misaligned(); | ||
|  |             break; | ||
|  |         case 0x5: | ||
|  |             dprintf("Test [Load access fault]\n"); | ||
|  |             load_instruction_access_fault(); | ||
|  |             break; | ||
|  |         case 0x6: | ||
|  |             dprintf("Test [addr_invalid]\n"); | ||
|  |             store_instruction_addr_misaligned(); | ||
|  |             break; | ||
|  |         case 0x7: | ||
|  |             dprintf("Test [Store access fault]\n"); | ||
|  |             store_instruction_addr_fault(); | ||
|  |             break; | ||
|  |         default: | ||
|  |             break; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | void exception_test_loop() | ||
|  | { | ||
|  |     /* if exception occer, need check exception code get is same as set */ | ||
|  |     if (exception_occer) { | ||
|  |         exception_occer = 0; | ||
|  |         kl3_exception_handler(g_mcause_get); | ||
|  |         if (g_mcause_get == g_mcause_set) { | ||
|  |             dcase_success(); | ||
|  |         } else { | ||
|  |             dcase_failed(); | ||
|  |         } | ||
|  |         /* test next exception code */ | ||
|  |         g_mcause_set++; | ||
|  |     } | ||
|  | 
 | ||
|  |     for (;;) { | ||
|  |         if ((mcause_test_bit_map & (1 << g_mcause_set)) != 0) { | ||
|  |             exception_test(g_mcause_set); | ||
|  |             /* when exception occer, it will not run here */ | ||
|  |             dprintf("%d - mcause[0x%02x] test failed\n", __LINE__,g_mcause_set); | ||
|  |             dcase_failed(); | ||
|  |         } else if (0 == mcause_test_bit_map >> g_mcause_set) { | ||
|  |             dend(); | ||
|  |             for (;;) { | ||
|  |                 os_delay(1000); | ||
|  |             } | ||
|  |         } | ||
|  |         g_mcause_set++; | ||
|  |         os_delay(100); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | void exception_test_task(void *arg) | ||
|  | { | ||
|  |     dprintf("exception test task entry...\n"); | ||
|  | 
 | ||
|  |     /* init common modules */ | ||
|  |     iot_bitops_init(); | ||
|  | 
 | ||
|  |     /* init os related modules and utilities */ | ||
|  |     os_utils_init(); | ||
|  | 
 | ||
|  |     /*init uart module*/ | ||
|  |     iot_uart_init(1); | ||
|  | 
 | ||
|  |     dconfig(); | ||
|  |     dstart(); | ||
|  |     dversion(); | ||
|  |     ahb_d_exp_enable(); | ||
|  |     exception_test_loop(); | ||
|  | } | ||
|  | 
 | ||
|  | static int32_t iot_task_init(void) | ||
|  | { | ||
|  |     div_zero(); | ||
|  |     /* create exception test task */ | ||
|  |     exception_test_handle = os_create_task(exception_test_task, NULL, 9); | ||
|  | 
 | ||
|  |     if (exception_test_handle != NULL) { | ||
|  |         dprintf("create exception test task successfully...\n"); | ||
|  |     } | ||
|  | 
 | ||
|  |     return 0; | ||
|  | } | ||
|  | 
 | ||
|  | static int32_t iot_task_start() | ||
|  | { | ||
|  |     //start the tasks;
 | ||
|  |     os_start_kernel(); | ||
|  | 
 | ||
|  |     return 0; | ||
|  | } | ||
|  | 
 | ||
|  | static void cache_init() | ||
|  | { | ||
|  |     cache_enable(AHB_CACHE_D0); | ||
|  |     cache_set_buffer_mode(AHB_CACHE_D0, 1); | ||
|  |     cache_enable(AHB_CACHE_D1); | ||
|  |     cache_set_buffer_mode(AHB_CACHE_D1, 1); | ||
|  | } | ||
|  | 
 | ||
|  | static int32_t iot_platform_init() | ||
|  | { | ||
|  |     cache_init(); | ||
|  |     /*platform intialization*/ | ||
|  |     platform_init(); | ||
|  | 
 | ||
|  |     /*install trap entry*/ | ||
|  |     write_csr(mtvec, &kl3_trap_entry); | ||
|  | 
 | ||
|  |     //resource initializations;
 | ||
|  |     system_clock_init(); | ||
|  | 
 | ||
|  |     system_uart_init(); | ||
|  | 
 | ||
|  |     dbg_uart_init(); | ||
|  | 
 | ||
|  |     dbg_uart_stage1_init(); | ||
|  | 
 | ||
|  |     /* rtc init, idle used rtc lock */ | ||
|  |     iot_rtc_init(); | ||
|  | 
 | ||
|  |     return 0; | ||
|  | } | ||
|  | 
 | ||
|  | int32_t iot_module_init(void) | ||
|  | { | ||
|  |     /* platform intialization; */ | ||
|  |     iot_platform_init(); | ||
|  | 
 | ||
|  |     /* create all the tasks; */ | ||
|  |     iot_task_init(); | ||
|  | 
 | ||
|  |     return 0; | ||
|  | } | ||
|  | 
 | ||
|  | int32_t iot_module_start(void) | ||
|  | { | ||
|  |     int32_t res = 0; | ||
|  | 
 | ||
|  |     res = iot_task_start(); | ||
|  | 
 | ||
|  |     return res; | ||
|  | } | ||
|  | 
 | ||
|  | int main(void) | ||
|  | { | ||
|  |     iot_module_init(); | ||
|  |     iot_module_start(); | ||
|  | 
 | ||
|  |     return 0; | ||
|  | } |