• 3、CubeMx FreeRTOS笔记


    在这里插入图片描述

    1、常用的任务函数

    1)、任务挂起函数:

    void vTaskSuspend( TaskHandle_t xTaskToSuspend )
    
    • 1

    挂起指定任务。被挂起的任务绝不会得到 CPU的使用权,不管该任务具有什么优先级。任务可以通过调用 vTaskSuspend()函数都可以将处于任何状态的任务挂起,被挂起的任务得不到 CPU 的使用权,也不会参与调度,它相对于调度器而言是不可见的,除非它从挂起态中除。

    void vTaskSuspendAll( void )
    
    • 1

    挂起所有任务就是挂起任务调度器。调度器被挂起后则不能进行上下文切换,但是中断还是使能的。 当调度器被挂起的时候,如果有中断需要进行上下文切换, 那么这个任务将会被挂起,在调度器恢复之后才执行切换任务。调度器恢复可以调用 xTaskResumeAll()函数,调用了多少次的 vTaskSuspendAll()就要调用多少次xTaskResumeAll()进行恢复

    2)、任务恢复函数:

    void vTaskResume( TaskHandle_t xTaskToResume )
    
    • 1

    任务恢复就是让挂起的任务重新进入就绪状态,恢复的任务会保留挂起前的状态信息,在恢复的时候根据挂起时的状态继续运行。如果被复任务在所有就绪态任务中,处于最高优先级列表的第一位,那么系统将进行任务上下文的切换。vTaskResume()函数用于恢复挂起的任务。无论任务在挂起时候调用过多少次这个vTaskSuspend()函数,也只需调用一次 vTaskResume ()函数即可将任务恢复运行,当然,无论调用多少次的 vTaskResume()函数,也只在任务是挂起态的时候才进行恢复。

    BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
    
    • 1

    xTaskResumeFromISR()与 vTaskResume()一样都是用于恢复被挂起的任务,不一样的是 xTaskResumeFromISR()专门用在中断 服务程序中。无论通过调用一次或多 次vTaskSuspend()函数而被挂起的任务,也只需调用一次 xTaskResumeFromISR()函数即可解挂 。
    在这里插入图片描述

    BaseType_t xTaskResumeAll( void )
    
    • 1

    恢复调度器,调用了多少次vTaskSuspendAll()函数就必须同样调用多少次 xTaskResumeAll()函数

    void vTaskDelete( TaskHandle_t xTaskToDelete )
    
    • 1

    vTaskDelete()用于删除一个任务。当一个任务删除另外一个任务时,形参为要删除任务创建时返回的任务句柄,如果是删除自身, 则形参为 NULL。

    3)、任务延时函数

    void vTaskDelay( const TickType_t xTicksToDelay )
    
    • 1

    相对延时函数,vTaskDelay()用于阻塞延时,调用该函数后,任务将进入阻塞状态,进入阻塞态的任务将让出 CPU资源。延时的时长由形参 xTicksToDelay 决定,单位为系统节拍周期, 比如系统的时钟节拍周期为 1ms,那么调用 vTaskDelay(1)的延时时间则为 1ms。
    其它任务和中断活动, 也会影响到 vTaskDelay()的调用(比如调用前高优先级任务抢占了当前任务),进而影响到任务的延时时间。

    void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
    
    • 1

    绝对延时函数 ,常用于较精确的周期运行任务,比如我有一个任务,希望它以固定频率定期执行,而不受外部的影响,任务从上一次运行开始到下一次运行开始的时间间隔是绝对的,而不是相对的。

    4)、任务创建

    void SystemInitTask(void const * argument);
    osThreadId SystemInitHandle;
      osThreadDef(SystemInit, SystemInitTask, osPriorityIdle, 0, 1024*2);
      SystemInitHandle = osThreadCreate(osThread(SystemInit), NULL);
    
    • 1
    • 2
    • 3
    • 4
    #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
    	BaseType_t xTaskCreate(	TaskFunction_t pxTaskCode,
    							const char * const pcName,	/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
    							const configSTACK_DEPTH_TYPE usStackDepth,
    							void * const pvParameters,
    							UBaseType_t uxPriority,
    							TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    2、消息队列在这里插入图片描述

    1)、消息队列创建函数

    #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
    	#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )
    #endif
    
    • 1
    • 2
    • 3

    xQueueCreate()用于创建一个新的队列并返回可用于访问这个队列的队列句柄。队列句柄其实就是一个指向队列数据结构类型的指针。
    在这里插入图片描述
    在这里插入图片描述

    2)、消息队列删除函数

    void vQueueDelete( QueueHandle_t xQueue )
    
    • 1

    **vQueueDelete()也可用于删除信号量。**如果删除消息队列时,有任务正在等待消息,则不应该进行删除操作。

    在这里插入图片描述

    3)、向消息队列发送消息函数

    #define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
    
    • 1
    #define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
    
    • 1

    xQueueSend() 等 同 于xQueueSendToBack()。xQueueSend()用于向队列尾部发送一个队列消息。消息以拷贝的形式入队,而不是以引用的形式。该函数绝对不能在中断服务程序里面被调用,中断中必须使用带有中断保护功能的 xQueueSendFromISR()来代替。
    在这里插入图片描述
    在这里插入图片描述

    #define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )
    
    • 1
    #define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )
    
    • 1

    在这里插入图片描述
    在这里插入图片描述

    #define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
    
    • 1
    #define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT )
    
    • 1

    在这里插入图片描述

    4)、从消息队列读取消息函数

    BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait )
    
    • 1

    在这里插入图片描述
    在这里插入图片描述
    **如果不想删除消息的话,就调用 xQueuePeek()函数。**其实这个函数与 xQueueReceive()函数的实现方式一样,连使用方法都一样,只不过xQueuePeek()函数接收消息完毕不会删除消息队列中的消息而已

    BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait )
    
    • 1
    BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer )
    
    • 1
    BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken )
    
    • 1

    在这里插入图片描述

    5)、消息队列清空

    /*
     * Reset a queue back to its original empty state.  The return value is now
     * obsolete and is always set to pdPASS.
     */
    #define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE )
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3、信号量

    1)、创建信号量函数

    a、创建二值信号量
    #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
    	#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
    #endif
    
    • 1
    • 2
    • 3

    二值信号量和互斥量都共同使用一个类型 SemaphoreHandle_t 的句柄,该句柄的原型是一个 void 型的指针。使用该函数创建的二值信号量是空的,在使用函数xSemaphoreTake()获取之前必须先调用函数 xSemaphoreGive()释放后才可以获取。

    b、创建计数信号量
    #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
    	#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
    #endif
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    在这里插入图片描述

    2)、信号量删除函数

    #define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
    
    • 1

    vSemaphoreDelete()用于删除一个信号量,包括二值信号量,计数信号量,互斥量和递
    归互斥量。如果有任务阻塞在该信号量上,那么不要删除该信号量。
    在这里插入图片描述

    3)、信号量释放函数

    #define xSemaphoreGive( xSemaphore )		xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
    
    • 1

    xSemaphoreGive()是一个用于释放信号量的宏,真正的实现过程是调用消息队列通用发送函数,xSemaphoreGive()函数原型具体见代码清单 18-8。释放的信号量对象必须是已经被创建的,可以用于二值信号量、计数信号量、互斥量的释放,但不能释放由函数xSemaphoreCreateRecursiveMutex()创建的递归互斥量。此外该函数不能在中断中使用。
    在这里插入图片描述

    #define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken )	xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) )
    
    • 1

    用于释放一个信号量,带中断保护。被释放的信号量可以是二进制信号量和计数信号量。和普通版本的释放信号量 API 函数有些许不同,它不能释放互斥量,这是因为互斥量不可以在中断中使用,互斥量的优先级继承机制只能在任务中起作用,而在中断中毫无意义。
    在这里插入图片描述

    4)、信号量获取函数

    #define xSemaphoreTake( xSemaphore, xBlockTime )		xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) )
    
    • 1

    xSemaphoreTake()函数用于获取信号量,不带中断保护。获取的信号量对象可以是二值信号量、计数信号量和互斥量,但是递归互斥量并不能使用这个 API 函数获取。
    在这里插入图片描述
    在这里插入图片描述

    #define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken )	xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) )
    
    • 1

    用于获取信号量,是一个不带阻塞机制获取信号量的函数,获取对象必须由是已经创建的信号量,信号量类型可以是二值信号量和计数信号量,它与xSemaphoreTake()函数不同,它不能用于获取互斥量,因为互斥量不可以在中断中使用,并且互斥量特有的优先级继承机制只能在任务中起作用,而在中断中毫无意义。
    在这里插入图片描述

    4、互斥量

    1)、互斥量创建函数

    	#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
    
    • 1

    在这里插入图片描述

    #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
    	#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
    #endif
    
    • 1
    • 2
    • 3

    xSemaphoreCreateRecursiveMutex()用于创建一个递归互斥量,不是递归的互斥量由函数 xSemaphoreCreateMutex() 或 xSemaphoreCreateMutexStatic()创建,且只能被同一个任务获取一次,如果同一个任务想再次获取则会失败。
    在这里插入图片描述

    2)、互斥量删除函数 vSemaphoreDelete()

    3)、互斥量获取函数 xSemaphoreTake()

    在这里插入图片描述

    4)、递归互斥量获取函数

    #if( configUSE_RECURSIVE_MUTEXES == 1 )
    	#define xSemaphoreTakeRecursive( xMutex, xBlockTime )	xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) )
    #endif
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    5)、互斥量释放函数

    #define xSemaphoreGive( xSemaphore )		xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
    
    • 1

    任务想要访问某个资源的时候,需要先获取互斥量,然后进行资源访问,在任务使用完该资源的时候,必须要及时归还互斥量,这样别的任务才能对资源进行访问。**互斥量的释放只能在任务中,不允许在中断中释放互斥量。**使用该函数接口时,只有已持有互斥量所有权的任务才能释放它,**当任务调用xSemaphoreGive()函数时会将互斥量变为开锁状态,**等待获取该互斥量的任务将被唤醒。如果任务的优先级被互斥量的优先级翻转机制临时提升,那么当互斥量被释放后,任务的优先级将恢复为原本设定的优先级。
    在这里插入图片描述

    6)、递归互斥量释放函数

    #if( configUSE_RECURSIVE_MUTEXES == 1 )
    	#define xSemaphoreGiveRecursive( xMutex )	xQueueGiveMutexRecursive( ( xMutex ) )
    #endif
    
    • 1
    • 2
    • 3

    释放递归互斥量,获取了多少次就要释放多少次

    本文来自[野火®]《FreeRTOS 内核实现与应用开发实战—基于STM32》

  • 相关阅读:
    centos7.9 postgresql 16.0 源码安装部署
    Nacos与Eureka中的高性能读写并发架构设计
    C#_事件简述
    了解这6个原因 才知道为什么需要FTP替代方案了
    阿里云服务器10M带宽容纳多少人同时在线?
    NO1-Kafka如何通过网络接收/发送请求
    wordpress遇到的问题
    JVM内存结构
    JVM虚拟机:JVM中垃圾回收器的总结
    宏电股份AI BOX新产品首次亮相2023中国移动全球合作伙伴大会,以创新性AI、5G技术推动数实共生
  • 原文地址:https://blog.csdn.net/qq_36561846/article/details/126678594