当前位置: 首页 > article >正文

FreeRTOS应用开发学习

了解FreeRTOS

任务相关API

FreeRTOS任务创建API

FreeRTOS 中,任务的创建有两种方法,一种是使用动态创建,一种是使用静态创建。动态创建时,任务控制块和栈的内存是创建任务时动态分配的,任务删除时,内存可以释放。静态创建时,任务控制块和栈的内存需要事先定义好,是静态的内存 ,任务删除时 ,内存不能释放 。

动态创建API:xTaskCreate()

BaseType_t  xTaskCreate(
TaskFunction_t	pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t  uxPriority,
TaskHandle t* const  pxCreatedTask 
)

在这里插入图片描述返回值:
pdPASS:任务创建成功
errCIOULD_NOT_ALLOCATE_REQUIRED_MEMORY:任务创建失败,因为内存不足

静态创建API:xTaskCreateStatic()

TaskHandle  xTaskCreateStatic(
TaskFunction_t	pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t  uxPriority,
StaticType_t *const puStackBuffer,
StaticTask_t *const pxTaskBuffer)

在这里插入图片描述返回值:
NULL:任务创建失败
其他:任务创建成功,返回任务句柄

删除任务API

vTaskDelete():删除一个任务。

vTaskDelete(TaskHandle_t xTaskToDelete)

参数:
xTaskToDelete:要删除的任务的句柄

任务挂起和恢复API

任务挂起:vTaskToSuspend

此函数用于将某个任务设置为挂起态, 进入挂起态的任务永远都不会进入运行态。退出挂
起态的唯一方法就是调用任务恢复函数 vTaskResume()或 xTaskResumeFromISR()。

void vTaskToSuspend(TaskHandle_t xTaskSuspend)

参数:
在这里插入图片描述

任务恢复

vTaskResume():恢复一个任务的运行。

将一个任务从挂起态恢复到就绪态, 只有通过函数 vTaskSuspend()设置为挂起态的任务才可以使用 vTaskRexume()恢复!

void vTaskResume(TaskHandleToResume)
xTaskResumeFromISR():中断服务函数中恢复一个任务的运行

此函数是 vTaskResume()的中断版本,用于在中断服务函数中恢复一个任务后

BaseType_t xTaskResumeFromISR(Task_Handle_t xTaskToResume)

参数:
xTaskToResume:要恢复的任务句柄

任务创建参考代码

对开始任务进入临界态再创建任务存在疑问

#include "sys.h"   
#include "usart.h" 
#include "gpio.h"                
#include "delay.h"
#include "FreeRTOS.h"
#include "task.h"
 
//LCD刷屏时使用的颜色
 
 
 
//任务优先级
#define START_TASK_PRIO		4
//任务堆栈大小	
#define START_STK_SIZE 		128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
 
//任务优先级
#define LED0_TASK_PRIO		0
//任务堆栈大小	
#define LED0_STK_SIZE 		20
//任务句柄
TaskHandle_t LED0Task_Handler;
//任务函数
void led0_task(void *pvParameters);
 
//任务优先级
#define LED1_TASK_PRIO	  0
//任务堆栈大小	
#define LED1_STK_SIZE 		20
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
 
int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4	 
	delay_init();	    				//延时函数初始化	  
	My_USART_Init();				//初始化串口
	MX_GPIO_Init();		  		//初始化GPIO
	
	//创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
}
 
//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    //创建LED0任务
    xTaskCreate((TaskFunction_t )led0_task,     	
                (const char*    )"led0_task",   	
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )LED0_TASK_PRIO,	
                (TaskHandle_t*  )&LED0Task_Handler);   
    //创建LED1任务
    xTaskCreate((TaskFunction_t )led1_task,     
                (const char*    )"led1_task",   
                (uint16_t       )LED1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LED1_TASK_PRIO,
                (TaskHandle_t*  )&LED1Task_Handler); 
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}
 
//LED0任务函数 
void led0_task(void *pvParameters)
{
    while(1)
    {
        LED0 = !LED0;
        vTaskDelay(500);
    }
}   
/* jwiw */
//LED1任务函数
void led1_task(void *pvParameters)
{
	uint16_t flag=0;
    while(1)
    {
			if(flag==0)
			{
				flag=1;vTaskDelay(200);
			}
			else flag=0;
        GPIO_ResetBits(GPIOE,GPIO_Pin_5);
        vTaskDelay(200);
        GPIO_SetBits(GPIOE,GPIO_Pin_5);
        vTaskDelay(800);
    }
}
 

队列相关API

了解队列

队列是为了任务与任务、任务与中断之间的通信而准备的,可以在任务与任务、任务与中断之间传递消息,队列中可以存储有限的、大小固定的数据项目。任务与任务、任务与中断之间要交流的数据保存在队列中,叫做队列项目。队列所能保存的最大数据项目数量叫做队列的长度,创建队列的时候会指定数据项目的大小和队列的长度。 由于队列用来传递消息的,所以也称为消息队列。 FreeRTOS 中的信号量的也是依据队列实现的! 所以有必要深入的了解FreeRTOS 的队列。

特点:先进先出,固定大小/长度

读取队列的两种方式

如果读取时队列 Q 是空

不阻塞:阻塞时间决定的,这个阻塞时间单位是时钟节拍数。 阻塞时间为 0 的话就是不阻塞,没有数据的话就马上返回任务继续执行接下来的代码。

阻塞:如果阻塞时间为 0~ portMAX_DELAY, 当任务没有从队列中获取到消息的话就进入阻塞态,阻塞时间指定了任务进入阻塞态的时间,当阻塞时间到了以后还没有接收到数据的话就退出阻塞态,返回任务接着运行下面的代码,如果在阻塞时间内接收到了数据就立即返回,执行任务中下面的代码


http://www.kler.cn/a/350413.html

相关文章:

  • MySQL面试题2025 每日20道【其四】
  • 通过学习更多样化的生成数据进行更广泛的数据分发来改进实例分割
  • Agent AI: 强化学习,模仿学习,大型语言模型和VLMs在智能体中的应用
  • SSM课设-学生管理系统
  • 【Golang/nacos】nacos配置的增删查改,以及服务注册的golang实例及分析
  • Linux(DISK:raid5、LVM逻辑卷)
  • qt 10.10作业
  • STM32—SPI通讯协议
  • Windows环境下Qt Creator调试模式下qDebug输出中文乱码问题
  • 华为OD机试 - 小朋友分组最少调整次数 - 贪心算法(Python/JS/C/C++ 2024 E卷 100分)
  • 讲一讲Redis五大数据类型的底层实现
  • libaom 源码分析:aomdec.c 文件
  • mac 桌面版docker no space left on device
  • PostgreSQL AUTO INCREMENT
  • Qt 如何 发送与解析不定长报文以及数组不定长报文
  • AUTOSAR CP, WdgM如何进行执行顺序监督的
  • Ubuntu 22.04 配置禁止密码登录,只允许密钥登录
  • 《深度学习》LSTM 长短期记忆网络 结构及原理解析
  • Redis学习笔记:跳跃表
  • nn.functional.softmax(X, dim=-1)
  • Visual Studio 2022常用快捷键
  • Elastisearch查询最近一年消费金额排名前五的用户
  • Jmeter脚本录制、Badboy脚本录制
  • Chromium html<img>对应c++接口定义
  • 【计算机毕设】springboot-考研资讯平台(附源码)
  • 五、UI弹窗提示