1.å¨å¦ä¹ freertosä¹åï¼åºå¦ä¹ åªäºä¸è¥¿
2.在学习freertos之前,源码阅读应学习哪些东西
3.FreeRTOS源码探析之——消息队列
4.FreeRTOSv202212.01移植到STM32
5.FreeRTOS系列教程(四):如何使用信号量
6.FreeRTOS系列教程(六):如何使用队列集
å¨å¦ä¹ freertosä¹åï¼åºå¦ä¹ åªäºä¸è¥¿
ããå¦ä¹ FreeRTOSåçåå¤å·¥ä½
ããè¿éåªè¦å好两ç¹å°±å¯ä»¥äºã
ãã1,源码阅读 ä»å®ç½ä¸è½½ææ°çç¨åºå
ãã2, å®ç½æFreeRTOSæ¯ä¸ªå½æ°çAPI说æï¼å·²ç»ç¸åºAPIçä¾åï¼å ¶å®æºç ç.hæ件éé¢ä¹æ大é¨åå½æ°ç使ç¨ä¾å
ãã æç¨è®¡å
ãã1 å æèªå·±åçè¿å 个ä¾å讲解ä¸ä¸ï¼å ³é®æ¯åæä¸ä¸æºç ï¼æºç å¿ é¡»å¾åæï¼è¦ä¸ç¥å ¶ç¶ä¸ç¥å ¶æ以ç¶ã
ãã2 ç¶åæå®æ¹çè¿å 个ä¾å讲解ä¸ä¸ï¼è¯´è¿å 个ä¾åç主è¦ç®çæ¯å åå¦ä¹ å®æ¹æ¯å¦ä½ä½¿ç¨è¿ä¸ªRTOSçï¼é常æåèä»·å¼ã
ãã3 é对æ们æ¿åèªå·±çå¤è®¾ï¼åä¸å¥å®æ´çï¼åºäºFreeRTOSçåºå±é©±å¨ï¼è®©è¿äºé©±å¨è½å¤æ´å ææçå¨FreeRTOSä¸é¢å·¥ä½ã
在学习freertos之前,应学习哪些东西
学习FreeRTOS前的源码阅读准备工作 这里只要做好两点就可以了。 1,源码阅读 从官网下载最新的程序包 2, 官网有FreeRTOS每个函数的API说明,已经相应API的源码阅读例子,其实源码的源码阅读信源码怎么去.h文件里面也有大部分函数的使用例子 教程计划 1 先把自己做的这几个例子讲解一下,关键是源码阅读分析一下源码,源码必须得分析,源码阅读要不知其然不知其所以然。源码阅读 2 然后把官方的源码阅读这几个例子讲解一下,说这几个例子的源码阅读主要目的是充分学习官方是如何使用这个RTOS的,非常有参考价值。源码阅读 3 针对我们板子自己的源码阅读外设,做一套完整的源码阅读,基于FreeRTOS的源码阅读底层驱动,让这些驱动能够更加有效的在FreeRTOS下面工作。在学习freertos之前,应学习哪些东西
FreeRTOS源码探析之——消息队列
消息队列是FreeRTOS中的一种关键数据结构,用于实现进程间通信。其运作机制首先由FreeRTOS分配内存空间给消息队列,并初始化为空,此时队列可用。任务或中断服务程序可以给消息队列发送消息,发送紧急消息时,消息将直接放置于队头,确保接收者能优先处理。这种机制保证了紧急消息的优先级。
为了防止消息队列被并发读写时的混乱,FreeRTOS提供了阻塞机制,确保操作的进程能够顺利完成,不受其他进程干扰。接收消息时,若队列为空,进程可选择等待,直到消息到达。在发送消息时,只有队列允许入队时,发送才成功,避免了队列溢出。优先级较高的进程将优先访问消息队列,这通过任务优先级排序实现。
消息队列控制块包含了队列的管理信息,如消息存储位置、易语言源码转换成e4a源码头尾指针、消息大小和队列长度等。这些信息在创建队列时即被初始化,并且无法改变。每个消息队列与消息空间共享同一段连续内存,只有在队列被删除时,这段内存才会被释放。消息队列长度在创建时指定,决定了消息空间总数。
FreeRTOS通过xQueueGenericCreate()函数创建消息队列,该函数首先分配内存,然后初始化队列。初始化过程涉及队列长度和消息大小等参数的设置,并通过xQueueGenericReset()函数进行队列复位。
队列复位时,vListInitialise()函数构建了列表结构,这是消息队列内部的组织形式。列表结构体定义了节点类型,而vListInitialise函数初始化了列表,为消息队列的使用做好准备。
发送消息时,xQueueSend()或其底层实现xQueueGenericSend()函数根据参数选择发送位置。默认情况下,消息会发送至队尾。接收消息则通过xQueueReceive()或xQueueGenericReceive()函数实现,参数通常包括队列句柄和接收的消息指针。
消息队列的发送和接收过程中,若队列已满或为空,可能会触发任务切换,以避免阻塞进程。这种机制确保了消息队列在进程间通信中的高效和有序,是FreeRTOS系统中实现进程间协作的关键组件。
FreeRTOSv.移植到STM
介绍
将FreeRTOSv.移植到STMFC8T6单片机的过程概述。此版本为当前最新,适用于开发者进行系统级编程。
硬件平台
选用STMFC8T6作为移植目标,此型号单片机提供丰富的外设资源,适合各种嵌入式应用。
软件架构与操作步骤
1. 从freertos.org/zh-cn-cmn下载源代码。注意,V9.0以后版本由Amazon收购后开发,V9.0被认为较为稳定。带溯源码和不带溯源码五常大米本文档介绍的移植方法适用于最新版本,与旧版本相比,源代码变化不大,可进行对比学习。
2. 解压源码并复制FreeRTOS目录内容至项目目录下。删除除Source文件夹外的所有文件,Source文件夹是核心模块,包含实际移植所需的文件。
3. 进入Source文件夹,删除非源代码文件,保留include和portable目录,前者包括头文件,后者为接口文件。
4. 进入Source下的portable文件夹,删除非必要的文件和文件夹(如RVDS和MemMang),仅保留与M3内核相关的ARM_CM3接口文件以及heap_4.c,其余可保留但暂不使用。
5. 从FreeRTOSv.\FreeRTOS\Demo\CORTEX_STMF_Keil复制FreeRTOSConfig.h至include文件夹。此配置文件用于系统裁剪。
6. 将保留的文件添加到工程中,并配置文件路径。确保编译无错误。
创建任务的详细步骤
在main.c文件中,创建任务。关注stmfx_it.h文件,增加xPortSysTickHandler外部声明,并注释掉SVC_Handler和PendSV_Handler。SysTick_Handler作为定时器回调函数,用于调度处理。
在FreeRTOSConfig.h中添加中断宏定义,由port.c中的汇编语言实现,用于任务启动和切换。设置INCLUDE_xTaskGetSchedulerState为1。
在main.h中加入RTOS头文件,包含操作系统所需的所有调用文件。
至此,重新编译即可运行程序。最后,确保工程总目录包含标准库stdlib(3.5.0版本),以支持完整的硬件抽象层。
FreeRTOS系列教程(四):如何使用信号量
大家好,我是开源的源码和原来的源码一样吗旭辉君,一个智能硬件领域深度探索的技术博主。
在上篇文章中,我们理解了在FreeRTOS中如何使用消息队列进行任务间的数据传递,链接如下:
本文我们就一起来探索信号量的使用。所谓信号量,可以简单的理解为就是一个状态标志,我们可以用这个状态标志来进行任务间的同步,有序访问,或者互斥访问。从这些对于信号量不同的应用,常用的信号量可以分为:
本文我们将重点讲述二值信号量与计数信号量的使用。互斥信号量放在下一篇文章讲解。通过本文,我们将会知道:
接下来让我们一起,进入信号量的探索之旅!
如前文所述,信号量可以提供任务间数据的同步机制。我们假设有两个任务TaskA和TaskB,其中TaskB等待TaskA产生的数据并进行处理,按照之前我们在裸机编程时候的思路,一般都是设置一个全局变量,然后在while1中轮流执行这两个任务,若TaskA产生的数据让这个全局变量发生改变,TaskB在轮询到之后就能处理这些数据,但是,如果TaskA里面的数据久久不发生改变,那么一直轮询TaskB就是无效的,CPU做了许多的无用功。
所以应该怎么优化呢?
假若在TaskA数据发生不改变的时候,TaskB进入阻塞态不执行,当TaskA数据发生改变的时候才去执行TaskB,这样就不会浪费CPU的资源。为此,FreeRTOS引入了信号量(Semaphore)概念,通过信号量的同步机制可以使任务在数据还没到达的时候进入阻塞状态,在数据到达之后才得以执行,提高系统资源利用率。
二进制信号量只有两个状态,只能用于两个任务间的同步;计数信号量中信号量的数目可以自定义设定为多个,可用于多个任务间的同步。
创建信号量时, 系统会为创建的主图源码和副图源码一起导入信号量对象分配内存, 二值信号量的最大可用信号量个数为 1。创建成功后,任何任务都可以从创建的二值信号量资源中获取这个二值信号量,获取成功则任务继续运行, 否则任务会根据用户指定的阻塞超时时间来等待其它任务或者中断释放信号量。在等待这段时间,系统将任务变成阻塞态, 任务将被挂到该信号量的阻塞等待列表中。下图为任务获取信号量时的示意图:获取信号量无效时任务进入阻塞,其他任务释放信号量后,信号量有效,该任务恢复为就绪态。
相比于二值信号量,计数信号量允许多个任务获取同一个信号量,这多个任务的数目可以由我们设定。比如我们设定,某个资源只能有 3 个任务访问,那么第 4 个任务访问的时候,会因为获取不到信号量而进入阻塞,等到有任务(比如任务 1)释放掉该资源的时候,第 4 个任务才能获取到信号量从而进行资源的访问,其运作的机制具体见下图:
观察信号量控制块结构体以及信号量创建函数的源码,我们就会惊奇的发现:FreeRTOS 的信号量控制块结构体与消息队列结构体是一模一样的!信 号 量 的 创 造 实 际 调 用 的 函 数 xQueueGenericCreate()也与消息队列一样!只是参数或者其代表的意义有一些差异。
所以我们可以理解为:信号量就是一种特殊的消息队列!由于我们只关注信号状态,不关注消息内容,这个队列就没有设置消息存储空间。
其中,xSemaphoreCreateBinary()是一个宏定义,展开后调用xQueueGenericCreate(),也就是上一篇文章我们创建队列时候使用的函数,只是传递的参数不同。
与二值信号量一样,xSemaphoreCreateCounting()展开后也是调用xQueueGenericCreate(),创建的计数信号量只有消息队列控制块结构体存储空间而没有消息存储空间 。
删除信号量函数vSemaphoreDelete()是一个宏定义,其调用的是vQueueDelete()函数。删除信号量过程其实就是删除消息队列过程, 因为信号量其实就是特殊的,无法存储消息的消息队列。
xSemaphoreGive()是一个用于释放信号量的宏, 真正的实现该过程是调用消息队列通用发送函数xQueueGenericSend()。释放信号量实际上是一次入队操作,并且阻塞时间为0,也就是释放信号量时,如果信号量计数值已满,就返回信号量释放错误。
xSemaphoreTake()是一个用于获取信号量的宏, 真正的实现该过程是调用消息队列通用接收函数xQueueGenericReceive()。信号量获取实际上就是一次消息出队操作,所以我们也可以按照消息队列的接收机制来理解信号量的获取:当有任务试图获取信号量的时候,当且仅当信号量有效,也就是队列中存在可用信号量的时候,任务才能获取到信号量。
如果信号量无效,在用户指定的阻塞超时时间中,该任务将保持阻塞状态以等待信号量有效。在阻塞超时等待的时间内,如果有其它任务或中断释放了有效的信号量,该任务将自动由阻塞态转移为就绪态。如果任务等待的时间超过了指定的阻塞时间,即使信号量中还是没有可用信号量,任务也会自动从阻塞态转移为就绪态。
创建三个任务,task_example_1,task_example_2和task_example_3。其中task_example_1用于计时,每3s让task_example_2释放二值信号量,task_example_3用于信号量获取,在获取不到信号量的时候一直死等。主体代码如下:
下图为运行后的串口输出结果:可以看到,cnt计数的时候,每3s释放一个二值信号量,然后立即就能被获取到,实现了Task2与Task3两个任务间的同步。
创建计数信号量xSemaphoreCreateCounting(5,3),其中参数5表示最大可容纳五个状态,任务每获取一个信号量,信号量计数减一,每释放一个信号量,信号量计数加一。初始值为3,表示初始里面已经有了三个信号量。同样三个任务,task_example_3每ms获取一个信号量, task_example_2每2s释放一个信号量,task_example_1用于每1s的计时显示。程序主体代码如下:
运行程序后串口输出如下:可以看到,初始计数信号量有3个,随着不断获取,计数信号量为空,之后就获取失败,只有计数信号量释放后才能继续获取。
本文主要探索了二值信号量与计数信号量的原理及其使用方法,包括信号量的原理,信号量的运行机制,信号量与消息队列的比较,信号量的相关API函数,以及信号量的使用实验等。通过本文,不知道大家对第一节的几个问题,有没有自己的答案。有疑问的同学,欢迎评论区留言交流。原创不易,大家的点赞和关注是对我持续更新最大的鼓励,谢谢!也为坚持看到系列文章此处的你点赞!
想要文中工程源码的同学,可以关注我的微信公众号:硬件电子与嵌入式小栈,留言:freertos源码 即可获取。同时我还整理了一些学习FreeRTOS实用的书籍资料,公众号留言:freertos资料 即可获取。公众号里也会不定期更新干货文章哦。
FreeRTOS系列教程(六):如何使用队列集
本文主要探讨FreeRTOS中的队列集功能,如何在多任务环境下实现高效的消息传递和信号处理。队列集允许任务同时等待多个队列或信号量,解决单一资源等待可能导致的阻塞问题。
在传统的FreeRTOS实现中,任务只能逐一处理消息队列或信号量。例如,任务A需要接收消息并获取信号量,如果消息队列无数据,信号量未释放,任务A会阻塞。队列集的引入则提供了解决方案:创建一个队列集,任务A不断从队列集中获取消息,根据句柄类型(队列或信号量)执行相应操作,这样就能确保任务在收到任何类型的事件时都能立即响应,避免了阻塞。
队列集的使用涉及几个关键API函数,如xQueueCreateSet()用于创建队列集,xQueueAddToSet()和xQueueRemoveFromSet()用于添加和删除队列,xQueueSelectFromSet()用于从队列集中获取消息。通过这些函数,可以灵活地管理任务之间的通信。
接下来,我们通过一个实验展示了队列集的应用。创建三个任务,任务1优先级最高,用于接收队列集中的消息。实验结果显示,任务能及时响应队列或信号量的变化,无论消息队列还是二值信号量,都能使任务从阻塞状态恢复。
总结来说,队列集是FreeRTOS中提升任务协作效率的重要工具,它扩展了任务的并发处理能力,降低了阻塞风险。如果你对队列集的使用还有疑问,欢迎在评论区交流。感谢你的关注与支持,如果你需要相关源码或学习资料,可关注微信公众号:硬件电子与嵌入式小栈,获取更多信息和资源。
搞懂 RTOS 需要哪些方面的知识储备?
想要深入理解RTOS?首先,你需要掌握哪些关键知识?</ 如同学习驾驶前必须先掌握基础技能,理解RTOS并非一蹴而就,而是需要循序渐进。切勿急于求成,直接跳入理论深渊。就好比一位新手司机,若无驾驶基础,贸然学习修车只会事倍功半。首要步骤,是从实践出发,选择一个易于上手的平台,如μCOS-II。 建议的学习路径如下:首先,找一块已经移植了μCOS-II的微控制器,运行起来。仔细阅读示例代码,理解如何运用μCOS的基本功能,比如实现一个能控制三个不同频率闪烁的LED灯。
当对μCOS的API运用自如后,再逐步深入理论,阅读操作系统原理书籍。将抽象的概念如堆栈、上下文切换、调度器、锁、文件系统、网络、中断管理、线程和消息队列(邮件箱)等与实践相结合,尝试编写一个多任务的HTTP服务器,并用μCOS重构现有代码。
接下来,挑战自己,阅读μCOS早期版本的源代码,理解操作系统实现的核心原理。这时,操作系统原理的理论知识将为你的理解提供更坚实的基石。
当你有了初步的实战经验后,尝试将μCOS移植到新的芯片上,避免依赖搜索引擎,独立解决问题,锻炼解决问题的能力。
不要害怕改动,试着修改μCOS的原始代码,观察系统行为的变化,理解每一步改动的影响。
最后,查阅μCOS的版本演化历史,理解代码优化和设计选择背后的逻辑,这样你才能真正领悟到RTOS的精髓所在。
记住,学习RTOS是一个实践与理论相结合的过程,一步步脚踏实地,你将逐渐掌握这个强大工具的关键知识。STM上的FreeRTOS实时操作系统
FreeRTOS是一款在嵌入式系统中广泛使用的实时操作系统,而STM是一系列由STMicroelectronics开发的微控制器。
在STM上使用FreeRTOS可以充分利用其多核处理能力,并实现多任务管理、任务调度等功能。下面将详细介绍如何在STM上使用FreeRTOS,并给出一些示例代码。
首先,确保你已经具备以下硬件准备:
- STM开发板
- 串行调试接口(如ST-LINK)用于下载程序
- 集成开发环境(IDE),如Keil MDK或STMCubeIDE
- FreeRTOS源代码
在创建一个新的FreeRTOS项目之前,需要对FreeRTOS进行配置。主要的配置包括选择所需的内核功能、任务数和任务堆栈大小等。这些配置的具体方法可以参考FreeRTOS的官方文档。
在FreeRTOS中,任务是最基本的执行单元。以下是一个简单的示例,展示了如何创建两个任务并实现它们的简单调度。
在FreeRTOS中,使用RTOS API可以进行任务的创建、删除、挂起和恢复等操作。以下是一些常用的API示例:
在使用FreeRTOS时,需要进行硬件准备,配置FreeRTOS,创建任务,并使用RTOS API进行任务管理和通信操作。通过合理地调度任务、管理资源和进行任务间通信,可以实现复杂的嵌入式应用程序。
FreeRTOS与STM的结合,使嵌入式系统的性能和稳定性得到显著提升,为开发人员提供了强大的工具来创建高效且可靠的多任务系统。