我爲我的ARM Cortex-M3操作系統使用了exokernel模型。當一個任務想從UART讀取時,它會調用一個庫函數,如果沒有數據,它會進行SVC調用來阻塞任務(這會導致內核將該任務置於該IRQ的等待隊列中,並啓用IRQ )。當中斷髮生時,等待它的所有任務都被移動到可運行隊列,並且中斷再次被禁止。在IRQ後Cortext-M3上的任務切換崩潰
當我有一個固定的任務數組時,這個模型工作正常,但現在我已經移動到鏈表以允許更多類型的等待隊列(例如IPC消息)。變化中的某些東西正在導致崩潰。這裏的調試輸出:
Creating task 0 (idle task)
task0 stack top is 2007cd20
Starting SysTick @ 100Hz
Becoming task 0
Switching to task [email protected] with SP 2007c3e8
GSM task starting
Switching to task [email protected] with SP 2007c810
Monitoring RFID reader
Blocking task rfid on IRQ 7
Switching to task [email protected] with SP 2007cc38
Switching to task [email protected] with SP 2007ccd8
Switching to task [email protected] with SP 2007c390
Blocking task gsm on IRQ 8
Switching to task [email protected] with SP 2007cc38
Switching to task [email protected] with SP 2007ccd8
Switching to task [email protected] with SP 2007cc38
Starting GPS tracking
Blocking task gps on IRQ 6
Switching to task [email protected] with SP 2007ccd8
[... repeats...]
Switching to task [email protected] with SP 2007ccd8
Unblocking tasks waiting on IRQ 8
Switching to task [email protected] with SP 2007c3a0
Switching to task [email protected] with SP 2007ccd8
Switching to task [email protected] with SP 2007c3a0
Fault: Usage fault
r0 = 2007c3a0
r1 = 10007fb8
r2 = 2007ccd8
r3 = 10007fb8
r12 = 00000008
lr = fffffffd
pc = 0070c858
psr = 00000003
BFAR = e000ed38
CFSR = 00040000
DFSR = 00000000
AFSR = 00000000
SHCSR = 00070008
所以一切都很好,直到中斷。實際輸出取決於哪個UART首先有數據,但是模式是相同的:發生中斷時,將未被阻止的任務切換到第二次時發生故障。
下面是代碼的相關位。一種組件,墊片:
zeptos_pendsv_isr:
push {lr}
mrs r0, psp
stmfd r0!, {r4-r11}
bl zeptos_schedule
ldmfd r0!, {r4-r11}
msr psp, r0
pop {pc}
以及C功能:
static void pendsv(void) {
SCB->ICSR |= 1 << 28;
}
void *zeptos_schedule(void *sp) {
if (current_task) {
current_task->sp = sp;
DL_APPEND(runnable_tasks, current_task);
}
current_task = runnable_tasks;
DL_DELETE(runnable_tasks, current_task);
zeptos_printf("Switching to task %[email protected]%p with SP %p\n", current_task->name, current_task, current_task->sp);
return current_task->sp;
}
static void block(void *sp, uint8_t irq) {
zeptos_printf("Blocking task %s on IRQ %i\n", current_task->name, irq);
current_task->sp = sp;
DL_APPEND(irq_blocked_tasks[irq], current_task);
current_task = 0;
NVIC_EnableIRQ(irq);
pendsv();
}
void __attribute__((interrupt)) zeptos_isr(void) {
int irq = (SCB->ICSR & 0xff) - 16;
zeptos_printf("Unblocking tasks waiting on IRQ %i\n", irq);
NVIC_DisableIRQ(irq);
// NVIC_ClearPendingIRQ(irq);
DL_CONCAT(runnable_tasks, irq_blocked_tasks[irq]);
irq_blocked_tasks[irq] = 0;
pendsv();
}
void __attribute__((interrupt)) zeptos_svc_isr(void) {
__disable_irq();
uint32_t *sp = (uint32_t *) __get_PSP();
uint32_t pc = sp[6];
uint8_t svc_type = *((uint8_t *) pc - 2);
switch (svc_type) {
case 0:
sleep(sp[0]);
break;
case 1:
block(sp, sp[0]);
break;
default:
zeptos_puts("Bad SVC type\n");
}
__enable_irq();
}
void Zeptos_BlockOnIrq(uint8_t irq) {
asm("svc 1");
}
SVC,系統定時器和PendSV的分別是優先29,30和31。
故障是INVPC類型的使用故障,這意味着正在使用錯誤類型的EXC_RETURN值。我檢查過,每次都是0xfffffffd。
有什麼建議嗎?我應該在哪裏看?
在http://www.keil.com/appnotes/files/apnt209.pdf中,它指出爲異常返回堆棧的PC值(您已標識爲0x0070c858)指向違規指令。你能不能在你的C代碼中給我們留下評論?在行尾會有'// < - 0x0070c858'。我懷疑你的「進程堆棧」以某種方式被錯誤地從異常中錯誤地返回。 – nonsensickle