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

[Cortex-M3] PendSV, svc and priorities

Note: This was originally posted on 15th June 2012 at http://forums.arm.com

Is it possible a case when PendSV will execute earlier than SVcall when both have the same priority? The cpu is Cortex-M3 STM32F1xx

I had an issue when PendSV and SVC have the same priority levels (lowest) with this code:

ePendSV_handler:
mrs r0,PSP
stmdb r0!,{r4-r11,lr}

; ... load ... load new PSP valu here to R0

ldmia r0!,{r4-r11,lr}
msr PSP,r0
bx lr


void eSVCall(void){
unsigned int a0,a1,a2,a3,svc,*psp;

psp=(U32*)__get_PSP();
a0=psp[0];a1=psp[1];a2=psp[2];a3=psp[3]; //get registers from user stack
svc=psp[4]; // service call ID

a0=service(svc,a0,a1,a2,a3);

psp[0]=a0; //overwrite R0(return value) in user stack
}

SVC usage in thread level code:
mov R12, #1 ; service call ID
mov R0, #123 ; arg
svc #0
; now R0 holds return value


PENDSVSET can be set asynchronously from timer interrupt or from service() function. Sometimes I had a situations when  ePendSV was called before  eSVCall and overwrited PSP register and then  eSVCall fails because new PSP is not tend to the thread which called svc instruction. When I incrased priority of SVcall exception the code above began working correct.

Can some exception execute and terminate executiong svc instruction when svc instruction is fetched but not executed yet?

sorry for bad english...
Parents
  • Note: This was originally posted on 15th June 2012 at http://forums.arm.com

    I see what is happening now.  I didn't really understand what you were doing because I thought PendSV exceptions was triggered from timer interrupt and the timer interrupt happen just before an SVC. What you are having is something different.

    The sequence:
    - PendSV pending status is set, so the NVIC detect it and accept the interrupt.
    - Since PendSV is an asynchronous exception, in parallel the core execute SVC as the last instruction before the core execute the ISR.
    - SVC pending is set, but because PendSV exception arrived before SVC, so the NVIC arranged it as tail chain.

    To be honest, it seems to be a very strange way to program this. SInce PendSV is asynchronous to the instruction stream, it could take place after several instructions has executed, or it can happened immediately. For example, if the program is running on a device with waitstate on flash, the SVC might not get executed.

    If you want to make sure PendSV happen before the SVC, you can use memory barrier instructions:
            SCB->ICSR=SCB_ICSR_PENDSVSET;
            __DSB();
            __ISB();
            svc00();


    If you want to make sure PendSV happen after SVC, you should set the PENDSV pending status inside SVC.

    Hope this helps.
    regards,
    Joseph
Reply
  • Note: This was originally posted on 15th June 2012 at http://forums.arm.com

    I see what is happening now.  I didn't really understand what you were doing because I thought PendSV exceptions was triggered from timer interrupt and the timer interrupt happen just before an SVC. What you are having is something different.

    The sequence:
    - PendSV pending status is set, so the NVIC detect it and accept the interrupt.
    - Since PendSV is an asynchronous exception, in parallel the core execute SVC as the last instruction before the core execute the ISR.
    - SVC pending is set, but because PendSV exception arrived before SVC, so the NVIC arranged it as tail chain.

    To be honest, it seems to be a very strange way to program this. SInce PendSV is asynchronous to the instruction stream, it could take place after several instructions has executed, or it can happened immediately. For example, if the program is running on a device with waitstate on flash, the SVC might not get executed.

    If you want to make sure PendSV happen before the SVC, you can use memory barrier instructions:
            SCB->ICSR=SCB_ICSR_PENDSVSET;
            __DSB();
            __ISB();
            svc00();


    If you want to make sure PendSV happen after SVC, you should set the PENDSV pending status inside SVC.

    Hope this helps.
    regards,
    Joseph
Children
No data