零基础STM32单片机编程入门(五)FreeRTOS实时操作系统详解及实战含源码视频

文章目录

    • 一.概要
    • 二.什么是实时操作系统
    • 三.FreeRTOS的特性
    • 四.FreeRTOS的任务详解
      • 1.任务函数定义
      • 2.任务的创建
      • 3.任务的调度原理
    • 五.CubeMX配置一个FreeRTOS例程
      • 1.硬件准备
      • 2.创建工程
      • 3.调试FreeRTOS任务调度
    • 六.CubeMX工程源代码下载
    • 七.讲解视频链接地址
    • 八.小结

一.概要

FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等,可基本满足较小系统的需要。
由于RTOS需占用一定的系统资源(尤其是RAM资源),只有μC/OS-II、embOS、salvo、FreeRTOS等少数实时操作系统能在小RAM单片机上运行。相对μC/OS-II、embOS等商业操作系统,FreeRTOS操作系统是完全免费的操作系统,具有源码公开、可移植、可裁减、调度策略灵活的特点,可以方便地移植到各种单片机上运行。

二.什么是实时操作系统

操作系统是一个控制程序,作为硬件和应用程序之间的桥梁,主要是和硬件打交道,负责协调分配计算资源和内存资源给不同的应用程序使用,并防止系统出现故障。面对来自不同应用程序的大量且互相竞争的资源请求,操作系统通过一个调度算法和内存管理算法尽可能把资源公平且有效率地分配给不同的程序。应用程序则通过调用操作系统提供的API接口获得相应资源完成指定的任务。

实时操作系统(RTOS-Real Time Operating System)中实时(Real Time)指的是任务(Task)或者说实现一个功能的线程(Thread)必须在给定的时间(Deadline)内完成。

三.FreeRTOS的特性

具有抢占式或者合作式的实时操作系统内核
功能可裁剪,最小占用10kB左右rom空间,0.5kB ram空间
灵活的任务优先级分配
具有低功耗模式
有互斥锁、信号量、消息队列等功能
运行过程可追踪
支持中断嵌套

四.FreeRTOS的任务详解

FreeRTOS的核心是任务调度器(Task Scheduler),它负责按照一定的调度策略将任务分配给处理器执行。每个任务都是一个独立的函数,可以有不同的优先级和堆栈大小。任务调度器根据任务的优先级和调度策略决定哪个任务被执行。

下图就是任务调度简单介绍
在这里插入图片描述

下面代码就是个简单的示例代码,通过调用osThreadCreate函数创建了两个任务LED_Thread1(驱动LED灯灭)和LED_Thread2(驱动LED灯亮)。在main函数中,通过调用osKernelStart函数启动了实时系统,使得任务可以被调度执行,由于两个任务都能不断运行,所以能驱动LED灯闪烁。

//定义任务函数1
void LED_Thread1(void const * argument)
{(void) argument;for (;;){HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);//PC13输出高,LED灭osDelay(100);//等待100ms}
}
//定义任务函数2
void LED_Thread2(void const * argument)
{(void) argument;for (;;){HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);//PC13输出低,LED亮osDelay(250);//等待250ms}
}int main(void)
{HAL_Init();SystemClock_Config();//外部8M晶振,系统72M主频MX_GPIO_Init();//PC13配置成推挽输出MX_FREERTOS_Init();//实时系统初始化/* Start scheduler */osThreadDef(THREAD1, LED_Thread1, osPriorityNormal, 0, 128);THREAD1Handle = osThreadCreate(osThread(THREAD1), NULL);//建立任务1/* definition and creation of THREAD2 */osThreadDef(THREAD2, LED_Thread2, osPriorityNormal, 0, 128);THREAD2Handle = osThreadCreate(osThread(THREAD2), NULL);//建立任务2osKernelStart();//实时系统启动while (1){}}

1.任务函数定义

无论采用何种方法创建任务,均需要用到任务函数。FreeRTOS 规定任务函数的返回值必须为void,而且带有一个void型指针参数。

void LED_Thread1(void const * argument)
{(void) argument;for (;;){HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);//PC13输出高,LED灭osDelay(100);//等待100ms}
}

STM32F103C8T6单片机只有一个内核,那怎么让多个人同时干活呢?其实每个子任务虽然都是死循环,但并不是每个子任务一直都在执行,每个子任务在执行期间,可能需要延时,这边就通过 osDelay(100),等待100ms,单片机就可以停止此任务,然后切换到其它任务执行,这样看起来就是多个人在同时干活了。

2.任务的创建

osThreadDef(THREAD1, LED_Thread1, osPriorityNormal, 0, 128);//定义一个任务,任务名,任务函数,优先级,堆栈大小
THREAD1Handle = osThreadCreate(osThread(THREAD1), NULL);  //根据上面定义的任务,创建一个任务

osThreadDef函数中的128是任务栈大小定义:

任务栈大小指定了任务可以使用多少RAM来存储局部变量和其他临时数据。这个大小应该足够大,能够容纳任务在执行期间可能出现的最大需求。

osThreadDef函数中的LED_Thread1是任务函数:

任务函数是任务执行的代码,它应该是一个无返回值的函数,其参数是一个可选的指针,可以用来传递任何需要的数据,我们代码中的任务就是控制GPIO输出高或者低电平。

osThreadDef函数中的osPriorityNormal任务优先级:

任务优先级决定了任务在操作系统调度下的执行顺序。数值越大,优先级越高。

osThreadCreate函数的返回值THREAD1Handle是任务句柄:

任务句柄是一个指针,可以用来引用已经创建的任务,以便可以在任务创建后对其进行操作,例如删除、挂起、恢复等。

3.任务的调度原理

FreeRTOS默认使用抢占式调度策略,对同等优先级的任务使用时间片轮询调度,时间片轮询就是可轮流享有相同的单片机时间(可设置),一个时间片等于SysTick中断周期。
抢占式调度是指调度器始终运行优先级最高且处于可运行状态的任务,无论任务何时可以运行。如在中断服务函数中更改了优先级最高且可运行的任务,调度器会停止当前执行的低优先级任务,并启动高优先级任务。
刚才程序中的osDelay 是通过将当前任务加入到延时列表中,并设置一个定时器来在指定的延时时间,延时时间过去之后将任务从延时列表中移除并将其设置为就绪状态。这样当定时器触发时,任务重新被加入到就绪列表中,等待被调度器再次调度执行。

上面代码中的LED_Thread1(驱动LED灯灭)和LED_Thread2(驱动LED灯亮)两个任务的调度顺序以及时间,如下图所示,横坐标是时间,箭头代表运行顺序
在这里插入图片描述

下面代码截图就是操作系统底层寻找就绪任务的最高优先级,获取优先级最高的就绪任务的 TCB(任务控制块),然后更新到 pxCurrentTCB ,当前运行的任务只可能有一个,因此pxCurrentTCB只是单个TCB_t指针,它始终指向当前运行的任务。通过xPortPendSVHandler(PendSV_Handler)函数实现调度
在这里插入图片描述
PendSV_Handler 是 ARM Cortex-M 处理器中的一个特殊的中断处理函数,用于处理挂起 PendSV(Pending Supervisor Call)中断。PendSV 中断是 Cortex-M 架构中的一种特殊的软件中断,它可以用来实现任务切换或者其他与系统调度相关的操作。
PendSV_Handler 在中断向量表的位置
在这里插入图片描述

__asm void xPortPendSVHandler( void ){extern uxCriticalNesting;extern pxCurrentTCB;extern vTaskSwitchContext;PRESERVE8mrs r0, psp //(1)        读取进程栈指针,保存在寄存器 R0 里面。isbldr r3, =pxCurrentTCB//(2)   获取当前任务的任务控制块,并将任务控制块的地址保存在寄存器 R2 里面。ldr r2, [r3] //(3)tst r14, #0x10 //(4)        判断任务是否使用了 FPUit eq //(5)vstmdbeq r0!, {s16-s31}// (6)stmdb r0!, {r4-r11, r14} //(7)str r0, [r2] //(8)stmdb sp!, {r3} //(9)mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY //(10)       msr basepri, r0 //(11)           关闭中断,进入临界区dsbisbbl vTaskSwitchContext //(12)    调用函数 vTaskSwitchContext(),此函数用来获取下一个要运行的任务,并将pxCurrentTCB 更新为这个要运行的任务。mov r0, #0 //(13)msr basepri, r0 //(14)        打开中断,退出临界区。ldmia sp!, {r3} //(15)ldr r1, [r3] //(16)ldr r0, [r1] //(17)ldmia r0!, {r4-r11, r14} //(18)tst r14, #0x10 //(19)it eq //(20)vldmiaeq r0!, {s16-s31} //(21)msr psp, r0 //(22)           更新进程栈指针 PSP 的值isbbx r14 //(23)     执行此行代码以后硬件自动恢复寄存器 R0~R3、 R12、 LR、 PC 和 xPSR 的值,确定异常返回以后应该进入处理器模式还是进程模式,使用主栈指针(MSP)还是进程栈指针(PSP)。很明显这里会进入进程模式,并且使用进程栈指针(PSP),寄存器 PC 值会被恢复为即将运行的任务的任务函数,新的任务开始运行!至此,任务切换成功。}

五.CubeMX配置一个FreeRTOS例程

1.硬件准备

STLINK接STM32F103C8T6小系统板,STLINK接电脑USB口。

在这里插入图片描述

2.创建工程

打开STM32CubeMX软件,新建工程
在这里插入图片描述
Part Number处输入STM32F103C8,再双击就创建新的工程
在这里插入图片描述
配置下载口引脚
在这里插入图片描述
配置外部晶振引脚
在这里插入图片描述

可以查看STM32F103C8T6小系统板原理图,PC13连接LED灯,所以配置PC13为GPIO输出

在这里插入图片描述
配置FreeRTOS
在这里插入图片描述
配置系统主频
在这里插入图片描述
配置工程文件名,保存路径,KEIL5工程输出方式
在这里插入图片描述
生成工程
在这里插入图片描述
用Keil5打开工程
在这里插入图片描述
添加代码
在这里插入图片描述
在这里插入图片描述

3.调试FreeRTOS任务调度

调试代码,能更好理解任务调度。
下载调试,在LED_Thread1打断点,程序能运行到断点处停止
在这里插入图片描述
在LED_Thread2打断点,程序也能运行到断点处停止
在这里插入图片描述

在xPortPendSVHandler调度函数中打断点,可以看到操作系统将要跳转到任务1运行
在这里插入图片描述
单步执行,运行指针就跳转到任务1开始运行
在这里插入图片描述

xPortPendSVHandler调度函数中打断点,可以看到操作系统将要跳转到任务2运行
在这里插入图片描述
单步执行,运行指针就跳转到任务2开始运行
在这里插入图片描述

六.CubeMX工程源代码下载

链接:https://pan.baidu.com/s/1f50X8w2UXnDtbM6U6zwYqw
提取码:0sys
如果链接失效,可以联系博主给最新链接

程序下载下来之后解压就行

七.讲解视频链接地址

FreeRTOS实验

八.小结

FreeRTOS实时操作系统能使在STM32软件开发中,程序结构清晰,单片机执行效率提升许多,在多个任务模块的代码中,可以考虑使用FreeRTOS。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/365460.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新版一键AI视频图片换脸神器来了!目前最强的AI视频换脸工具Swapface!

之前发过一款AI换脸工具,可惜部署门槛太高, 有没有换头换脸的AI工具? 今天就给你们安排到家! Swapface AI工具一键开箱包‍(一键整合包添加下方领取~) 它使用先进的人工智能和计算机视觉技术,可以在几秒…

秋招突击——6/24——复习{完全背包问题——买书,状态转换机——股票买卖V}——新作{两数相除,LRU缓存实现}

文章目录 引言复习完全背包问题——买书个人实现 状态转换机——股票买卖V个人实现参考实现 新作两数相除个人实现 新作LRU缓存实现个人实现unordered_map相关priority_queue相关 参考实现自己复现 总结 引言 今天知道拼多多挂掉了,难受,那实习就是颗粒无…

体验升级:扫描全能王智能高清滤镜2.0全面测评

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

【接口自动化测试】第四节.实现项目核心业务的单接口自动化测试

文章目录 前言一、登录单接口自动化测试 1.1 登录单接口文档信息 1.2 登录成功 1.3 登录失败(用户名为空)二、数据驱动的实现 2.1 json文件实现数据驱动总结 前言 一、登录单接口自动化测试 1.1 登录单接口文档信息 需求&#xff1…

LeetCode 子集

原题链接78. 子集 - 力扣(LeetCode) 这是一道暴力搜索问题参考大佬们的题解,对这类题目做出一下总结 1.确定递归参数变量 2.递归结束条件 3.做出选择,递归调用进入下一层 4.回溯,返回到递归前的状态 要完成前面这…

【Matlab函数分析】imread从图形文件读取图像

🔗 运行环境:Matlab 🚩 撰写作者:左手の明天 🥇 精选专栏:《python》 🔥 推荐专栏:《算法研究》 #### 防伪水印——左手の明天 #### 💗 大家好🤗&#x1f91…

Qt6.6编译Qt二维图形编辑器QVGE源码

QVGE是一个开源的多平台QtC编写的图形编辑器,可以用来画网络节点图,或者其他作用。 QVGE可以轻松创建和参数设定的小型到中型图形(1000节点/边缘),共同的视觉特性的节点和边缘:形状、尺寸、颜色、标签等。定义(用户定义)属性的图表…

前端技术(二)——javasctipt 介绍

一、javascript基础 1. javascript简介 ⑴ javascript的起源 ⑵ javascript 简史 ⑶ javascript发展的时间线 ⑷ javascript的实现 ⑸ js第一个代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>…

探究Qt5【元对象编译器,moc】的 设计原理和技术细节

Qt5是一个跨平台C框架&#xff0c;它有个突出的特点就是其元对象系统&#xff0c;该系统通过扩展C的能力&#xff0c;为事件处理提供了信号与槽机制、为对象内省提供了属性系统。为了支持这些特性&#xff0c;Qt引入了元对象编译器&#xff08;Meta-Object Compiler, MOC&#…

C++视觉开发 一.OpenCV环境配置

一.OpenCV安装环境配置 1.OpenCV安装 &#xff08;1&#xff09;下载 官方下载链接&#xff1a;http://opencv.org/releases 这边选择需要的版本&#xff0c;我是在windows下的4.9.0。&#xff08;科学上网下载很快&#xff0c;否则可能会有点慢&#xff09; (2)安装 双击下…

使用systemd管理Linux下的frps服务:安装、配置及自动化操作指南

在 Linux 系统下&#xff0c;使用 systemd 可以方便地控制 frps 服务端的启动、停止、配置后台运行以及开机自启动。以下是具体的操作步骤&#xff1a; 1. 安装 systemd 如果您的 Linux 服务器上尚未安装 systemd&#xff0c;可以使用包管理器如 yum&#xff08;适用于 Cent…

基于RabbitMQ的异步消息传递:发送与消费

引言 RabbitMQ是一个流行的开源消息代理&#xff0c;用于在分布式系统中实现异步消息传递。它基于Erlang语言编写&#xff0c;具有高可用性和可伸缩性。在本文中&#xff0c;我们将探讨如何在Python中使用RabbitMQ进行消息发送和消费。 安装RabbitMQ 在 Ubuntu 上安装 Rabbi…

GaussDB关键技术原理:高性能(三)

GaussDB关键技术原理&#xff1a;高性能&#xff08;二&#xff09;从查询处理综述对GaussDB的高性能技术进行了解读&#xff0c;本篇将从查询重写RBO、物理优化CBO、分布式优化器、布式执行框架、轻量全局事务管理GTM-lite等五方面对高性能关键技术进行分享。 目录 3 高性能…

PyTorch之nn.Module、nn.Sequential、nn.ModuleList使用详解

文章目录 1. nn.Module1.1 基本使用1.2 常用函数1.2.1 核心函数1.2.2 查看函数1.2.3 设置函数1.2.4 注册函数1.2.5 转换函数1.2.6 加载函数 2. nn.Sequential()2.1 基本定义2.2 Sequential类不同的实现2.3 nn.Sequential()的本质作用 3. nn.ModuleList参考资料 本篇文章主要介绍…

AI绘画-Stable Diffusion 原理介绍及使用

引言 好像很多朋友对AI绘图有兴趣&#xff0c;AI绘画背后&#xff0c;依旧是大模型的训练。但绘图类AI对计算机显卡有较高要求。建议先了解基本原理及如何使用&#xff0c;在看看如何实现自己垂直行业的绘图AI逻辑。或者作为使用者&#xff0c;调用已有的server接口。 首先需…

Open3D (C++) 点云旋转至主成分空间

目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 首先使用主成分分析法计算出点云的特征值与特征向量,然后根据点云的特征向量计算出点云与主成分空间之间的…

CAM350怎么添加文字?

CAM350怎么添加文字&#xff1f; CAM350只能修改用CAM350本身做的文字&#xff0c;其它软件生成的GERBER文件导入到CAM350会默认为线条&#xff0c;没办法修改。 如果想添加文字&#xff0c;先把原先的文字删除。然后在CAM350里面重新添加文字就可以了。 操作方法如下&#xf…

Java代码生成器(开源版本)

一、在线地址 Java在线代码生成器&#xff1a;在线访问 二、页面截图 三、核心功能 支持Mybatis、MybatisPlus、Jpa代码生成使用 antlr4 解析SQL语句&#xff0c;保证了SQL解析的成功率支持自定义包名、作者名信息支持自定义方法名、接口地址支持自定义选择是否生成某个方法…

力扣 单链表元素删除解析及高频面试题

目录 删除元素的万能方法 构造虚拟头结点来应对删除链表头结点的情况 一、203.移除链表元素 题目 题解 二、19.删除链表中倒数第K个节点 题目 题解 三、 83.删除某个升序链表中的重复元素&#xff0c;使重复的元素都只出现一次 题目 题解 82.删除某个升序链表中的…

mongodb在windows环境安装部署

一、mongodb 1.释义 MongoDB 是一种开源的文档型 NoSQL 数据库管理系统&#xff0c;使用 C 编写&#xff0c;旨在实现高性能、高可靠性和易扩展性。MongoDB 采用了面向文档的数据模型&#xff0c;数据以 JSON 风格的 BSON&#xff08;Binary JSON&#xff09;文档存储&#x…