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

注册于 5 months ago

回答
212
文章
2
关注者
3

看了下ipv4_nat.c,它的DEBUG使用的debug.h的定义,
image.png
image.png
如果你需要看ipv4_nat.c的DEBUG,还需要打开LWIP_NAT_DEBUG
image.png

啊,有些不可思议;
rt_sem_take()应该是一个应用非常广泛的接口,
不应该会出这种致命命题,
建议参考文档,排查上是否有接口使用流程上的时序问题?

这个问题看样子像是前后版本的兼容问题。
查一下struct rt_delayed_work结构体的定义,头文件包含。

请问下,你的具体问题或疑问是什么?似乎没有说清楚?

搜索了下“memory allocation failed”,
没找到关键代码,
建议你看下你的对应的报错代码。
从qemu-vexpress-a9的map文件可以看出,
它的RAM内存并没有严格限制,
应该它都是通过PC的RAM环境来模拟的,
并不是真实的硬件RAM空间。

看这个报错位置,是创建memory pool就失败了。
image.png
其他几个启动脚本有试过吗?
image.png
我印象中调试这个qemu-vexpress-a9,就装qemu环境卡壳了一下,其他还挺顺利的,
不过我用的是qemu-nographic.sh脚本启动的,其他两个在我的环境下启动都会失败。

针对这个问题,可以简单看下rt_timer_start的源码实现:
image.png
image.png
从代码可以看出,多次start就是相当于timer复位重新计时了。
如果说你的任务里面会多次调用到rt_timer_start,
那么你需要考虑下这是不是你需要的逻辑,因为这有可能你的timer一直没法超时,
也就是你的timer-callback会一直没法执行,确认下这个是不是你想要的。

我想到有一种场景,是可以timer一直不超时的,比如接收数据超时定时器,
当我发送出去了,我开始去收了,我就start timer开始计时,然后在超时到来之前,
我就收到了我想要的报文,这个时候你可以stop timer,而不是re-start timer。

给我的感觉是,楼主对“任务调度切换的时机”理解不是很深刻,
说白了就是没有理解好,到底是什么时候发生任务切换的。
从楼主的理解“线程B一直占着CPU呢,调度器怎么执行啊”就可以看出来。
理论上说,每发生一次systick中断,都有可能触发一次任务切换,
具体如何切换,切换到哪个任务运行,取决于任务调度算法的实现。
另外,线程B只要不是while(1);这种死跑,CPU就不会被它一直占着。
以上是个人理解,欢迎大家指正。

我认为没有什么东西是脚本没办法执行的,
IDE只是把脚本化的东西可视化了,
只需要配置相关的编译脚本,
就可以完成你需要的编译前/中/后,
甚至是任意位置执行的任意操作。

SPI是一种全双工的数据交换协议,它内部是通过移位寄存器来实现的,也就是说你在发数据的同时也在收数据。
参考文档
SPI 以主从方式工作,通常有一个主设备和一个或多个从设备。通信由主设备发起,主设备通过 CS 选择要通信的从设备,然后通过 SCLK 给从设备提供时钟信号,数据通过 MOSI 输出给从设备,同时通过 MISO 接收从设备发送的数据。
RRT中定义的SPI接口有:
image.png
一般都是收发同时操作。
如果想实现你所说的,收完了数据要(callback)执行一个应用层的逻辑,可能需要额外去实现。

USB虚拟串口接收有问题,具体是什么问题呢?
有没有相关log或者可以辅助排查的信息?
当靠一张menuconfig的配置图,啥有效信息都无法提供。

你可以打开一个shell脚本看一下,里面就是调用了qemu-system-arm
你可以试下直接运行qemu-system-arm
看会不会有输出,正常应该类似如下输出:
image.png
如果没有输出,那可以初步判断你的qemu环境没有安装好,排查下吧。

FAT文件系统在频繁断电的时候是很容易出问题的,尤其当它需要更新FAT表头的时候,如果掉电了,就直接损坏了FAT文件系统,导致无法正常挂载。
需要使用其他的方法规避下异常掉电对数据的破坏。

要解决这问题,首先得明白INIT_DEVICE_EXPORT的实现原理,
它是一个宏定义,在include/rtdef.h里面定义的,如下:
image.png

追溯到INIT_EXPORT,本质就是顶一个init-object,然后编译时放在指定的SECTION: .rti_fn里面,
以gcc编译环境为例,如下:
image.png

再到一个具体的bsp,以bsp/qemu-vexpress-a9为例,在它的链接脚本里面有:
image.png
这个SORT就是把里面的段按名称排序,因为定义段的时候引入数字,所有顺序就是.rti_fn.0 .rti_fn.1 .rti_fn.2 .rti_fn.3 .rti_fn.4 .rti_fn.5 .rti_fn.6这样,而INIT_DEVICE_EXPORT用的level3。
举个例子,如果按照你给的lcd和pwm,那应该会lcd在pwm的前面。
而这个顺序直接就决定了obj-init的顺序,实现代码见src/components.c
里面的注释里面有提到:
image.png

真正执行初始化的代码时在,本c文件的rt_components_board_init函数和rt_components_init函数
image.png

ta它的核心实现就是从段里面遍历一个个obj,然后取出obj对应的init函数指针,执行初始化。
所以段在里面的顺序就是init的执行顺序,这点可以在map文件中可以看到谁先谁后。
以我的为例:
image.png

那么问题来了,如果在同一个level的,顺序是怎么样的呢?
由于最后的init函数指针是进入到代码段的,所以谁(C文件)参与编译,谁就先被链接到指定的段里面,那么它的地址就靠前,就有点像FIFO结构那种感觉。

综上,要解决你的需求,如果不想改init-level,那么可以考虑从C文件的编译顺序来考虑,而C文件的编译顺序,跟C文件在目录和文件名是有关系的,可以去实践下。
建议在实践过程中,把init的过程打印出来,或者直接把RT_DEBUG_INIT宏打开。

以上,希望能帮助到你。

回到
顶部

发布
问题

投诉
建议