下载FreeRTOS

首先下载FreeRTOS的网址:FreeRTOS网址
官网界面
打开网址后,选择下载弹出窗口,再次点击 查看更多下载选项和后续步骤
特定版本
点击就会跳转新的页面 在下载FreeRTOS一栏中 找到 后续步骤内容中的之前版本
在这里插入图片描述
选择要下载的版本 FreeRTOSv202212.01.zip(这是2022年12月发布的稳定版本)
在这里插入图片描述
在这里插入图片描述

裁切文件

将下载的压缩包解压,复制7个C文件,文件在路径 FreeRTOSv202212.01\FreeRTOS\Source

在这里插入图片描述自己创建一个空白的文件夹用来放这7个C文件,例如我的 Middlewares\FreeRTOS\Source,这个Middlewares以后就可以直接复制移植到工程中。
在这里插入图片描述
在当前文件夹创建一个 portable 文件夹
在这里插入图片描述
这个文件夹里面分别再创建两个文件夹
在这里插入图片描述
首先第一个 MemMang ,将官方的文件夹中MemMang里面 heap_4.c文件复制到我们创建的文件夹中
在这里插入图片描述
转移到自己创建的
在这里插入图片描述
下面是 RVDS 文件夹,直接复制官方的RVDS里面的ARM_CM3这个选择跟芯片有关系
在这里插入图片描述
下图是自己创建的

下面移植include文件夹,将官方的include文件夹直接复制到自己的Source文件夹中
在这里插入图片描述
在这里插入图片描述
最后一个文件路径如下
在这里插入图片描述
我先暂时放到FreeRTOS路径下面,等创建好工程再转移到专门放头文件的路径下
在这里插入图片描述

创建HAL工程

这里使用cubemx创建工程

配置时钟

在这里插入图片描述

配置时钟树

在这里插入图片描述

配置时基源

在这里插入图片描述

配置NVIC

将时基源优先级设为1(数字越小优先级越高)
在这里插入图片描述

配置代码生成 code generstion

这样就不会每次更改cubemx都要进行注释这个两个中断函数了
在这里插入图片描述

移植测试引脚

在这里插入图片描述

生成Keil工程项目

当前工程还没将FreeRTOS复制过去
在这里插入图片描述

移植FreeRTOS到Keil 并配置

直接将 Middlewares 文件夹移动到 FreeRTOS_basic 工程路径下
在这里插入图片描述
再将 Middlewares 文件夹中的 FreeRTOSConfig.h 文件移动到 Inc 文件夹中,移动完成后开始配置Keil
在这里插入图片描述

配置Keil

添加文件分类
在这里插入图片描述
添加 FreeRTOSConfig.h 文件 有利于修改配置
在这里插入图片描述

配置include paths

添加这两个路径
在这里插入图片描述

FreeRTOSConfig.h 文件添加宏定义

/* FreeRTOS中断服务函数相关定义 */
#define xPortPendSVHandler                              PendSV_Handler
#define vPortSVCHandler                                 SVC_Handler

/* 可选函数, 1: 使能 */
#define INCLUDE_xTaskGetSchedulerState                  1                       /* 获取任务调度器状态 */

在这里插入图片描述

stm32f1xx_it.c 文件配置

添加头文件

#include "FreeRTOS.h"
#include "task.h"

配置中断服务函数

void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */

  /* USER CODE BEGIN SysTick_IRQn 1 */
  if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
  {
    xPortSysTickHandler();
  }
  /* USER CODE END SysTick_IRQn 1 */
}

引用函数extern void xPortSysTickHandler( void );
在这里插入图片描述

创建一个动态任务测试

将LED0每1000ms闪烁一次

#include "freertos_task.h"
#include "FreeRTOS.h"
#include "task.h"

#include "main.h"

#define START_TASK_PRIO 1            /* 任务优先级 */
#define START_STK_SIZE 128           /* 任务堆栈大小 */
TaskHandle_t StartTask_Handler;      /* 任务句柄 */
void start_task(void *pvParameters); /* 任务函数 */

#define TASK1_PRIO 2            /* 任务优先级 */
#define TASK1_STK_SIZE 128      /* 任务堆栈大小 */
TaskHandle_t Task1Task_Handler; /* 任务句柄 */
void task1(void *pvParameters); /* 任务函数 */

void freertos_init(void)
{
    xTaskCreate((TaskFunction_t)start_task,          /* 任务函数 */
                (const char *)"start_task",          /* 任务名称 */
                (uint16_t)START_STK_SIZE,            /* 任务堆栈大小 */
                (void *)NULL,                        /* 传入给任务函数的参数 */
                (UBaseType_t)START_TASK_PRIO,        /* 任务优先级 */
                (TaskHandle_t *)&StartTask_Handler); /* 任务句柄 */
    vTaskStartScheduler();
}

void start_task(void *pvParameters)
{
    taskENTER_CRITICAL(); /* 进入临界区 */
    /* 创建任务1 */
    xTaskCreate((TaskFunction_t)task1,               /* 任务函数 */
                (const char *)"task1",               /* 任务名称 */
                (uint16_t)TASK1_STK_SIZE,            /* 任务堆栈大小 */
                (void *)NULL,                        /* 传入给任务函数的参数 */
                (UBaseType_t)TASK1_PRIO,             /* 任务优先级 */
                (TaskHandle_t *)&Task1Task_Handler); /* 任务句柄 */
    vTaskDelete(StartTask_Handler);                  /* 删除开始任务 */
    taskEXIT_CRITICAL();                             /* 退出临界区 */
}

void task1(void *pvParameters)
{
    while (1)
    {
        HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
        vTaskDelay(1000);
    }
}

在 main 函数中初始化 freertos_init 任务即可创建成功 并执行task1任务 每1s翻转一次电平,此次移植完成

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐