嗨,对话框中,我构建了一个基于px reporter的应用程序,添加了一个定时器,连接到中心设备时通过适配器从I2C总线读取数据。最奇怪的是,它在jlink jtag模式下工作得很好,但在连接后就停止了,当单独工作时发送几个数据包的数据。我使用附加函数,发现它在hw_hard_fault.c循环中结束。原因是什么?非常感谢。的问候。段
嗨段,
硬故障处理程序(函数hw_hard_fault.c中的hardfault_handlerc)将堆栈帧复制到内存中的固定位置。此堆栈框包含许多参数,可以帮助您找到硬故障的源。首先要开始的PC - 这是在发生硬故障发生时程序计数器的值I.E。它将指向正在执行的指令,导致硬故障。您可以使用调试器访问PC的值。附加并在硬盘处理程序中查找执行的代码(1)循环检查内存位置状态_base + 0x18 - 这将包含PC的值。status_base的值可以在hw_hard_fault.c文件中找到。一旦您有PC,您可以了解哪些指令(因此C代码的WHCH线)导致硬故障。
IM_Dialog
谢谢你的帮助。按照您的说明,我发现pc的硬件故障原因是0x7fd11e0。找出发生的事情是有助于的吗?
嗨,对话框中,我本周末做了一系列测试:1.简化了我的代码仅包括一个init函数,到init gpio和i2c异步交易,一个读取功能,从imu读取寄存器,并将其打印到UART。
2.将我的驱动程序代码移动到“Clean”BLE_PLE_PERITELAL项目,在任务开始时添加init,将计时器添加到ble_peripheral_task,然后在for for(;;)循环之前启动它,并且当任务接收计时器通知时,从i2c读取数据。
空白ble_peripheral_task (void * params){Int8_t wdog_id;ble_service_t * svc;OS_TASK handle = NULL;my_peripheral_init ();
......SNS_TIMER = OS_TIMER_CREATE(“SNS”,PORTCONVERD_MS_2_TICKS(100),OS_TIMER_SUCCESS,OS_GET_CURRENT_TASK(), sns_timer_cb); / /执行命令os_assert(sns_timer);OS_TIMER_START (sns_timer OS_TIMER_FOREVER);......if (notif & SNS_TIMER_NOTIF) {refresh_sensor ();}......但几秒钟后,uart打印停止了。当连接时,我发现该程序运行在sys_power_mgr.c的第2132行://暂停任何正在进行的QSPI程序/擦除操作。if(op!= null){// 2132dbg_set_high(flash_debug,flashdbg_suspend);
如果(qspi_check_and_suspend ()) {op - > = true暂停;}
DBG_SET_LOW (FLASH_DEBUG FLASHDBG_SUSPEND);}}
3.我尝试了另一种方法,在ble services启动后,在for(;;)之前删除sns_timer和一个无限循环:而(1){refresh_sensor ();OS_DELAY (50);}就像之前一样,几秒钟后,UART打印停止了。当Attch时,我发现该程序在Sys_Power_Mgr.c的Line1513中运行:/** 睡觉* /__WFI ();
/*确保代码将以尽可能快的速度执行。* /If (!allow_entering_sleep){//修改hw_cpm_set_hclk_div (ahb_div1);}4.我创建了一个新任务,比ble_peripheral_task优先级低。除了while循环什么也不做:而(1){refresh_sensor ();OS_DELAY (50);}我得到了与3的结果相同。所有的测试2,3,4我尝试pm_stay_alive()函数,或不启用看门狗,但得到相同的结果。
5.最后一次测试,我在下一行初始循环时,在所有BLE SEVICE开始之前。这次I2C数据读得很好!
空白ble_peripheral_task (void * params){Int8_t wdog_id;
ble_service_t * svc;OS_TASK handle = NULL;my_peripheral_init ();而(1){refresh_sensor ();OS_DELAY (50);}.....
似乎经常读取I2C不能与ble stack共存。有什么问题吗?
为您的回复循环。谢谢你。
您应该能够通过I2C读取设备,并且仍然可以执行BLE操作。你能发布你正在使用的代码来初始化I2C接口和读取传感器吗?
嗨IM_Dialog,谢谢你的回复。以下是初始化代码:bool i2c_devices_async_init(void){bool ret1 ret2;Static const i2c_config CFG = {.speed = hw_i2c_speed_standard,.mode = HW_I2C_MODE_MASTER,.ddr_mode = hw_i2c_addressing_7b,};
hw_i2c_init(hw_i2c1,cfg);将srand (OS_GET_TICK_COUNT ());
/**获取温度传感器设备的手柄。*此调用尚未配置I2C控制器。* /// tpdev = ad_i2c_open(tp_mms427);imudev = ad_i2c_open (IMU_LSM6DS3);// magdev = ad_i2c_open(MAG_AK09915);/**创建GUI用来等待I2C事务完成的事件。*此事件将用于从GUI任务访问温度传感器或EEPROM。* /init_event (&i2c_signal);
// ret1 = tp_device_init();
ret2 = imu_6axes_init ();/* ret1 = ret1 && ret2;
ret2 = mag_device_init ();Ret1 = Ret1 && re2;
//仅进行测试mag_set_power_mode(4);// 100Hz刷新* /返回(ret2);}和刷新传感器代码,在计时器中突出的折断通知:静态孔隙refresh_sensor(空白){Int32_t imudata [6];int16_t magdata [3];uint8_t k1status,tpirqstatus;uint8_t xy [2];
/ / pm_stay_alive ();k1status = (uint8_t)hw_gpio_get_pin_status(APP_BUTTON_GPIO_PORT, APP_BUTTON_GPIO_PIN);tpirqstatus = (uint8_t)hw_gpio_get_pin_status(TP_IRQ_GPIO_PORT, TP_IRQ_GPIO_PIN);
如果(imu_6axes_read_data (imudata)) {printf (" IO: % d | % d Acc: % d % d % d”,k1status, tpirqstatus, (int) imudata [0], (int) imudata [1], (int) imudata [2]);
printf(“gyro:%d,%d,%d \ r \ n”,(int)imudata [3],(int)imudata [4],(int)imudata [5]);}/* if (tp_drv_read_coordinate(xy)) {printf("TP:%u,%u ", xy[0], xy[1]);
}如果(mag_device_read (magdata)) {printf(“mag:%d,%d,%d \ r \ n”,magdata [0],magdata [1],magdata [2]);
* // / pm_resume_sleep ();
}
函数imu_6axes_read_data使用imu_i2c_read函数从IMU中读取多个寄存器并计算值:
bool i2c_read(uint8_t* pBuffer, uint8_t DeviceAddr, uint8_t RegisterAddr)uint16_t NumByteToRead){Bool ret = false;
ad_i2c_device_acquire(imudev);
if(HW_I2C_ABORT_NONE != i2c_device_read_async(imudev, &RegisterAddr, pBuffer, 1, NumByteToRead, &i2c_signal))转到退出;
ret = true;
退出:ad_i2c_device_release(imudev);返回受潮湿腐烂;}I2C读寄存器函数:与信号相关的函数与i2c_demo.c相同。
static hw_i2c_abort_source i2c_device_read_async(i2c_device dev,uint8_t * reg,const uint8_t * buf,uint8_t reglen,Uint8_t buflen, i2c_event *event){/**确保事件尚未处于信号状态;* /reset_event(事件);
/**写入传感器寄存器,使用回调将信号事件同步。* /ad_i2c_async_transact(dev, I2C_SND(reg, reglen), I2C_RCV(buf, buflen),I2C_CB1 (signal_event、事件),I2C_END);/**等待事务完成。* /wait_for_event(事件);
/**错误代码如果在事件中存储,则返回它。* /返回事件- >错误;
我需要强调,在系统停止之前,我可以成功识别并读取数十次的IMU数据。printf输出如下:
2017/1/11 10:08:05.658 [rx] -x69 IMU XG_ID: 0广告开始!IO: 1 | 1 Acc: -38年,16岁,1043年,陀螺:1680,-10710,-7630IO: 1 | 1 Acc: -38年,16岁,1041年,陀螺:1610,-10570,-7630IO:1 | 1 ACC:-38,16,1041,陀螺仪:1680,-10640,-7630IO: 1 | 1 Acc: -38, 17日,1040年,陀螺:1750,-10640,-7560IO:1 | 1 ACC:-38,16,1041,陀螺仪:1680,-10640,-7630IO:1 | 1 ACC:-38,16,1041,陀螺仪:1680,-10640,-7630......
问候,段
当使用I2C适配器时,你需要配置你的设备和I2C总线,方法是将以下内容添加到一个名为platform_devices.h的文件中,放置在你的config文件夹中:
#如果dg_configI2C_ADAPTERI2C_BUS(I2C1)i2c_slave_device(i2c1,device_a,0x20,hw_i2c_addressing_7b,hw_i2c_speed_standard);I2C_BUS_END.# endif
当您希望初始化您进行以下呼叫的端口时:
I2C_BUS_INIT (I2C1);I2C_DEVICE_INIT (DEVICE_A);
我无法在代码中看到这些呼叫,所以我不确定您是否使用此机制,如果不是,那么我建议您相应地更改代码。您可以在以下内容中找到如何使用I2C适配器的一个很好的示例:
DA1468x_SDK_BTLE_v_1.0.8.1050.1 \ dk_apps \ demo \ \项目peripherals_demo \ demo \ demo_i2c_async.c
谢谢你的重播。我完全遵循演示演示_i2c_async.c。设备的声明是在platform_devices.h的副本中进行的,如demo,如demo:I2C_BUS(I2C1)
#ifdef config_imu_lsm6ds3./*示例温度传感器FM75 */i2c_slave_device(i2c1,imu_lsm6ds3,0x6a,hw_i2c_addressing_7b,hw_i2c_speed_standard);# endif# ifdef CONFIG_MAG_AK09915/*示例温度传感器FM75 */I2C_SLAVE_DEVICE(I2C1, MAG_AK09915, 0x0c, HW_I2C_ADDRESSING_7B, HW_I2C_SPEED_STANDARD);# endif
但我找不到任何初始化,如i2c_bus_init(i2c1);在演示中。所以我没有在以前的代码中添加它们。
我在init中添加宏在hardware init和devices open之间:hw_i2c_init(hw_i2c1,cfg);将srand (OS_GET_TICK_COUNT ());I2C_BUS_INIT (I2C1);
i2c_device_init(imu_lsm6ds3);i2c_device_init(mag_ak09915);/**获取温度传感器设备的手柄。*此调用尚未配置I2C控制器。* /// tpdev = ad_i2c_open(tp_mms427);imudev = ad_i2c_open (IMU_LSM6DS3);magdev = ad_i2c_open(mag_ak09915);
但结果是一样的。接下来我应该尝试什么?谢谢你!
嗨Neil.duan,
你提到你的代码卡住了,它没有卡住(没有while(1)或任何让你的代码卡住的断言),代码仍然执行(你能检查一下当代码停止时你是否能在广播中看到任何广告)。当您附加和您发现代码在这些点是因为代码通过这些点更频繁或在__WFI()情况下,它只是等待一个中断发生。你提到的硬错误是一个不同的原因,它不是BLE或适配器的原因,硬错误发生在内存中错误的访问,空指针函数的调用,内存损坏等。我建议做的是检查弗兰克-威廉姆斯与系统查看器或臭氧调试器为了检查发生了什么任务和适配器使用,也可以调查传感器和打印在一个较小的频率和检查系统无法打印。我们很难假设代码中可能出现的错误,但是因为您使用的是适配器,所以SDK应该正确地处理BLE事件和I2C事务。
谢谢mt_dialog.
我也有同样的困难的错误问题。但这只发生在其中一块板上。我有两块黑板。另一个工作得很好。
我也使用I2C适配器从I2C传感器读取温度。这个问题的解决办法是什么,,,,?有人能在这方面帮助我吗?
嗨mahmed106,
谢谢你的评论。在以下论坛主题下,我已经回复了您:
https://support.dialog-semicondiondiondiondum/forums/post/dialog-smartbond-bluetooth-low-energy-%2%80%93-software/da14681-hardfault-when-reading-i2c.
谢谢,PM_DIALOG.
嗨段,
硬故障处理程序(函数hw_hard_fault.c中的hardfault_handlerc)将堆栈帧复制到内存中的固定位置。此堆栈框包含许多参数,可以帮助您找到硬故障的源。首先要开始的PC - 这是在发生硬故障发生时程序计数器的值I.E。它将指向正在执行的指令,导致硬故障。您可以使用调试器访问PC的值。附加并在硬盘处理程序中查找执行的代码(1)循环检查内存位置状态_base + 0x18 - 这将包含PC的值。status_base的值可以在hw_hard_fault.c文件中找到。一旦您有PC,您可以了解哪些指令(因此C代码的WHCH线)导致硬故障。
IM_Dialog
谢谢你的帮助。按照您的说明,我发现pc的硬件故障原因是0x7fd11e0。
找出发生的事情是有助于的吗?
嗨,对话框中,
我本周末做了一系列测试:
1.简化了我的代码仅包括一个init函数,到init gpio和i2c异步交易,一个读取功能,从imu读取寄存器,并将其打印到UART。
2.将我的驱动程序代码移动到“Clean”BLE_PLE_PERITELAL项目,在任务开始时添加init,将计时器添加到ble_peripheral_task,然后在for for(;;)循环之前启动它,并且当任务接收计时器通知时,从i2c读取数据。
空白ble_peripheral_task (void * params)
{
Int8_t wdog_id;
ble_service_t * svc;
OS_TASK handle = NULL;
my_peripheral_init ();
......
SNS_TIMER = OS_TIMER_CREATE(“SNS”,PORTCONVERD_MS_2_TICKS(100),OS_TIMER_SUCCESS,
OS_GET_CURRENT_TASK(), sns_timer_cb); / /执行命令
os_assert(sns_timer);
OS_TIMER_START (sns_timer OS_TIMER_FOREVER);
......
if (notif & SNS_TIMER_NOTIF) {
refresh_sensor ();
}
......
但几秒钟后,uart打印停止了。当连接时,我发现该程序运行在sys_power_mgr.c的第2132行:
//暂停任何正在进行的QSPI程序/擦除操作。
if(op!= null){// 2132
dbg_set_high(flash_debug,flashdbg_suspend);
如果(qspi_check_and_suspend ()) {
op - > = true暂停;
}
DBG_SET_LOW (FLASH_DEBUG FLASHDBG_SUSPEND);
}
}
3.我尝试了另一种方法,在ble services启动后,在for(;;)之前删除sns_timer和一个无限循环:
而(1){
refresh_sensor ();
OS_DELAY (50);
}
就像之前一样,几秒钟后,UART打印停止了。当Attch时,我发现该程序在Sys_Power_Mgr.c的Line1513中运行:
/*
* 睡觉
* /
__WFI ();
/*确保代码将以尽可能快的速度执行。* /
If (!allow_entering_sleep){//修改
hw_cpm_set_hclk_div (ahb_div1);
}
4.我创建了一个新任务,比ble_peripheral_task优先级低。除了while循环什么也不做:
而(1){
refresh_sensor ();
OS_DELAY (50);
}
我得到了与3的结果相同。
所有的测试2,3,4我尝试pm_stay_alive()函数,或不启用看门狗,但得到相同的结果。
5.最后一次测试,我在下一行初始循环时,在所有BLE SEVICE开始之前。这次I2C数据读得很好!
空白ble_peripheral_task (void * params)
{
Int8_t wdog_id;
ble_service_t * svc;
OS_TASK handle = NULL;
my_peripheral_init ();
而(1){
refresh_sensor ();
OS_DELAY (50);
}
.....
似乎经常读取I2C不能与ble stack共存。有什么问题吗?
为您的回复循环。
谢谢你。
您应该能够通过I2C读取设备,并且仍然可以执行BLE操作。你能发布你正在使用的代码来初始化I2C接口和读取传感器吗?
嗨IM_Dialog,
谢谢你的回复。以下是初始化代码:
bool i2c_devices_async_init(void)
{
bool ret1 ret2;
Static const i2c_config CFG = {
.speed = hw_i2c_speed_standard,
.mode = HW_I2C_MODE_MASTER,
.ddr_mode = hw_i2c_addressing_7b,
};
hw_i2c_init(hw_i2c1,cfg);
将srand (OS_GET_TICK_COUNT ());
/*
*获取温度传感器设备的手柄。
*此调用尚未配置I2C控制器。
* /
// tpdev = ad_i2c_open(tp_mms427);
imudev = ad_i2c_open (IMU_LSM6DS3);
// magdev = ad_i2c_open(MAG_AK09915);
/*
*创建GUI用来等待I2C事务完成的事件。
*此事件将用于从GUI任务访问温度传感器或EEPROM。
* /
init_event (&i2c_signal);
// ret1 = tp_device_init();
ret2 = imu_6axes_init ();
/* ret1 = ret1 && ret2;
ret2 = mag_device_init ();
Ret1 = Ret1 && re2;
//仅进行测试
mag_set_power_mode(4);// 100Hz刷新
* /返回(ret2);
}
和刷新传感器代码,在计时器中突出的折断通知:
静态孔隙refresh_sensor(空白)
{
Int32_t imudata [6];
int16_t magdata [3];
uint8_t k1status,tpirqstatus;
uint8_t xy [2];
/ / pm_stay_alive ();
k1status = (uint8_t)hw_gpio_get_pin_status(APP_BUTTON_GPIO_PORT, APP_BUTTON_GPIO_PIN);
tpirqstatus = (uint8_t)hw_gpio_get_pin_status(TP_IRQ_GPIO_PORT, TP_IRQ_GPIO_PIN);
如果(imu_6axes_read_data (imudata)) {
printf (" IO: % d | % d Acc: % d % d % d”,k1status, tpirqstatus, (int) imudata [0], (int) imudata [1], (int) imudata [2]);
printf(“gyro:%d,%d,%d \ r \ n”,(int)imudata [3],(int)imudata [4],(int)imudata [5]);
}
/* if (tp_drv_read_coordinate(xy)) {
printf("TP:%u,%u ", xy[0], xy[1]);
}
如果(mag_device_read (magdata)) {
printf(“mag:%d,%d,%d \ r \ n”,magdata [0],magdata [1],magdata [2]);
* /
/ / pm_resume_sleep ();
}
函数imu_6axes_read_data使用imu_i2c_read函数从IMU中读取多个寄存器并计算值:
bool i2c_read(uint8_t* pBuffer, uint8_t DeviceAddr, uint8_t RegisterAddr)
uint16_t NumByteToRead)
{
Bool ret = false;
ad_i2c_device_acquire(imudev);
if(HW_I2C_ABORT_NONE != i2c_device_read_async(imudev, &RegisterAddr, pBuffer, 1, NumByteToRead, &i2c_signal))
转到退出;
ret = true;
退出:
ad_i2c_device_release(imudev);
返回受潮湿腐烂;
}
I2C读寄存器函数:与信号相关的函数与i2c_demo.c相同。
static hw_i2c_abort_source i2c_device_read_async(i2c_device dev,uint8_t * reg,const uint8_t * buf,uint8_t reglen,
Uint8_t buflen, i2c_event *event)
{
/*
*确保事件尚未处于信号状态;
* /
reset_event(事件);
/*
*写入传感器寄存器,使用回调将信号事件同步。
* /
ad_i2c_async_transact(dev, I2C_SND(reg, reglen), I2C_RCV(buf, buflen),
I2C_CB1 (signal_event、事件),I2C_END);
/*
*等待事务完成。
* /
wait_for_event(事件);
/*
*错误代码如果在事件中存储,则返回它。
* /
返回事件- >错误;
}
我需要强调,在系统停止之前,我可以成功识别并读取数十次的IMU数据。printf输出如下:
2017/1/11 10:08:05.658 [rx] -
x69 IMU XG_ID: 0
广告开始!
IO: 1 | 1 Acc: -38年,16岁,1043年,陀螺:1680,-10710,-7630
IO: 1 | 1 Acc: -38年,16岁,1041年,陀螺:1610,-10570,-7630
IO:1 | 1 ACC:-38,16,1041,陀螺仪:1680,-10640,-7630
IO: 1 | 1 Acc: -38, 17日,1040年,陀螺:1750,-10640,-7560
IO:1 | 1 ACC:-38,16,1041,陀螺仪:1680,-10640,-7630
IO:1 | 1 ACC:-38,16,1041,陀螺仪:1680,-10640,-7630
......
问候,
段
当使用I2C适配器时,你需要配置你的设备和I2C总线,方法是将以下内容添加到一个名为platform_devices.h的文件中,放置在你的config文件夹中:
当您希望初始化您进行以下呼叫的端口时:
我无法在代码中看到这些呼叫,所以我不确定您是否使用此机制,如果不是,那么我建议您相应地更改代码。您可以在以下内容中找到如何使用I2C适配器的一个很好的示例:
DA1468x_SDK_BTLE_v_1.0.8.1050.1 \ dk_apps \ demo \ \项目peripherals_demo \ demo \ demo_i2c_async.c
谢谢你的重播。
我完全遵循演示演示_i2c_async.c。设备的声明是在platform_devices.h的副本中进行的,如demo,如demo:
I2C_BUS(I2C1)
#ifdef config_imu_lsm6ds3.
/*示例温度传感器FM75 */
i2c_slave_device(i2c1,imu_lsm6ds3,0x6a,hw_i2c_addressing_7b,hw_i2c_speed_standard);
# endif
# ifdef CONFIG_MAG_AK09915
/*示例温度传感器FM75 */
I2C_SLAVE_DEVICE(I2C1, MAG_AK09915, 0x0c, HW_I2C_ADDRESSING_7B, HW_I2C_SPEED_STANDARD);
# endif
但我找不到任何初始化,如i2c_bus_init(i2c1);在演示中。所以我没有在以前的代码中添加它们。
我在init中添加宏在hardware init和devices open之间:
hw_i2c_init(hw_i2c1,cfg);
将srand (OS_GET_TICK_COUNT ());
I2C_BUS_INIT (I2C1);
i2c_device_init(imu_lsm6ds3);
i2c_device_init(mag_ak09915);
/*
*获取温度传感器设备的手柄。
*此调用尚未配置I2C控制器。
* /
// tpdev = ad_i2c_open(tp_mms427);
imudev = ad_i2c_open (IMU_LSM6DS3);
magdev = ad_i2c_open(mag_ak09915);
但结果是一样的。接下来我应该尝试什么?谢谢你!
嗨Neil.duan,
你提到你的代码卡住了,它没有卡住(没有while(1)或任何让你的代码卡住的断言),代码仍然执行(你能检查一下当代码停止时你是否能在广播中看到任何广告)。当您附加和您发现代码在这些点是因为代码通过这些点更频繁或在__WFI()情况下,它只是等待一个中断发生。你提到的硬错误是一个不同的原因,它不是BLE或适配器的原因,硬错误发生在内存中错误的访问,空指针函数的调用,内存损坏等。我建议做的是检查弗兰克-威廉姆斯与系统查看器或臭氧调试器为了检查发生了什么任务和适配器使用,也可以调查传感器和打印在一个较小的频率和检查系统无法打印。我们很难假设代码中可能出现的错误,但是因为您使用的是适配器,所以SDK应该正确地处理BLE事件和I2C事务。
谢谢mt_dialog.
我也有同样的困难的错误问题。但这只发生在其中一块板上。我有两块黑板。另一个工作得很好。
我也使用I2C适配器从I2C传感器读取温度。这个问题的解决办法是什么,,,,?有人能在这方面帮助我吗?
嗨mahmed106,
谢谢你的评论。在以下论坛主题下,我已经回复了您:
https://support.dialog-semicondiondiondiondum/forums/post/dialog-smartbond-bluetooth-low-energy-%2%80%93-software/da14681-hardfault-when-reading-i2c.
谢谢,PM_DIALOG.