RT-Thread内核基础

2023-05-16

RT-Thread内核基础

1、RT-Thread 内核介绍

下图为 RT-Thread 内核架构图,内核处于硬件层之上,内核部分包括内核库、实时内核实现。
在这里插入图片描述
实时内核的实现包括:对象管理、线程管理及调度器、线程间通信管理、时钟管理及内存管理等等,内核最小的资源占用情况是3KB ROM,1.2KB RAM

1.线程调度

  线程是 RT-Thread 操作系统中最小的调度单位,线程调度算法是基于优先级的全抢占式多线程调度算法,即在系统中除了中断处理函数、调度器上锁部分的代码和禁止中断的代码是不可抢占的之外,系统的其他部分都是可以抢占的,包括线程调度器自身。支持256个线程优先级(也可通过配置文件更改为最大支持 32 个或 8 个线程优先级,针对 STM32 默认配置是 32 个线程优先级),0 优先级代表最高优先级,最低优先级留给空闲线程使用;同时它也支持创建多个具有相同优先级的线程,相同优先级的线程间采用时间片的轮转调度算法进行调度,使每个线程运行相应时间;另外调度器在寻找那些处于就绪状态的具有最高优先级的线程时,所经历的时间是恒定的,系统也不限制线程数量的多少,线程数目只和硬件平台的具体内存相关。

2.时钟管理

  RT-Thread 的时钟管理以时钟节拍为基础,时钟节拍是 RT-Thread 操作系统中最小的时钟单位。RT-Thread 的定时器提供两类定时器机制:第一类是单次触发定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。第二类是周期触发定时器,这类定时器会周期性的触发定时器事件,直到用户手动的停止定时器否则将永远持续执行下去。

  另外,根据超时函数执行时所处的上下文环境,RT-Thread 的定时器可以设置为 HARD_TIMER 模式或者 SOFT_TIMER 模式

  通常使用定时器定时回调函数(即超时函数),完成定时服务。用户根据自己对定时处理的实时性要求选择合适类型的定时器。

3.线程间同步

  ==RT-Thread 采用信号量互斥量事件集实现线程间同步。线程通过对信号量、互斥量的获取与释放进行同步;互斥量采用优先级继承的方式解决了实时系统常见的优先级翻转问题。线程同步机制支持线程按优先级等待或按先进先出方式获取信号量或互斥量。线程通过对事件的发送与接收进行同步;事件集支持多事件的 “或触发” 和“与触发”,适合于线程等待多个事件的情况

4.线程间通信

  RT-Thread 支持邮箱消息队列等通信机制。邮箱中一封邮件的长度固定为 4 字节大小消息队列能够接收不固定长度的消息,并把消息缓存在自己的内存空间中。邮箱效率较消息队列更为高效。邮箱和消息队列的发送动作可安全用于中断服务例程中。通信机制支持线程按优先级等待或按先进先出方式获取。

5.内存管理

  RT-Thread 支持静态内存池管理动态内存堆管理。当静态内存池具有可用内存时,系统对内存块分配的时间将是恒定的;当静态内存池为空时,系统将申请内存块的线程挂起或阻塞掉 (即线程等待一段时间后仍未获得内存块就放弃申请并返回,或者立刻返回。等待的时间取决于申请内存块时设置的等待时间参数),当其他线程释放内存块到内存池时,如果有挂起的待分配内存块的线程存在的话,则系统会将这个线程唤醒。

  动态内存堆管理模块在系统资源不同的情况下,分别提供了面向小内存系统的内存管理算法及面向大内存系统的 SLAB 内存管理算法。

  还有一种动态内存堆管理叫做 memheap,适用于系统含有多个地址可不连续的内存堆。使用 memheap 可以将多个内存堆 “粘贴” 在一起,让用户操作起来像是在操作一个内存堆

6.I/O 设备管理

  RT-Thread 将 PIN、I2C、SPI、USB、UART 等作为外设设备,统一通过设备注册完成。实现了按名称访问的设备管理子系统,可按照统一的 API 界面访问硬件设备。在设备驱动接口上,根据嵌入式系统的特点,对不同的设备可以挂接相应的事件。当设备事件触发时,由驱动程序通知给上层的应用程序。

2、RT-Thread 启动流程

RT-Thread 支持多种平台和多种编译器,而 rtthread_startup()函数是 RT-Thread 规定的统一启动入口。一般执行顺序是:系统先从启动文件开始运行,然后进入 RT-Thread 的启动 rtthread_startup() ,最后进入用户入口 main()。下图为启动流程图
在这里插入图片描述
以 MDK-ARM 为例,用户程序入口为 main() 函数,位于 main.c 文件中。系统启动后先从汇编代码 startup_stm32f103xe.s (这个文件是stm32f103的启动文件)开始运行,然后跳转到 C 代码,进行 RT-Thread 系统启动,最后进入用户程序入口 main()。

为了在进入 main() 之前完成 RT-Thread 系统功能初始化,我们使用了 MDK 的扩展功能 $Sub$$$Super$$。可以给 main 添加 $Sub$$的前缀符号作为一个新功能函数$Sub$$main,这个 $Sub$$main 可以先调用一些要补充在 main 之前的功能函数(这里添加 RT-Thread 系统启动,进行系统一系列初始化),再调用$Super$$main 转到main()函数执行,这样可以让用户不用去管main()之前的系统初始化操作。

1.系统启动流程图

stm32f103xe.s
$Sub$$main
rtthread_startup
$Super$$main
main

2.$Sub$$main 函数

/* $Sub$$main 函数 */
int $Sub$$main(void)
{
  rtthread_startup();
  return 0;
}

3.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() 中完成系统时钟设置,为系统提供心跳、串口初始化,将系统输入输出终端绑定到这个串口,后续系统运行信息就会从串口打印出来。

main() 函数是 RT-Thread 的用户代码入口,用户可以在 main() 函数里添加自己的应用。

3、RT-Thread 程序内存分布

1.Program Size 包含以下几个部分:

(1)Code:代码段,存放程序的代码部分;

(2)RO-data:只读数据段,存放程序中定义的常量;

(3)RW-data:读写数据段,存放初始化为非 0 值的全局变量;

(4)ZI-data:0 数据段,存放未初始化的全局变量及初始化为 0 的变量;

4、RT-Thread 自动初始化机制

自动初始化机制是指初始化函数不需要被显式调用,只需要在函数定义处通过宏定义的方式进行申明,就会在系统启动过程中被执行

例如在串口驱动中调用一个宏定义告知系统初始化需要调用的函数,代码如下:

int rt_hw_usart_init(void)  /* 串口初始化函数 */
{
     ... ...
     /* 注册串口 1 设备 */
     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(rt_hw_usart_init) 表示使用自动初始化功能按照这种方式,rt_hw_usart_init() 函数就会被系统自动调用

用来实现自动初始化功能的宏接口定义详细描述如下表所示:

初始化顺序宏接口描述
1INIT_BOARD_EXPORT(fn)非常早期的初始化,此时调度器还未启动
2INIT_PREV_EXPORT(fn)主要是用于纯软件的初始化、没有太多依赖的函数
3INIT_DEVICE_EXPORT(fn)外设驱动初始化相关,比如网卡设备
4INIT_COMPONENT_EXPORT(fn)组件初始化,比如文件系统或者 LWIP
5INIT_ENV_EXPORT(fn)系统环境初始化,比如挂载文件系统
6INIT_APP_EXPORT(fn)应用初始化,比如 GUI 应用

  RT-Thread 的自动初始化机制使用了自定义 RTI 符号段,将需要在启动时进行初始化的函数指针放到了该段中,形成一张初始化函数表,在系统启动过程中会遍历该表,并调用表中的函数,达到自动初始化的目的。

  初始化函数主动通过这些宏接口进行申明,如 INIT_BOARD_EXPORT(rt_hw_usart_init),链接器会自动收集所有被申明的初始化函数,放到 RTI 符号段中,该符号段位于内存分布的 RO 段中,该 RTI 符号段中的所有函数在系统初始化时会被自动调用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RT-Thread内核基础 的相关文章

  • 关于 find grep xargs 命令总结

    1 定义 amp 区别 xff1a 1 find命令是根据文件的属性进行查找 xff0c 如文件名 xff0c 文件大小 xff0c 所有者 xff0c 所属组 xff0c 是否为空 xff0c 访问时间 xff0c 修改时间等 2 gre
  • ubuntu如何在当前文件夹下打开终端

    1 打开终端 xff0c 执行以下命令 xff1a sudo apt get install nautilus open terminal 2 在终端中执行下列命令 xff0c 重新加载文件管理器 nautilus q 3 执行以上指令后在
  • 解决libssl.so.1.0.0: 找不到的问题

    安装了多个版本的openssl后 xff0c 导致adb或svn无法使用 xff0c 出现以下错误 xff1a libssl so 1 0 0 no version information available 记录下最后的解决方法 xff0
  • JS对象—5.文档对象(document)

    document对象 一 span class token punctuation span 元数据 span class token number 1 span characterSet span class token operator
  • Keil5及芯片包的安装以及 Keil5打开Keil4工程编译出错解决方法

    一 温馨提示 1 安装路径不能带中文 xff0c 必须是英文路径 2 安装目录不能跟 51 的 KEIL 或者 KEIL4 冲突 xff0c 三者目录必须分开 3 KEIL5 的安装比起 KEIL4 多了一个步骤 xff0c 必须添加 MC
  • 上下文切换

    上下文切换是操作系统比较重要的一部分 xff0c 提到它 xff0c 我们第一时间想到的会是使用时间片轮转方式调度的os中涉及的进程之间上下文切换 再问还有没有其他 xff0c 也许会想到中断时 xff0c 上下文似乎也要切换 这两种切换是
  • Android系统 应用图标显示未读消息数(BadgeNumber) 桌面app图标的角标显示

    http www 51itong net android badgenumber 9789 html
  • smbclient介绍

    smbclient介绍 1 Smbclient介绍1 1 SMB 协议介绍 2 Smbclient命令使用技巧2 1 Smbclient 功能说明2 2 语法2 3 参数2 4 使用举例 1 Smbclient介绍 Smbclient sa
  • 关于void指针的地址问题

    如图 void指针指向其他类型的数据时对其地址加1 它可指向几乎任何数据 xff0c 且指针加1时相当于字符指针加1 xff0c 利用这一特性可将void指针作为形参类型 xff0c 可传入任意数据且对形参操作时可类比字符指针 xff0c
  • Ubuntu apt update无论使用什么源都出现类似的错误

    下面是清华源执行后的情况 Ign 1 https mirrors tuna tsinghua edu cn ubuntu jammy InRelease Ign 2 https mirrors tuna tsinghua edu cn ub
  • 从源码分析C++中forward完美转发和move移动语义的本质区别

    完美转发可以看做一种能够按照原来类型转发到另一个地方 xff08 函数 xff09 的方法 xff08 废话 xff09 咱不如直接上源代码 xff08 move h xff09 xff1a template lt typename Tp
  • 实现对单链表的倒置

    我们知道数组的倒置比较简单 xff0c 只需要知道数组的头 xff0c 和数组的尾 xff0c 将其数据互换 xff0c 再将第二个和倒数第二个互换 xff0c 一直这样操作下去 xff0c 数组就实现倒置了 那么单链表也可以通过这样的方法
  • 立创开源|18650锂电池四路充电器

    该工程为18650四路电池充电器 xff0c 支持DC Micro USB USB typec输入 xff0c 同时四路充电 充电芯片采用价格便宜的TP4056 xff0c 电池盒采用直插电池盒 每节电池充电电流为1A xff0c 由于电流
  • 无法连接上 archive.ubuntukylin.com:10006 (120.79.211.60),连接超时

    无法连接上 archive ubuntukylin com 10006 120 79 211 60 xff0c 连接超时解决方法 问题描述 执行sudo apt get update时出现如下错误 xff1a 错误 12 http arch
  • 【C++】模板与泛型编程

    泛型编程 泛型编程最初诞生于C 43 43 中 xff0c 由Alexander Stepanov 2 和David Musser 3 创立 目的是为了实现C 43 43 的STL xff08 标准模板库 xff09 其语言支持机制就是模板
  • LXC(Linux containers)常用命令介绍

    lxc version 用于显示系统LXC的版本号 xff08 可以通过此命令判断系统是否安装了lxc xff09 用法 xff1a lxc version 例如 lxc version lxc checkconfig 用于判断linux内
  • Docker 大势已去,Podman 万岁

    前言 郑重声明 xff1a 本文不是 Podman 的入门篇 xff0c 入门请阅读这篇文章 xff1a 再见 Docker xff0c 是时候拥抱下一代容器工具了 Podman 原来是 CRI O 项目的一部分 xff0c 后来被分离成一
  • 使用node开发一个解放双手的小工具《二》- vsCode插件包装

    背景 xff1a 此篇是上篇 使用node开发一个解放双手的小工具 的后续 xff0c 前边遗留了一些问题 xff0c 最近完善了一下 因为发现实际使用起来 xff0c 有很多的不方便 xff1a 使用上 xff0c 需要配置对应的根目录
  • 使用网络调试助手时,踩坑

    在使用网络调试助手时 xff0c 踩坑很多 xff1a 1 作为tcp的客户端 xff0c 或者服务端 xff0c 没有注意发送设置以ASCII还是HEX 导致目标环境接收解析数据异常出现段错误 2 xff1a 作为UDP作为客户端 xff
  • Win7 32 不能安装STM32 虚拟串口驱动解决方法

    1 对于一些精简过的系统 xff0c 无法安装虚拟串口 xff0c 是由于系统缺少mdmcpq inf和usbser sys文件所造成的 只需要将文件下载下来放在相应的文件夹下面就行了 文件对应的目录如下 xff1a mdmcpq inf在

随机推荐

  • gitee使用教程

    目录 版本控制 1 Gitee上注册账户 2 新建一个远程代码仓 xff0c 点击右上方的加号 3 修改远程仓为开源的 编辑 4 本地下载git 5 克隆远程仓到本地 xff0c 复制地址 6 创建代码并提交到远程仓库 7 将本地代码提交到
  • Telnet 接口的使用(一):Telnet的安装与开启

    什么是 Telnet 简介 telnet 用于远程登录 xff0c Telnet的工作方式为 服务器 客户端 方式 xff0c 它提供了从一台设备 xff08 Telnet客户端 xff09 远程登录到另一台设备 xff08 Telnet服
  • Android系统四层体系架构

    Android体系架构分为四层 xff1a 应用层 应用框架层 库层 内核层 xff08 盗用一张图 xff09 一 应用层 应用层包括手机上的所有APP xff0c 无论是系统自带的还是用户开发的 他们都是基于第二层应用框架层开发的 二
  • 芯片的开发板和评估板的区别

    评估版一般都是半导体生产厂家所提供的 xff0c 用于器件性能评估用 xff0c 大公司不用他来赚钱 xff1b 开发板大多说是通过板子赚钱的 xff0c 就是很多的网友工程师做的 xff1b 目标板是在开发产品的过程中 xff0c 相对于
  • 增量式pid+位置式PID(电机位置闭环控制)

    ps xff1a 2022更新 pid详细解释 一般很少用增量式 xff0c 都是用位置式 xff0c 下文增量式可以不看 本文分为几个部分 xff1a 1 编码器 2 定时器输入捕获 xff08 把定时器初始化为编码器模式 xff09 3
  • Vmware 扩容磁盘

    Vmware 扩容磁盘 第一步 xff0c 首先添加一块磁盘 xff0c 进行分区第二步 xff0c 创建物理卷加入组第三步 xff0c 进行扩容 目录第四步 xff0c 刷新逻辑卷 第一步 xff0c 首先添加一块磁盘 xff0c 进行分
  • 思科模拟器中的交换机使用方法

    思科模拟器中的交换机使用方法 思科模拟器中有较多种交换机型号 xff0c 这里只是简单的介绍一下二层交换机2960 xff0c 以及三层交换机中的3560 1 关于交换机的原理 xff1a 交换机是通过其保存的MAC地址表来进行工作的 xf
  • 计算机发展15件重大事件(图说)

    链接 xff1a https vision xitek com famous 201001 28 36559 html 一 1946年 xff0c 第一台电子计算机 埃尼阿克 问世 二 1976年 xff0c 苹果电脑Apple I现世 三
  • vsftp登录报530 Login incorrect无法登录问题解决

    vsftp登录报530 Login incorrect无法登录问题解决 今天在搭建FTP服务器的时候遇到了530 Login incorrect这个问题 通过修改配置文件解决了 总结了一下在搭建FTP服务器的时要注意的地方大概有下面这几点
  • Linux上SMB挂载提示mount: block device //xxx.xxx.xx.xx/xx is write-protected, mounting read-only时解决办法

    当在Linux上挂载SMB服务器时候有时会提示如下错误 xff1a root 64 test mount o username 61 lisi 192 168 23 32 smb test mount block device 192 16
  • Linux下的LAMP环境搭建时访问PHP页面时变成下载页面的原因

    在搭建LAMP环境的时候遇到了配置完PHP环境后测试访问PHP页面的时候却变成下载的情况 xff0c 主要的影响有一下两个方面 1 PHP的配置问题 2 主要原因是httpd conf配置文件内容出错大致有下面几个地方 xff1a Load
  • 服务器肉鸡/入侵被恶意利用的排查和优化方案

    排查方法 xff1a 1 账户方面 xff1a Windows xff1a xff08 1 xff09 检查服务器内是否有异常的账户 xff0c 查看下服务器内是否有非系统和用户本身创建的账户 xff0c 一般黑客创建的账户账户名 后会有
  • Opensuse如何安装桌面环境

    安装必须的范式 xff1a zypper install t pattern kde kde plasma 编辑 etc sysconfig displaymanager 文件并设定 DISPLAYMANAGER 61 kdm xff0c
  • 怎么用谷歌学术检索下载外文文献

    谷歌学术是一个可以免费搜索外文学术文章的搜索引擎 xff0c 包括了世界上绝大部分出版的学术期刊 xff0c 可广泛搜索学术文献 谷歌学术可了解有关某一领域的学术文献 xff1b 了解某一作者的著述 xff0c 并提供书目信息 xff08
  • 英文文献去哪里查找,8个超强英文文献查找网站建议收藏

    英文文献去哪里查找 xff1f 找对方向用对工具可大幅提升学习和研究效率 xff01 下面详细介绍8个查找英文文献非常好用的网站 一 文献党下载器 xff08 wxdown org xff09 xff1a 该网站几乎整合汇聚了所有文献数据库
  • 基于STM32系列的模拟串口(非阻塞式)

    STM32单片机一般少则3个串口 多则5个 而我这次的项目还偏偏5个硬件串口还是不够用 至于不够用的原因 哎 是项目做到后面有定制 随便哪个串口都省不得 没得办法 只能另想法子咯 板子上有几个预留IO口 可以用来模拟串口 模拟串口一般都选9
  • 复制一个目录下的所有文件到另外一个目录(Java实现)

    首先说说我的思路 xff0c 要复制一个目录下的所有文件到另外的一个目录下 xff0c 我们不知道目录下的结构是怎么样的 xff0c 也不知道目录有多少层 xff0c 文件有多少个 xff0c 这样我们会想用循环 xff0c for 但是我
  • RT-Thread嵌入式操作系统

    一 系统架构 RT Thread xff0c 全称是 Real Time Thread xff0c 顾名思义 xff0c 它是一个嵌入式实时多线程操作系统 RT Thread 主要采用 C 语言编写 xff0c 浅显易懂 xff0c 方便移
  • 1.javascript类型中你不知道的细节

    1 数据类型 基本数据类型 xff1a Undefined xff1b Null xff1b Boolean xff1b String xff1b Number xff1b Symbol xff1b Object 1 1 undefined
  • RT-Thread内核基础

    RT Thread内核基础 1 RT Thread 内核介绍 下图为 RT Thread 内核架构图 xff0c 内核处于硬件层之上 xff0c 内核部分包括内核库 实时内核实现 实时内核的实现包括 xff1a 对象管理 线程管理及调度器