Interrupts
- 了解 IRQControl能力的用途。
- 能够取得对于某些特定中断的能力
- 学习如何处理中断以及中断和通知对象之间的关系
Background
IRQControl
根任务被赋予了一个单一的能力,从该能力可以派生出系统中所有 irq的能力,seL4_CapIRQControl。此功能可以在 CSpace 和 CSlot 之间移动,但不能复制。撤销此能力会导致删除对所有 irq能力的所有访问。
IRQHandlers
IRQHandler能力提供对单个 irq 的访问,并且是标准的 seL4 能力:它们可以根据系统策略移动和复制。IRQHandler 是通过调用 IRQControl 能力以及特定于架构的参数来获得的。下面是获取 IRQHandler 的示例。
//获取 7 号 irq 的能力并将其放置在单级 cspace 的 cslot 10 中。
error = seL4_IRQControl_Get(seL4_IRQControl, 7, cspace_root, 10, seL4_WordBits);
有多种不同的调用来获取依赖于硬件的 irq能力,包括:
- seL4_IRQControl_GetIOAPIC (x86)
- seL4_IRQControl_GetMSI (x86)
- seL4_IRQControl_GetTrigger (ARM)
Receiving interrupts
通过使用irq 的 IRQHandler 能力向通知对象注册能力来接收中断,如下所示:
seL4_IRQHandler_SetNotification(irq_handler, notification);
成功时,此调用将在中断发生时向通知对象传递信号。为了在同一个通知对象上处理多个中断,可以为绑定到每个 IRQHandler(中断处理程序)的通知能力设置不同的徽章。当中断到达时,绑定到该 IRQHandler 的通知对象的徽章会与通知对象中的数据字进行按位或运算。可以回想一下在通知教程中用于区分信号的徽章技术。
可以使用seL4_Poll 轮询中断或使用seL4_Wait 等待中断。任一系统调用都会导致通知对象的数据字作为消息的标记进行传递,并且数据字被清除。
seL4_IRQHandler_Clear 可用于解除通知与 IRQHandler 的绑定。
Handling interrupts
一旦中断被接收并由软件处理完毕,可以通过对该 IRQHandler 调用 seL4_IRQHandler_Ack 来解除中断屏蔽。在一个中断被触发后,seL4 不会再传递进一步的中断,直到该 IRQHandler 被确认(acked)。这意味着中断在被处理后,需要显式地通过 seL4_IRQHandler_Ack 来告知内核,中断已处理完毕,并且可以再次接收该中断。
练习
在本教程中,您将为 zynq7000 ARM 平台上提供的定时器驱动程序设置中断处理。该计时器驱动程序可以位于项目目录根目录下的projects/sel4-tutorials/zynq_timer_driver 文件夹内,即可以找到.repo 文件夹以及执行初始repo init 命令的位置。本教程设置了两个进程:timer.c(计时器驱动程序和 RPC 服务器)和 client.c(发出单个请求)。
教程成功初始化后,您将看到以下内容:
Booting all finished, dropped to user space
timer client: hey hey hey
timer: got a message from 61 to sleep 2 seconds
<<seL4(CPU 0) [decodeInvocation/646 T0xe8276600 "tcb_timer" @10658]: Attempted to invoke a null cap #9.>>
main@timer.c:79 [Cond failed: error]
Failed to ack irq
我们使用的定时器驱动程序在 TTC0_TIMER1_IRQ 编号中发出中断。
练习:调用包含seL4_IRQControl 功能的irq_control,将TTC0_TIMER1_IRQ 的IRQHandler 功能放入irq_handler CSlot 中。
/* TODO invoke irq_control to put the interrupt for TTC0_TIMER1_IRQ in
cslot irq_handler (depth is seL4_WordBits) */
error = seL4_IRQControl_Get(irq_control, TTC0_TIMER1_IRQ, cnode, irq_handler, seL4_WordBits);
成功后,您应该看到以下输出,没有之前出现的错误消息,因为 irq_handle 功能现在有效:
Booting all finished, dropped to user space
timer client: hey hey hey
timer: got a message from 61 to sleep 2 seconds
Undelivered IRQ: 42
这是来自内核的警告消息,表示已收到 IRQ 号 42 的 IRQ,但未设置通知功能来发送信号。
练习:现在通过调用 irq 处理程序来设置通知功能 (ntfn)。
/* TODO set ntfn as the notification for irq_handler */
error = seL4_IRQHandler_SetNotification(irq_handler, ntfn);
现在的输出是:
Booting all finished, dropped to user space
timer client: hey hey hey
timer: got a message from 61 to sleep 2 seconds
Tick
由于中断尚未被确认,因此仅传送一个中断。定时器驱动程序被编程为每毫秒发出一个中断,因此我们需要在回复客户端之前计算 2000 个中断。
练习:在定时器驱动程序中处理中断后确认该中断。
while (1) {
/* Handle the timer interrupt */
seL4_Word badge;
seL4_Wait(ntfn, &badge);
timer_handle_irq(&timer_drv);
if (count == 0) {
printf("Tick\n");
}
/* TODO ack the interrupt */
error = seL4_IRQHandler_Ack(irq_handler);
ZF_LOGF_IF(error, "Failed to ack irq");
count++;
if (count == 1000 * msg) {
break;
}
}
现在定时器中断继续进来,并且回复被传递到客户端。
Booting all finished, dropped to user space
timer client: hey hey hey
timer: got a message from 61 to sleep 2 seconds
Tick
timer client wakes up
1194

被折叠的 条评论
为什么被折叠?



