精华内容
下载资源
问答
  • 该资源包是基于STM32为基础的实战项目源代码,其中也包含了UCOS实战项目源代码,很适合初学者。
  • stm32 freertos项目模板

    2018-11-21 17:09:06
    此keil5项目FREERTOS V9.0的STM32移植项目模板,基于STM32F103开发,外部高速时钟频率为12MHz,可根据自己的MCU做对应更改。 目录介绍: startup:stm32官方启动文件; lib:st官方库; freertosfreertos系统...
  • FreeRTOS Labs项目的源代码和示例项目,源码有详细说明,简单操作,便于移植应用到其他项目
  • ESP32_FreeRTOS-SD卡 ESP32 FreeRTOS项目将数据记录到SDCard
  • C ++ FreeRTOS GCC 介绍 包含的库实现了在FreeRTOS中启用C ++多线程的接口。 那是: 创建线程-std :: thread,... 适用于ARM 32位的GCC 7.2和8.2(cmake生成Eclipse项目FreeRTOS 10.1.1 Windows 10 恩智浦MCUXpr
  • 每一个FreeRTOS Port都提供一个无错误、无警告的演示应用程序。建议通过调整现有项目创建新项目,这将允许项目包含正确的文件、安装正确的中断应用程序、和正确的编译器选项集。 从现在项目开始新的应用程序: ...

    1、基于提供的演示项目

    每一个FreeRTOS Port都提供一个无错误、无警告的演示应用程序。建议通过调整现有项目创建新项目,这将允许项目包含正确的文件、安装正确的中断应用程序、和正确的编译器选项集。

    从现在项目开始新的应用程序:

    1. 打开演示项目,并确保它按预期的方式编译和执行。
    2. 删除演示任务的源文件。任何位于Demo\Common目录中的文件都可以删除。
    3. 删除main()中所有调用函数,除了prvSetupHardware()和vTaskStartScheduler()。如下面代码片段。
    4. 检查项目直到正常编译。

      int main( void ) 
      { 
          /* Perform any hardware setup necessary. */ 
          prvSetupHardware(); 
       
          /* --- APPLICATION TASKS CAN BE CREATED HERE --- */ 
           
          /* Start the created tasks running. */ 
          vTaskStartScheduler(); 
           
          /* Execution will only reach here if there was insufficient heap to 
          start the scheduler. */ 
          for( ;; ); 
          return 0; 
      } 


    2、从头开始创建

    如前所述,建议从现有演示项目中创建新项目。 如果这是不可取的,则可以使用以下过程创建一个新项目:

    1. 使用您选择的工具链,创建一个尚未包含任何FreeRTOS源文件的新项目。
    2. 确保可以构建新项目,下载到目标硬件并执行。
    3. 只有当您确定已经有一个工作项目时,才能将项目中的FreeRTOS源文件添加到'Table 1'中。
    4. 将所使用端口提供的演示项目使用的FreeRTOSConfig.h头文件复制到项目目录中。
    5. 将以下目录添加到项目将搜索的头文件路径中:
      FreeRTOS / Source / include
      FreeRTOS / Source / portable / [compiler] / [architecture]
      包含FreeRTOSConfig.h头文件的目录
    6. 从相关演示项目复制编译器设置。
    7. 安装任何可能需要的FreeRTOS中断处理程序。 使用网页描述正在使用的端口,以及为使用的端口提供的演示项目作为参考。
    Table 1. FreeRTOS源文件
    FileLocation
    tasks.cFreeRTOS/Source
    queue.cFreeRTOS/Source
    List.cFreeRTOS/Source
    event_groups.cFreeRTOS/Source
    All C and asm fileFreeRTOS/Source/portable/[compiler]/[architecture]
    heap_n.cFreeRTOS/Source/portable/MemMang, n: 1,2,3,4 or 5
      



    展开全文
  • freertos项目编译总结 安装必要的编译环境。 1.1 安装arm-gcc :sudo apt-get install gcc-arm-none-eabi g++ 1.2 安装cmake:版本不能低于3.13.0 $ cd /opt $ sudo wget ...

    freertos项目编译总结

    1. 安装必要的编译环境。
      1.1 安装arm-gcc :sudo apt-get install gcc-arm-none-eabi g++
      1.2 安装cmake:版本不能低于3.13.0
        $ cd /opt
        $ sudo wget  https://cmake.org/files/v3.15/cmake-3.15.0.tar.gz
        $ sudo tar -zxv -f cmake-3.15.0.tar.gz
        $ cd  cmake-3.15.0
        $ sudo ./bootstrap
    ---------------------------------------------
        CMake 3.15.0, Copyright 2000-2018 Kitware, Inc. and Contributors
        Found GNU toolchain
        C compiler on this system is: gcc       
        C++ compiler on this system is: g++  -std=gnu++1z        
        Makefile processor on this system is: make
        g++ has setenv
        g++ has unsetenv
        g++ does not have environ in stdlib.h
        g++ has stl wstring
        g++ has <ext/stdio_filebuf.h>
    ---------------------------------------------
        $ sudo make
        $ sudo make install
    
    1.3  cmake  --version 查看版本号 看是否安装上
    
    1. 拉去源代码:git clone https://github.com/aws/amazon-freertos.git --recurse-submodules
    2. 进入源代码目录: cd amazon-freertos
    3. 在amazon-freertos目录下创建:mkdir build 文件
    4. 再执行: cmake -DVENDOR=st -DBOARD=stm32l475_discovery -DCMAKE_C_FLAGS=-std=gnu11 -DCOMPILER=arm-gcc -S . -B build
    5. 进入build 文件:make
    展开全文
  • STM32CubeIDE构建通用freertos项目(一)

    千次阅读 2020-03-12 17:52:04
    感慨 本人大约三四年没有碰... 工程方面值的是freertos工程。 背景需求 做任何事情都要有目标,朝着目标去前进。本文关注的目标如下: 1. 代码如何复用,达到多项目复用的目的 2. 如何满足多项目复用的前提下...

    感慨

    本人大约三四年没有碰单片机了,遥想当年我还是用的keil工具。
    有幸以援助的身份介入公司的嵌入式项目,结合自身经验讲讲。
    工作是一个长期的过程,开头不注意则会产生蝴蝶效应,导致接下来的工作一直处于挖坑填坑的状态,最终大好青春年华耗费在一些无谓的事情上。
    本文不过多去讲具体操作,只描述针对问题的思考方式。
    工程方面指的是freertos工程。

    背景需求

    做任何事情都要有目标,朝着目标去前进。本文关注的目标如下:
    1. 代码如何复用,达到多项目复用的目的
    2. 如何满足多项目复用的前提下,又不混淆各自的代码模块

    分析

    代码复用,在嵌入式中,关键是模块的复用。模块又分为硬件模块和软件模块两类。同时,不管是硬件模块还是软件模块,关键点上要有相应的模块测试。

    硬件模块

    硬件模块主要是驱动相关的函数操作,见识过linux驱动的小伙伴应该知道有四个关键点需要实现: 加载、卸载、读、写。
    同时,硬件模块分为内设和外设。内设驱动通过工程配置可以自动生成;外设驱动往往需要自己开发。

    软件模块

    软件模块是衔接硬件和业务主体的中间层,开发过程中一定要注意解耦。软件模块必须在不同硬件平台上是可移植的!

    模块测试

    代码要复用,必须有相应的模块测试,否则更换硬件平台时,很大概率看着一堆跑不起来的代码发呆。

    工程结构

    .ioc文件和.xml文件配置

    要实现不同硬件平台下的工程代码复用,首先要按照不同工程去创建不同的ioc文件,该文件涉及硬件平台,每次调整修改后,会重新生成内设驱动,内设驱动文件直接生成在Src目录下;并且include配置也会被刷新掉。
    随便打开一个内设驱动代码,添加部分说明,如下:

    void ADC_IRQHandler(void)
    {
      /* USER CODE BEGIN ADC_IRQn 0 */
      // USER CODE注释之间的代码,重新生成是不会消失的
      /* USER CODE END ADC_IRQn 0 */
      HAL_ADC_IRQHandler(&hadc1);
      /* USER CODE BEGIN ADC_IRQn 1 */
      // USER CODE注释之间的代码,重新生成是不会消失的
      /* USER CODE END ADC_IRQn 1 */
    }
    

    include配置被刷掉的话,通过以下Import和Export即可解决,将会保存为.xml文件,其中包括了include路径和define;define的设置尤为关键,用它来实现硬件设施的切换
    导入导出
    总结,硬件设施由.ioc来定义,而.xml则定义了软件行为,在不同的硬件设施下,对应不同的软件行为,采用切换文件配置来实现代码统一维护。

    代码目录

    	在了解STM32CubeIDE开发工具的特点以及模块测试相关内容后,简要讲解一下代码上要如何排布。
    	源文件目录,分为硬件模块dev、框架配置framework、业务主体main、软件架构soft、测试单元test,如下:
    

    在这里插入图片描述

    	头文件目录,则少了业务主体和测试单元相应的头文件,因为这两者是引用别人,同时不必暴露自身变量和函数,故无需提供头文件。	
    

    在这里插入图片描述

    依赖关系

    学过java的同学,会知道一个细节,当import一个不使用的包时,IDE会给你相应的提示。而在C/C++的IDE中,则没有那么方便的提示。所以在写C工程时,需要仔细处理好依赖关系,要有一定的章法,而不是随意引用,能够运行就不管了。
    仿造Nginx源码的组织方式,在Nginx中,有一个头文件ngx_core.h包含了所有头文件,而其他文件统一引用该文件即可。
    那么在STM32CubeIDE中,哪个文件适合干这种事呢?答案是main.h文件!主要原因在于,其包含是自动生成的内设驱动;并在其中添加咱自定义的config.h文件,之后不再动main.h文件。

    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    #include "config.h"
    /* USER CODE END Includes */
    

    config

    config主要用途在于控制一个函数指针指向,参数及返回不是关键点,为void即可,声明如下:

    void (*init)(void);
    

    调用方放在freertos.c中,该文件生成时已经引用了main.h,从而引用了config.h

      /* USER CODE BEGIN RTOS_THREADS */
    	init();
      /* USER CODE END RTOS_THREADS */
    

    至此,已经分离解耦了硬件设施和软件设施,通过一个init函数指针来衔接。
    控制工程行为自然是采用宏定义来完成,代码如下:

    #if(PRO==CONFIG_MAIN)
    	extern void main_init();
    	void(*init)(void) = main_init;
    #elif(PRO==CONFIG_TEST_HTTP)
    	extern void test_http_init(void);
    	void(*init)(void) = test_http_init;
    #endif
    

    只需要在Symbols中配置好,即可完成不同功能的切换。
    在这里插入图片描述

    开发流程

    上面讲述了关键点,具备了一个通用工程架构的基础雏形,还需要一定的开发流程规范才能完整。
    首先,你需要一个完整的A项目,而B项目和A项目,仅仅是少量需求不同,硬件接口也可能稍有不同。
    接着,构建好B项目的ioc文件,自动生成代码,然后将A项目中的测试逐个在B项目上运行,运行不通过的地方,使之兼容,并确保A项目不受影响。
    最后,开开心心在上面开发你的B项目吧,可别忘了export你的xml配置哟。

    展开全文
  • FreeRTOS 是由Richard Barry在2003年由设计的,由于其设计的小巧简单,整个核心代码只有3到4个C文件。在设计之初就异军突起,累计开发者数百万,是目前市场占有率最高的RTOS,现在FreeRTOS已经支持三十多种芯片,...
  • FreeRTOS 实时系统 源码

    2019-01-10 21:26:39
    基于STM32F103平台的FreeRTOS 实时系统源码程序,应用在实际项目中,包含有RTC实时时钟,ModBus协议通信,IIC, 外部EEPROM存储器,HT1621液晶驱动,等等;
  • freeRTOS嵌入式实时操作系统在Windows平台下的示例程序,免去初学者没有硬件平台的烦恼,快速入门。freeRTOS初学者必备资料。
  • 在keil MDK中编译通过之后,进入debug模式,可以直接用软件仿真查看RTOS系统任务的运行机制,详情请看readme文档。
  • stm32移植FreeRTOS操作系统,写了个例程,通过串口中断收发数据控制LED亮灭
  • STM32F407FReeRTOS工程

    2018-07-02 22:53:27
    使用STM32CUBEMX工具生成代码,具体配置见.ioc文件,项目freertos,和多个串口,串口DMA接收,运行稳定。
  • FreeRTOS includes libraries that are part of the FreeRTOS 202012.00 LTS release. Learn more about the FreeRTOS 202012.00 LTS libraries at https://freertos.org/lts-libraries.html. Getting started The ...
  • 基于STM32F103RBT6的FreeRTOS的移植与实现。工程为MDK Keil V5的,功能为建立2个小任务,实现LED按不同的时间闪烁,运行正常。可以作为移植后的模板程序使用。
  • 2.3 移植FreeRTOS 2.3.1 内核配置文件 FreeRTOS内核是高度可定制的,使用配置文件FreeRTOSConfig.h进行定制。每个FreeRTOS应用都必须包含这个头文件,用户根据实际应用来裁剪定制FreeRTOS内核。这个配置文件是针对...

    2.3 移植FreeRTOS

    2.3.1 内核配置文件

    FreeRTOS内核是高度可定制的,使用配置文件FreeRTOSConfig.h进行定制。每个FreeRTOS应用都必须包含这个头文件,用户根据实际应用来裁剪定制FreeRTOS内核。这个配置文件是针对用户程序的,而非内核,因此配置文件一般放在应用程序目录下,不要放在RTOS内核源码目录下。

    可以参考Demo中的FreeRTOSConfig.h,有些例程的配置文件是比较旧的版本,可能不会包含所有有效选项。如果没有在配置文件中指定某个选项,那么RTOS内核会使用默认值。

    在初始移植的时候,可以考虑使用default的配置,以便先完成porting后再细挑。而也可以暂时跳过这个章节。

    2.3.1.1 configUSE_PREEMPTION

    l 1:RTOS使用抢占式调度器

    l 0:RTOS使用协作式调度器(时间片)。

    2.3.1.2 configUSE_PORT_OPTIMISED_TASK_SELECTION

    用于选择下一个task的调度方式,通用方法和特定于硬件的方法。

    l 通用方法

    • configUSE_PORT_OPTIMISED_TASK_SELECTION设置为0或者硬件不支持这种特殊方法。
    • 可以用于所有FreeRTOS支持的硬件。
    • 完全用C实现,效率略低于特殊方法。
    • 不强制要求限制最大可用优先级数目

    l 特定方法

    • 并非所有硬件都支持。
    • 必须将configUSE_PORT_OPTIMISED_TASK_SELECTION设置为1。
    • 依赖一个或多个特定架构的汇编指令(一般是类似计算前导零[CLZ]指令)。
    • 比通用方法更高效。
    • 一般强制限定最大可用优先级数目为32。

    2.3.2.3 configUSE_TICKLESS_IDLE

    • 2 用户可以自定义tickless低功耗模式的实现
    • 1使能低功耗tickless模式
    • 0保持系统节拍(tick)中断一直运行。

    通常情况下,FreeRTOS回调空闲任务钩子函数(需要设计者自己实现),在空闲任务钩子函数中设置微处理器进入低功耗模式来达到省电的目的。因为系统要响应系统节拍中断事件,因此使用这种方法会周期性的退出、再进入低功耗状态。如果系统节拍中断频率过快,则大部分电能和CPU时间会消耗在进入和退出低功耗状态上。

    FreeRTOS的tickless空闲模式会在空闲周期时停止周期性系统节拍中断。停止周期性系统节拍中断可以使微控制器长时间处于低功耗模式。移植层需要配置外部唤醒中断,当唤醒事件到来时,将微控制器从低功耗模式唤醒。微控制器唤醒后,会重新使能系统节拍中断。由于微控制器在进入低功耗后,系统节拍计数器是停止的,但我们又需要知道这段时间能折算成多少次系统节拍中断周期,这就需要有一个不受低功耗影响的外部时钟源,即微处理器处于低功耗模式时它也在计时的,这样在重启系统节拍中断时就可以根据这个外部计时器计算出一个调整值并写入RTOS 系统节拍计数器变量中。

    2.3.1.4 configUSE_IDLE_HOOK

    • 1使用空闲钩子(IdleHook类似于回调函数);
    • 0忽略空闲钩子。

    当RTOS调度器开始工作后,为了保证至少有一个任务在运行,空闲任务被自动创建,占用最低优先级(0优先级)。对于已经删除的RTOS任务,空闲任务可以释放分配给它们的堆栈内存。因此,在应用中应该注意,使用vTaskDelete()函数时要确保空闲任务获得一定的处理器时间。除此之外,空闲任务没有其它特殊功能,因此可以任意的剥夺空闲任务的处理器时间。

    应用程序也可能和空闲任务共享同个优先级。

    那么,如何实现hook函数呢?

    空闲任务钩子是一个函数,这个函数由用户来实现,RTOS规定了函数的名字和参数,这个函数在每个空闲任务周期都会被调用。

     要创建一个空闲钩子:

    • 设置FreeRTOSConfig.h 文件中的configUSE_IDLE_HOOK 为1;
    • 定义一个函数,函数名和参数如下所示:

    voidvApplicationIdleHook(void ); 

    这个钩子函数不可以调用会引起空闲任务阻塞的API函数(例如:vTaskDelay()、带有阻塞时间的队列和信号量函数),在钩子函数内部使用协程是被允许的。

    使用空闲钩子函数设置CPU进入省电模式是很常见的。

    2.3.1.5 configUSE_MALLOC_FAILED_HOOK

    • 1,那么必须定义一个malloc()失败钩子函数
    • 0,malloc()失败钩子函数不会被调用,即便已经定义了这个函数

    当pvPortMalloc()申请内存失败的回调函数。只是针对heap_1.c,heap_2.c,heap_3.c,heap_4.c,heap_5.c有效果。 如果定义并正确配置malloc()失败钩子函数,则这个函数会在pvPortMalloc()函数返回NULL时被调用。只有FreeRTOS在响应内存分配请求时发现堆内存不足才会返回NULL。

    malloc()失败钩子函数的函数名和原型必须如下所示:

    void vApplicationMallocFailedHook(void); 

    2.3.1.6 configUSE_TICK_HOOK

    • 1使用时间片钩子(TickHook),
    • 0忽略时间片钩子。

    时间片中断可以周期性的调用一个被称为钩子函数(回调函数)的应用程序。时间片钩子函数可以很方便的实现一个定时器功能。

    只有在FreeRTOSConfig.h中的configUSE_TICK_HOOK设置成1时才可以使用时间片钩子。一旦此值设置成1,就要定义钩子函数,函数名和参数如下所示:

    void vApplicationTickHook(void ); 

     vApplicationTickHook()函数在中断服务程序中执行,因此这个函数必须非常短小,不能大量使用堆栈,不能调用以”FromISR" 或 "FROM_ISR”结尾的API函数。

    在FreeRTOSVx.x.x\FreeRTOS\Demo\Common\Minimal文件夹下的crhook.c文件中有使用时间片钩子函数的例程。

    2.3.1.7 configCPU_CLOCK_HZ

    写入实际的CPU内核时钟频率,也就是CPU指令执行频率,通常称为Fcclk。配置此值是为了正确的配置系统节拍中断周期。

    2.3.1.8 configTICK_RATE_HZ

    RTOS 系统节拍中断的频率。即一秒中断的次数,每次中断RTOS都会进行任务调度。

    系统节拍中断用来测量时间,因此,越高的测量频率意味着可测到越高的分辨率时间。但是,高的系统节拍中断频率也意味着RTOS内核占用更多的CPU时间,因此会降低效率。RTOS演示例程都是使用系统节拍中断频率为1000HZ,这是为了测试RTOS内核,比实际使用的要高。(实际使用时不用这么高的系统节拍中断频率)

    多个任务可以共享一个优先级,RTOS调度器为相同优先级的任务分享CPU时间,在每一个RTOS 系统节拍中断到来时进行任务切换。高的系统节拍中断频率会降低分配给每一个任务的“时间片”持续时间。

    2.3.1.9 configMAX_PRIORITIES

     配置应用程序有效的优先级数目。任何数量的任务都可以共享一个优先级,使用协程可以单独的给与它们优先权。见configMAX_CO_ROUTINE_PRIORITIES。

    在RTOS内核中,每个有效优先级都会消耗一定量的RAM,因此这个值不要超过你的应用实际需要的优先级数目。

    注:任务优先级

    每一个任务都会被分配一个优先级,优先级值从0~ (configMAX_PRIORITIES- 1)之间。低优先级数表示低优先级任务。空闲任务的优先级为0(tskIDLE_PRIORITY),因此它是最低优先级任务。

    FreeRTOS调度器将确保处于就绪状态(Ready)或运行状态(Running)的高优先级任务比同样处于就绪状态的低优先级任务优先获取处理器时间。换句话说,处于运行状态的任务永远是高优先级任务。

    处于就绪状态的相同优先级任务使用时间片调度机制共享处理器时间。

    2.3.1.10 configMINIMAL_STACK_SIZE

     定义空闲任务使用的堆栈大小。通常此值不应小于对应处理器演示例程文件FreeRTOSConfig.h中定义的数值。

    就像xTaskCreate()函数的堆栈大小参数一样,堆栈大小不是以字节为单位而是以字为单位的,比如在32位架构下,栈大小为100表示栈内存占用400字节的空间。

    2.3.1.11 configTOTAL_HEAP_SIZE

    RTOS内核总计可用的有效的RAM大小。仅在你使用官方下载包中附带的内存分配策略时,才有可能用到此值。每当创建任务、队列、互斥量、软件定时器或信号量时,RTOS内核会为此分配RAM,这里的RAM都属于configTOTAL_HEAP_SIZE指定的内存区。

    2.3.1.12 configMAX_TASK_NAME_LEN

    调用任务函数时,需要设置描述任务信息的字符串,这个宏用来定义该字符串的最大长度。这里定义的长度包括字符串结束符’\0’。

    2.3.1.13 configUSE_TRACE_FACILITY

    1表示启动可视化跟踪调试,会激活一些附加的结构体成员和函数。

    2.3.1.14 configUSE_STATS_FORMATTING_FUNCTIONS

    设置宏configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_FUNCTIONS为1会编译vTaskList()和vTaskGetRunTimeStats()函数。如果将这两个宏任意一个设置为0,上述两个函数不会被编译。

    2.3.1.15 configUSE_16_BIT_TICKS

    • 1意味着portTickType代表16位无符号整形
    • 0意味着portTickType代表32位无符号整形。

    使用16位类型可以大大提高8位和16位架构微处理器的性能,但这也限制了最大时钟计数为65535个’Tick’。因此,如果Tick频率为250HZ(4MS中断一次),对于任务最大延时或阻塞时间,16位计数器是262秒,而32位是17179869秒。

    2.3.1.16 configIDLE_SHOULD_YIELD

    这个参数控制任务在空闲优先级中的行为。仅在满足下列条件后,才会起作用。

    • 使用抢占式内核调度
    • 用户任务使用空闲优先级。

    ü 设置为0将阻止空闲任务为用户任务让出CPU,直到空闲任务的时间片结束。这确保所有处在空闲优先级的任务分配到相同多的处理器时间,但是,这是以分配给空闲任务更高比例的处理器时间为代价的。

    通过时间片共享同一个优先级的多个任务,如果共享的优先级大于空闲优先级,并假设没有更高优先级任务,这些任务应该获得相同的处理器时间。

    但如果共享空闲优先级时,情况会稍微有些不同。当configIDLE_SHOULD_YIELD为1时,其它共享空闲优先级的用户任务就绪时,空闲任务立刻让出CPU,用户任务运行,这样确保了能最快响应用户任务。处于这种模式下也会有不良效果(取决于你的程序需要),描述如下:

    图中描述了四个处于空闲优先级的任务,任务A、B和C是用户任务,任务I是空闲任务。上下文切换周期性的发生在T0、T1…T6时刻。当用户任务运行时,空闲任务立刻让出CPU,但是,空闲任务已经消耗了当前时间片中的一定时间。这样的结果就是空闲任务I和用户任务A共享一个时间片。用户任务B和用户任务C因此获得了比用户任务A更多的处理器时间。

    可以通过下面方法避免:

    •  如果合适的话,将处于空闲优先级的各单独的任务放置到空闲钩子函数中;
    • 创建的用户任务优先级大于空闲优先级;
    • 设置IDLE_SHOULD_YIELD为0;

    2.3.1.17 configUSE_TASK_NOTIFICATIONS(V8.2.0新增)

    • 1(或不定义宏configUSE_TASK_NOTIFICATIONS)将会开启任务通知功能,有关的API函数也会被编译。
    • 0则关闭任务通知功能,相关API函数也不会被编译。

    默认这个功能是开启的。开启后,每个任务多增加8字节RAM。 每个RTOS任务具有一个32位的通知值,RTOS任务通知相当于直接向任务发送一个事件,接收到通知的任务可以解除任务的阻塞状态(因等待任务通知而进入阻塞状态)。相对于以前必须分别创建队列、二进制信号量、计数信号量或事件组的情况,使用任务通知显然更灵活。更好的是,相比于使用信号量解除任务阻塞,使用任务通知可以快45%(使用GCC编译器,-o2优化级别)

    2.3.1.18 configUSE_MUTEXES

    • 1表示使用互斥量,
    •  0表示忽略互斥量。

    读者应该了解在FreeRTOS中互斥量和二进制信号量的区别。关于互斥量和二进制信号量简单说:

    • 互斥型信号量必须是同一个任务申请,同一个任务释放,其他任务释放无效。
    • 二进制信号量,一个任务申请成功后,可以由另一个任务释放。
    • 互斥型信号量是二进制信号量的子集

    2.3.1.19 configUSE_RECURSIVE_MUTEXES

    • 1表示使用递归互斥量,
    • 0表示不使用。

    2.3.1.20 configUSE_COUNTING_SEMAPHORES

    • 1表示使用计数信号量,
    • 0表示不使用。

    2.3.1.21 configUSE_ALTERNATIVE_API

    • 1表示使用“替代”队列函数('alternative' queue functions),
    • 0不使用。

    替代API在queue.h头文件中有详细描述。

    注:“替代”队列函数已经被弃用,在新的设计中不要使用它!

    2.3.1.22 configCHECK_FOR_STACK_OVERFLOW

    用于调试堆栈的溢出情况。堆栈溢出是设备运行不稳定的最常见原因,因此FreeeRTOS提供了两个可选机制用来辅助检测和改正堆栈溢出。配置宏configCHECK_FOR_STACK_OVERFLOW为不同的常量来使用不同堆栈溢出检测机制。

    • 0表示不使用这个机制

    推荐仅在开发或测试阶段使用栈溢出检查,因为堆栈溢出检测会增大上下文切换开销。如果宏configCHECK_FOR_STACK_OVERFLOW没有设置成0,用户必须提供一个栈溢出钩子函数,这个钩子函数的函数名和参数必须如下所示:

    voidvApplicationStackOverflowHook(TaskHandle_t xTask, signed char *pcTaskName); 

    参数xTask和pcTaskName为堆栈溢出任务的句柄和名字。请注意,如果溢出非常严重,这两个参数信息也可能是错误的!在这种情况下,可以直接检查pxCurrentTCb变量。

    • 1方法速度很快,但是不能检测到所有堆栈溢出情况(比如,堆栈溢出没有发生在上下文切换时)。

    任务切换出去后,该任务的上下文环境被保存到自己的堆栈空间,这时很可能堆栈的使用量达到了最大(最深)值。在这个时候,RTOS内核会检测堆栈指针是否还指向有效的堆栈空间。如果堆栈指针指向了有效堆栈空间之外的地方,堆栈溢出钩子函数会被调用。

    • 2有效捕捉堆栈溢出事件(即使堆栈溢出没有发生在上下文切换时),但是理论上它也不能百分百的捕捉到所有堆栈溢出(比如堆栈溢出的值和标记值相同,当然,这种情况发生的概率极小)。

    当堆栈首次创建时,在它的堆栈区中填充一些已知值(标记)。当任务切换时,RTOS内核会检测堆栈最后的16个字节,确保标记数据没有被覆盖。如果这16个字节有任何一个被改变,则调用堆栈溢出钩子函数。

    2.3.1.23 configQUEUE_REGISTRY_SIZE

    队列记录有两个目的,都涉及到RTOS内核的调试:

    • 它允许在调试GUI中使用一个队列的文本名称来简单识别队列;
    • 包含调试器需要的每一个记录队列和信号量定位信息;

    除了进行内核调试外,队列记录没有其它任何目的。

    configQUEUE_REGISTRY_SIZE定义可以记录的队列和信号量的最大数目。如果你想使用RTOS内核调试器查看队列和信号量信息,则必须先将这些队列和信号量进行注册,只有注册后的队列和信号量才可以使用RTOS内核调试器查看。查看API参考手册中的vQueueAddToRegistry() 和vQueueUnregisterQueue()函数获取更多信息。

    2.3.1.24 configUSE_QUEUE_SETS

    •  1使能队列集功能(可以阻塞、挂起到多个队列和信号量),
    •  0取消队列集功能。

    2.3.1.25 configUSE_TIME_SLICING

    默认情况下(宏configUSE_TIME_SLICING未定义或者宏configUSE_TIME_SLICING设置为1),FreeRTOS使用基于时间片的优先级抢占式调度器。这意味着RTOS调度器总是运行处于最高优先级的就绪任务,在每个RTOS 系统节拍中断时在相同优先级的多个任务间进行任务切换。如果宏configUSE_TIME_SLICING设置为0,RTOS调度器仍然总是运行处于最高优先级的就绪任务,但是当RTOS 系统节拍中断发生时,相同优先级的多个任务之间不再进行任务切换。

    2.3.1.26 configUSE_NEWLIB_REENTRANT

    如果宏configUSE_NEWLIB_REENTRANT设置为1,每一个创建的任务会分配一个newlib(一个嵌入式C库)reent结构。

    2.3.1.27 configENABLE_BACKWARD_COMPATIBILITY

    头文件FreeRTOS.h包含一系列#define宏定义,用来映射版本V8.0.0和V8.0.0之前版本的数据类型名字。这些宏可以确保RTOS内核升级到V8.0.0或以上版本时,之前的应用代码不用做任何修改。在FreeRTOSConfig.h文件中设置宏configENABLE_BACKWARD_COMPATIBILITY为0会去掉这些宏定义,并且需要用户确认升级之前的应用没有用到这些名字。

    2.3.1.28 configNUM_THREAD_LOCAL_STORAGE_POINTERS

    设置每个任务的线程本地存储指针数组大小。

    线程本地存储允许应用程序在任务的控制块中存储一些值,每个任务都有自己独立的储存空间,宏configNUM_THREAD_LOCAL_STORAGE_POINTERS指定每个任务线程本地存储指针数组的大小。API函数vTaskSetThreadLocalStoragePointer()用于向指针数组中写入值,API函数pvTaskGetThreadLocalStoragePointer()用于从指针数组中读取值。

    比如,许多库函数都包含一个叫做errno的全局变量。某些库函数使用errno返回库函数错误信息,应用程序检查这个全局变量来确定发生了那些错误。在单线程程序中,将errno定义成全局变量是可以的,但是在多线程应用中,每个线程(任务)必须具有自己独有的errno值,否则,一个任务可能会读取到另一个任务的errno值。

    FreeRTOS提供了一个灵活的机制,使得应用程序可以使用线程本地存储指针来读写线程本地存储。

    2.3.1.29 configGENERATE_RUN_TIME_STATS

    设置宏configGENERATE_RUN_TIME_STATS为1使能运行时间统计功能。一旦设置为1,则下面两个宏必须被定义:

    ü portCONFIGURE_TIMER_FOR_RUN_TIME_STATS():

    用户程序需要提供一个基准时钟函数,函数完成初始化基准时钟功能,这个函数要被define到宏portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()上。这是因为运行时间统计需要一个比系统节拍中断频率还要高分辨率的基准定时器,否则,统计可能不精确。基准定时器中断频率要比统节拍中断快10~100倍。基准定时器中断频率越快,统计越精准,但能统计的运行时间也越短(比如,基准定时器10ms中断一次,8位无符号整形变量可以计到2.55秒,但如果是1秒中断一次,8位无符号整形变量可以统计到255秒)。

    ü portGET_RUN_TIME_COUNTER_VALUE():

    用户程序需要提供一个返回基准时钟当前“时间”的函数,这个函数要被define到宏portGET_RUN_TIME_COUNTER_VALUE()上。

    举一个例子,假如我们配置了一个定时器,每500us中断一次。在定时器中断服务例程中简单的使长整形变量ulHighFrequencyTimerTicks自增。那么上面提到两个宏定义如下(可以在FreeRTOSConfig.h中添加):

    extern volatile unsignedlongulHighFrequencyTimerTicks; 

    #defineportCONFIGURE_TIMER_FOR_RUN_TIME_STATS() ( ulHighFrequencyTimerTicks = 0UL) 

    #defineportGET_RUN_TIME_COUNTER_VALUE() ulHighFrequencyTimerTicks 

    2.3.1.30 configUSE_CO_ROUTINES

    • 1表示使用协程,
    • 0表示不使用协程。

    如果使用协程,必须在工程中包含croutine.c文件。

    注:协程(Co-routines)主要用于资源发非常受限的嵌入式系统(RAM非常少),通常不会用于32位微处理器。

    在当前嵌入式硬件环境下,不建议使用协程,FreeRTOS的开发者早已经停止开发协程。

    2.3.1.31 configMAX_CO_ROUTINE_PRIORITIES

    应用程序协程(Co-routines)的有效优先级数目,任何数目的协程都可以共享一个优先级。使用协程可以单独的分配给任务优先级。见configMAX_PRIORITIES。

    2.3.1.32 configUSE_TIMERS

    •  1使用软件定时器,
    •  0不使用软件定时器功能。

    2.3.1.33 configTIMER_TASK_PRIORITY

    设置软件定时器服务/守护进程的优先级。

    2.3.1.34 configTIMER_QUEUE_LENGTH

    设置软件定时器命令队列的长度。

    2.3.1.35 configTIMER_TASK_STACK_DEPTH

    设置软件定时器服务/守护进程任务的堆栈深度

    2.3.1.36 configKERNEL_INTERRUPT_PRIORITY、configMAX_SYSCALL_INTERRUPT_PRIORITY和configMAX_API_CALL_INTERRUPT_PRIORITY

    这是移植和应用FreeRTOS出错最多的地方,所以需要打起精神仔细读懂。

    关于Cortex-M3的优先级请参考文章《Cortex-M3异常处理机制研究》,链接地址为:http://www.junsion.icoc.bz/nd.jsp?id=6#_np=2_405

    Cortex-M3、PIC24、dsPIC、PIC32、SuperH和RX600硬件设备需要设置宏configKERNEL_INTERRUPT_PRIORITY;

    PIC32、RX600和Cortex-M硬件设备需要设置宏configMAX_SYSCALL_INTERRUPT_PRIORITY。

    configMAX_SYSCALL_INTERRUPT_PRIORITY和configMAX_API_CALL_INTERRUPT_PRIORITY,这两个宏是等价的,后者是前者的新名字,用于更新的移植层代码。

    注意下面的描述中,在中断服务例程中仅可以调用以“FromISR”结尾的API函数。

    仅需要设置configKERNEL_INTERRUPT_PRIORITY的硬件设备(也就是宏configMAX_SYSCALL_INTERRUPT_PRIORITY不会用到):configKERNEL_INTERRUPT_PRIORITY用来设置RTOS内核自己的中断优先级。调用API函数的中断必须运行在这个优先级;不调用API函数的中断,可以运行在更高的优先级,所以这些中断不会被因RTOS内核活动而延时。

    configKERNEL_INTERRUPT_PRIORITY和configMAX_SYSCALL_INTERRUPT_PRIORITY都需要设置的硬件设备:configKERNEL_INTERRUPT_PRIORITY用来设置RTOS内核自己的中断优先级。因为RTOS内核中断不允许抢占用户使用的中断,因此这个宏一般定义为硬件最低优先级。configMAX_SYSCALL_INTERRUPT_PRIORITY用来设置可以在中断服务程序中安全调用FreeRTOS API函数的最高中断优先级。优先级小于等于这个宏所代表的优先级时,程序可以在中断服务程序中安全的调用FreeRTOS API函数;如果优先级大于这个宏所代表的优先级,表示FreeRTOS无法禁止这个中断,在这个中断服务程序中绝不可以调用任何API函数。

    通过设置configMAX_SYSCALL_INTERRUPT_PRIORITY的优先级级别高于configKERNEL_INTERRUPT_PRIORITY可以实现完整的中断嵌套模式。这意味着FreeRTOS内核不能完全禁止中断,即使在临界区。此外,这对于分段内核架构的微处理器是有利的。请注意,当一个新中断发生后,某些微处理器架构会(在硬件上)禁止中断,这意味着从硬件响应中断到FreeRTOS重新使能中断之间的这段短时间内,中断是不可避免的被禁止的。

    不调用API的中断可以运行在比configMAX_SYSCALL_INTERRUPT_PRIORITY高的优先级,这些级别的中断不会被FreeRTOS禁止,因此不会因为执行RTOS内核而被延时。

    例如:假如一个微控制器有8个中断优先级别:0表示最低优先级,7表示最高优先级(Cortex-M3和Cortex-M4内核优先数和优先级别正好与之相反,后续文章会专门介绍它们)。当两个配置选项分别为4和0时,下图描述了每一个优先级别可以和不可做的事件:

    configMAX_SYSCALL_INTERRUPT_PRIORITY=4

    configKERNEL_INTERRUPT_PRIORITY=0

     

    这些配置参数允许非常灵活的中断处理:

    在系统中可以像其它任务一样为中断处理任务分配优先级。这些任务通过一个相应中断唤醒。中断服务例程(ISR)内容应尽可能的精简---仅用于更新数据然后唤醒高优先级任务。ISR退出后,直接运行被唤醒的任务,因此中断处理(根据中断获取的数据来进行的相应处理)在时间上是连续的,就像ISR在完成这些工作。这样做的好处是当中断处理任务执行时,所有中断都可以处在使能状态。

    中断、中断服务例程(ISR)和中断处理任务是三码事:当中断来临时会进入中断服务例程,中断服务例程做必要的数据收集(更新),之后唤醒高优先级任务。这个高优先级任务在中断服务例程结束后立即执行,它可能是其它任务也可能是中断处理任务,如果是中断处理任务,那么就可以根据中断服务例程中收集的数据做相应处理。

    configMAX_SYSCALL_INTERRUPT_PRIORITY接口有着更深一层的意义:在优先级介于RTOS内核中断优先级(等于configKERNEL_INTERRUPT_PRIORITY)和configMAX_SYSCALL_INTERRUPT_PRIORITY之间的中断允许全嵌套中断模式并允许调用API函数。大于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断优先级绝不会因为执行RTOS内核而延时。

    运行在大于configMAX_SYSCALL_INTERRUPT_PRIORITY的优先级中断是不会被RTOS内核所屏蔽的,因此也不受RTOS内核功能影响。这主要用于非常高的实时需求中。比如执行电机转向。但是,这类中断的中断服务例程中绝不可以调用FreeRTOS的API函数。

    为了使用这个方案,应用程序要必须符合以下规则:调用FreeRTOS API函数的任何中断,都必须和RTOS内核处于同一优先级(由宏configKERNEL_INTERRUPT_PRIORITY设置),或者小于等于宏configMAX_SYSCALL_INTERRUPT_PRIORITY定义的优先级。

    回到STM32来看,这个微控制器基于Cortex-M3的内核,芯片厂商为STM32提供0~15个可抢占的优先级,这个是通过如下的代码实现的:

        /* 优先级分组设置为4,可配置0~15级抢占式优先级,0级子优先级*/

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

    那么就强烈建议,在FreeRTOSConfig.h中将configMAX_SYSCALL_INTERRUPT_PRIORITY配置为16。这样FreeRTOS的优先级配置就不会影响到STM32自身的可抢占式的优先级配置。

    以“FromISR”结尾的FreeRTOS函数是具有中断调用保护的(执行这些函数会进入临界区),但是就算是这些函数,也不可以被逻辑优先级高于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断服务函数调用。(宏configMAX_SYSCALL_INTERRUPT_PRIORITY定义在头文件FreeRTOSConfig.h中)。因此,任何使用RTOSAPI函数的中断服务例程的中断优先级数值大于等于configMAX_SYSCALL_INTERRUPT_PRIORITY宏的值。这样就能保证中断的逻辑优先级等于或低于configMAX_SYSCALL_INTERRUPT_PRIORITY。

    Cortex中断默认情况下有一个数值为0的优先级。大多数情况下0代表最高级优先级。因此,绝对不可以在优先级为0的中断服务例程中调用RTOSAPI函数。

    宏configKERNEL_INTERRUPT_PRIORITY指定RTOS内核使用的中断优先级,因为RTOS内核不可以抢占用户任务,因此这个宏一般设置为硬件支持的最小优先级。对于Cortex-M硬件,RTOS使用到硬件的PendSV和SysTick硬件中断,在函数xPortStartScheduler()中(该函数在port.c中,由启动调度器函数vTaskStartScheduler()调用),将PendSV和SysTick硬件中断优先级寄存器设置为宏configKERNEL_INTERRUPT_PRIORITY指定的值。

    1.  /*PendSV优先级设置寄存器地址为0xe000ed22 SysTick优先级设置寄存器地址为0xe000ed23*/  

    #define portNVIC_SYSPRI2_REG                           ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )

    #define portNVIC_PENDSV_PRI             ( portMIN_INTERRUPT_PRIORITY << 16UL )

    #define portNVIC_SYSTICK_PRI            ( portMIN_INTERRUPT_PRIORITY << 24UL )

           /* Make PendSV and SysTick the lowest priority interrupts. */

           portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;

           portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;

    2.3.1.37 configASSERT

    断言,调试时可以检查传入的参数是否合法。FreeRTOS内核代码的关键点都会调用configASSERT( x )函数,如果参数x为0,则会抛出一个错误。这个错误很可能是传递给FreeRTOS API函数的无效参数引起的。定义configASSERT()有助于调试时发现错误,但是,定义configASSERT()也会增大应用程序代码量,增大运行时间。推荐在开发阶段使用这个断言宏。

    举一个例子,我们想把非法参数所在的文件名和代码行数打印出来,可以先定义一个函数vAssertCalled,该函数有两个参数,分别接收触发configASSERT宏的文件名和该宏所在行,然后通过显示屏或者串口输出。代码如下:

    #define configASSERT( ( x ))     if( ( x ) == 0 )vAssertCalled(__FILE__, __LINE__ ) 

    这里__FILE__和__LINE__是大多数编译器预定义的宏,分别表示代码所在的文件名(字符串格式)和行数(整形)。

    这个例子虽然看起来很简单,但由于要把整形__LINE__转换成字符串再显示,在效率和实现上,都不能让人满意。我们可以使用C标准库assert的实现方法,这样函数vAssertCalled只需要接收一个字符串形式的参数(推荐仔细研读下面的代码并理解其中的技巧):

    #defineSTR(x)  VAL(x) 

    #defineVAL(x)  #x 

    #defineconfigASSERT(x) ((x)?(void) 0 :xAssertCalld(__FILE__ ":"STR(__LINE__) " " #x"\n")) 

    这里稍微讲解一下,由于内置宏__LINE__是整数型的而不是字符串型,把它转化成字符串需要一个额外的处理层。宏STR和和宏VAL正是用来辅助完成这个转化。宏STR用来把整形行号替换掉__LINE__,宏VAL用来把这个整形行号字符串化。忽略宏STR和VAL中的任何一个,只能得到字符串”__LINE__”,这不是我们想要的。

    这里使用三目运算符’?:’来代替参数判断if语句,这样可以接受任何参数或表达式,代码也更紧凑,更重要的是代码优化度更高,因为如果参数恒为真,在编译阶段就可以去掉不必要的输出语句。

    2.3.1.38 INCLUDE Parameters

     以“INCLUDE”起始的宏允许用户不编译那些应用程序不需要的实时内核组件(函数),这可以确保在你的嵌入式系统中RTOS占用最少的ROM和RAM。

    每个宏以这样的形式出现:

    INCLUDE_FunctionName

    在这里FunctionName表示一个你可以控制是否编译的API函数。如果你想使用该函数,就将这个宏设置成1,如果不想使用,就将这个宏设置成0。比如,对于API函数vTaskDelete():

    #defineINCLUDE_vTaskDelete    1 

    表示希望使用vTaskDelete(),允许编译器编译该函数

    #defineINCLUDE_vTaskDelete    0 

    表示禁止编译器编译该函数。

    2.3.1.39 INCLUDE_vTaskSuspend

     注意,xSemaphoreTake函数的第二个参数设置为portMAX_DELAY,且在FreeRTOSConig.h 中设定INCLUDE_vTaskSuspend 为1,那么阻塞等待将没有超时限制。
    展开全文
  • freeRTOS开源项目crazyflie

    千次阅读 2016-09-14 21:58:47
    不小心接触到了开源飞控,有一个小四轴的项目:crazyflie,有兴趣百度搜。使用的就是freeRTOS内核,可以作为学习freeRTOS应用的一个参考。另外freeRTOS官方源码包里面就有好多Demo可以参考学习。
  • 非常完整的有关FreeRTOS和uC/GUI3.98的移植及源码 另外uC/GUI3.98是当前能找到完整源码的最高版本,本人辛辛苦苦转了3天才弄完,很全,绝对对得起你的5分,网上iar的几乎找不到!
  • FreeRTOS——创建新的项目
  • 掌握FreeRTOS中列表和列表项相关函数的使用。 02. 任务设计 3 个任务:start_task、task1_task 和task2_task,这三个任务的任务功能如下: start_task:用来创建其他2 个任务。 task1_task:应用任务1,控制LED0 ...
  • 移植使用的是V10.3.1版本的FreeRTOS 二、最小工程创建 先用Keil创建一个工程,选择STM32F103C8 选择否,后面我们自己添加官方外设库的文件 工程建好了之后,就可以将ST官方外设库相关文件加入工程目录里了 先新建个...
  • 最近从原来的裸机工程项目中迁移到freertos系统,编起程来的确方便了许多,官方文档说最好不要使用全局变量,我也尽量削减全局变量,现在遇到一个问题,求教有经验的大神们:对于万年历,是使用驱动的,但是很多项目...
  • FreeRTOS常用资源

    2020-04-11 22:38:56
    1.FreeRTOS官网的学习资料:...FreeRTOS现有的项目资料(github 源代码):http://www.osrtos.com/rtos/freertos 2.源代码下载地址: 官网下载地址1(sourceForage):http://sourceforge.net/projects/freertos/fi...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,488
精华内容 1,395
关键字:

freertos项目