Linux I2C Driver - 使用str8131(4)static int str8131_i2c_dev_init(void) {     int rc;     str8131_i2c_init();     if ((rc = i2c_add_adapter(&str8131_i2c_adapter)) != 0)     {         TRACE("Adapter %s registration failed, rc=%d\n", str8131_i2c_adapter.name, rc);     婚禮顧問    return rc;     }     if ((rc=request_irq(INTC_I2C_BIT_INDEX, str8131_i2c_interrupt, 0, "HS STR8131_I2C", NULL)) != 0)     {         TRACE("It is unable to get IRQ %d, rc=%d\n", INTC_I2C_BIT_INDEX, rc);         if 房屋買賣((rc=i2c_del_adapter(&str8131_i2c_adapter)) != 0)             TRACE(" i2c_del_adapter failed (%i), that's bad!\n", rc);         return -EAGAIN;     }     return rc; }static __init int i2c_init(void){    澎湖民宿TRACE("i2c_init........\n");    return str8131_i2c_dev_init();}static __exit void i2c_exit(void){    int rc;    TRACE("i2c_exit........\n");    if ((rc=i2c_del_adapter(&str8131_i2c_adapter)) != 0)        TRACE(" i2c_del_adapter failed (%i), that's bad!\n", 西服rc);    free_irq(INTC_I2C_BIT_INDEX,NULL);}module_init(i2c_init);module_exit(i2c_exit);MODULE_AUTHOR("Hughes Chang");MODULE_DESCRIPTION("Test I2C driver for Str8131");MODULE_LICENSE("GPL");我們在 str8131_i2c_dev_init 裡面做硬體的初始化、加入自已的adapter和註冊中斷函式(ISR)。在 i2c_exit時刪除 adapter 和取消中斷。str8131_i2c_init是在做硬體的初始化。關鍵字排名str8131_i2c_interrupt是註冊的中斷函式,內容如下:static irqreturn_t str8131_i2c_interrupt(int irq, void *dev_id, struct pt_regs *regs){    unsigned int volatile interrupt_status;    interrupt_status = *((u32 volatile *)I2C_INTERRUPT_STATUS_REG_ADDR);    *((u32 volatile *)I2C_INTERRUPT_STATUS_REG_ADDR) = interrupt_status;    室內裝潢i2c_cmd_transfer.action_done = (interrupt_status & I2C_ACTION_DONE_FLAG) ? 1 : 0;    i2c_cmd_transfer.error_status = (interrupt_status & I2C_BUS_ERROR_FLAG) ? ((interrupt_status >> 8) & 0xFF) : 0;    TRACE("Get an interrupt from i2c bus, %d, 0x%x\n"            , i2c_cmd_transfer.action_done, 買屋i2c_cmd_transfer.error_status);    if (i2c_cmd_transfer.error_status && (i2c_cmd_transfer.error_status != 0xFF)){        TRACE("Get an error from i2c bus, error_status=0x%x\n", i2c_cmd_transfer.error_status);        HAL_I2C_DISABLE_I2C();    }    新成屋wake_up_interruptible(&wait_queue);    return IRQ_HANDLED;}i2c_cmd_transfer 是一個自訂的結構,為全域變數,主要要來代表要傳送給i2c的命令,這裡判斷中斷時是不是有錯誤發生,如果有的話,就關掉 i2c,不然的話就喚醒 wait_queue,wait_queue 這裡是當硬體傳輸時,用來等待中斷用的,類似下面的用法(I2C_Command代表傳輸的函式,ISR代表中斷函式) 1. I2C_Command 開始硬體傳輸2. I2C_Command呼叫 居酒屋interruptible_sleep_on_timeout 函式來等待中斷函式傳回的結果3. 中斷發生,kernel 呼叫 ISR4. ISR呼叫 wake_up_interruptible(&wait_queue) 來喚醒 interruptible_sleep_on_timeout 5. I2C_Command 查看中斷函式的結果來判斷傳輸是否正常6. 如果沒有發生中斷的話,interruptible_sleep_on_timeout 就會傳回0, I2C_Command就知道並沒等到     中斷發生,那可能就要再調整等待的時間,又或是其他的錯誤(硬裝潢體初始化時未開啟其功能等)。


.msgcontent .wsharing ul li { text-indent: 0; }



分享

Facebook
Plurk
YAHOO!

創作者介紹

POLYMUSO

rc61rclesz 發表在 痞客邦 PIXNET 留言(0) 人氣()