3

I am creating a RTOS kernel and need to use the PendSV handler for context switching. I trigger the PendSV handler by doing : 0xE000ED04 = (0x1 << 28);. This sets the PendSVset register to 1, so theoretically, the handler should trigger. I do disable interrupts before triggering and enable after triggering. After the enabling PendSV should trigger. The priority is the lowest 0xFF and the systick handler priority is 0x00. I am not sure what is going on and why the pendsv handler is not running. I am using an TI-MSP432 controller and I figure maybe its the way the controller is handling the interrupt?

It is set in vectpending, vectpending is 001110 which is 14 for pendsv.

If anybody can help, I'd greatly appreciate it.

Dan
  • 10,303
  • 5
  • 36
  • 53
Mperez
  • 85
  • 1
  • 6
  • Have you stepped into the code in a debugger? Please post an [mcve]. Where is your interrupt handler? – jwdonahue Feb 28 '21 at 03:58
  • I have stepped through the code but when I step into enable_interrupts my code goes to the default_handler. – Mperez Feb 28 '21 at 17:47

2 Answers2

1

I am assuming that you set PENDSVSET bit within Systick timer handler (from the information you gave in your comment). Since you set the PendSV priority lower than the priority of the Systick, so PendSV will pend until Systick interrupt returns. PendSV cannot interrupt Systick because it has lower priority. On returning from the Systick interrupt, PendSV will take hold through tail-chaining interrupt.

So no, PendSV interrupt will not be immediately generated when you set PENDSVSET bit within Systick timer handler as what you've expected. It will only interrupt on returning from the Systick interrupt.

kaosad
  • 21
  • 5
  • I recommend against rhetoric questions in answers. They risk being misunderstood as not an answer at all. You are trying to answer the question at the top of this page, aren't you? Otherwise please delete this post. – Yunnosch Jun 11 '21 at 13:01
0

Have you tried something simple like this (throwaway code experiments are crucial for bare-metal development, try without the rest of the project and all the over-complications)

.thumb

.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word pendsv_handler
.word hang

.thumb_func
reset:
    bl notmain
    b hang
    
.thumb_func
hang:   b .
.align

...


.thumb_func
pendsv_handler:
    mov r4,#1
    bx lr
    
.thumb_func
.globl pendsv_test
pendsv_test:
    push {r4,lr}
    mov r4,#0
    str r1,[r0]
pendsv_loop:
    cmp r4,#0
    bne pendsv_loop
    mov r0,r4
    pop {r4,pc}

call with

#define ICSR 0xE000ED04

hexstring(0x12345678);
hexstring(pendsv_test(ICSR,1<<28));
hexstring(0x11111111);

and in my case that has some uart output:

12345678 
00000001 
11111111 

And can then move on to this:

.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word pendsv_handler
.word hang



// ************** EXCEPTION HANDLER ***************
void pendsv_handler ( void )
{
    hexstring(GET32(ICSR));
}
// ************** EXCEPTION HANDLER ***************

int notmain ( void )
{
    clock_init();
    uart2_init();
    hexstring(0x12345678);
    PUT32(ICSR,1<<28);
    hexstring(0x11111111);
    return(0);
}

and see

12345678 
0000080E 
11111111 

which tells me that PendSV is cleared when it goes to the handler.

As far as priority goes, the docs say pendsv and svc are equal, so

stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word svc_handler
.word hang
.word hang
.word pendsv_handler
.word hang

and

// ************** EXCEPTION HANDLER ***************
void pendsv_handler ( void )
{
    hexstring(0x22222222);
    hexstring(GET32(ICSR));
    hexstring(0x22222222);
}
// ************** EXCEPTION HANDLER ***************

// ************** EXCEPTION HANDLER ***************
void svc_handler ( void )
{
    unsigned int ra;
    
    hexstring(GET32(ICSR));
    PUT32(ICSR,1<<28);
    for(ra=0;ra<20;ra++)
    {
        hexstring(GET32(ICSR));
    }
}
// ************** EXCEPTION HANDLER ***************

int notmain ( void )
{
    clock_init();
    uart2_init();
    hexstring(0x12345678);
    SVC();
    hexstring(0x11111111);
    return(0);
}

note:

.thumb_func
.globl PUT32
PUT32:
    str r1,[r0]
    bx lr

.thumb_func
.globl GET32
GET32:
    ldr r0,[r0]
    bx lr

then we get

12345678 
0000080B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
1000E80B 
22222222 
0000080E 
22222222 
11111111

An eternity of time for the pendsv to fire but because the svc call is equal per the documentation then it cannot, until svc call returns. You can do this with interrupts as well, but the exceptions should be higher than the interrupts? Check the docs.

No reason why your experience should be different than mine on your cortex-m. If pendsv is not happening then divide and conquer. Divide the problem in half. Take the current code and start removing stuff working toward nothing. Do that for a bit. Start from almost nothing having the pendsv firing then start adding stuff, work toward the middle where you find what seems to cause it, understanding that even if you find it, that may not be IT. That is IT for the gutted code, you may have created another situation.

Reading and throwaway code experiments are well over 99% of your time with bare-metal. Writing of the final program is a very small percentage of your time.

Have you done these things to see how interrupt handlers or other things you are doing has affected pendsv success? What is the ICSR register showing you after you set pendsv?

How much time is in the systick or other equal level handlers relative to clock cycles left for pendsv, have you insured in your system level design that there are free clocks for the handlers to all have time.

If you want to do the thread swap in the systick handler then either just do it or use svc perhaps and not pendsv.

old_timer
  • 69,149
  • 8
  • 89
  • 168
  • I removed some code and realized that now vectpending is 001110 which is PendSV and vectactive is 001111 is Systick Handler. I am going to keep dividing but I thought it was a priority issue but now I don't think so since the priorities are set properly. – Mperez Feb 28 '21 at 17:54
  • 1
    one step at a time you will figure it out – old_timer Feb 28 '21 at 18:31
  • Please take care with your spellings here, especially words containing apostrophes. Here are some correct spellings, plus the number of mispellings in your post history: don't (757), doesn't (479), can't (295), won't (215), let's (150), isn't (140), esp (87). There is some tolerance here for people who don't have English as a first language, but stylistic and deliberate misspelling works against the aims of the site, and is a great deal of work being deliberately made for volunteer editors. Please use the spell-checker feature in your browser. – halfer Mar 06 '21 at 14:55