<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          解決一個(gè)I2C讀寫問題

          共 12759字,需瀏覽 26分鐘

           ·

          2021-01-29 08:44

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

          排查一個(gè)觸摸屏驅(qū)動(dòng)問題

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

          1、問題

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

          log提示看到是返回 -6

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

          下面流程找一下這個(gè) -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);

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

          所以,就開始去找吧。

          因?yàn)槲矣玫氖荕TK平臺(tái),所以需要去找到MTK平臺(tái)相關(guān)里面初始化的這個(gè)指針

          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)答

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


          解決

          問題日志

          <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可以讀寫,后面再讀寫的時(shí)候,就容易出現(xiàn)I2C操作失敗的情況。

          FAE給的答復(fù)是

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

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

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

          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;
          ?}

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




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

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

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



          瀏覽 212
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美99狠 | 欧美成人A级视频 | 小泬BBBBBB免费看 | 欧美综合久久 | 欧美成人精品欧美一级私黄 |