百问网FreeRTOS复习笔记第15到21讲

/*

源代码以及其他一切形式的知识转述均出自百问网课程,仅供参考,请勿用作商业用途。

  【FreeRTOS入门与工程实践 --由浅入深带你学习FreeRTOS(FreeRTOS教程 基于STM32,以实际项目为导向)】 https://www.bilibili.com/video/BV1Jw411i7Fz/?p=8&share_source=copy_web&vd_source=bab35cd72a6b7a3ffd3c77e664d802f1 

*/

第15讲     内存管理

内存管理即是如何使用FreeRTOS中的堆。对于堆中的内存,CubeMX做出如下图管理,首先内存分配既可以是静态的也可以是动态的,其次堆的总容量大约为3072字节,最后使用的内存调度算法是heap_4 。

不同内存调度算法对比:

一般使用heap_4,有多块内存使用heap_5。有关heap的函数,大家可以参考韦老师编撰的手册。

第16讲 创建任务_声光色影

这一讲的目的是分别用静态、动态的方式创建多个任务。

一个任务至少需要三个要素:函数、栈空间和任务优先级。当它被挂起之后我们又应该如何寻找它呢?FreeRTOS对于被被挂起的任务提供了查询链表,找到头节点之后就可以顺藤摸瓜,这个链表中存放着任务结构体(TCB:TaskControlBlock)。

主要学习任务就是学会使用这两个API,xTaskCreate与xTaskCreateStatic的用法。我按照老师思路编程并且改掉了所有的error和warning,不然后面越积越多。贴一下代码:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "Music.h"
#include "driver_led.h"
#include "driver_lcd.h"
#include "driver_mpu6050.h"
#include "driver_timer.h"
#include "driver_ds18b20.h"
#include "driver_dht11.h"
#include "driver_active_buzzer.h"
#include "driver_passive_buzzer.h"
#include "driver_color_led.h"
#include "driver_ir_receiver.h"
#include "driver_ir_sender.h"
#include "driver_light_sensor.h"
#include "driver_ir_obstacle.h"
#include "driver_ultrasonic_sr04.h"
#include "driver_spiflash_w25q64.h"
#include "driver_rotary_encoder.h"
#include "driver_motor.h"
#include "driver_key.h"
#include "driver_uart.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
StackType_t g_pucStackofLightTask[128];
StaticTask_t g_TCBofLightTask;

StackType_t g_pucStackofColourTask[128];
StaticTask_t g_TCBofColourTask;
/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */
  TaskHandle_t xSoundTaskHandle;
	BaseType_t ret1;
	TaskHandle_t ret2,ret3;
	
	
  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of defaultTask */
  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
	/*创建任务:声*/
  do{
	  ret1=xTaskCreate(PlayMusic,"SoundTask",128,NULL,osPriorityNormal,&xSoundTaskHandle);
	}while(ret1==pdFAIL);
	/*创建任务:光*/
	do{
	  ret2=xTaskCreateStatic(Led_Test,"lightTask",128,NULL,osPriorityNormal,g_pucStackofLightTask,&g_TCBofLightTask);
	}while(ret2==pdFAIL);
	/*创建任务:色*/
	do{
	  ret3=xTaskCreateStatic(ColorLED_Test,"ColorLEDTask",128,NULL,osPriorityNormal,g_pucStackofColourTask,&g_TCBofColourTask);
	}while(ret3==pdFAIL);
	
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  LCD_Init();
	LCD_Clear();
	
	
  for(;;)
  {
		LCD_Test();
    osDelay(5);
  }
  /* USER CODE END StartDefaultTask */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

仅供大家参考吧,实际上用do while循环判断是不合理的。

第17讲 创建任务_估算栈的大小

栈里面保存着返回地址(LR寄存器等,用来存储函数的调用关系等)、局部变量、现场(任务发生切换时保留16✖4字节)。调用程度越深,需要的栈就越大。

第18讲 创建任务_使用任务参数

这节课的任务是用同一个函数互斥地使用访问OLED屏幕。

首先为了完成需求,我们抽象出一个打印函数,需要传递的参数有x、y坐标轴以及打印内容。

然后设置一个全局变量保护LCD屏幕的访求权限,这实际上是一种不可靠的方式。这节课老师留下了两个疑问,怎么样才能可靠地互斥使用LCD以及为什么单片机先执行了最后创建地任务三。

贴一下我改的0错误0警告代码:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "Music.h"
#include  "driver_led.h"
#include "driver_lcd.h"
#include "driver_mpu6050.h"
#include "driver_timer.h"
#include "driver_ds18b20.h"
#include "driver_dht11.h"
#include "driver_active_buzzer.h"
#include "driver_passive_buzzer.h"
#include "driver_color_led.h"
#include "driver_ir_receiver.h"
#include "driver_ir_sender.h"
#include "driver_light_sensor.h"
#include "driver_ir_obstacle.h"
#include "driver_ultrasonic_sr04.h"
#include "driver_spiflash_w25q64.h"
#include "driver_rotary_encoder.h"
#include "driver_motor.h"
#include "driver_key.h"
#include "driver_uart.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
struct TaskPrintInfo{
    uint8_t x;
	  uint8_t y;
    char name[16];
};

struct TaskPrintInfo g_Task1Info={0,0,"Task1"};
struct TaskPrintInfo g_Task2Info={0,3,"Task2"};
struct TaskPrintInfo g_Task3Info={0,6,"Task3"};

int g_LCDCanUse=1;

void LcdPrintfTask(void * params)
{
	 struct TaskPrintInfo *pInfo=params;
   uint32_t count=0;
   int len;
	
   for(;;)
	{
		 if (g_LCDCanUse)
		{
			g_LCDCanUse = 0;
			len = LCD_PrintString(pInfo->x, pInfo->y, pInfo->name);
			len += LCD_PrintString(len, pInfo->y, ":");
			LCD_PrintSignedVal(len, pInfo->y, count++);
			g_LCDCanUse = 1;
		}
		mdelay(500);
	}
}
/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */
  LCD_Init();
	LCD_Clear();
  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of defaultTask */
//  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
	/*使用同一个函数常见不同的任务*/
	xTaskCreate(LcdPrintfTask,"Task1",128,&g_Task1Info,osPriorityNormal,NULL);
	xTaskCreate(LcdPrintfTask,"Task2",128,&g_Task2Info,osPriorityNormal,NULL);
	xTaskCreate(LcdPrintfTask,"Task3",128,&g_Task3Info,osPriorityNormal,NULL);
	
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
	LCD_Init();
	LCD_Clear();
	
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END StartDefaultTask */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

第19讲 删除任务_用遥控器控制音乐

/*我的遥控器电池没电了,所以后面和遥控器有关的代码我只能说没有逻辑错误。*/

这一讲要掌握的API是:

void vTaskDelete( TaskHandle_t xTaskToDelete );

其中的参数pvTaskCode是指一个任务句柄,使用 xTaskCreate 创建任务时可以得到一个句柄。

也可传入 NULL,这表示删除自己。注意在实际开发过程中我们应该尽量避免频繁创建任务、删除任务,这可能造成内存碎片化,浪费MCU稀缺的内存资源。

第20讲 优先级与阻塞_改善播放状态

本节课我们的目标是学会提高音乐播放任务的优先级,以及vTaskDelay延时函数的用法。

在FreeRTOS中,vTaskDelay函数是用于使当前任务延迟一段相对时间的方法。这是实时操作系统中任务调度的一个重要部分,它允许任务暂停执行一段时间,以便其他任务可以执行。

函数的原型如下:

void vTaskDelay( TickType_t xTicksToDelay );

其中,xTicksToDelay参数表示任务需要延迟的时间量,以时钟节拍(tick)为单位。这个时间是从当前时间开始计算的。举个例子,如果你设置xTicksToDelay为100,那么当前任务将会被延迟100个时钟节拍。在这段时间内,该任务不会执行任何代码,而其他任务则可以在这段时间内执行。当100个时钟节拍过去后,该任务将自动从延返回到其被vTaskDelay调用之前的位置,并继续执行。请注意,任务的延迟时间是以FreeRTOS的时钟节拍为单位的,而不是以通常的秒或毫秒为单位。你可以使用FreeRTOS的xPortSysTickHandler函数获取当前的时钟节拍值。这个函数是线程/任务调度的基础,它允许你控制任务的执行顺序和时间,从而实现复杂的实时应用程序。

第21讲 任务状态_改进播放控制

这一讲我们的任务是解析任务管理的内部机制(链表、优先级管理、任务的挂起与恢复),实验现象上是为孤泳者(big胆!)的播放增加暂停与恢复的功能。

一个任务可能有这么几种状态:挂起(suspended)、阻塞(blocked)、运行(running)、就绪(ready)态。如下图所示:

一个任务被创建之后默认处于Ready状态,进入运行态时可能被带有阻塞作用的API(例如vTaskDelay)带入Blocked态,然后等待预设时间的发生回到就绪态。想要进入挂起态的方法只有一种,就是调用vTaskSuspend(既可以是自身调用,也可能是处于running态的任务调用)。

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "Music.h"
#include "driver_led.h"
#include "driver_lcd.h"
#include "driver_mpu6050.h"
#include "driver_timer.h"
#include "driver_ds18b20.h"
#include "driver_dht11.h"
#include "driver_active_buzzer.h"
#include "driver_passive_buzzer.h"
#include "driver_color_led.h"
#include "driver_ir_receiver.h"
#include "driver_ir_sender.h"
#include "driver_light_sensor.h"
#include "driver_ir_obstacle.h"
#include "driver_ultrasonic_sr04.h"
#include "driver_spiflash_w25q64.h"
#include "driver_rotary_encoder.h"
#include "driver_motor.h"
#include "driver_key.h"
#include "driver_uart.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
StackType_t g_pucStackofLightTask[128];
StaticTask_t g_TCBofLightTask;

StackType_t g_pucStackofColourTask[128];
StaticTask_t g_TCBofColourTask;
/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */
  TaskHandle_t xSoundTaskHandle;
	BaseType_t ret1;
	TaskHandle_t ret2,ret3;
  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of defaultTask */
  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
	/*创建任务:声*/
  do{
	  ret1=xTaskCreate(PlayMusic,"SoundTask",128,NULL,osPriorityNormal,&xSoundTaskHandle);
	}while(ret1==pdFAIL);
	/*创建任务:光*/
	do{
	  ret2=xTaskCreateStatic(Led_Test,"lightTask",128,NULL,osPriorityNormal,g_pucStackofLightTask,&g_TCBofLightTask);
	}while(ret2==pdFAIL);
	/*创建任务:色*/
	do{
	  ret3=xTaskCreateStatic(ColorLED_Test,"ColorLEDTask",128,NULL,osPriorityNormal,g_pucStackofColourTask,&g_TCBofColourTask);
	}while(ret3==pdFAIL);
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  uint8_t dev, data;
  BaseType_t ret;
	TaskHandle_t xSoundTaskHandle=NULL;
	int bRunning;
	
	LCD_Init();
	LCD_Clear();

  IRReceiver_Init();
	LCD_PrintString(0,0,"Waiting control");

	 for(;;)
	{
    /*读取红外遥控器键值*/
		 if(IRReceiver_Read(&dev,&data)==0)
		{
			if(data==0xa8)/*play按键*/
			{
			  /*创建播放音乐的任务*/
				if(xSoundTaskHandle==NULL)
				{
					LCD_ClearLine(0,0);
					LCD_PrintString(0,0,"Create Task");
					do{
					 xTaskCreate(PlayMusic,"SoundTask",128,NULL,osPriorityNormal+1,&xSoundTaskHandle);
					}while(ret==pdFAIL);
					bRunning=1;
			  }else{
				 /*要么suspemd、要么resume*/
					if(bRunning==1)
					{
					  vTaskSuspend(xSoundTaskHandle);
						LCD_ClearLine(0,0);
					  LCD_PrintString(0,0,"Suspend Task");
						PassiveBuzzer_Control(0);//停止蜂鸣器
					  bRunning=0;
					}else
					{
					  vTaskResume(xSoundTaskHandle);
						LCD_ClearLine(0,0);
					  LCD_PrintString(0,0,"Resume Task");
					  bRunning=1;
					}
				}
			}else if(data==0xa2)/*power按键*/
			{
			  /*删除播放音乐的任务*/
				if(xSoundTaskHandle!=NULL)
				{
					LCD_ClearLine(0,0);
					LCD_PrintString(0,0,"Delete Task");
			    vTaskDelete(xSoundTaskHandle);
					PassiveBuzzer_Control(0);//停止蜂鸣器
					xSoundTaskHandle=NULL;
				}
			}
		}
	}
  /* USER CODE END StartDefaultTask */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值