The app is ucos II.
OSStartHighRdy LDR R0, =NVIC_SYSPRI14 ; Set the PendSV exception priority LDR R1, =NVIC_PENDSV_PRI STR R1, [R0] ; Not storing entire byte with STRB to avoid error
MOVS R0, #0 ; Set the PSP to 0 for initial context switch call MSR PSP, R0
LDR R0, =OS_CPU_ExceptStkBase ; Initialize the MSP to the OS_CPU_ExceptStkBase LDR R1, [R0] MSR MSP, R1
LDR R0, =OSRunning ; OSRunning = TRUE MOVS R1, #1 STRB R1, [R0]
LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) LDR R1, =NVIC_PENDSVSET STR R1, [R0]
CPSIE I ; Enable interrupts at processor level
OSStartHang B OSStartHang ; Should never get here
PendSV_Handler CPSID I ; Prevent interruption during context switch MRS R0, PSP ; PSP is process stack pointer
CMP R0, #0 BEQ OS_CPU_PendSVHandler_nosave ; equivalent code to CBZ from M3 arch to M0 arch ; Except that it does not change the condition code flags
SUBS R0, R0, #0x10 ; Adjust stack pointer to where memory needs to be stored to avoid overwriting STM R0!, {R4-R7} ; Stores 4 4-byte registers, default increments SP after each storing SUBS R0, R0, #0x10 ; STM does not automatically call back the SP to initial location so we must do this manually
LDR R1, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP; LDR R1, [R1] STR R0, [R1] ; R0 is SP of process being switched out
; At this point, entire context of process has been savedOS_CPU_PendSVHandler_nosave PUSH {R14} ; Save LR exc_return value LDR R0, =OSTaskSwHook ; OSTaskSwHook(); BLX R0 POP {R0} MOV R14, R0
LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy; LDR R1, =OSPrioHighRdy LDRB R2, [R1] STRB R2, [R0]
LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy; LDR R1, =OSTCBHighRdy LDR R2, [R1] STR R2, [R0]
LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
LDM R0!, {R4-R7} ; Restore R4-R7 from new process stack
MSR PSP, R0 ; Load PSP with new process SP
MOV R0, R14 MOVS R1, #0x04 ; Immediate move to register ORRS R0, R1 ; Ensure exception return uses process stack MOV R14, R0 CPSIE I BX LR ; Exception return will restore remaining context
;ALIGN ; Ensures that ARM instructions start on four-byte boundary
END
the boot code
void PendSV_Handler(){// void (*pFunction)(void);
uint32_t address;
// HT_Flash_WordRead(&address, FLASH_OFFSET+4*16,1); // pFunction = (void (*)(void))address; // pFunction();//Jump t address=FLASH_OFFSET+4*14; (*(void(*)(void))(*(uint32_t*) address))();}
void SVC_Handler(){// void (*pFunction)(void);
// HT_Flash_WordRead(&address, FLASH_OFFSET+4*16,1); // pFunction = (void (*)(void))address; // pFunction();//Jump t address=FLASH_OFFSET+4*11; (*(void(*)(void))(*(uint32_t*) address))();}
Hi Robert, it seems like you took handler mode as thread mode. The CPU enters handler mode to service the interrupt. PendSV is expected to be set in handler mode as pending, and be serviced until the current interrupt handler is complete
You can see that the Bootloader calls the Application from either the PendSV or SVC. This means the application is starting up in Handler Mode as opposed to Thread Mode like it is normally after startup. This is why when the OP runs the Application without the Bootloader it works and running it with the Bootloader it does not. SO when the application set the PendSV bit, the interrupt never happens because we have not left Handler Mode. So It returns to the Infinite loop on OSStartHang.
Thank you, Robert, for the explanation. Yes, you are right.
When the app code trigger the PendSV, the PendSV interrupt was happen, but PendSV interrupt function is in bootloader code. So I added code in bootloader PendSV_Handler in order to jumb to PendSV of app. I found that the SP and LR was wrong. Finally, I solved the problem by adding some assemblers to make the SP and LR was right 。
Hi, hyue, I meet the same problem. And it seem like we are using the same chip (HT).
My app can run ok with preemption disable, but not ok while preemption enable. and app can run ok in both situations if without bootloader.
Could you please share the detail about how you fix this problem? that will be very helpful to me. Thank you!