资产监测设备之华大单片机Boot软件升级
Posted 瑞奇Ricky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了资产监测设备之华大单片机Boot软件升级相关的知识,希望对你有一定的参考价值。
近期笔者在研究如何从软件方面提升资产监测设备的性能,从而提升用户的使用体验感。
资产监测设备的主要作用是帮助用户监测设备的实时位置、实时状态避免运动中的货物出现丢失等情况。环境监测设备在智慧物流方面发挥了重要的作用,例如在运输贵重货物过程中,只需要将该设备安装在货物中,用户即可远程了解货物的位置、货物是否出现暴力扔件、以及避免货物在运输过程中的丢失。
资产监测设备中的华大单片机,对该设备的工作发挥了重要的作用。笔者的软件团队对单片机进行了软件升级。
具体流程如下:
/**
** \\brief 上位机数据帧解析及处理
**
** \\param [in] None
**
** \\retval Ok APP程序升级完成,并接受到跳转至APP命令
** \\retval OperationInProgress 数据处理中
** \\retval Error 通讯错误
**
******************************************************************************/
en_result_t Modem_Process(void)
{
uint8_t u8Cmd, u8FlashAddrValid, u8Cnt, u8Ret;
uint16_t u16DataLength, u16PageNum, u16Ret;
uint32_t u32FlashAddr, u32FlashLength, u32Temp;
if (enFrameRecvStatus == FRAME_RECV_PROC_STATUS) //有数据帧待处理, enFrameRecvStatus值在串口中断中调整
{
u8Cmd = u8FrameData[PACKET_CMD_INDEX]; //获取帧指令码
if (PACKET_CMD_TYPE_DATA == u8FrameData[PACKET_TYPE_INDEX]) //如果是数据指令
{
u8FlashAddrValid = 0u;
u32FlashAddr = u8FrameData[PACKET_ADDRESS_INDEX] + //读取地址值
(u8FrameData[PACKET_ADDRESS_INDEX + 1] << 8) +
(u8FrameData[PACKET_ADDRESS_INDEX + 2] << 16) +
(u8FrameData[PACKET_ADDRESS_INDEX + 3] << 24);
if ((u32FlashAddr >= (FLASH_BASE + BOOT_SIZE)) && (u32FlashAddr < (FLASH_BASE + FLASH_SIZE))) //如果地址值在有效范围内
{
u8FlashAddrValid = 1u; //标记地址有效
}
}
switch (u8Cmd) //根据指令码跳转执行
{
case PACKET_CMD_HANDSHAKE : //握手帧 指令码
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_OK; //返回状态为:正确
Modem_SendFrame(&u8FrameData[0], PACKET_INSTRUCT_SEGMENT_SIZE); //发送应答帧给上位机
break;
case PACKET_CMD_ERASE_FLASH : //擦除flash 指令码
if ((u32FlashAddr % FLASH_SECTOR_SIZE) != 0) //如果擦除地址不是页首地址
{
u8FlashAddrValid = 0u; //标记地址无效
}
if (1u == u8FlashAddrValid) //如果地址有效
{
u32Temp = u8FrameData[PACKET_DATA_INDEX] + //获取待擦除flash尺寸
(u8FrameData[PACKET_DATA_INDEX + 1] << 8) +
(u8FrameData[PACKET_DATA_INDEX + 2] << 16) +
(u8FrameData[PACKET_DATA_INDEX + 3] << 24);
u16PageNum = FLASH_PageNumber(u32Temp); //计算需擦除多少页
for (u8Cnt=0; u8Cnt<u16PageNum; u8Cnt++) //根据需要擦除指定数量的扇区
{
u8Ret = Flash_EraseSector(u32FlashAddr + (u8Cnt * FLASH_SECTOR_SIZE));
if (Ok != u8Ret) //如果擦除失败,反馈上位机错误代码
{
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_ERROR;
break;
}
}
if (Ok == u8Ret) //如果全部擦除成功,反馈上位机成功
{
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_OK;
}else //如果擦除失败,反馈上位机错误超时标志
{
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_TIMEOUT;
}
}
else //地址无效,反馈上位机地址错误
{
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_ADDR_ERROR;
}
Modem_SendFrame(&u8FrameData[0], PACKET_INSTRUCT_SEGMENT_SIZE); //发送应答帧到上位机
break;
case PACKET_CMD_APP_DOWNLOAD : //数据下载 指令码
if (1u == u8FlashAddrValid) //如果地址有效
{
u16DataLength = u8FrameData[FRAME_LENGTH_INDEX] + (u8FrameData[FRAME_LENGTH_INDEX + 1] << 8)
- PACKET_INSTRUCT_SEGMENT_SIZE; //获取数据包中的数据长度(不包含指令码指令类型等等)
if (u16DataLength > PACKET_DATA_SEGMENT_SIZE) //如果数据长度大于最大长度
{
u16DataLength = PACKET_DATA_SEGMENT_SIZE; //设置数据最大值
}
u8Ret = Flash_WriteBytes(u32FlashAddr, (uint8_t *)&u8FrameData[PACKET_DATA_INDEX], u16DataLength); //把所有数据写入flash
if (Ok != u8Ret) //如果写数据失败
{
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_ERROR; //反馈上位机错误 标志
}
else //如果写数据成功
{
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_OK; //反馈上位机成功 标志
}
}
else //如果地址无效
{
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_ADDR_ERROR; //反馈上位机地址错误
}
Modem_SendFrame(&u8FrameData[0], PACKET_INSTRUCT_SEGMENT_SIZE); //发送应答帧到上位机
break;
case PACKET_CMD_CRC_FLASH : //查询flash校验值 指令码
if (1u == u8FlashAddrValid) //如果地址有效
{
u32FlashLength = u8FrameData[PACKET_DATA_INDEX] +
(u8FrameData[PACKET_DATA_INDEX + 1] << 8) +
(u8FrameData[PACKET_DATA_INDEX + 2] << 16) +
(u8FrameData[PACKET_DATA_INDEX + 3] << 24); //获取待校验flash大小
if ((u32FlashLength + u32FlashAddr) > (FLASH_BASE + FLASH_SIZE)) //如果flash长度超出有效范围
{
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_FLASH_SIZE_ERROR; //反馈上位机flash尺寸错误
}else
{
u16Ret = Cal_CRC16(((unsigned char *)u32FlashAddr), u32FlashLength);//读取flash指定区域的值并计算crc值
u8FrameData[PACKET_FLASH_CRC_INDEX] = (uint8_t)u16Ret; //把crc值存储到应答帧
u8FrameData[PACKET_FLASH_CRC_INDEX+1] = (uint8_t)(u16Ret>>8);
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_OK; //反馈上位机成功 标志
}
}
else //如果地址无效
{
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_ADDR_ERROR; //反馈上位机地址错误
}
Modem_SendFrame(&u8FrameData[0], PACKET_INSTRUCT_SEGMENT_SIZE+2); //发送应答帧到上位机
break;
case PACKET_CMD_JUMP_TO_APP : //跳转至APP 指令码
Flash_EraseSector(BOOT_PARA_ADDRESS); //擦除BOOT parameter 扇区
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_OK; //反馈上位机成功
Modem_SendFrame(&u8FrameData[0], PACKET_INSTRUCT_SEGMENT_SIZE); //发送应答帧到上位机
return Ok; //APP更新完成,返回OK,接下来执行跳转函数,跳转至APP
case PACKET_CMD_APP_UPLOAD : //数据上传
if (1u == u8FlashAddrValid) //如果地址有效
{
u32Temp = u8FrameData[PACKET_DATA_INDEX] +
(u8FrameData[PACKET_DATA_INDEX + 1] << 8) +
(u8FrameData[PACKET_DATA_INDEX + 2] << 16) +
(u8FrameData[PACKET_DATA_INDEX + 3] << 24); //读取上传数据长度
if (u32Temp > PACKET_DATA_SEGMENT_SIZE) //如果数据长度大于最大值
{
u32Temp = PACKET_DATA_SEGMENT_SIZE; //设置数据长度为最大值
}
Flash_ReadBytes(u32FlashAddr, (uint8_t *)&u8FrameData[PACKET_DATA_INDEX], u32Temp); //读flash数据
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_OK; //反馈上位机成功 标志
Modem_SendFrame(&u8FrameData[0], PACKET_INSTRUCT_SEGMENT_SIZE + u32Temp);//发送应答帧到上位机
}
else //如果地址无效
{
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_ADDR_ERROR; //反馈上位机地址错误 标志
Modem_SendFrame(&u8FrameData[0], PACKET_INSTRUCT_SEGMENT_SIZE); //发送应答帧到上位机
}
break;
case PACKET_CMD_START_UPDATE : //启动APP更新(此指令正常在APP程序中调用)
u8FrameData[PACKET_RESULT_INDEX] = PACKET_ACK_OK; //反馈上位机成功 标志
Modem_SendFrame(&u8FrameData[0], PACKET_INSTRUCT_SEGMENT_SIZE); //发送应答帧到上位机
break;
}
enFrameRecvStatus = FRAME_RECV_IDLE_STATUS; //帧数据处理完成,帧接收状态恢复到空闲状态
}
return OperationInProgress; //返回,APP更新中。。。
}
同样从事软件工作相关的用户,对资产监测设备感兴趣的话可以参考该文档。
以上是关于资产监测设备之华大单片机Boot软件升级的主要内容,如果未能解决你的问题,请参考以下文章