我试图让I2C适配器工作,但由于某些原因,它永远阻塞当我调用ad_i2c_write_read()。
对于上下文,我正在以以下方式使用适配器:
- 有一个任务具有处理I2C事务的唯一功能。
—该任务有一个FreeRTOS队列,其中包含等待处理的事务。
—任务从队列中获取下一个事务(如果为空则阻塞),然后执行
事务同步。
—当事务完成时,任务向事务的发起任务发送一个信号。
- 没有其他任务使用I2C外设。
这种设计非常简单,这意味着所有其他线程都可以使用I2C
阻塞。这与我在其他处理器上实现I2C驱动程序的方式相匹配,并且可以工作
很好。
任务看起来是这样的(它是一个c++类的一部分):
空白I2CMasterDriver: task_func_impl ()
{
//初始化I2C设备。
ad_i2c_init();
//可能有休息或暂停条件。
而(真实)
{
//如果队列中没有任何内容,则将阻止。
m_queue.receive (m_trans);
//调用者可以传入一个指向数据缓冲区的指针(对于更大的块)。
//如果为null,则指向我们自己的缓冲区。注意:在这一点上这样做
//因为结构体是按值复制的,任何其他指针都可能
//无效。
如果(m_trans。数据= = nullptr)
{
m_trans。data = &m_trans.buffer [0];
}
//打开我们想要通话的I2C从设备。这是最奇怪的建筑
//我已经看到了管理奴隶。
i2c_device device = ad_i2c_open(NFC_CHIP);
这是一个阻塞调用。
Int ret_code = ad_i2c_write_read()
设备,
(m_trans.tx_length> 0)?&m_trans.data [0]:nullptr,
m_trans.tx_length,
(m_trans。Rx_length > 0) ?&m_trans.data [m_trans。tx_length]: nullptr,
m_trans.rx_length,
HW_I2C_F_ADD_STOP);
//我们将返回值-通过调度程序-所以恢复数据指针到
//表示我们使用了自己的缓冲区或外部缓冲区。
如果(m_trans。数据= = &m_trans.buffer [0])
{
m_trans。数据= nullptr;
}
//让客户知道我们已经完成了。
m_on_complete.emit (m_trans);
//关闭设备以准备下一个事务。
ad_i2c_close(设备);
}
}
以下几行包含在我的配置中:
#define dg_configUSE_HW_I2C (1)
#define dg_configI2C_ADAPTER (1)
以下行包含在外围的init中:
hw_gpio_configure_pin(HW_GPIO_PORT_0, HW_GPIO_PIN_0, HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_I2C_SCL, true);
hw_gpio_configure_pin(HW_GPIO_PORT_0, HW_GPIO_PIN_1, HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_I2C_SDA, true);
platform_devices.h包含以下几行:
I2C_BUS (I2C1)
I2C1, nfc_chip, 0x28, HW_I2C_ADDRESSING_7B, HW_I2C_SPEED_STANDARD, 0)
I2C_BUS_END
此问题是对AD_I2C_WRITE_READ()块的调用,而不是返回。如果我发表评论
排队,以便排队的事务刚刚被抛弃,任务完全按预期工作。
我可能错过了其他哪些设置、宏或选项?因为只有一个任务使用I2C,也许我应该使用低级的驱动程序代替…
按照目前的情况,我想我宁愿为此编写自己的裸金属驱动程序。有这样的例子吗?
谢谢。
似乎我需要在启动事务之前获得总线——这是初始化外围设备本身并启用中断的原因。所以它现在不会阻塞。然而……
电线上什么都没有。没有附加设备,但我至少应该看到地址。
谢谢。
啊!回答了我自己的问题。它帮助很多,如果你使引脚输出开路排水沟和粘在总线上的设备拉上来的线。
谢谢。
嗨UnicycleBloke,
我强烈建议您看一看I2C适配器概念(HTML)从DA14680的支持页面。本教程解释了I2C适配器以及如何将DA1468x配置为I2C主设备。适配器未实现为单独的任务,并且应视为应用程序和LLD之间的附加层。建议使用适配器来访问硬件块。
谢谢,PM_Dialog
谢谢,但我已经完成了所有这些。我理解I2C适配器概念。不幸的是,我认为设计是理想的。这就是为什么我创建了一个线程到序列式调用的线程,而不停止应用程序中的任何其他线程。它现在运作得很好,并且更适合我的活动驱动应用程序框架。
我还有一个问题:如果我要使用两个I2C外设,适配器似乎会阻止它们上的并发事务。这是真的吗?
谢谢。
嗨UnicycleBloke,
是的,这是真的!适配器将阻止它们上的并发事务。
谢谢,PM_Dialog
嗯。谢谢你告诉我。我觉得这是个很糟糕的设计。