网站服务类型有哪些,上杭网站建设,网站 建设需求,创造与魔法官方网站做自己喜欢的事1、内核简介
内核是操作系统的核心#xff0c;是操作系统最基础也是最重要的部分#xff0c;主要负责系统的线程、线程间通信、系统时钟、中断以及内存等。其架构图如下#xff1a;
2、线程调度
线程是RT-Thread操作系统中最小的调度单位#xff0c;线程调度算法的基于…1、内核简介
内核是操作系统的核心是操作系统最基础也是最重要的部分主要负责系统的线程、线程间通信、系统时钟、中断以及内存等。其架构图如下
2、线程调度
线程是RT-Thread操作系统中最小的调度单位线程调度算法的基于优先级的全抢占式多线程调度算法即在系统中除了中断处理函数、调度器上锁部分的代码和禁止中断的代码外是不可抢占的其他都可以抢占包括线程调度器自身。线程调度算法支持256个线程优先级0优先级代表最高优先级最低优先级留给空闲线程使用对于相同优先级的线程采用时间片的轮转调度算法进行调度使每个线程运行相应时间调度器在寻找那些处于就绪态的具有最高优先级的线程时所经历的时间是恒定的系统不限制线程数量的多少线程数目只和硬件平台的具体内存相关这个具体的内存要去掉实际程序中已经用掉的内存实际的代码会用掉一部分内存因此不能只看硬件的参数还需要考虑代码对内存的占用情况。
3、 时钟管理
RT-Thread的时钟管理是以时钟节拍为基础的时钟节拍的RT-Thread中最小的时钟单位。RT-Thread提供两种定时器的机制一是单次触发定时器此定时器在启动之后只会触发一次定时器事件然后定时器自动停止二是周期触发定时器这类定时器会周期性的触发定时器事件直到用户手动的停止定时器否则将永远持续执行下去。 根据超时函数执行时的上下文RT-Thread的定时器可以设置为HARD_TIMER模式和SOFT_TIMER模式。
4、线程间同步
RT-Thread采用信号量、互斥量与事件实现线程间同步。线程通过对信号量、互斥量的获取与释放进行同步互斥量采用优先级继承的方式解决了实时系统常见的优先级反转问题。线程同步机制支持线程按优先级等待方式获取信号量或互斥量。线程通过对事件的发送与接受进行同步事件集支持多事件的“或触发”和“与触发”适合于线程等待多个事件的情况。
5、线程间通信
RT-Thread 支持邮箱和消息队列等通信机制。邮箱中一封邮件的长度固定为 4 字节大小消息队列能够接收不固定长度的消息并把消息缓存在自己的内存空间中。邮箱效率较消息队列更为高效。邮箱和消息队列的发送动作可安全用于中断服务例程中。通信机制支持线程按优先级等待方式获取。
6、内存管理
RT-Thread支持静态内存池管理和动态内存堆管理。当静态内存池具有可用内存时系统对内存块分配的时间是恒定的当静态内存池为空时系统将申请内存块的线程挂起或者阻塞掉线程等待一段时间后仍未获得内存块就放弃申请并返回或者立刻返回。等待的时间取决去申请内存块时设置的等待时间参数当其他线程释放内存块到内存池时如有挂起的待分配的线程存在的话则系统会将这个线程唤醒。 动态内存堆管理模块在系统资源不同的情况下分别提供了面向小内存管理算法及面向大内存系统的SLAB内存管理算法。 另一种动态内存堆管理叫做memheap适用于系统含有多个地址且不连续的内存堆。使用memheap可以将多个内存堆“粘贴”在一起让用户操作起来像是在操作一个内存堆。
7、I/O设备管理
RT-Thread 将 PIN、I2C、SPI、USB、UART 等作为外设设备统一通过设备注册完成。实现了按名称访问的设备管理子系统可按照统一的 API 界面访问硬件设备。在设备驱动接口上根据嵌入式系统的特点对不同的设备可以挂接相应的事件。当设备事件触发时由驱动程序通知给上层的应用程序。
8、RT-Thread启动流程
RT-Thread 支持多种平台和多种编译器而 rtthread_startup() 函数是 RT-Thread 规定的统一启动入口。一般执行顺序是系统先从启动文件开始运行然后进入 RT-Thread 的启动函数 rtthread_startup() 最后进入用户入口函数 main()如下图所示 rtthread_startup() 函数其中 rtthread_startup() 函数的代码如下所示
int rtthread_startup(void)
{rt_hw_interrupt_disable();/* 板级初始化需在该函数内部进行系统堆的初始化 */rt_hw_board_init();/* 打印 RT-Thread 版本信息 */rt_show_version();/* 定时器初始化 */rt_system_timer_init();/* 调度器初始化 */rt_system_scheduler_init();#ifdef RT_USING_SIGNALS/* 信号初始化 */rt_system_signal_init();
#endif/* 由此创建一个用户 main 线程 */rt_application_init();/* 定时器线程初始化 */rt_system_timer_thread_init();/* 空闲线程初始化 */rt_thread_idle_init();/* 启动调度器 */rt_system_scheduler_start();/* 不会执行至此 */return 0;
}
这部分启动代码大致可以分为四个部分 1初始化与系统相关的硬件 2初始化系统内核对象例如定时器、调度器、信号 3创建 main 线程在 main 线程中对各类模块依次进行初始化 4初始化定时器线程、空闲线程并启动调度器。 启动调度器之前系统所创建的线程在执行 rt_thread_startup() 后并不会立马运行它们会处于就绪状态等待系统调度待启动调度器之后系统才转入第一个线程开始运行根据调度规则选择的是就绪队列中优先级最高的线程。 rt_hw_board_init() 中完成系统时钟设置为系统提供心跳、串口初始化将系统输入输出终端绑定到这个串口后续系统运行信息就会从串口打印出来。
9、RT-Thread程序内存分布
一般MCU包含的存储空间有片内Flash与片内RAMRAM相当于内存Flash相当于硬盘。编译器会将程序分为几个部分分别存储在MCU不同的位置。 Keil 工程在编译完之后会有相应的程序所占用的空间提示信息如下所示
linking...
Program Size: Code54872 RO-data8656 RW-data764 ZI-data21812
After Build - User command #1: fromelf --bin .\build\rtthread-stm32.axf --output rtthread.bin
.\build\rtthread-stm32.axf - 0 Error(s), 0 Warning(s).
Build Time Elapsed: 00:00:14上面提到的 Program Size 包含以下几个部分 1Code代码段存放程序的代码部分 2RO-data只读数据段存放程序中定义的常量 3RW-data读写数据段存放初始化为非 0 值的全局变量 4ZI-data0 数据段存放未初始化的全局变量及初始化为 0 的变量 编译完工程会生成一个.map 的文件该文件说明了各个函数占用的尺寸和地址在文件的最后几行也说明了上面几个字段的关系
Total RO Size (Code RO Data) 63528 ( 62.04kB)Total RW Size (RW Data ZI Data) 22576 ( 22.05kB)Total ROM Size (Code RO Data RW Data) 63676 ( 62.18kB)1RO Size 包含了 Code 及 RO-data表示程序占用 Flash 空间的大小 2RW Size 包含了 RW-data 及 ZI-data表示运行时占用的 RAM 的大小 3ROM Size 包含了 Code、RO-data 以及 RW-data表示烧写程序所占用的 Flash 空间的大小 程序运行之前需要有文件实体被烧录到 STM32 的 Flash 中一般是 bin 或者 hex 文件该被烧录文件称为可执行映像文件。如下图左边部分所示是可执行映像文件烧录到 STM32 后的内存分布它包含 RO 段和 RW 段两个部分其中 RO 段中保存了 Code、RO-data 的数据RW 段保存了 RW-data 的数据由于 ZI-data 都是 0所以未包含在映像文件中。 STM32 在上电启动之后默认从 Flash 启动启动之后会将 RW 段中的 RW-data初始化的全局变量搬运到 RAM 中但不会搬运 RO 段即 CPU 的执行代码从 Flash 中读取另外根据编译器给出的 ZI 地址和大小分配出 ZI 段并将这块 RAM 区域清零。 其中动态内存堆为未使用的 RAM 空间应用程序申请和释放的内存块都来自该空间。而一些全局变量则是存放于 RW 段和 ZI 段中RW 段存放的是具有初始值的全局变量而常量形式的全局变量则放置在 RO 段中是只读属性的ZI 段存放的系统未初始化的全局变量。