Hello,
As mentioned in the title, I am trying to use 4 pairs of I2C on nRF5340. Each of the four I2C pairs will be connected to a TCA9548A (I2C MUX), but that is not important.
In the test program, each of the four pairs of I2C are threaded, so they should be processed in parallel.
I copy main.c below. I know that .overlay file and prj.conf are also needed, but copying them all would be redundant.
So I attach the entire project with zip.
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/settings/settings.h>
#include "twim.h"
#include "tca9548a.h"
LOG_MODULE_REGISTER(main, LOG_LEVEL_INF);
// Device
#if defined(CONFIG_NRFX_TWIM0)
static const struct device *dev_twim0 = DEVICE_DT_GET(DT_NODELABEL(i2c0));
#endif
#if defined(CONFIG_NRFX_TWIM1)
static const struct device *dev_twim1 = DEVICE_DT_GET(DT_NODELABEL(i2c1));
#endif
#if defined(CONFIG_NRFX_TWIM2)
static const struct device *dev_twim2 = DEVICE_DT_GET(DT_NODELABEL(i2c2));
#endif
#if defined(CONFIG_NRFX_TWIM3)
static const struct device *dev_twim3 = DEVICE_DT_GET(DT_NODELABEL(i2c3));
#endif
static void imu_sensors_init(const struct device *dev)
{
int err;
uint8_t twim_buffer[8] = {0};
// No.1
twim_buffer[0] = CHANNEL0_ENABLED;
err = twim_write_noreg(dev, TCA9548A_ADDR0, twim_buffer, 1);
if (err < 0) {
LOG_ERR("Failed to initialize I2C No.1 on %s.(%d)",dev->name, err);
} else {
LOG_INF("I2C No.1 has been initialized.");
}
// No.2
twim_buffer[0] = CHANNEL1_ENABLED;
err = twim_write_noreg(dev, TCA9548A_ADDR0, twim_buffer, 1);
if (err < 0) {
LOG_ERR("Failed to initialize I2C No.2 on %s.(%d)",dev->name, err);
} else {
LOG_INF("I2C No.2 has been initialized.");
}
// No.3
twim_buffer[0] = CHANNEL2_ENABLED;
err = twim_write_noreg(dev, TCA9548A_ADDR0, twim_buffer, 1);
if (err < 0) {
LOG_ERR("Failed to initialize I2C No.3 on %s.(%d)",dev->name, err);
} else {
LOG_INF("I2C No.3 has been initialized.");
}
// No.4
twim_buffer[0] = CHANNEL3_ENABLED;
err = twim_write_noreg(dev, TCA9548A_ADDR0, twim_buffer, 1);
if (err < 0) {
LOG_ERR("Failed to initialize I2C No.4 on %s.(%d)",dev->name, err);
} else {
LOG_INF("I2C No.4 has been initialized.");
}
// No.5
twim_buffer[0] = CHANNEL4_ENABLED;
err = twim_write_noreg(dev, TCA9548A_ADDR0, twim_buffer, 1);
if (err < 0) {
LOG_ERR("Failed to initialize I2C No.5 on %s.(%d)",dev->name, err);
} else {
LOG_INF("I2C No.5 has been initialized.");
}
// No.6
twim_buffer[0] = CHANNEL5_ENABLED;
err = twim_write_noreg(dev, TCA9548A_ADDR0, twim_buffer, 1);
if (err < 0) {
LOG_ERR("Failed to initialize I2C No.6 on %s.(%d)",dev->name, err);
} else {
LOG_INF("I2C No.6 has been initialized.");
}
// No.7
twim_buffer[0] = CHANNEL6_ENABLED;
err = twim_write_noreg(dev, TCA9548A_ADDR0, twim_buffer, 1);
if (err < 0) {
LOG_ERR("Failed to initialize I2C No.7 on %s.(%d)",dev->name, err);
} else {
LOG_INF("I2C No.7 has been initialized.");
}
// No.8
twim_buffer[0] = CHANNEL7_ENABLED;
err = twim_write_noreg(dev, TCA9548A_ADDR0, twim_buffer, 1);
if (err < 0) {
LOG_ERR("Failed to initialize I2C No.8 on %s.(%d)",dev->name, err);
} else {
LOG_INF("I2C No.8 has been initialized.");
}
}
#if defined(CONFIG_NRFX_TWIM0)
static void sensors_init_twim0_work_thread(void)
{
// Initialize IMU sensor(s)
imu_sensors_init(dev_twim0);
}
K_THREAD_DEFINE(sensors_init_twim0, 1024, sensors_init_twim0_work_thread, NULL, NULL, NULL, K_PRIO_PREEMPT(15), 0, 0);
#endif
#if defined(CONFIG_NRFX_TWIM1)
static void sensors_init_twim1_work_thread(void)
{
// Initialize IMU sensor(s)
imu_sensors_init(dev_twim1);
}
K_THREAD_DEFINE(sensors_init_twim1, 1024, sensors_init_twim1_work_thread, NULL, NULL, NULL, K_PRIO_PREEMPT(15), 0, 0);
#endif
#if defined(CONFIG_NRFX_TWIM2)
static void sensors_init_twim2_work_thread(void)
{
// Initialize IMU sensor(s)
imu_sensors_init(dev_twim2);
}
K_THREAD_DEFINE(sensors_init_twim2, 1024, sensors_init_twim2_work_thread, NULL, NULL, NULL, K_PRIO_PREEMPT(15), 0, 0);
#endif
#if defined(CONFIG_NRFX_TWIM3)
static void sensors_init_twim3_work_thread(void)
{
// Initialize IMU sensor(s)
imu_sensors_init(dev_twim3);
}
K_THREAD_DEFINE(sensors_init_twim3, 1024, sensors_init_twim3_work_thread, NULL, NULL, NULL, K_PRIO_PREEMPT(15), 0, 0);
#endif
int main(void)
{
// Settings
if (IS_ENABLED(CONFIG_SETTINGS)) {
LOG_INF("Settings have been loaded.");
settings_load();
}
// Main loop
while (true) {
k_sleep(K_MSEC(500));
}
}
Since nothing is connected to the nRF7002 (nRF5340) evaluation board, this test program should produce an I2C error. As mentioned earlier, the four sets of I2C are threaded, so they are processed in parallel, so the error should occur in parallel. In fact, three of the four pairs (i2c1 to i2c3) output errors in parallel.
But only i2c0 behaves strangely. I think it is being processed in parallel, but the response time is very long.
My ideal error output would be
Error on i2c0
Error on i2c1
Error on i2c2
Error on i2c3
...
...
Error on i2c0
Error on i2c1
Error on i2c2
Error on i2c3
But here's the actual log
SEGGER J-Link V7.94e - Real time terminal output SEGGER J-Link (unknown) V1.0, SN=1050716044 Process: JLink.exe *** Booting nRF Connect SDK v2.7.0-5cb85570ca43 *** *** Using Zephyr OS v3.6.99-100befc70c74 *** [00:00:08.892,608] <inf> main: Settings have been loaded. [00:00:08.893,371] <err> main: Failed to initialize I2C No.1 on i2c@9000.(-5) [00:00:08.893,554] <err> main: Failed to initialize I2C No.1 on i2c@b000.(-5) [00:00:08.893,615] <err> main: Failed to initialize I2C No.1 on i2c@c000.(-5) [00:00:08.893,829] <err> main: Failed to initialize I2C No.2 on i2c@9000.(-5) [00:00:08.893,951] <err> main: Failed to initialize I2C No.2 on i2c@b000.(-5) [00:00:08.894,012] <err> main: Failed to initialize I2C No.2 on i2c@c000.(-5) [00:00:08.894,226] <err> main: Failed to initialize I2C No.3 on i2c@9000.(-5) [00:00:08.894,348] <err> main: Failed to initialize I2C No.3 on i2c@b000.(-5) [00:00:08.894,409] <err> main: Failed to initialize I2C No.3 on i2c@c000.(-5) [00:00:08.894,622] <err> main: Failed to initialize I2C No.4 on i2c@9000.(-5) [00:00:08.896,728] <err> main: Failed to initialize I2C No.4 on i2c@b000.(-5) [00:00:08.896,850] <err> main: Failed to initialize I2C No.4 on i2c@c000.(-5) [00:00:08.897,064] <err> main: Failed to initialize I2C No.5 on i2c@9000.(-5) [00:00:08.897,247] <err> main: Failed to initialize I2C No.5 on i2c@b000.(-5) [00:00:08.897,369] <err> main: Failed to initialize I2C No.5 on i2c@c000.(-5) [00:00:08.897,460] <err> main: Failed to initialize I2C No.6 on i2c@9000.(-5) [00:00:08.897,644] <err> main: Failed to initialize I2C No.6 on i2c@b000.(-5) [00:00:08.897,766] <err> main: Failed to initialize I2C No.6 on i2c@c000.(-5) [00:00:08.897,827] <err> main: Failed to initialize I2C No.7 on i2c@9000.(-5) [00:00:08.898,071] <err> main: Failed to initialize I2C No.7 on i2c@b000.(-5) [00:00:08.898,712] <err> main: Failed to initialize I2C No.7 on i2c@c000.(-5) [00:00:08.898,803] <err> main: Failed to initialize I2C No.8 on i2c@9000.(-5) [00:00:08.898,986] <err> main: Failed to initialize I2C No.8 on i2c@b000.(-5) [00:00:08.899,047] <err> main: Failed to initialize I2C No.8 on i2c@c000.(-5) [00:00:09.393,432] <err> main: Failed to initialize I2C No.1 on i2c@8000.(-5) [00:00:09.893,829] <err> main: Failed to initialize I2C No.2 on i2c@8000.(-5) [00:00:10.394,226] <err> main: Failed to initialize I2C No.3 on i2c@8000.(-5) [00:00:10.894,622] <err> main: Failed to initialize I2C No.4 on i2c@8000.(-5) [00:00:11.395,019] <err> main: Failed to initialize I2C No.5 on i2c@8000.(-5) [00:00:11.895,416] <err> main: Failed to initialize I2C No.6 on i2c@8000.(-5) [00:00:12.395,812] <err> main: Failed to initialize I2C No.7 on i2c@8000.(-5) [00:00:12.896,209] <err> main: Failed to initialize I2C No.8 on i2c@8000.(-5)
Considering the elapsed time in the log, it appears that only i2c0 is taking 0.5 seconds per error.
Why is this?
I don't think it is conflicting because I have disabled Uart0, but I think there might be something going on.
Or am I missing some setting?