我有一个工作的I2C与加速计连接到开发板。
初始化后通信工作。
设备进入长时间睡眠并唤醒后,I2C不再工作。I2C上目前只有一个设备。电源未被禁用。
该任务陷入ad_i2c.c:284 os_event_wait(dev_config-> bus_data->事件,os_event_forever);
中断火灾一次,但我无法清除它,因为我需要读取地址以清除来自加速度计侧的PIN。所以加速似乎仍在工作。
我有一次I2C_BUS_INIT(I2C1)和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()包含(使用HW_GPIO_PINCONFIG宏,因此名称已正确扩展)
hw_gpio_configure_pin(HW_GPIO_PORT_3, HW_GPIO_PIN_0, INPUT, I2C_SDA, false);/ / IC21数据
硬件gpio配置引脚(硬件gpio端口4,硬件gpio引脚7,输出,I2C SCL,假);//I2C1时钟
hw_gpio_configure_pin(hw_gpio_port_4,hw_gpio_pin_3,输入,gpio,false);// Accel Irq.
醒来后,这些例子说要重新整理台词。在periph_init()中还有什么我在长时间睡眠后I2C通信无法正常工作的地方需要做吗。
谢谢你的帮助。
设备:
我已经探测了SCL线,延长睡眠后没有在线上的活动。
你好理查德•Legault
我没有看到您提到的配置中缺少的任何缺失,如何触发系统从系统读取传感器存储器等?设备停顿的代码的一部分是因为它等待来自I2C模块的完整事件,并且显然没有发生任何内容。
还请看看下面的职位,也许这将有所帮助:
https://support.dialog-semiconductor.com/forums/post/dialog-smartbond-bl...
由于MT_dialog
当它出来的睡眠时,I2C状态为0(禁用)。
要再次获取I2C功能,请执行HW_I2C_ENABLE(HW_I2C1)我不得不in in in in in in in in in in in in in entr设置目标地址。
因此,I2C periph_init的代码现在是:
=================
hw_gpio_configure_pin(HW_GPIO_PORT_3, HW_GPIO_PIN_0, INPUT, I2C_SDA, false);/ / IC21数据
硬件gpio配置引脚(硬件gpio端口4,硬件gpio引脚7,输出,I2C SCL,假);//I2C1时钟
hw_gpio_configure_pin(hw_gpio_port_4,hw_gpio_pin_3,输入,gpio,false);// Accel Irq.
静态常数i2c_配置cfg={
。speed = HW_I2C_SPEED_FAST,
.mode=HW_I2C_mode_MASTER,
.ddr_mode = hw_i2c_addressing_7b,
};
hw_i2c_init(hw_i2c1,cfg);
hw_i2c_set_target_address (HW_I2C1 0 x0e);/*显示适配器没有设置地址时,只有一个I2C设备在总线上?*/
hw_i2c_enable(hw_i2c1);
====================
否在示例或文档中没有提及睡眠时需要完成这些初始步骤。我只发现了之前的响应中的链接。
问题是:在深度睡眠后正确行为或在I2C适配器或HW_I2C代码中是一个错误所需的初始化。即使仅具有一个设备的总线,适配器也更新设备地址。
当适配器为我设置TargetAddress时,为什么我必须设置TargetAddress?如果我没有在init中设置地址,那么对于从设备读取的所有寄存器,我会得到一个0x07的值。这是总线上只有一个设备的产物吗。
你好理查德•Legault
如前所述先前有直接回答这些初始化并不必要,因为你正在使用适配器来与传感器交互,适配器将重新启用和配置I2C总线,您只需要将配置你的别针periph_setup()函数。因此,如果您正在使用适配器,您只需要使用ad_i2c_open()打开在platform_devices.h中声明的I2C设备的连接,并使用ad_i2c_transact()或ad_i2c_write()、ad_i2c_read()等启动一个事务。那么如何触发事务呢?
由于MT_dialog
是的,这是预期的行为,但观察到的行为是,我确实需要执行这3个步骤,否则I2C从长时间睡眠中醒来时不会有反应。
嗨理查德
它的预期和系统的表现性实际上,如果您调用上面提到的功能,以便启动I2C模块的交互,则
调用ad_i2c_总线_aquire()函数,ad_i2c_总线_应用_配置()将为当前事务配置i2c模块(hw_i2c_init()/hw_i2c_enable()
将对当前事务执行,主目标地址也将从hw_i2c_init()设置。所以如果这是你唯一能做到的
I2C通信也许您不使用适配器才能触发I2C交互。例如,我从RTOS计时器定期读取传感器的值,所以
系统醒来,通过下面的功能,我可以读出传感器的名称。
/*通过单独的读写事务从传感器读取*/
无效读取(uint8注册地址)
{
静态uint8_t who_i_am_rw = 0;
uint8_t addr = reg_addr;
mpu6050 = ad_i2c_open (MPU_6050);
AD_I2C_WRITE(MPU6050,&REG_ADDR,1);
ad_i2c_read(mpu6050,&who_i_am_rw,1);
printf (" % 02 x r \ n \”,who_i_am_rw);
}
由于MT_dialog
是的,我做公开赛。transact调用永远不会返回,因为它正在等待I2C完成。我将transact替换为write and read,但我观察到的行为保持不变。DA14681的SDK为1.0.8.1050.1
谢谢你一直这么做。我很困惑,为什么我在长时间睡眠后没有看到预期的行为。
顺便说一下,当我执行hw_i2c_get_enable_status()时,它在长时间睡眠后返回0,除非我在periph_init中执行了3个不必要的步骤。
在I2C_Handler()调用中,I2C->intr_cb的值为NULL。
我没有改变任何保留设置,但看起来I2C的内存(状态)在延长睡眠期间丢失了。
可以在那里造成这种行为吗?请注意,我们已将8Mbit Winbond替换为64Mbit Winbond闪存部分。我们已经为它创建了新的适当的头文件。
#定义proj_configOPTIMAL_RETRAM (0)
#if !define (RELEASE_BUILD) && (proj_configOPTIMAL_RETRAM == 1)
/*警告:调试版本中禁用了重新扫描优化*/
#未定义项目配置最佳重新培训
#定义proj_configOPTIMAL_RETRAM (0)
#elif(dg_配置执行模式!=模式(已缓存)
/*警告:重新扫描优化不适用于镜像模式*/
#未定义项目配置最佳重新培训
#定义proj_configOPTIMAL_RETRAM (0)
#恩迪夫
#if(proj_configoptimal_retram == 0)
#define dg_configmem_retention_mode(0x1f)
#define dg_configshuffling_mode(0x3)
嗨理查德,
你能告诉我,你如何在代码中触发I2C事务,为了让设备开始交互,你将代码放置在哪里?
由于MT_dialog
它是一个由中断醒来的任务。我在以前的响应中向KXCJBDevRegistergitter展示了呼叫链。
由于中断不能使用适配器与I2C交互,因此任务必须在通过I2C读取中断清除寄存器时清除中断。
这是中断处理程序(清除HW GPIO由我编写的WKUP处理程序完成。任务向WKUP注册,以便在检测到某个端口/引脚中断时调用其处理程序。
//它的想法是,这是中断的上半部分,它发出信号让下半部分(任务)在稍后的时间运行。
静态void kxcjbtapeventerrupt(void*eventData)
{
//tp_interruptEventData p_eventData=(tp_interruptEventData)eventData;
BaseType_t xhigherprioritytaskkoken = pdFALSE;
xTaskNotifyFromISR(accelInterruptTaskHandle、ACCEL\u INTR\u NOTIFY、eSetBits、,
&xhigherprioritytaskwoken);
来自ISR的端口收益(xHigherPriorityTask唤醒);
返回;
}
//以下是任务//
//这个想法是,这是中断的下半部分计划以稍后的时间运行。
静态void acceltaskhl(空白* pvparameters)
{
/ *定义变量静态以使其从堆栈中获取* /
静态UINT8_T Accelsource [2];
t_errorCode errCode;
BOOL ST;
bool dataValid = false;
uint32_t notifyValue;
uint8_t数据;
常量TimerHandle\u t accelTimer=xTimerCreate(“accelTaskTimer”,
pdms_to_ticks(750),
pdFALSE,
(无效*)0,
加速时间回调);
而(1)
{
XTaskNotifyWait(0x00,Ulong_max,&NotifyValue,portmax_delay);//在这里等待下一个信号:中断,超时或控制消息
kxcjbdevregistergett - null,whoami_addr和数据);//在此函数中,我执行ad_i2c_transact()
if(notifyvalue&Accel_enable_notify){
g_accelstate = Accel_State_0;
kxcjbInterruptEnable();
i2c_设备开发=ad_i2c_打开(加速度KXCJB);
errcode = kxcjbbitsset(dev,ctrl_reg1_addr,ctrl_reg1_pc1_en);
断言(errCode==ERRORCODE\u OK);
ad_i2c_close (dev);
}
否则if(notifyValue&Accel_disable_notify){
kxcjbInterruptDisable();
i2c_设备开发=ad_i2c_打开(加速度KXCJB);
errCode = kxcjbbitclear (dev, CTRL_REG1_ADDR, CTRL_REG1_PC1_EN);
断言(errCode==ERRORCODE\u OK);
ad_i2c_close (dev);
g_accelstate = Accel_State_disable;
}
别的
{
切换(G_accelstate){
案例ACCEL_STATE_DISABLE:
/*什么都不做*/
休息;
案例Accel_State_0:
if (notifyValue & ACCEL_INTR_NOTIFY) {
kxcjbInterruptSrc(NULL,&accelSource[ACCEL_STATE_0]);
/*将处理计时器已经在运行的情况,
*不应该发生
*/
xTimerReset(加速定时器,0);
g_accelstate = Accel_State_1;
}
/ *我们忽略了定时器中断,不应该发生* /
休息;
案例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);
/*测试源中断是否在同一轴上
*正如以前的中断发生
*/
如果(((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))
)
) {
Xtimstrimer(Accellimer,0);
如果(加速任务禁用打开轻触检测){
g_accelState=加速状态_禁用;
kxcjbInterruptDisable();
}
否则{
g_accelState = ACCEL_STATE_0;
}
如果(gfp_tapEventCb){
gfp_tapEventCb (g_appInfo);
}
}
否则{
printf(“ac:to \ n \ r”);
fflush(stdout);
xTimerReset(加速定时器,0);
accelSource [ACCEL_STATE_0] = accelSource [ACCEL_STATE_1];
g_accelState=加速状态_1;/*重新进入同一状态*/
}
}
否则if(notifyValue&Accel_timer_Notify){
g_accelstate = Accel_State_0;
}
否则{
断言(0 = = 1);
}
}
}
}
}
//以下是创建任务的代码,
UINT32_T Status = OS_TASK_CREATE(“AccelIntErrupthl”,/ *分配给任务的文本名称,
只调试;内核不使用*/
Acceltaskhl,/ *系统初始化任务。*/
(void *)0,/ *传递给任务的参数。*/
配置最小\u堆栈\u大小*OS\u堆栈\u字大小*2,
/*要分配给服务器的字节数
堆栈的任务。*/
OS_TASK_PRIORITY_HIGHEST, /*执行任务的优先级。*/
accelInterruptTaskHandle);/*任务句柄*/
你好理查德•Legault
因此,您已经配置了唤醒计时器,以便触发来自附加传感器的传感器读数,每次传感器发出中断时,您就通知触发读取的任务,然后执行数据读取和清除中断。似乎ok,我不太明白的是唤醒中断的中断处理程序(我认为这是kxcjbTapEventInterrupt,我是正确的),为什么处理程序有一个事件参数?也不推荐调用portYIELD_FROM_ISR(虽然我已经测试它,至少在我身边不会影响I2C交互在睡眠模式)和你不应该运行一个任务优先级最高,因为这可能会影响其他任务(BLE的任务,任务管理器等)。无论如何,我不认为这些会导致任何问题的I2C,所以我的建议是调试这个,并检查代码是否通过I2C交互功能,我的意思是ad_i2c_read/write等,也,你提到的配置后睡眠是零,只要调用I2C交互函数ad_i2c_read/write等,就应用I2C模块的配置。也可以编写一个简单的代码来测试如果与i2c的交互简单项目(你可以通过一个简单的计时器与传感器交互或通过唤醒定时器触发中断gpio)并检查如果正在定制设备,与你现在。我注意到的最后一件事是,您使用的I2C引脚端口是PORT4和port3,请注意,如果您使用的是WCSP包,这些端口是不可用的。
由于MT_dialog
这似乎是由于使用了gcc-arm-none-eabi-6-2017-q1-update(有了这个工具链,我必须使用额外的步骤才能让I2C正常工作)。
通过提供的gcc工具链:4_9-2015q3,I2C可以按照广告的方式工作。
谢谢你在这方面的帮助和坚持。
希望这能节省其他人的时间,因为知道工具链会影响记录的行为。
嗨理查德,
谢谢你指出这一点,很高兴你解决了你的问题。
最好的问候mt_dialog.