FreeRTOS实时操作系统(1)

ops/2024/10/24 10:20:32/

RTOS.html" title=FreeRTOS>FreeRTOS%E5%86%85%E5%AE%B9%E8%BE%83%E5%A4%9A%EF%BC%8C%E5%88%86%E7%AF%87%E5%8F%91%E5%B8%83%EF%BC%8C%E8%BE%83%E4%B8%BA%E5%9F%BA%E7%A1%80%EF%BC%8C%E6%97%A8%E5%9C%A8%E6%A2%B3%E7%90%86%E7%9F%A5%E8%AF%86%EF%BC%8C%E9%80%82%E5%90%88%E5%85%A5%E9%97%A8%E7%9A%84%E5%90%8C%E5%AD%A6%C2%A0%20%C2%A0">前言:RTOS.html" title=FreeRTOS>FreeRTOS内容较多,分篇发布,较为基础,旨在梳理知识,适合入门的同学   

(基于正点原子STM32F103开发板V2

(对于本篇,若有疑问,欢迎在评论区留言,作者将在两小时内解答)

RTOS.html" title=FreeRTOS>FreeRTOS%EF%BC%89">(本篇参考B站正点原子RTOS.html" title=FreeRTOS>FreeRTOS

目录

RTOS.html" title=FreeRTOS>FreeRTOS%E5%86%85%E5%AE%B9%E8%BE%83%E5%A4%9A%EF%BC%8C%E5%88%86%E7%AF%87%E5%8F%91%E5%B8%83%EF%BC%8C%E8%BE%83%E4%B8%BA%E5%9F%BA%E7%A1%80%EF%BC%8C%E6%97%A8%E5%9C%A8%E6%A2%B3%E7%90%86%E7%9F%A5%E8%AF%86%EF%BC%8C%E9%80%82%E5%90%88%E5%85%A5%E9%97%A8%E7%9A%84%E5%90%8C%E5%AD%A6%C2%A0%20%C2%A0-toc" style="margin-left:0px;">前言:RTOS.html" title=FreeRTOS>FreeRTOS内容较多,分篇发布,较为基础,旨在梳理知识,适合入门的同学   

(基于正点原子STM32F103开发板V2)

(对于本篇,若有疑问,欢迎在评论区留言,作者将在两小时内解答)

RTOS.html" title=FreeRTOS>FreeRTOS%EF%BC%89-toc" style="margin-left:0px;">(本篇参考B站正点原子RTOS.html" title=FreeRTOS>FreeRTOS

RTOS-toc" style="margin-left:0px;">1.RTOS

RTOS%E5%8E%9F%E7%90%86-toc" style="margin-left:40px;">1.1RTOS原理

RTOS%E7%89%B9%E7%82%B9-toc" style="margin-left:40px;">1.2RTOS特点

RTOS.html" title=FreeRTOS>FreeRTOS-toc" style="margin-left:0px;">2.RTOS.html" title=FreeRTOS>FreeRTOS

RTOS.html" title=FreeRTOS>FreeRTOS-toc" style="margin-left:40px;"> 2.1RTOS.html" title=FreeRTOS>FreeRTOS

RTOS.html" title=FreeRTOS>FreeRTOS%E7%89%B9%E7%82%B9-toc" style="margin-left:40px;">2.2RTOS.html" title=FreeRTOS>FreeRTOS特点

RTOS.html" title=FreeRTOS>FreeRTOS%E7%9A%84API%E5%87%BD%E6%95%B0-toc" style="margin-left:40px;">2.3RTOS.html" title=FreeRTOS>FreeRTOS的API函数

RTOS.html" title=FreeRTOS>FreeRTOS%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86-toc" style="margin-left:0px;">3.RTOS.html" title=FreeRTOS>FreeRTOS基础知识

3.1任务调度

3.2抢占式调度

3.3时间片调度

3.5任务状态

3.6任务状态列表

3.8总结

RTOS.html" title=FreeRTOS>FreeRTOS%E4%BB%BB%E5%8A%A1%E5%88%9B%E5%BB%BA%E5%92%8C%E5%88%A0%E9%99%A4-toc" style="margin-left:0px;">4.RTOS.html" title=FreeRTOS>FreeRTOS任务创建和删除

 4.1任务控制块结构体

4.2动态创建任务

4.3静态创建任务

4.4任务删除函数

4.5空闲任务

4.6动态创建函数实战

4.7静态创建函数实战

4.8实战总结

5.总结


RTOS">1.RTOS

RTOS%E5%8E%9F%E7%90%86">1.1RTOS原理

RTOS全称为:Real Time OS,就是实时操作系统,强调的是:实时性,

宏观上是可多任务同时进行的操作系统,实际上是在规定的若干很小的时刻,交替进行各个任务的一个工作原理,从表面上看像是在同时进行多任务

RTOS%E7%89%B9%E7%82%B9">1.2RTOS特点

1.多任务:实现功能划分为多个任务

2.延时函数:任务调度

3.抢占式:高优先级任务抢占低优先级任务

4.任务堆栈:每个任务都有自己的栈空间

注意1:中断可以打断任意任务

注意2:任务可以同等优先级

RTOS.html" title=FreeRTOS>FreeRTOS">2.RTOS.html" title=FreeRTOS>FreeRTOS

RTOS.html" title=FreeRTOS>FreeRTOS"> 2.1RTOS.html" title=FreeRTOS>FreeRTOS

  RTOS.html" title=FreeRTOS>FreeRTOS 可以分为两部分:“Free”和“RTOS”,
Free”就是免费的、 自由的、不受约束的意思
因此,从 RTOS.html" title=FreeRTOS>FreeRTOS 的名字中就 能看出,FreeROTS 是一款免费的实时操作系统

RTOS.html" title=FreeRTOS>FreeRTOS%E7%89%B9%E7%82%B9">2.2RTOS.html" title=FreeRTOS>FreeRTOS特点

RTOS.html" title=FreeRTOS>FreeRTOS%E7%9A%84API%E5%87%BD%E6%95%B0">2.3RTOS.html" title=FreeRTOS>FreeRTOS的API函数

RTOS.html" title=FreeRTOS>FreeRTOS 是一个轻量级的实时操作系统内核,它提供了丰富的 API 函数,用于创建和管理任务、同步任务间的通信、调度任务以及进行系统配置等。以下是一些 RTOS.html" title=FreeRTOS>FreeRTOS 中常见的 API 函数及其用途:

1.任务创建:

  • xTaskCreate: 创建一个新的任务
  • xTaskCreateStatic: 创建一个静态分配的任务

2.任务管理:

  • vTaskDelete: 删除一个任务
  • vTaskSuspend: 暂停一个任务
  • vTaskResume: 恢复一个任务
  • eTaskGetState: 获取任务当前的状态

3.任务同步:

  • xSemaphoreCreateBinary: 创建一个二值信号量
  • xSemaphoreCreateMutex: 创建一个互斥量
  • xSemaphoreGive: 释放一个信号量
  • xSemaphoreTake: 获取一个信号量

4.任务通信:

  • xQueueCreate: 创建一个队列
  • xQueueSend: 向队列发送数据
  • xQueueReceive: 从队列接收数据

5.定时器:

  • xTimerCreate: 创建一个定时器
  • vTimerStart: 启动一个定时器
  • vTimerStop: 停止一个定时器

6.任务调度:

  • vTaskDelay: 延迟一个任务执行
  • eTaskGetIdleTaskHandle: 获取空闲任务句柄

7.系统配置:

  • eKernelGetTickRateHz: 获取系统滴答时钟的频率
  • vApplicationGetIdleTaskMemory: 获取空闲任务的内存

8.内存管理:

  • pvPortMalloc: 动态分配内存
  • vPortFree: 释放动态分配的内存

这些只是 RTOS.html" title=FreeRTOS>FreeRTOS API 的一部分。RTOS.html" title=FreeRTOS>FreeRTOS 提供了全面的文档,详细介绍了每个函数的用法、参数和返回值。开发者在使用这些 API 时,需要根据具体的任务需求和环境配置来选择合适的函数

RTOS.html" title=FreeRTOS>FreeRTOS%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86">3.RTOS.html" title=FreeRTOS>FreeRTOS基础知识

3.1任务调度

任务调度器就是使用相关的调度算法来决定当前需要执行的哪个任务

RTOS.html" title=FreeRTOS>FreeRTOS 一共支持三种任务调度方式:

3.2抢占式调度

运行条件:

运行过程:

特点

1.高优先级任务,优先执行

2.高优先级任务不停止,低优先级任务无法执行

3.被抢占的任务将会进入就绪态

3.3时间片调度

时间片:同等优先级任务轮流地享有相同的 CPU 时间(可设置一个时间片的时间(SysTick 中断周期)),在RTOS.html" title=FreeRTOS>FreeRTOS中,一个时间片就等于SysTick 中断周期,并且一个任务只能拥有一个时间片

运行条件:

运行过程:

特点:

1.同等优先级任务,轮流执行;时间片流转

2.一个时间片大小,取决为滴答定时器中断周期

3.注意没有用完的时间片不会再使用,下次任务Task3得到执行 还是按照一个时间片的时钟节拍运行

(在RTOS.html" title=FreeRTOS>FreeRTOS中,当一个任务阻塞时,操作系统会立即停止该任务的执行,并将CPU的控制权切换给另一个就绪状态的任务。如果Task1已经准备好执行(即它处于就绪状态),那么它将会被调度器选中,并开始执行)

3.5任务状态

RTOS.html" title=FreeRTOS>FreeRTOS中任务共存在4种状态:

四种任务状态之间的转换图:

特点:

1.仅就绪态可转变成运行态

2.其他状态的任务想运行,必须先转变成就绪态

3.6任务状态列表

RTOS.html" title=FreeRTOS>FreeRTOS中无非就四种状态,运行态,就绪态、阻塞态、挂起态

这四种状态中,除了运行态,其他三种任务状态的任务都有其对应的任务状态列表

特点:

1. 32位的变量,当某个位,置一时,代表所对应的优先级就绪列表有任务存在

2. 列表跟链表很像,后续会讲到

3. 调度器总是在所有处于就绪列表的任务中,选择具有最高优先级的任务来执行

4. 相同优先级的任务会连接在同一个就绪列表上

3.8总结

RTOS.html" title=FreeRTOS>FreeRTOS%E4%BB%BB%E5%8A%A1%E5%88%9B%E5%BB%BA%E5%92%8C%E5%88%A0%E9%99%A4">4.RTOS.html" title=FreeRTOS>FreeRTOS任务创建和删除

 任务的创建和删除本质就是调用RTOS.html" title=FreeRTOS>FreeRTOS的API函数

 4.1任务控制块结构体

typedef struct tskTaskControlBlock       
{volatile StackType_t 		* pxTopOfStack; 					/* 任务栈栈顶,必须为TCB的第一个成员 */ListItem_t 			        xStateListItem;           					/* 任务状态列表项 */      ListItem_t 			        xEventListItem;					/* 任务事件列表项 */     UBaseType_t 			    uxPriority;                					/* 任务优先级,数值越大,优先级越大 */StackType_t 		        * pxStack;						/* 任务栈起始地址 */char 				        pcTaskName[ configMAX_TASK_NAME_LEN ]; 	/* 任务名字 */		…省略很多条件编译的成员
} tskTCB;

4.2动态创建任务

        动态创建任务:任务的任务控制块以及任务的栈空间所需的内存,均由 RTOS.html" title=FreeRTOS>FreeRTOS

RTOS.html" title=FreeRTOS>FreeRTOS 管理的堆中分配

动态创建任务函数:

BaseType_t xTaskCreate
( TaskFunction_t 				    pxTaskCode,	    /* 指向任务函数的指针 */ 				            const char * const                pcName          /* 任务名字,最大长度configMAX_TASK_NAME_LEN ,默认16个字符*/const configSTACK_DEPTH_TYPE 		usStackDepth, 	/* 任务堆栈大小,注意字为单位 */void * const 					    pvParameters,	/* 传递给任务函数的参数 */UBaseType_t 		                uxPriority,		/*  任务优先级,范围:0 ~ configMAX_PRIORITIES - 1(0~31) */TaskHandle_t * const 			    pxCreatedTask 	/* 任务句柄,就是任务的任务控制块 */
)

errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY:一般是任务所需要的空间太大,RTOS.html" title=FreeRTOS>FreeRTOS所管理的堆栈空间不够

实现动态创建任务流程

4.3静态创建任务

        静态创建任务任务的任务控制块以及任务的栈空间所需的内存,需用户分配提供

静态创建任务函数

TaskHandle_t xTaskCreateStatic
(TaskFunction_t		    pxTaskCode,				/* 指向任务函数的指针 */const char * const		pcName,				/* 任务函数名 */const uint32_t			ulStackDepth, 			/* 任务堆栈大小注意字为单位 */void * const			pvParameters, 			/* 传递的任务函数参数 */UBaseType_t			    uxPriority, 				/* 任务优先级 */StackType_t * const		puxStackBuffer, 			/* 任务堆栈,一般为数组,由用户分配 */StaticTask_t * const	pxTaskBuffer				/* 任务控制块指针,由用户分配 */
); 	

实现静态创建任务流程

4.4任务删除函数

用于删除已被创建的任务,被删除的任务将从就绪态任务列表、阻塞态任务列表、挂起态任务列表和事件列表中移除

void vTaskDelete(TaskHandle_t xTaskToDelete);

注意:

1.当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)

2.2、空闲任务(下面会讲到)会负责释放被删除任务中由系统分配的内存(动态创建任务),但是由用户在任务删除前申请的内存, 则需要由用户在任务被删除前提前释放,否则将导致内存泄露(静态创建任务)

删除任务流程

4.5空闲任务

  • 当一个任务调用 vTaskDelete() 删除自身时,它会被标记为删除状态,但它的内存不会被立即回收。
  • 空闲任务周期性地运行,它会检查系统中是否有任务被标记为删除状态
  • 如果发现被删除的任务,空闲任务会释放该任务的堆栈空间和任务控制块,将其占用的内存归还给系统。
  • 通过这种方式,空闲任务帮助维护系统的内存资源,确保不会有内存泄漏

4.6动态创建函数实战

(基于正点原子STM32F103开发板V2   a盘资料)

第一步:

将宏configSUPPORT_DYNAMIC_ALLOCATION 配置为 1 (默认)

路径:   \User\freertos_demo.c\RTOS.html" title=FreeRTOS>FreeRTOSConfig.h

第二步:

配置任务task1、task2、task3、start_task以及屏幕显示

路径:User\freertos_demo.c

详细细节在代码中有解释(注释)

#include "freertos_demo.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*RTOS.html" title=FreeRTOS>FreeRTOS*********************************************************************************************/
#include "RTOS.html" title=FreeRTOS>FreeRTOS.h"
#include "task.h"/******************************************************************************************************/
/*RTOS.html" title=FreeRTOS>FreeRTOS配置*//* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 128偏大定义*/
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 *//* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 *//* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO      3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 *//* TASK3 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK3_PRIO      4                   /* 任务优先级 */
#define TASK3_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task3Task_Handler;  /* 任务句柄 */
void task3(void *pvParameters);             /* 任务函数 *//******************************************************************************************************//* LCD刷屏时使用的颜色 */
uint16_t lcd_discolor[11] = {WHITE, BLACK, BLUE, RED,MAGENTA, GREEN, CYAN, YELLOW,BROWN, BRRED, GRAY};/*** @brief       RTOS.html" title=FreeRTOS>FreeRTOS例程入口函数* @param       无* @retval      无*/
void freertos_demo(void)
{lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);lcd_show_string(10, 47, 220, 24, 24, "Task Create & Del", RED);lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);lcd_draw_rectangle(5, 110, 115, 314, BLACK);lcd_draw_rectangle(125, 110, 234, 314, BLACK);lcd_draw_line(5, 130, 115, 130, BLACK);lcd_draw_line(125, 130, 234, 130, BLACK);lcd_show_string(15, 111, 110, 16, 16, "Task1: 000", BLUE);lcd_show_string(135, 111, 110, 16, 16, "Task2: 000", BLUE);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();
}/*** @brief       start_task* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           /* 进入临界区 *//* 创建任务1 */xTaskCreate((TaskFunction_t )task1,                 /* 任务函数 */(const char*    )"task1",               /* 任务名称 */(uint16_t       )TASK1_STK_SIZE,        /* 任务堆栈大小 */(void*          )NULL,                  /* 传入给任务函数的参数 */(UBaseType_t    )TASK1_PRIO,            /* 任务优先级 */(TaskHandle_t*  )&Task1Task_Handler);   /* 任务句柄 *//* 创建任务2 */xTaskCreate((TaskFunction_t )task2,                 /* 任务函数 */(const char*    )"task2",               /* 任务名称 */(uint16_t       )TASK2_STK_SIZE,        /* 任务堆栈大小 */(void*          )NULL,                  /* 传入给任务函数的参数 */(UBaseType_t    )TASK2_PRIO,            /* 任务优先级 */(TaskHandle_t*  )&Task2Task_Handler);   /* 任务句柄 *//* 创建任务3 */xTaskCreate((TaskFunction_t )task3,                 /* 任务函数 */(const char*    )"task3",               /* 任务名称 */(uint16_t       )TASK3_STK_SIZE,        /* 任务堆栈大小 */(void*          )NULL,                  /* 传入给任务函数的参数 */(UBaseType_t    )TASK3_PRIO,            /* 任务优先级 */(TaskHandle_t*  )&Task3Task_Handler);   /* 任务句柄 */vTaskDelete(StartTask_Handler); /* 删除开始任务 */taskEXIT_CRITICAL();            /* 退出临界区 */
}/*** @brief       task1* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task1(void *pvParameters)
{uint32_t task1_num = 0;while (1){lcd_fill(6, 131, 114, 313, lcd_discolor[++task1_num % 11]);lcd_show_xnum(71, 111, task1_num, 3, 16, 0x80, BLUE);vTaskDelay(500);}
}/*** @brief       task2* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task2(void *pvParameters)
{uint32_t task2_num = 0;while (1){lcd_fill(126, 131, 233, 313, lcd_discolor[11 - (++task2_num % 11)]);lcd_show_xnum(191, 111, task2_num, 3, 16, 0x80, BLUE);vTaskDelay(500);}
}/*** @brief       task3* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task3(void *pvParameters)
{uint8_t key = 0;while (1){key = key_scan(0);switch (key){case KEY0_PRES:                     /* 删除任务1 */{if (Task1Task_Handler != NULL){vTaskDelete(Task1Task_Handler);Task1Task_Handler = NULL;}break;}case KEY1_PRES:                     /* 删除任务2 */{if (Task2Task_Handler != NULL){vTaskDelete(Task2Task_Handler);Task2Task_Handler = NULL;}break;}default:{break;}}vTaskDelay(10);}
}

实验现象:

每500ms,两块区域颜色变化,并计数+1

4.7静态创建函数实战

(基于正点原子STM32F103开发板V2   a盘资料)

第一步:

将宏configSUPPORT_STATIC_ALLOCATION 配置为 1(默认为0)

路径:\User\freertos_demo.c\RTOS.html" title=FreeRTOS>FreeRTOSConfig.h

第二步:

定义空闲任务&定时器任务的任务堆栈及TCB

接口函数:vApplicationGetTimerTaskMemory ( ):这个函数用于获取计时器任务(Timer Task)的内存分配

目的:获取定时器服务任务的任务堆栈和任务控制块内存

static StackType_t  TimerTaskStack[configTIMER_TASK_STACK_DEPTH];   /* 定时器服务任务堆栈 */
static StaticTask_t TimerTaskTCB;                                   /* 定时器服务任务控制块 */* @brief       获取定时器服务任务的任务堆栈和任务控制块内存* @param       ppxTimerTaskTCBBuffer:任务控制块内存ppxTimerTaskStackBuffer:任务堆栈内存pulTimerTaskStackSize:任务堆栈大小* @retval      无*/
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,StackType_t  **ppxTimerTaskStackBuffer,uint32_t     *pulTimerTaskStackSize)
{*ppxTimerTaskTCBBuffer  = &TimerTaskTCB;*ppxTimerTaskStackBuffer= TimerTaskStack;*pulTimerTaskStackSize  = configTIMER_TASK_STACK_DEPTH;
}

第三步:

接口函数

vApplicationGetIdleTaskMemory( ):这个函数用于获取空闲任务(Idle Task)的内存分配

目的:获取空闲任务地任务堆栈和任务控制块内存,因为本例程使用的静态内存,因此空闲任务的任务堆栈和任务控制块的内存就应该由用户来提供,RTOS.html" title=FreeRTOS>FreeRTOS提供了接口函数(上面的两个函数)

static StackType_t  IdleTaskStack[configMINIMAL_STACK_SIZE];        /* 空闲任务任务堆栈 */
static StaticTask_t IdleTaskTCB;                                    /* 空闲任务控制块 */* @brief       获取空闲任务地任务堆栈和任务控制块内存,因为本例程使用的静态内存,因此空闲任务的任务堆栈和任务控制块的内存就应该由用户来提供,RTOS.html" title=FreeRTOS>FreeRTOS提供了接口函数vApplicationGetIdleTaskMemory()实现此函数即可。* @param       ppxIdleTaskTCBBuffer:任务控制块内存ppxIdleTaskStackBuffer:任务堆栈内存pulIdleTaskStackSize:任务堆栈大小* @retval      无*/
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t  **ppxIdleTaskStackBuffer, uint32_t     *pulIdleTaskStackSize)
{*ppxIdleTaskTCBBuffer   = &IdleTaskTCB;*ppxIdleTaskStackBuffer = IdleTaskStack;*pulIdleTaskStackSize   = configMINIMAL_STACK_SIZE;
}

第四步:

配置任务task1、task2、task3、start_task以及屏幕显示

路径:User\freertos_demo.c

详细细节在代码中有解释(注释)

完整代码(包括二三步):


static StackType_t  IdleTaskStack[configMINIMAL_STACK_SIZE];        /* 空闲任务任务堆栈 */
static StaticTask_t IdleTaskTCB;                                    /* 空闲任务控制块 */
static StackType_t  TimerTaskStack[configTIMER_TASK_STACK_DEPTH];   /* 定时器服务任务堆栈 */
static StaticTask_t TimerTaskTCB;                                   /* 定时器服务任务控制块 *//*** @brief       获取空闲任务地任务堆栈和任务控制块内存,因为本例程使用的静态内存,因此空闲任务的任务堆栈和任务控制块的内存就应该有用户来提供,RTOS.html" title=FreeRTOS>FreeRTOS提供了接口函数vApplicationGetIdleTaskMemory()实现此函数即可。* @param       ppxIdleTaskTCBBuffer:任务控制块内存ppxIdleTaskStackBuffer:任务堆栈内存pulIdleTaskStackSize:任务堆栈大小* @retval      无*/
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t  **ppxIdleTaskStackBuffer, uint32_t     *pulIdleTaskStackSize)
{*ppxIdleTaskTCBBuffer   = &IdleTaskTCB;*ppxIdleTaskStackBuffer = IdleTaskStack;*pulIdleTaskStackSize   = configMINIMAL_STACK_SIZE;
}/*** @brief       获取定时器服务任务的任务堆栈和任务控制块内存* @param       ppxTimerTaskTCBBuffer:任务控制块内存ppxTimerTaskStackBuffer:任务堆栈内存pulTimerTaskStackSize:任务堆栈大小* @retval      无*/
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,StackType_t  **ppxTimerTaskStackBuffer,uint32_t     *pulTimerTaskStackSize)
{*ppxTimerTaskTCBBuffer  = &TimerTaskTCB;*ppxTimerTaskStackBuffer= TimerTaskStack;*pulTimerTaskStackSize  = configTIMER_TASK_STACK_DEPTH;
}/* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
StackType_t StartTaskStack[START_STK_SIZE]; /* 任务堆栈 */
StaticTask_t            StartTaskTCB;       /* 任务控制块 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 *//* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
StackType_t Task1TaskStack[TASK1_STK_SIZE]; /* 任务堆栈 */
StaticTask_t            Task1TaskTCB;       /* 任务控制块 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 *//* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO      3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
StackType_t Task2TaskStack[TASK2_STK_SIZE]; /* 任务堆栈 */
StaticTask_t            Task2TaskTCB;       /* 任务控制块 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 *//* TASK3 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK3_PRIO      4                   /* 任务优先级 */
#define TASK3_STK_SIZE  128                 /* 任务堆栈大小 */
StackType_t Task3TaskStack[TASK3_STK_SIZE]; /* 任务堆栈 */
StaticTask_t            Task3TaskTCB;       /* 任务控制块 */
TaskHandle_t            Task3Task_Handler;  /* 任务句柄 */
void task3(void *pvParameters);             /* 任务函数 *//******************************************************************************************************//* LCD刷屏时使用的颜色 */
uint16_t lcd_discolor[11] = {WHITE, BLACK, BLUE, RED,MAGENTA, GREEN, CYAN, YELLOW,BROWN, BRRED, GRAY};/*** @brief       RTOS.html" title=FreeRTOS>FreeRTOS例程入口函数* @param       无* @retval      无*/
void freertos_demo(void)
{lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);lcd_show_string(10, 47, 220, 24, 24, "Task Create & Del", RED);lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);lcd_draw_rectangle(5, 110, 115, 314, BLACK);lcd_draw_rectangle(125, 110, 234, 314, BLACK);lcd_draw_line(5, 130, 115, 130, BLACK);lcd_draw_line(125, 130, 234, 130, BLACK);lcd_show_string(15, 111, 110, 16, 16, "Task1: 000", BLUE);lcd_show_string(135, 111, 110, 16, 16, "Task2: 000", BLUE);StartTask_Handler = xTaskCreateStatic((TaskFunction_t   )start_task,        /* 任务函数 */(const char*      )"start_task",      /* 任务名称 */(uint32_t         )START_STK_SIZE,    /* 任务堆栈大小 */(void*            )NULL,              /* 传递给任务函数的参数 */(UBaseType_t      )START_TASK_PRIO,   /* 任务优先级 */(StackType_t*     )StartTaskStack,    /* 任务堆栈 */(StaticTask_t*    )&StartTaskTCB);    /* 任务控制块 */vTaskStartScheduler();
}/*** @brief       start_task* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           /* 进入临界区 *//* 创建任务1 */Task1Task_Handler = xTaskCreateStatic((TaskFunction_t   )task1,         /* 任务函数 */(const char*      )"task1",       /* 任务名称 */(uint32_t         )TASK1_STK_SIZE,/* 任务堆栈大小 */(void*            )NULL,          /* 传递给任务函数的参数 */(UBaseType_t      )TASK1_PRIO,    /* 任务优先级 */(StackType_t*     )Task1TaskStack,/* 任务堆栈 */(StaticTask_t*    )&Task1TaskTCB);/* 任务控制块 *//* 创建任务2 */Task2Task_Handler = xTaskCreateStatic((TaskFunction_t   )task2,         /* 任务函数 */(const char*      )"task2",       /* 任务名称 */(uint32_t         )TASK2_STK_SIZE,/* 任务堆栈大小 */(void*            )NULL,          /* 传递给任务函数的参数 */(UBaseType_t      )TASK2_PRIO,    /* 任务优先级 */(StackType_t*     )Task2TaskStack,/* 任务堆栈 */(StaticTask_t*    )&Task2TaskTCB);/* 任务控制块 *//* 创建任务3 */Task3Task_Handler = xTaskCreateStatic((TaskFunction_t   )task3,         /* 任务函数 */(const char*      )"task3",       /* 任务名称 */(uint32_t         )TASK3_STK_SIZE,/* 任务堆栈大小 */(void*            )NULL,          /* 传递给任务函数的参数 */(UBaseType_t      )TASK3_PRIO,    /* 任务优先级 */(StackType_t*     )Task3TaskStack,/* 任务堆栈 */(StaticTask_t*    )&Task3TaskTCB);/* 任务控制块 */vTaskDelete(StartTask_Handler); /* 删除开始任务 */taskEXIT_CRITICAL();            /* 退出临界区 */
}/*** @brief       task1* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task1(void *pvParameters)
{uint32_t task1_num = 0;while (1){lcd_fill(6, 131, 114, 313, lcd_discolor[++task1_num % 11]);lcd_show_xnum(71, 111, task1_num, 3, 16, 0x80, BLUE);vTaskDelay(500);}
}/*** @brief       task2* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task2(void *pvParameters)
{uint32_t task2_num = 0;while (1){lcd_fill(126, 131, 233, 313, lcd_discolor[11 - (++task2_num % 11)]);lcd_show_xnum(191, 111, task2_num, 3, 16, 0x80, BLUE);vTaskDelay(500);}
}/*** @brief       task3* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task3(void *pvParameters)
{uint8_t key = 0;while (1){key = key_scan(0);switch (key){case KEY0_PRES:                     /* 删除任务1 */{if (Task1Task_Handler != NULL){vTaskDelete(Task1Task_Handler);Task1Task_Handler = NULL;}break;}case KEY1_PRES:                     /* 删除任务2 */{if (Task2Task_Handler != NULL){vTaskDelete(Task2Task_Handler);Task2Task_Handler = NULL;}break;}default:{break;}}vTaskDelay(10);}
}

除了定义接口函数外,其余与动态创建的函数相同

实验现象:

每500ms,两块区域颜色变化,并计数+1

4.8实战总结

注意:

1.动态创建相对简单,在实际的应用中,动态方式创建任务是比较常用的,除非有特殊的需求,一般都会使用动态方式创建任务
2.静态创建:可将任务堆栈放置在特定的内存位置,并且无需关心对内存分配失败的处理

5.总结

RTOS.html" title=FreeRTOS>FreeRTOS官网:https://www.freertos.org/

正点原子STM32F103开发板V2   a盘资料: https://pan.baidu.com/s/1iebOVd87jBVtoudMijboIg 提取码:1ypa

RTOS.html" title=FreeRTOS>FreeRTOS内容较多,内容分篇发布,感谢大家观看

连载中...  

作者留言:本人学生,大多数为网络资源,如有侵权,及时联系

创作时间:2024.10.22


http://www.ppmy.cn/ops/127708.html

相关文章

[LeetCode] 50. Pow(x, n)

题目描述: 实现 pow(x, n) ,即计算 x 的整数 n 次幂函数(即,xn )。 示例 1: 输入:x 2.00000, n 10 输出:1024.00000示例 2: 输入:x 2.10000, n 3 输出…

2024年科技赋能教育,AI辅导引领新趋势

在近日举行的2024年中国国际服务贸易交易会上,教育服务展区凭借科技与教育深度融合的特色,成功吸引了大量参观者的注意。特别是主打AI个性化辅导的学习产品,更是成为了众多家长眼中的“省妈神器”。 “大语言模型”技术的快速发展及其科学化…

【C++刷题】力扣-#243-最短单词距离

题目描述 给定一个单词列表 words 和两个单词 word1 和 word2,返回这两个单词在列表中的最短距离。如果 word1 和 word2 是同一个单词,则返回它与自身的最近距离。 示例 示例 1: 输入: words ["practice", "makes", "perfec…

函数模板和类模板

博客ID:LanFuRenC系列专栏:C语言重点部分 C语言注意点 C基础 Linux 数据结构 C注意点 声明等级:黑色->蓝色->红色 欢迎新粉加入,会一直努力提供更优质的编程博客,希望大家三连支持一下啦 目录 1&#xff0…

【系统规划与管理师】历年各章节分值汇总(论文)

【移动端浏览】☞【系统规划与管理师】历年各章节分值汇总(论文) 第4章 IT服务规划设计 第5章 IT服务部署实施 第6章 IT服务运营管理 第7章 IT服务持续改进 第8章 监督管理 第9章 IT服务营销 第10章 团队建设与管理

新版idea菜单栏展开与合并

新版idea把菜单栏合并了看着很是不习惯,找了半天原来在这里展开 ① 点击文件 -> 设置 ② 点击外观与行为 -> 外观 -> 合并主菜单和窗口标题 然后确定,重启即可

10.22学习

1.求余 在C语言中,求余操作是通过取模运算符 % 来实现的。取模运算符会返回两个数相除后的余数。对于正数和负数的除法,求余的结果会有所不同,但 % 运算符总是返回被除数的符号。 下面是一个简单的例子,展示如何使用 % 运…

KubeSphere

初始密码 Account: admin Password: P88w0rd ansible部署 选一台master 节点 --- - hosts: k8s_mastersbecome: yestasks:- name: Install Gitpackage:name: gitstate: present- name: Download Helmget_url:url: https://get.helm.sh/helm-v3.16.2-linux-amd64.tar.gzdest: …