我用STM32给cc2530 做seralboot升级中遇到了一个奇怪的问题, 部分设备的bootloder头(最前面的2kbytes(第一个page))被擦除了,这个现象在墨西哥和英国的有些设备中出现了这个问题,在上海地做过很多试验都没有复现(做了超过一个星期的升级,每15min升级一次), 不知道这个是否和bootloder的改动有关,请大神们帮忙看看。
zstack mesh 1.0上原来计算SB_ENABLE_CMD是每个字节每个字节读取flash的,我觉得有点慢,就改成了每512 bytes一读计算,因为本地不能复现,然后在已经出货的国外设备中出现这个问题,我们又没办法调试(把出问题的设备带回来,然后我把zigbee read back回来,发现bootloader头部被擦除了2k bytes,而且读出来出问题的两个设备读出来的数据是一样的,头部2k都擦除), 我不知道是否和电压有关,本地做了如下实验都无法复现,现在不知道什么问题,求大神们指点,帮看看有没有什么问题,谢谢:
1. 每15min给设备升级一次zigbee, 超过一个星期不能复现,
2. 每次设备run起来然后就设备断电重启,超过一个星期不能复现
我的修改如下:
/**************************************************************************************************
* @fn sbCmnd
*
* @brief Act on the SB command and received buffer.
*
* input parameters
*
* None.
*
* output parameters
*
* None.
*
* @return TRUE to indicate that the SB_ENABLE_CMD command was successful; FALSE otherwise.
**************************************************************************************************
*/
static uint8 sbCmnd(void)
{
uint16 tmp = BUILD_UINT16(sbBuf[SB_DATA_STATE], sbBuf[SB_DATA_STATE+1]) + SB_IMG_OSET;
uint16 crc[2];
uint8 len = 1;
uint8 rsp = SB_SUCCESS;
uint8 rtrn = FALSE;
switch (sbCmd2)
{
case SB_HANDSHAKE_CMD:
break;
case SB_WRITE_CMD:
if ((tmp % SB_WPG_SIZE) == 0)
{
HalFlashErase(tmp / SB_WPG_SIZE);
}
HalFlashWrite(tmp, sbBuf+SB_DATA_STATE+2, SB_RW_BUF_LEN / HAL_FLASH_WORD_SIZE);
break;
case SB_READ_CMD:
#if !MT_SYS_OSAL_NV_READ_CERTIFICATE_DATA
if ((tmp / (HAL_FLASH_PAGE_SIZE / 4)) >= HAL_NV_PAGE_BEG)
{
rsp = SB_FAILURE;
break;
}
#endif
HalFlashRead(tmp / (HAL_FLASH_PAGE_SIZE / 4),
(tmp % (HAL_FLASH_PAGE_SIZE / 4)) << 2,
sbBuf + SB_DATA_STATE + 3, SB_RW_BUF_LEN);
sbBuf[SB_DATA_STATE+2] = sbBuf[SB_DATA_STATE+1];
sbBuf[SB_DATA_STATE+1] = sbBuf[SB_DATA_STATE];
len = SB_RW_BUF_LEN + 3;
break;
case SB_ENABLE_CMD:
HalFlashRead(HAL_SB_CRC_ADDR / HAL_FLASH_PAGE_SIZE,
HAL_SB_CRC_ADDR % HAL_FLASH_PAGE_SIZE,
(uint8 *)crc, sizeof(crc));
// Bootload master must have verified extra checks to be issuing the SB_ENABLE_CMD.
//if ((crc[0] != crc[1]) && (crc[0] != 0xFFFF) && (crc[0] != 0x0000))
// if (crc[1] != crc[0])
// {
// crc[1] = crc[0];
// HalFlashWrite((HAL_SB_CRC_ADDR / HAL_FLASH_WORD_SIZE), (uint8 *)crc, 1);
// HalFlashRead( HAL_SB_CRC_ADDR / HAL_FLASH_PAGE_SIZE,
// HAL_SB_CRC_ADDR % HAL_FLASH_PAGE_SIZE,
// (uint8 *)crc, sizeof(crc));
// }
if (crc[0] != crc[1])
{
crc[1] = calcCRC();
if (crc[0] != crc[1])
{
crc[1] = recalcCRC();
}
HalFlashWrite((HAL_SB_CRC_ADDR / HAL_FLASH_WORD_SIZE), (uint8 *)crc, 1);
HalFlashRead( HAL_SB_CRC_ADDR / HAL_FLASH_PAGE_SIZE,
HAL_SB_CRC_ADDR % HAL_FLASH_PAGE_SIZE,
(uint8 *)crc, sizeof(crc));
}
// Bootload master must have verified extra checks to be issuing the SB_ENABLE_CMD.
//if ((crc[0] == crc[1]) && (crc[0] != 0xFFFF) && (crc[0] != 0x0000))
if ((crc[0] == crc[1]) && (crc[0] != 0xFFFF) && (crc[0] != 0x0000))
{
rtrn = TRUE;
}
else
{
rsp = SB_VALIDATE_FAILED;
}
break;
default:
break;
}
sbResp(rsp, len);
return rtrn;
}
/**************************************************************************************************
* @fn calcCRC
*
* @brief Run the CRC16 Polynomial calculation over the RC image.
*
* input parameters
*
* None.
*
* output parameters
*
* None.
*
* @return The CRC16 calculated.
**************************************************************************************************
*/
static uint16 calcCRC(void)
{
uint32 addr;
uint16 crc = 0;
uint32 offset = HAL_SB_IMG_ADDR;
uint16 read_size = 512;
uint8 buf[512];
uint16 i;
// Run the CRC calculation over the active body of code.
/* for (addr = HAL_SB_IMG_ADDR; addr < HAL_SB_IMG_ADDR + HAL_SB_IMG_SIZE; addr++)
{
if (addr == HAL_SB_CRC_ADDR)
{
addr += 3;
}
else
{
uint8 buf;
HalFlashRead(addr / HAL_FLASH_PAGE_SIZE, addr % HAL_FLASH_PAGE_SIZE, &buf, 1);
crc = runPoly(crc, buf);
}
}
*/
// modified by qnchen
for ( addr = offset; addr < offset + HAL_SB_IMG_SIZE; addr += read_size )
{
HalFlashRead(addr / HAL_FLASH_PAGE_SIZE, addr % HAL_FLASH_PAGE_SIZE, buf, read_size);
for ( i = 0; i < read_size; i++ )
{
// crc in 0x2090
if ( (addr - offset + i) == (HAL_SB_CRC_ADDR - HAL_SB_IMG_ADDR) )
{
i += 3;
}
else
{
crc = runPoly(crc, buf[i]);
}
}
}
// IAR note explains that poly must be run with value zero for each byte of crc.
crc = runPoly(crc, 0);
crc = runPoly(crc, 0);
return crc;
}
/**************************************************************************************************
* @fn calcCRC
*
* @brief Run the CRC16 Polynomial calculation over the RC image.
*
* input parameters
*
* None.
*
* output parameters
*
* None.
*
* @return The CRC16 calculated.
**************************************************************************************************
*/
static uint16 recalcCRC(void)
{
uint32 addr;
uint16 crc = 0;
uint32 offset = HAL_SB_IMG_ADDR;
uint16 read_size = 256;
uint8 buf[256];
uint16 i;
for ( addr = offset; addr < offset + HAL_SB_IMG_SIZE; addr += read_size )
{
HalFlashRead(addr / HAL_FLASH_PAGE_SIZE, addr % HAL_FLASH_PAGE_SIZE, buf, read_size);
for ( i = 0; i < read_size; i++ )
{
// crc in 0x2090
if ( (addr - offset + i) == (HAL_SB_CRC_ADDR - HAL_SB_IMG_ADDR) )
{
i += 3;
}
else
{
crc = runPoly(crc, buf[i]);
}
}
}
// IAR note explains that poly must be run with value zero for each byte of crc.
crc = runPoly(crc, 0);
crc = runPoly(crc, 0);
return crc;
}