困扰一周的奇葩bug:重复相似代码多,导致单片机程序跑飞
今天是個好日子,困擾一周的bug終于解決了,迫不及待將這個奇葩問題分享給各位朋友~
硬件環境:
國產MCU:華大HC32L130
問題描述:
最近做一款基于Modbus協議的三通道溫度采集模塊,程序設計是移植之前驗證過的兩通道溫度、壓力采集模塊的程序,完成后,三通道溫度采集程序可正常運行。
最后需要對三通道溫度采集模塊添加二次校準算法功能,新功能寫好后,也可正常采集和通信,但是使用IAP功能時,flash扇區擦除失敗,無法跳轉到升級程序,且程序跑飛。
問題分析和解決:
嘗試1:修改新增加的二次校準算法功能程序。
將二次校準算法功能屏蔽,升級程序可正常使用,估計是這里的問題,進行修改:變量定義、指針地址、內存管理等一系列操作下來,問題沒有解決。
此時我的排查側重點是數據內存或者地址溢出方面。
嘗試2:查看flash配置是否存在問題。
既然是flash扇區擦除失敗,會不是是配置存在問題?通過查看寄存器,修改時隙間隔等方面,還是無法解決問題,主要是之前運行一直沒問題,排除這點。
那么會不會新添加的二次校準算法功能和已經存在的功能沖突呢?或者是使用的全局結構體變量有問題?
嘗試3:整體研讀項目代碼,重點排查二次校準算法功能中全局變量、全局結構體變量的使用。
并沒有變量使用不合理或者邏輯錯誤的地方。
嘗試4:按照功能模塊屏蔽代碼,是否是程序中某部分功能與二次校準算法功能程序沖突。
通過一點點屏蔽程序,發現在二次校準算法功能程序正常運行前提下,屏蔽主循環的Modbus顯示功能、Modbus配置UART功能、傳感器GPIO配置等多個部分均可正常使用IAP功能。
通過仔細分析,這些功能模塊中變量定義和使用均不存在問題,此時心態很郁悶了,這些模塊功能基本沒有關聯。
嘗試5:通過修改某個功能模塊代碼,是否可使程序正常運行。
此時項目整體功能是不存在邏輯問題和bug的,是否可以通過將以上那些存在未知沖突故障的代碼換種寫法,讓程序正常運行呢?
經過了一系列操作和嘗試,將主循環的Modbus顯示功能代碼換種更簡潔的寫法,程序可以完美運行~
原程序如下所示:
if(nModbusCalRegs[Modbus_RegCalChan-Modbus_RegCalChan] == TEMP1_CHANNEL_ID){///< 初始化溫度傳感器:校準量程、零點偏移、靈敏度、零點偏移系數和靈敏度偏移系數nModbusCalRegs[Modbus_CalChanIndex] = strDeviceParamSave.temp1_range;memcpy((uint8_t *) <emp,(uint8_t *) &strDeviceParamSave.temp1_bias1, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalZeroIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalZeroIndex+1] = ntemp;memcpy((uint8_t *) <emp,(uint8_t *) &strDeviceParamSave.temp1_kate1, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalKateIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalKateIndex+1] = ntemp;memcpy((uint8_t *) <emp,(uint8_t *) &strDeviceParamSave.temp1_bias2, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalKZeroIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalKZeroIndex+1] = ntemp;memcpy((uint8_t *) <emp,(uint8_t *) &strDeviceParamSave.temp1_kate2, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalKSensiIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalKSensiIndex+1] = ntemp;}else if(nModbusCalRegs[Modbus_RegCalChan-Modbus_RegCalChan] == TEMP2_CHANNEL_ID){///< 初始化溫度傳感器:校準量程、零點偏移、靈敏度、零點偏移系數和靈敏度偏移系數nModbusCalRegs[Modbus_CalChanIndex] = strDeviceParamSave.temp2_range;memcpy((uint8_t *) <emp,(uint8_t *) &strDeviceParamSave.temp2_bias1, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalZeroIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalZeroIndex+1] = ntemp;memcpy((uint8_t *) <emp,(uint8_t *) &strDeviceParamSave.temp2_kate1, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalKateIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalKateIndex+1] = ntemp;memcpy((uint8_t *) <emp,(uint8_t *) &strDeviceParamSave.temp2_bias2, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalKZeroIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalKZeroIndex+1] = ntemp;memcpy((uint8_t *) <emp,(uint8_t *) &strDeviceParamSave.temp2_kate2, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalKSensiIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalKSensiIndex+1] = ntemp;}else if(nModbusCalRegs[Modbus_RegCalChan-Modbus_RegCalChan] == TEMP3_CHANNEL_ID){///< 初始化溫度傳感器:校準量程、零點偏移、靈敏度、零點偏移系數和靈敏度偏移系數nModbusCalRegs[Modbus_CalChanIndex] = strDeviceParamSave.temp3_range;memcpy((uint8_t *) <emp,(uint8_t *) &strDeviceParamSave.temp3_bias1, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalZeroIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalZeroIndex+1] = ntemp;memcpy((uint8_t *) <emp,(uint8_t *) &strDeviceParamSave.temp3_kate1, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalKateIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalKateIndex+1] = ntemp;memcpy((uint8_t *) <emp,(uint8_t *) &strDeviceParamSave.temp3_bias2, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalKZeroIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalKZeroIndex+1] = ntemp;memcpy((uint8_t *) <emp,(uint8_t *) &strDeviceParamSave.temp3_kate2, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalKSensiIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalKSensiIndex+1] = ntemp;}else{nModbusCalRegs[Modbus_CalChanIndex] = 0;nModbusCalRegs[Modbus_CalZeroIndex] = 0;nModbusCalRegs[Modbus_CalZeroIndex+1] = 0;nModbusCalRegs[Modbus_CalKateIndex] = 0;nModbusCalRegs[Modbus_CalKateIndex+1] = 0;nModbusCalRegs[Modbus_CalKZeroIndex] = 0;nModbusCalRegs[Modbus_CalKZeroIndex+1] = 0;nModbusCalRegs[Modbus_CalKSensiIndex] = 0;nModbusCalRegs[Modbus_CalKSensiIndex+1] = 0;}
優化后程序如下所示:
if(nModbusCalRegs[Modbus_RegCalChan-Modbus_RegCalChan] == TEMP1_CHANNEL_ID){temp_range = strDeviceParamSave.temp1_range;temp_bias1 = strDeviceParamSave.temp1_bias1;temp_kate1 = strDeviceParamSave.temp1_kate1;temp_bias2 = strDeviceParamSave.temp1_bias2;temp_kate2 = strDeviceParamSave.temp1_kate2;}else if(nModbusCalRegs[Modbus_RegCalChan-Modbus_RegCalChan] == TEMP2_CHANNEL_ID){temp_range = strDeviceParamSave.temp2_range;temp_bias1 = strDeviceParamSave.temp2_bias1;temp_kate1 = strDeviceParamSave.temp2_kate1;temp_bias2 = strDeviceParamSave.temp2_bias2;temp_kate2 = strDeviceParamSave.temp2_kate2; }else if(nModbusCalRegs[Modbus_RegCalChan-Modbus_RegCalChan] == TEMP3_CHANNEL_ID){temp_range = strDeviceParamSave.temp3_range;temp_bias1 = strDeviceParamSave.temp3_bias1;temp_kate1 = strDeviceParamSave.temp3_kate1;temp_bias2 = strDeviceParamSave.temp3_bias2;temp_kate2 = strDeviceParamSave.temp3_kate2;}///< 初始化溫度傳感器:校準量程、零點偏移、靈敏度、零點偏移系數和靈敏度偏移系數nModbusCalRegs[Modbus_CalChanIndex] = temp_range;memcpy((uint8_t *) <emp,(uint8_t *) &temp_bias1, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalZeroIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalZeroIndex+1] = ntemp;memcpy((uint8_t *) <emp,(uint8_t *) &temp_kate1, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalKateIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalKateIndex+1] = ntemp;memcpy((uint8_t *) <emp,(uint8_t *) &temp_bias2, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalKZeroIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalKZeroIndex+1] = ntemp;memcpy((uint8_t *) <emp,(uint8_t *) &temp_kate2, 4);ntemp = (uint16_t) ltemp;nModbusCalRegs[Modbus_CalKSensiIndex] = ntemp;ntemp = (uint16_t) (ltemp >> 16);nModbusCalRegs[Modbus_CalKSensiIndex+1] = ntemp;
哎,淚奔,回頭想想,可能是重復代碼過多,導致編譯過程存在問題,硬件開發工程師的程序bug往往出其不意,切忌先入為主,始終要保持質疑的態度呀~
總結
以上是生活随笔為你收集整理的困扰一周的奇葩bug:重复相似代码多,导致单片机程序跑飞的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言中“野指针”、“悬空指针”是什么?
- 下一篇: 单片机如何从上电复位执行到main函数?