本帖最后由 jlwg 于 2014-1-28 11:00 编辑
zhangjin_comeon 发表于 2013-11-30 22:17
应该还可以吧
当初我刚接触CPAL的时候,还是觉得这个很可以的。可是仔细看了代码之后,我现在觉得它是"完全不可以",而不是"应该还可以"。
今天又重新看了一遍stm32的i2c相关.发现网上所有的关于stm32的i2c的硬件bug的描述都不透彻.其实stm32的i2c在勘误表中的第一个硬件bug,他的描述方式是事件相关.其实用另一种描述方式会更透彻,我在这里提供给大家(理解我的这句话的前提是对stm32的i2c的寄存器非常熟悉),核心就是一句话: 猜测由于硬件设计的原因,只要在DSR移动的过程中,DR的数据发生了变化(被读取或被写入),则会影响DSR的数据,造成错误.所以,DR变化时,一定要在DSR停止移动的时刻才可以. 所以在发送的时候,要么在刚产生TxE,DSR还没来得及移位发送时;要么在产生BTF中断,DSR移动完毕的时候,再写入DR.
而在接收的时候,要么在刚产生RxNE,DSR还没来得及移位继续下一个接收时;要么在产生BTF中断,DSR移动完毕的时候,再读出DR.
这就是I2C中断优先级要为最高优先级的原因,而DMA传输时,系统自动设置,不用担心这个问题.
另外,st的勘误手册上提出解决这个bug的方法是使用dma方式或者将i2c相关中断设为最高优先级.也有人说可以用轮询的方式,其实,轮训的方式只适合于发送数据的情况,在接收数据时,因为要提前设置NACK和停止位,所以必须用中断或者DMA方式.
按照st的建议,用dma 方式,没什么可说的,如果用中断的方式,优先级必须设置为最高,这在一些用户的系统设计中,可能是不可接受的.而用dma方式,就是占用了dma通道,相关的其他外围用不了dma方式而已.
回过来再说keil的mdk5的i2c驱动,keil的这个新驱动,还是有好的接口风格,但是他是完全按照数据手册来编写的主模式驱动,没有考虑从模式,没有考虑勘误表中硬件bug的处理.
所以keil的这个i2c驱动的dma方式是可以直接使用的,但是中断方式,需要用户自己设置i2c的两个中断为最高优先级才可以(err中断最高,evt次之)..(在rte_config.h中不选dma ,就是中断方式.) |