You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							138 lines
						
					
					
						
							4.6 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							138 lines
						
					
					
						
							4.6 KiB
						
					
					
				| /* | |
|  * Copyright (c) 2006-2021, RT-Thread Development Team | |
|  * | |
|  * SPDX-License-Identifier: Apache-2.0 | |
|  * | |
|  * Change Logs: | |
|  * Date           Author       Notes | |
|  * 2010-01-25     Bernard      first version | |
|  * 2012-05-31     aozima       Merge all of the C source code into cpuport.c | |
|  * 2012-08-17     aozima       fixed bug: store r8 - r11. | |
|  * 2012-12-23     aozima       stack addr align to 8byte. | |
|  * 2019-03-31     xuzhuoyi     port to Cortex-M23. | |
|  */ | |
| 
 | |
| #include <rtthread.h> | |
|  | |
| struct exception_stack_frame | |
| { | |
|     rt_uint32_t r0; | |
|     rt_uint32_t r1; | |
|     rt_uint32_t r2; | |
|     rt_uint32_t r3; | |
|     rt_uint32_t r12; | |
|     rt_uint32_t lr; | |
|     rt_uint32_t pc; | |
|     rt_uint32_t psr; | |
| }; | |
| 
 | |
| struct stack_frame | |
| { | |
|     /* r4 ~ r7 low register */ | |
|     rt_uint32_t r4; | |
|     rt_uint32_t r5; | |
|     rt_uint32_t r6; | |
|     rt_uint32_t r7; | |
| 
 | |
|     /* r8 ~ r11 high register */ | |
|     rt_uint32_t r8; | |
|     rt_uint32_t r9; | |
|     rt_uint32_t r10; | |
|     rt_uint32_t r11; | |
| 
 | |
|     struct exception_stack_frame exception_stack_frame; | |
| }; | |
| 
 | |
| /* flag in interrupt handling */ | |
| rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; | |
| rt_uint32_t rt_thread_switch_interrupt_flag; | |
| 
 | |
| /** | |
|  * This function will initialize thread stack | |
|  * | |
|  * @param tentry the entry of thread | |
|  * @param parameter the parameter of entry | |
|  * @param stack_addr the beginning stack address | |
|  * @param texit the function will be called when thread exit | |
|  * | |
|  * @return stack address | |
|  */ | |
| rt_uint8_t *rt_hw_stack_init(void       *tentry, | |
|                              void       *parameter, | |
|                              rt_uint8_t *stack_addr, | |
|                              void       *texit) | |
| { | |
|     struct stack_frame *stack_frame; | |
|     rt_uint8_t         *stk; | |
|     unsigned long       i; | |
| 
 | |
|     stk  = stack_addr + sizeof(rt_uint32_t); | |
|     stk  = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stk, 8); | |
|     stk -= sizeof(struct stack_frame); | |
| 
 | |
|     stack_frame = (struct stack_frame *)stk; | |
| 
 | |
|     /* init all register */ | |
|     for (i = 0; i < sizeof(struct stack_frame) / sizeof(rt_uint32_t); i ++) | |
|     { | |
|         ((rt_uint32_t *)stack_frame)[i] = 0xdeadbeef; | |
|     } | |
| 
 | |
|     stack_frame->exception_stack_frame.r0  = (unsigned long)parameter; /* r0 : argument */ | |
|     stack_frame->exception_stack_frame.r1  = 0;                        /* r1 */ | |
|     stack_frame->exception_stack_frame.r2  = 0;                        /* r2 */ | |
|     stack_frame->exception_stack_frame.r3  = 0;                        /* r3 */ | |
|     stack_frame->exception_stack_frame.r12 = 0;                        /* r12 */ | |
|     stack_frame->exception_stack_frame.lr  = (unsigned long)texit;     /* lr */ | |
|     stack_frame->exception_stack_frame.pc  = (unsigned long)tentry;    /* entry point, pc */ | |
|     stack_frame->exception_stack_frame.psr = 0x01000000L;              /* PSR */ | |
| 
 | |
|     /* return task's current stack address */ | |
|     return stk; | |
| } | |
| 
 | |
| #if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS) | |
| extern long list_thread(void); | |
| #endif | |
| extern rt_thread_t rt_current_thread; | |
| /** | |
|  * fault exception handling | |
|  */ | |
| void rt_hw_hard_fault_exception(struct exception_stack_frame *contex) | |
| { | |
|     rt_kprintf("psr: 0x%08x\n", contex->psr); | |
|     rt_kprintf(" pc: 0x%08x\n", contex->pc); | |
|     rt_kprintf(" lr: 0x%08x\n", contex->lr); | |
|     rt_kprintf("r12: 0x%08x\n", contex->r12); | |
|     rt_kprintf("r03: 0x%08x\n", contex->r3); | |
|     rt_kprintf("r02: 0x%08x\n", contex->r2); | |
|     rt_kprintf("r01: 0x%08x\n", contex->r1); | |
|     rt_kprintf("r00: 0x%08x\n", contex->r0); | |
| 
 | |
|     rt_kprintf("hard fault on thread: %s\n", rt_current_thread->name); | |
| 
 | |
| #if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS) | |
|     list_thread(); | |
| #endif | |
|  | |
|     while (1); | |
| } | |
| 
 | |
| #define SCB_CFSR        (*(volatile const unsigned *)0xE000ED28) /* Configurable Fault Status Register */ | |
| #define SCB_HFSR        (*(volatile const unsigned *)0xE000ED2C) /* HardFault Status Register */ | |
| #define SCB_MMAR        (*(volatile const unsigned *)0xE000ED34) /* MemManage Fault Address register */ | |
| #define SCB_BFAR        (*(volatile const unsigned *)0xE000ED38) /* Bus Fault Address Register */ | |
| #define SCB_AIRCR       (*(volatile unsigned long *)0xE000ED00)  /* Reset control Address Register */ | |
| #define SCB_RESET_VALUE 0x05FA0004                               /* Reset value, write to SCB_AIRCR can reset cpu */ | |
|  | |
| #define SCB_CFSR_MFSR   (*(volatile const unsigned char*)0xE000ED28)  /* Memory-management Fault Status Register */ | |
| #define SCB_CFSR_BFSR   (*(volatile const unsigned char*)0xE000ED29)  /* Bus Fault Status Register */ | |
| #define SCB_CFSR_UFSR   (*(volatile const unsigned short*)0xE000ED2A) /* Usage Fault Status Register */ | |
|  | |
| /** | |
|  * reset CPU | |
|  */ | |
| RT_WEAK void rt_hw_cpu_reset(void) | |
| { | |
|     SCB_AIRCR  = SCB_RESET_VALUE;//((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |SCB_AIRCR_SYSRESETREQ_Msk); | |
| }
 | |
| 
 |