ARM cortex 如何处理 PendSV Handler

问题描述

我正在创建一个 RTOS 内核,需要使用 PendSV 处理程序进行上下文切换。我通过执行以下操作来触发 PendSV 处理程序:0xE000ED04 = (0x1

在vectpending中设置,vectpending为001110,pendsv为14。

如果有人可以提供帮助,我将不胜感激。

解决方法

你有没有尝试过这样简单的事情(一次性代码实验对于裸机开发至关重要,不要尝试项目的其余部分和所有过度复杂的东西)

.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 调用返回。你也可以用中断来做到这一点,但异常应该高于中断?检查文档。

没有理由为什么您的 cortex-m 体验应该与我的不同。如果 pendsv 没有发生,则分而治之。将问题一分为二。获取当前代码并开始删除无用的东西。这样做一会儿。从几乎没有触发 pendsv 的情况开始,然后开始添加内容,向中间方向努力,找到似乎导致它的原因,了解即使找到它,也可能不是 IT。这是内脏代码的 IT,您可能创造了另一种情况。

阅读和一次性代码实验超过 99% 的时间都是使用裸机进行的。编写最终程序只占您时间的很小一部分。

您是否已完成这些操作以查看中断处理程序或您正在执行的其他操作如何影响 pendsv 的成功?设置 pendsv 后,ICSR 寄存器显示什么?

相对于为 pendsv 留下的时钟周期而言,systick 或其他同等级别的处理程序中有多少时间,您是否在系统级设计中确保有空闲时钟供处理程序全部使用。

如果您想在 sysstick 处理程序中进行线程交换,那么要么直接执行此操作,要么使用 svc 而不是 pendsv。

,

我假设您在 Systick 计时器处理程序中设置了 PENDSVSET 位(根据您在评论中提供的信息)。由于您设置的 PendSV 优先级低于 Systick 的优先级,因此 PendSV 将挂起直到 Systick 中断返回。 PendSV 不能中断 Systick,因为它的优先级较低。这对你来说有意义吗?

从 Systick 中断返回后,PendSV 将通过尾链中断进行控制。