Freertos入门代码(不全)

124 阅读11分钟

debug

image.png

  • 蓝色三角形表示光标LINE,黄色三角形表示程序运行到的line,

静态任务创建(推荐动态)

#include "freertos_demo.h"


/*静态宏*/
#define configSUPPORT_STATIC_ALLOCATION   	1 
//开启软件定时器
//#define configUSE_TIMERS                                1                               /* 1: 使能软件定时器, 默认: 0 */
//#define configTIMER_TASK_PRIORITY                       ( configMAX_PRIORITIES - 1 )    /* 定义软件定时器任务的优先级, 无默认configUSE_TIMERS为1时需定义 */
//#define configTIMER_QUEUE_LENGTH                        5                               /* 定义软件定时器命令队列的长度, 无默认configUSE_TIMERS为1时需定义 */
//#define configTIMER_TASK_STACK_DEPTH                    ( configMINIMAL_STACK_SIZE * 2) /* 定义软件定时器任务的栈空间大小, 无默认configUSE_TIMERS为1时需定义 */



 volatile int task1_flag=0;
volatile int task2_flag=0;
volatile int task3_flag=0;
volatile int key_flag=0;


#define START_TASK_PRIORITY 1
#define START_TASK_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t start_task_handle ;
StackType_t start_task_stack[START_TASK_STACK]; //静态任务任务栈以数组存储
StaticTask_t start_task_TCB;//静态任务TCb结构体类型

void start_task(void *   pvParameters);




#define  TASK1_PRIORITY 2
#define  TASK1_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t  task1_handle ;
StackType_t  task1_stack[TASK1_STACK]; //静态任务任务栈以数组存储
StaticTask_t  task1_TCB;//静态任务TCb结构体类型

void  task1(void *   pvParameters);



#define TASK2_PRIORITY 3
#define TASK2_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t task2_handle ;
StackType_t  task2_stack[TASK2_STACK]; //静态任务任务栈以数组存储
StaticTask_t  task2_TCB;//静态任务TCb结构体类型

void task2(void *   pvParameters);


#define TASK3_PRIORITY 4
#define TASK3_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t task3_handle ;
StackType_t  task3_stack[TASK3_STACK]; //静态任务任务栈以数组存储
StaticTask_t  task3_TCB;//静态任务TCb结构体类型

void task3(void *   pvParameters);





//接口函数

/* 空闲任务配置 */
StaticTask_t idle_task_tcb;
StackType_t  idle_task_stack[configMINIMAL_STACK_SIZE];

/* 软件定时器任务配置 */
StaticTask_t timer_task_tcb;
StackType_t  timer_task_stack[configTIMER_TASK_STACK_DEPTH];

/* 空闲任务内存分配 */
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
                                    StackType_t ** ppxIdleTaskStackBuffer,
                                    uint32_t * pulIdleTaskStackSize )
{
    * ppxIdleTaskTCBBuffer = &idle_task_tcb;
    * ppxIdleTaskStackBuffer = idle_task_stack;
    * pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/* 空闲软件定时器任务资源 */
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
									StackType_t **ppxTimerTaskStackBuffer, 
									uint32_t *pulTimerTaskStackSize )
{
	*ppxTimerTaskTCBBuffer=&timer_task_tcb;
	*ppxTimerTaskStackBuffer=timer_task_stack;
	*pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
	
}






void freertos_start(void)
{
	/* 创建一个启动任务*/
	

	
start_task_handle=xTaskCreateStatic(		
					(TaskFunction_t) start_task,
					(char *)   "start_task",
					(uint16_t) START_TASK_STACK,
					(void *)   NULL,
					(UBaseType_t) START_TASK_PRIORITY,
					(StackType_t * )	 start_task_stack,/* 任务栈地址*/
					(StaticTask_t *)	  &start_task_TCB )  ;//TCB地址
				
			/*开启任务调度器:自动创建空闲任务,和软件定时器,静态需要实现两个接口函数*/
			
vTaskStartScheduler();					
			
}

void start_task(void *   pvParameters) 
{
	/* 进入临界区*/
taskENTER_CRITICAL();//临界区里面的代码不会被打断,加锁
	
	


task1_handle=xTaskCreateStatic(	
		(TaskFunction_t) task1,
		(char *)   "task1",
		(uint16_t) TASK1_STACK,
		(void *)   NULL,
		 (UBaseType_t) TASK1_PRIORITY,
		(StackType_t * )	  task1_stack,/* 任务栈地址*/
		(StaticTask_t *)	  & task1_TCB )  ;//TCB地址
task2_handle=xTaskCreateStatic(	
		(TaskFunction_t) task2,
		(char *)   "task2",
		(uint16_t) TASK2_STACK,
		(void *)   NULL,
		 (UBaseType_t) TASK2_PRIORITY,
		(StackType_t * )	  task2_stack,/* 任务栈地址*/
		(StaticTask_t *)	  & task2_TCB )  ;//TCB地址
			

	task3_handle=xTaskCreateStatic(	
		(TaskFunction_t) task3,
		(char *)   "task3",
		(uint16_t) TASK3_STACK,
		(void *)   NULL,
		 (UBaseType_t) TASK3_PRIORITY,
		(StackType_t * )	  task3_stack,/* 任务栈地址*/
		(StaticTask_t *)	  & task3_TCB )  ;//TCB地址
	
		
		
		taskEXIT_CRITICAL();
		
		
		vTaskDelete(NULL);// 要先退临界区再删除,这样才能确保系统调度准确性
		
}
void task1( void * pvParameters )
{
	while(1)
	{
		task1_flag++;
		
 		 HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
		
		 
		vTaskDelay(500);
		

	}
}
void task2( void * pvParameters )
{
	while(1)
	{
		
		 
		task2_flag++;
		
		 HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
		
		 
		vTaskDelay(500);
		
		 
		 
		

	}
}
 
void task3( void * pvParameters )
{
	while(1)
	{
		
 

		task3_flag++;

if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==0)
{
	key_flag++;
if(task1_handle!=NULL)
{
 vTaskDelete( task1_handle);
task1_handle=NULL;


}

}

vTaskDelay(500);
		

	}
}



动态

#include "freertos_demo.h"



 volatile int task1_flag=0;
volatile int task2_flag=0;
volatile int task3_flag=0;
volatile int key_flag=0;


#define START_TASK_PRIORITY 1
#define START_TASK_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t start_task_handle ;

StackType_t start_task_stack[START_TASK_STACK]; //静态任务任务栈以数组存储
StaticTask_t start_task_TCB;//静态任务TCb结构体类型

void start_task(void *   pvParameters);


#define  TASK1_PRIORITY 2
#define  TASK1_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t  task1_handle ;

void  task1(void *   pvParameters);



#define TASK2_PRIORITY 3
#define TASK2_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t task2_handle ;

void task2(void *   pvParameters);


#define TASK3_PRIORITY 4
#define TASK3_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t task3_handle ;

void task3(void *   pvParameters);


void freertos_start(void)
{
	/* 创建一个启动任务*/
	
xTaskCreate(	(TaskFunction_t) start_task,
			(char *)   "start_task",
			(uint16_t) START_TASK_STACK,
			(void *)   NULL,
			 (UBaseType_t) START_TASK_PRIORITY,
			(TaskHandle_t * )  &start_task_handle )  ;
			
	
	//静态返回值为句柄
 		
}

void start_task(void *   pvParameters) 
{
	/* 进入临界区*/
taskENTER_CRITICAL();//临界区里面的代码不会被打断,加锁
	
	

		
xTaskCreate(	
		(TaskFunction_t) task2,
		(char *)   "task2",
		(uint16_t) TASK2_STACK,
		(void *)   NULL,
		 (UBaseType_t) TASK2_PRIORITY,
		(TaskHandle_t * )  &task2_handle )  ;
		
xTaskCreate(	
		(TaskFunction_t) task3,
		(char *)   "task3",
		(uint16_t) TASK3_STACK,
		(void *)   NULL,
		 (UBaseType_t) TASK3_PRIORITY,
		(TaskHandle_t * )  &task3_handle )  ;
xTaskCreate(	
		(TaskFunction_t) task1,
		(char *)   "task1",
		(uint16_t) TASK1_STACK,
		(void *)   NULL,
		 (UBaseType_t) TASK1_PRIORITY,
		(TaskHandle_t * )  &task1_handle )  ;
		
		
		
		
		
		taskEXIT_CRITICAL();
		
		
		vTaskDelete(NULL);// 要先退临界区再删除,这样才能确保系统调度准确性
		
}
void task1( void * pvParameters )
{
	while(1)
	{
		task1_flag++;
		
 		 HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
		
		 
		vTaskDelay(500);
		

	}
}
void task2( void * pvParameters )
{
	while(1)
	{
		
		 
		task2_flag++;
		
		 HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
		
		 
		vTaskDelay(500);
		
		 
		 
		

	}
}
 
void task3( void * pvParameters )
{
	while(1)
	{
		
 

		task3_flag++;

if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==0)
{
	key_flag++;
if(task1_handle!=NULL)
{
 vTaskDelete( task1_handle);
task1_handle=NULL;


}

}

vTaskDelay(500);
		

	}
}

队列(动态)

#include "freertos_demo.h"



volatile int task1_flag=0;
volatile int task2_flag=0;
volatile int task3_flag=0;


char str[500];//接受任务信息

 
#define START_TASK_PRIORITY 1
#define START_TASK_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t start_task_handle ;
 
void start_task(void *   pvParameters);




#define  TASK1_PRIORITY 2
#define  TASK1_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t  task1_handle ;
 

void  task1(void *   pvParameters);



#define TASK2_PRIORITY 3
#define TASK2_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t task2_handle ;
  
void task2(void *   pvParameters);


#define TASK3_PRIORITY 4
#define TASK3_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t task3_handle ;
 
void task3(void *   pvParameters);






/*队列句柄*/

QueueHandle_t queue1;
QueueHandle_t big_queue;

 

void freertos_start(void)
{
	
	/*在创建任务之前,将队列设置好*/
	//存放key值
	queue1=xQueueCreate(2,sizeof(uint8_t));
	if(queue1!=NULL)
		printf("queue1 create successfully\r\n");
	else
		printf("queue1   error\r\n");

	//存放大数据的队列==>存放地址即可
	big_queue=xQueueCreate(1,sizeof(char *));
	if(big_queue!=NULL)
		printf("big_queue create successfully\r\n");
	else
		printf("big_queue   error\r\n");
	
	
	
	
	
	/* 创建一个启动任务*/
	
xTaskCreate(	(TaskFunction_t) start_task,
			(char *)   "start_task",
			(uint16_t) START_TASK_STACK,
			(void *)   NULL,
			 (UBaseType_t) START_TASK_PRIORITY,
			(TaskHandle_t * )  &start_task_handle )  ;
			
	
 /*开启任务调度器:自动创建空闲任务,和软件定时器,静态需要实现两个接口函数*/
			
vTaskStartScheduler();					
			
}

void start_task(void *   pvParameters) 
{
	/* 进入临界区*/
taskENTER_CRITICAL();//临界区里面的代码不会被打断,加锁
	
	

if(xTaskCreate(	
		(TaskFunction_t) task1,
		(char *)   "task1",
		(uint16_t) TASK1_STACK,
		(void *)   NULL,
		 (UBaseType_t) TASK1_PRIORITY,
		(TaskHandle_t * )  &task1_handle )  != pdPASS)
		printf("Failed to create task1\r\n");
		
if(xTaskCreate(	
		(TaskFunction_t) task2,
		(char *)   "task2",
		(uint16_t) TASK2_STACK,
		(void *)   NULL,
		 (UBaseType_t) TASK2_PRIORITY,
		(TaskHandle_t * )  &task2_handle )   != pdPASS)
			printf("Failed to create task2\r\n");
		
		
if(xTaskCreate(	
		(TaskFunction_t) task3,
		(char *)   "task3",
		(uint16_t) TASK3_STACK,
		(void *)   NULL,
		 (UBaseType_t) TASK3_PRIORITY,
		(TaskHandle_t * )  &task3_handle )  != pdPASS)
		
		printf("Failed to create task3\r\n");
		
 	

 
		
		taskEXIT_CRITICAL();
		
		
		vTaskDelete(NULL);// 要先退临界区再删除,这样才能确保系统调度准确性
		
}

/** task1
目标:当按键key1或key2按下,将键值拷贝到队列queue1(入队);当按键key3按下,将传输大数据,这里拷贝大数据的地址到队列big_queue中。

*/
void task1( void * pvParameters )
{
	uint8_t key_value=0;
	
	BaseType_t que_retn;
	char * big_data=" abcdefghigklmnopq ";
	
	
	
	while(1)
	{
		task1_flag++;
		
		
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==0) 
{
	
	key_value=1;
	
printf("key1 down\r\n");

}
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2)==0) 
{
		key_value=2;	
printf("key2 down\r\n");

}
 if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0) 
{
		key_value=3;

	
printf("key3 down\r\n");

}

if(key_value==1||key_value==2)
{
	que_retn=xQueueSend(queue1, &key_value, portMAX_DELAY);
	
	if(que_retn==1)
		
		printf("successed in sending kv:%d to queue1\r\n",key_value);	
	
	else
		printf("failed to send  queue1!!\r\n");	
		
}	

else if(key_value==3)
{
	/*将大数据发送到big_queue*/
	que_retn=xQueueSend(big_queue,&big_data,portMAX_DELAY);
	if(que_retn==1)
		
		printf("successed in sending data to big_queue\r\n");	
	else
		printf("failed to send  big_queue!!\r\n");	
	
}
		vTaskDelay(100);

	}
	
}
/** task2
目标:读取队列queue1中的消息(出队),打印出接收到的键值。(访问小数据出队)


*/
void task2( void * pvParameters )
{
	uint8_t r2_data=0;
	BaseType_t r2_que=0;
	
	while(1)
	{ 
		r2_que=xQueueReceive(queue1 ,&r2_data,portMAX_DELAY);
		if(r2_que==pdTRUE)
			printf("task2 receive  data:%d from queue1\r\n",r2_data);
		else
			printf("failed receive  data from queue1!!\r\n");	
	}
}

/** task3
目标:从队列big_queue读取大数据地址,通过地址访问大数据。


*/

void task3( void * pvParameters )
{
	BaseType_t r3_que=0;
	
	char * r3_data;
	
	task3_flag++;
	while(1)
	{
 
		r3_que=xQueueReceive(big_queue ,&r3_data,portMAX_DELAY);

		if(r3_que==pdTRUE)
			
			printf("big_data:%s \r\n",r3_data);
		else if(r3_que==pdFALSE)
			
			printf("failed receive  data from bigqueue!!\r\n");	

	}
}


内存管理

image.png

#include "freertos_demo.h"


volatile uint8_t key1_flag;
volatile uint8_t key2_flag;


/*
************************************任务通知模仿轻量信号量
*/

 
#define START_TASK_PRIORITY 1
#define START_TASK_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t start_task_handle ;
 
void start_task(void *   pvParameters);

#define  TASK1_PRIORITY 2
#define  TASK1_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t  task1_handle ;
 

void  task1(void *   pvParameters);


void freertos_start(void)
{
	/* 创建一个启动任务*/
	
xTaskCreate(	(TaskFunction_t) start_task,
			(char *)   "start_task",
			(uint16_t) START_TASK_STACK,
			(void *)   NULL,
			 (UBaseType_t) START_TASK_PRIORITY,
			(TaskHandle_t * )  &start_task_handle )  ;
			
	
 /*开启任务调度器:自动创建空闲任务,和软件定时器,静态需要实现两个接口函数*/
			
vTaskStartScheduler();					
			
}

void start_task(void *   pvParameters) 
{
	/* 进入临界区*/
taskENTER_CRITICAL();//临界区里面的代码不会被打断,加锁
	
	
if(xTaskCreate(	
		(TaskFunction_t) task1,
		(char *)   "task1",
		(uint16_t) TASK1_STACK,
		(void *)   NULL,
		 (UBaseType_t) TASK1_PRIORITY,
		(TaskHandle_t * )  &task1_handle )  != pdPASS)
		printf("Failed to create task1 \r\n");
                
		taskEXIT_CRITICAL();
	
		vTaskDelete(NULL);// 要先退临界区再删除,这样才能确保系统调度准确性
		
}
void task1( void * pvParameters )
{
	void *buff;
	while(1)
	{
		 
		
		/*key1:申请内存	 */
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==0) 
		{
			key1_flag++;
			buff=pvPortMalloc(20);
			printf("key1 按下申请20内存,剩余内存:%d b\r\n",xPortGetFreeHeapSize());
		
			
	  
		}
		
		/*key2:释放内存	 */
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2)==0) 
		{
			key2_flag++;
			vPortFree(buff);
			printf("key2 按下释放内存,剩余内存:%d b\r\n",xPortGetFreeHeapSize());
		
	 
		}

		/*最后发现申请了32*/
		 
		vTaskDelay(500);
		

	}
}




内存管理改正版本

image.png

  • 专门使用一个数组来保存每次的地址

#include "freertos_demo.h"


volatile uint8_t key1_flag;
volatile uint8_t key2_flag;


/*
************************************任务通知模仿轻量信号量
*/

 
#define START_TASK_PRIORITY 1
#define START_TASK_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t start_task_handle ;
 
void start_task(void *   pvParameters);




#define  TASK1_PRIORITY 2
#define  TASK1_STACK 128 //堆栈大小,有128*4大小
TaskHandle_t  task1_handle ;
 

void  task1(void *   pvParameters);

 
 
 
#define MAX_ALLOCATIONS 10 // 最大内存申请数量
void *allocated_buffers[MAX_ALLOCATIONS]; // 用于存储已分配内存的数组
uint8_t allocation_count = 0; // 当前已分配内存块的数量


void freertos_start(void)
{
	/* 创建一个启动任务*/
	
xTaskCreate(	(TaskFunction_t) start_task,
			(char *)   "start_task",
			(uint16_t) START_TASK_STACK,
			(void *)   NULL,
			 (UBaseType_t) START_TASK_PRIORITY,
			(TaskHandle_t * )  &start_task_handle )  ;
			
	
 /*开启任务调度器:自动创建空闲任务,和软件定时器,静态需要实现两个接口函数*/
			
vTaskStartScheduler();					
			
}

void start_task(void *   pvParameters) 
{
	/* 进入临界区*/
taskENTER_CRITICAL();//临界区里面的代码不会被打断,加锁
	
	
if(xTaskCreate(	
		(TaskFunction_t) task1,
		(char *)   "task1",
		(uint16_t) TASK1_STACK,
		(void *)   NULL,
		 (UBaseType_t) TASK1_PRIORITY,
		(TaskHandle_t * )  &task1_handle )  != pdPASS)
		printf("Failed to create task1 \r\n");

		
 
 
		
		taskEXIT_CRITICAL();
		
		
		vTaskDelete(NULL);// 要先退临界区再删除,这样才能确保系统调度准确性
		
}
void task1( void * pvParameters )
{
	void *buff;
	uint8_t count=0;
	while(1)
	{
		 
		
		/*key1:申请内存	 */
		
	
             
		/*实际申请的内存,会比实际多出两部分:堆结构体,字节对齐*/
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==0) 
		{
			key1_flag++;
			
		if (allocation_count < MAX_ALLOCATIONS) 
			{
			  buff = pvPortMalloc(20);
			
			if (buff != NULL) 
			{
                    allocated_buffers[allocation_count] = buff; // 存储内存地址
                    allocation_count++; // 增加已分配数量
                    printf("key1 按下申请20内存, 剩余内存:%d b\r\n", xPortGetFreeHeapSize());
			}
			else
			printf("内存申请失败!!!\r\n");
             
			}
		else
		printf("已达到最大内存申请数量!!!\r\n");
		
			 
		}
		
		
		
		/*key2:释放内存	 */
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2)==0) 
		{
			key2_flag++;
			
			if (allocation_count > 0) {
                allocation_count--; // 减少已分配数量
                vPortFree(allocated_buffers[allocation_count]); // 释放内存
                allocated_buffers[allocation_count] = NULL; // 清空指针
                printf("key2 按下释放内存, 剩余内存:%d b\r\n", xPortGetFreeHeapSize());
            } 
			else 
				{
                printf("没有可释放的内存\r\n");
            }
			
			 
	 
		}

		  
		 
		vTaskDelay(500);
		

	}
}




延时函数

void delay_us(uint32_t delay_us)
{    
  volatile unsigned int num;
  volatile unsigned int t;
 
  
  for (num = 0; num < delay_us; num++)
  {
    t = 11;
    while (t != 0)
    {
      t--;
    }
  }
}

//毫秒级的延时
void delay_ms(uint16_t delay_ms)
{    
  volatile unsigned int num;
  for (num = 0; num < delay_ms; num++)
  {
    delay_us(1000);
  }
}

bug

  • 别把几节课能容写在一起