最近一直在调试mqtt升级相关的东西,总结问题其实不大,最开始一直W25Q16擦除不干净, 然后再BootLoader程序中,校验一直出现很奇怪的问题。
然后找啊找,找原因找了好久好久。。。。。。
最后在小伙伴的帮助下 终于发现spi初始化 出现了问题,导致在第一调用spi相关的函数都失效,mmp的,最后强制在 spi初始化的时候加了一个 SPI_Flash_WAKEUP(); 函数,先调用一下,解决初始化问题。
其实问题还没有解决,还是没有明白为啥第一次调用spi相关的函数会失效。。。。后续需要继续查找。
好吧 还是记录MQTT升级相关的。
代码分析:
(1)在一个任务里,主动订阅升级任务,当平台发布升级信息后,进入接受任务,校验接受数据。
topicString.cstring = Mqtt_topic.topic_updateprocess;
len = MQTTSerialize_subscribe(buf, buflen, 0, msgid, 1, &topicString, &req_qos);
rc = transport_sendPacketBuffer(mysock, buf, len);
(2)当接受的数据为升级包后 ,订阅第一包升级包,包的大小为1024 (平台那边发过来的,接受就好)
if(UpdateMsg.DeviceTypeValue == DEVICE_TYPE_INVERTER_ARM || UpdateMsg.DeviceTypeValue == DEVICE_TYPE_INVERTER_DSP)
{
if(UpdateMsg.PackageSizeValue>2097152)
return;
if(UpdateMsg.DeviceTypeValue == DEVICE_TYPE_INVERTER_ARM) //升级 arm
{
// SPI_FLASH_Write_Enable();
for(u16 secpos=0;secpos<16;secpos++)
{
SPI_Flash_Erase_Sector(secpos); //清除前1M
}
}
else if(UpdateMsg.DeviceTypeValue == DEVICE_TYPE_INVERTER_DSP) //升级DSP
{
// SPI_FLASH_Write_Enable();
for(u16 secpos=16;secpos<32;secpos++)
{
SPI_Flash_Erase_Sector(secpos); //清楚后1M 数据
}
}
sprintf(Mqtt_topic.topic_updateprocess, update/package/%32.32s/%d",UpdateMsg.TaskIDValue,1);
MQTT_Subscrib(Mqtt_topic.topic_updateprocess); //订阅第一个固件包
UpdatePara.RetryCnt = 0;
UpdatePara.UpdateTimeout = 0;
UpdatePara.StartUpdateFlag = 1;
UpdatePara.temp_blockNum = 1;
(3)接受就是循环订阅接受 订阅接受 固件包了 ,将收到的 数据 按顺序 存放在W25Q16中,获取一次,地址加一次,同时订阅下一个 固件包。
W25QXX_Write(hex_con,ARM_Flash_Add,size_j);
ARM_Flash_Add = ARM_Flash_Add+size_j;
size_j =0 ;
UpdatePara.temp_blockNum++; //请求包数 加
sprintf(Mqtt_topic.topic_updateprocess, "update/package/%32.32s/%d", UpdateMsg.TaskIDValue, UpdatePara.temp_blockNum);
MQTT_Subscrib(Mqtt_topic.topic_updateprocess);
UpdatePara.RetryCnt = 0;
UpdatePara.UpdateTimeout = 0;
(4)在后来测试的时候,发现固件包太大,要超过1M,(原定计划是q16中前1M用于存放ARM固件,后1M用于存放DSP固件) 所以只能另外想办法。
后来发现hex文件的存储方式是以ascii的方式存储的,这就造成了内存的浪费啊,本来一个字节就可以存储的信息,非得用两字节存储,真是的。
so。。。。。。用一下方式吧hex文件转存下,大小立刻就缩小为原来的一般左右。。。
/* ???????? */
static unsigned char ChartoByte(char c)
{
if(c - 'a' >= 0) return (c - 'a' + 10);
else if(c - 'A' >= 0) return (c - 'A' +10);
else return (c - '0');
}
/* ????????????? */
static unsigned char Char2toByte(char *s)
{
return (ChartoByte(*s)*16 + ChartoByte(*(s + 1)));
}
unsigned char data_hex[1024]; //报文原始数据
unsigned char hex_con[1024]; //转换后的数据
int i=0,size_j=0; // size_j 表示转存后的大小
char misplace_temp[2]={0}; //用于存储 如果包的最后一个字节如果被分开[0]存储包的最后一个半字节 [1] 用于存下一个包的 第一个半字节
char misplace_flag = 0; //标记为,用于记录报文最后一个字节是否被分开
size_j=0;
for(i=0;i<1024;i++)
{
if(misplace_flag == 1)
{
misplace_flag = 0 ;
misplace_temp[1]=data_hex[0];
hex_con[size_j++]=Char2toByte(misplace_temp); //如果出现半字节情况,将包的第一个半字节放在缓存数组中
misplace_temp[0]=0; //清除缓存数组中的内容
misplace_temp[1]=0;
}
else
{
if((data_hex[i]==':')||(data_hex[i]==0x0d)||(data_hex[i]==0x0a))
{
hex_con[size_j++]=data_hex[i];
}
else
{
hex_con[size_j++]=Char2toByte(&data_hex[i++]);
}
if(i>1023) //如果出现半字节的情况
{
misplace_flag=1;
size_j=size_j-1;
misplace_temp[0]=data_hex[1023]; // 最后一个半字节放在缓存数组中
break;
}
}
}
其中hex文件 格式参考:http://www.cnblogs.com/libra13179/p/5821266.html
其中介绍了 hex一行中数据的意义。