准备工作
在上一篇文章里, 我们已经通过空白工程配置好了系统框架. 这一篇文章我们将在框架的基础上实现Blinky即LED灯闪烁实验 FreeRTOS在Keil里的简单配置, 可以参考这一篇文章: 使用Keil内置工具一键为工程安装FreeRTOS
注意事项
- 在本例程中, 没有用到软件定时器, 所以我们在配置工程时, 不要选择Timers选项, 可如图配置:
将FreeRTOSConfig.h中configUSE_TIMERS参数设为0, 避免任务无法正常运行的情况. - 为了正常运行程序, 空白工程需包含串行输出的初始化, 在TM4C单片机中, 特别的, 是UART0.
亮灯原理
系统运行了两个任务, 分别是Task1和Task2, 其中, Task1执行时间为1000个机器周期, 而Task2为100个. Task1中, 始终执行亮灯语句, 即
GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1,GPIO_PIN_1);
printf("task1 working\n");
vTaskDelay(1000);
而Task2为:
GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1,0);
printf("task2 working\n");
vTaskDelay(100);
将Task1的任务优先级设置成高于Task2的任务优先级. 由于Task1执行时间为Task2的10倍, 故在10份时间内, 将会有1份时间执行优先级高的Task1的命令即亮灯, 而其余时间LED灯则会被Task2控制熄灭. 其实如果将两者优先级设置成一样的, 也能够观察到相同时间间隔的亮灯现象, 说明在同优先级下, 先声明的函数具有更高的支配权?(还没研究明白FreeRTOS的任务调度机制)
代码
#include "tiva_sys.h"
#include "freeRTOS.h"
#include "task.h"
int fputc(int ch, FILE *f)
{
UARTCharPut(UART0_BASE, ch);
return (ch);
}
int fgetc(FILE *f)
{
int ch = UARTCharGet(UART0_BASE);
return (ch);
}
#define START_TASK_PRIO 1
#define START_STK_SIZE 128
StackType_t StartTaskStack[START_STK_SIZE];
TaskHandle_t StartTask_Handler;
void start_task(void *pvParameters);
#define TASK1_TASK_PRIO 2
#define TASK1_STK_SIZE 128
StackType_t Task1TaskStack[TASK1_STK_SIZE];
TaskHandle_t Task1Task_Handler;
void task1_task(void *pvParameters);
#define TASK2_TASK_PRIO 3
#define TASK2_STK_SIZE 128
TaskHandle_t Task2Task_Handler;
void task2_task(void *pvParameters);
void ConfigureUART0(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
UARTStdioConfig(0, 115200, 16000000);
printf("Init uart0");
}
int main(void)
{
SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_16MHZ);
Led_init();
ConfigureUART0();
xTaskCreate((TaskFunction_t)start_task,
(const char *)"start_task",
(uint16_t)START_STK_SIZE,
(void *)NULL,
(UBaseType_t)START_TASK_PRIO,
(TaskHandle_t *)StartTaskStack);
vTaskStartScheduler();
}
void start_task(void *pvParameters)
{
taskENTER_CRITICAL();
xTaskCreate((TaskFunction_t)task1_task,
(const char *)"task1_task",
(uint16_t)TASK1_STK_SIZE,
(void *)NULL,
(UBaseType_t)TASK1_TASK_PRIO,
(TaskHandle_t *)&Task1Task_Handler);
xTaskCreate((TaskFunction_t)task2_task,
(const char *)"task2_task",
(uint16_t)TASK2_STK_SIZE,
(void *)NULL,
(UBaseType_t)TASK2_TASK_PRIO,
(TaskHandle_t *)&Task2Task_Handler);
vTaskDelete(StartTask_Handler);
taskEXIT_CRITICAL();
}
void task1_task(void *pvParameters)
{
while (1)
{
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0);
printf("task1 working\n");
vTaskDelay(100);
}
}
void task2_task(void *pvParameters)
{
while (1)
{
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1);
printf("task2 working\n");
vTaskDelay(1000);
}
}
工程文件在此 FreeRTOS_Blinky
|