开发环境
- Win10 64位 + VS Code,ssh 远程连接 ubuntu
- VMware Workstation Pro 16 + Ubuntu 20.04
- FreeRTOSv202212.01(备注:可以在 github 获取最新版本)
- qemu qemu-system-arm mps2-an385 开发板,qemu 版本 QEMU emulator version 4.2.1 或更高
- arm gcc 交叉编译工具链:当前使用 gcc 编译环境, gcc-arm-11.2-2022.02-x86_64-arm-none-eabi, gcc version 11.2.1 20220111
前言
- 前面的 FreeRTOS qemu mps2-an385 bsp 移植制作 :环境搭建篇 大体讲了一下环境搭建,初步配置了工程目录
- FreeRTOS qemu mps2-an385 bsp 移植制作 :系统启动篇 配置了 VS Code gdb 调试环境,初步让MCU 启动,进入了启动入口函数
- 本篇继续优化,创建 FreeRTOS task ,让系统启动起来
中断向量表
- 为了实现系统 systick 定时器与 任务调度,FreeRTOS 实现了 systick、pendSV 等功能,需要关联启动文件
- 在
qemu_mps2/application/FreeRTOSConfig.h
中,追加
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
- 【备注】这个
FreeRTOSConfig.h
可以从FreeRTOS 的 相关 demo 中复制出来并修改,当前复制于FreeRTOSv202212.01\FreeRTOS\Demo\CORTEX_MPS2_QEMU_IAR_GCC\FreeRTOSConfig.h
- 这样就对接了系统的 systick 定时器与任务调度中断处理:
PendSV_Handler
让启动直接进入 main 函数
- 默认第一个执行函数是:
qemu_mps2/CMSDK_CM3/Source/GCC/startup_CMSDK_CM3.S
中的Reset_Handler
,当前调试发现bl _start
时会卡住,所以这里直接改为bl main
,也就是跳转到 main 函数
- main.c 的代码如下:
#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>
#include <string.h>
#define TASK_TEST_PRIORITY (tskIDLE_PRIORITY + 6)
static void task_test_entry(void *pvParameters)
{
while (1)
{
vTaskDelay(1000);
}
}
void main( void )
{
xTaskCreate(task_test_entry, "task_test", configMINIMAL_STACK_SIZE, NULL, TASK_TEST_PRIORITY, NULL);
vTaskStartScheduler();
for( ;; );
}
- 这里暂时没有开启串口打印,后续补上,创建一个 task,taks 里面什么都不干,就是 1秒延时
ilde 与 timer 任务栈
- 编译并运行后,发现出现了断言,提示 idle task 的 栈指针为空,经过分析发现,需要完善 idle 线程栈的获取函数,当前 timer task 的栈也需要完善,比如使用静态数组作为 task 的线程栈
- hook 等函数在
qemu_mps2/application/port.c
中实现,完善
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{
static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )
{
static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
- 再次编译后调试运行,发现 FreeRTOS 正常进入 task 任务函数,并且周期性的工作(1秒的延时)
- 以上说明 FreeRTOS 系统运行起来了,初步移植成功
小结
- 后续继续实现系统串口的打印功能,让系统运行可以看的到
- 后续继续完善 FreeRTOS 的 例程,比如实现多任务间的通信等功能