查看: 5137|回复: 20

[分享] mk1l4 i2c进入I2c_wait出不来

[复制链接]

该用户从未签到

16

主题

90

帖子

0

中级会员

Rank: 3Rank: 3

积分
357
最后登录
2015-12-1
发表于 2015-4-22 13:32:09 | 显示全部楼层 |阅读模式
本帖最后由 cjpx84 于 2015-4-22 13:36 编辑

MKL14的I2C模块做为master,通过I2C总线与电池和充电芯片连接在一起。MKL14和电池都会访问充电芯片,现在碰到一个问题,在MKL14读充电芯片的寄存器值时,出现进入I2C_wait出不来。默认情况下,电池也是作为master会去访问充电芯片,这个问题只有把电池插上的时候,才会出现,但是,在进入读接口之前,我已经通过I2C_S寄存器的busy位判断了总线是否忙的状态了,只要是总线忙,就先等待,不读取数据。在出现这个问题的时候,通过仿真器看到,读取数据的时候,总线应该是空闲的,然后发起了start信号,按照手册描述,此时busy位应该置1,但是,出问题时,发现i2c_s的busy位为0,请问freescale的各位大神,有没有碰到过类似的问题?有没有什么建议可以解决该问题?

while( i2c_bus_busy());------------这里等待I2C总线空闲
  
  /* send start signal */
   i2c_Start();
  /* Send Slave Address */
  i2c_send_slave_addr(slaveID,MWSR);
  /*wait the data transfer complete*/
  i2c_Wait();
i2c_get_ack();
  
  /* Write command code*/
  i2c_write_byte(cmdCode);
  i2c_Wait();---------------------通过仿真器抓到出问题的地方,查看I2C_S寄存器,busy已经被设置成0
  i2c_get_ack();
回复

使用道具 举报

该用户从未签到

16

主题

90

帖子

0

中级会员

Rank: 3Rank: 3

积分
357
最后登录
2015-12-1
 楼主| 发表于 2015-4-22 15:43:01 | 显示全部楼层
#define i2c_Wait()               while((I2C0_S & I2C_S_IICIF_MASK)==0) {} \
                                  I2C0_S |= I2C_S_IICIF_MASK;

感觉多主的情况下,用这种死循环等待的方式很危险,一出问题就挂了。。。。。
回复 支持 反对

使用道具 举报

该用户从未签到

16

主题

90

帖子

0

中级会员

Rank: 3Rank: 3

积分
357
最后登录
2015-12-1
 楼主| 发表于 2015-4-22 16:39:52 | 显示全部楼层
cjpx84 发表于 2015-4-22 15:43
#define i2c_Wait()               while((I2C0_S & I2C_S_IICIF_MASK)==0) {} \
                         ...

这个问题我做了一下分析,猜测可能的原因是:MCU经过总线判忙,发现总线是空闲的,就开始发起start信号,而电池支持的是标准的SMBUS协议,估计没有总线判忙功能(这个是猜测),此时,电池也发起了start信号,那么这时候,就需要总线仲裁了,经过仲裁,MCU退出竞争。但是,驱动还在I2C_WAIT中,因为是退出竞争,所有字节还没有发送完成,也就是IICIF位还没有置1,就导致卡在I2C_WAIT上,另一方面,电池竞争成功,读取数据结束之后,发起了stop信号,被MCU的总线判忙检测到,将busy清0.
但是,我不知道MKL14对仲裁失败有没有状态标志的,或者我应该怎么修改这个问题?
回复 支持 反对

使用道具 举报

该用户从未签到

16

主题

90

帖子

0

中级会员

Rank: 3Rank: 3

积分
357
最后登录
2015-12-1
 楼主| 发表于 2015-4-23 14:48:13 | 显示全部楼层
今天继续看了下这个问题,MKL14状态寄存器有一个ARBL位表示仲裁失败,一般在仲裁失败之后,会将状态寄存器的ICIF位置1,但是我的case中,ARBL位没有被置1,并且BUSY位为0。另一方面,我FLT寄存器的STOPF位被置1了。看了下手册,只有FLT寄存器的STOPIE位置1,并且STOPF位置1之后,状态寄存器的IICIF位才会置1,而我的配置中没有将STOPIE位置1,导致程序卡在i2c_wait出不来。

到这里我还是比较疑惑的,按照我的使用场景,应该是双主机,MKL14和电池都作为I2C的master,代码卡在I2C_WAIT出不来,我的理解是双主出现了仲裁,而 MKL14仲裁失败,退出,正常情况下状态寄存器的ARBL位会置1,导致IICIF位置1,从而i2c_wait退出,但是实际情况并不没有按照这个预期执行。反而出现了FLT的STOPF位被置1,也就是检测到stop信号的产生,那这个stop信号是谁产生的呢?肯定不是MKL14,那只能是电池产生的。既然是电池产生了stop信号,那从侧面证明MKL14和电池竞争的时候,MKL14仲裁失败啦。悲剧的是,仲裁失败的位没有置1.


这个问题还得需要freescale的大神给答复下呀。。。。。。
回复 支持 反对

使用道具 举报

  • TA的每日心情
    开心
    2018-7-2 06:04
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    59

    主题

    2888

    帖子

    10

    金牌会员

    Rank: 6Rank: 6

    积分
    6020
    最后登录
    2020-9-28
    发表于 2015-4-23 14:57:34 | 显示全部楼层
    楼主你好
    官方给出的那个查询方式的sample code的确不怎么好。
    建议你还是根据参考手册里的这个中断流程来写。
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    16

    主题

    90

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    357
    最后登录
    2015-12-1
     楼主| 发表于 2015-4-23 15:56:07 | 显示全部楼层
    本帖最后由 cjpx84 于 2015-4-23 15:58 编辑

    我现在的代码就是参考手册上的中断流程写的。我用的是master,那块代码。
        unsigned short i2c_read_word(unsigned char slaveID,unsigned int cmdCode)
    {
        unsigned char result[2];
        unsigned short retval=0;
        unsigned char dumpbyte;

        clear_iicif();
    start:   
        while( i2c_bus_busy());-------------总线判忙
       
        /* send start signal */
        i2c_Start();
        /* Send Slave Address */
        i2c_send_slave_addr(slaveID,MWSR);
        /*wait the data transfer complete*/
        if(i2c_Wait())
            goto start;
        i2c_get_ack();
       
        /* Write command code*/
        i2c_write_byte(cmdCode);
        if(i2c_Wait())
            goto start;
        i2c_get_ack();
       
        /* Do a repeated start */
        i2c_RepeatedStart();
        /* Send Slave Address */
        i2c_send_slave_addr(slaveID,MRSW);
        if(i2c_Wait())
            goto start;
        i2c_get_ack();
       
        /* Put in Rx Mode */
        i2c_EnterRxMode();
        /* Dummy read */
        dumpbyte = I2C0_D ;
        if(i2c_Wait())
            goto start;
       
        /*2nd to last byte to be read*/
        /*set txack*/
        i2c_give_nack();
        result[0] = I2C0_D;
        if(i2c_Wait())
            goto start;
       
        /*last byte to be read generate stop signal*/
        i2c_Stop();
        /* Read byte */
        resu    return retval;
    }

    int  i2c_Wait()
    {
        int ret=0;
        /**
           * wait one byte transfer completes
           * or loss of arbitration
           * or detection I2C bus stop
         **/
        while((I2C0_S & I2C_S_IICIF_MASK)==0) { }
        /*loss of arbitration*/
        if(I2C0_S & I2C_S_ARBL_MASK){
            /*write 1 to clear the ARBL flag*/
            I2C0_S |= I2C_S_ARBL_MASK;
            ret = 1;
        }
        /*detection I2C bus stop*/
        if(I2C0_FLT & I2C_FLT_STOPF_MASK){
            /*write 1 to clear the STOPF flag*/
            I2C0_FLT |= I2C_FLT_STOPF_MASK;
            ret =1;
        }
        /*write 1 clear the IICIF FLAG*/
        I2C0_S |= I2C_S_IICIF_MASK;
        return ret;


    回复 支持 反对

    使用道具 举报

    该用户从未签到

    16

    主题

    90

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    357
    最后登录
    2015-12-1
     楼主| 发表于 2015-4-23 15:59:28 | 显示全部楼层
    FSL_TICS_Robin 发表于 2015-4-23 14:57
    楼主你好
    官方给出的那个查询方式的sample code的确不怎么好。
    建议你还是根据参考手册里的这个中断流程来 ...

    多主机仲裁失败,状态寄存器的ARBL位没有被置上,会是什么问题呢?


    另外,有没有多主机的参考代码?
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    124

    主题

    3600

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    5781
    最后登录
    1970-1-1
    发表于 2015-4-27 15:27:04 | 显示全部楼层
    cjpx84 发表于 2015-4-23 15:59
    多主机仲裁失败,状态寄存器的ARBL位没有被置上,会是什么问题呢?

    单主机连接时,工作时正常的吗?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2017-1-4 14:54
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    5

    主题

    130

    帖子

    0

    高级会员

    Rank: 4

    积分
    585
    最后登录
    2017-2-11
    发表于 2015-4-27 18:05:17 | 显示全部楼层
    学习了。。
    回复

    使用道具 举报

    该用户从未签到

    16

    主题

    90

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    357
    最后登录
    2015-12-1
     楼主| 发表于 2015-4-28 10:55:41 | 显示全部楼层
    本帖最后由 cjpx84 于 2015-4-28 10:57 编辑
    FSL_TICS_ZP 发表于 2015-4-27 15:27
    单主机连接时,工作时正常的吗?


    正常的。就是多主的时候,会出现问题。并且电池我看了下SMBUS协议,也是支持总线仲裁的。这个问题困扰了好久了,freescale的大神们,有什么招吗?
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-24 08:14 , Processed in 0.100194 second(s), 28 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表