我试图让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)
定义dg_configI2C_ADAPTER (1)
peripher_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)
I2C_SLAVE_DEVICE_DMA(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
嗯。谢谢你告诉我。在我看来,这是一个相当糟糕的设计。