- 本次采用的os是freertos,基于stm32f407zgt6
- 移植过程及代码
代码分析
startup_stm32f407xx.s
Reset_Handler
初始化栈
从flash 上 加载data 段入sram
清bss段
SystemInit
__libc_init_array
main
$ nm build/startup_stm32f407xx.o |grep " U "
U _ebss
U _edata
U _estack
U __libc_init_array
U main
U _sbss
U _sdata
U _sidata
U SystemInit
main
xTaskCreate(start_task)
vTaskStartScheduler
start_task
taskENTER_CRITICAL
task1_task
task2_task
taskEXIT_CRITICAL
task1_task
while(1)
task2_task
while(1)
-------------
1. 首先创建了一个任务A
2. 然后开始调度
3. A开始执行
4. A创建了两个任务B C ,并删除了任务A
5. B 开始执行
6. B结束执行,C 开始执行
7. C结束执行,B 开始执行
8. B结束执行,C 开始执行
9. ...
分析到 6 应该能分析完所有系统做的内存相关的动作.这里面包括了所有状态下的调度.
3中的 A 开始执行
5中的 B 开始执行
6中的 C 开始执行
从其他角度分析
os管理内存的话
1. 为 os 提供 api 和 内存空间
1. os的正常运行需要内存
1.1 os的 各个段
.code
.data
.ro-data
.bss
.stack
.heap
1.2 调度器
1.3 消息队列
1.4 定时器
2. 为 user space 提供 api和内存空间
1. os 需要维护应用程序的状态(TCB和STACK)
2.1 为了提供应用程序需要的各个段做了什么
用户使用内存的话
1. 使用 os 提供的malloc 函数 操作 os 提供给应用程序的空间.
1.1 应用程序的各个段在哪里
1.2 应用程序什么时候用了哪个段
运行的时候
.code 从 flash 加载,通过TCB中的PC控制
.ro-data 直接在.code中,通过.code索引
.data 在 ram ,通过 .code 索引
.bss 在 ram ,通过.code 索引
.stack 在 ram ,通过TCB中的SP索引
.heap 在 ram ,通过malloc索引
不运行的时候
.code 对应的PC放在了 TCB 中,其他进程不能访问该进程TCB,也就访问不了该进程的.code
.ro-data 在 .code中
.data .bss 在ram中,其他进程没有 索引(索引在.code中)
.stack 对应的SP被放在了TCB中,其他进程不能访问该进程TCB,也就访问不了该进程的.stack
.heap 在 ram 中,已经被malloc过,未被free,其他进程不能malloc到该进程的.heap
------------------------------
按照stm32 freertos来说
系统的.code(调度器) .ro-data .data .bss .heap 和 应用程序的.code(功能函数) .ro-data .data .bss .heap 是在一块的
系统的.stack 和 应用程序的.stack 是分离的.
且 .code .ro-data 在flash上
.data .bss .heap .stack 在内存里
另外内存里还有每个进程的TCB
所以整体来说,大小的话
初始化的时候 .data .bss 是初始化好的,占用的内存可以通过map来查看
另外只要知道 .heap(可以通过配置来查看) .stack(可以通过配置来查看) TCB(可以通过配置来查看) 占用多少内存就可以了
整体来说,布局的话
flash
.code .ro-data
ram
.data .bss .heap TCB(应用程序)
.stack(内核) .stack(应用程序1) .stack(应用程序2) ...
---------------------------和裸机内存的布局有什么不同
1.大体相同(都是 .code .ro-data .data .bss .heap .stack)
2.只不过.heap被内核用了一部分(用于TCB的管理)
3.stack被分成了很多份(内核一份(内核的stack在.stack),每个应用程序一份(用户的stack在.heap))
参考资料