Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
Bootloader
使用Air720H 进行OTA升级,下载数据异常
发布于 2020-02-11 21:13:49 浏览:3390
订阅该版
* 本帖最后由 面码1314 于 2020-2-11 21:14 编辑 * 采用4G模块Air720H 通过HTTP进行下载固件升级。未采用webclient组件,采用了AT指令的形式。 1.使用串口调试助手和Air720H通信 通过AT指令成功获取到 HTTP服务器上的固件。具体如下: ![1.png](/uploads/202002/11/203243fwr5isscu5dcizv5.png) 通过AT指令 AT+HTTPACTION=0 获取到了整个固件的大小字节 +HTTPACTION: 0,200,92240 固件一共92240字节。 通过AT指令 AT+HTTPREAD=0,100 获取固件的起始的前100个字节,而 RBLk??^app2.0.000010203040506070809`?荱{qa苎餲噗?%2? 就是获取到的固件前100字节。 串口调试助手和Air720H通信测试正常。 2. 使用AT组件在程序中进行通信 经过一系列AT指令设置Air720H后,都是成功的。 最后两个AT指令 分别为获取固件大小 和 下载固件 运行结果如下: ![2.png](/uploads/202002/11/204841ajbqyexljydvlqqw.png) 通过 1 可以知道成功获取到了固件大小 +HTTPACTION: 0,200,92240 获取到固件大小为92240字节 (和 串口调试助手测试的一致)。 通过 2 可以看出向 服务器请求获取固件的前100字节 。 第3个圈 是这次请求返回的所有数据 。 正常情况下 第3行应该是 固件的前100字节的数据。但是可以看出返回的数据是 06070809 而不是之前使用串口调试助手返回的 RBLk??^app2.0.000010203040506070809`?荱{qa苎餲噗?%2? 的数据。 感觉返回的数据是其中的一段。 以下是上面两个命令AT指令的代码部分 ``` resp = at_create_resp(200, 4, rt_tick_from_millisecond(5000)); /* 创建响应结构体*/ /*获取HTTP 状态码, 由远端服务器响应 200确定(OK) 获取请求下载总大小 */ /* AT+HTTPACTION=0 GET 开始 OK +HTTPACTION: 0,200,92240 */ if (at_exec_cmd(resp,"AT+HTTPACTION=0") != RT_EOK) { LOG_E("AT+HTTPACTION=0, send commands failed , response error or timeout !"); return -RT_ETIMEOUT; } /*提取固件的大小*/ resp__buf_data=at_resp_get_line_by_kw(resp,"+HTTPACTION:"); at_resp_parse_line_args(resp, 4,"+HTTPACTION: %d,%d,%d", &num1, &resp_status, &file_size); LOG_I("%d,%d,%d",num1, resp_status, file_size); /*HTTP 服务器响应状态是否正确*/ if (resp_status != 200) { LOG_E("webclient GET request failed, response(%d) error.", resp_status); ret = -RT_ERROR; } at_delete_resp(resp); /*删除响应结构体*/ resp = at_create_resp(1024, 0, rt_tick_from_millisecond(4000)); /* 创建响应结构体*/ if(resp == NULL) { LOG_E(" create HTTP resp no memory"); } /*请求下载固件的前100字节*/ if (at_exec_cmd(resp,"AT+HTTPREAD=0,100") != RT_EOK) { LOG_E("AT+HTTPACTION=0, send commands failed , response error or timeout !"); return -RT_ETIMEOUT; } resp__buf_data=at_resp_get_line_by_kw(resp,"+HTTPREAD:"); LOG_I("%s",resp__buf_data); if(resp__buf_data==RT_NULL) { LOG_E("no +HTTPREAD:"); } /* 按行数循环打印接收到的响应数据 */ { const char *line_buffer = RT_NULL; LOG_D("Response buffer"); for(rt_size_t line_num = 1; line_num <= resp->line_counts; line_num++) { if((line_buffer = at_resp_get_line(resp, line_num)) != RT_NULL) { LOG_E("line %d buffer : %s", line_num, line_buffer); } else { LOG_E("Parse line buffer error!"); } } }``` 其中还遇到了另外一个问题, 在请求下载固件AT指令前如果先进行了 对 download 分区擦除下载分区 。那么将会出现以下情况。 ![3.png](/uploads/202002/11/210348nq1c5fwqwbc61uqw.png) 可以看到 依然获取到了待下载固件文件的大小 并找到了download分区,并成功擦除了分区 但是从最后的打印数据来看 似乎没有自己想要的固件数据 ,甚至可以说什么返回数据都没。 这部分代码如下 ,仅仅在 获取云端固件大小 和 下载固件两个操作中间加上了 一段擦除download分区。 ``` resp = at_create_resp(200, 4, rt_tick_from_millisecond(5000)); /* 创建响应结构体*/ /*获取HTTP 状态码, 由远端服务器响应 200确定(OK) 获取请求下载总大小 */ /* AT+HTTPACTION=0 GET 开始 OK +HTTPACTION: 0,200,92240 */ if (at_exec_cmd(resp,"AT+HTTPACTION=0") != RT_EOK) { LOG_E("AT+HTTPACTION=0, send commands failed , response error or timeout !"); return -RT_ETIMEOUT; } /*提取固件的大小*/ resp__buf_data=at_resp_get_line_by_kw(resp,"+HTTPACTION:"); at_resp_parse_line_args(resp, 4,"+HTTPACTION: %d,%d,%d", &num1, &resp_status, &file_size); LOG_I("%d,%d,%d",num1, resp_status, file_size); /*HTTP 服务器响应状态是否正确*/ if (resp_status != 200) { LOG_E("webclient GET request failed, response(%d) error.", resp_status); ret = -RT_ERROR; } at_delete_resp(resp); /*删除响应结构体*/ /************************添加擦除 下载分区代码 ***************************/ // /*获取总共固件大小 合理性检测*/ rt_kprintf("http file_size:%d
",file_size); if (file_size == 0) { LOG_E("Request file size is 0!"); ret = -RT_ERROR; } else if (file_size < 0) { LOG_E("webclient GET request type is chunked."); ret = -RT_ERROR; } /* 获取下载分区信息并删除下载分区数据 */ /* Get download partition information and erase download partition data */ if ((dl_part = fal_partition_find("download")) == RT_NULL) { LOG_E("Firmware download failed! Partition (%s) find error!", "download"); ret = -RT_ERROR; } LOG_I("Start erase flash (%s) partition!", dl_part->name); /* 擦除下载分区 */ if (fal_partition_erase(dl_part, 0, file_size) < 0) { LOG_E("Firmware download failed! Partition (%s) erase error!", dl_part->name); ret = -RT_ERROR; } LOG_I("Erase flash (%s) partition success!", dl_part->name); buffer_read = rt_malloc(HTTP_OTA_BUFF_LEN); /*申请4k存储空间*/ if (buffer_read == RT_NULL) { LOG_E("No memory for http ota!"); ret = -RT_ERROR; } memset(buffer_read, 0x00, HTTP_OTA_BUFF_LEN); LOG_I("OTA file size is (%d)", file_size); /************************添加擦除 下载分区代码结束段 ***************************/ resp = at_create_resp(1024, 0, rt_tick_from_millisecond(4000)); /* 创建响应结构体*/ if(resp == NULL) { LOG_E(" create HTTP resp no memory"); } /*请求下载固件的前100字节*/ if (at_exec_cmd(resp,"AT+HTTPREAD=0,100") != RT_EOK) { LOG_E("AT+HTTPACTION=0, send commands failed , response error or timeout !"); return -RT_ETIMEOUT; } resp__buf_data=at_resp_get_line_by_kw(resp,"+HTTPREAD:"); LOG_I("%s",resp__buf_data); if(resp__buf_data==RT_NULL) { LOG_E("no +HTTPREAD:"); } /* 按行数循环打印接收到的响应数据 */ { const char *line_buffer = RT_NULL; LOG_D("Response buffer"); for(rt_size_t line_num = 1; line_num <= resp->line_counts; line_num++) { if((line_buffer = at_resp_get_line(resp, line_num)) != RT_NULL) { LOG_E("line %d buffer : %s", line_num, line_buffer); } else { LOG_E("Parse line buffer error!"); } } } ``` 各位网友帮我提提意见,接下来我应该如何调试
查看更多
26
个回答
默认排序
按发布时间排序
面码1314
2020-02-11
这家伙很懒,什么也没写!
[i=s] 本帖最后由 面码1314 于 2020-2-11 22:28 编辑 [/i] 继续测试发现,突然想起之前重新使用 ENV后忘了改串口缓存大小 修改 打印串口大小 RT_SERIAL_RB_BUFSZ = 2048 自己用于AT指令的客户端 串口大小已经设置为 5632 ``` int at_client_uart2_init(void) { #define AT_CLIENT_RECV_BUFF_LEN 5632 /*串口2接收缓存*/ #define AIR720_UART "uart2" rt_int32_t error_num = 0; error_num=at_client_init(AIR720_UART, AT_CLIENT_RECV_BUFF_LEN); /*配置at客户端*/ return error_num; } INIT_DEVICE_EXPORT(at_client_uart2_init); /*外设驱动类自动初始化*/ ``` 接着继续调试测试 ,发现加上 对download分区的擦除代码后,AT指令获取服务器固件数据有了。 但是 只有开头的3个字母 RBL 恰好是固件未乱码数据部分的开头 RBLk??^app2.0.000010203040506070809`?荱{qa苎餲噗?%2? [attach]13591[/attach] 同时还发现个问题 ,此条AT指令响应结构体设置的为 resp = at_create_resp(1024, 0, rt_tick_from_millisecond(4000)); 意思是,在未超时的情况下,只有收到 OK 或者 ERROR 才会认为接收完毕。 但是最后打印的所有接收数据缺没有 OK 或ERROR。 现在我就觉得是不是数据乱码的问题导致的。 测试: 上传了一个文件文件 进行下载打印前100字节 [attach]13594[/attach] 下载 结果如下 [attach]13593[/attach] 通过1知道了文本 大小126字节 通过2知道 成功下载了前100字节 通过3知道 得到了响应的OK 难道真的是数据格式的问题? 如果是接下来应该怎么办呢
面码1314
2020-02-11
这家伙很懒,什么也没写!
继续调试 ``` /*请求下载固件的前100字节*/ if (at_exec_cmd(resp,"AT+HTTPREAD=0,100") != RT_EOK) { LOG_E("AT+HTTPACTION=0, send commands failed , response error or timeout !"); return -RT_ETIMEOUT; } resp__buf_data=at_resp_get_line_by_kw(resp,"RBL"); LOG_I("%s",resp__buf_data); if(resp__buf_data==RT_NULL) { LOG_E("no RBL"); } ulog_hexdump(LOG_TAG, 16, (rt_uint8_t *)resp__buf_data, 100); ``` 使用 ulog_hexdump(LOG_TAG, 16, (rt_uint8_t *)resp__buf_data, 100); 将 数据进行16进制的形式打印。 得到了如下数据 [attach]13596[/attach] 使用UltraEdit 以十六进制 打开源文件 对比 [attach]13597[/attach] 一致诶 。数据没错 明天继续搞 下载进去看行不行,看能升级不
fhqmcu
认证专家
2020-02-14
个人博客:https://blog.csdn.net/fhqlongteng
没有详细看完,太多了。在使用AT指令读取下载固件的不能使用正常的at指令发送,接收应答的方式,这是因为固件中数据变成了AT指令的应答,固件什么数据都有,比如是OK, ERROR,\r,\n这样的数据,这些数据会导致AT模块代码分析AT指令的应答时产生错误,你的问题原因出在这里。 告诉你修改的方法。读取固件代码的函数中只发送AT指令,等待一个信号, 对于这条AT指令的返回的数据,使用的urc数据的方式处理,参考模块底层驱动代码中模块接收TCP连接数据时,处理接收数据的方法来实现,接收到数据后发送一个信号给等待信号的函数。
面码1314
2020-02-14
这家伙很懒,什么也没写!
>没有详细看完,太多了。在使用AT指令读取下载固件的不能使用正常的at指令发送,接收应答的方式,这是因为固 ... --- 感谢你提供的解决办法。 ;P确实遗漏了关于固件里面什么数据都可能存在的情况。
面码1314
2020-02-16
这家伙很懒,什么也没写!
>没有详细看完,太多了。在使用AT指令读取下载固件的不能使用正常的at指令发送,接收应答的方式,这是因为固 ... --- 感谢提供的思路和解决方案。已经成功解决之前遇到过的有时无论怎么升级都不能成功的问题。现在测试,已经可以稳定连续升级10个版本了。:lol:lol
yc985055
2020-04-10
这家伙很懒,什么也没写!
楼主,你好!我也是用STM32F1+Air720H来做升级的。 1.片内(512K)分区#define FAL_PART_TABLE \ { \ {FAL_PART_MAGIC_WROD, "bl", "onchip_flash", 0, 32 * 1024, 0}, \ {FAL_PART_MAGIC_WROD, "app", "onchip_flash", 32*1024, 196 * 1024, 0}, \ {FAL_PART_MAGIC_WROD, "download", "onchip_flash", 228*1024 , 196 * 1024, 0}, \ } 升级前先用仿真器烧录bootloader和app初始版本。 升级过程如下: 1.用仿真器烧录bootloader(未加密)和app的初始版本, 2.然后程序启动http下载升级文件到download区域. 下载前: if ((dl_part = fal_partition_find("download")) == RT_NULL) { rt_kprintf("find download partion fail!\r\n"); } else { if (fal_partition_erase(dl_part, 0, 196 * 1024) < 0) { rt_kprintf("erase download partion fail!\r\n"); } } 下载过程中(写入文件): fal_partition_write(dl_part, (uint32_t)(http_size_conts * HTTP_SIZE_PER_PKT), pDataBuf, dataLen); 3.下载完成,系统复位。 rt_hw_cpu_reset(); 目前是升级失败的,问题如下: 1.首次烧录的app文件需要通过rt_ota_packaging_tool处理后再用仿真器烧录吗? 2.fal_partition_write和fal_partition_erase是否能直接用stm32_flash_wirte和stm32_flash_erase来替换。 3.升级失败的可能原因是?
小小李sunny
2020-04-10
这家伙很懒,什么也没写!
>楼主,你好!我也是用STM32F1+Air720H来做升级的。 1.片内(512K)分区#define FAL_PART_TABLE ... --- 1.用调试器烧录APP文件时,不用处理,跟平常烧写一样,不过要确保烧录地址正确; 3.你得贴出来升级失败的日志是啥才能查原因啊。
yc985055
2020-04-11
这家伙很懒,什么也没写!
>1.用调试器烧录APP文件时,不用处理,跟平常烧写一样,不过要确保烧录地址正确; >3.你得贴出来升级失败的 ... --- 开始是数据没有写入到download(内部flash-0x39000) ,后来修改http下载,确定下载到download位置(0x39000)的数据是正确并且完整(对比了升级文件rtthread.bin)。但重启cpu没有覆盖现有的app.。 估计是bootloader里面没有把download拷贝到app位置,原因还在查。在反复读这篇文档,看是不是哪个步骤没设置对. [https://www.rt-thread.org/document/site/application-note/system/rtboot/an0028-rtboot/](https://www.rt-thread.org/document/site/application-note/system/rtboot/an0028-rtboot/)
yc985055
2020-04-11
这家伙很懒,什么也没写!
补充描述一下:我是用官方链接[http://iot.rt-thread.com](http://iot.rt-thread.com)生成的bootloader。然后烧录自己的app, 在app程序里面用air720下载升级文件到download,下载完成后立即复位mcu。 按理bootloader应该自动判断比较app<->download中的数据,决定是否需要更新。 如果再不找不到原因,只用自己找bootloader代码修改了。
面码1314
2020-04-11
这家伙很懒,什么也没写!
>补充描述一下:我是用官方链接http://iot.rt-thread.com生成的bootloader。然后烧录自己的app, 在app程序里 ... --- 我没有采用官网的http例程下载,我是直接使用的AIr720H的HTTP的AT指令集进行下载的。
撰写答案
登录
注册新账号
关注者
0
被浏览
3.4k
关于作者
面码1314
这家伙很懒,什么也没写!
提问
23
回答
41
被采纳
1
关注TA
发私信
相关问题
1
Linux下通过USBTinyISP为Arduino开发板烧?写Bootloader
2
请教修改NVIC后RTT调度函数失效的问题[已解决 bootloader中打开了不必要的中断]
3
进入bootloader的方式探讨
4
求助:IAP里的APP使用的RTT,跳转后出错。[已解决]
5
有没有人在STM32F103上用UART IAP跑过RT-Thread?
6
想做网口的IAP远程升级,不知可不可行
7
IAP问题
8
[已解决]请教基于RTT的IAP程序切换到应用程序不成功的问题(基于STM32F4)?
9
stm32f4xx-----IAP移植APP程序需要注意的地方
10
在调试IAP网络升级遇到跳转之后bootloader程序网络不通
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
机器人操作系统 (ROS2) 和 RT-Thread 通信
4
国产MCU移植系列教程汇总,欢迎查看!
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
milk-v duo RT-Thread 网络示例
2
vscode出现“scons : 无法将“scons”项识别为 cmdlet、函数、脚本文件或可运行程序的名称”问题解决方法
3
星火一号 音频驱动使用
4
英飞凌XMC7200评测 -SPI
5
记录第一次pr遇到的问题总结
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
ART-Pi
CAN总线
FinSH
USB
文件系统
DMA
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
ota在线升级
WIZnet_W5500
I2C_IIC
UART
flash
packages_软件包
cubemx
PWM
freemodbus
潘多拉开发板_Pandora
BSP
定时器
ADC
中断
flashDB
socket
Debug
GD32
编译报错
msh
at_device
rt_mq_消息队列_msg_queue
keil_MDK
ulog
C++_cpp
SFUD
本月问答贡献
踩姑娘的小蘑菇
11
个答案
2
次被采纳
张世争
6
个答案
2
次被采纳
红枫
2
个答案
2
次被采纳
rv666
2
个答案
2
次被采纳
梦笑真美
12
个答案
1
次被采纳
本月文章贡献
大龄码农
1
篇文章
10
次点赞
530china
1
篇文章
3
次点赞
螺丝松掉的人
1
篇文章
3
次点赞
zhp123
1
篇文章
3
次点赞
ljcjames
1
篇文章
3
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部