recan
recan
http://yyds.recan-li.cn 一个专注于嵌入式软件架构设计的新生代农名工

注册于 7 months ago

回答
356
文章
7
关注者
12

我在实践过程中,试过2种方法,效果还不错:

方法一:利用电脑的无线热点
使用笔记本电脑开设一个无线热点,然后让终端设备连接这个热点,同时电脑开启wireshark抓取经过这个热点网卡的网络报文,做一下过滤,是可以取到终端与后台交互的网络报文的。
这种方法需要设备支持Wi-Fi通讯,有一定的局限性。

方法二:利用带网络转发的软件
在电脑上安装一些网络报文转发的软件工具,让终端先连到这个转发器,再由转发器把报文转发给真正的后端服务器,相当于转发器做了一个中间人,然后再在电脑上,使用wireshark监听网络报文,通过报文过滤,也可以把终端与真实服务器的交互报文给抓取下来。
这个方法,倒是灵活性更大,不过首先需要解决终端可以连上电脑,如果两者是在一个局域网内,自然就可以互相通讯。

以上两种方法,打算后面专门写个教程出来分享分享,毕竟这个对抓取网络报文还是非常有效的。

操作方法

gcc在编译的过程中,要实现楼主说的这种需求,一般的做法如下:
1.在编译C文件时,CFLAGS里面添加-ffunction-sections和 -fdata-sections 这两个选项;
加上之后,gcc会将每个函数或符号创建为一个sections,其中每个sections名与function或data名保持一致;
2.在执行链接过程中,LDFLAGS里面添加-gc-sections选项;
这个选项的意思就是让ld在执行链接的时候,执行section的垃圾回收,也就是没有被使用的sections,全部移除,不要放在最后的可执行文件里;
3.实践过程中发现,最好编译优化级别开-Os,针对固件尺寸比较敏感的情景下,非常有效果。

原理分析

以上设置这些编译的选项的目的就是,最终ld做回收的时候,它的基本单元是sections,所以必须使用-fdata-sections和-ffunction-sections将函数和符号拆开成一个个section,以便于最后的回收。
如果不添加这两个选项的话,那么一般来说,一个.c文件就会产生一个.o文件,而当整个.o文件都没有被调用的时候,那么它才不会最终被链接进去;否则,假设你写了100个函数而其中1个函数被调用了,那这100个函数都会被链接进去。

以上分析,希望对你有所理解和帮助。

undefined reference to "xxx"
这个编译错误是一个典型的链接错误,
与头文件无关,头文件的包含,只影响编译预处理阶段。

一个C程序的编译流程大致如下:
1.编译预处理 (头文件包含,宏定义替换等等,仅仅是文本级别的替换:.c文件变成.i文件)
2.C代码编译 (将替换后的C代码编译成汇编代码:.i文件变成.S文件)
3.汇编代码处理 (把汇编代码转出目标文件:.S文件变成.o文件)
4.目标文件链接 (将所有的目标的文件,链接成一个可执行文件: .o文件变成.elf文件或exe文件)

先使用snprintf格式化一下到字符串中,在把字符串当log用%s输出呢?

gitee上面有个开源的项目再做这个,有空可以研究看看,或许有帮助。

image.png

github上找到一个它的使用DEMO,或许可以参考下。

从技术上是可行的,重点在于SD卡地址空间的划分和管理。
如果把SD卡的存储空间,类比成一段纯粹的FLASH区域,
比如它的总大小是16MB,那么可以0-8MB的区域划做文件系统,
8MB-16MB的区域划做U盘,
这样操作SD卡的接口两边都是可以复用的,唯一不一样的就是传入的地址空间范围。
SD卡也就是一个存储载体,与FLASH存储类比好,我觉得实现起来就不难了。
以上是个人思路,希望对你有所帮助和启发。

看了你的log截图,3种情况都是发生在TLS握手阶段,
第一个错误是证书校验有误,
第二个第三个错误都可以理解成服务器关闭了握手链接。
因为TLS握手阶段涉及到非对称算法计算比如RSA运算,而这类算法属于计算密集型的操作,非常耗CPU,在没有硬件加速器的情况下,单靠软件去计算,就会比较慢。如果你的CPU处理性能本身就比较弱,那么个慢会更加明显,有时就可能导致握手失败了。
对于你的问题,联系抓取一下TLS的握手交互报文,分析下大致可以知道是什么原因。
希望能给你提供点思路。

既然是 把awtk线程加到rtthread 上 而报错的,
那么应该要重点排查你新增的这个线程。
看log,十有八九是内存相关的错误,
所以排查你的线程的时候,重点看内存相关的操作,
比如有操作malloc/free这种堆空间的,
或者全局的变量/数组这些。
如果你的发现了某个指针是异常了,可以单步调试下,
看看在什么时候这个指针被修改成异常了,
找到时间点,再分析其操作的上下文,或许有点眉目。

楼主使用的是RRT的哪个版本呢?我手上的RRT 4.0.3版本没有找到这个函数的调用:
image.png

关于RTOS的对比和选择,
可以先浏览下这个帖子
里面我也给出了一个我之前调研各个RTOS的简要总结。
不过从国内的开放生态来看,RRT不失为一个好的选择。

建议参考下RRT的ramfs官方示例教程

你给出的代码,建议排查下dfs_ramfs_create是否传参有误?
并且把这个接口的返回值打出来判断下,看接口调用成功没有?
image.png

示例的调用方法:
image.png

问题分析

首先纠正一个小问题:
image.png
这个test1字段应该是在BSS段,而不是在DATA段;
他们都是全局数据区,但是区别在于BSS段一般存放的是未初始化或初始化为0的全局变量/数组,而DATA段存放的是初始化为非0的全局变量/数组
关于你的疑问的内存分布的问题,你可以看下map文件。

以qemu-vexpress-a9为例做分析:

找到link文件关于内存分布的规划

image.png

map文件里面找到__bss_start、__bss_end、__data_start、__data_end

image.png

分析RRT关于HEAP初始化的代码 bsp/qemu-vexpress-a9/driver/board.h

image.png
可以看到HEAP_START和HEAP_END,而HEAP_START恰好就是__bss_end。
image.png
注意这里的都是还未考虑地址对齐的情况,对齐的是在init那里处理;
image.png

image.png

image.png

把以上这些地址值打出来观察,或者可以解决你的疑惑。

参考下定时器的使用示例

动态定时器的接口使用的顺序:
timer_create -> timer_start -> timer_stop -> timer_delete

动态定时器的接口使用的顺序:
timer_init -> timer_start -> timer_stop、

看了你的代码有个错误:
image.png

rt_timer_init(&Timer1, ...);  //注意第一个参数记得取地址
rt_timer_start(&Timer1); //取地址

回到
顶部

发布
问题

投诉
建议