1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        解決一個I2C讀寫問題

        共 12759字,需瀏覽 26分鐘

         ·

        2021-01-29 08:44

        之前寫關(guān)于I2C相關(guān)的文章

        排查一個觸摸屏驅(qū)動問題

        MTK 平臺TP調(diào)試遇坑

        1、問題

        今天遇到一個問題,我們有一個芯片,I2C讀寫失敗,導(dǎo)致錄音有問題,而且是偶現(xiàn)的。

        log提示看到是返回 -6

        <3>[??730.336308]??(3)[2085:tinycap]es7243_read?error2,?ret?=?-6.

        下面流程找一下這個 -6 是從哪里來的

        2、I2c 發(fā)送流程

        i2c-core.c

        調(diào)用發(fā)送函數(shù)

        /**
        ?*?__i2c_transfer?-?unlocked?flavor?of?i2c_transfer
        ?*?@adap:?Handle?to?I2C?bus
        ?*?@msgs:?One?or?more?messages?to?execute?before?STOP?is?issued?to
        ?*?terminate?the?operation;?each?message?begins?with?a?START.
        ?*?@num:?Number?of?messages?to?be?executed.
        ?*
        ?*?Returns?negative?errno,?else?the?number?of?messages?executed.
        ?*
        ?*?Adapter?lock?must?be?held?when?calling?this?function.?No?debug?logging
        ?*?takes?place.?adap->algo->master_xfer?existence?isn't?checked.
        ?*/

        int?__i2c_transfer(struct?i2c_adapter?*adap,?struct?i2c_msg?*msgs,?int?num)
        {
        ?unsigned?long?orig_jiffies;
        ?int?ret,?try;

        ?if?(adap->quirks?&&?i2c_check_for_quirks(adap,?msgs,?num))
        ??return?-EOPNOTSUPP;

        ?/*?i2c_trace_msg?gets?enabled?when?tracepoint?i2c_transfer?gets
        ??*?enabled.??This?is?an?efficient?way?of?keeping?the?for-loop?from
        ??*?being?executed?when?not?needed.
        ??*/

        ?if?(static_key_false(&i2c_trace_msg))?{
        ??int?i;
        ??for?(i?=?0;?i????if?(msgs[i].flags?&?I2C_M_RD)
        ????trace_i2c_read(adap,?&msgs[i],?i);
        ???else
        ????trace_i2c_write(adap,?&msgs[i],?i);
        ?}

        ?/*?Retry?automatically?on?arbitration?loss?*/
        ?orig_jiffies?=?jiffies;
        ?for?(ret?=?0,?try?=?0;?try?<=?adap->retries;?try++)?{
        ??ret?=?adap->algo->master_xfer(adap,?msgs,?num);
        ??if?(ret?!=?-EAGAIN)
        ???break;
        ??if?(time_after(jiffies,?orig_jiffies?+?adap->timeout))
        ???break;
        ?}

        ?if?(static_key_false(&i2c_trace_msg))?{
        ??int?i;
        ??for?(i?=?0;?i????if?(msgs[i].flags?&?I2C_M_RD)
        ????trace_i2c_reply(adap,?&msgs[i],?i);
        ??trace_i2c_result(adap,?i,?ret);
        ?}

        ?return?ret;
        }
        EXPORT_SYMBOL(__i2c_transfer);

        里面有一句

        ret?=?adap->algo->master_xfer(adap,?msgs,?num);

        這里需要找到初始化的位置,這種指針初始化的位置,一般都是和平臺設(shè)備相關(guān)的,這里也是一個技巧,初學(xué)者看到這類指針一般都會比較懵。

        所以,就開始去找吧。

        因為我用的是MTK平臺,所以需要去找到MTK平臺相關(guān)里面初始化的這個指針

        i2c-mt65xx.c?(D:\source\kernel-4.4\drivers\i2c\busses)?line?755?:??.master_xfer?=?mtk_i2c_transfer,

        在文件

        i2c-mt65xx.c

        這里初始化了

        static?const?struct?i2c_algorithm?mtk_i2c_algorithm?=?{
        ?.master_xfer?=?mtk_i2c_transfer,
        ?.functionality?=?mtk_i2c_functionality,
        };

        然后再調(diào)用發(fā)送函數(shù)

        static?int?mtk_i2c_transfer(struct?i2c_adapter?*adap,
        ???????struct?i2c_msg?msgs[],?int?num)

        {
        ?int?ret;
        ?int?left_num?=?num;
        ?struct?mtk_i2c?*i2c?=?i2c_get_adapdata(adap);

        ?ret?=?mtk_i2c_clock_enable(i2c);
        ?if?(ret)
        ??return?ret;

        ?i2c->auto_restart?=?i2c->dev_comp->auto_restart;

        ?/*?checking?if?we?can?skip?restart?and?optimize?using?WRRD?mode?*/
        ?if?(i2c->auto_restart?&&?num?==?2)?{
        ??if?(!(msgs[0].flags?&?I2C_M_RD)?&&?(msgs[1].flags?&?I2C_M_RD)?&&
        ??????msgs[0].addr?==?msgs[1].addr)?{
        ???i2c->auto_restart?=?0;
        ??}
        ?}

        ?if?(i2c->auto_restart?&&?num?>=?2?&&?i2c->speed_hz?>?MAX_FS_MODE_SPEED)
        ??/*?ignore?the?first?restart?irq?after?the?master?code,
        ???*?otherwise?the?first?transfer?will?be?discarded.
        ???*/

        ??i2c->ignore_restart_irq?=?true;
        ?else
        ??i2c->ignore_restart_irq?=?false;

        ?while?(left_num--)?{
        ??if?(!msgs->buf)?{
        ???dev_dbg(i2c->dev,?"data?buffer?is?NULL.\n");
        ???ret?=?-EINVAL;
        ???goto?err_exit;
        ??}

        ??if?(msgs->flags?&?I2C_M_RD)
        ???i2c->op?=?I2C_MASTER_RD;
        ??else
        ???i2c->op?=?I2C_MASTER_WR;

        ??if?(!i2c->auto_restart)?{
        ???if?(num?>?1)?{
        ????/*?combined?two?messages?into?one?transaction?*/
        ????i2c->op?=?I2C_MASTER_WRRD;
        ????left_num--;
        ???}
        ??}

        ??/*?len?<=?8:?use?fifo?mode,?len?>?8:?use?DMA?mode.?*/
        ??ret?=?mtk_i2c_do_transfer(i2c,?msgs,?num,?left_num);
        ??if?(ret?0)
        ???goto?err_exit;

        ??msgs++;
        ?}
        ?/*?the?return?value?is?number?of?executed?messages?*/
        ?ret?=?num;

        err_exit:
        ?mtk_i2c_clock_disable(i2c);
        ?return?ret;
        }

        3、返回 值的代碼位置

        在文件

        i2c-mt65xx.c

        中的函數(shù)

        static?int?mtk_i2c_do_transfer(struct?mtk_i2c?*i2c,?struct?i2c_msg?*msgs,
        ??????????int?num,?int?left_num)

        {
        ?bool?dma_en;
        ?u8?*data_buf;
        ?u16?data_len;
        ?u16?read_len;
        ?u16?addr_reg;
        ?u16?start_reg;
        ?u16?control_reg;
        ?u16?restart_flag?=?0;
        ?u32?reg_4g_mode;
        ?dma_addr_t?rpaddr?=?0;
        ?dma_addr_t?wpaddr?=?0;
        ?int?ret;

        ?i2c->irq_stat?=?0;

        ?if?(i2c->auto_restart)
        ??restart_flag?=?I2C_RS_TRANSFER;

        ?reinit_completion(&i2c->msg_complete);

        ?control_reg?=?readw(i2c->base?+?OFFSET_CONTROL)?&
        ???~(I2C_CONTROL_DIR_CHANGE?|?I2C_CONTROL_RS);
        ?if?((i2c->speed_hz?>?400000)?||?(left_num?>=?1))
        ??control_reg?|=?I2C_CONTROL_RS;

        ?if?(i2c->op?==?I2C_MASTER_WRRD)
        ??control_reg?|=?I2C_CONTROL_DIR_CHANGE?|?I2C_CONTROL_RS;

        ?writew(control_reg,?i2c->base?+?OFFSET_CONTROL);

        ?/*?set?start?condition?*/
        ?if?(i2c->speed_hz?<=?100000)
        ??writew(I2C_ST_START_CON,?i2c->base?+?OFFSET_EXT_CONF);
        ?else
        ??writew(I2C_FS_START_CON,?i2c->base?+?OFFSET_EXT_CONF);

        ?addr_reg?=?msgs->addr?<1;
        ?if?(i2c->op?==?I2C_MASTER_RD)
        ??addr_reg?|=?0x1;

        ?writew(addr_reg,?i2c->base?+?OFFSET_SLAVE_ADDR);

        ?/*?Clear?interrupt?status?*/
        ?writew(restart_flag?|?I2C_HS_NACKERR?|?I2C_ACKERR?|
        ????????I2C_TRANSAC_COMP,?i2c->base?+?OFFSET_INTR_STAT);
        ?writew(I2C_FIFO_ADDR_CLR,?i2c->base?+?OFFSET_FIFO_ADDR_CLR);

        ?/*?Enable?interrupt?*/
        ?writew(restart_flag?|?I2C_HS_NACKERR?|?I2C_ACKERR?|
        ????????I2C_TRANSAC_COMP,?i2c->base?+?OFFSET_INTR_MASK);

        ?/*?Set?transfer?and?transaction?len?*/
        ?if?(i2c->op?==?I2C_MASTER_WRRD)?{
        ??if?(i2c->dev_comp->aux_len_reg)?{
        ???writew(msgs->len,?i2c->base?+?OFFSET_TRANSFER_LEN);
        ???writew((msgs?+?1)->len,?i2c->base?+
        ??????????OFFSET_TRANSFER_LEN_AUX);
        ??}?else?{
        ???writew(msgs->len?|?((msgs?+?1)->len)?<8,
        ??????????i2c->base?+?OFFSET_TRANSFER_LEN);
        ??}
        ??writew(I2C_WRRD_TRANAC_VALUE,?i2c->base?+?OFFSET_TRANSAC_LEN);
        ?}?else?{
        ??writew(msgs->len,?i2c->base?+?OFFSET_TRANSFER_LEN);
        ??writew(num,?i2c->base?+?OFFSET_TRANSAC_LEN);
        ?}

        ?/*?Prepare?buffer?data?to?start?transfer?*/
        ?if?(msgs->len?>?I2C_FIFO_SIZE?||?(i2c->op?==?I2C_MASTER_WRRD?&&
        ?????(msgs?+?1)->len?>?I2C_FIFO_SIZE))?{
        ??dma_en?=?true;

        ??if?(i2c->op?==?I2C_MASTER_RD)?{
        ???writel(I2C_DMA_INT_FLAG_NONE,?i2c->pdmabase?+?OFFSET_INT_FLAG);
        ???writel(I2C_DMA_CON_RX,?i2c->pdmabase?+?OFFSET_CON);
        ???rpaddr?=?dma_map_single(i2c->dev,?msgs->buf,
        ??????msgs->len,?DMA_FROM_DEVICE);
        ???if?(dma_mapping_error(i2c->dev,?rpaddr))
        ????return?-ENOMEM;

        ???if?(i2c->dev_comp->support_33bits)?{
        ????reg_4g_mode?=?mtk_i2c_set_4g_mode(rpaddr);
        ????writel(reg_4g_mode,?i2c->pdmabase?+?OFFSET_RX_4G_MODE);
        ???}

        ???writel((u32)rpaddr,?i2c->pdmabase?+?OFFSET_RX_MEM_ADDR);
        ???writel(msgs->len,?i2c->pdmabase?+?OFFSET_RX_LEN);
        ??}?else?if?(i2c->op?==?I2C_MASTER_WR)?{
        ???writel(I2C_DMA_INT_FLAG_NONE,?i2c->pdmabase?+?OFFSET_INT_FLAG);
        ???writel(I2C_DMA_CON_TX,?i2c->pdmabase?+?OFFSET_CON);
        ???wpaddr?=?dma_map_single(i2c->dev,?msgs->buf,
        ??????msgs->len,?DMA_TO_DEVICE);
        ???if?(dma_mapping_error(i2c->dev,?wpaddr))
        ????return?-ENOMEM;

        ???if?(i2c->dev_comp->support_33bits)?{
        ????reg_4g_mode?=?mtk_i2c_set_4g_mode(wpaddr);
        ????writel(reg_4g_mode,?i2c->pdmabase?+?OFFSET_TX_4G_MODE);
        ???}

        ???writel((u32)wpaddr,?i2c->pdmabase?+?OFFSET_TX_MEM_ADDR);
        ???writel(msgs->len,?i2c->pdmabase?+?OFFSET_TX_LEN);
        ??}?else?{
        ???writel(I2C_DMA_CLR_FLAG,?i2c->pdmabase?+?OFFSET_INT_FLAG);
        ???writel(I2C_DMA_CLR_FLAG,?i2c->pdmabase?+?OFFSET_CON);
        ???wpaddr?=?dma_map_single(i2c->dev,?msgs->buf,
        ??????msgs->len,?DMA_TO_DEVICE);
        ???if?(dma_mapping_error(i2c->dev,?wpaddr))
        ????return?-ENOMEM;
        ???rpaddr?=?dma_map_single(i2c->dev,?(msgs?+?1)->buf,
        ??????(msgs?+?1)->len,?DMA_FROM_DEVICE);
        ???if?(dma_mapping_error(i2c->dev,?rpaddr))?{
        ????dma_unmap_single(i2c->dev,?wpaddr,
        ???????msgs->len,?DMA_TO_DEVICE);
        ????return?-ENOMEM;
        ???}

        ???if?(i2c->dev_comp->support_33bits)?{
        ????reg_4g_mode?=?mtk_i2c_set_4g_mode(wpaddr);
        ????writel(reg_4g_mode,?i2c->pdmabase?+?OFFSET_TX_4G_MODE);

        ????reg_4g_mode?=?mtk_i2c_set_4g_mode(rpaddr);
        ????writel(reg_4g_mode,?i2c->pdmabase?+?OFFSET_RX_4G_MODE);
        ???}

        ???writel((u32)wpaddr,?i2c->pdmabase?+?OFFSET_TX_MEM_ADDR);
        ???writel((u32)rpaddr,?i2c->pdmabase?+?OFFSET_RX_MEM_ADDR);
        ???writel(msgs->len,?i2c->pdmabase?+?OFFSET_TX_LEN);
        ???writel((msgs?+?1)->len,?i2c->pdmabase?+?OFFSET_RX_LEN);
        ??}

        ??if?(i2c->op?!=?I2C_MASTER_RD)
        ???writel(I2C_DMA_START_EN,?i2c->pdmabase?+?OFFSET_EN);
        ?}?else?{
        ??dma_en?=?false;

        ??if?(i2c->op?!=?I2C_MASTER_RD)?{
        ???data_buf?=?msgs->buf;
        ???data_len?=?msgs->len;

        ???while?(data_len--)
        ????writew_relaxed(*(data_buf++),?i2c->base?+?OFFSET_DATA_PORT);
        ??}
        ?}

        ?if?(!i2c->auto_restart)?{
        ??start_reg?=?I2C_TRANSAC_START;
        ?}?else?{
        ??start_reg?=?I2C_TRANSAC_START?|?I2C_RS_MUL_TRIG;
        ??if?(left_num?>=?1)
        ???start_reg?|=?I2C_RS_MUL_CNFG;
        ?}
        ?writew(start_reg,?i2c->base?+?OFFSET_START);

        ?if?(dma_en?&&?i2c->op?==?I2C_MASTER_RD)
        ??writel(I2C_DMA_START_EN,?i2c->pdmabase?+?OFFSET_EN);

        ?ret?=?wait_for_completion_timeout(&i2c->msg_complete,
        ???????i2c->adap.timeout);

        ?/*?Clear?interrupt?mask?*/
        ?writew(~(restart_flag?|?I2C_HS_NACKERR?|?I2C_ACKERR?|
        ????????I2C_TRANSAC_COMP),?i2c->base?+?OFFSET_INTR_MASK);

        ?if?(dma_en)?{
        ??if?(i2c->op?==?I2C_MASTER_WR)?{
        ???dma_unmap_single(i2c->dev,?wpaddr,
        ??????msgs->len,?DMA_TO_DEVICE);
        ??}?else?if?(i2c->op?==?I2C_MASTER_RD)?{
        ???dma_unmap_single(i2c->dev,?rpaddr,
        ??????msgs->len,?DMA_FROM_DEVICE);
        ??}?else?{
        ???dma_unmap_single(i2c->dev,?wpaddr,?msgs->len,
        ??????DMA_TO_DEVICE);
        ???dma_unmap_single(i2c->dev,?rpaddr,?(msgs?+?1)->len,
        ??????DMA_FROM_DEVICE);
        ??}
        ?}

        ?if?(ret?==?0)?{
        ??dev_dbg(i2c->dev,?"addr:?%x,?transfer?timeout\n",?msgs->addr);
        ??mtk_i2c_init_hw(i2c);
        ??return?-ETIMEDOUT;
        ?}

        ?completion_done(&i2c->msg_complete);

        ?if?(i2c->irq_stat?&?(I2C_HS_NACKERR?|?I2C_ACKERR))?{
        ??dev_dbg(i2c->dev,?"addr:?%x,?transfer?ACK?error\n",?msgs->addr);
        ??mtk_i2c_init_hw(i2c);
        ??return?-ENXIO;
        ?}

        ?if?(!dma_en?&&?i2c->op?!=?I2C_MASTER_WR)?{
        ??data_buf?=?(i2c->op?==?I2C_MASTER_RD)???msgs->buf?:
        ??????(msgs?+?1)->buf;
        ??data_len?=?(i2c->op?==?I2C_MASTER_RD)???msgs->len?:
        ??????(msgs?+?1)->len;
        ??read_len?=?(readw(i2c->base?+?OFFSET_FIFO_STAT)?>>?4)?&?0xf;

        ??if?(read_len?==?data_len)?{
        ???while?(data_len--)
        ????*(data_buf++)?=?readw_relaxed(i2c->base?+?OFFSET_DATA_PORT);
        ??}?else?{
        ???dev_dbg(i2c->dev,?"data_len?%x,?read_len?%x,?fifo?read?len?error\n",
        ????data_len,?read_len);
        ???mtk_i2c_init_hw(i2c);
        ???return?-EIO;
        ??}
        ?}

        ?return?0;
        }

        下面這段代碼

        ?if?(i2c->irq_stat?&?(I2C_HS_NACKERR?|?I2C_ACKERR))?{
        ??dev_dbg(i2c->dev,?"addr:?%x,?transfer?ACK?error\n",?msgs->addr);
        ??mtk_i2c_init_hw(i2c);
        ??return?-ENXIO;
        ?}

        宏定義

        errno-base.h


        #define?ENXIO???6?/*?No?such?device?or?address?*/

        表示就是找不到設(shè)備,沒有應(yīng)答

        我用邏輯分析儀抓波形,確實存在沒有應(yīng)答的情況下打印了上面的錯誤日志。


        解決

        問題日志

        <6>[?1594.422871]??(3)[1663:AudioInMic][ES7243]:?es7243_pcm_startup()?line:?444?start.
        <6>[?1594.432778]??(3)[1663:AudioInMic][ES7243]:?es7243_pcm_startup()?line:?444?start.
        <6>[?1594.432902]??(3)[1663:AudioInMic][ES7243]:?es7243_pcm_hw_params()?line:?472?es7243_pcm_hw_params
        <6>[?1594.432918]??(3)[1663:AudioInMic][ES7243]:?es7243_set_bias_level()?line:?568?level:1
        <6>[?1594.433367]??(3)[1663:AudioInMic][ES7243]:?es7243_write()?line:?161?es7243_write?reg:0x00?val:0x09?ok
        <6>[?1594.433741]??(0)[1663:AudioInMic][ES7243]:?es7243_write()?line:?161?es7243_write?reg:0x06?val:0x18?ok
        <6>[?1594.434121]??(2)[1663:AudioInMic][ES7243]:?es7243_write()?line:?161?es7243_write?reg:0x07?val:0x80?ok
        <6>[?1594.434506]??(0)[1663:AudioInMic][ES7243]:?es7243_write()?line:?161?es7243_write?reg:0x01?val:0x0c?ok
        <6>[?1594.434886]??(0)[1663:AudioInMic][ES7243]:?es7243_write()?line:?161?es7243_write?reg:0x02?val:0x10?ok
        <6>[?1594.435288]??(2)[1663:AudioInMic][ES7243]:?es7243_write()?line:?161?es7243_write?reg:0x03?val:0x04?ok
        <6>[?1594.435682]??(3)[1663:AudioInMic][ES7243]:?es7243_write()?line:?161?es7243_write?reg:0x04?val:0x02?ok
        <6>[?1594.436136]??(1)[1663:AudioInMic][ES7243]:?es7243_write()?line:?161?es7243_write?reg:0x05?val:0x1a?ok
        <6>[?1594.436574]??(3)[1663:AudioInMic][ES7243]:?es7243_write()?line:?161?es7243_write?reg:0x09?val:0x3f?ok
        <6>[?1594.437004]??(0)[1663:AudioInMic][ES7243]:?es7243_write()?line:?161?es7243_write?reg:0x06?val:0x00?ok
        <6>[?1594.437424]??(3)[1663:AudioInMic][ES7243]:?es7243_write()?line:?161?es7243_write?reg:0x05?val:0x36?ok
        <3>[?1594.437676]??(3)[1663:AudioInMic]es7243_write?13?error->[REG-0x08,val-0x07]
        <3>[?1594.437907]??(3)[1663:AudioInMic]es7243_read?error1
        <3>[?1594.438220]??(3)[1663:AudioInMic]es7243_write?13?error->[REG-0x01,val-0x8c]
        <6>[?1594.438246]??(3)[1663:AudioInMic][ES7243]:?es7243_update_bits()?line:?175?value:12
        <3>[?1594.438951]??(3)[1663:AudioInMic]es7243_read?error2,?ret?=?-6.
        <6>[?1594.438990]??(3)[1663:AudioInMic][ES7243]:?es7243_pcm_hw_params()?line:?538?es7243_pcm_hw_params538?--?Reg?08?---->?0x0!
        <3>[?1594.439477]??(3)[1663:AudioInMic]es7243_read?error2,?ret?=?-6.
        <6>[?1594.439510]??(3)[1663:AudioInMic][ES7243]:?es7243_pcm_hw_params()?line:?540?es7243_pcm_hw_params540?--?Reg?05?---->?0x0!

        復(fù)現(xiàn)了十幾把,發(fā)現(xiàn)每次都是剛開始I2C可以讀寫,后面再讀寫的時候,就容易出現(xiàn)I2C操作失敗的情況。

        FAE給的答復(fù)是

        • I2C走線是否有其他干擾
        • I2C有沒有加RC濾波電路

        硬件已經(jīng)確定了,想再修改硬件可能性比較小,也比較麻煩,硬件測量了I2C波形,也沒有發(fā)現(xiàn)異常。故此,還是想在軟件上做規(guī)避。

        我猜測可能是芯片操作過快,芯片沒有來得及反應(yīng),而且每次操作開始I2C都是可以讀寫的,所以就想在讀寫函數(shù)中阻塞一會會來規(guī)避這個問題。

        patch


        diff?--git?a/kernel-4.4/sound/soc/codecs/es7243.c?b/kernel-4.4/sound/soc/codecs/es7243.c
        index?272f5dbf88..0e6a1e6bcc?100755
        ---?a/kernel-4.4/sound/soc/codecs/es7243.c
        +++?b/kernel-4.4/sound/soc/codecs/es7243.c
        @@?-32,6?+32,7?@@
        ?#include?
        ?#include?
        ?#include?
        +#include?
        ?#ifdef?CONFIG_OF
        ?#include?
        ?#include?
        @@?-127,6?+128,7?@@?static?int?es7243_read(u8?reg,?u8?*rt_value,?struct?i2c_client?*client)
        ????????read_cmd[0]?=?reg;
        ????????cmd_len?=?1;

        +???????udelay(2000);
        ????????if?(client->adapter?==?NULL)
        ????????????????pr_err("es7243_read?client->adapter==NULL\n");

        @@?-141,6?+143,7?@@?static?int?es7243_read(u8?reg,?u8?*rt_value,?struct?i2c_client?*client)
        ????????????????pr_err("es7243_read?error2,?ret?=?%d.\n",?ret);
        ????????????????return?-1;
        ????????}
        +
        ????????ES7243_DEBUG("es7243_read?OK\n");
        ????????return?0;
        ?}
        @@?-153,12?+156,14?@@?static?int?es7243_write(u8?reg,?unsigned?char?value,?struct?i2c_client?*client)
        ????????write_cmd[0]?=?reg;
        ????????write_cmd[1]?=?value;

        +???????udelay(2000);
        ????????ret?=?i2c_master_send(client,?write_cmd,?2);
        ????????if?(ret?!=?2)?{
        ????????????????pr_err("es7243_write?%x?error->[REG-0x%02x,val-0x%02x]\n",client->addr,reg,value);
        ????????????????return?-1;
        ????????}
        ????????ES7243_DEBUG("es7243_write?reg:0x%.2x?val:0x%.2x?ok?\n",reg,value);
        +
        ????????return?0;
        ?}

        修改后,驗證了十幾把,確實沒有再發(fā)現(xiàn)問題,如果再有問題的話,再分析。




        推薦閱讀:
        專輯|Linux文章匯總
        專輯|程序人生
        專輯|C語言
        我的知識小密圈

        關(guān)注公眾號,后臺回復(fù)「1024」獲取學(xué)習(xí)資料網(wǎng)盤鏈接。

        歡迎轉(zhuǎn)發(fā),在看,評論~



        瀏覽 212
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            在线视频 日本无码 | 囯产精品久久免费蜜桃 | 少妇羞红丰满奶水 | 少妇的大肉蚌一开一合电影 | 久操网在线视频观看 | 一级爱爱免费看 | 天天躁夜夜躁狠狠躁AV | 图片区偷拍区小说区 | a级片少妇 | 日本全黄裸体片 |