I2c Not working after waking from sleep

⚠️
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. 我们将在未来几天内修复bug/优化搜索和标记。
13 posts / 0 new
最后一篇文章
Richard Legault
Offline
最后一次见到:3 years 7 months ago
已加入:2017-03-01 18:54
I2c Not working after waking from sleep

我有一个工作的I2C,它有一个加速计连接到开发板。
Communication works after initialization.
After the unit goes to Extended_Sleep and wakes the I2C is no longer working. There is currently only the one device on the I2C. The Power is not disabled.
The task gets stuck at ad_i2c.c:284 OS_EVENT_WAIT(dev_config->bus_data->event, OS_EVENT_FOREVER);

The interrupt fires one time but I cannot clear it because I need to read an address to clear the pin from the accelerometer side. So the accelermeter appears to be still working.

I have one time init of I2C_BUS_INIT(I2C1) and I2C_DEVICE_INIT(ACCEL_KXCJB).
平台设备.h包含

I2C炱总线(I2C1)

I2C从机设备(I2C1,ACCEL\u KxJB,0x0E,
HW_I2C_ADDRESSING_7B, HW_I2C_SPEED_FAST);

I2C总线端

periph_init() contains (using the HW_GPIO_PINCONFIG macro so the names get extended properly)

hw\u gpio配置\u引脚(hw_UGPIO U端口U 3,hw_gpio U pin 0,INPUT,I2C_USDA,false)//IC21数据
hw_gpio_configure_pin(HW_GPIO_PORT_4, HW_GPIO_PIN_7, OUTPUT, I2C_SCL, false); // I2C1 CLK
hw_gpio_configure_pin(HW_GPIO_PORT_4, HW_GPIO_PIN_3, INPUT, GPIO, false); // accel irq

After the wake up the examples say to reinit the lines. Is there anything else that needs to be done in periph_init() that I am missing for I2C communication to work after extended sleep.

谢谢你的帮助。

Device:
Richard Legault
Offline
最后一次见到:3 years 7 months ago
已加入:2017-03-01 18:54
我已经探测过SCL线了

我已经探测过SCL线了and there is no activity on the line after the extended sleep.

MT\u对话框
Offline
最后一次见到:2 months 2 weeks ago
工作人员
已加入:2015-06-08 11:34
嗨理查德·勒高,

嗨理查德·勒高,

I dont see anything missing from the configuration that you mention, how do you trigger the reading of the sensor memory etc from the system ? The part of the code that the device stalls is because it waits for an the complete event from the I2C module and apparently nothing occurs.

Also please have a look at the post below, perhaps this will help:

https://support.dialog-semiconductor.com/forums/post/dialog-smartbond-bl...

谢谢你的对话

Richard Legault
Offline
最后一次见到:3 years 7 months ago
已加入:2017-03-01 18:54
When it comes out of sleep

When it comes out of sleep the I2C status is 0 (disabled).
To get the I2C functional again it was not enough to do hw_i2c_enable(HW_I2C1) I had to also init the bus and set the target address.
Thus the code for the I2C periph_init is now:

=================
hw\u gpio配置\u引脚(hw_UGPIO U端口U 3,hw_gpio U pin 0,INPUT,I2C_USDA,false)//IC21数据
hw_gpio_configure_pin(HW_GPIO_PORT_4, HW_GPIO_PIN_7, OUTPUT, I2C_SCL, false); // I2C1 CLK
hw_gpio_configure_pin(HW_GPIO_PORT_4, HW_GPIO_PIN_3, INPUT, GPIO, false); // accel irq

static const i2c_config cfg = {
.speed=HW_UI2C炣U speed炣炣,
.mode = HW_I2C_MODE_MASTER,
.addr_mode = HW_I2C_ADDRESSING_7B,
};

hw_i2c_init(HW_I2C1, &cfg);
hw\u i2c\u设置目标\u地址(hw I2C1,0x0E);/*显示当总线上只有一个I2C设备时适配器未设置地址*/
hw_i2c_enable(HW_I2C1);
====================

它没有在示例或文档mention that these init steps needs to be done when coming out of sleep. I only discovered this from the link in the previous response.

The question is: is this initialization needed for proper behaviour after a deep sleep or is this a bug in the i2c adapter or hw_i2c code. Does the adapter update the device address even for busses with only one device.

为什么我要当广告设置TargetAddressapter is suppose to do this for me? If I don't set the address in init, then I get a value of 0x07 for all register reads from the device. Is this an artifact of only having one device on the bus.

MT\u对话框
Offline
最后一次见到:2 months 2 weeks ago
工作人员
已加入:2015-06-08 11:34
嗨理查德·勒高,

嗨理查德·勒高,

正如前面文章中提到的直接答案所述,这些初始化是不必要的,因为您使用适配器以与传感器交互,适配器将重新启用和配置I2C总线,因此您只需将PIN的配置置于外围设备设置()函数中。因此,如果您使用适配器,您只需要打开与在平台_Udevices.h中声明的具有ad_I2C_uOpen()的I2C设备的连接,然后使用ad_I2CTransact()或ad_I2C_UWrite()、ad I2C_Uread()等打开事务。那么如何触发事务?

谢谢你的对话

Richard Legault
Offline
最后一次见到:3 years 7 months ago
已加入:2017-03-01 18:54
是的,这是预期的

是的,这是预期的behaviour but the observed behaviour is that I do need to do those 3 steps otherwise I2C does not respond when waking from extended sleep.

MT\u对话框
Offline
最后一次见到:2 months 2 weeks ago
工作人员
已加入:2015-06-08 11:34
Hi Richard

Hi Richard

Its the expected and how the system behaves indeed, if you invoke one the functions i ve mentioned above in order to start the interaction the I2C module, the
ad_i2c_bus_aquire() function is invoked and the ad_i2c_bus_apply_config() will configure the I2C module for the current transaction (hw_i2c_init() / hw_i2c_enable()
将对当前事务执行主目标地址也将从hw\uI2C\u init()设置)。所以如果这是你唯一能做到的方法
I2C communication perhaps you dont use the adapter in order to trigger a I2C interaction. For example i read a sensor's value periodically from an RTOS timer, so
系统会唤醒,通过以下功能,我可以读取传感器的名称。

/*Read from sensor with seperate read and write transactions*/
void read_mpu_reg_rw(uint8_t reg_addr)
{
static uint8_t who_i_am_rw = 0;
uint8_t addr = reg_addr;
mpu6050=ad_UI2C U打开(MPU_);
ad_i2c_write(mpu6050, ®_addr, 1);
ad_i2c_read(mpu6050, &who_i_am_rw, 1);
printf(“%02x\n\r”,谁是\u i_urw);
}

谢谢你的对话

Richard Legault
Offline
最后一次见到:3 years 7 months ago
已加入:2017-03-01 18:54
Yes I do an open. The

Yes I do an open. The transact call never returns as it is waiting for an I2C to complete. I replaced the transact with write and read but the behaviour I have observed has remained the same. The SDK is 1.0.8.1050.1 for the DA14681

Thanks for keeping with this. I am confused as to why I am not seeing the expected behaviour after the extended sleep.

By the way when I do a hw_i2c_get_enable_status() it returns 0 after an extended sleep unless I have the 3 unnecessary steps in the periph_init.

In the I2C_Handler() call the value for i2c->intr_cb is NULL.

我没有更改任何保留设置,但看起来I2C的内存(状态)在延长睡眠期间丢失。

Could there be something there that is causing this behaviour?Do note that we have replaced the 8MBit winbond with a 64MBit winbond Flash part.We have created the new appropriate header file for it.

#定义proj\u configoptim\u RETRAM(0)

#如果!定义(版本构建)&&(proj\u configoptim\u RETRAM==1)
/* WARNING: retRAM optimizations are disabled in DEBUG builds! */
#undef proj_configOPTIMAL_RETRAM
#定义proj\u configoptim\u RETRAM(0)
#elif (dg_configEXEC_MODE != MODE_IS_CACHED)
/* WARNING: retRAM optimizations are not applicable in MIRRORED mode! */
#undef proj_configOPTIMAL_RETRAM
#定义proj\u configoptim\u RETRAM(0)
#endif

#if (proj_configOPTIMAL_RETRAM == 0)
#define dg_configMEM_RETENTION_MODE (0x1F)
#define dg_configSHUFFLING_MODE (0x3)

MT\u对话框
Offline
最后一次见到:2 months 2 weeks ago
工作人员
已加入:2015-06-08 11:34
Hi Richard,

Hi Richard,

您能告诉我,您如何触发代码中的I2C事务,您将代码放置在哪里以便设备开始交互?

谢谢你的对话

Richard Legault
Offline
最后一次见到:3 years 7 months ago
已加入:2017-03-01 18:54
It is within a task that is

It is within a task that is woken by an interrupt. I showed the call chain to kxcjbDevRegisterGet in a previous response.

Since interrupts cannot use adapters to interact with I2C, the task has to clear the interrupt when it reads the interrupt clearing register via I2C.

Here is the interrupt handler (The clearing of the HW GPIO is done by the WKUP handler I wrote. Tasks register with WKUP to have their handler called when a certain PORT/PIN interrupt is detected.

//其思想是,这是中断的上半部分,它指示下半部分(任务)计划在稍后运行。
static void kxcjbTapEventInterrupt(void* eventData)
{
//tp_interruptEventData p_eventData = (tp_interruptEventData) eventData;
BaseType_UT XhighPriorityTaskwoken=pdFALSE;

xTaskNotifyFromISR( accelInterruptTaskHandle, ACCEL_INTR_NOTIFY, eSetBits,
&xHigherPriorityTaskWoken);
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
返回;
}

// HERE IS THE TASK //
//the idea is that this is the bottom Half of the interrupt that is scheduled to run at a later time.

static void accelTaskHL( void *pvParameters )
{
/* define variables static to get it off the stack */
static uint8_t accelSource[2];
错误代码错误代码;
bool st;

bool dataValid=false;
uint32炦t notifyValue;
uint8_t data;
const TimerHandle_t accelTimer = xTimerCreate( "accelTaskTimer",
pdMS_TO_TICKS(750),
pdFALSE,
(void *)0,
accelTimerCallback);

while (1)
{
xTaskNotifyWait(0x00, ULONG_MAX, ¬ifyValue, portMAX_DELAY); // WAIT here for the next signal: Interrupt, Timeout, or control message

kxcjbDevRegisterGet(NULL, WHOAMI_ADDR, &data);// Within this function I do the ad_i2c_transact()
if (notifyValue&ACCEL_ENABLE_NOTIFY) {
g_accelState=ACCEL_STATE_0;
kxcjbInterruptEnable();
i2c_device dev = ad_i2c_open(ACCEL_KXCJB);
errCode = kxcjbBitsSet( dev, CTRL_REG1_ADDR, CTRL_REG1_PC1_EN);
assert(errCode==ERRORCODE_OK);
ad_UI2C_U关闭(dev);

}
else if (notifyValue&ACCEL_DISABLE_NOTIFY) {
kxcjbInterruptDisable();
i2c_device dev = ad_i2c_open(ACCEL_KXCJB);
errCode=kxcjbBitsClear(dev,CTRL\u REG1\u ADDR,CTRL\u REG1\u PC1\u EN);
assert(errCode==ERRORCODE_OK);
ad_UI2C_U关闭(dev);

g_accelState=ACCEL_STATE_DISABLE;
}
else
{
switch (g_accelState) {
case ACCEL\u状态\u禁用:
/*无所作为*/
break;
case ACCEL_STATE_0:
if(notifyValue&ACCEL\u INTR\u NOTIFY){
kxcjbInterruptSrc(NULL, &accelSource[ACCEL_STATE_0]);

/*会处理计时器已经运行的情况,
*should not happen
*/
xTimerReset(accelTimer, 0);

g_accelState=ACCEL_STATE_1;
}
/* else we are ignoring the timer interrupt, should not happen */
break;
case ACCEL_STATE_1:

if(notifyValue&ACCEL\u INTR\u NOTIFY){
kxcjbInterruptSrc(NULL, &accelSource[ACCEL_STATE_1]);
printf ("0=0x%02x\n\r1=0x%02x\n\r",accelSource[0],accelSource[1]);
fflush(stdout);
/*测试是否在同一轴上有源中断
*as occurred in previous interrupt
*/
if(((accelSource[ACCEL\u STATE\u 0]&(INT\u SOURCE2\uxpwu | INT\u SOURCE2\u XNWU))
&&(accelSource[ACCEL_STATE_1]&(INT_SOURCE2_XPWU|INT_SOURCE2_XNWU))
)||
( (accelSource[ACCEL_STATE_0]&(INT_SOURCE2_YPWU|INT_SOURCE2_YNWU))
&&(accelSource[ACCEL_STATE_1]&(INT_SOURCE2_YPWU|INT_SOURCE2_YNWU))
)||
( (accelSource[ACCEL_STATE_0]&(INT_SOURCE2_ZPWU|INT_SOURCE2_ZNWU))
&&(accelSource[ACCEL_STATE_1]&(INT_SOURCE2_ZPWU|INT_SOURCE2_ZNWU))
)
) {
xTimerStop(accelTimer, 0);
if (ACCEL_TASK_DISABLE_ON_TAP_DETECT) {
g_accelState = ACCEL_STATE_DISABLE;
kxcjbInterruptDisable();
}
else {
g_UAccelerState=加速状态\u 0;
}

if (gfp_tapEventCb) {
gfp U tapEventCb(g_appInfo);
}
}
else {
printf("AC:TO\n\r");
fflush(stdout);

xTimerReset(accelTimer, 0);
accelSource[ACCEL\u STATE\u 0]=加速源[ACCEL\u状态\u 1];
g_accelState = ACCEL_STATE_1; /* reenter the same state */
}
}
else if (notifyValue & ACCEL_TIMER_NOTIFY) {
g_accelState=ACCEL_STATE_0;
}
else {
断言(0==1);
}
}
}
}
}

// Here is the code that creates the task,

uint32_t status = OS_TASK_CREATE("AccelInterruptHL", /* The text name assigned to the task, for
debug only; not used by the kernel. */
accelTaskHL, /* The System Initialization task. */
( void * ) 0, /* The parameter passed to the task. */
configMINIMAL_STACK_SIZE * OS_STACK_WORD_SIZE * 2,
/* The number of bytes to allocate to the
stack of the task. */
操作系统任务\u优先级\u最高,/*分配给任务的优先级*/
accelInterruptTaskHandle ); /* The task handle */

MT\u对话框
Offline
最后一次见到:2 months 2 weeks ago
工作人员
已加入:2015-06-08 11:34
嗨理查德·勒高,

嗨理查德·勒高,

因此,您配置唤醒计时器以触发来自所连接传感器的传感器读数,每次传感器发出中断时,您都会通知触发读取的任务,并执行数据读取和中断清除。看起来可以,我不太明白的是唤醒中断的中断处理程序(我想这是kxcjbtapeventinterpropt,是不是正确),为什么处理程序有一个事件参数?另外,它不建议从\u ISR调用Port屈服_U(尽管我已经测试过它,至少在我的一侧,它不会影响处于休眠模式时的I2C交互),您不应该运行优先级最高的任务,因为这可能会影响其他任务(BLE任务、电源管理器任务等)。不管怎样,我认为这些不会给I2C带来任何问题,所以我的重新建议是调试这个,检查代码是否通过I2C交互函数,我是说ad I2C_U读/写等,您也提到了睡眠后的配置为零,I2C模块的配置在调用I2C交互函数时立即应用,如ad味I2C炦读/写等。您也可以编写一个更简单的代码,以测试在更简单的项目中与I2C的交互(您可以通过简单计时器或唤醒计时器与传感器交互-触发gpio的中断)和检查这是否在您的自定义设备上工作,然后与您现在的设备进行比较。最后一件事我注意到,您用于I2C引脚的端口是PORT4和port 3,请注意,如果您使用的是WCSP包,那么这些端口不可用。

谢谢你的对话

Richard Legault
Offline
最后一次见到:3 years 7 months ago
已加入:2017-03-01 18:54
It appears to be due to using

It appears to be due to using gcc-arm-none-eabi-6-2017-q1-update ( with this tool chain I have to use the extra steps to get I2C to work).
With the provided gcc tool chain: 4_9-2015q3 the I2C works as advertised.

Thanks for your assistance and perseverance on this.
Hopefully this saves others time, knowing that the tool chain affects the documented behaviour.

MT\u对话框
Offline
最后一次见到:2 months 2 weeks ago
工作人员
已加入:2015-06-08 11:34
Hi Richard,

Hi Richard,

谢谢你的指示,很高兴你已经解决了你的问题。

Best Regards MT_dialog