一:静态任务创建理论
二:创建静态任务实操
1、在前一节动态任务创建的基础上删除xcreattask()函数所创建的全部任务,只需要修改main.c文件即可,例如:
xTaskCreate((TaskFunction_t) led2_task,
(const char * ) "led2_task",
(uint16_t ) LED2_STK_DEPTH,
(void * ) NULL,
(UBaseType_t ) LED2_TASK_PRIO,
(TaskHandle_t *) &led2_task_handler);
2、根据上面静态创建任务的流程将宏定义configSUPPORT_STATIC_ALLOCATION 设置为 1,可以参考官网api手册。
3、将宏定义设置为1之后,我们需要定义 vApplicationGetIdleTaskMemory()、xTimerCreateTimerTask(); 这两个任务,可以通过开始任务调度函数vTaskStartScheduler找到这两个函数,直接跳转到该函数的定义即可。例如:
注意:如果不想定义这个定时器任务,我们需要吧宏定义configUSE_TIMERS改为0,否则会报错,不过新版本freertos系统默认为0.这里还是跟着课程走,将其改为1.
(这里还是写0,写1 相比老版本要改的位置有的多)
其中vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize )函数中pxIdleTaskTCBBuffer表示任务控制块内存,pxIdleTaskStackBuffer表示任务堆栈内存,ulIdleTaskStackSize表示任务堆栈大小。在任务调度函数vTaskStartScheduler中我们可以看到该函数并未声明 ,既需要我们自己定义,定义函数的模板可以全局跳转下。
3、 在main.c文件中添加这空闲任务和定时任务的函数定义,如下:
注意:这里定时器任务如果要把configUSE_TIMERS设置为1的话,上图中的所有定义都得修改,比较麻烦,这里还是将configUSE_TIMERS设置为0继续实验。
/*空闲任务配置*/
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;
}
/*软件定时器内存分配
vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer,
&pxTimerTaskStackBuffer,
&ulTimerTaskStackSize )
{
*pxTimerTaskTCBBuffer=&timer_task_tcb;
*pxTimerTaskStackBuffer=timer_task_stack;
*ulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
}*/
4、创建静态任务,可以参考官网
/* Dimensions of the buffer that the task being created will use as its stack.
NOTE: This is the number of words the stack will hold, not the number of
bytes. For example, if each stack item is 32-bits, and this is set to 100,
then 400 bytes (100 * 32-bits) will be allocated. */
#define STACK_SIZE 200
/* Structure that will hold the TCB of the task being created. */
StaticTask_t xTaskBuffer;
/* Buffer that the task being created will use as its stack. Note this is
an array of StackType_t variables. The size of StackType_t is dependent on
the RTOS port. */
StackType_t xStack[ STACK_SIZE ];
/* Function that implements the task being created. */
void vTaskCode( void * pvParameters )
{
/* The parameter value is expected to be 1 as 1 is passed in the
pvParameters value in the call to xTaskCreateStatic(). */
configASSERT( ( uint32_t ) pvParameters == 1UL );
for( ;; )
{
/* Task code goes here. */
}
}
/* Function that creates a task. */
void vOtherFunction( void )
{
TaskHandle_t xHandle = NULL;
/* Create the task without using any dynamic memory allocation. */
xHandle = xTaskCreateStatic(
vTaskCode, /* Function that implements the task. */
"NAME", /* Text name for the task. */
STACK_SIZE, /* Number of indexes in the xStack array. */
( void * ) 1, /* Parameter passed into the task. */
tskIDLE_PRIORITY,/* Priority at which the task is created. */
xStack, /* Array to use as the task's stack. */
&xTaskBuffer ); /* Variable to hold the task's data structure. */
/* puxStackBuffer and pxTaskBuffer were not NULL, so the task will have
been created, and xHandle will be the task's handle. Use the handle
to suspend the task. */
vTaskSuspend( xHandle );
}
5、根据官网创建属于我们自己的静态任务
#define START_STK_DEPTH 64
#define START_TASK_PRIO 1
TaskHandle_t start_task_handler;
StackType_t start_task_stack[START_STK_DEPTH];
StaticTask_t start_task_tcb;
void start_task(void * pvParameters);
start_task_handler=xTaskCreateStatic( (TaskFunction_t) start_task,
(char *) "start_task", /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
(uint32_t) START_STK_DEPTH,
(void * ) NULL,
(UBaseType_t)START_TASK_PRIO,
(StackType_t * ) start_task_stack,
(StaticTask_t * )&start_task_tcb );
6:完整版main函数
#include "stm32f10x.h" // Device header
#include "LED.h"
#include "Key.h"
#include "OLED.h"
#include "Serial.h"
#include "FreeRTOS.h"
#include "task.h"
uint16_t Num=0;
#define START_STK_DEPTH 64
#define START_TASK_PRIO 1
TaskHandle_t start_task_handler;
StackType_t start_task_stack[START_STK_DEPTH];
StaticTask_t start_task_tcb;
void start_task(void * pvParameters);
#define LED2_STK_DEPTH 64
#define LED2_TASK_PRIO 2
TaskHandle_t led2_task_handler;
void led2_task(char * pvParameters);
StackType_t led2_task_stack[LED2_STK_DEPTH];
StaticTask_t led2_task_tcb;
#define LED3_STK_DEPTH 64
#define LED3_TASK_PRIO 3
TaskHandle_t led3_task_handler;
void led3_task(char * pvParameters);
StackType_t led3_task_stack[LED3_STK_DEPTH];
StaticTask_t led3_task_tcb;
#define Stop_LED2_STK_DEPTH 64
#define Stop_LED2_TASK_PRIO 4
TaskHandle_t stop_LED2_task_handler;
void stop_LED2_task(char * pvParameters);
StackType_t stop_led2_task_stack[Stop_LED2_STK_DEPTH];
StaticTask_t stop_led2_task_tcb;
/*空闲任务配置*/
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;
}
/*软件定时器内存分配
vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer,
&pxTimerTaskStackBuffer,
&ulTimerTaskStackSize )
{
*pxTimerTaskTCBBuffer=&timer_task_tcb;
*pxTimerTaskStackBuffer=timer_task_stack;
*ulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
}*/
int main(void)
{
LED_Init();
Serial_Init();
Key_Init();
start_task_handler=xTaskCreateStatic( (TaskFunction_t) start_task,
(char *) "start_task", /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
(uint32_t) START_STK_DEPTH,
(void * ) NULL,
(UBaseType_t)START_TASK_PRIO,
(StackType_t * ) start_task_stack,
(StaticTask_t * )&start_task_tcb );
vTaskStartScheduler(); //开启任务调度器
}
/*******开始任务函数*****/
void start_task(void * pvParameters)
{
taskENTER_CRITICAL();
led2_task_handler=xTaskCreateStatic( (TaskFunction_t) led2_task,
(char *) "led2_task", /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
(uint32_t) LED2_STK_DEPTH,
(void * ) NULL,
(UBaseType_t)LED2_TASK_PRIO,
(StackType_t * ) led2_task_stack,
(StaticTask_t * )&led2_task_tcb );
led3_task_handler=xTaskCreateStatic( (TaskFunction_t) led3_task,
(char *) "led3_task", /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
(uint32_t) LED3_STK_DEPTH,
(void * ) NULL,
(UBaseType_t)LED3_TASK_PRIO,
(StackType_t * ) led3_task_stack,
(StaticTask_t * )&led3_task_tcb );
stop_LED2_task_handler=xTaskCreateStatic( (TaskFunction_t) stop_LED2_task,
(char *) "stop_LED2_task", /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
(uint32_t) Stop_LED2_STK_DEPTH,
(void * ) NULL,
(UBaseType_t)Stop_LED2_TASK_PRIO,
(StackType_t * ) stop_led2_task_stack,
(StaticTask_t * )&stop_led2_task_tcb );
vTaskDelete(start_task_handler);
taskEXIT_CRITICAL();
}
void led2_task(char * pvParameters)
{
for(;;)
{
Serial_Printf("LED2_task\r\n");
LED1_Turn();
vTaskDelay(333);
}
}
void led3_task(char * pvParameters)
{
for(;;)
{
Serial_Printf("LED3_task\r\n");
LED2_Turn();
vTaskDelay(1000);
}
}
void stop_LED2_task(char * pvParameters)
{
for(;;)
{
Serial_Printf("stop_LED2_task\r\n");
Num=Key_GetNum();
if(Num==1)
{
if(led2_task_handler!=NULL)
{
Serial_Printf("LED2_task已删除\r\n");
vTaskDelete(led2_task_handler);
led2_task_handler=NULL;
}
else{
Serial_Printf("LED2_task不存在\r\n");
}
}
vTaskDelay(300);
}
}