嵌入式技术论坛
直播中

fanB

8年用户 1470经验值
擅长:20615
私信 关注
[问答]

使用SAL_AT组件下载文件运行过程中内存占用太大咋办

现象:使用RTT的SAL_AT组件,利用sim800c, 在阿里物联网平台进行OTA下载过程中,占用内存超大(700K的文件下载,动态内存使用最高超过600K)。下载完毕后内存全部释放。

查找问题:

看了下RTT实现机理是AT组件检查到+RECEIVE标志后,通过URC表调用回调函数,回调函数再执行at_socket.c中的at_recv_notice_cb()回调函数,使用at_recvpkt_put()将接收到的数据写入list链表上,然后使用workqueue唤醒等待接收数据的线程使用at_recvpkt_get()数据读取, 该函数读完后使用at_recvpkt_node_delete()删除链表节点并且释放内存。

在这个过程中内存申请就在urc_recv_func()函数,没接收到一个“+RECEIVE”b标志就会申请内存,因为没有释放,造成动态内存使用超高。

请教:

只要内存足够大,整个下载过程非常完整,但是过程中动态内存申请巨大。同样的应用程序,使用netdev组件转换成以太网,则没有这么大的内存消耗。

所以请教下这个占用内存超大的原理。以下是运行日志:

[172703] I/ali-ota: receive 4096 bytes, total recieve: 0 bytes
[172944] I/ali-ota: receive 4096 bytes, total recieve: 4096 bytes
[174964] I/ali-ota: receive 4096 bytes, total recieve: 8192 bytes
[175205] I/ali-ota: receive 4096 bytes, total recieve: 12288 bytes
free
memheap pool size max used size available size


ext-sram 1048576 63012 985564
heap 62816 62804 12
msh />[177267] I/ali-ota: receive 4096 bytes, total recieve: 16384 bytes
[177508] I/ali-ota: receive 4096 bytes, total recieve: 20480 bytes
[180038] I/ali-ota: receive 4096 bytes, total recieve: 24576 bytes
msh />free
memheap pool size max used size available size


ext-sram 1048576 77200 971376
heap 62816 62804 12
msh />[181498] I/ali-ota: receive 4096 bytes, total recieve: 28672 bytes
[181739] I/ali-ota: receive 4096 bytes, total recieve: 32768 bytes
msh />free
memheap pool size max used size available size


ext-sram 1048576 84220 964356
heap 62816 62804 12
msh />[183979] I/ali-ota: receive 4096 bytes, total recieve: 36864 bytes
[184220] I/ali-ota: receive 4096 bytes, total recieve: 40960 bytes
[186718] I/ali-ota: receive 4096 bytes, total recieve: 45056 bytes
[188782] I/ali-ota: receive 4096 bytes, total recieve: 49152 bytes
[189024] I/ali-ota: receive 4096 bytes, total recieve: 53248 bytes
[191181] I/ali-ota: receive 4096 bytes, total recieve: 57344 bytes
[191422] I/ali-ota: receive 4096 bytes, total recieve: 61440 bytes
[193701] I/ali-ota: receive 4096 bytes, total recieve: 65536 bytes
msh />free
memheap pool size max used size available size


ext-sram 1048576 126600 921976
heap 62816 62804 12

可以看见,从固件开始下载后,动态内存的使用往上飙升,直至下载完毕后,所有内存释放得干干净净。

回帖(7)

王萍

2022-10-26 14:24:32
调用 recv 函数接收完一段数据之后,链表中的这段数据数据应该就会被释放,sim800c 这段数据长度应该为 1.5 K 左右,内存占用这么大是一直没有调用 recv 接收数据??
举报

张娟

2022-10-26 14:24:38
PS 看下 at client 线程优先级是否比 OTA 接收固件的线程优先级高,感觉像是 client 一直在收,可是收完了没人去取
举报

fanB

2022-10-26 14:24:48
这个是我最先就想到的问题, 默认at_client的现场是9, 后面我把MQTT的现场改为8, 高于at_client线程, 但是现象依然是这样.

举报

fanB

2022-10-26 14:24:56
是这样的,关于at_recvpkt_get()和at_recvpkt_put()代码我是看了的. 但仿佛是SIM800的接收超级快, at_recvfrom()来不及接收. 造成at_socket_sim800c.c中的urc_recv_func()一直在申请内存, 造成动态内存超级大.

最开始我使用的内部内SRAM, 经常报警urc_recv_func()内部的内存申请失败. 然后使用外部SRAM后得以解决. 而后又出现resp buffer爆满, 我又增加了AT接口使用的uart驱动fifo的尺寸为8K, 问题也得以解决, 整个下载过程成功. 但是整个下载过程中,动态内存申请消耗太大, 几乎接近于下载文件的大小. 给人的感觉是at_recvpkt_get()未释放内存, 但是这部分代码看上去是没有问题的.
举报

张娟

2022-10-26 14:25:13
加大 固件接收的频率及包尺寸试试呢
举报

fanB

2022-10-26 14:25:22
加大固件的接收频率怎么做?我已经将OTA的线程优先级提到最高, 包的尺寸加大可能会加剧at_client线程的内存块申请数量, 毕竟sim800c一次性传输数据最大也就1.5K左右.

我想连接下RTT的DFS实现poll/select的方式, 按照unix/linux的机制,系统使用的fd数量就这么几个, 轮询效率也应该不会低到哪里去的. 我看wqueue_wake()实现机理是查询socket号,然后直接唤醒持有socket号的线程. 如果一个线程里面有两个或者两个以上socket, 会不会造成延时??
举报

张娟

2022-10-26 14:25:33
增加更多的日志再分析下呢,比如:每次 at client 线程收到一个报文,OTA 线程收到一个报文。看下时序关系
举报

更多回帖

发帖
×
20
完善资料,
赚取积分