ARM Cortex如何处理PendSV Handler

3
我正在创建一个RTOS内核,并需要使用PendSV处理程序进行上下文切换。我通过执行以下操作来触发PendSV处理程序:0xE000ED04 = (0x1 << 28);。这将把PendSVset寄存器设置为1,理论上,处理程序应该被触发。在触发之前我禁用了中断,在触发后启用。启用之后,PendSV应该被触发。优先级是最低的0xFF,systick处理程序的优先级是0x00。 我不确定发生了什么,以及为什么pendsv处理程序没有运行。 我正在使用TI-MSP432控制器,我想也许是控制器处理中断的方式导致的?
它被设置在vectpending中,vectpending为001110,即14表示pendsv。 如果有人能帮忙,我将非常感激。

你有在调试器中进入代码吗?请发布一个 [mcve]。你的中断处理程序在哪里? - jwdonahue
我已经逐步执行了代码,但当我进入enable_interrupts时,我的代码转到了default_handler。 - Mperez
2个回答

1

我假设您在Systick定时器处理程序中设置了位(根据您在评论中提供的信息)。由于您将PendSV优先级设置为低于Systick的优先级,因此PendSV将挂起,直到Systick中断返回。 PendSV无法中断Systick,因为它的优先级较低。从Systick中断返回后,PendSV将通过尾链接中断进行控制。

因此,当您在Systick定时器处理程序中设置位时,PendSV中断不会立即生成,就像您所期望的那样。只有在从Systick中断返回时才会中断。


我建议在回答中不要使用修辞性问题。它们可能会被误解为根本不是答案。你是在尝试回答这个页面顶部的问题,对吗?否则请删除此帖子。 - Yunnosch

0

你尝试过像这样简单的东西吗(随意编写代码实验对于裸机开发至关重要,请尝试不依赖项目其他部分和所有过度复杂的东西)

.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}

调用

#define ICSR 0xE000ED04

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

而在我的情况下,它具有一些UART输出:

12345678 
00000001 
11111111 

然后可以继续进行以下操作:

.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);
}

并查看

12345678 
0000080E 
11111111 

这告诉我当PendSV进入处理程序时会被清除。

就优先级而言,文档说pendsv和svc是相等的,因此

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

并且

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

注意:

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

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

然后我们得到

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

对于pendsv触发而言,时间似乎是永恒的,但由于文档中svc调用相等,所以直到svc调用返回之前它才能被触发。你也可以使用中断来实现这一点,但异常应该比中断更高?请查看文档。

如果pendsv没有发生,那么你的经验与我不应该有什么不同。将问题分成两半。拿出当前的代码并开始逐步删除一些东西,朝着没有任何东西的方向努力。坚持一段时间。从几乎没有东西开始,让pendsv触发,然后开始添加东西,朝着中间的方向努力,找到似乎引起问题的东西,即使你找到了它,那也可能不是最终答案。这是裁剪代码的IT,你可能会创造出另一种情况。

阅读和丢弃代码实验在裸机编程中占据了超过99%的时间。编写最终程序只占很小一部分时间。

你是否做过这些事情来查看中断处理程序或其他你正在执行的操作如何影响pendsv的成功?设置pendsv后,ICSR寄存器显示给你多少时间?

在systick或其他相等级别的处理程序中,剩余的时钟周期相对于pendsv有多少时间?在系统级设计中,你是否确保有空闲时钟供所有处理程序使用?

如果你想在systick处理程序中进行线程交换,那么要么直接执行它,要么使用svc,而不是pendsv。

我删除了一些代码,发现现在vectpending是001110,即PendSV,而vectactive是001111,即Systick Handler。我将继续分析,但我认为这不是优先级问题,因为优先级已经正确设置。 - Mperez
1
一步一步地,你会搞清楚的。 - old_timer
请注意您此处的拼写,特别是包含撇号的单词。这里是一些正确的拼写方式,以及您过去发帖历史中的错拼数量:don't(757),doesn't(479),can't(295),won't(215),let's(150),isn't(140),esp(87)。对于英语不是母语的人有一定的容忍度,但是,风格和故意拼错单词会影响网站的目标,并且会让志愿编辑者额外付出很多努力。请使用浏览器的拼写检查功能。 - halfer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接