零基础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.mzph.cn/diannao/38581.shtml

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

相关文章

[SwiftUI 开发] 嵌套的ObservedObject中的更改不会更新UI

1. 发生问题的demo 业务逻辑代码 class Address: ObservableObject {Published var street "123 Apple Street"Published var city "Cupertino" }class User: ObservableObject {Published var name "Tim Cook"Published var address Addr…

解决 Win11 微软拼音输入法下 JetBrains IDE Shift+F6 失效的问题

一、使用旧版微软拼音输入法 1.在任务栏中输入法图标上右键,点击“设置”,或者在系统设置中进入“时间和语言 -> 语言和区域 -> 微软拼音输入法”设置项。 2.点击进入“常规”类别,滚动到页面底部,找到“兼容性 -> 使用…

nacos漏洞小结

Alibaba Nacos是阿里巴巴推出来的一个新开源项目,是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。致力于帮助发现、配置和管理微服务。Nacos提供了一组简单易用的特性集,可以快速实现动态服务发现、服务配置、服务元数据及流量管理…

我的创作纪念日 第四年 我在人间遭罪,也在人间享乐

回顾 一晃四年过去了,从毕业到现在依旧没有后悔自己当初的选择是工作而不是继续读研。 读研虽然可以给我更高的起点,但破碎的底层建筑和生活压力让我没的选择,毕竟只是一介凡人,而且还是底层出身,环境差,观…

64、哥伦比亚大学:CU-Net-目前脑肿瘤分割的最先进模型

本文已被接受发表在2024年IEEE MLISE会议上(c)2024 IEEE。准确地将脑肿瘤从MRI扫描中分割出来对于制定有效的治疗方案和改善患者预后至关重要。本研究引入了一种新的哥伦比亚大学网络(CU-Net)架构实现,用于使用BraTS 2…

收银系统源码-千呼新零售2.0【移动管理端】

千呼新零售2.0系统是零售行业连锁店一体化收银系统,包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体,线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物等连锁店使用。 详细介绍请…

如何循环遍历循环中的剩余元素

1、问题背景 给定一段文本,文本中包含多条错误信息,每条错误信息包含行号、错误路径和错误信息。需要从文本中提取出这些错误信息,并以特定的格式输出。 line, Error 12, This is the Error line, Error 34, Another Error line, Error …

【Linux】线程周边002之线程安全

👀樊梓慕:个人主页 🎥个人专栏:《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 🌝每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.Linux线程互斥 1…

每日一题——Python实现PAT乙级1050 螺旋矩阵(举一反三+思想解读+逐步优化)6千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页:用哲学编程-CSDN博客专栏:每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 时间复杂度分析 空间复杂度分析 总结 我要更强 代码解释 时间复杂度 …

小区服务前台小程序的设计

管理员账户功能包括:系统首页,个人中心,住户管理,管理员管理,员工管理,安保管理,安保分配管理,客服聊天管理 微信端账号功能包括:系统首页,公告,…

Mongodb集群中的分布式读写

学习mongodb,体会mongodb的每一个使用细节,欢迎阅读威赞的文章。这是威赞发布的第81篇mongodb技术文章,欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题,欢迎在文章下面点个赞,或者关…

互联网摸鱼日报(2024-07-01)

互联网摸鱼日报(2024-07-01) 36氪新闻 最前线 | 孚能科技广州基地投产,年产能30GWh,主推SPS大软包产品 本周双碳大事:800亿元“风光火储”大项目来了;光伏巨头SolarEdge股价骤跌20%;韩国电池厂大火,锂电安…

目标检测算法的优缺点

目标检测算法在计算机视觉领域具有广泛的应用,其优缺点因算法类型和具体实现而有所不同。以下是对一些主流目标检测算法优缺点的概述: 1. 传统目标检测算法 优点: 模型简单:传统目标检测算法通常基于手工设计的特征和分类器&am…

Java进阶学习|Day3.Java集合类(容器),Stream的使用,哈希初接触

java集合类(容器) Java中的集合类主要由Collection和Map这两个接口派生而出,其中Collection接口又派生出三个子接口,分别是Set、List、Queue。所有的Java集合类,都是Set、List、Queue、Map这四个接口的实现类&#xf…

Powershell 简易爬虫,提取种子网站的磁力链接

目录 一. 需求二. 分析2.1 思路分析2.2 技术点 三. 代码四. 效果 一. 需求 ⏹有网站如下所示,先要求从按照关键词搜索到的网页中,提取出所有的磁力链接。 二. 分析 2.1 思路分析 打开网页之后,从网页中先提取出所有的标题相关的url然后再打…

linux驱动部分内容整理

文章目录 Linux驱动概念应用程序调用驱动程序流程驱动模块的加载linux设备号加载和卸载注册新字符设备注册设备节点自动创建设备节点编译编译驱动程序编译应用程序 地址映射ioctrl命令码的解析 并发与竞争原子操作自旋锁信号量互斥体 linux中断DMA映射其它printkmemcpyvolatile…

如何在ubuntu上安装ros-noetic?

如何在ubuntu上安装ros-noetic? 1. 源由2. 快速安装3. ROS学习 1. 源由 围绕ros-noetic这个系统,前面已经有不少谈及: Linux 35.5 JetPack v5.1.3ros-noetic安装Linux 35.5 JetPack v5.1.3Fast-Planner编译安装Linux 35.5 JetPack v5.1.…

RocketMQ常用基本操作

文章中的rabbitmq使用的是rocketmq-all-5.1.3-bin-release版本,需要安装包的可自行下载 RockerMQ启动停止命令 启动命令 nohup sh bin/mqnamesrv & nohup sh bin/mqbroker -n localhost:9876 --enable-proxy & 查看日志 tail -f ~/logs/rocketmqlogs/…

多线程编程的挑战与解决方案

多线程编程的挑战与解决方案 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 1. 多线程编程的挑战 在现代软件开发中,多线程编程成为处理并发任务…

PatchTST创新点

这篇论文的创新点主要集中在PatchTST模型的设计和应用中。以下是对其创新点的详细说明: 创新点 频道独立补丁设计:PatchTST模型通过将多变量时间序列分割成不同的频道,每个频道作为单变量时间序列处理。每个频道独立地通过实例归一化操作和补…