一、简介
开发环境:vscode + platformio + cmsis
验证平台:野火指南者(STM32F103VE)
FreeRTOS操作系统很多博主都介绍过了,我就不过多的介绍,总结一句话就是免费、资料多、移植简单、能够快速开发。
二、移植
2.1 打开vscode + platformio新建工程
图2.1 新建工程
图2.2 创建一个标准库工程
图2.3 工程创建完成
2.2 移植野火固件库点亮LED灯例程
图2.4 需要移植的文件
图2.5 把文件复制到工程src目录下
图2.6 删除不需要的文件
图2.7 修改core_cm3.c里面的内容(736、753行)
图2.8 在platformio.ini添加配置
图2.9 编译成功
2.3移植FreeRTOS
图2.10找到FreeRTOS源码
图2.11 需要用到的源码文件
图2.12 在src目录下创建FreeRTOS目录
图2.13 在FreeRTOS目录下创建include、source、portable目录,存放对应的文件
图2.14 删除portable目录里面不需要的文件
图2.15 需要把FreeRTOSConfig.h、stm32f10x_it.c文件复制到工程User目录下(路径:D:\MCU\指南者霸天虎\A盘(资料盘)\1-程序源码_教程文档\3-[野火]《FreeRTOS内核实现与应用开发实战指南》\1-书籍配套程序\3-增值程序:FreeRTOS+基础外设\F103_指南者开发板\01-FreeRTOS-LED\User)
图2.16 把文件复制到User目录会出现3个错误提示
图2.17 由于FreeRTOSConfig.h文件使用了串口,我们需要把串口移植过来(也可以直接屏蔽掉)
图2.18 串口配置文件
图2.19 把串口配置文件复制到User目录下,在platformio.ini文件添加路径,此时配置已经完成
图2.20 编译成功
platformio.ini配置文件
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:genericSTM32F103VE]
platform = ststm32
board = genericSTM32F103VE
framework = cmsis
upload_protocol = cmsis-dap ;烧录工具
debug_tool = cmsis-dap ;调试工具
build_flags =
-Wl,-u,_printf_float ;支持输出小数
-Wl,-Map,output.map ;输出map
-O0 ;编译优先级(0,1,2,3)
-Isrc/Libraries
-Isrc/Libraries/CMSIS
-Isrc/Libraries/FWlib/inc
-Isrc/User
-Isrc/User/led
-Isrc/User/usart
-Isrc/FreeRTOS/include
-Isrc/FreeRTOS/source
-Isrc/FreeRTOS/portable/GCC/ARM_CM3
-Isrc/FreeRTOS/portable/MemMang
-D STM32F10X_HD
-D USE_STDPERIPH_DRIVER
main函数中创建两个线程,方便看实验现象
#include "stm32f10x.h"
#include "FreeRTOS.h"
#include "task.h"
#include "bsp_led.h"
#include "bsp_usart.h"
static TaskHandle_t StartTaskHandle = NULL;
static TaskHandle_t LedTaskHandle = NULL;
static TaskHandle_t UartTaskHandle = NULL;
#define START_TASK_SIZE 255
#define START_TASK_PRIO 8
static void StartTask(void *arg);
#define LED_TASK_SIZE 255
#define LED_TASK_PRIO 7
static void LedTask(void *arg);
#define UART_TASK_SIZE 255
#define UART_TASK_PRIO 6
static void UartTask(void *arg);
int main(void)
{
LED_GPIO_Config();
USART_Config();
xTaskCreate((TaskFunction_t) StartTask,
(const char* ) "Start Task",
(uint16_t ) START_TASK_SIZE,
(void* ) NULL,
(UBaseType_t ) START_TASK_PRIO,
(TaskHandle_t* ) StartTaskHandle);
vTaskStartScheduler();
}
static void StartTask(void *arg)
{
taskENTER_CRITICAL();
xTaskCreate((TaskFunction_t) LedTask,
(const char* ) "Led Task",
(uint16_t ) LED_TASK_SIZE,
(void* ) NULL,
(UBaseType_t ) LED_TASK_PRIO,
(TaskHandle_t* ) LedTaskHandle);
xTaskCreate((TaskFunction_t) UartTask,
(const char* ) "Uart Task",
(uint16_t ) UART_TASK_SIZE,
(void* ) NULL,
(UBaseType_t ) UART_TASK_PRIO,
(TaskHandle_t* ) UartTaskHandle);
vTaskDelete(StartTaskHandle);
taskEXIT_CRITICAL();
}
static void LedTask(void *arg)
{
while(1)
{
LED2_TOGGLE;
printf("Led Task\r\n");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
static void UartTask(void *arg)
{
while(1)
{
printf("Uart Task\r\n");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
三、验证
烧录验证,LED一秒闪烁一次,串口一秒打印一次(串口配置文件需要修改,printf才能使用,可以参考我前面的文章)