ARM Macro Assembler Page 1 1 00000000 ;Copyright (C) 2021 xiaoliang<1296283984@qq.com>. 2 00000000 3 00000000 PRESERVE8 4 00000000 THUMB 5 00000000 6 00000000 AREA |.text|, CODE, READONLY 7 00000000 8 00000000 PendSV_Handler PROC 9 00000000 IMPORT kevent_schedule 10 00000000 EXPORT PendSV_Handler 11 00000000 12 00000000 ;PendSV异常处理程序通过插入伪造的异常返 上下文实现抢占被中断的线程的CPU 13 00000000 ;并在抢占结束后手动的回复被中断线程的 下文 14 00000000 15 00000000 ;当发生异常时,当前的LR与被压栈的xPSR指 了被中断的线程某些配置和状态, 16 00000000 ;LR: 17 00000000 ;BIT3: 当这个位被设置时,指示异常返回到T hread模式,否则返回到Handler模式,PendSV异 发生时,这个位应该为1 18 00000000 ;BIT2: 当这个位被设置时,指示异常返回使 PSP恢复线程上下文,否则使用MSP 19 00000000 ; 20 00000000 ;已压栈的xPSR: 21 00000000 ;BIT24: 当这个位被设置时,异常返回后进入 Thumb模式,否则返回到ARM模式 22 00000000 ;BIT9: 当这个位被设置时,表示栈已开启8Byt e对齐,并指示在弹出线程上下文后SP+4 23 00000000 24 00000000 ;备份LR的状态 25 00000000 4670 MOV R0, LR 26 00000002 27 00000002 ;我们需要插入异常返回现场需要使用的空 ,并获取它的栈顶 28 00000002 29 00000002 ;检查LR BIT2确定异常返回使用PSP还是MSP 30 00000002 0741 LSLS R1, R0, #29 31 00000004 D402 BMI INSERT_FAKE_EXC_RETURN_CONTEXT_ SPACE_USE_PSP 32 00000006 33 00000006 ;因为当前处于Handler模式,因此我们可以直 接使用SP来操作MSP 34 00000006 B088 SUB SP, #32 35 00000008 466A MOV R2, SP 36 0000000A E004 B INSERT_FAKE_EXC_RETURN_CONTEXT_ SPACE_ENDIF 37 0000000C 38 0000000C INSERT_FAKE_EXC_RETURN_CONTEXT_SPACE_USE_PSP 39 0000000C ;在Handler模式下,需要使用MRS与MSR指令操作 PSP 40 0000000C F3EF 8209 MRS R2, PSP 41 00000010 3A20 SUBS R2, #32 42 00000012 F382 8809 MSR PSP, R2 43 00000016 INSERT_FAKE_EXC_RETURN_CONTEXT_SPACE_ENDIF 44 00000016 45 00000016 ;我们设置堆栈中返回后的位置为PENDSV_EXCRET ARM Macro Assembler Page 2 URNHANDLER 46 00000016 A005 ADR R0, PENDSV_EXC_RETURN_HANDLER 47 00000018 6190 STR R0, [R2, #24] 48 0000001A 49 0000001A ;我们设置堆栈中xPSR,使异常返回后进入Thu mb模式并恢复以前的IPSR状态 50 0000001A 2101 MOVS R1, #1 51 0000001C 0609 LSLS R1, #24 52 0000001E ;读取返回上下文中的IPSR 53 0000001E 6BD0 LDR R0, [R2, #60] 54 00000020 0680 LSLS R0, #26 55 00000022 0E80 LSRS R0, #26 56 00000024 ;设置xPSR为BIT24 + IPSR 57 00000024 4301 ORRS R1, R0 58 00000026 61D1 STR R1, [R2, #28] 59 00000028 60 00000028 ;异常返回,进入PENDSV_EXCRETURNHANDLER 61 00000028 4770 BX LR 62 0000002A BF00 NOP 63 0000002C PENDSV_EXC_RETURN_HANDLER 64 0000002C ;调用调度程序 65 0000002C F7FF FFFE BL kevent_schedule 66 00000030 67 00000030 ;当抢占程序执行结束之后,我们需要恢复 占前的上下文 68 00000030 ;我们还需要检查xPSR的BIT9,确定恢复之后 栈顶位置 69 00000030 70 00000030 ;我们将R3指向线程恢复后栈顶的前两个字 位置,用于存放R4与PC 71 00000030 AB06 ADD R3, SP, #24 72 00000032 73 00000032 ;读取xPSR 74 00000032 9807 LDR R0, [SP, #28] 75 00000034 76 00000034 ;判断xPSR的BIT9,若置位则栈顶需要+4 77 00000034 0581 LSLS R1, R0, #22 78 00000036 0FC9 LSRS R1, #31 79 00000038 0089 LSLS R1, #2 80 0000003A 185B ADDS R3, R1 81 0000003C 82 0000003C ;读取线程的PC,并根据xPSR的BIT24设置Thumb或 者ARM模式 83 0000003C 9906 LDR R1, [SP, #24] 84 0000003E 01C2 LSLS R2, R0, #7 85 00000040 0FD2 LSRS R2, #31 86 00000042 4311 ORRS R1, R2 87 00000044 88 00000044 ;我们总是需要在R0-R12,LR,SP恢复之后才能 执行返回 89 00000044 ;此时,我们没有可以使用的寄存器保存PC 90 00000044 ;因此需要将PC存入栈中,使用POP指令进行 复 91 00000044 ;同时我们也无法在恢复R0-R3之后,再保存 顶的位置 92 00000044 ;因此我们必须使用R4记录栈顶,因此还需 对R4做保存 93 00000044 6059 STR R1, [R3, #4] ARM Macro Assembler Page 3 94 00000046 601C STR R4, [R3, #0] 95 00000048 461C MOV R4, R3 96 0000004A 97 0000004A ;恢复R12,LR,xPSR 98 0000004A ;为了兼容M0,我们不使用LDRD指令来恢复R12 LR 99 0000004A F380 8803 MSR xPSR, R0 100 0000004E A804 ADD R0, SP, #16 101 00000050 C806 LDM R0!, {R1-R2} 102 00000052 468C MOV R12, R1 103 00000054 4696 MOV LR, R2 104 00000056 105 00000056 ;恢复R0-R3,SP 106 00000056 BC0F POP {R0-R3} 107 00000058 46A5 MOV SP, R4 108 0000005A 109 0000005A ;返回被抢占的线程 110 0000005A BD10 POP {R4, PC} 111 0000005C 112 0000005C ENDP 113 0000005C END Command Line: --debug --xref --diag_suppress=9931 --cpu=Cortex-M3 --apcs=interw ork --depend=.\objects\preempt_nofp.d -o.\objects\preempt_nofp.o -ID:\Keil\ARM\ Packs\Keil\STM32F1xx_DFP\2.4.1\Device\Include -Id:\Keil\ARM\CMSIS\Include --pre define="__UVISION_VERSION SETA 538" --predefine="STM32F10X_HD SETA 1" --list=.\ listings\preempt_nofp.lst ..\..\..\arch\cortex-m\armcc\preempt_nofp.s ARM Macro Assembler Page 1 Alphabetic symbol ordering Relocatable symbols .text 00000000 Symbol: .text Definitions At line 6 in file ..\..\..\arch\cortex-m\armcc\preempt_nofp.s Uses None Comment: .text unused INSERT_FAKE_EXC_RETURN_CONTEXT_SPACE_ENDIF 00000016 Symbol: INSERT_FAKE_EXC_RETURN_CONTEXT_SPACE_ENDIF Definitions At line 43 in file ..\..\..\arch\cortex-m\armcc\preempt_nofp.s Uses At line 36 in file ..\..\..\arch\cortex-m\armcc\preempt_nofp.s Comment: INSERT_FAKE_EXC_RETURN_CONTEXT_SPACE_ENDIF used once INSERT_FAKE_EXC_RETURN_CONTEXT_SPACE_USE_PSP 0000000C Symbol: INSERT_FAKE_EXC_RETURN_CONTEXT_SPACE_USE_PSP Definitions At line 38 in file ..\..\..\arch\cortex-m\armcc\preempt_nofp.s Uses At line 31 in file ..\..\..\arch\cortex-m\armcc\preempt_nofp.s Comment: INSERT_FAKE_EXC_RETURN_CONTEXT_SPACE_USE_PSP used once PENDSV_EXC_RETURN_HANDLER 0000002C Symbol: PENDSV_EXC_RETURN_HANDLER Definitions At line 63 in file ..\..\..\arch\cortex-m\armcc\preempt_nofp.s Uses At line 46 in file ..\..\..\arch\cortex-m\armcc\preempt_nofp.s Comment: PENDSV_EXC_RETURN_HANDLER used once PendSV_Handler 00000000 Symbol: PendSV_Handler Definitions At line 8 in file ..\..\..\arch\cortex-m\armcc\preempt_nofp.s Uses At line 10 in file ..\..\..\arch\cortex-m\armcc\preempt_nofp.s Comment: PendSV_Handler used once 5 symbols ARM Macro Assembler Page 1 Alphabetic symbol ordering External symbols kevent_schedule 00000000 Symbol: kevent_schedule Definitions At line 9 in file ..\..\..\arch\cortex-m\armcc\preempt_nofp.s Uses At line 65 in file ..\..\..\arch\cortex-m\armcc\preempt_nofp.s Comment: kevent_schedule used once 1 symbol 338 symbols in table