使用适配器的I2c从机:挂起的事务和SCLK保持低

⚠️
你好。。谢谢你来到论坛。令人兴奋的消息!我们现在正在迁移到新的论坛平台,该平台将提供更好的功能,并包含在主对话网站中。所有员额和帐户都已迁移。我们现在只接受新论坛的流量-请在//www.xmece.com/support. 我们将在未来几天内修复bug/优化搜索和标记。
4个员额/0个新员额
最后一篇文章
拉贾姆斯
离线
最后一次见到:3年5个月前
加入:2017-12-07 11:04
使用适配器的I2c从机:挂起的事务和SCLK保持低

嗨,对话,

我尝试使用DA1468x设备作为I2C从设备,使用I2C适配器(ad_i2c_start_slave)。在大多数情况下,它是有效的,但有时并不有效。

通信协议(或多或少)如下所示:
-等待消息头
ad_i2c_启动_从站(ack、sizeof ack、msgHeader、sizeof msgHeader、回调、OS_事件_永久);
...等待data_sent和data_received回调
-等待有效载荷
ad_i2c_start_slave(ack, sizeof ack, msgPayload, sizeof msgPayload, callback, TIMEOUT);
-处理并准备好结果
ad_i2c_启动_从机(ack、sizeof ack、等待_结果、等待_结果、回调、超时);
-发送结果
ad_i2c_start_slave(ack,sizeof ack,result,sizeof result,回调,超时);

ad_i2c_start_slave()可以生成4个不同的回调,具体取决于是否提供了读和/或写缓冲区。根据我的经验,我无法正确处理读取请求回调,因此我选择始终为ad_i2c_start_slave()提供wbuf和rbuf,以便我只关心发送的数据和接收的数据回调。
因此,在每个阶段(如上所述),i2c主机都会发送数据并读取数据(比如确认)。因此,基本上我在等待数据发送和数据接收事件被触发,以便进入协议的下一阶段(见上文)。

但有时i2c总线挂起(SCLK保持低位)。我猜这是因为数据被请求(或发送到)而不是由软件处理。这怎么会发生?我认为在每个阶段之间切换缓冲区时可能会发生这种情况。但是,不应该使用旧的缓冲区吗?或者这些缓冲区只使用一次?

我猜,另一个可能发生的问题是,有挂起的事务,我不知道在超时的情况下如何取消。看到我的其他帖子在这里:https://support.dialog-semiconductor.com/forums/post/dialog-smartbond-bl..。

所以我的问题是如何使用ad_i2c_start_slave()与超时的方式在协议中提到的上面和或你有任何建议,我可以实现这一点。

另外,我之前在读取请求回调时遇到的问题是,从缓冲区读取数据并没有真正阻止中断(RX_FULL)被持续触发。也许,如果你对如何结合协议来实现这一点提出建议,我会非常欢迎你的建议。

设备:
MT_对话框
离线
最后一次见到:7个月3天前
工作人员
加入:2015-06-08 11:34
嗨rajames,

嗨rajames,

不幸的是,没有使用68x作为从设备的示例演示。关于I2C和驱动程序如何操作的一些事情。当68x处于i2c从模式时,如果有一个读或写取决于从主服务器发送的命令,随从服务器地址一起读或写,而不是从可用的缓冲区。根据来自主机的命令,设备将公开适当的缓冲区读或写。关于时钟线保持低由奴隶,这可能发生当奴隶没有数据在它的FIFO和有一个读请求从主人,在这种情况下,线将保持低,直到读数据提供给奴隶I2C控制器。关于你提供的功能ad_i2c_start_slave(),我看到最后一个参数你都提供了某种超时,没有将设置一个超时参数,你所要做的就是实现自己的超时,然后调用ad_i2c_stop_slave()为了中止的交互,如果没有,设备将等待直到交互完成。在与主人互动时,你也要注意
应该首先在你的事务中设置缓冲区,以便从主服务器读取数据,然后开始一个新的事务,以便写入,而不是在你实现上述代码的同时。

谢谢你的对话

拉贾姆斯
离线
最后一次见到:3年5个月前
加入:2017-12-07 11:04
嗨,对话,

嗨,对话,

让我澄清一下,ad_i2c_start_slave确实没有TIMEOUT参数,我将在下面解释我的意思。

//准备ack缓冲区以进行响应

//消息头
ad_i2c_启动_从机(ack、sizeof ack、msgHeader、sizeof msgHeader、回调);
...等待data_sent和data_received回调
操作系统事件组等待(事件,(数据接收-数据发送),操作系统事件组永久);

//有效载荷
ad_i2c_start_slave(ack, sizeof ack, msgPayload, sizeof msgPayload, callback);
...等待data_sent和data_received回调
操作系统事件组等待(事件,(数据接收-数据发送),超时);

//等待结果
Ad_i2c_start_slave (ack, sizeof ack, waiting_for_result, sizeof waiting_for_result, callback);
...等待data_sent和data_received回调
操作系统事件组等待(事件,(数据接收-数据发送),超时);

//处理并准备结果缓冲区(可能需要一些时间)

//发送结果
ad_i2c_start_从机(ack、sizeof ack、result、sizeof result、回调);
...等待data_sent和data_received回调
操作系统事件组等待(事件,(数据接收-数据发送),超时);

其次,所有wbuf用于ad_i2c_start_从机在调用ad_i2c_start_从机之前准备好。

我希望是这样wbufrbuf调用ad_i2c_start_slave将能够异步处理写入和读取。

否则我如何能够与主设备同步(如果只是查看DATA_RECEIVED和DATA_SENT事件)?

示例场景。
1.如果奴隶期待一个但是师父做了一个相反

  • 只有rbuf提供。
  • DATA_SENT事件
  • 而是触发了数据准备就绪事件

2.如果slave正在等待一个但是师父做了一个相反

  • 只有wbuf提供。
  • 从服务器等待DATA_RECEIVED事件
  • 而是触发READ_REQUEST事件

我是否应该处理所有4个事件数据接收、数据准备、数据发送、读取请求事件??我宁愿不这样做,因为这确实使状态机看到这一点变得复杂
我可能正在等待可能不会发生的事件,并且可能必须处理回调(isr上下文)中的一些逻辑。如果我记得的话,在isr上下文中调用ad_i2c例程可能不是一个好主意。

劳尔

MT_对话框
离线
最后一次见到:7个月3天前
工作人员
加入:2015-06-08 11:34
嗨rajames,

嗨rajames,

关于这个事实,你看到设备保持SCK线低,这是为了向主设备声明一个忙碌的状态,这个保持线低是当设备从主设备接受一个读请求,,发生时(当READ_REQ已经发生)西南会检查是否有有效的回调函数和缓冲区,如果有,它将开始装hw缓冲为了I2C hw发送数据,因此,尽管这个过程执行时钟像低。

我认为您可以提供写缓冲区和读缓冲区,以便执行标准的读命令(因为i2c先执行写,然后执行读)。同样如前所述,如果在主机发送读或写请求(读请求和数据准备)时没有可用的缓冲区,您可以管理设备将从这些回调中执行的操作。您应该处理什么事件以及如何处理这些事件取决于您的实现,如果您希望系统能够处理主设备和从设备可以访问总线的不同步情况,那么您应该处理所有事件。

谢谢你的对话