<FreeRTOS入门第十一节>空闲函数和钩子函数

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

今天学习了空闲函数和钩子函数感觉很不错


一、空闲函数是什么?

就是在FreeRTOS系统运行时主要任务不处理时进行的一个闲的蛋疼的任务,
同时我们可以在空闲函数里面进入低功耗模式来降低单片机的功耗

二、相关API介绍

1.空闲函数环境搭建

只需要打开和关闭下面的宏定义
在这里插入图片描述

2.相关API介绍

这里其实只需要重写一个函数就行,这个函数就是空闲任务执行的事情。
重写 vApplicationIdleHook();函数

void vApplicationIdleHook(void){
//这里的代码别管,只用看函数名。
	flag_task1=0;
	flag_task2=0;
	flag_task3=0;
	flag_IDLE=1;
	__disable_irq();
	__dsb(portSY_FULL_READ_WRITE);
	__isb(portSY_FULL_READ_WRITE);
	Free_PreSleepProcessing();
	__wfi();
	Free_PostSleepProcessing();
	
	__dsb(portSY_FULL_READ_WRITE);
	__isb(portSY_FULL_READ_WRITE);
	__enable_irq();
}

3.案例

空闲函数里面进入低功耗,关闭时钟。

#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "Timers.h"
#include "event_groups.h"
#include "stdio.h"
#include "Key.h"
#ifdef __GNUC__ //printf重定向
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
	HAL_UART_Transmit(&huart1, (uint8_t*)&ch,1,HAL_MAX_DELAY);
    return ch;
}

TaskHandle_t HandlerTask1;
TaskHandle_t Task_Name4;


BaseType_t xReturn;
SemaphoreHandle_t Task1semaphore;

TimerHandle_t AutoTimerTask;
TimerHandle_t OneTimerTask;

SemaphoreHandle_t semaphoreTask;



void SystemClock_Config(void);
StackType_t xTask3Static[128];
StaticTask_t xTaskTCB;

StackType_t xIdle3Static[128];
StaticTask_t xIdleTCB;

StackType_t xTimerStatic[526];
StaticTask_t xTimerTCB;

uint8_t flag_task1=0;
uint8_t flag_task2=0;
uint8_t flag_task3=0;
uint8_t flag_IDLE=0;
//进入低功耗模式执行任务
void Free_PreSleepProcessing(void){
	__HAL_RCC_GPIOA_CLK_DISABLE();
	__HAL_RCC_GPIOB_CLK_DISABLE();
	__HAL_RCC_GPIOC_CLK_DISABLE();
	__HAL_RCC_GPIOD_CLK_DISABLE();
	__HAL_RCC_GPIOE_CLK_DISABLE();
}

//退出低功耗模式执行任务
void Free_PostSleepProcessing(void){
	__HAL_RCC_GPIOA_CLK_ENABLE();
	__HAL_RCC_GPIOB_CLK_ENABLE();
	__HAL_RCC_GPIOC_CLK_ENABLE();
	__HAL_RCC_GPIOD_CLK_ENABLE();
	__HAL_RCC_GPIOE_CLK_ENABLE();
}

void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,StackType_t ** ppxIdleTaskStackBuffer,uint32_t * pulIdleTaskStackSize ){
			*ppxIdleTaskTCBBuffer=&xIdleTCB;				
			*ppxIdleTaskStackBuffer=xIdle3Static;
			*pulIdleTaskStackSize=128;
}
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
                                          StackType_t ** ppxTimerTaskStackBuffer,
                                              uint32_t * pulTimerTaskStackSize ){
		 	* ppxTimerTaskTCBBuffer=&xTimerTCB;
			* ppxTimerTaskStackBuffer=xTimerStatic;
			* pulTimerTaskStackSize=526;																																															
}

//空闲函数
void vApplicationIdleHook(void){
	flag_task1=0;
	flag_task2=0;
	flag_task3=0;
	flag_IDLE=1;
	__disable_irq();
	__dsb(portSY_FULL_READ_WRITE);
	__isb(portSY_FULL_READ_WRITE);
	Free_PreSleepProcessing();
	__wfi();
	Free_PostSleepProcessing();
	
	__dsb(portSY_FULL_READ_WRITE);
	__isb(portSY_FULL_READ_WRITE);
	__enable_irq();
}


void Task1Function( void * param){
	flag_task1=1;
	flag_task2=0;
	flag_task3=0;
	flag_IDLE=0;
	for(;;){
		
		printf("TASK1..\r\n");
		vTaskDelay(10);
	}
}
void Task2Function(void* param){
	flag_task1=0;
	flag_task2=1;
	flag_task3=0;
	flag_IDLE=0;
		int num;
		BaseType_t err;
  for(;;)
  {
		xSemaphoreGive(semaphoreTask);
		err=xSemaphoreTake(semaphoreTask,0);
		num =atoi(Rxbuff);
		//printf("NUM=%d\r\n",num);
		
			if(num==1){
				printf("NUM=%d\r\n",num);
				vTaskDelay(1000);
			}
			
		
		vTaskDelay(10);
  }
}
void Task3Funtion(void* param){
	flag_task1=0;
	flag_task2=0;
	flag_task3=1;
	flag_IDLE=0;
	TickType_t st_time=xTaskGetTickCount(); 

	while(1){
		uint32_t num =1;
		xTaskDelayUntil(&st_time,30);
		
	}
	
}

void Task4Funtion(void* param){
	taskENTER_CRITICAL();
	//创建标志位
	semaphoreTask=xSemaphoreCreateBinary();
														
	//创建任务
	xReturn=xTaskCreate(Task1Function,"Task1",128,NULL,2,&HandlerTask1);
	xTaskCreate(Task2Function,"Task2",128,NULL,2,NULL);
 	xTaskCreateStatic(Task3Funtion,"Task3",128,NULL,2,xTask3Static,&xTaskTCB);
	if(xReturn == pdPASS){
			uint8_t buffS[20]="Task1 Create OK..\r\n";
			HAL_UART_Transmit(&huart1,(uint8_t*)buffS,strlen(buffS)*sizeof(char),HAL_MAX_DELAY);
	
		}
	vTaskDelete(Task_Name4);
	taskEXIT_CRITICAL();
}



int main(void)
{
  
	
	HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
	MX_USART1_UART_Init();
	
	xTaskCreate(Task4Funtion,"Task4",600,NULL,1,&Task_Name4);
	
  vTaskStartScheduler();
	
  while (1)
  {
   
  }
 
}


void SystemClock_Config(void)
{
	
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};


  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

 
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

void Error_Handler(void)
{
 
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT

void assert_failed(uint8_t *file, uint32_t line)
{

}
#endif /* USE_FULL_ASSERT */


总结

空闲函数就是这么简单,好了差不多要入门FreeRTOS的操作系统了。嘿嘿。
春风得意马蹄疾,一日看尽长安花

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

单片有机机

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值