当前位置: 代码迷 >> 综合 >> FreeRTOS API笔记
  详细解决方案

FreeRTOS API笔记

热度:98   发布时间:2023-10-11 10:05:20.0

消息队列

两个任务之间要通信,要传输数据使用消息队列
xQueueCreat();
xQueueSend() //默认添加在队尾
xQueueSendToFont()//添加在队头
xQueueReceive()//从队尾接收
xQueueReceive() //从队列接收数据,然后删除
xQueuePeek() //接收数据并不删除

信号量

二值信号量用来同步任务,计数信号量表示资源的可使用数,使用的是消息队列一样的数据结构
xSemaphoreCreateBinary() //创建二值信号量
xSemaphoreCreateCounting() //创建技术信号量
xSemaphoreDelete() //删除信号量
xSemaphoreGive() //释放信号量
xSemaphoreTake() //获取信号量

互斥信号量

互斥信号量用来表示对临界资源的保护(比如两个任务同事往一个串口发送数据),与二值信号量和技术信号量不同的是,互斥信号量具有优先级继承功能,用来降低优先级翻转的情况下高优先级的阻塞时间损失,互斥信号量只有0和1,并且高优先级也会因为互斥信号量阻塞。
xSemaphoreCreateMutex() //创建互斥信号量

xSemaphoreCreateRecursiveMutex()//递归互斥信号量,获得信号量的任务可以递归获得该信号量,别的任务不能获得,递归几次就要释放几次。

vSemaphoreDelete() //删除互斥信号量
xSemaphoreTake() //获取互斥信号量
xSemaphoreTakeRecursive()// 递归互斥量获取函数
xSemaphoreGive()//互斥量释放函数
xSemaphoreGiveRecursive()//递归互斥量释放函数

事件

  • 事件是一种实现任务间通信的机制,主要用于实现多任务间的同步,但事件通信只能
    是事件类型的通信,无数据传输。与信号量不同的是,它可以实现一对多,多对多的同步。
    即一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理;
    也可以是几个事件都发生后才唤醒任务进行事件处理。同样,也可以是多个任务同步多个
    事件
  • 如 果 宏configUSE_16_BIT_TICKS 定义为 1, 那么变量 uxEventBits 就是 16 位的, 其中有 8 个位用来存储事件组; 而如果宏 configUSE_16_BIT_TICKS 定义为 0, 那么变量 uxEventBits 就是32 位 的, 其 中 有 24 个 位 用 来 存 储 事 件 组 。 在 STM32 中 ,我 们 一 般 将configUSE_16_BIT_TICKS 义为 0,那么 uxEventBits 是 32 位的,有 24 个位用来实现事件标志组。
  • FreeRTOS 提供的事件具有如下特点:
    • 事件只与任务相关联,事件相互独立,一个 32 位的事件集合(EventBits_t 类型的
      变量, 实际可用与表示事件的只有 24 位),用于标识该任务发生的事件类型,其
      中每一位表示一种事件类型(0 表示该事件类型未发生、 1 表示该事件类型已经发
      生),一共 24 种事件类型
    • 事件仅用于同步,不提供数据传输功能。
    • 事件无排队性,即多次向任务设置同一事件(如果任务还未来得及读走), 等效于
      只设置一次。
    • 允许多个任务对同一事件进行读写操作。
    • 支持事件等待超时机制

xEventGroupCreate()//创建事件
vEventGroupDelete()//删除事件
xEventGroupSetBits()//事件置位
xEventGroupSetBitsFromISR()//事件组置位函数(中断置位是在守护任务(软件定时器)中完成的)
xEventGroupWaitBits()//等待事件
xEventGroupClearBits()//清除事件位
xEventGroupClearBitsFromISR()//清除事件位(中断)

  • 如果事件创建的时候设置成清除事件位,在事件唤醒任务后,事件组的值会被清除为0,置位函数的返回值也是0

软件定时器

xTimerCreate() //创建软件定时器
xTimerStart() //启动软件定时器
xTimerStartFromISR() //中断中启动定时器任务
xTimerStop() //停止软件定时器
xTimerStopFromISR() //中断中停止软件定时器
xTimerDelete() //删除一个已经被成功创建的定时器

通知

通知是任务控制块自带的数据,不需要创建可以直接使用,用来替代信号量

xTaskGenericNotify() // 全功能向一个任务发送一个通知,通知的方法即改变任务控制块中ulNotifiedValue的值,又多种不同的操作

xTaskNotifyGive()//任务控制块中ulNotifiedValue值+1 可以作为二值信号量和计数信号量的 轻量级实现,与 ulTaskNotifyTake() 是一对,不可使用xTaskNotifyWait()

vTaskNotifyGiveFromISR() //vTaskNotifyGiveFromISR()是 vTaskNotifyGive()的中断保护版本。 用于在中断中向指定任务发送任务通知,并更新对方的任务通知值(加 1 操作) ,在某些场景中可以替代信号量操作,因为这两个通知都是不带有通知值的

xTaskNotify() //发送一个指定的通知值并且可以指定任务发送方式
xTaskNotifyFromISR()//带中断发送一个指定的通知值并且可以指定任务发送方式
xTaskGenericNotifyFromISR() //中断中发送通知的通用函数,是xTaskNotifyFromISR()中执行的主要方法
xTaskNotifyAndQuery() //比xTaskNotify()多了一个可以获取接收任务通知值的参数。不用传回通知值可以设置成NULL,此时本函数等价于xTaskNotify()
xTaskNotifyAndQueryFromISR() //xTaskNotifyAndQuery()的中断版本

ulTaskNotifyTake()//ulTaskNotifyTake()作为二值信号量和计数信号量的一种轻量级实现,速度更快。 如果FreeRTOS 中使用函数 xSemaphoreTake() 来获取信号量, 这个时候则可以试试使用函数ulTaskNotifyTake()来代替与xTaskNotifyGive()配套,任务通知值减一

xTaskNotifyWait():xTaskNotifyWait()函数用于实现全功能版的等待任务通知,根据用户指定的参数的不同,可以灵活的用于实现轻量级的消息队列队列、二值信号量、计数信号量和事件组功能,并带有超时等待。

  • **如果只是简单的二值信号量,建议用通知代替xTaskNotifyGive()、ulTaskNotifyTake() **
  • 如果是用来传递消息(消息队列)可以使用xTaskNotify()、xTaskNotifyWait() 传递的消息设置成地址即可传递字符串

内存管理

  • 内部存储空间 ram 外部存储空间flash

  • 在嵌入式实时操作系统中使用C中的malloc()和free()可能存在以下问题

    • 这些函数在小型嵌入式系统中并不总是可用的,小型嵌入式设备中的 RAM 不足。
    • 它们的实现可能非常的大,占据了相当大的一块代码空间
    • 他们几乎都不是安全的。
    • 它们并不是确定的,每次调用这些函数执行的时间可能都不一样
    • 它们有可能产生碎片
    • 这两个函数会使得链接器配置得复杂
    • 果允许堆空间的生长方向覆盖其他变量占据的内存,它们会成为 debug 的灾难
    • 嵌入式系统中内存经常申请和释放可能导致内存碎片,长时间后会让内存无法分配而导致系统瘫痪,所以一定要有一个优良的内存分配算法。
  • heap_1.c:只有内存申请,没有释放,按8字节对齐
    FreeRTOS API笔记

  • heap_2.c

    • heap_2.c 内存管理方案采用最佳匹配算法管理内存,找到满足条件的最小内存块进行分割,申请出指定内存,多余部分插入内存块空闲列表

FreeRTOS API笔记
FreeRTOS API笔记

  • heap_3.c

    • heap_3.c只是简单的封装了标准C的malloc()和free()
    • 需要链接器设置一个堆, malloc()和 free()函数由编译器提供
    • 具有不确定性。
    • 要 注 意 的 是 在 使 用 heap_3.c 方 案 时 , FreeRTOSConfig.h 文 件 中 的configTOTAL_HEAP_SIZE 宏定义不起作用。 在 STM32 系列的工程中, 这个由编译器定义的堆都在启动文件里面设置, 单位为字节,FreeRTOS API笔记
  • heap_4.c

    • heap_4.c 方案与 heap_2.c 方案一样都采用最佳匹配算法来实现动态的内存分配,但是不一样的是 heap_4.c 方案还包含了一种合并算法,能把相邻的空闲的内存块合并成一个更大的块,这样可以减少内存碎片。
    • heap_4.c 内存管理方案的空闲块链表不是以内存块大小进行排序的,而是以内存块起始地址大小排序, 内存地址小的在前,地址大的在后,因为 heap_4.c 方案还有一个内存合并算法,在释放内存的时候,假如相邻的两个空闲内存块在地址上是连续的,那么就可以合并为一个内存块, 这也是为了适应合并算法而作的改变。
    • 可用于重复删除任务、队列、信号量、互斥量等的应用程序
    • 可用于分配和释放随机字节内存的应用程序, 但并不像 heap2.c 那样产生严重的内存碎片。
    • 具有不确定性,但是效率比标准 C 库中的 malloc 函数高得多。
      FreeRTOS API笔记
      FreeRTOS API笔记
  • heap_5.c

    • heap_5.c 方案在实现动态内存分配时与 heap4.c 方案一样, 采用最佳匹配算法和合并算
      法,并且允许内存堆跨越多个非连续的内存区,也就是允许在不连续的内存堆中实现内存
      分配,比如用户在片内 RAM 中定义一个内存堆,还可以在外部 SDRAM 再定义一个或多
      个内存堆,这些内存都归系统管理。
      FreeRTOS API笔记
  相关解决方案