这几天被LM3S的I2C控制器差点搞死了。
问题是由于LWIP的回调函数操作I2C控制器引起的。
在我的程序中,网络收到的命令有的会要求从I2C设备中读取数据,其它任务也可能会操作同一个I2C设备。当I2C操作正在进行时,如果来了一个网络请求也要操作该I2C设备,就有可能会把原来的I2C操作进程打断,插入新的操作,从而导致总线异常。同样道理,操作需要独占的外设的时候也有可能会出现这样的问题。
虽然已经知道I2C控制器是怎么死的了,修改程序也基本能避免这样的问题再出现。
但出现问题后I2C0 Mater control/status寄存器的内容一直为0x00000007(总线忙、仲裁失败),I2C控制器再无法正常工作,所以还是不放心。
尝试过重新初始化I2C控制器,用I2C控制器发起START和STOP和用IO口产生冗余SCL时钟等方法也不能使这些错误标志复位。
MCU的规格书上有说重启后各个标志会复位,但我实在不想因为I2C而重启整个系统。
后来终于芯片的系统控制库里找到了可以单独重启I2C模块的函数SysCtlPeripheralReset( SYSCTL_PERIPH_I2C0 )。
在检测到I2C控制器错误标志后,先发起START和STOP来释放总线,然后重启并重新初始化MCU的I2C模块,再进行读写操作。
这样即使I2C控制器死掉也可以正常操作了。