嗨,对话框,我构建基于PX Reporter的应用程序,在连接到中央设备时,添加一个定时器以通过适配器从I2C总线读取数据。最奇怪的是,它在jlink JTAG模式下工作很好,但在连接后停止并单独工作时发送多个数据数据包。我使用附加功能,发现它在HW_HARD_FAULT.C的循环中结束。是什么原因?谢谢。问候。段
嗨段,
硬故障处理程序(功能文件hw\u hard\u fault.c)中的HardFault\u HandlerC将堆栈帧复制到内存中的固定位置。此堆栈帧包含许多参数,这些参数将帮助您找到硬故障的来源。首先是PC—这是发生硬故障时程序计数器的值,即它将指向正在执行的指令和导致硬故障的指令。您可以使用调试器访问PC的值。附加并找到在hardfault处理程序中执行while(1)循环的代码后,检查内存位置STATUS\u BASE+0x18-这将包含PC的值。STATUS\u BASE的值可以在hw\u hard\u fault.c文件中找到。一旦你有了电脑,你就可以找出是哪条指令(以及C代码的哪一行)导致了硬故障。
im_dialog.
谢谢你的帮助。按照您的说明,我发现硬件故障原因的PC为0x7fd11e0。找出发生了什么有帮助吗?
嗨,对话框,这个周末我做了一系列测试:1简化我的代码只包括一个初始化函数,初始化gpio和I2C异步事务,一个读取函数,从IMU读取寄存器,并打印到uart。
2将我的驱动程序代码移到一个“clean”ble_peripheral项目中,在任务开始时添加init,在ble_peripheral_任务中添加计时器,并在(;)之前启动它循环,并在任务接收计时器通知时从I2C读取数据。
void ble_peripheral_task(void * params){国际号码;ble_service_t * svc;OS_TASK句柄= null;my_peripheral_init();
...sns\u timer=OS\u timer\u CREATE(“sns”,端口转换\u MS\u 2个刻度(100),OS\u timer\u SUCCESS,(void *)os_get_current_task(),sns_timer_cb);OS\u断言(sns\u定时器);os_timer_start(sns_timer,os_timer_forever);...if(notf&sns_timer_notif){refresh_sensor();}...但几秒钟后,UART打印停止了。当Attch时,我发现该程序在Sys_Power_Mgr.c的第2132行运行://暂停任何正在进行的QSPI程序/擦除操作。如果(操作)=空){//2132DBG\u SET\u HIGH(FLASH\u DEBUG,FLASHDBG\u SUSPEND);
if(qspi_check_and_suspend()){OP->暂停=真;}
dbg_set_low(flash_debug,flashdbg_suspend);}}
3.我尝试了另一种方式,删除了SNS_Timer,然后删除了(;;)之前的无限循环,在BLE服务开始之后:而(1){refresh_sensor();os_delay(50);}就像以前一样,几秒钟后,uart打印停止了。当连接时,我发现程序在sys\u power\u mgr.c的第1513行运行:/ **睡眠* /__WFI();
/ *确保代码将以最快的速度执行。* /如果(!allow_entering_sleep){// 1513hw_cpm_set_hclk_div(ahb_div1);}4.我创建了一个新的任务,比ble_peripheral_task更低的优先级。除了循环中什么也不做:而(1){refresh_sensor();os_delay(50);}我得到了与3相同的结果。所有测试的2,3,4我尝试了pm_stay_alive()函数,或者不要启用看门狗,但同样的结果。
5最后一个测试,我把while循环放在init的下一行,在所有ble服务开始之前。这次的I2C数据读得很好!
void ble_peripheral_task(void * params){国际号码;
ble_service_t * svc;OS_TASK句柄= null;my_peripheral_init();而(1){refresh_sensor();os_delay(50);}.....
它似乎读取I2C经常无法与BLE堆叠共存。什么是问题?
循环转发你的回复。非常感谢。
您应该能够通过I2C读取设备并仍执行BLE操作。您可以发布您使用的代码,以初始化I2C接口并读取传感器。
嗨im_dialog,谢谢你尊敬地重播。这是init代码:bool i2c\u设备\u异步\u初始化(void){BOOL RET1,RET2;静态const i2c_config cfg = {.速度=HW\ I2C\速度\标准,.mode = hw_i2c_mode_master,.addr_mode=HW_I2C_寻址_7B,};
hw\u i2c\u init(hw\u 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 && Ret2;
//仅用于测试mag\ U set\ U power\ U模式(4)//100hz刷新* /返回(RET2);}以及在定时器通知中执行的刷新传感器代码:静电void refresh_sensor(void){国际货币基金组织[6];int16_t magdata [3];uint8\t k1状态,tpirqstatus;单位:8μ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);
if(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(“陀螺:%d,%d,%d\r\n”,(int)imudata[3],(int)imudata[4],(int)imudata[5]);}/ * if(tp_drv_read_coorder(xy)){printf(“tp:%u,%u”,xy [0],xy [1]);
}if(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 IMU_I2C_READ(UINT8_T * PBUFFER,UINT8_T DEVICEADDR,UINT8_TREGRARADDR,uint16_t numbytetoread){bool ret = false;
采集设备(imudev);
if(hw_i2c_abort_none!= = i2c_device_read_async(imudev,&regreadAddr,pbuffer,1,numbytetoread,&i2c_signal))转到出口;
ret=真;
出口:ad\u i2c\u设备\u释放(imudev);返回Ret;}I2C读取寄存器功能:信号相关的功能与I2C_DEMO.C中的相同。
静态硬件I2C中止源I2C设备读取异步,UINT8_T BUFLEN,I2C_EVENT *事件){/ **确保事件尚未处于信号状态;* /reset_event(事件);
/ **编写传感器寄存器,使用回调将信号发生同步。* /AD_I2C_ASYNC_TRANSACT(DEV,I2C_SND(REG,REGLEN),I2C_RCV(BUF,BUFLEN),i2c_cb1(signal_event,事件),i2c_end);/ **等待交易完成。* /等待事件(event);
/ **如果事件中存储了错误代码,则返回它。* /返回Event->错误;
我需要强调的是,在系统停止之前,我可以成功地初始化并读取数十次IMU数据。printf输出如下:
2017/1/11 10:08:05.658 [rx] -IMU XG_ID:0x69广告开始!IO:1 | 1 ACC:-38,16,1043,陀螺仪:1680,-10710,-7630IO:1 | 1 ACC:-38,16,1041,陀螺仪:1610,-10570,-7630IO:1 | 1附件:-38,161041,Gyro:1680,-10640,-7630IO:1 | 1 ACC:-38,17,1040,陀螺仪:1750,-10640,-7560IO:1 | 1附件:-38,161041,Gyro:1680,-10640,-7630IO:1 | 1附件:-38,161041,Gyro:1680,-10640,-7630...
问候,段
使用I2C适配器时需要通过将以下内容添加到名为platform_devices.h的文件来配置您的设备和I2C总线。
#如果dg_configi2c_adapterI2C\ U总线(I2C1)I2C\从设备(I2C1、设备\ A、0x20、硬件\ I2C\寻址\ 7B、硬件\ I2C\速度\标准);I2C总线端#万一
然后要初始化端口时,请进行以下调用:
i2c_bus_init(i2c1);i2c_device_init(device_a);
我在你的代码中看不到这些调用,所以我不确定你是否在使用这种机制,如果没有,我建议你相应地更改代码。下面是如何使用I2C适配器的一个很好的示例:
da1468x_sdk_btle_v_1.0.8.1050.1 \ projects \ dk_apps \ demos \ peripherals_demo \ demos \ demo_i2c_async.c
谢谢你的重播。我完全按照演示i2c\u async.c。设备的声明是在config foler中的platform_devices.h的副本中进行的,如演示:I2C\ U总线(I2C1)
#ifdef配置\u IMU \u LSM6DS3/ *实施例温度传感器FM75 * /I2C\从设备(I2C1、IMU\ LSM6DS3、0x6A、HW\ U I2C\ U寻址\U 7B、HW\ U I2C\ U速度\U标准);#万一#ifdef config_mag_ak09915./ *实施例温度传感器FM75 * /i2c_slave_device(i2c1,mag_ak09915,0x0c,hw_i2c_addressing_7b,hw_i2c_speed_standard);#万一
但是我找不到像I2C总线初始化(I2C1)这样的初始化;在演示中。所以我没有在以前的代码中添加它们。
我在硬件init和设备打开之间将宏添加宏:hw\u i2c\u init(hw\u I2C1,&cfg);srand(os_get_tick_count());i2c_bus_init(i2c1);
I2C\设备\初始化(IMU\ LSM6DS3);I2C\设备\初始化(MAG\ u AK09915);/ **拿到温度传感器装置的手柄。*此调用尚未配置I2C控制器。* ///tpdev=ad_i2c_open(TP_MMS427);imudev = ad_i2c_open(imu_lsm6ds3);magdev=ad_i2c_open(MAG_AK09915);
但同样的结果。我应该接下来怎么样?谢谢!
嗨Neil.伙伴,
你提到代码卡住的点,它没有卡住,(没有(1)或任何断言使您的代码卡住),代码仍然执行(可以检查您是否能够查看任何广告代码摊位的空气)。当您附加并且您在这些点处找到代码是因为代码经常或在__wfi()案例中浏览这些点,它只等待发生中断。您提到的硬盘是一种不同的原因,它不是一个BLE或适配器的原因,HardFaults发生在内存中未alalign的访问,对空指针函数,记忆损坏等的调用。我建议做的是检查FW通过系统查看器或臭氧调试器,检查任务和使用的适配器会发生什么,也可以轮询传感器并以较小的频率打印并检查系统是否无法打印。我们非常困难地假设代码可能出现问题,但由于您使用的适配器,SDK应该正确处理BLE事件和I2C交易。
谢谢你的对话
我也有相同的硬故障问题。但它只是在其中一个板上发生的。我总共有2个董事会。其他工作完全正常。
I M还使用I2C适配器进行I2C传感器读取温度。这个问题的解决方案是什么,,,,?任何人都可以帮助我吗?
你好,mahmed106,
谢谢你的评论。我已经在以下论坛帖子中回复了您:
https://support.dialog-semiconductor.com/forums/post/dialog-smartbond-bluetooth-low-energy-%E2%80%93-software/da14681-hardfault-when-reading-i2c
谢谢,下午好
嗨段,
硬故障处理程序(功能文件hw\u hard\u fault.c)中的HardFault\u HandlerC将堆栈帧复制到内存中的固定位置。此堆栈帧包含许多参数,这些参数将帮助您找到硬故障的来源。首先是PC—这是发生硬故障时程序计数器的值,即它将指向正在执行的指令和导致硬故障的指令。您可以使用调试器访问PC的值。附加并找到在hardfault处理程序中执行while(1)循环的代码后,检查内存位置STATUS\u BASE+0x18-这将包含PC的值。STATUS\u BASE的值可以在hw\u hard\u fault.c文件中找到。一旦你有了电脑,你就可以找出是哪条指令(以及C代码的哪一行)导致了硬故障。
im_dialog.
谢谢你的帮助。按照您的说明,我发现硬件故障原因的PC为0x7fd11e0。
找出发生了什么有帮助吗?
嗨,对话框,
这个周末我做了一系列测试:
1简化我的代码只包括一个初始化函数,初始化gpio和I2C异步事务,一个读取函数,从IMU读取寄存器,并打印到uart。
2将我的驱动程序代码移到一个“clean”ble_peripheral项目中,在任务开始时添加init,在ble_peripheral_任务中添加计时器,并在(;)之前启动它循环,并在任务接收计时器通知时从I2C读取数据。
void ble_peripheral_task(void * params)
{
国际号码;
ble_service_t * svc;
OS_TASK句柄= null;
my_peripheral_init();
...
sns\u timer=OS\u timer\u CREATE(“sns”,端口转换\u MS\u 2个刻度(100),OS\u timer\u SUCCESS,
(void *)os_get_current_task(),sns_timer_cb);
OS\u断言(sns\u定时器);
os_timer_start(sns_timer,os_timer_forever);
...
if(notf&sns_timer_notif){
refresh_sensor();
}
...
但几秒钟后,UART打印停止了。当Attch时,我发现该程序在Sys_Power_Mgr.c的第2132行运行:
//暂停任何正在进行的QSPI程序/擦除操作。
如果(操作)=空){//2132
DBG\u SET\u HIGH(FLASH\u DEBUG,FLASHDBG\u SUSPEND);
if(qspi_check_and_suspend()){
OP->暂停=真;
}
dbg_set_low(flash_debug,flashdbg_suspend);
}
}
3.我尝试了另一种方式,删除了SNS_Timer,然后删除了(;;)之前的无限循环,在BLE服务开始之后:
而(1){
refresh_sensor();
os_delay(50);
}
就像以前一样,几秒钟后,uart打印停止了。当连接时,我发现程序在sys\u power\u mgr.c的第1513行运行:
/ *
*睡眠
* /
__WFI();
/ *确保代码将以最快的速度执行。* /
如果(!allow_entering_sleep){// 1513
hw_cpm_set_hclk_div(ahb_div1);
}
4.我创建了一个新的任务,比ble_peripheral_task更低的优先级。除了循环中什么也不做:
而(1){
refresh_sensor();
os_delay(50);
}
我得到了与3相同的结果。
所有测试的2,3,4我尝试了pm_stay_alive()函数,或者不要启用看门狗,但同样的结果。
5最后一个测试,我把while循环放在init的下一行,在所有ble服务开始之前。这次的I2C数据读得很好!
void ble_peripheral_task(void * params)
{
国际号码;
ble_service_t * svc;
OS_TASK句柄= null;
my_peripheral_init();
而(1){
refresh_sensor();
os_delay(50);
}
.....
它似乎读取I2C经常无法与BLE堆叠共存。什么是问题?
循环转发你的回复。
非常感谢。
您应该能够通过I2C读取设备并仍执行BLE操作。您可以发布您使用的代码,以初始化I2C接口并读取传感器。
嗨im_dialog,
谢谢你尊敬地重播。这是init代码:
bool i2c\u设备\u异步\u初始化(void)
{
BOOL RET1,RET2;
静态const i2c_config cfg = {
.速度=HW\ I2C\速度\标准,
.mode = hw_i2c_mode_master,
.addr_mode=HW_I2C_寻址_7B,
};
hw\u i2c\u init(hw\u 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 && Ret2;
//仅用于测试
mag\ U set\ U power\ U模式(4)//100hz刷新
* /返回(RET2);
}
以及在定时器通知中执行的刷新传感器代码:
静电void refresh_sensor(void)
{
国际货币基金组织[6];
int16_t magdata [3];
uint8\t k1状态,tpirqstatus;
单位:8μ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);
if(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(“陀螺:%d,%d,%d\r\n”,(int)imudata[3],(int)imudata[4],(int)imudata[5]);
}
/ * if(tp_drv_read_coorder(xy)){
printf(“tp:%u,%u”,xy [0],xy [1]);
}
if(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 IMU_I2C_READ(UINT8_T * PBUFFER,UINT8_T DEVICEADDR,UINT8_TREGRARADDR,
uint16_t numbytetoread)
{
bool ret = false;
采集设备(imudev);
if(hw_i2c_abort_none!= = i2c_device_read_async(imudev,&regreadAddr,pbuffer,1,numbytetoread,&i2c_signal))
转到出口;
ret=真;
出口:
ad\u i2c\u设备\u释放(imudev);
返回Ret;
}
I2C读取寄存器功能:信号相关的功能与I2C_DEMO.C中的相同。
静态硬件I2C中止源I2C设备读取异步,
UINT8_T BUFLEN,I2C_EVENT *事件)
{
/ *
*确保事件尚未处于信号状态;
* /
reset_event(事件);
/ *
*编写传感器寄存器,使用回调将信号发生同步。
* /
AD_I2C_ASYNC_TRANSACT(DEV,I2C_SND(REG,REGLEN),I2C_RCV(BUF,BUFLEN),
i2c_cb1(signal_event,事件),i2c_end);
/ *
*等待交易完成。
* /
等待事件(event);
/ *
*如果事件中存储了错误代码,则返回它。
* /
返回Event->错误;
}
我需要强调的是,在系统停止之前,我可以成功地初始化并读取数十次IMU数据。printf输出如下:
2017/1/11 10:08:05.658 [rx] -
IMU XG_ID:0x69
广告开始!
IO:1 | 1 ACC:-38,16,1043,陀螺仪:1680,-10710,-7630
IO:1 | 1 ACC:-38,16,1041,陀螺仪:1610,-10570,-7630
IO:1 | 1附件:-38,161041,Gyro:1680,-10640,-7630
IO:1 | 1 ACC:-38,17,1040,陀螺仪:1750,-10640,-7560
IO:1 | 1附件:-38,161041,Gyro:1680,-10640,-7630
IO:1 | 1附件:-38,161041,Gyro:1680,-10640,-7630
...
问候,
段
使用I2C适配器时需要通过将以下内容添加到名为platform_devices.h的文件来配置您的设备和I2C总线。
然后要初始化端口时,请进行以下调用:
我在你的代码中看不到这些调用,所以我不确定你是否在使用这种机制,如果没有,我建议你相应地更改代码。下面是如何使用I2C适配器的一个很好的示例:
da1468x_sdk_btle_v_1.0.8.1050.1 \ projects \ dk_apps \ demos \ peripherals_demo \ demos \ demo_i2c_async.c
谢谢你的重播。
我完全按照演示i2c\u async.c。设备的声明是在config foler中的platform_devices.h的副本中进行的,如演示:
I2C\ U总线(I2C1)
#ifdef配置\u IMU \u LSM6DS3
/ *实施例温度传感器FM75 * /
I2C\从设备(I2C1、IMU\ LSM6DS3、0x6A、HW\ U I2C\ U寻址\U 7B、HW\ U I2C\ U速度\U标准);
#万一
#ifdef config_mag_ak09915.
/ *实施例温度传感器FM75 * /
i2c_slave_device(i2c1,mag_ak09915,0x0c,hw_i2c_addressing_7b,hw_i2c_speed_standard);
#万一
但是我找不到像I2C总线初始化(I2C1)这样的初始化;在演示中。所以我没有在以前的代码中添加它们。
我在硬件init和设备打开之间将宏添加宏:
hw\u i2c\u init(hw\u I2C1,&cfg);
srand(os_get_tick_count());
i2c_bus_init(i2c1);
I2C\设备\初始化(IMU\ LSM6DS3);
I2C\设备\初始化(MAG\ u AK09915);
/ *
*拿到温度传感器装置的手柄。
*此调用尚未配置I2C控制器。
* /
//tpdev=ad_i2c_open(TP_MMS427);
imudev = ad_i2c_open(imu_lsm6ds3);
magdev=ad_i2c_open(MAG_AK09915);
但同样的结果。我应该接下来怎么样?谢谢!
嗨Neil.伙伴,
你提到代码卡住的点,它没有卡住,(没有(1)或任何断言使您的代码卡住),代码仍然执行(可以检查您是否能够查看任何广告代码摊位的空气)。当您附加并且您在这些点处找到代码是因为代码经常或在__wfi()案例中浏览这些点,它只等待发生中断。您提到的硬盘是一种不同的原因,它不是一个BLE或适配器的原因,HardFaults发生在内存中未alalign的访问,对空指针函数,记忆损坏等的调用。我建议做的是检查FW通过系统查看器或臭氧调试器,检查任务和使用的适配器会发生什么,也可以轮询传感器并以较小的频率打印并检查系统是否无法打印。我们非常困难地假设代码可能出现问题,但由于您使用的适配器,SDK应该正确处理BLE事件和I2C交易。
谢谢你的对话
我也有相同的硬故障问题。但它只是在其中一个板上发生的。我总共有2个董事会。其他工作完全正常。
I M还使用I2C适配器进行I2C传感器读取温度。这个问题的解决方案是什么,,,,?任何人都可以帮助我吗?
你好,mahmed106,
谢谢你的评论。我已经在以下论坛帖子中回复了您:
https://support.dialog-semiconductor.com/forums/post/dialog-smartbond-bluetooth-low-energy-%E2%80%93-software/da14681-hardfault-when-reading-i2c
谢谢,下午好