实验 | RT-Thread:L0

news/2024/11/13 9:08:16/

1 理解

官网文档:RT-Thread 简介

  1. 在 RT-Thread 系统中,任务通过线程实现的,RT-Thread 中的线程调度器也就是以上提到的任务调度器。
  2. RT-Thread与FreeRTOS是同等地位的东西,都是属于RTOS
  3. 项目设置:RT-Thread 4.0.2 基于开发板

2 时钟管理

RT-Thread 的时钟管理以时钟节拍为基础,时钟节拍是 RT-Thread 操作系统中最小的时钟单位。RT-Thread 的定时器提供两类定时器机制:

  • 第一类是单次触发定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止

疑问:这一类定时器是干什么作用的?

  • 第二类是周期触发定时器,这类定时器会周期性的触发定时器事件,直到用户手动的停止定时器否则将永远持续执行下去。

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

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

2.1 时钟节拍

任何操作系统都需要提供一个时钟节拍,以供系统处理所有和时间有关的事件,如线程的延时、线程的时间片轮转调度以及定时器超时等。时钟节拍是特定的周期性中断,这个中断可以看做是系统心跳,中断之间的时间间隔取决于不同的应用,一般是 1ms–100ms,时钟节拍率越快,系统的实时响应越快,但是系统的额外开销就越大,从系统启动开始计数的时钟节拍数称为系统时间。

RT-Thread 中,时钟节拍的长度可以根据 RT_TICK_PER_SECOND 的定义来调整,等于 1/RT_TICK_PER_SECOND 秒。

2.2 定时器管理

定时器有硬件定时器和软件定时器之分:

1)硬件定时器是芯片本身提供的定时功能。一般是由外部晶振提供给芯片输入时钟,芯片向软件模块提供一组配置寄存器,接受控制输入,到达设定时间值后芯片中断控制器产生时钟中断。硬件定时器的精度一般很高,可以达到纳秒级别,并且是中断触发方式。

2)软件定时器是由操作系统提供的一类系统接口,它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务。

RT-Thread 操作系统提供软件实现的定时器,以时钟节拍(OS Tick)的时间长度为单位,即定时数值必须是 OS Tick 的整数倍,例如一个 OS Tick 是 10ms,那么上层软件定时器只能是 10ms,20ms,100ms 等,而不能定时为 15ms。RT-Thread 的定时器也基于系统的节拍,提供了基于节拍整数倍的定时能力。

2.3 RT-Thread的定时器

RT-Thread 的定时器可以分为 HARD_TIMER 模式与 SOFT_TIMER 模式:

image.png

SOFT_TIMER 模式可配置,通过宏定义 RT_USING_TIMER_SOFT 来决定是否启用该模式。该模式被启用后,系统会在初始化时创建一个 timer 线程,然后 SOFT_TIMER 模式的定时器超时函数在都会在 timer 线程的上下文环境中执行。(理解:上图的线程环境就是指这个线程)可以在初始化 / 创建定时器时使用参数 RT_TIMER_FLAG_SOFT_TIMER 来指定设置 SOFT_TIMER 模式。

疑问:RT-Thread中的全局变量rt_tick值溢出怎么办?

2.4 周期定时器与单词定时器

/* 定时器 1 超时函数 */
static void timeout1(void *parameter)
{rt_kprintf("periodic timer is timeout %d\n", cnt);/* 运行第 10 次,停止周期定时器 */if (cnt++>= 9){rt_timer_stop(timer1);rt_kprintf("periodic timer was stopped! \n");}
}/* 定时器 2 超时函数 */
static void timeout2(void *parameter)
{rt_kprintf("one shot timer is timeout\n");
}

区别:RT-Thread周期定时器通过用户手动停止rt_timer_stop(timer1);

3 RT-Thread 程序内存分布

一般 MCU 包含的存储空间有:片内 Flash 与片内 RAM,RAM 相当于内存,Flash 相当于硬盘编译器会将一个程序分类为好几个部分,分别存储在 MCU 不同的存储区。

4 RT-Thread启动流程

image.png

5 RT-Thread程序内存分布

5.1 区分RO,RW,ZI段

RO 段RW 段ZI 段
常量形式的全局变量则放置在 RO 段中,是只读属性的存放的是具有初始值的全局变量ZI 段存放的系统未初始化的全局变量

6 线程

6.1 什么是线程上下文

当线程运行时,它会认为自己是以独占 CPU 的方式在运行,线程执行时的运行环境称为上下文,具体来说就是各个变量和数据,包括所有的寄存器变量、堆栈、内存信息等

6.2 静态线程对象和动态线程对象的区别

  1. 静态线程对象的内存空间,包括线程控制块 thread1 与栈空间 thread1_stack 都是编译时决定的,存放在RW段或者ZI段中,通过定义全局变量来实现。静态对象会占用 RAM 空间,不依赖于内存堆管理器,内存分配时间确定
/* 线程 1 的对象和运行时用到的栈 */ 
static struct rt_thread thread1; 
static rt_uint8_t thread1_stack[512];
  1. 动态线程对象通过一个创建函数来实现,依赖于内存堆管理器,运行时申请 RAM 空间,当对象被删除后,占用的 RAM 空间被释放
/* 创建线程 2 */ /* 线程的入口是 thread2_entry, 参数是 RT_NULL * 栈空间是 512,优先级是 250,时间片是 25 个 OS Tick */ 
thread2_ptr = rt_thread_create("thread2", thread2_entry, RT_NULL, 512, 250, 25);
  1. 动态线程是系统自动从动态内存堆上分配栈空间与线程句柄(初始化 heap 之后才能使用 create 创建动态线程),静态线程是由用户分配栈空间与线程句柄

6.3 线程工作机制

线程控制块
由结构体 struct rt_thread 表示
image.png

6.4 线程错误码

#define RT_EOK           0 /* 无错误     */
#define RT_ERROR         1 /* 普通错误     */
#define RT_ETIMEOUT      2 /* 超时错误     */
#define RT_EFULL         3 /* 资源已满     */
#define RT_EEMPTY        4 /* 无资源     */
#define RT_ENOMEM        5 /* 无内存     */
#define RT_ENOSYS        6 /* 系统不支持     */
#define RT_EBUSY         7 /* 系统忙     */
#define RT_EIO           8 /* IO 错误       */
#define RT_EINTR         9 /* 中断系统调用   */
#define RT_EINVAL       10 /* 非法参数      */

6.5 线程状态切换的一些函数代码

image.png

线程通过调用函数 rt_thread_create/init() 进入到初始状态(RT_THREAD_INIT);初始状态的线程通过调用函数 rt_thread_startup() 进入到就绪状态(RT_THREAD_READY);就绪状态的线程被调度器调度后进入运行状态(RT_THREAD_RUNNING);当处于运行状态的线程调用 rt_thread_delay(),rt_sem_take(),rt_mutex_take(),rt_mb_recv() 等函数或者获取不到资源时,将进入到挂起状态(RT_THREAD_SUSPEND);处于挂起状态的线程,如果等待超时依然未能获得资源或由于其他线程释放了资源,那么它将返回到就绪状态。挂起状态的线程,如果调用 rt_thread_delete/detach() 函数,将更改为关闭状态(RT_THREAD_CLOSE);而运行状态的线程,如果运行结束,就会在线程的最后部分执行 rt_thread_exit() 函数,将状态更改为关闭状态。

6.6 线程在实时操作系统中的注意点

  1. 线程中不能陷入死循环操作,必须要有让出 CPU 使用权的动作,如循环中调用延时函数或者主动挂起。

7 内核对象管理架构

RT-Thread 内核对象包括:线程,信号量,互斥量,事件,邮箱,消息队列和定时器,内存池,设备驱动等。对象容器中包含了每类内核对象的信息,包括对象类型,大小等。对象容器给每类内核对象分配了一个链表,所有的内核对象都被链接到该链表上,RT-Thread 的内核对象容器及链表如下图所示:

image.png

7.1 RT-Thread 中各类内核对象的派生和继承关系

image.png

ipc术语理解: IPC 对象(IPC:Inter-Process Communication,进程间通信

7.2 内核对象容器的数据结构

struct rt_object_information
{/* 对象类型 */enum rt_object_class_type type;/* 对象链表 */rt_list_t object_list;/* 对象大小 */rt_size_t object_size;
};

一类对象由一个 rt_object_information 结构体来管理,每一个这类对象的具体实例都通过链表的形式挂接在 object_list 上。而这一类对象的内存块尺寸由 object_size 标识出来(每一类对象的具体实例,他们占有的内存块大小都是相同的)。

7.3 静态对象和动态对象

在 RT-Thread 操作系统中,一个系统对象也就是一个静态对象,对象类型标识上 RT_Object_Class_Static 位置位。通常使用 rt_object_init() 方式初始化的对象都是系统对象。


http://www.ppmy.cn/news/1443737.html

相关文章

Maven的基础使用

1 Maven概述 引入案例:idea创建javaWeb项目,如何打包并发布tomcat上去,以便于客户端访问? 方案一:DOS命令完成打包,操作性不方便,代码频繁修改,频繁使用命令打包一阶段可以打包&am…

源码篇--Nacos服务--中章(8):Nacos服务端感知客户端实例变更(集群数据校验)-4

文章目录 前言一、集群数据校验:二、数据校验过程2.1 心跳定时任务:2.2 客户端版本数据发送:2.2.1 任务的添加:2.2.2 任务的执行: 2.3 服务端本数据处理:2.4 客户度数据全量推送: 总结 前言 本…

赋能智慧校园!A3D数字孪生可视化,轻量又高效!

放假之后,学生们会逐步返学,大量人员出入校园,安全更是不容忽视,如何在短时间内对大批人员及设施进行智能监管?数字化转型是关键手段,我们可以融合线上线下数据,搭建3D立体的智慧校园&#xff0…

WebGL/Cesium 大空间相机抖动 RTE(Relative to Eye)实现原理简析

在浏览器中渲染大尺寸 3D 模型:Speckle 处理空间抖动的方法 WebGL/Cesium 大空间相机抖动 RTE(Relative to Eye)实现原理简析 注: 相机空间和视图空间 概念等效混用 1、实现的关键代码 const material new THREE.RawShaderMaterial({uniforms: {cameraPostion: {…

人人开源框架运行

Getting started renrenio/renren-fast-vue Wiki GitHub 人人开源 1.启动navicat:新建一个数据库renren-fast,字符集为utf-8,utf-8mb3或者utf-8mb4,排序规则不选 2.数据库操作在renren-fast数据库中选择表,运行renren-fast-ma…

【C++ STL序列容器】list 双向链表

文章目录 【 1. 基本原理 】【 2. list 的创建 】2.1 创建1个空的 list2.2 创建一个包含 n 个元素的 list(默认值)2.3 创建一个包含 n 个元素的 list(赋初值)2.4 通过1个 list 初始化另一个 list2.5 拷贝其他类型容器的指定元素创…

Java各种Map实现类以及特点

目录 1. HashMap 2. LinkedHashMap 3. TreeMap 4. Hashtable 5. ConcurrentHashMap 6. WeakHashMap 7. IdentityHashMap 8. EnumMap 1. HashMap 特性: 无序集合,基于哈希表实现。允许存储null键和null值。不保证映射的顺序;顺序可能随时间发生变…

机器人--机械臂的组成

控制器 控制器-----机器人的大脑。 简单视频介绍 怎么发挥作用的 组成 固定的硬件可实现的软件控制器。 作用 1. 控制器:动作指令信号的输出装置。 2. 驱动器:接收控制器发出的指令,并驱动马达(电机)的运动。 3. 伺服马达:…