先说结论,用I2C配crosslink估计是不行的,如果你们搜到这篇文章,那就不要想了,抓紧换SPI。
有项目在树莓派平台上需要用I2C把lattice 的crosslink的配置文件发送出去,但是看手册的意思又比较变态,I2C直接发,中间应该是不能有停顿,即不能重启一个I2C消息。
用python尝试了几个方法,思路就是把文件读到一个数组里面,然后再分段把这个数组传输出去。
from periphery import I2C
low_bit_list=[]
try:
with open("RAWtoCSI2.bit","rb") as fh:
#ba = bytearray(fh.read())
low_bit_list = [byte for byte in bytearray(fh.read(-1))]
datalen=len(low_bit_list)
except IOError:
print("error open file")
low_bit_list.append(255)
#msgwrite=I2C.Message(low_bit_list,read=False)
msgs=[]
index=0
bufflen=4096
while True:
if(index+bufflen<datalen):
sendlen=index+bufflen
else:
sendlen=-1
sendbuff=low_bit_list[index:sendlen]
msgwrite=I2C.Message(sendbuff,read=False)
msgs.append(msgwrite)
print(sendbuff)
if(sendlen==-1):
break
index=index+bufflen
i2c.transfer(devAddr,msgs)
均以失败告终,后来查了一下底层代码,有如下几个问题,如果有不同见解的可以讨论。
- I2C的内核驱动中有明确的数据长度不能超过8192的限制,超过了会报 argument invalid 错误。也就是说I2C.transfer函数的message长度不能超过8192
- I2C的内核驱动又说了,一个message不能超过8192,但是你可以一次性发多个message,最多不能超过42个message。
我尝试了一下思路2,如上的代码就是思路2的,读数据后
msgwrite=I2C.Message(sendbuff,read=false)
msgs.append(msgwrite),
最后所有数据读完了,再一次性
i2c.transfer(devAddr,msgs)
我测试下来是21个msg包,但是改报i2c_transfer: timed out 错。
到此我感觉这个思路应该是不行的,linux驱动里面可能就没打算让你一次性传这么多东西,于是改用SPI接口。还好这个芯片也可以用SPI配置。
如果有人搜到crosslink 配置,希望这篇文章能让你少走点弯路,不要用i2c,用spi会好一点。