在本章,我们将直接上手创建一个简单的串口打印任务,检查我们的操作系统是否移植成功,并为我们之后的功能调试打基础。
下图为本章的思维导图。
以下是我自用的demo,只包含了这章要完成的串口打印任务。
注:demo里有些我之后写的东西没删干净,参考的时候忽略就好。
接下来,我们步入正题。
初始化
和逻辑系统一样,在使用外设的时候要先进行初始化。只有完成初始化才能使用外设。
在 main 函数中,这句话也是放在循环前面执行的。
void Hardware_Config(void)
{
USART_Config();
}
定义任务
我们这里定义一个每 500ms 打印一次的串口任务。
void Uart_Task(void * param)
{
while(1)
{
printf("Uart_Task is ok \r\n");
vTaskDelay(500);
}
}
在 FreeRTOS 中,有任务调度算法来管理任务的运行,因此每个任务都是一个简单的死循环任务。
创建任务控制块指针
我们还需要创建两个任务控制块指针,一个是任务创建函数的,一个是要执行的任务。
通过任务控制块指针,我们可以直接对任务进行操作。
static TaskHandle_t AppTaskCreate_Handle = NULL;
static TaskHandle_t Uart_Handle = NULL;
任务创建函数
在这个函数中,我们将所有的任务都在这里面完成创建。因为我们采用的是动态创建,所以我们不需要为任务提供内存空间,这些东西都会有系统来自动实现。我们只需要在完成任务创建之后删除任务创建函数就行。
void AppTaskCreate(void)
{
printf("LED_Task!\r\n");
/* 创建LED_Task任务 */
xTaskCreate((TaskFunction_t )Uart_Task, /* 任务入口函数 */
(const char* )"Uart_Task",/* 任务名字 */
(uint16_t )256, /* 任务栈大小 */
(void* )NULL, /* 任务入口函数参数 */
(UBaseType_t )2, /* 任务的优先级 */
(TaskHandle_t* )&Uart_Handle);/* 任务控制块指针 */
// printf("创建LED_Task任务成功!\r\n");
vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreate任务
}
main函数
在 main 函数中,首先要进行硬件初始化,然后是任务创建函数,最后开启调度器。为了防止程序执行出现异常,我们在写一个死循环放在函数末尾。
int main(void)
{
/* 开发板硬件初始化 */
Hardware_Config();
// printf("Task Creating\r\n");
/* 创建AppTaskCreate任务 */
xTaskCreate((TaskFunction_t )AppTaskCreate, /* 任务入口函数 */
(const char* )"AppTaskCreate",/* 任务名字 */
(uint16_t )256, /* 任务栈大小 */
(void* )NULL,/* 任务入口函数参数 */
(UBaseType_t )1, /* 任务的优先级 */
(TaskHandle_t* )&AppTaskCreate_Handle);/* 任务控制块指针 */
vTaskStartScheduler(); /* 启动任务,开启调度 */
while(1); /* 正常不会执行到这里 */
}
需要注意的是,任务创建函数中规定了任务栈的大小,如果因为任务栈过小而导致任务创建或执行出现异常,我们可以通过调整任务栈大小来解决。但是原则上,任务栈大小要合适,不要一味地让任务栈较大。
到此为止,我们的任务创建就完成了,接下来就是验证。我在demo里用的串口是串口一。
在下一章,我们将学习如何使用摇杆按键。