天天看點

STM32 I2C 總線占用問題解析

這幾天解決 STM32 MCU的I2C 總線占用(BUSY) 問題,覺得是不錯的Lesson Learn,分享給大家。

問題描述

  1. STM32F207 MCU有三組I2C,在Pre-ES1使用I2C1接上DSP/Codec/EEPROM,運作良好
  2. 新硬體(ES1)把Codec/EEPROM移到I2C3,DSP還是留在I2C1,發現在I2C3有機率性的BUSY,MCU無法開始傳資料
  3. 查MCU datasheet,BUSY意思為register I2C3_SR2[bit1]=1,代表SCL/SDA曾經 low而且沒出現stop condition
    STM32 I2C 總線占用問題解析
    STM32 I2C 總線占用問題解析
    STM32 I2C 總線占用問題解析
  4. I2C3 BUSY和timing有關,在程式加個delay就莫名PASS,再加delay又莫名BUSY,有些image是機率性發生BUSY

分析方向

  1. 觀察I2C3 SCL/SDA波形
  2. I2C3在Pre-ES1沒用過,初始化是否有問題?
  3. 觀察BUSY時機,何時開始,何時結束
  4. 和chip有關?将 Codec和Flash斷開
  5. 和I2C bus有關?将Codec接到 I2C1測試
  6. 為何Pre-ES1沒問題?

分析過程

  1. 剛開始不太穩定,莫名的連續一直BUSY,有時一直PASS,而且LED時亮時暗

    > 量電壓發現VDD3.3V不穩,high > low > high > low 震蕩

    > 加大LDO之後VDD3.3V穩定了(Solution1),但I2C3還是BUSY 

  2. 東改西改,發現一版100% PASS的軟體,和另一版100% FAIL的軟體,隻差在delay,應該還有其他問題
  3. 量波形,I2C1(DSP)很正常,I2C1 init之後一直FREE,隻有傳資料期間才BUSY
    STM32 I2C 總線占用問題解析
  4. 100% BUSY的軟體,在I2C3 初始化之後SCL/SDA停在2.6V,當VDD3.3V ON 後才升到3.3V
    STM32 I2C 總線占用問題解析
  5. 100% PASS的軟體,波形同上,但之後開LED時因為LDO供電不足,SCL/SDA被短暫下拉,馬上回到3.3V
    STM32 I2C 總線占用問題解析

    應是因為SCL/SDA短暫下拉,誤打誤撞造成SCL/SDA high > low > high離開BUSY,有兩個證據

    證據一,如果沒下拉,I2C3就一直BUSY:

      a. 斷開小闆(上面有LED) 以降低VDD3.3V電流,不會短暫下拉 > 100% PASS的軟體變成100% FAIL

      b. 斷開小版LED以降低VDD3.3V電流,不會短暫下拉 > 100% PASS的軟體變成100% FAIL

      c. 軟體關閉LED以降低VDD3.3V電流,不會短暫下拉 > 100% PASS的軟體變成100% FAIL

    證據二,如果有下拉,I2C3從BUSY恢複成FREE:

      a. BUSY時設SCL/SDA為GPIO out,拉low > high > low > high,重新初始化SCL/SDA (workaround)  > 離開BUSY并可傳I2C指令

      b. BUSY時手動把SCL拉電線接地  離開BUSY并可傳I2C指令

      c. 100% BUSY軟體就是因為沒下拉波形才會100% FAIL

    PS: 開LED造成電流超出LDO負荷也是問題,須加大LED電阻或更換LDO

  6. SCL/SDA短暫下拉不是造成BUSY的原因,重點在SCL/SDA有0.8s處于2.6V不正常電壓,原因可能有:

    - flash/codec去拉SCL/SDA

    - MCU去拉SCL/SDA

    - SCL/SDA上拉電阻不正确

    - SCL/SDA的上拉電路接在stby3.3v,可能stby3.3v不穩

    STM32 I2C 總線占用問題解析
  7. 斷開flash還是BUSY,而且SCL/SDA還是有0.8秒被下拉到2.6v

    > 和flash無關

  8. 斷開codec後,SCL/SDA不會下拉到2.6v,但I2C3還是BUSY

    > 懷疑Codec供電不正确,檢查I2C3初始化當下的VDD3.3v (供給Codec電壓),發現VDD3.3V本應處于無電狀态(0V),但實際量得2.7V,對codec是不正常電壓,可能造成工作異常

    > MCU将VDD3.3V提早開電(得到3.3V),確定I2c3初始化時Codec正常工作,SCL/SDA下拉電壓消失 (Solution2)

    > I2C3還是BUSY,其實還需要下個Solution

    STM32 I2C 總線占用問題解析
  9. 比較I2C1和I2C3初始化,發現重要差異:

       I2C1 pins(PB7, PB6)都在GPIO group B,共用一組GPIO register,填一次register可初始化兩根pin

       I2C3 pins(PA8, PC9)分在GPIO group A和C,必須分兩次初始化,先SDA再SDL

       > 懷疑初始化順序錯誤,I2C3先初始化SCL再SDA,終于PASS!(Solution3)

    STM32 I2C 總線占用問題解析

其他實驗

  1. 基本電路檢查: SCL/SDA pull high電阻都是4.7KR,Stby3.3v是穩定3.3V,SCL/SDA沒接反,Codec的25Mhz clock穩定
  2. 将Codec從I2C3移到I2C1,可正常傳輸 > 被誤導以為和Codec無關

結論

  1. 三個Solution

    a. 加大LDO讓VDD3.3V穩定供電

    b. I2C3先初始化SCL再SDA。雖然datasheet沒寫此限制,但sample code确實依照此順序執行初始化。

    c. 為確定Codec在I2C3 初始化時有正常電壓(VDD3.3v=3.3v),将VDD3.3V移到I2C3初始化之前

  2. 一個workaround

    - 為確定BUSY時可恢複,當BUSY時将SCL/SDA設為GPIO out,然後pull low > high > low > high,再重新初始化I2C3

  3. Pre-ES1沒問題是因為

    a. Pre-ES1 LDO較強力,無供電問題

    b. Pre-ES1的VDD3.3v無法由MCU開關,而是由stby3.3v穩定供電,是以無SCL/SDA 2.7V問題

    c. Pre-ES1隻用I2C1,沒用I2C3。I2C1兩根pin在同一個GPIO group,無SCL/SDA初始化順序問題

以後I2C問題可檢查

  1. 電路:pull high電阻,pull high電壓,slave device供電
  2. 軟體:I2C SCL/SDA初始化,slave device初始化timing
  3. SCL/SDA檢查:SCL是否穩定,SCL/SDA電壓,slave device有回ACK? 傳輸資料是否正确
  4. 斷開I2C3 chip做測試
  5. 量測slave device期望的timing和MCU送出得是否一樣

繼續閱讀