我试图让I2C适配器工作,但由于某种原因,当我调用ad_I2C_write_read()时,它将永远阻塞。
对于上下文,我以以下方式使用适配器:
—有一个任务,它的唯一功能是处理I2C事务。
-该任务有一个FreeRTOS挂起事务队列。
-该任务从队列中获取下一个事务(如果为空则阻塞),然后执行
事务将同步进行。
-事务完成后,任务向事务的原始任务发送信号。
—没有其他任务使用I2C外设。
这种设计非常简单,这意味着所有其他线程都可以使用I2C,而无需任何修改
这与我在其他处理器上实现I2C驱动程序的方式相匹配,而且很有效
很好。
任务看起来像这样(它是C++类的一部分):
void I2CMasterDriver::task_func_impl()
{
//初始化I2C设备。
ad_i2c_init ();
//可能有中断或暂停条件。
而(真)
{
//如果队列中没有任何东西,则会阻塞。
m_queue.receive(m_trans);
//调用者可以传入指向数据缓冲区的指针(对于较大的块)。
//如果为null,则将其指向我们自己的缓冲区。注意:此时请执行此操作
//因为结构是按值复制的,任何其他指针都是可能的
//无效。
如果(m_trans.data==nullptr)
{
m_trans.data=&m_trans.buffer[0];
}
//打开我们想与之对话的I2C从设备。这是最奇怪的一种结构
//我还没见过如何管理奴隶。
i2c_设备=ad_i2c_开放(NFC_芯片);
//这是一个阻塞呼叫。
int ret_code=ad_i2c_写入_读取(
装置,
(m_trans。Tx_length > 0) ?&m_trans。数据[0]:nullptr,
m_trans.tx_长度,
(m_trans.rx_length>0)?&m_trans.data[m_trans.tx_length]:nullptr,
m_trans.rx_length,
HW_I2C_F_添加_停止);
//我们将通过调度程序按值返回,因此将数据指针恢复到
//表明我们使用了自己的缓冲区或外部缓冲区。
if(m_trans.data==&m_trans.buffer[0])
{
m_trans.data=nullptr;
}
//让客户知道我们都完成了。
m_on_complete.emit(m_trans);
//关闭设备以准备下一个事务。
ad_i2c_闭合(装置);
}
}
我的配置中包括以下行:
#定义dg_配置使用_硬件_I2C(1)
#定义dg_配置I2C_适配器(1)
periph_init中包含以下行:
硬件gpio配置引脚(硬件gpio端口0,硬件gpio引脚0,硬件gpio模式输出,硬件gpio功能I2C\U SCL,true);
硬件gpio配置引脚(硬件gpio端口0,硬件gpio引脚1,硬件gpio模式输出,硬件gpio功能I2C\U SDA,true);
平台设备h中包括以下线路:
I2C_总线(I2C1)
I2C_从设备_DMA(I2C1,nfc_芯片,0x28,硬件I2C_寻址_7B,硬件I2C_速度_标准,0)
I2C_总线_端
这个问题是对ad_i2c_write_read()的调用阻塞并且永不返回。如果我添加注释
行,以便将排队的事务直接丢弃,任务完全按照预期工作。
我可能错过了哪些其他设置、宏或选项?因为只有一个任务使用了I2C,也许我应该使用低级驱动程序来代替。。。
就目前的情况而言,我想我更愿意为此编写自己的裸机驱动程序。有这方面的例子吗?
谢谢。
似乎我需要在启动事务之前获取总线-这就是初始化外围设备本身并启用中断的原因。因此,它现在不会阻塞。但是。。。。
电线上没有任何东西。没有连接设备,但我至少应该看到地址。
谢谢。
啊!回答了我自己的问题。如果你让引脚输出开漏,并在总线上粘贴一个设备来拉起线路,这会有很大帮助。
谢谢。
嗨,独轮车,
我强烈建议你去看看I2C适配器概念(HTML)从DA14680的支持页面。本教程解释I2C适配器以及如何将DA1468x配置为I2C主设备。适配器不是作为单独的任务实现的,应该将其视为应用程序和lld之间的附加层。建议使用适配器访问硬件块。
谢谢,下午好
谢谢,但我已经做完了。我理解I2C适配器的概念。不幸的是,我认为这个设计并不理想。这就是为什么我创建了一个线程来序列化对ad_i2c_write_read()的调用,而不会停止应用程序中的任何其他线程。它现在工作得非常好,更适合我的事件驱动应用程序框架。
我确实有一个后续问题:如果我使用两个I2C外围设备,适配器似乎会阻止它们上的并发事务。这是真的吗?
谢谢。
嗨,独轮车,
是的,没错!适配器将阻止在其上进行并发事务。
谢谢,下午好
谢谢你让我知道。对我来说,这似乎是一个相当糟糕的设计。