Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
新手学习
rt-smart
rt smart初始化学习贴
发布于 2023-08-16 13:29:24 浏览:1160
订阅该版
[tocm] 本文主要是本人跟踪调试rt smart启动过程的记录贴,所使用的bsp为`qemu-virt64-aarch64`。(持续更新中) ## _start阶段 系统时先进入`_start`执行。首先判断cpu核,如果是0号核的话执行初始化过程,其它核则执行`wfe`指令进入睡眠。初始化的过程如下: - 将异常等级转入`el1` - 设置栈顶指针 - 清理bss段 - 初始化mmu的翻译控制寄存器 - 设置内核和用户空间页表基址寄存器,并进行初始化阶段的页表设置。`ttbr0_el1`设置为`0x4015d000`,`ttbr1_el1`设置为`0x4015e000`,这个地址在`.bss`节中。将内核空间虚拟地址映射为物理地址+`0xffff0000000000`-`0x40000000`,用户空间虚拟地址映射为物理地址,映射大小为`0x10000000`(256M)。 - 使能mmu,启用页表翻译地址 - 使用户空间页表基地址寄存器失效(原来设置该寄存器只为了跳转高地址前的地址翻译),只用内核地址,并设置栈寄存器为`sp_el1` - 跳转到`rtthread_startup` ## rt_hw_board_init部分 该部分实际属于`rtthread_startup`,但内容较多,故这里单独作一部分 ### 内存相关初始化过程及内存管理初步学习 进入内核后首先进行的是内存相关初始化,由于初始化的过程因bsp而异,故该过程在`rt_board_init`中。 首先进入的是`rt_hw_mmu_map_init`,该函数作用是对表示内核地址空间数据结构`rt_kernel_space`的初始化。初始化后其值如下: ``` // 表示内核地址空间 struct rt_aspace rt_kernel_space{ .start = 0xffff000000000000; // 内核起始地址 .size = 0x1000000000000; // 内核地址空间大小 .page_table = MMUTable; // 内核所使用的页表,为变量MMUTable地址0xffff00000015c000,与_start中设置的页表位置相近 .pgtbl_lock; .tree; // 内核地址空间,使用平衡树表示 .bst_lock.parent.parent.name = "aspace"; // bst_lock的名字 .asid = 0; // 地址空间id } ``` 在`rt_page_init`中,要做的事情: - 将页区域范围对齐 - 计算`shadow`范围,涵盖了页区域,边缘与伙伴系统最大chunk对齐 - 清空各秩空闲page列表 - 初始化`mpr_varea`数据结构 - 设置页元数据的范围,并通过`_install_page`初始化页元数据 - 调用`rt_aspace_load_page`来将可分配页加载到内核地址空间 一个需要注意的地方:`void *rt_mpr_start`所标示的位置,不负责具体的页元数据存放,而只负责页元数据大小及偏移的计算。 执行完该部分后,内核地址空间相关全局数据如下: ``` // 表示页表空间 struct rt_varea mpr_varea{ .start = rt_mpr_start; // 页元数据基址,值为0xfffffdfff0000000,(还未清楚用途) .size = rt_mpr_size; // 页元数据区域大小,值为0x20000000000 .offset = 0; .attr = 1536; .flag = 8704; .aspace = rt_kernel_space; .mem_obj = mm_page_mapper; // 内存操作接口 .node; .frames = 0; .data = 0; } init_mpr_align_start = 0xfffffdfff0880000; // 表示shadow页空间起始页在mpr中元数据,由于页元数据起始地址(rt_mpr_start)是从0物理地址页开始存,所以需要此数据 init_mpr_align_end = 0xfffffdfff0900000; // 表示shadow页空间末尾页对应的页元数据在rt_mpr_start中位置 init_mpr_cont_start = 0xffff000004100000; // 表示mpr容器的起始地址,设为之前页空间的起始地址 early_offset = 0xffff020013880000; // 表示的是初始阶段真实页元数据与mpr之间距离 mpr_cont = 0xffff000003880000; // 表示的是真实页元数据中0物理地址页(不存在的虚拟页)元数据位置 head_cont = 0xffff000004102000; // 表示可分配页区域首页在真实页元数据容器中位置,shadow页区域起始地址较可分配页靠前,4100000是shadow页区域起始页的元数据 tail_cont = 0xffff000004180000; // 表示可分配页区域尾页对应页元数据 reg.start = init_mpr_cont_end/tail_cont; // 将前面的页元数据区域剔除可分配页区域 ``` 最后结果是页区域的前一部分用于存放页元数据,初始化后页相关内存分布如下: - 页元数据区域起始地址:0xffff000003880000(`mpr_cont`),从这里到`head_cont`不会用到 - 原可分配页区域起始地址(0xffff00000410000)对应页元数据地址:0xffff000004102000(`head_cont`) - 页元数据结束地址/可分配页起始地址:0xffff000004180000(`tail_cond`/`reg.start`) - 可分配页的终止地址:0xffff000008000000 只有在rt_hw_mmu_ktbl_set设置rt_hw_mmu_ktbl_set了内核页表才可以用rt_kernel_v2p,因为程序执行包括mmu的模拟也需要mmu来翻译页表地址(页表地址也是内核空间一部分) 接下来调用`rt_system_heap_init`进行堆的初始化,该函数在内核对象管理中添加一个`MemHeap`对象,并初始化该对象的成员变量。堆空间设置为`__bss_end`~`0xffff000004000000` ### 中断初始化 由`rt_hw_interrupt_init`执行,大致步骤如下: - 将`VBAR_EL1`中断向量寄存器设置为`system_vector` - 初始化gic(aarch64的中断控制器),并将其mmio映射的物理地址重映射到一个虚拟地址 ### 时钟初始化 由`rt_hw_gtimer_init`执行 - 设置时钟中断的回调函数 - 时钟中断频率设为100次/秒 ### 控制台初始化 由`rt_hw_uart_init`执行串口初始化 - 重映射uart的io虚拟地址 - 注册`uart0`设备 - 注册uart中断,并使能uart的接收和发送 由`rt_console_set_device`将`uart0`设为控制台设备 - 寻找`uart0`设备 - 注册`console`控制台,关联到`uart0`设备 - 使用`tty_init`初始化`console`,提供tty设备抽象 ### 设备树初始化 由`device_tree_setup`来初始化扁平设备树 - 待补充 ### PSCI(Power State Coordination Interface)初始化 由`psci_init`来进行 - 待补充 ### rt_components_board_init 该阶段无重要初始化函数执行 ## rtthread_startup部分 ### 定时器初始化 由`rt_system_timer_init`执行 - 初始化全局时钟链表`_timer_list`,将链表设空 ### 调度器初始化 由`rt_system_scheduler_init`执行 - 初始化全局基于优先级的线程表`rt_thread_priority_table` - 初始化每个cpu的基于优先级线程表`per_cpu->priority_table`及cpu结构体中调度相关变量 - 之后就可以创建线程 ### 应用初始化 由`rt_application_init`执行 - 创建并启动`main`线程,优先级为10,由于并未调用`rt_scheduler`故该线程并未直接运行 ### 空闲线程初始化 由`rt_thread_idle_init`执行 - 创建与cpu相同个数的`idle`线程,并调用`rt_thread_control`绑定到各cpu后启动,优先级最低,由于并未调用`rt_scheduler`故该线程并未直接运行 - 该线程主要负责系统空闲时的资源回收,自定义`idle_hook`执行,及能量管理 ### 启动调度器 由`rt_system_scheduler_start`执行 - 之后会调度到目前就绪队列中优先级最高的`main`函数执行,永不返回 ## main阶段 该阶段执行各个系统组件的初始化,之后打印hello信息并退出 ### libc_system_init 将012号标准输入输出错误文件设为串口
1
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
zms123456
这家伙很懒,什么也没写!
文章
3
回答
0
被采纳
0
关注TA
发私信
相关文章
1
大神们,rt-thread启用WDT了,但是还是没启动,怎么办?
2
求一个师傅带带队,有偿交学费 肯吃苦
3
自己按照官方手册 在drv_gpio.c里面找不到PIN脚信息
4
rtt studio f4默认生成的代码无法使用
5
官方例程中的 USB设置配置不成功
6
STM32F4的虚拟串口 的USB时钟如何配置
7
AT24CXX 软件包函数 at24cxx的问题
8
rtthread studio和bsp文件之间生成的区别和联系?
9
pwm根据手册修改为对应的引脚后无效
10
文件系统挂实验 ls命令异常
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
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组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部