超过460,000+ 应用技术资源下载
pdf

FreeRTOS概览

  • 1星
  • 日期: 2018-09-06
  • 大小: 412.95KB
  • 所需积分:1分
  • 下载次数:0
  • favicon收藏
  • rep举报
  • 分享
  • free评论
标签: FreeRTOS概览

学习FreeRTOS不错的入门资料

文档内容节选

FreeRTOS FreeRTOS读作freearrtoss是一个嵌入式系统使用的开源实时操作系统FreeRTOS 被设计为小巧, 简单,和易用,能支持许多不同硬件架构以及交叉编译器 FreeRTOS 自 2002 年 Richard Barry 开始开发以来,一直都在积极开发中至于我,我不是 FreeRTOS 的开 发人员或贡献者,我只不过是一个最终用户和爱好者因此,这章将着重与 FreeRTOS 架构之是什么和怎 么做,而相对本书其他章节来说,较少去讲为什么 就像所有操作系统一样,FreeRTOS 的主要工作是执行任务大部分 FreeRTOS 的代码都涉及优先权 调度以及执行用户自定义任务但又与所有其他操作系统不同,FreeRTOS 是一款运行在嵌入式系统上的 实时操作系统 到本章结束,我希望你可以了解 FreeRTOS 的基本架构大部分 FreeRTOS 致力于执行任务,所以你 可以很好地看到它究竟是如何做到的 如果这是你首次去深入了解一个操作系统,我还是希望你可以学习到最基本的操作系统是如何工作的 FreeRTOS 是相对简单的,特别是相比 Windows,linux......

FreeRTOS FreeRTOS(读作"free-arr-toss")是一个嵌入式系统使用的开源实时操作系统。FreeRTOS 被设计为“小巧, 简单,和易用”,能支持许多不同硬件架构以及交叉编译器。 FreeRTOS 自 2002 年 Richard Barry 开始开发以来,一直都在积极开发中。至于我,我不是 FreeRTOS 的开 发人员或贡献者,我只不过是一个最终用户和爱好者。因此,这章将着重与 FreeRTOS 架构之“是什么”和“怎 么做”,而相对本书其他章节来说,较少去讲“为什么”。 就像所有操作系统一样,FreeRTOS 的主要工作是执行任务。大部分 FreeRTOS 的代码都涉及优先权、 调度以及执行用户自定义任务。但又与所有其他操作系统不同,FreeRTOS 是一款运行在嵌入式系统上的 实时操作系统。 到本章结束,我希望你可以了解 FreeRTOS 的基本架构。大部分 FreeRTOS 致力于执行任务,所以你 可以很好地看到它究竟是如何做到的。 如果这是你首次去深入了解一个操作系统,我还是希望你可以学习到最基本的操作系统是如何工作的。 FreeRTOS 是相对简单的,特别是相比 Windows,linux,或者 OS X 而言,不过所有操作系统都有着相同 的概念和目标,所以不论学习哪个操作系统都是有启发和有趣的。 3.1 什么是“嵌入式”和“实时”? “嵌入式”和“实时”对于不同的人来说代表不同的理解,所以让我们像 FreeRTOS 用户那样来定义它们。 嵌入式系统就是一个专门设计用来做一些简单事情的计算机系统,就像是电视遥控器,车载 GPS,电子手 表,或者起搏器这类。嵌入式系统比通用计算机系统显著的区别在于更小和更慢,通常也更便宜。一个典 型的低端嵌入式系统可能有一个运行速度为 25MHz 的 8 位 CPU,几 KB 的内存,和也许 32KB 的闪存。 一个高端的嵌入式系统可能有一个运行速度为 750MHz 的 32 位 CPU,一个 GB 左右的内存,和几个 GB 的闪存。 实时系统是设计去完成一定时间内的事,它们保证这些事是在应该做的时候去做。 心脏起搏器是实时嵌入式系统的一个极好例子。起搏器必须在正确的时间收缩心肌,以挽救你的生命; 它不能够太忙而没有及时响应。心脏起搏器以及其他的实时嵌入式系统都必须精心设计,以便在任何时刻 都能及时执行它们的任务。 3.2 架构概述 FreeRTOS 是一个相对较小的应用程序。最小化的 FreeRTOS 内核仅包括 3 个( .c )文件和少数头文 件,总共不到 9000 行代码,还包括了注释和空行。一个典型的编译后(二进制)代码映像小于 10KB。 FreeRTOS 的代码可以分解为三个主要区块:任务,通讯,和硬件接口。 ● 任务:大约有一半的 FreeRTOS 的核心代码用来处理多数操作系统首要关注的问题:任务。任务是给定 优先级的用户定义的 C 函数。task.c 和 task.h 完成了所有有关创建,调度,和维护任务的繁重工作。 ● 通讯:任务很重要,不过任务间可以互相通讯则更为重要!它给我们带来 FreeRTOS 的第二项任务:通 讯。大约 40%的 FreeRTOS 核心代码是用来处理通讯的。 queue.c 和 queue.h 是负责处理 FreeRTOS 的通讯 的。任务和中断使用队列互相发送数据,并且使用信号量和互斥来发送临界资源的使用情况。 ● 硬件接口:接近 9000 行的代码拼凑起基本的 FreeRTOS,是硬件无关的;相同的代码都能够运行,不论 FreeRTOS 是运行在不起眼的 8051,还是最新、最炫的 ARM 内核上。大约有 6%的 FreeRTOS 的核心代码, 在硬件无关的 FreeRTOS 内核与硬件相关的代码间扮演着垫片的角色。我们将在下个部分讨论硬件相关的 代码。 硬件注意事项 FreeRTOS 硬件无关的 FreeRTOS 层在硬件相关层之上。硬件相关层声明了你选择什么样的芯片架构。图 3.1 显 示了 FreeRTOS 的各层。 图 3.1:FreeRTOS 的软件层 FreeRTOS 包含所有你需要用来启动很运行系统的硬件无关以及硬件相关的代码。它支持许多编译器 (CodeWarrior,GCC,IAR 等)也支持许多处理器架构(ARM7,ARM Cortex-M3,PICs 各系列,Silicon Labs 8051, x86 等)。请参阅 FreeRTOS 网站,可以看到处理器和编译器支持列表。 FreeRTOS 是高可配置设计。FreeRTOS 可以被编译成为适合单 CPU,极简 RTOS,只之支持少数任务 的操作系统,也可以被编译成为适合多核功能强大的结合了 TCP/IP,文件系统,和 USB 的怪兽。 配置选项可以通过设置不同的 #defines ,在 FreeRTOSConfig.h 文件里选择。时钟速度,堆大小,互斥, 和 API 子集,连同其他许多选项,都可以在这个文件中配置。这里是几个例子,设置了任务优先级的最大 数量,CPU 的频率,系统节拍器的频率,最小的堆栈大小和总的堆大小: #define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 ) #define configCPU_CLOCK_HZ ( 12000000UL ) #define configTICK_RATE_HZ ( ( portTickType ) 1000 ) #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 100 ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 4 * 1024 ) ) 对于不同的交叉编译器和 CPU 架构,硬件相关代码分布在多个文件中。举例来说,如果你使用 ARM Cortex-M3 芯片,IAR 编译器工作,那么硬件相关的代码就存在 FreeRTOS/Source/portable/IAR/ARM_CM3/ 目录 下。 portmacro.h 文件声明了所有硬件特定功能, port.c 和 portasm.s 包含了所有实际硬件相关的代码。硬件 无关的头文件 portable.h 在编译的时候用 #include's 引入正确的 portmacro.h 文件。FreeRTOS 使用 #define'd 调用在 portmacro.h 中声明的硬件特定功能。 让我们来看一个例子,FreeRTOS 是如何调用一个硬件相关功能的。硬件无关的文件 tasks.c 常常需要 插入一个代码的临界区,以防止抢占。在不同架构上,插入一个临界区的表现也不同,并且硬件无关的 task.c 不需要了解硬件相关的细节。所以 task.c 调用全局宏指令 portENTER_CRITICAL() , 乐得忽略它实际上 是如何做到的。假设我们使用 IAR 编译器在 ARM Crotex-M3 芯片上编译生成 FreeRTOS,使用那个定义了 portENTER_CRITICAL() 的文件 /Source/portable/IAR/ARM_CM3/portmacro.h ,如下所示: #define portENTER_CRITICAL() vPortEnterCritical() vPortEnterCritical() 实际上是在 FreeRTOS/Source/portable/IAR/ARM_CM3/port.c 中定义的。这个 port.c 文件是一个 硬件相关的文件,同时包含了对 IAR 编译器和 Cortex-M3 芯片认识的代码文件。 vPortEnterCritical() 函数利 用这些硬件特定的知识进入临界区,又返回到与硬件无关的 task.c 中。 protmacro.h 文件也定义了一个数据类型的基本架构。这个数据类型中包括了基本整型变量,指针,以及系 统时钟节拍器的数据类型,在 ARM Cortex-M3 chips 上使用 IAR 编译器时,就采用如下定义: FreeRTOS #define portBASE_TYPE long // Basic integer variable type #define portSTACK_TYPE unsigned long // Pointers to memory locations typedef unsigned portLONG portTickType; // The system timer tick type 这样使用数据类型的方法,和函数透过小层的 #defines ,看上去略微有点复杂,不过它允许了 FreeRTOS 能 够被重新编译在一个完全不同的系统架构上,仅仅只需要通过修改这些硬件相关的文件。同时,如果你想 要让 FreeRTOS 运行在一个当前尚未被支持的架构上,你只仅仅需要去实现硬件相关的功能,这要比在 FreeRTOS 上去实现硬件无关的部分,要少得多。 就如同我们已经见到的,FreeRTOS 用 C 的预处理宏 #define 来实现硬件相关的功能。FreeRTOS 也同 样用 #define 来应对大量的硬件无关的代码。对于非嵌入式应用程序这样频繁使用 #define 是一个严重的错 误,不过在许多小型嵌入式系统中这点开销比起“实时”所提供的功能来说就微不足道了。 3.3. 调度任务:快速概述 任务优先级和就绪列表 所有任务都有一个用户指定优先级,从 0(最低优先级)到 configMAX_PRIORITIES-1 的编译时间值(最 高优先级)。例如,如果 configMAX_PRIORITIES 设置为 5,当 FreeRTOS 使用 5 个优先等级时:0(最低优 先级),1,2,3,和 4(最高优先级)。 FreeRTOS 使用一个“就绪列表”来跟踪所有已经准备好运行的任务。它像一个任务列表数组来实现就 绪列表,如下所示: static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; // Prioritised ready tasks. pxReadyTasksLists[0] 是所有准备好的优先级为 0 的任务列表,pxReadyTasksLists[1] 是所有准备好的优先级为 1 的任务列表,以此类推,直到 pxReadyTasksLists[configMAX_PRIORITIES-1] 。 系统节拍器(时钟) FreeRTOS 系统的心跳就是被称为系统节拍器(时钟)。FreeRTOS 配置这个系统生成一个定期的节拍 (时钟)中断。用户可以配置的节拍中断频率,通常是在毫秒范围。 vTaskSwitchContext() 函数在每次的节拍 中断释放的时候被调用。 vTaskSwitchContext() 选择优先级最高的就绪任务并将它赋予 pxCurrentTCB 变量, 如下所示: /* Find the highest-priority queue that contains ready tasks. */ while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) { configASSERT( uxTopReadyPriority ); --uxTopReadyPriority; } // listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the same // priority get an equal share of the processor time. listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); 在当型循环(while loop)开始之前,uxTopReadyPriority 就被确保大于或等于优先级最高的就绪任务。while() 循环从优先级 uxTopReadyPriority 开始,循环走下去从 pxReadyTasksLists[] 数组里找到就绪任务优先级最高的 那个。接着 listGET_OWNER_OF_NEXT_ENTRY() 就抢占那个就绪列表中优先级最高的下一个就绪任务。 现在 pxCurrentTCB 指向了优先级最高的任务,并且当 vTaskSwitchContext() 返回硬件相关代码时开始运行那 个任务。 那九行代码是 FreeRTOS 的绝对核心。其余 FreeRTOS 的 8900+行代码都是用来确保那九行代码,全 都是用来保持优先级最高任务的运行的。 图 3.2 是一个大致的就绪列表看起来像什么的图。这个例子有三个优先级,有一个优先级为 0 的任务, 没有优先级为 1 的任务,和三个优先级为 2 的任务。这张图是准确的,但不完整的;它的少掉一些细节,我 们稍后将补充。 FreeRTOS 图 3.2:FreeRTOS 的就绪列表的基本视图 现在我们有了大致概述的方式,让我们去深究它的细节。我们将着眼于三个主要 FreeRTOS 的数据结 构:任务,列表和队列。 3.4. 任务 所有操作系统的主要工作是运行和协调用户任务。像多数操作系统一样,FreeRTOS 中的基本工作单 元是任务。FreeRTOS 的使用任务控制块(TCB)来表示每个任务。 任务控制块(TCB) TCB 的在 tasks.c 定义是这样的: typedef struct tskTaskControlBlock { // Points to the location of the last item placed on the tasks stack. // THIS MUST BE THE FIRST MEMBER OF THE STRUCT. volatile portSTACK_TYPE *pxTopOfStack; // List item used to place the TCB in ready and blocked queues. xListItem xGenericListItem; // List item used to place the TCB in event lists. xListItem xEventListItem; // The priority of the task where 0 is the lowest priority. unsigned portBASE_TYPE uxPriority; // Points to the start of the stack. portSTACK_TYPE *pxStack; FreeRTOS // Descriptive name given to the task when created. Facilitates debugging only. signed char pcTaskName[ configMAX_TASK_NAME_LEN ]; #if ( portSTACK_GROWTH > 0 ) // Used for stack overflow checking on architectures where the stack grows up from low memory. portSTACK_TYPE *pxEndOfStack; #endif #if ( configUSE_MUTEXES == 1 ) // The priority last assigned to the task - used by the priority inheritance mechanism. unsigned portBASE_TYPE uxBasePriority; #endif } tskTCB; TCB 在 pxStack 里存储堆栈的起始地址,以及在 pxTopOfStack 里存储当前堆栈的顶部。如果堆栈“向 上”增长到更高的地址,它还在 pxEndOfStack 存储堆栈的结束的指针来检查堆栈溢出。如果堆栈“向下”增长 到更低的地址,那么通过比较当前堆栈的顶部与 pxStack 中的堆内存起始位置来检查溢出。 TCB 在 uxPriority 和 uxBasePriority 中存储任务的初始优先级。一个任务在它创建的时候被赋予优先级, 同时任务的优先级是可以被改变的。如果 FreeRTOS 实现了优先级继承,那么当任务临时提升到“继承的” 优先级时,它使用 uxBasePriority 去记住原来的优先级。(优先级继承,请参见下面关于互斥的讨论。) 每个任务有两个清单项目给 FreeRTOS 操作系统的各种调度列表使用。当一个任务被插入到 FreeRTOS 的 一个列表中,不会直接向 TCB 插入一个指针。取而代之的是,它向 TCB 的 xGenericListItem 或 xEventListItem 插入一个指针。这些 xListItem 变量,比起若是仅仅获得一个指向 TCB 的指针来说,让 FreeRTOS 的列表 变得更加灵活。 任务可以在以下四种状态之一:运行,准备运行,挂起或阻塞。你可能希望每个任务都有一个变量来 告诉 FreeRTOS 它正处于什么状态,但事实上并非如此。相反,FreeRTOS 通过把任务放入相应的列表: 就绪列表,挂起列表等,隐式地跟踪任务状态。随着任务的变化,从一个状态到另一个,FreeRTOS 的只 是简单的将它从一个列表移动到另一个。 任务设置 我们已经触及如何利用 pxReadyTasksLists 数组来选择和调度一个任务的;现在让我们来看一看一个任 务最初是如何被创建的。当 xTaskCreate() 函数被调用的时候,一个任务被创建。FreeRTOS 为一个任务新分 配一个 TCB 对象,来记录它的名称,优先级,和其他细节,接着分配用户请求的总的堆栈(假设有足够 使用的内存)和在 TCB 的 pxStack 成员中记录堆内存的开始。 堆栈被初始化看起来就像一个已经在运行的新任务被上下文切换所中断。这就是任务调度处理最新创 建的任务的方法,同样也是处理运行了一段时间的任务的方法;任务调度在不需要任何特殊(case)代码 的情况下去处理新的任务。 任务的堆栈建立看起来像是它通过上下文切换来被中断,这个方法是取决于 FreeRTOS 正在运行的架 构,但这个 ARM Cortex-M3 处理器的实现是一个很好的例子: unsigned int *pxPortInitialiseStack( unsigned int *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) { /* Simulate the stack frame as it would be created by a context switch interrupt. */ pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ pxTopOfStack--; *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ pxTopOfStack--; *pxTopOfStack = 0; /* LR */
更多简介内容

推荐帖子

EEDrone开源四旋翼从零开始(6)--FreeRTOS CLI调试
本帖最后由 lb8820265 于 2017-2-17 10:28 编辑       ST在16年末对STM32F7的库文件进行了一次重要的升级,推出了LL库,该库与HAL库功能类似,LL库相当于操作寄存器,可分别单独使用也可以共同使用,HAL库的效率低下是受人诟病的,高频率的uart与tim都不敢用,LL库就解决了这个问题。因此接下来的工程中所有的初始化采用HAL库,其他的操作全部使用LL代
lb8820265 DIY/开源硬件专区
新人求助stm32在FreeRtos下的PWM读取
各位前辈,我现在在用一个传感器,其中两个引脚分别输出两个PWM信号,我准备用STM32F4discover的板子在Freertos下面进行数据读取,我看了官方的例程,我用的笨办法就是用两个Timer分别捕获一路的PWM信号。但是我现在的问题是代码在网站上我找到了,也明白具体是怎么工作的了,但是现在就是不懂要是在Freertos下面怎么进行修改,比如怎么设置task。这里我想请有经验的前辈给我指点一
haohongyu 【stm32/stm8】
STM32F+FreeRTOS+IAR, 令人抓狂的问题
小弟虽然玩C/C++快十年了,但刚接触MCU不到3个月,今天算是栽上了。问题描述如下:环境: MCU : STM32F207ZG  OS: FreeRTOS 7.1.1 Toolchain: IAR EWARM 6.30.7.3447 固件库: STM32F2xx_StdPeriph_Lib_V1.1.0 (基本没用到,主要使用了其中的CMSIS中的IAR启动文件)所以整个工程代码就是ST
carylin 【stm32/stm8】
我接触过的嵌入式操作系统——基于时间片的嵌入式系统,RTX,FREERTOS,RT-THREAD
本帖最后由 ddllxxrr 于 2019-11-21 09:49 编辑 1,基于时间片触发的操作系统 我记得这是个美国人写的,当时我用来做个键盘。结果,不适用,因为有一位质检过不去,后为我用循环加嵌套,也就是说没有用操作系统,实现了这个键盘。但我对操作系统从此画了个问号。这个东东有用么????? 2,RTX51 这个是我司一个大老用RTX51写的一个小程序。也是我接触操作
ddllxxrr 嵌入式系统编程
我接触过的嵌入式操作系统——rtx51、freertos等
本帖最后由 dcexpert 于 2019-11-20 18:31 编辑 1. 听说过哪些嵌入式操作系统,是否实际使用过嵌入式操作系统   使用单片机多年了,从51单片机,到AVR、PIC,STM32等,也用过或研究过一些rtos,如rtx51、smll rtos、freertos、ucos、OSA、mbed os、rt-thread等。有的RTOS现在发展的不错,有的已经消失很久了
dcexpert 嵌入式系统编程
【GE32E231_DIY】FreeRTOS+DAP_RTT+多功能按键+USART_DMA再加入FREEMODBUS
FreeRTOS+DAP_RTT+多功能按键+USART_DMA再加入FREEMODBUS 到这里,项目一步一步实现了,一步一步调试真不容易。感谢家人的支持,成有时间码代码。 freemodbus主要思想是用状态机实现,发送—中断。接收—中断,硬时间确认,加一轮询 int main(void) {     systick_config(); //    button
boming 【GD32 MCU】

评论


个人中心

意见反馈

求资源

回顶部

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

EEWorld电子技术资料下载——分享有价值的资料

北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved
$(function(){ var appid = $(".select li a").data("channel"); $(".select li a").click(function(){ var appid = $(this).data("channel"); $('.select dt').html($(this).html()); $('#channel').val(appid); }) })