作者gn00618777 (非常念旧)
看板LinuxDev
标题[问题] 关於 kernel driver interrupt ISR
时间Wed Mar 8 17:50:55 2017
先进们好,现在状况是这样的。目前 MCU 端要传 data 给我 AP 开发板端,透过一根
gpio,注册为irq,我这边写了个 driver,当中用到的 API 为 request_threaded_irq。
这个 api 的第二个参数 handler(上半部)为 null,第三个参数为一个 function thread
这个 thread(下半部),会透过 spi_sync 来跟 MCU 要资料,至於甚麽时候 MCU
会透过 irq 来通知我的 driver? 也就是每 1ms(每秒1000笔) 来通知我,我
每次透过 spi_sync要到的 64 byte 资料,都还会做个 check crc 的错误判断,只要
有错,这64 byte 就作废。录了 7200 秒,crc error 98 笔,大概1%,想要降至0.x%
看了波型,发现错误的时机点几乎都是,MCU发了irq,而我的 driver 却没有马上
进入 thread 发 spi command 来要资料,都是延迟了才要,也就是延迟进入 thread。
我估狗了中断机制,和API查询,发现用 request_threaded_irq 创造的 thread,
会类似於 workqueue 这下半部机制,而且属於 process 上下文。既然属於process
它就会被 kernel 来排班,甚麽时候执行,是看 kernel 而定。
request_thread_irq 里面有个 irqflags 参数,我给他设定为 IRQF_ONE_SHOT,这个
参数代表表的是 当我这个 thread 执行完毕,才会再把 irq 打开,所以我猜想,
也许就是 kernel 还在处理 thread 的 task,irq 还没被打开,所以 MCU 就算发 irq
我可能会导致延迟去处理,或者甚至不理IRQ(有看过波型也有发生过)。请问有甚麽可
行的方向来解决我想要即刻去处理中断的问题?
1 我有想过把 thread 要做的内容写在第二个参数的上半部 funcion,既然是上半部
的中断的函式,driver 一定能立即去做处理。可是这又有一个问题,我在网路上
搜寻到,在中断的 context 下,规定他不能睡眠,也不能阻塞,我 spi_sync 似乎
是个阻塞的 function,我除了作 spi_sync 也有做 input_sync 的 function,这看
起来也是个阻塞同步 function。中断函式一定不能加上阻塞的吗? 即使它运作时间
非常短?
2 softirq (下半部机制方法)???
希望能有些资讯能从前辈们获得,万分感激。
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 61.220.69.181
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/LinuxDev/M.1488966659.A.105.html
1F:→ wens: 不能等 buffer 满了才送 interrupt 啊, 大概 1/2 ~ 3/4 满 03/09 10:49
2F:→ wens: 就该送了。interrupt handler没有保证马上执行的 03/09 10:49
3F:→ gn00618777: 好感动,感谢w大回应。您说 buffer 满是说谁的 buffer 03/09 12:57
4F:→ gn00618777: interrupt handler 没有保证马上执行,那如果我是在上 03/09 12:58
5F:→ gn00618777: 半部,也就是request_thread_irq的第二个参数设一个 03/09 13:00
6F:→ gn00618777: ISR(硬中断),会不会这个handler 就会保证马上执行? 03/09 13:01
7F:→ gn00618777: 因为查询结果,request_thread_irq的第三个参数,是在 03/09 13:02
8F:→ gn00618777: process context的,所以不保证迅速执行,而是被kerne 03/09 13:02
9F:→ gn00618777: 排班,而 request_thread_irq的irqflags我有设 03/09 13:03
10F:→ gn00618777: IRQF_ONE_SHOT,这个代表 thread process要执行完才能 03/09 13:04
11F:→ gn00618777: 再打开 interrupt,所以我的 driver 会不理 mcu 发的 03/09 13:04
12F:→ gn00618777: interrupt 甚至会延迟进入 thread handler 03/09 13:05
13F:推 askacis: 要是我会请MCU那边改写法,miss interrupt就掉资料, 03/10 12:53
14F:→ askacis: 别人一天到晚在等MCU就饱了 03/10 12:54
15F:→ gn00618777: 好,我再花点时间去了解MCU有没有更好的解决方案 03/11 11:26
16F:→ gn00618777: AP这端我还有两到三种方法可以尝试,之後再来这边报告 03/11 11:27
17F:→ gn00618777: 谢谢。 03/11 11:27
18F:→ wens: 没设ONE_SHOT会更崩溃,而且SPI bus一次也只能一个存取啊 03/13 00:09
19F:→ wens: 我说的buffer指的是MCU上的buffer。举一些I/O装置为例,通常 03/13 00:10
20F:→ wens: 会内建个FIFO,可以存一点资料,然後可以设定要满到什麽程度 03/13 00:10
21F:→ wens: 的时候发 interrupt或DRQ (DMA的状况) 03/13 00:11
22F:→ wens: AP这端我觉得你没太多可以做的,因为你就是没办法在top half 03/13 00:12
23F:→ wens: 做IO去读资料出来,而且即便是top half也没保证马上轮到你, 03/13 00:12
24F:→ wens: 其他的ISR 也会挡你啊 03/13 00:12
25F:推 askacis: 另外一个暴力的方式是不要用kernel的SPI API,自己填 03/13 09:19
26F:→ askacis: register去控制SPI拿资料, 03/13 09:20
27F:→ gn00618777: 为什麽要用填 register的方式? 目前测时间 spi cs 拉 03/14 19:17
28F:→ gn00618777: 下来到被拉上来,整个spi写入读取只花 0.1ms 03/14 19:18
29F:→ gn00618777: 请问w大,您说我没办法在 top half 读资料,是因为API 03/14 19:20
30F:→ gn00618777: 是阻塞的function吗? 然後a大才说用填暂存器方式? 03/14 19:21
31F:→ gn00618777: 另外为何说没设 ONE_SHOT会更崩溃..?? 我就是不打算 03/14 19:29
32F:→ gn00618777: 在 thread 做,所以 ONE_SHOT 没有应该不会影响吧?? 03/14 19:29
33F:→ gn00618777: 抱歉..因为板子还未到,我只能一直先这样询问了解 03/14 19:30
34F:→ gn00618777: 恳请各位赐教 谢谢 03/14 19:31
35F:→ wens: 如果没有要在 thread 里面做,那似乎无所谓? 03/17 16:50
36F:→ wens: 然後top half不能读资料确实是 API 限制没错 (SPI可能sleep) 03/17 16:51