seL4 Interrupts(七)

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
/******************************************************************************* * Function Name : USB_Init * Description : USB初始化 * Input : None * * Output : None * Return : None ******************************************************************************/ void USB_Init(void) { //CCM->PHYPA = 0x10;//usbphy clk sel 60M USB_POWER_ON; USB_SoftReset(); //释放USB_PHY CPM->CPM_SRSTCR1 &= ~(1 << USBPHY_RST_RELEASE_BIT); USBPHY_CLK_SEL_60M; g_RevOffset = 0; g_transLens = 0; g_Ep0Data_Stage = 0; g_usbVer = 0;//USB1.1 /* Global USB Register */ gUSBC_fifoReg = (USBC_FIFOTypeDef*)(USBC_BASE_ADDR+0x60); gUSBC_ComReg = (USBC_CommonTypeDef*)USBC_BASE_ADDR; gUSBC_IdxReg = (USBC_IndexedTypeDef*)(USBC_BASE_ADDR+0x10); //The suspend mode is disable before BULK-Only tranfer start g_suspendMode = 0; /* Setup USB register */ //enable usb common interrupt //0 1 2 3 4 5 6 7 (bit) //Susp Resume Reset SOF Conn Discon SessReq VBusErr gUSBC_ComReg->INTRUSBE = USB_INTERRUPT_RESET |USB_INTERRUPT_CONNECT |USB_INTERRUPT_DISCON |USB_INTERRUPT_SUSPEND |USB_INTERRUPT_RESUME; //|USB_INTERRUPT_SOF; //enable ep0 and ep1 tx interrupts,clear other tx interrupts gUSBC_ComReg->INTRTXE_L = USB_INTERRUPT_EP0|(1<<USB_ENDPOINT_INDEX); //enable ep1 rx interrupt,clear other rx interrupts gUSBC_ComReg->INTRRXE_L = (1<<USB_ENDPOINT_INDEX); g_usb_data_in_ep = USB_ENDPOINT_INDEX; g_usb_data_out_ep = USB_ENDPOINT_INDEX;//send //ensure ep0 control/status regesters appeare in the memory map. gUSBC_ComReg->EINDEX = CONTROL_EP; SetFIFO_Addr(USBEPX_TABLE[0],3); //Enable Soft connection if(g_usbVer == 1) gUSBC_ComReg->UCSR = USB_POWER_SOFT_CONN|USB_POWER_HS_ENAB; else { gUSBC_ComReg->UCSR = USB_POWER_SOFT_CONN; } interrupt_setup(USB_INT_NUM, 0x00); }解析,如果需要提供相关手册资料,请提出
03-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值