从睡觉醒来后i2c不起作用

⚠️
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 athttps://www.dialog-seminile.com/support.。我们将在未来几天修复错误/优化搜索和标记。
13 posts / 0 new
最后一篇
理查德莱克
Offline
最后一次露面:3 years 7 months ago
加入:2017-03-01 18:54
从睡觉醒来后i2c不起作用

我有一个工作I2C,加速度计连接到DEV板。
初始化后的通信工作。
在该单元转到Extended_sleep之后并唤醒I2C不再工作。目前只有I2C上的一个设备。电源未禁用。
这task gets stuck at ad_i2c.c:284 OS_EVENT_WAIT(dev_config->bus_data->event, OS_EVENT_FOREVER);

这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).
platform_devices.h包含

I2C_BUS(I2C1)

i2c_slave_device(i2c1,Accel_kxcjb,0x0e,
HW_I2C_ADDRESSING_7B, HW_I2C_SPEED_FAST);

I2C_BUS_END.

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

hw_gpio_configure_pin(hw_gpio_port_3,hw_gpio_pin_0,输入,i2c_sda,false);// IC21数据
hw_gpio_configure_pin(hw_gpio_port_4,hw_gpio_pin_7,输出,i2c_scl,false);// i2c1 clk.
hw_gpio_configure_pin(HW_GPIO_PORT_4, HW_GPIO_PIN_3, INPUT, GPIO, false); // accel irq

醒来后,示例说要改变线条。在Periph_init()中是否需要在延长睡眠后缺少I2C通信的情况下进行任何其他需要完成。

感谢你的协助。

Device:
理查德莱克
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_dialog.
Offline
最后一次露面:2 months 2 weeks ago
职员
加入:2015-06-08 11:34
嗨Richard Legault,

嗨Richard Legault,

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-semicondiondiondum/forums/post/dialog-smartbond-bl ...

谢谢mt_dialog.

理查德莱克
Offline
最后一次露面:3 years 7 months ago
加入:2017-03-01 18:54
当它出来的睡眠

当它出来的睡眠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.
因此,I2C Periph_Init的代码现在:

=================.
hw_gpio_configure_pin(hw_gpio_port_3,hw_gpio_pin_0,输入,i2c_sda,false);// IC21数据
hw_gpio_configure_pin(hw_gpio_port_4,hw_gpio_pin_7,输出,i2c_scl,false);// i2c1 clk.
hw_gpio_configure_pin(HW_GPIO_PORT_4, HW_GPIO_PIN_3, INPUT, GPIO, false); // accel irq

静态const i2c_config cfg = {
.speed = hw_i2c_speed_fast,
.mode = hw_i2c_mode_master,
。addr_mode = HW_I2C_ADDRESSING_7B,
};

hw_i2c_init(HW_I2C1, &cfg);
hw_i2c_set_target_address(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.

这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.

为什么当适配器假设为我这样做时,我必须设置目标Address?如果我没有在init中设置地址,那么我可以为设备读取所有寄存器的值0x07。这是仅在总线上具有一个设备的工件。

mt_dialog.
Offline
最后一次露面:2 months 2 weeks ago
职员
加入:2015-06-08 11:34
嗨Richard Legault,

嗨Richard Legault,

如上所述,由于之前的帖子上的直接答案不需要,因为您正在使用适配器才能与传感器进行交互,因此适配器将重新启用并为您配置I2C总线,您只需要放置PERIPH_SETUP()函数中的PIN配置。因此,如果您使用的适配器,您将只需使用ad_i2c_open()中声明的I2C设备“和”AD_I2C_TRANSACT()或AD_I2C_WRITE(),AD_I2C_READ()“开始”将打开“已声明的I2C设备”。等等,你如何触发交易?

谢谢mt_dialog.

理查德莱克
Offline
最后一次露面:3 years 7 months ago
加入:2017-03-01 18:54
是的,这是预期的

是的,这是预期的行为,但观察到的行为是我确实需要做那些3个步骤,否则I2C在延长睡眠时醒来时没有响应。

mt_dialog.
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()函数,ad_i2c_bus_apply_config()将为当前事务配置I2C模块(HW_I2C_INIT()/ hw_i2c_enable()
将为当前事务执行主目标地址,也将从HW_I2C_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
系统唤醒,使用以下功能,我可以读取传感器的名称。

/ *从传感器读取单独的阅读和写交易* /
void read_mpu_reg_rw(uint8_t reg_addr)
{
static uint8_t who_i_am_rw = 0;
uint8_t addr = reg_addr;
MPU6050 = AD_I2C_OPEN(MPU_6050);
ad_i2c_write(mpu6050, ®_addr, 1);
ad_i2c_read(mpu6050, &who_i_am_rw, 1);
printf(“%02x \ n \ r”,who_i_am_rw);
}

谢谢mt_dialog.

理查德莱克
Offline
最后一次露面:3 years 7 months ago
加入:2017-03-01 18:54
是的,我开了一个开放。这

是的,我开了一个开放。交易呼叫永远不会返回,因为它正在等待I2C完成。我用书写和读数替换了交易,但观察到的行为仍然是相同的。SDK为DA14681为1.0.8.1050.1

谢谢你与此保持一致。我很困惑为什么我在延长睡眠后没有看到预期的行为。

顺便说一下,当我执行HW_I2C_GET_ENABLE_STATUS_STATUS_STATUS()后,延长睡眠后返回0,除非我在PERIPH_INIT中有3个不必要的步骤。

在I2C_Handler()调用I2C-> Intr_CB的值为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.我们为此创建了新的适当标题文件。

#define proj_configoptimal_retram(0)

#if!定义(Reford_Build)&&(proj_configoptimal_retram == 1)
/ *警告:在调试版本中禁用了鼠尾优化!* /
#undef proj_configoptimal_retram.
#define proj_configoptimal_retram(0)
#elif(dg_configexec_mode!= mode_is_cached)
/ *警告:对镜像模式不适用于逆流优化!* /
#undef proj_configoptimal_retram.
#define proj_configoptimal_retram(0)
#万一

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

mt_dialog.
Offline
最后一次露面:2 months 2 weeks ago
职员
加入:2015-06-08 11:34
Hi Richard,

Hi Richard,

你能告诉我,如何在代码中触发i2c事务的方式,您在哪里放置代码,以便设备启动交互?

谢谢mt_dialog.

理查德莱克
Offline
最后一次露面:3 years 7 months ago
加入:2017-03-01 18:54
它是一项任务

它是一项任务woken by an interrupt. I showed the call chain to kxcjbDevRegisterGet in a previous response.

由于中断不能使用适配器与I2C交互,因此当通过I2C读取中断清除寄存器时,任务必须清除中断。

这是中断处理程序(HW GPIO的清除由我写的WKUP处理程序完成。任务在检测到某个端口/引脚中断时,使用WKUP寄存器。

//这个想法是,这是中断的顶部,即它向稍后的时间运行的下半部分(任务)的信号。
静态void kxcjbtapeventintr>(void * enceData)
{
// tp_interrupteventdata p_eventdata =(tp_interrupteventdata)eventData;
baseType_t xhigherprioritytaskwoken = pdfalse;

xtasknotifyfromisr(AccelIntractTaskHandle,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];
t_errorcode错误码;
bool st;

bool datavalid = false;
UINT32_T NotifyValue;
UINT8_T数据;
const timerhandle_t acceltimer = xtimercreate(“AcceltaskTimer”,
pdMS_TO_TICKS(750),
pdfalse,
(void *)0,
acceltimercallback);

而(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);
断言(errcode == errercode_ok);
ad_i2c_close(dev);

}
else if (notifyValue&ACCEL_DISABLE_NOTIFY) {
kxcjbinterruptdisable();
i2c_device dev = ad_i2c_open(Accel_kxcjb);
errcode = kxcjbbitleclear(dev,ctrl_reg1_addr,ctrl_reg1_pc1_en);
断言(errcode == errercode_ok);
ad_i2c_close(dev);

g_accelState=ACCEL_STATE_DISABLE;
}
else
{
switch (g_accelState) {
案例Accel_State_disable:
/* 没做什么 */
break;
case ACCEL_STATE_0:
if(notifyValue&Accel_Intr_Notify){
kxcjbinterruptsrc(null,&accelsource [Accel_State_0]);

/ *将处理计时器已经运行的情况,
*不应该发生
* /
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_Intr_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_State_0]&(int_source2_xpwu | Int_source2_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();
}
别的 {
g_accelstate = Accel_State_0;
}

if(gfp_tapeventcb){
gfp_tapeventcb(g_appinfo);
}
}
别的 {
printf("AC:TO\n\r");
fflush(stdout);

Xtimerreset(Acceltimer,0);
Accelsource [Accel_State_0] = Accelsource [Accel_State_1];
g_accelstate = Accel_State_1;/ *重新输入相同的状态* /
}
}
else if (notifyValue & ACCEL_TIMER_NOTIFY) {
g_accelState=ACCEL_STATE_0;
}
别的 {
断言(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
只调试;内核不使用。* /
accelTaskHL, /* The System Initialization task. */
( void * ) 0, /* The parameter passed to the task. */
configminimal_stack_size * os_stack_word_size * 2,
/ *分配给的字节数
stack of the task. */
OS_TASK_PRIORITY_HIGHEST,/ *分配给任务的优先级。* /
AccelInterractTaskHandle);/ *任务句柄* /

mt_dialog.
Offline
最后一次露面:2 months 2 weeks ago
职员
加入:2015-06-08 11:34
嗨Richard Legault,

嗨Richard Legault,

因此,您已经配置了唤醒定时器,以便从附加的传感器触发传感器读数,每次传感器发出中断时,您通知触发读数的任务,并且您执行读取数据并清除中断清除。似乎好的,我不太得到的是唤醒中断的中断处理程序(我想这是KxcjbtapeventInterrupt,我是正确的),为什么处理程序有一个事件参数?此外,不建议调用portyield_from_isr(虽然我在睡眠模式下测试了它,并且至少在我的侧面时,它不会影响I2C交互),并且您不应该以最高优先级运行任务,因为这可能会影响其他任务(BLE任务,Power Manager任务等)。无论如何,我不认为那些会对I2C造成任何问题,所以我的推荐将调试它并检查代码是否通过I2C交互功能,我的意思是AD_I2C_READ / WRITE等,也,您提到的是配置的配置睡眠为零,一旦I2C交互功能被调用AD_I2C_READ / WRITE等,也可以应用I2C模块的配置。此外,您还可以编写更简单的代码,以测试与I2C中更简单的项目(您可以进行交互)通过简单的计时器或通过唤醒定时器使用传感器 - 从GPIO触发中断)并检查其在您的自定义设备上工作,然后与您现在的那个相比。最后一件事我注意到,您正在使用的I2C引脚的端口是Port4和Port 3,请注意,如果您使用的是WCSP包,则这些端口不可用。

谢谢mt_dialog.

理查德莱克
Offline
最后一次露面:3 years 7 months ago
加入:2017-03-01 18:54
It appears to be due to using

它似乎是由于使用gcc-arm-none-eabi-6-2017-q1-update(使用这个刀具链,我必须使用额外的步骤来获得I2c工作)。
随着提供的GCC工具链:4_9-2015Q3 I2C为广告工作。

感谢您的帮助和坚持不懈。
希望这可以节省他人的时间,知道工具链会影响文档的行为。

mt_dialog.
Offline
最后一次露面:2 months 2 weeks ago
职员
加入:2015-06-08 11:34
Hi Richard,

Hi Richard,

感谢您的表明,很高兴您解决了您的问题。

Best Regards MT_dialog