内核框架
内核是操作系统最基础也是最重要的部分,内核处于硬件层之上,内核部分包括内核库、实时内核实现。
内核库是为了保证内核能够独立运行的一套小型的类似C库的函数实现子集。这部分根据编译器不同自带C库的情况也会不同。
当使用GNU GCC编译器时,会携带更多的标准C库实现。
线程调度
线程是RT-Thread操作系统中最小的调度单位,线程调度算法是基于优先级的全抢占式多线程调度算法。
即在系统中除了中断处理函数、调度器上锁部分的代码和禁止中断的代码不可抢占之外,系统的其它部分都可以抢占的,包括线程调度器自身。
支持256个线程优先级(也可通过配置文件更改为最大支持32个或8个线程优先级,针对STM32默认配置是32个线程优先级)。
0优先级代表最高优先级,最低优先级留给空闲线程使用。
同时也支持创建多个具有相同优先级的线程,相同优先级的线程间采用时间片的轮转调度算法,使每个线程运行相应时间。
调度器在寻找那些处于就绪状态的具有最高优先级的线程时,所经历的时间是恒定的。
系统也不限制线程数量的多少,线程数目只和硬件平台的具体内存相关。
时钟管理
RT-Thread的时钟管理以时钟节拍为基础,时钟节拍是RT-Thread操作系统中最小的时钟单位。
提供两类定时器机制:
- 单次触发定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。
- 周期触发定时器,定时器会周期性的触发定时器事件,直到用户手动停止定时器。
根据超时函数执行时所处的上下文环境,定时器可以设置为HARD_TIMER或SOFT_TIMER模式。
通常使用定时器定时回调函数(即超时函数),完成定时服务。
线程间同步
采用信号量、互斥量与事件集实现线程间同步。
线程通过对信号量、互斥量的获取与释放进行同步。
互斥量采用优先级继承的方式解决了实时系统常见的优先级翻转问题。
线程同步机制支持线程按优先级等待或按先进先出方式获取信号量或互斥量。
线程通过对事件的发送与接收进行同步。
事件集支持多事件的“或触发”和“与触发”,支持线程等待多个事件的情况。
线程间通信
RT-Thread支持邮箱和消息队列等通信机制。
邮箱中一封邮件的长度固定为4字节大小。
消息队列能够接收不固定长度的消息,并把消息缓存在自己的内存空间中。
邮箱效率比消息队列更高。
邮箱和消息队列的发送动作可安全用于中断服务例程中。
通信机制支持线程优先级等待或按先进先出方式获取。
内存管理
支持静态内存池管理和动态内存堆管理。
当静态内存池具有可用内存时,系统对内存块分配的时间是恒定的。
当静态内存池为空时,系统将申请内存块的线程挂起或阻塞掉(即线程等待一段时间后仍未获得内存块就放弃申请并返回,或者立刻返回。等待的时间取决于申请内存块时设置的等待时间参数)。
当其他线程释放内存块到内存池时,如果有挂起的待分配内存块的线程存在的话,则系统会将这个线程唤醒。
动态内存堆管理模块在系统资源不同的情况下,分别提供了面向小内存系统的内存管理算法及面向大内存系统的SLAB内存管理算法。
还有一种动态内存堆管理叫做memheap,适用于系统含有多个地址可不连续的内存堆。使用memheap可将多个内存堆“粘贴”在一起,让用户操作起来像是在操作一个内存堆。
I/O设备管理
将PIN、I2C、SPI、USB、UART等作为外设设备,统一通过设备注册完成。
实现了按名称访问的设备管理子系统,可按照统一的API界面访问硬件设备。
在设备驱动接口上,根据嵌入式系统的特点,对不同的设备可以挂接相应的事件。
当设备事件触发时,由驱动程序通知给上层的应用程序。
RTT内核启动流程
RT-Thread支持多种平台和多种编译器。
rtthread_startup()函数是RT-Thread规定的统一启动入口。
一般执行顺序是:系统先从启动文件.s开始运行,然后进入RT-Thread的启动rtthread_startup(),最后进入用户入口main()。
- 先关掉硬件中断:rt_hw_interrupt_disable()
- 板级初始化:rt_hw_board_init() rt_components_board_init() board init functions
- 展示版本号rt_show_version()
- 系统定时器初始化rt_system_timer_init()
- 系统调度器初始化rt_system_scheduler_init()
- 信号初始化rt_system_signal_init()
- 应用层初始化rt_application_init() rt_thread_init(main_thread_entry)
- 系统定时器线程初始化,rt_system_timer_thread_init() rt_thread_init(rt_thread_timer_entry)
- 空闲线程初始化rt_thread_idle_init() rt_thread_init(rt_thread_idle_entry)
- rt_system_scheduler()启动调度器
清空BSS段,为C语言执行准备条件。
C语言中全局未初始化变量放在BSS段,所以当我们打印全局未初始化变量时,也会显示0。
调用SystemInit,调用完后进入entry入口,由此进入C语言代码执行。
void SystemInit (void)
{/* Reset the RCC clock configuration to the default reset state(for debug purpose) *//* Set HSION bit */RCC->CR |= 0x00000001U;/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#if !defined(STM32F105xC) && !defined(STM32F107xC)RCC->CFGR &= 0xF8FF0000U;
#elseRCC->CFGR &= 0xF0FF0000U;
#endif /* STM32F105xC */ /* Reset HSEON, CSSON and PLLON bits */RCC->CR &= 0xFEF6FFFFU;/* Reset HSEBYP bit */RCC->CR &= 0xFFFBFFFFU;/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */RCC->CFGR &= 0xFF80FFFFU;#if defined(STM32F105xC) || defined(STM32F107xC)/* Reset PLL2ON and PLL3ON bits */RCC->CR &= 0xEBFFFFFFU;/* Disable all interrupts and clear pending bits */RCC->CIR = 0x00FF0000U;/* Reset CFGR2 register */RCC->CFGR2 = 0x00000000U;
#elif defined(STM32F100xB) || defined(STM32F100xE)/* Disable all interrupts and clear pending bits */RCC->CIR = 0x009F0000U;/* Reset CFGR2 register */RCC->CFGR2 = 0x00000000U;
#else/* Disable all interrupts and clear pending bits */RCC->CIR = 0x009F0000U;
#endif /* STM32F105xC */
#elif defined(__GNUC__)
/* Add -eentry to arm-none-eabi-gcc argument */
int entry(void)
{rtthread_startup();return 0;
}
#endif
int rtthread_startup(void)
{rt_hw_interrupt_disable();/* board level initialization* NOTE: please initialize heap inside board initialization.*/rt_hw_board_init();/* show RT-Thread version */rt_show_version();/* timer system initialization */rt_system_timer_init();/* scheduler system initialization */rt_system_scheduler_init();#ifdef RT_USING_SIGNALS/* signal system initialization */rt_system_signal_init();
#endif/* create init_thread */rt_application_init();/* timer thread initialization */rt_system_timer_thread_init();/* idle thread initialization */rt_thread_idle_init();#ifdef RT_USING_SMPrt_hw_spin_lock(&_cpus_lock);
#endif /*RT_USING_SMP*//* start scheduler */rt_system_scheduler_start();/* never reach here */return 0;
}
void rt_application_init(void)
{rt_thread_t tid;#ifdef RT_USING_HEAPtid = rt_thread_create("main", main_thread_entry, RT_NULL,RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);RT_ASSERT(tid != RT_NULL);
#elsert_err_t result;tid = &main_thread;result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);RT_ASSERT(result == RT_EOK);/* if not define RT_USING_HEAP, using to eliminate the warning */(void)result;
#endifrt_thread_startup(tid);
}
/* the system main thread */
void main_thread_entry(void *parameter)
{extern int main(void);extern int $Super$$main(void);#ifdef RT_USING_COMPONENTS_INIT/* RT-Thread components initialization */rt_components_init();
#endif
#ifdef RT_USING_SMPrt_hw_secondary_cpu_up();
#endif/* invoke system main function */
#if defined(__CC_ARM) || defined(__CLANG_ARM)$Super$$main(); /* for ARMCC. */
#elif defined(__ICCARM__) || defined(__GNUC__)main();
#endif
}