RT-Thread内核启动流程与自动初始化机制详解
RT-Thread内核启动流程深度解析1. RT-Thread内核架构概述RT-Thread是一款开源的实时操作系统(RTOS)其内核设计采用模块化架构主要由两大部分组成1.1 内核库实现内核库是RT-Thread独立运行的基础设施提供了一套精简的C库函数实现。这些函数位于src/kservice.c文件中为避免与标准C库冲突所有函数都添加了rt_前缀。典型实现包括void *rt_memset(void *s, int c, rt_ubase_t count); void *rt_memcpy(void *dst, const void *src, rt_ubase_t count); rt_int32_t rt_memcmp(const void *cs, const void *ct, rt_ubase_t count); char *rt_strstr(const char *s1, const char *s2); rt_size_t rt_strlen(const char *s);这种设计使RT-Thread能够脱离标准C库独立运行最小资源占用仅为3KB ROM和1.2KB RAM。1.2 实时内核实现RT-Thread的实时内核包含以下核心组件线程管理基于优先级的全抢占式调度算法支持256级优先级(可配置为32或8级)时钟管理提供单次触发和周期触发两种定时器机制线程同步通过信号量、互斥量和事件集实现线程通信支持邮箱(固定4字节)和消息队列(可变长度)内存管理包含静态内存池和动态内存堆管理后者支持小内存系统和大内存系统两种算法2. 系统启动流程分析2.1 启动流程概述RT-Thread的启动流程与传统RTOS有所不同其特点在于系统初始化在main()函数之前完成采用MDK-ARM的$Sub$$和$Super$$扩展机制启动过程分为硬件初始化、内核初始化和应用初始化三个阶段典型启动序列如下startup_xx.s → rtthread_startup() → main()2.2 关键启动函数解析2.2.1 $Sub$$main实现在src/components.c中通过$Sub$$main重定义了main函数extern int $Super$$main(void); int $Sub$$main(void) { rtthread_startup(); return 0; }这种设计使系统在进入用户main()前完成所有初始化工作。2.2.2 rtthread_startup()函数该函数是RT-Thread的核心启动函数主要完成以下工作int rtthread_startup(void) { rt_hw_interrupt_disable(); // 关闭全局中断 rt_hw_board_init(); // 硬件初始化 rt_show_version(); // 显示版本信息 rt_system_timer_init(); // 定时器系统初始化 rt_system_scheduler_init(); // 调度器初始化 #ifdef RT_USING_SIGNALS rt_system_signal_init(); // 信号初始化 #endif rt_application_init(); // 创建主线程 rt_system_timer_thread_init();// 定时器线程初始化 rt_thread_idle_init(); // 空闲线程初始化 rt_system_scheduler_start(); // 启动调度器 return 0; }启动过程可分为四个阶段硬件相关初始化内核对象初始化(定时器、调度器、信号等)创建main线程并初始化应用模块初始化定时器线程和空闲线程最终启动调度器3. 自动初始化机制3.1 初始化阶段划分RT-Thread的自动初始化机制将初始化过程分为6个阶段序号初始化类型宏定义描述1板级初始化INIT_BOARD_EXPORT(fn)早期硬件初始化调度器未启动2预初始化INIT_PREV_EXPORT(fn)纯软件初始化3设备初始化INIT_DEVICE_EXPORT(fn)外设驱动初始化4组件初始化INIT_COMPONENT_EXPORT(fn)文件系统、网络栈等组件初始化5环境初始化INIT_ENV_EXPORT(fn)挂载文件系统等环境初始化6应用初始化INIT_APP_EXPORT(fn)GUI等应用初始化3.2 实现原理自动初始化机制通过自定义RTI符号段实现关键宏定义如下#define INIT_EXPORT(fn, level) \ RT_USED const init_fn_t __rt_init_##fn SECTION(.rti_fn. level) fn #define INIT_BOARD_EXPORT(fn) INIT_EXPORT(fn, 1) #define INIT_PREV_EXPORT(fn) INIT_EXPORT(fn, 2) #define INIT_DEVICE_EXPORT(fn) INIT_EXPORT(fn, 3) #define INIT_COMPONENT_EXPORT(fn) INIT_EXPORT(fn, 4) #define INIT_ENV_EXPORT(fn) INIT_EXPORT(fn, 5) #define INIT_APP_EXPORT(fn) INIT_EXPORT(fn, 6)其中SECTION属性将函数指针放入指定段RT_USED告知编译器不要优化掉这些符号##用于字符串拼接生成唯一的符号名初始化函数表的遍历通过以下函数实现void rt_components_board_init(void) { const init_fn_t *fn_ptr; for(fn_ptr __rt_init_rti_board_start; fn_ptr __rt_init_rti_board_end; fn_ptr) { (*fn_ptr)(); } } void rt_components_init(void) { const init_fn_t *fn_ptr; for(fn_ptr __rt_init_rti_board_end; fn_ptr __rt_init_rti_end; fn_ptr) { (*fn_ptr)(); } }4. 应用实例分析4.1 串口设备初始化示例典型的设备初始化函数声明如下int rt_hw_usart_init(void) { // 串口硬件初始化代码 rt_hw_serial_register(serial1, uart1, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart); return 0; } INIT_BOARD_EXPORT(rt_hw_usart_init);通过INIT_BOARD_EXPORT宏串口初始化函数将在板级初始化阶段自动执行。4.2 main线程入口在rt_application_init()中创建的主线程入口函数为void main_thread_entry(void *parameter) { #ifdef RT_USING_COMPONENTS_INIT rt_components_init(); // 组件初始化 #endif #ifdef RT_USING_SMP rt_hw_secondary_cpu_up(); #endif #if defined(__CC_ARM) || defined(__CLANG_ARM) $Super$$main(); // ARMCC编译器进入main() #elif defined(__ICCARM__) || defined(__GNUC__) main(); // IAR/GCC编译器进入main() #endif }该函数在完成组件初始化后最终跳转到用户main()函数执行。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2449767.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!