I2C adopter blocks forever

Hi there.. thanks for coming to the forums. Exciting news! we’re now in the process of moving to our new forum platform that will offer better functionality and is contained within the main Dialog website. All posts and accounts have been migrated. We’re now accepting traffic on the new forum only - please POST any new threads at//www.wsdof.com/support. We’ll be fixing bugs / optimising the searching and tagging over the coming days.
7 posts / 0 new
Last post
UnicycleBloke
Offline
Last seen:1 week 2 days ago
加入:2015-10-26 13:43
I2C adopter blocks forever

I am trying to get the I2C adapter working, but for some reason it is blocking forever when I call ad_i2c_write_read().

For context, I am using the adapter in following way:
- 有一个任务具有处理I2C事务的唯一功能。
- The task has a FreeRTOS queue of pending transactions.
- The task fetches the next transaction from the queue (blocks if empty), and then performs
the transaction synchronously.
- When the transaction is complete, the task sends a signal to the transaction's originating task.
- 没有其他任务使用I2C外设。

This design is pretty simple, and means that all the other threads can use I2C without ever
blocking. This matches the way I've implemented I2C drivers on other processors, and it works
很好。

The task looks like this (it's part of a C++ class):

void I2CMasterDriver::task_func_impl()
{
// Initialise the I2C device.
ad_i2c_init();

//可能有休息或暂停条件。
而(真实)
{
//如果队列中没有任何内容,则将阻止。
m_queue.receive(m_trans);

// The caller may pass in a pointer to a data buffer (for larger blocks).
// If null, we point this to our own buffer. Note: do this at this point
// because the structure is copied by value, and any other pointer is likely
// to be invalid.
if (m_trans.data == nullptr)
{
m_trans.data = &m_trans.buffer[0];
}

// Open the I2C slave device we want to talk to. This is the oddest achitecture
// I've yet seen for managing slaves.
i2c_device device = ad_i2c_open(NFC_CHIP);

// This is a blocking call.
int ret_code = ad_i2c_write_read(
device,
(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);

// We are going to return by value - via the scheduler - so restore the data pointer to
// indicate that we used own buffer or external buffer.
if (m_trans.data == &m_trans.buffer[0])
{
m_trans.data = nullptr;
}

// Let the clients know that we're all done.
m_on_complete.emit(m_trans);

// Close the device in preparation for the next transaction.
ad_i2c_close(device);
}
}

The following lines are included in my configuration:

#define dg_configUSE_HW_I2C ( 1 )
#define dg_configI2C_ADAPTER ( 1 )

The following lines are included in periph_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);

The following lines are included in 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()块的调用,而不是返回。如果我发表评论
排队,以便排队的事务刚刚被抛弃,任务完全按预期工作。
What other settings, macros or options might I have missed? Since only one task used the I2C, perhaps I should used the low-level driver instead...

事情的方式,我想我早期er just write my own bare metal driver for this. Are there any example of this available?

谢谢。

Device:
UnicycleBloke
Offline
Last seen:1 week 2 days ago
加入:2015-10-26 13:43
It seems that I need to

It seems that I need to acquire the bus before starting the transaction - this is what initialises the peripheral itself and enables the interrupts. So it doesn't block now. However....

Nothing is coming out on the wire. There is no device attached, but I should at least see the address.

谢谢。

UnicycleBloke
Offline
Last seen:1 week 2 days ago
加入:2015-10-26 13:43
Ah! Answered my own question.

Ah! Answered my own question. It helps a lot if you make the pins output open drain and stick a device on the bus to pull up the lines.

谢谢。

PM_Dialog
Offline
Last seen:18 hours 14 min ago
Staff
加入:2018-02-08 11:03
Hi UnicycleBloke,

Hi UnicycleBloke,

I would strongly recommend you to have a look at theI2C适配器概念(HTML)从DA14680的支持页面。本教程解释了I2C适配器以及如何将DA1468x配置为I2C主设备。适配器未实现为单独的任务,并且应视为应用程序和LLD之间的附加层。建议使用适配器来访问硬件块。

Thanks, PM_Dialog

UnicycleBloke
Offline
Last seen:1 week 2 days ago
加入:2015-10-26 13:43
Thank you, but I've already

谢谢,但我已经完成了所有这些。我理解I2C适配器概念。不幸的是,我认为设计是理想的。这就是为什么我创建了一个线程到序列式调用的线程,而不停止应用程序中的任何其他线程。它现在运作得很好,并且更适合我的活动驱动应用程序框架。

I do have a follow up question: if I were to use two I2C peripherals, it seems like the adapter would prevent concurrent transactions on them. Is that true?

谢谢。

PM_Dialog
Offline
Last seen:18 hours 14 min ago
Staff
加入:2018-02-08 11:03
Hi UnicycleBloke,

Hi UnicycleBloke,

Yes, that’s true! The adapters will prevent concurrent transactions on them.

Thanks, PM_Dialog

UnicycleBloke
Offline
Last seen:1 week 2 days ago
加入:2015-10-26 13:43
Hmm. Thanks for letting me

Hmm. Thanks for letting me know. That seems like quite a poor design to me.