设备驱动--中断开关执行的匹配
近期項目生產過程中出現概率為萬分之幾異常,此中異常實在是折磨人啊!連續幾天的熬夜復現分析,總算是找到異常原因;為加強自己對問題的認知特編輯此文對問題做進一步梳理。
???
1 問題現象
????? 開機偶見TP失效;
2 問題分析
??? 2.1? 先后對測量TP各路信號均正常;
??? 2.2? 通過 cat? /proc/interrupts? 查看開機過程中TP中斷有成功注冊;
??? 2.3? 因為問題發生在開機過程所有按照開機時TP驅動的執行流程對代碼進行再次評審,發現可能存在TP中斷關閉與開啟可能存在不匹配問題;
? ? ? ??2.3.1??? TP驅動代碼異常時的執行流程如下:
? ? ? ? ? ? ? ? ? ? ? ? 在開機TP驅動注冊的probe函數中首先會完成TP的中斷處理函數注冊,再進 入TP固件升級的邏輯判斷。如下函數:
?
? ? ? ? ? ? ? ? ? ? ? ? s32?MsDrvInterfaceTouchDeviceProbe(struct i2c_client, const structi2c_device_id )
? ? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.........
? ? ? ? ? ? ? ? ? ? ? ? ? ? DrvPlatformLyrTouchDeviceRegisterFingerTouchInterruptHandler();
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.........
? ? ? ? ? ? ? ? ? ? ? ? ? ? DrvIcFwLyrCheckFirmwareUpdateBySwId();
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.........
? ? ? ? ? ? ? ? ? ? ? }
?
? ? ? ? ? ? ? ? ? ? ? ? ?在進入固件升級處理邏輯時會進行判斷是否需要關閉TP中斷,如下代碼當判斷符合_gInterruptFlag == 1條件但沒有執行到關閉中斷并沒有清除 _gInterruptFlag ? ? ? ? ? ?? ? ? ? ??標志時,TP有中斷產生執行流程轉入執行TP的中斷處理程序。
?
? ? ? ? ? ? ? ? ? ? ? ?void DrvPlatformLyrDisableFingerTouchReport(void)
? ? ? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(_gInterruptFlag == 1)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? disable_irq(_gIrq);
???????????????????????????????????? ?_gInterruptFlag = 0;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ?在進入到中斷處理函數后會同樣進行中斷邏輯判斷,即 _gInterruptFlag ?為1時 就關閉TP中斷處理。此異常的執行流程正好滿足 _gInterruptFlag 等于1,所以在 ? ? ? ? ? ? ? ? ? ? ? TP中斷處理函數會執行關閉TP中斷動作并設置 _gInterruptFlag 為0 ;但是當代碼流程返回到TP固件升級的處理,接著之前判斷成功 _gInterruptFlag ?==1之后關閉TP中 ? ? ? ? ? ? ? ? 斷函數繼續執行。? ? ? ? ? ? ? ? ? ? ??代碼執行到此時TP中斷被連續關閉兩次。而此后代碼的執行流程中不會存在多個進程同時訪問同一全局變量數據,所以后續代碼的執行流程中對于TP中斷的開啟和? ? ??關閉都是成對的執行,所以前面異常的連續兩次的關閉中斷只會有一次對應的中斷開啟處理。
???????2.3.2???? kernel中開/關閉中斷代碼如下,在開和關中斷的處理函數中會對會對開關中斷次數進行匹配性計數,關中斷時desc->depth?會被加1,而開中斷時會對desc->depth進行減一操作。
???????????????????
??????????????????? 假設設備代碼中開關中斷的執行流程如:連續兩次的disable ,之后每執行一次enable都會對應的執行一次disable。那么問題就出現了由于之前執行了兩次disable動作desc->depth值為2,之后執行enable函數時也之能走到default 流程即給desc->depth數值減一,不會真正的enable中斷。
??????????????????????
????????????????????設備驅動中對于中斷關和開一定要匹配,進行多少次關中斷就需要對應的進行多少次開中斷操作才能使能中斷處理,否則可能出現中斷關閉后不能開啟造成設備無法被響應的問題。????????????????
?
???????????????????? void __disable_irq(struct irq_desc *desc)
???????????????????? {
?????????????????????????? if (!desc->depth++)
?????????????????????????? irq_disable(desc);
?????????????????????}
?
????????????????? ??void __enable_irq(struct irq_desc *desc)
??????????????????? {
????????????????????????? ?switch (desc->depth) {
?????????????????????????? case 0:
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?err_out:
?????????????????????????????????????? WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n",
??????????????????????????????????? ?? irq_desc_get_irq(desc));
???????????????????????????????????????break;
?????????????????????????? case 1: {
???????????????????????????????????????if (desc->istate & IRQS_SUSPENDED)
????????????????????????????????????? ?goto err_out;
????????????????????????????????????????/* Prevent probing on this irq: */
????????????????????????????????????? ?irq_settings_set_noprobe(desc);
???????????????????????????????????? ??irq_enable(desc);
?????????????????????????????????????? check_irq_resend(desc);
?????????????????????????????????????? ?/* fall-through */
??????????????????????????????????????}
?????????????????????????? ?default:
?????????????????????????????????? ???desc->depth--;
????????????????????????????}
?????????????????? }
??
3 問題總結
?
??????????對于多進程間共享的全局變量沒有進行保護,多個進程間同時對該變量進行方式時期間變量數據發生變化造成代碼執行? 關中斷 與 開中斷 次數不匹配,雖然設備成功注冊但是不能被正常響應。
?????????????
4? 問題修改
?????
????????? 對于多進程間共享數進行鎖保護,只有獲得鎖的進行才能訪問該共享數據。
? ? ? ? ? ?
spin_lock_irqsave(&_gIrqLock, nIrqFlag);
?? ? ? if(_gInterruptFlag == 1)
? ? ? ? {
? ? ? ? ? ?disable_irq(_gIrq);
? ? ? ? ? _gInterruptFlag = 0;
? ? ? ? }
spin_unlock_irqrestore(&_gIrqLock,nIrqFlag); ??
總結
以上是生活随笔為你收集整理的设备驱动--中断开关执行的匹配的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 电容屏(二):驱动调试之
- 下一篇: input驱动12种事件类型Event