您是否尝试过像这样简单的事情(一次性代码实验对于裸机开发至关重要,请尝试不使用项目的其余部分和所有过度复杂的东西)
.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 调用返回。您也可以使用中断来执行此操作,但是异常应该高于中断吗?检查文档。
没有理由为什么您的皮质-m 体验与我的不同。如果没有发生pendsv,则分而治之。把问题分成两半。获取当前代码并开始删除无用的东西。这样做一会儿。从几乎没有触发 pendsv 开始,然后开始添加东西,向中间工作,在那里你找到似乎导致它的原因,理解即使你找到它,也可能不是 IT。那是 IT 的内脏代码,你可能创造了另一种情况。
阅读和一次性代码实验的时间远远超过您使用裸机的 99%。编写最终程序只占您时间的一小部分。
您是否做过这些事情来查看中断处理程序或您正在做的其他事情如何影响pendsv 成功?设置 pendsv 后 ICSR 寄存器向您显示什么?
相对于为 pendsv 留下的时钟周期,systick 或其他同等级别的处理程序中有多少时间,您是否在系统级设计中确保有空闲时钟供处理程序所有时间使用。
如果你想在 systick 处理程序中进行线程交换,那么要么就这样做,要么使用 svc 而不是 pendsv。