This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Tasks can't switch to others, always run at OSStartHang. but whitout boot code ,the app can run ok. the core of the chip is cortex-M0

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 saved
OS_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);

    uint32_t address;

 //   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))();
}

Parents
  • It seems like the PendSV exception is not triggered as you expected. Please note setting the PendSV bit in the code should allow the PendSV operation to be pended to the current operation or to execute at the next opportunity when priority allows.

    Without knowing detail of the code and what is occurring around the setting of the PendSV bit I cannot comment on why this is failing, there are 2 reasons that may stop the PendSV exception from running.


    Firstly, is the priority of the executing code correct, if the current execution level is too high then the PendSV code will not execute as it will not have sufficient priority.

    Secondly, has there been any change to the System Handler and State Register which can remove the active bit of the PendSVC, this will ensure that a PendSV exception is not taken.

    It seems like you meet the first one. You set the PendSV in the main code (thread mode) instead of interrupt handler (handler mode). The PendSV will wait for the complete of current thread mode code's execution, but it will not. So no PendSV will be taken.

Reply
  • It seems like the PendSV exception is not triggered as you expected. Please note setting the PendSV bit in the code should allow the PendSV operation to be pended to the current operation or to execute at the next opportunity when priority allows.

    Without knowing detail of the code and what is occurring around the setting of the PendSV bit I cannot comment on why this is failing, there are 2 reasons that may stop the PendSV exception from running.


    Firstly, is the priority of the executing code correct, if the current execution level is too high then the PendSV code will not execute as it will not have sufficient priority.

    Secondly, has there been any change to the System Handler and State Register which can remove the active bit of the PendSVC, this will ensure that a PendSV exception is not taken.

    It seems like you meet the first one. You set the PendSV in the main code (thread mode) instead of interrupt handler (handler mode). The PendSV will wait for the complete of current thread mode code's execution, but it will not. So no PendSV will be taken.

Children
No data