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 Reply Children
  • 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!