硬件初始化

定义一个bsp_init初始化函数,把初始化外设的函数都放到那里面去,

1
2
3
4
static void BSP_INIT(void){
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
LED_GPIO_Config(); //初始化led
}

创建单任务——SRAM静态内存

静态内存,即预先定义好的全局变量,这些变量保存值内部SRAM中。他们是运行前分配的,之前用ucos是就一直使用的是静态内存,

定义任务函数

任务必须返回值,是死循环,要延时时,要使用freertos提供的延时函数,不能自己写一个for循环延时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static void  LED_Task(void* parameter){
while(1){
LED(ON);
vTaskDelay(500); // 延时500个tick
LED(OFF);
vTaskDelay(500); // 延时500个tick
}
}
下面这种做法是不对的
/*static void LED_Task(void* parameter){
while(1){
for(i=0; i < 0xfffff; i++){
i++;
}
LED(ON);
for(i=0; i < 0xfffff; i++){
i++;
}
LED(OFF);
}
}*/

空闲任务与定时器任务函数

使用静态创建任务时,需要将 configSUPPORT_STATIC_ALLOCATION 置为1,(貌似freertos并不能控制stm32硬件支不支持静态内存,只是对系统做了一个限制)。同时,支持静态内存后,我们还必须为空闲任务(idle)和定时器(timer)分配任务堆栈,不能是动态分配,即需要实现 vApplicationGetIdleTaskMemory 和 vApplicationGetTimerTaskMemory两个函数。代码中有如下解释:

1
2
3
4
5
6
7
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
/* If static allocation is supported then the application must provide the
following callback function - which enables the application to optionally
provide the memory that will be used by the timer task as the task's stack
and TCB. */
extern void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize );
#endif

两个任务实现如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//空闲任务堆栈
static StackType_t Idle_Task_Stack[configMINIMAL_STACK_SIZE];
//定时器任务堆栈
static StackType_t Timer_Task_Stack[configTIMER_TASK_STACK_DEPTH]; //config文件中有

//任务控制块
static StaticTask_t Idle_Task_TCB;
static StaticTask_t Timer_Task_TCB;
//实现接口函数
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 vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ){
*ppxIdleTaskTCBBuffer = &Idle_Task_TCB;
*ppxIdleTaskStackBuffer = Idle_Task_Stack;
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}

定义任务栈与任务控制块

与ucos极其类似

1
2
3
4
5
6
//创建任务堆栈
static StackType_t AppTaskCreate_Stack[configMINIMAL_STACK_SIZE];
static StackType_t LED_Task_Stack[configMINIMAL_STACK_SIZE];
//任务控制块
static StaticTask_t AppTaskCreate_TCB;
static StaticTask_t LED_Task_TCB;

静态创建任务

静态任务创建函数——xTaskCreateStatic

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
static void AppTaskCreate(void){
TaskHandle_t LED_Task_Handle;
taskENTER_CRITICAL(); //进入临界区

LED_Task_Handle = xTaskCreateStatic((TaskFunction_t)LED_Task,//任务函数
(const char*)"LED_Task",//任务名
(uint32_t)configMINIMAL_STACK_SIZE,//任务堆栈大小
(void*)NULL,//传给任务函数的参数
(UBaseType_t)3,//任务优先级
(StackType_t*)LED_Task_Stack,//任务堆栈
(StaticTask_t*)&LED_Task_TCB);//任务TCB
if(NULL != LED_Task_Handle)
printf("LED TASK 任务创建成功");
else
printf("LED TASK 任务创建失败");
vTaskDelete(AppTaskCreate_Handle);

taskEXIT_CRITICAL();
}
int main(void){
int i = 0;
TaskHandle_t AppTaskCreate_Handle; //TaskHandle_t是void*类型
BSP_INIT();
AppTaskCreate_Handle = xTaskCreateStatic((TaskFunction_t)AppTaskCreate,
(const char*)"AppTaskCreate",
(uint32_t)configMINIMAL_STACK_SIZE,
(void*)NULL,
(UBaseType_t)3,
(StackType_t*)AppTaskCreate_Stack,
(StaticTask_t*)&AppTaskCreate_TCB);
if(NULL != AppTaskCreate_Handle)
vTaskStartScheduler();
while(1);
}

创建单任务——SRAM动态内存

动态内存空间的堆来自哪——在SRAM中定义一个大数组,供FreeRTOS的动态分配内存使用,第一次使用时会对堆进行初始化,这些代码在heap_x.c中

1
2
3
4
5
6
7
8
9
10
11
12
1 //系统所有总的堆大小
2 #define configTOTAL_HEAP_SIZE ((size_t)(36*1024)) (1)
3 static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; (2)
4 /* 如果这是第一次调用 malloc 那么堆将需要
5 初始化,以设置空闲块列表。*/
6 if ( pxEnd == NULL )
7 {
8 prvHeapInit(); (3)
9 } else
10 {
11 mtCOVERAGE_TEST_MARKER();
12 }

定义任务函数

与创建静态任务时一致

定义任务控制块指针

不需要预先定义好全局静态的控制块空间,任务创建时任务控制块会自动创建,任务创建函数会返回一个任务控制块指针,所以要预先定义一个任务控制块指针(任务句柄)。