I have a working I2C with an accelerometer connected to the dev board.
初始化后的通信工作。
在该单元转到Extended_sleep之后并唤醒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 contains
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 Data
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,输入,gpio,false);// Accel Irq.
醒来后,示例说要改变线条。在Periph_init()中是否需要在延长睡眠后缺少I2C通信的情况下进行任何其他需要完成。
Thanks for your assistance.
我已经探测了SCL线,延长睡眠后没有在线上的活动。
嗨理查德Legault,
我没有看到您提到的配置中缺少的任何缺失,如何触发系统从系统读取传感器存储器等?设备停顿的代码的一部分是因为它等待来自I2C模块的完整事件,并且显然没有发生任何内容。
还请看看下面的职位,也许这将有所帮助:
https://support.dialog-semicondiondiondum/forums/post/dialog-smartbond-bl ...
Thanks 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 Data
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,输入,gpio,false);// Accel Irq.
静态const i2c_config 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,0x0E); /* appears the adapter does not set the address when only one I2C device is on the bus?? */
hw_i2c_enable(hw_i2c1);
====================.
否在示例或文档中没有提及睡眠时需要完成这些初始步骤。我只发现了之前的响应中的链接。
问题是:在深度睡眠后正确行为或在I2C适配器或HW_I2C代码中是一个错误所需的初始化。即使仅具有一个设备的总线,适配器也更新设备地址。
为什么当适配器假设为我这样做时,我必须设置目标Address?如果我没有在init中设置地址,那么我可以为设备读取所有寄存器的值0x07。这是仅在总线上具有一个设备的工件。
嗨理查德Legault,
As mentioned as a direct answer on the previous post those initialization are not necessary, since you are using the adapters in order to interact with the sensor, the adapter will re-enable and configure the I2C bus for you, you will just have to place the configuration of your pins in the periph_setup() function. So if you are using the adapters, you will just have to open the connection with the I2C device that you have declared in the platform_devices.h with ad_i2c_open() and start a transaction, with ad_i2c_transact() or ad_i2c_write(), ad_i2c_read() etc. So how do you trigger the transaction ?
Thanks MT_dialog
是的,这是预期的行为,但观察到的行为是我确实需要做那些3个步骤,否则I2C在延长睡眠时醒来时没有响应。
嗨理查德
它的预期和系统的表现性实际上,如果您调用上面提到的功能,以便启动I2C模块的交互,则
调用AD_I2C_BUS_AQUIRE()函数,ad_i2c_bus_apply_config()将为当前事务配置I2C模块(HW_I2C_INIT()/ hw_i2c_enable()
will be executed for the current transaction the master target address will be also set from the hw_i2c_init()). So if this is the only way that you can achieve
I2C通信也许您不使用适配器才能触发I2C交互。例如,我从RTOS计时器定期读取传感器的值,所以
the system wakes up and with the below function i can read the name of the sensor.
/ *从传感器读取单独的阅读和写交易* /
void read_mpu_reg_rw(uint8_t reg_addr)
{
静态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("%02x \n\r", who_i_am_rw);
}
Thanks MT_dialog
是的,我开了一个开放。交易呼叫永远不会返回,因为它正在等待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。
I have not changed any of the retention settings but it looks like the memory (state) for the I2C is being lost during extended sleep.
可以在那里造成这种行为吗?请注意,我们已将8Mbit Winbond替换为64Mbit Winbond闪存部分。我们为此创建了新的适当标题文件。
#define proj_configOPTIMAL_RETRAM (0)
#if !defined(RELEASE_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)
嗨理查德,
Can you please let me know, how do you trigger the I2C transaction in the code, where do you place the code in order for the device to start the interaction ?
Thanks MT_dialog
它是一个由中断醒来的任务。我在以前的响应中向KXCJBDevRegistergitter展示了呼叫链。
由于中断不能使用适配器与I2C交互,因此当通过I2C读取中断清除寄存器时,任务必须清除中断。
这是中断处理程序(HW GPIO的清除由我写的WKUP处理程序完成。任务在检测到某个端口/引脚中断时,使用WKUP寄存器。
//the idea is that this is the top Half of the interrupt that it signals to have the bottom half (task) scheduled to run at a later time.
静态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);
return;
}
//以下是任务//
//这个想法是,这是中断的下半部分计划以稍后的时间运行。
静态void acceltaskhl(空白* pvparameters)
{
/ *定义变量静态以使其从堆栈中获取* /
静态UINT8_T Accelsource [2];
t_errorCode errCode;
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,&NotifyValue,portmax_delay);//在这里等待下一个信号:中断,超时或控制消息
kxcjbdevregistergett - null,whoami_addr和数据);//在此函数中,我执行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);
}
否则if(notifyValue&Accel_disable_notify){
kxcjbinterruptdisable();
i2c_device dev = ad_i2c_open(Accel_kxcjb);
errCode =kxcjbBitsClear( dev, CTRL_REG1_ADDR, CTRL_REG1_PC1_EN);
断言(errcode == errercode_ok);
ad_i2c_close(dev);
g_accelstate = Accel_State_disable;
}
别的
{
切换(G_accelstate){
case ACCEL_STATE_DISABLE:
/* do nothing */
休息;
案例Accel_State_0:
if (notifyValue & ACCEL_INTR_NOTIFY) {
kxcjbinterruptsrc(null,&accelsource [Accel_State_0]);
/* will handle the case where the timer is already running,
*不应该发生
* /
Xtimerreset(Acceltimer,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);
/* test if we got source interrupt on the same axis
*正如以前的中断发生
* /
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))
)
) {
Xtimstrimer(Accellimer,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;/ *重新输入相同的状态* /
}
}
否则if(notifyValue&Accel_timer_Notify){
g_accelstate = Accel_State_0;
}
别的 {
assert (0==1);
}
}
}
}
}
//以下是创建任务的代码,
UINT32_T Status = OS_TASK_CREATE(“AccelIntErrupthl”,/ *分配给任务的文本名称,
只调试;内核不使用。* /
Acceltaskhl,/ *系统初始化任务。* /
(void *)0,/ *传递给任务的参数。* /
configminimal_stack_size * os_stack_word_size * 2,
/ *分配给的字节数
堆栈的任务。* /
OS_TASK_PRIORITY_HIGHEST, /* The priority assigned to the task. */
AccelInterractTaskHandle);/ *任务句柄* /
嗨理查德Legault,
So, you have configured the wake up timer in order to trigger sensor readings from the attached sensor, every time the sensor issues an interrupt you notify the task that triggers the reading, and you perform the read of data and clearing of the interrupt. Seems ok, what i dont quite get is the interrupt handler of the wakeup interrupt (i suppose that this is the kxcjbTapEventInterrupt, am i correct), why the handler has an event parameter ? Also its not recommended invoke the portYIELD_FROM_ISR (although i ve tested it and at least on my side it doesn't affect the I2C interaction when you are in sleep mode) and you should not run a task with a highest priority since this might affect other tasks (BLE task, power manager task etc). Anyway i dont think that those will cause any issues to the I2C, so my recomendation would be debug this and check if the code goes through the I2C interaction function, i mean the ad_i2c_read/write etc, also, you ve mentioned that the configuration after sleep is zero, the configuration for the I2C module is applied as soon as the i2c interaction functions are invoked ad_i2c_read/write etc. Also you could write a simpler code in order to test if the interaction with the i2c in simpler project (you could interact with the sensor via a simple timer or via the wake up timer - trigger the interrupt from a gpio) and check if that is working on your custom device then compare with the one that you have now. One last thing i 've noticed that the port that you are using for the I2C pins is PORT4 and PORT 3, be aware that if you are using the WCSP package those ports are not available.
Thanks MT_dialog
它似乎是由于使用gcc-arm-none-eabi-6-2017-q1-update(使用这个刀具链,我必须使用额外的步骤来获得I2c工作)。
随着提供的GCC工具链:4_9-2015Q3 I2C为广告工作。
感谢您的帮助和坚持不懈。
希望这可以节省他人的时间,知道工具链会影响文档的行为。
嗨理查德,
Thanks for indicating this, glad you have resolved your issue.
最好的问候mt_dialog.