2.1 FreeRTOS移植
2.1.1 移植准备
准备一个用以移植的基础工程和FreeRTOS源码。
1.基础工程,正点原子开发文档中以标准例程-HAL库的内存管理的基础工程进行移植。所以我们直接去找基础工程。
首先去往网盘,资料查找在第一章已经说明。
下载好后如图所示
2 FreeROTS源码,昨天已经下载好了 如图所示
在做好移植准备后 就可以开始我们的移植过程了。
2.1.2 开始移植
![](https://i-blog.csdnimg.cn/blog_migrate/17246784630d453837e762f27104e758.png)
②要将 FreeRTOS 的源代码添加到刚刚新建的 FreeRTOS 子文件中
全选复制 去刚刚新建的FreeRTOS下复制
③打开基础工程,新建两个文件分组,分别为 Middlewares/FreeRTOS_CORE 和
![](https://i-blog.csdnimg.cn/blog_migrate/3adb8a43657dfa36c5cbcfa58f53f4de.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6873d865a81b5d45bb03c56d7a7f48ba.png)
![](https://i-blog.csdnimg.cn/blog_migrate/7ede5985ebff51ac771cc1cd54728eb2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6340f2e305bb7ab790ecf87921119d48.png)
![](https://i-blog.csdnimg.cn/blog_migrate/993305064fcbbe38f8584d713ef7df76.png)
![](https://i-blog.csdnimg.cn/blog_migrate/154d1f27d5f60ac9c84b9b0097c60754.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6351ab06178b89bfad9388c8579b0d30.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c3e6a28f4417e26eeaa0b733d11edb34.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3ac5040d1274c926c87cff08b7aada5b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/5cb1b67c3213fc1f118d71640d98319c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/81b3b078fc45cae06af5b88f377b13bc.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b320a9842c58bf0fe0d49867ece831a2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a8de46f7905ecaff9698ee865b10aa4c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a16ba36a2e8fd19698396b42a697d76b.png)
2.1.3 修改SYSTEM文件
![](https://i-blog.csdnimg.cn/blog_migrate/92a59c52936ce67abf3d0b48f2ec7a9e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2c48abbd7024c3e66c7afcd4d9a5a5d4.png)
![](https://i-blog.csdnimg.cn/blog_migrate/df820d07827d0c27130fd8eee4e126c9.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6c8c648ecd4ec415b635cd90d610a6e4.png)
![](https://i-blog.csdnimg.cn/blog_migrate/01b0060e7f7097e7c9a8f6392b4ba2d5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a4ebc660c2a36e3faef6c3c89bb1e237.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9799a76a78c596ef3e306309a9d47632.png)
{ HAL_IncTick();
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) /* OS开始跑了,才执行正常的调度处理 */
{
xPortSysTickHandler();
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/c099173fac1684ee43b8fbeca3734e2b.png)
void delay_init(uint16_t sysclk)
{
#if SYS_SUPPORT_OS /* 如果需要支持OS. */
uint32_t reload;
#endif
SysTick->CTRL = 0; /* 清Systick状态,以便下一步重设,如果这里开了中断会关闭其中断 */
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8); /* SYSTICK使用内核时钟源8分频,因systick的计数器最大值只有2^24 */
g_fac_us = sysclk / 8; /* 不论是否使用OS,g_fac_us都需要使用,作为1us的基础时基 */
#if SYS_SUPPORT_OS /* 如果需要支持OS. */
reload = sysclk / 8; /* 每秒钟的计数次数 单位为M */
reload *= 1000000 / configTICK_RATE_HZ; /* 根据delay_ostickspersec设定溢出时间
* reload为24位寄存器,最大值:16777216,在9M下,约合1.86s左右
*/
SysTick->CTRL |= 1 << 1; /* 开启SYSTICK中断 */
SysTick->LOAD = reload; /* 每1/delay_ostickspersec秒中断一次 */
SysTick->CTRL |= 1 << 0; /* 开启SYSTICK */
#endif
}
借鉴的是能跑的示例工程 按照文档上的会报错如图
修改后如图
{
uint32_t ticks;
uint32_t told, tnow, tcnt = 0;
uint32_t reload = SysTick->LOAD;
/* 删除适用于 μC/OS 用于锁定任务调度器的自定义函数 */
ticks = nus * g_fac_us;
told = SysTick->VAL;
while (1)
{
tnow = SysTick->VAL;
if (tnow != told)
{
if (tnow < told)
{
tcnt += told - tnow;
}
else
{
tcnt += reload - tnow + told;
}
told = tnow;
if (tcnt >= ticks)
{
break;
}
}
}
}
和示例文件略有出入 在此标记一下。
{
uint32_t i;
for (i=0; i<nms; i++)
{
delay_us(1000);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/2ed13dd9e414d508368ce29272376f11.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c3a3de047b46a4d73df8157ef959de01.png)
![](https://i-blog.csdnimg.cn/blog_migrate/80f08c797b915ce984c86a8d3c1f62da.png)
2.1.4 修改中断相关文件
正点原子教程如图所示
![](https://i-blog.csdnimg.cn/blog_migrate/700d313e7d0dd1c7006ab735d3406df7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2d682689d0821929f8c93ba1e5160920.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c68e4806a4991eec147594ed059d07fd.png)
![](https://i-blog.csdnimg.cn/blog_migrate/db84bb2bbb6fb3132074d50618ae2f6c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/4eff2f6d16518a314f7ead905c258029.png)
![](https://i-blog.csdnimg.cn/blog_migrate/901752eb054a6fce358364b377518f4a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/dd776913ec6229b855de95405a49ef51.png)
![](https://i-blog.csdnimg.cn/blog_migrate/78007ba43efbb3a0644d90febed3a934.png)
![](https://i-blog.csdnimg.cn/blog_migrate/dada64c2ab2730b6e436563709886126.png)
2.1.5 可选修改流程
①修改工程名。
②移除USMART组件
③添加定时器驱动
但是去到移植好的BSP库中发现还有SRAM文件所以直接复制两个到我们的移植文件夹下
到这我们就完成了环境的修改 接下来我们通过添加应用程序来测试是否移植成功。
2.1.6 添加应用程序
一修改,二添加。
①首先修改mian.c文件
![](https://i-blog.csdnimg.cn/blog_migrate/183d9f94b9f37821c0b6d2c0c0abab41.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2f6380a23d2ae0f32789c213a4401d36.png)
******************************************************************************
* @file main.c
* @author 正点原子团队(ALIENTEK)
* @version V1.4
* @date 2022-01-04
* @brief FreeRTOS 移植实验
* @license Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
******************************************************************************
* @attention
*
* 实验平台:正点原子 战舰 F103 开发板
* 在线视频:www.yuanzige.com
* 技术论坛:www.openedv.com
* 公司网址:www.alientek.com
* 购买地址:openedv.taobao.com
*
******************************************************************************
*/
#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
/*FreeRTOS********************************************************************/
#include "FreeRTOS.h"
#include "task.h"
/*****************************************************************************/
/*FreeRTOS 配置*/
/* START_TASK 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define START_TASK_PRIO 1 /* 任务优先级 */
#define START_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t StartTask_Handler; /* 任务句柄 */
void start_task(void *pvParameters); /* 任务函数 *//* TASK1 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK1_PRIO 2 /* 任务优先级 */
#define TASK1_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task1Task_Handler; /* 任务句柄 */
void task1(void *pvParameters); /* 任务函数 */
/* TASK2 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK2_PRIO 3 /* 任务优先级 */
#define TASK2_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task2Task_Handler; /* 任务句柄 */
void task2(void *pvParameters); /* 任务函数 */
/*****************************************************************************/
/* LCD 刷屏时使用的颜色 */
uint16_t lcd_discolor[11] = { WHITE, BLACK, BLUE, RED,
MAGENTA, GREEN, CYAN, YELLOW,
BROWN, BRRED, GRAY};
/**
* @brief FreeRTOS 例程入口函数
* @param 无
* @retval 无
*/
void freertos_demo(void)
{
lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
lcd_show_string(10, 47, 220, 24, 24, "FreeRTOS Porting", RED);
lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);
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();
}/**
* @brief start_task
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
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);
/* 创建任务 2 */
xTaskCreate((TaskFunction_t )task2,
(const char* )"task2",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
/**
* @brief task1
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task1(void *pvParameters)
{
uint32_t task1_num = 0;
while(1)
{
lcd_clear(lcd_discolor[++task1_num % 14]); /* 刷新屏幕 */
lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
lcd_show_string(10, 47, 220, 24, 24, "FreeRTOS Porting", RED);
lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);
LED0_TOGGLE(); /* LED0 闪烁 */
vTaskDelay(1000); /* 延时 1000ticks */}
}
/**
* @brief task2
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task2(void *pvParameters)
{
float float_num = 0.0;
while(1)
{
float_num += 0.01f; /* 更新数值 */
printf("float_num: %0.4f\r\n", float_num); /* 打印数值 */
vTaskDelay(1000); /* 延时 1000ticks */
}
![](https://i-blog.csdnimg.cn/blog_migrate/be2fac1bbf413d19404126872a5d8369.png)
#define __FREERTOS_DEMO_H
void freertos_demo(void);
#endif
2.2 FreeRTOS移植实验
其实正点原子就是对我们之前的行为载入开发板的代码和原理做一个解释,有兴趣的可以去查看官方文档的讲解或者我的后续补充。
就可以编译代码了
2.3bug解决
我出现了两个问题
1第一个问题是无法打开freertos_demo.h文件 是因为没有将头文件路径配置
2第二个问题是必须将FreeRTOS.h放在task.h路径前
![](https://i-blog.csdnimg.cn/blog_migrate/d8c25ceac06ef3d8c054b0700bb81fbd.png)
![](https://i-blog.csdnimg.cn/blog_migrate/062eae873bf0ed8d9d5c8ace7a4a0a44.png)