diff options
Diffstat (limited to 'libcpu')
| -rw-r--r-- | libcpu/arm/cortex-m23/SConscript | 23 | ||||
| -rw-r--r-- | libcpu/arm/cortex-m23/context_gcc.S | 211 | ||||
| -rw-r--r-- | libcpu/arm/cortex-m23/context_iar.S | 207 | ||||
| -rw-r--r-- | libcpu/arm/cortex-m23/context_rvds.S | 216 | ||||
| -rw-r--r-- | libcpu/arm/cortex-m23/cpuport.c | 136 |
5 files changed, 793 insertions, 0 deletions
diff --git a/libcpu/arm/cortex-m23/SConscript b/libcpu/arm/cortex-m23/SConscript new file mode 100644 index 0000000000..9ff30a796b --- /dev/null +++ b/libcpu/arm/cortex-m23/SConscript @@ -0,0 +1,23 @@ +# RT-Thread building script for component + +from building import * + +Import('rtconfig') + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') +CPPPATH = [cwd] + +if rtconfig.PLATFORM == 'armcc': + src += Glob('*_rvds.S') + +if rtconfig.PLATFORM == 'gcc': + src += Glob('*_init.S') + src += Glob('*_gcc.S') + +if rtconfig.PLATFORM == 'iar': + src += Glob('*_iar.S') + +group = DefineGroup('cpu', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/libcpu/arm/cortex-m23/context_gcc.S b/libcpu/arm/cortex-m23/context_gcc.S new file mode 100644 index 0000000000..4fc5a3adbd --- /dev/null +++ b/libcpu/arm/cortex-m23/context_gcc.S @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2010-01-25 Bernard first version + * 2012-06-01 aozima set pendsv priority to 0xFF. + * 2012-08-17 aozima fixed bug: store r8 - r11. + * 2013-02-20 aozima port to gcc. + * 2013-06-18 aozima add restore MSP feature. + * 2013-11-04 bright fixed hardfault bug for gcc. + * 2019-03-31 xuzhuoyi port to Cortex-M23. + */ + + .cpu cortex-m23 + .fpu softvfp + .syntax unified + .thumb + .text + + .equ SCB_VTOR, 0xE000ED08 /* Vector Table Offset Register */ + .equ NVIC_INT_CTRL, 0xE000ED04 /* interrupt control state register */ + .equ NVIC_SHPR3, 0xE000ED20 /* system priority register (3) */ + .equ NVIC_PENDSV_PRI, 0x00FF0000 /* PendSV priority value (lowest) */ + .equ NVIC_PENDSVSET, 0x10000000 /* value to trigger PendSV exception */ + +/* + * rt_base_t rt_hw_interrupt_disable(); + */ + .global rt_hw_interrupt_disable + .type rt_hw_interrupt_disable, %function +rt_hw_interrupt_disable: + MRS R0, PRIMASK + CPSID I + BX LR + +/* + * void rt_hw_interrupt_enable(rt_base_t level); + */ + .global rt_hw_interrupt_enable + .type rt_hw_interrupt_enable, %function +rt_hw_interrupt_enable: + MSR PRIMASK, R0 + BX LR + +/* + * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); + * R0 --> from + * R1 --> to + */ + .global rt_hw_context_switch_interrupt + .type rt_hw_context_switch_interrupt, %function + .global rt_hw_context_switch + .type rt_hw_context_switch, %function +rt_hw_context_switch_interrupt: +rt_hw_context_switch: + /* set rt_thread_switch_interrupt_flag to 1 */ + LDR R2, =rt_thread_switch_interrupt_flag + LDR R3, [R2] + CMP R3, #1 + BEQ _reswitch + MOVS R3, #1 + STR R3, [R2] + + LDR R2, =rt_interrupt_from_thread /* set rt_interrupt_from_thread */ + STR R0, [R2] + +_reswitch: + LDR R2, =rt_interrupt_to_thread /* set rt_interrupt_to_thread */ + STR R1, [R2] + + LDR R0, =NVIC_INT_CTRL /* trigger the PendSV exception (causes context switch) */ + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + BX LR + +/* R0 --> switch from thread stack + * R1 --> switch to thread stack + * psr, pc, LR, R12, R3, R2, R1, R0 are pushed into [from] stack + */ + .global PendSV_Handler + .type PendSV_Handler, %function +PendSV_Handler: + /* disable interrupt to protect context switch */ + MRS R2, PRIMASK + CPSID I + + /* get rt_thread_switch_interrupt_flag */ + LDR R0, =rt_thread_switch_interrupt_flag + LDR R1, [R0] + CMP R1, #0x00 + BEQ pendsv_exit /* pendsv aLReady handled */ + + /* clear rt_thread_switch_interrupt_flag to 0 */ + MOVS R1, #0 + STR R1, [R0] + + LDR R0, =rt_interrupt_from_thread + LDR R1, [R0] + CMP R1, #0x00 + BEQ switch_to_thread /* skip register save at the first time */ + + MRS R1, PSP /* get from thread stack pointer */ + + SUBS R1, R1, #0x20 /* space for {R4 - R7} and {R8 - R11} */ + LDR R0, [R0] + STR R1, [R0] /* update from thread stack pointer */ + + STMIA R1!, {R4 - R7} /* push thread {R4 - R7} register to thread stack */ + + MOV R4, R8 /* mov thread {R8 - R11} to {R4 - R7} */ + MOV R5, R9 + MOV R6, R10 + MOV R7, R11 + STMIA R1!, {R4 - R7} /* push thread {R8 - R11} high register to thread stack */ +switch_to_thread: + LDR R1, =rt_interrupt_to_thread + LDR R1, [R1] + LDR R1, [R1] /* load thread stack pointer */ + + LDMIA R1!, {R4 - R7} /* pop thread {R4 - R7} register from thread stack */ + PUSH {R4 - R7} /* push {R4 - R7} to MSP for copy {R8 - R11} */ + + LDMIA R1!, {R4 - R7} /* pop thread {R8 - R11} high register from thread stack to {R4 - R7} */ + MOV R8, R4 /* mov {R4 - R7} to {R8 - R11} */ + MOV R9, R5 + MOV R10, R6 + MOV R11, R7 + + POP {R4 - R7} /* pop {R4 - R7} from MSP */ + + MSR PSP, R1 /* update stack pointer */ + +pendsv_exit: + /* restore interrupt */ + MSR PRIMASK, R2 + + MOVS R0, #0x04 + RSBS R0, R0, #0x00 + BX R0 +/* + * void rt_hw_context_switch_to(rt_uint32 to); + * R0 --> to + */ + .global rt_hw_context_switch_to + .type rt_hw_context_switch_to, %function +rt_hw_context_switch_to: + LDR R1, =rt_interrupt_to_thread + STR R0, [R1] + + /* set from thread to 0 */ + LDR R1, =rt_interrupt_from_thread + MOVS R0, #0 + STR R0, [R1] + + /* set interrupt flag to 1 */ + LDR R1, =rt_thread_switch_interrupt_flag + MOVS R0, #1 + STR R0, [R1] + + /* set the PendSV exception priority */ + LDR R0, =NVIC_SHPR3 + LDR R1, =NVIC_PENDSV_PRI + LDR R2, [R0,#0x00] /* read */ + ORRS R1, R1, R2 /* modify */ + STR R1, [R0] /* write-back */ + + LDR R0, =NVIC_INT_CTRL /* trigger the PendSV exception (causes context switch) */ + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + NOP + /* restore MSP */ + LDR R0, =SCB_VTOR + LDR R0, [R0] + LDR R0, [R0] + NOP + MSR MSP, R0 + + /* enable interrupts at processor level */ + CPSIE I + + /* never reach here! */ + +/* compatible with old version */ + .global rt_hw_interrupt_thread_switch + .type rt_hw_interrupt_thread_switch, %function +rt_hw_interrupt_thread_switch: + BX LR + NOP + + .global HardFault_Handler + .type HardFault_Handler, %function +HardFault_Handler: + /* get current context */ + MRS R0, PSP /* get fault thread stack pointer */ + PUSH {LR} + BL rt_hw_hard_fault_exception + POP {PC} + + +/* + * rt_uint32_t rt_hw_interrupt_check(void); + * R0 --> state + */ + .global rt_hw_interrupt_check + .type rt_hw_interrupt_check, %function +rt_hw_interrupt_check: + MRS R0, IPSR + BX LR diff --git a/libcpu/arm/cortex-m23/context_iar.S b/libcpu/arm/cortex-m23/context_iar.S new file mode 100644 index 0000000000..4f30c0bc0c --- /dev/null +++ b/libcpu/arm/cortex-m23/context_iar.S @@ -0,0 +1,207 @@ +;/* +; * Copyright (c) 2006-2019, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2010-01-25 Bernard first version +; * 2012-06-01 aozima set pendsv priority to 0xFF. +; * 2012-08-17 aozima fixed bug: store r8 - r11. +; * 2013-06-18 aozima add restore MSP feature. +; * 2019-03-31 xuzhuoyi port to Cortex-M23. +; */ + +;/** +; * @addtogroup CORTEX-M23 +; */ +;/*@{*/ + +SCB_VTOR EQU 0xE000ED08 ; Vector Table Offset Register +NVIC_INT_CTRL EQU 0xE000ED04 ; interrupt control state register +NVIC_SHPR3 EQU 0xE000ED20 ; system priority register (2) +NVIC_PENDSV_PRI EQU 0x00FF0000 ; PendSV priority value (lowest) +NVIC_PENDSVSET EQU 0x10000000 ; value to trigger PendSV exception + + SECTION .text:CODE(2) + THUMB + REQUIRE8 + PRESERVE8 + + IMPORT rt_thread_switch_interrupt_flag + IMPORT rt_interrupt_from_thread + IMPORT rt_interrupt_to_thread + +;/* +; * rt_base_t rt_hw_interrupt_disable(); +; */ + EXPORT rt_hw_interrupt_disable +rt_hw_interrupt_disable: + MRS r0, PRIMASK + CPSID I + BX LR + +;/* +; * void rt_hw_interrupt_enable(rt_base_t level); +; */ + EXPORT rt_hw_interrupt_enable +rt_hw_interrupt_enable: + MSR PRIMASK, r0 + BX LR + +;/* +; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); +; * r0 --> from +; * r1 --> to +; */ + EXPORT rt_hw_context_switch_interrupt + EXPORT rt_hw_context_switch +rt_hw_context_switch_interrupt: +rt_hw_context_switch: + ; set rt_thread_switch_interrupt_flag to 1 + LDR r2, =rt_thread_switch_interrupt_flag + LDR r3, [r2] + CMP r3, #1 + BEQ _reswitch + MOVS r3, #0x1 + STR r3, [r2] + + LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread + STR r0, [r2] + +_reswitch + LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread + STR r1, [r2] + + LDR r0, =NVIC_INT_CTRL ; trigger the PendSV exception (causes context switch) + LDR r1, =NVIC_PENDSVSET + STR r1, [r0] + BX LR + +; r0 --> switch from thread stack +; r1 --> switch to thread stack +; psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from] stack + EXPORT PendSV_Handler +PendSV_Handler: + + ; disable interrupt to protect context switch + MRS r2, PRIMASK + CPSID I + + ; get rt_thread_switch_interrupt_flag + LDR r0, =rt_thread_switch_interrupt_flag + LDR r1, [r0] + CMP r1, #0x00 + BEQ pendsv_exit ; pendsv already handled + + ; clear rt_thread_switch_interrupt_flag to 0 + MOVS r1, #0x00 + STR r1, [r0] + + LDR r0, =rt_interrupt_from_thread + LDR r1, [r0] + CMP r1, #0x00 + BEQ switch_to_thread ; skip register save at the first time + + MRS r1, psp ; get from thread stack pointer + + SUBS r1, r1, #0x20 ; space for {r4 - r7} and {r8 - r11} + LDR r0, [r0] + STR r1, [r0] ; update from thread stack pointer + + STMIA r1!, {r4 - r7} ; push thread {r4 - r7} register to thread stack + + MOV r4, r8 ; mov thread {r8 - r11} to {r4 - r7} + MOV r5, r9 + MOV r6, r10 + MOV r7, r11 + STMIA r1!, {r4 - r7} ; push thread {r8 - r11} high register to thread stack + +switch_to_thread + LDR r1, =rt_interrupt_to_thread + LDR r1, [r1] + LDR r1, [r1] ; load thread stack pointer + + LDMIA r1!, {r4 - r7} ; pop thread {r4 - r7} register from thread stack + PUSH {r4 - r7} ; push {r4 - r7} to MSP for copy {r8 - r11} + + LDMIA r1!, {r4 - r7} ; pop thread {r8 - r11} high register from thread stack to {r4 - r7} + MOV r8, r4 ; mov {r4 - r7} to {r8 - r11} + MOV r9, r5 + MOV r10, r6 + MOV r11, r7 + + POP {r4 - r7} ; pop {r4 - r7} from MSP + + MSR psp, r1 ; update stack pointer + +pendsv_exit + ; restore interrupt + MSR PRIMASK, r2 + + MOVS r0, #0x04 + RSBS r0, r0, #0x00 + BX r0 + +;/* +; * void rt_hw_context_switch_to(rt_uint32 to); +; * r0 --> to +; * this fucntion is used to perform the first thread switch +; */ + EXPORT rt_hw_context_switch_to +rt_hw_context_switch_to: + ; set to thread + LDR r1, =rt_interrupt_to_thread + STR r0, [r1] + + ; set from thread to 0 + LDR r1, =rt_interrupt_from_thread + MOVS r0, #0x0 + STR r0, [r1] + + ; set interrupt flag to 1 + LDR r1, =rt_thread_switch_interrupt_flag + MOVS r0, #1 + STR r0, [r1] + + ; set the PendSV exception priority + LDR r0, =NVIC_SHPR3 + LDR r1, =NVIC_PENDSV_PRI + LDR r2, [r0,#0x00] ; read + ORRS r1,r1,r2 ; modify + STR r1, [r0] ; write-back + + ; trigger the PendSV exception (causes context switch) + LDR r0, =NVIC_INT_CTRL + LDR r1, =NVIC_PENDSVSET + STR r1, [r0] + NOP + + ; restore MSP + LDR r0, =SCB_VTOR + LDR r0, [r0] + LDR r0, [r0] + NOP + MSR msp, r0 + + ; enable interrupts at processor level + CPSIE I + + ; never reach here! + +; compatible with old version + EXPORT rt_hw_interrupt_thread_switch +rt_hw_interrupt_thread_switch: + BX lr + + IMPORT rt_hw_hard_fault_exception + EXPORT HardFault_Handler +HardFault_Handler: + + ; get current context + MRS r0, psp ; get fault thread stack pointer + PUSH {lr} + BL rt_hw_hard_fault_exception + POP {pc} + + END diff --git a/libcpu/arm/cortex-m23/context_rvds.S b/libcpu/arm/cortex-m23/context_rvds.S new file mode 100644 index 0000000000..f243097cc6 --- /dev/null +++ b/libcpu/arm/cortex-m23/context_rvds.S @@ -0,0 +1,216 @@ +;/* +; * Copyright (c) 2006-2019, RT-Thread Development Team +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Change Logs: +; * Date Author Notes +; * 2010-01-25 Bernard first version +; * 2012-06-01 aozima set pendsv priority to 0xFF. +; * 2012-08-17 aozima fixed bug: store r8 - r11. +; * 2013-06-18 aozima add restore MSP feature. +; * 2019-03-31 xuzhuoyi port to Cortex-M23. +; */ + +;/** +; * @addtogroup CORTEX-M23 +; */ +;/*@{*/ + +SCB_VTOR EQU 0xE000ED08 ; Vector Table Offset Register +NVIC_INT_CTRL EQU 0xE000ED04 ; interrupt control state register +NVIC_SHPR3 EQU 0xE000ED20 ; system priority register (2) +NVIC_PENDSV_PRI EQU 0x00FF0000 ; PendSV priority value (lowest) +NVIC_PENDSVSET EQU 0x10000000 ; value to trigger PendSV exception + + AREA |.text|, CODE, READONLY, ALIGN=2 + THUMB + REQUIRE8 + PRESERVE8 + + IMPORT rt_thread_switch_interrupt_flag + IMPORT rt_interrupt_from_thread + IMPORT rt_interrupt_to_thread + +;/* +; * rt_base_t rt_hw_interrupt_disable(); +; */ +rt_hw_interrupt_disable PROC + EXPORT rt_hw_interrupt_disable + MRS r0, PRIMASK + CPSID I + BX LR + ENDP + +;/* +; * void rt_hw_interrupt_enable(rt_base_t level); +; */ +rt_hw_interrupt_enable PROC + EXPORT rt_hw_interrupt_enable + MSR PRIMASK, r0 + BX LR + ENDP + +;/* +; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); +; * r0 --> from +; * r1 --> to +; */ +rt_hw_context_switch_interrupt + EXPORT rt_hw_context_switch_interrupt +rt_hw_context_switch PROC + EXPORT rt_hw_context_switch + + ; set rt_thread_switch_interrupt_flag to 1 + LDR r2, =rt_thread_switch_interrupt_flag + LDR r3, [r2] + CMP r3, #1 + BEQ _reswitch + MOVS r3, #0x01 + STR r3, [r2] + + LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread + STR r0, [r2] + +_reswitch + LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread + STR r1, [r2] + + LDR r0, =NVIC_INT_CTRL ; trigger the PendSV exception (causes context switch) + LDR r1, =NVIC_PENDSVSET + STR r1, [r0] + BX LR + ENDP + +; r0 --> switch from thread stack +; r1 --> switch to thread stack +; psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from] stack +PendSV_Handler PROC + EXPORT PendSV_Handler + + ; disable interrupt to protect context switch + MRS r2, PRIMASK + CPSID I + + ; get rt_thread_switch_interrupt_flag + LDR r0, =rt_thread_switch_interrupt_flag + LDR r1, [r0] + CMP r1, #0x00 + BEQ pendsv_exit ; pendsv already handled + + ; clear rt_thread_switch_interrupt_flag to 0 + MOVS r1, #0x00 + STR r1, [r0] + + LDR r0, =rt_interrupt_from_thread + LDR r1, [r0] + CMP r1, #0x00 + BEQ switch_to_thread ; skip register save at the first time + + MRS r1, psp ; get from thread stack pointer + + SUBS r1, r1, #0x20 ; space for {r4 - r7} and {r8 - r11} + LDR r0, [r0] + STR r1, [r0] ; update from thread stack pointer + + STMIA r1!, {r4 - r7} ; push thread {r4 - r7} register to thread stack + + MOV r4, r8 ; mov thread {r8 - r11} to {r4 - r7} + MOV r5, r9 + MOV r6, r10 + MOV r7, r11 + STMIA r1!, {r4 - r7} ; push thread {r8 - r11} high register to thread stack + +switch_to_thread + LDR r1, =rt_interrupt_to_thread + LDR r1, [r1] + LDR r1, [r1] ; load thread stack pointer + + LDMIA r1!, {r4 - r7} ; pop thread {r4 - r7} register from thread stack + PUSH {r4 - r7} ; push {r4 - r7} to MSP for copy {r8 - r11} + + LDMIA r1!, {r4 - r7} ; pop thread {r8 - r11} high register from thread stack to {r4 - r7} + MOV r8, r4 ; mov {r4 - r7} to {r8 - r11} + MOV r9, r5 + MOV r10, r6 + MOV r11, r7 + + POP {r4 - r7} ; pop {r4 - r7} from MSP + + MSR psp, r1 ; update stack pointer + +pendsv_exit + ; restore interrupt + MSR PRIMASK, r2 + + MOVS r0, #0x04 + RSBS r0, r0, #0x00 + BX r0 + ENDP + +;/* +; * void rt_hw_context_switch_to(rt_uint32 to); +; * r0 --> to +; * this fucntion is used to perform the first thread switch +; */ +rt_hw_context_switch_to PROC + EXPORT rt_hw_context_switch_to + ; set to thread + LDR r1, =rt_interrupt_to_thread + STR r0, [r1] + + ; set from thread to 0 + LDR r1, =rt_interrupt_from_thread + MOVS r0, #0x0 + STR r0, [r1] + + ; set interrupt flag to 1 + LDR r1, =rt_thread_switch_interrupt_flag + MOVS r0, #1 + STR r0, [r1] + + ; set the PendSV exception priority + LDR r0, =NVIC_SHPR3 + LDR r1, =NVIC_PENDSV_PRI + LDR r2, [r0,#0x00] ; read + ORRS r1,r1,r2 ; modify + STR r1, [r0] ; write-back + + ; trigger the PendSV exception (causes context switch) + LDR r0, =NVIC_INT_CTRL + LDR r1, =NVIC_PENDSVSET + STR r1, [r0] + + ; restore MSP + LDR r0, =SCB_VTOR + LDR r0, [r0] + LDR r0, [r0] + MSR msp, r0 + + ; enable interrupts at processor level + CPSIE I + + ; never reach here! + ENDP + +; compatible with old version +rt_hw_interrupt_thread_switch PROC + EXPORT rt_hw_interrupt_thread_switch + BX lr + ENDP + + IMPORT rt_hw_hard_fault_exception + +HardFault_Handler PROC + EXPORT HardFault_Handler + + ; get current context + MRS r0, psp ; get fault thread stack pointer + PUSH {lr} + BL rt_hw_hard_fault_exception + POP {pc} + ENDP + + ALIGN 4 + + END diff --git a/libcpu/arm/cortex-m23/cpuport.c b/libcpu/arm/cortex-m23/cpuport.c new file mode 100644 index 0000000000..842802c866 --- /dev/null +++ b/libcpu/arm/cortex-m23/cpuport.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2006-2019, 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; +} + +extern long list_thread(void); +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); + +#ifdef RT_USING_FINSH + 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); +} |
