基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)

news/2024/5/19 8:33:06/文章来源:https://blog.csdn.net/m0_64053511/article/details/130869760

1. 资料准备

因为板子是stm32F407的第二版的,所以开始下的资料是旧版本的,但是旧版本的FreeRTOS工程没有hal库的,都是标准库的,这里是下载stm32F407最新版的资料,进行移植。

资料可以在正点原子官网下载,如下:
http://www.openedv.com/docs/boards/stm32/index.html
在这里插入图片描述
一定要下载最新的资料(开始用旧版本的移植不成功)。

准备stm32F407 hal库的 实验8 基本定时器实验和 实验37 内存管理实验两个工程,以及FreeRTOS的源码,以内存管理实验为模版,进行移植。

2. 实验流程

  1. 添加 FreeRTOS 源码
  2. 添加FreeRTOSConfig.h配置文件
  3. 修改SYSTEM文件
  4. 修改中断相关文件
  5. 添加应用程序
    在这里插入图片描述

2.1 添加 FreeRTOS 源码

在Middlewares文件夹中新建一个FreeRTOS文件夹,把FreeRTOS源码中的source中文件都拷贝到新建的FreeRTOS文件夹中,删去其余不是.c的文件。

在这里插入图片描述
portable文件夹里面的东西是连接软件层面的FreeRTOS 操作系统和硬件层面的芯片的桥梁,这里只保留portable文件夹中的RVDS、MemMang、Keil三个文件夹(因为stm32F4只用到这三个文件夹)。
在这里插入图片描述

2.2 将文件添加到工程

在工程中新建两个分组,Middlewares/FreeRTOS_CORE 和 Middlewares/FreeRTOS_PORT。

在这里插入图片描述
将.c文件添加到Middlewares/FreeRTOS_CORE 分组中。
在这里插入图片描述
将MemMang文件夹下的heap_4.c添加到Middlewares/FreeRTOS_PORT分组中。
在这里插入图片描述
将RVDS文件夹下的ARM_CM4F下的port.c添加到Middlewares/FreeRTOS_PORT分组中。
在这里插入图片描述

2.3 添加头文件路径

添加头文件路径FreeRTOS/include和port.c的文件路径。
在这里插入图片描述

2.4 添加 FreeRTOSConfig.h文件

在FreeRTOS的例程中找到该文件FreeRTOSConfig.h,放到移植工程即可,这里放到user文件夹中。
在这里插入图片描述
在这里插入图片描述

2.5 修改SYSTEM文件

  1. 修改sys.h文件
/**1. SYS_SUPPORT_OS用于定义系统文件夹是否支持OS2. 0,不支持OS3. 1,支持OS*/
//#define SYS_SUPPORT_OS       0
#define SYS_SUPPORT_OS         1
  1. 修改usart.c 文件,删掉OSIntEnter()和 OSIntExit()两个函数
void USART_UX_IRQHandler(void)
{ uint32_t timeout = 0;uint32_t maxDelay = 0x1FFFF;
//#if SYS_SUPPORT_OS                              /* 使用OS */
//    OSIntEnter();    
//#endifHAL_UART_IRQHandler(&g_uart1_handle);       /* 调用HAL库中断处理公用函数 */timeout = 0;while (HAL_UART_GetState(&g_uart1_handle) != HAL_UART_STATE_READY) /* 等待就绪 */{timeout++;                              /* 超时处理 */if(timeout > maxDelay){break;}}timeout=0;/* 一次处理完成之后,重新开启中断并设置RxXferCount为1 */while (HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE) != HAL_OK){timeout++;                              /* 超时处理 */if (timeout > maxDelay){break;}}
//#if SYS_SUPPORT_OS                              /* 使用OS */
//    OSIntExit();
//#endif
}
  1. 将 usart.c中包含的关于 OS 的头文件删除
///* 如果使用os,则包括下面的头文件即可 */
//#if SYS_SUPPORT_OS
//#include "includes.h"                               /* os 使用 */
//#endif
  1. 修改delay.c 文件,删除如下代码
//static uint16_t g_fac_ms = 0;
///*
// *  当delay_us/delay_ms需要支持OS的时候需要三个与OS相关的宏定义和函数来支持
// *  首先是3个宏定义:
// *      delay_osrunning    :用于表示OS当前是否正在运行,以决定是否可以使用相关函数
// *      delay_ostickspersec:用于表示OS设定的时钟节拍,delay_init将根据这个参数来初始化systick
// *      delay_osintnesting :用于表示OS中断嵌套级别,因为中断里面不可以调度,delay_ms使用该参数来决定如何运行
// *  然后是3个函数:
// *      delay_osschedlock  :用于锁定OS任务调度,禁止调度
// *      delay_osschedunlock:用于解锁OS任务调度,重新开启调度
// *      delay_ostimedly    :用于OS延时,可以引起任务调度.
// *
// *  本例程仅作UCOSII和UCOSIII的支持,其他OS,请自行参考移植
// */
// 
///* 支持UCOSII */
//#ifdef  OS_CRITICAL_METHOD                      /* OS_CRITICAL_METHOD定义了,说明要支持UCOSII */
//#define delay_osrunning     OSRunning           /* OS是否运行标记,0,不运行;1,在运行 */
//#define delay_ostickspersec OS_TICKS_PER_SEC    /* OS时钟节拍,即每秒调度次数 */
//#define delay_osintnesting  OSIntNesting        /* 中断嵌套级别,即中断嵌套次数 */
//#endif///* 支持UCOSIII */
//#ifdef  CPU_CFG_CRITICAL_METHOD                 /* CPU_CFG_CRITICAL_METHOD定义了,说明要支持UCOSIII */
//#define delay_osrunning     OSRunning           /* OS是否运行标记,0,不运行;1,在运行 */
//#define delay_ostickspersec OSCfg_TickRate_Hz   /* OS时钟节拍,即每秒调度次数 */
//#define delay_osintnesting  OSIntNestingCtr     /* 中断嵌套级别,即中断嵌套次数 */
//#endif///**
// * @brief     us级延时时,关闭任务调度(防止打断us级延迟)
// * @param     无  
// * @retval    无
// */  
//void delay_osschedlock(void)
//{
//#ifdef CPU_CFG_CRITICAL_METHOD          /* 使用UCOSIII */
//    OS_ERR err;
//    OSSchedLock(&err);                  /* UCOSIII的方式,禁止调度,防止打断us延时 */
//#else                                   /* 否则UCOSII */
//    OSSchedLock();                      /* UCOSII的方式,禁止调度,防止打断us延时 */
//#endif
//}///**
// * @brief     us级延时时,恢复任务调度
// * @param     无
// * @retval    无
// */  
//void delay_osschedunlock(void)
//{
//#ifdef CPU_CFG_CRITICAL_METHOD          /* 使用UCOSIII */
//    OS_ERR err;
//    OSSchedUnlock(&err);                /* UCOSIII的方式,恢复调度 */
//#else                                   /* 否则UCOSII */
//    OSSchedUnlock();                    /* UCOSII的方式,恢复调度 */
//#endif
//}///**
// * @brief     us级延时时,恢复任务调度
// * @param     ticks : 延时的节拍数
// * @retval    无
// */  
//void delay_ostimedly(uint32_t ticks)
//{
//#ifdef CPU_CFG_CRITICAL_METHOD
//    OS_ERR err; 
//    OSTimeDly(ticks, OS_OPT_TIME_PERIODIC, &err);   /* UCOSIII延时采用周期模式 */
//#else
//    OSTimeDly(ticks);                               /* UCOSII延时 */
//#endif 
//}
  1. 添加 FreeRTOS 的相关代码(在delay.c文件中)
extern void xPortSysTickHandler(void);
  1. 修改SysTick_Handler()函数
void SysTick_Handler(void)
{HAL_IncTick();
//    if (delay_osrunning == 1)       /* OS开始跑了,才执行正常的调度处理 */
//    {
//        OSIntEnter();               /* 进入中断 */
//        OSTimeTick();               /* 调用ucos的时钟服务程序 */
//        OSIntExit();                /* 触发任务切换软中断 */
//    }/* OS 开始跑了,才执行正常的调度处理 */if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED){xPortSysTickHandler();}
}
  1. 修改delay_init()函数
void delay_init(uint16_t sysclk)
{
reload *= 1000000 / configTICK_RATE_HZ;
//    g_fac_ms = 1000 / delay_ostickspersec; 
}/* 删除不用的 g_fac_ms 相关代码 */
  1. 修改delay_us()函数
void delay_us(uint32_t nus)
{// delay_osschedlock();                    /* 阻止OS调度,防止打断us延时 */// delay_osschedunlock();                  /* 恢复OS调度 */
}
  1. 修改delay_ms()函数
void delay_ms(uint16_t nms)
{
//    if (delay_osrunning && delay_osintnesting == 0)     /* 如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度) */
//    {
//        if (nms >= g_fac_ms)                            /* 延时的时间大于OS的最少时间周期 */
//        { 
//            delay_ostimedly(nms / g_fac_ms);            /* OS延时 */
//        }
//        nms %= g_fac_ms;                                /* OS已经无法提供这么小的延时了,采用普通方式延时 */
//    }                                        
//    delay_us((uint32_t)(nms * 1000));                   /* 普通方式延时 */uint32_t i;for (i=0; i<nms; i++){delay_us(1000);}
}
  1. 包含头文件
/* 添加公共头文件 ( ucos需要用到) */
//#include "includes.h"
#include "FreeRTOS.h"
#include "task.h"
  1. 修改中断相关文件,修改stm32f4xx_it.c文件
//void SVC_Handler(void)
//{
//}//void PendSV_Handler(void)
//{
//}//void SysTick_Handler(void)
//{
//  HAL_IncTick();
//}
  1. 修改FreeRTOSConfig.h文件。
#define configPRIO_BITS __NVIC_PRIO_BITS
//#define __NVIC_PRIO_BITS            4U     
#define __NVIC_PRIO_BITS              4 

2.6 移除USMART调试组件

因为没有使用到 USMART 调试组件,所以把这个组件删掉。
在这里插入图片描述

注释掉main.c中的有关USMART代码。

//#include "./USMART/usmart.h"
//int main(void){
//    usmart_dev.init(84);                /* 初始化USMART */
}

2.7 添加定时器驱动

把基本定时器工程中的TIMER文件夹,复制到移植工程中的BSP文件夹中。
在这里插入图片描述
在这里插入图片描述
将定时器的相关驱动文件添加到工程的 Drivers/BSP 文件分组中。
在这里插入图片描述

3. 实验验证

把FreeRTOS例程中的demo复制到移植工程中User中。
在这里插入图片描述
在这里插入图片描述

将demo的驱动文件添加到工程的User文件分组中。

在这里插入图片描述

删减之后的部分代码如下:

int main(void)
{HAL_Init(); /* 初始化 HAL 库 */sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */delay_init(72); /* 延时初始化 */usart_init(115200); /* 串口初始化为 115200 */led_init(); /* 初始化 LED */lcd_init(); /* 初始化 LCD */key_init(); /* 初始化按键 */sram_init(); /* SRAM 初始化 */my_mem_init(SRAMIN); /* 初始化内部 SRAM 内存池 */my_mem_init(SRAMEX); /* 初始化外部 SRAM 内存池 */freertos_demo(); /* 运行 FreeRTOS 例程 */
}
void freertos_demo(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 task1(void *pvParameters)
{while(1){LED0_TOGGLE();                                                  /* LED0闪烁 */vTaskDelay(1000);                                               /* 延时1000ticks */}
}
void task2(void *pvParameters)
{while(1){LED1_TOGGLE();                                         /* LED1闪烁 */vTaskDelay(500);                                      /* 延时500ticks */}
}

把程序烧到开发板中,实验结果如下,可以看到与预设程序一致,红色LED,1000ms亮灭一次,蓝色LED,500ms亮灭一次(可以在如下视频看到)。

FreeRTOS移植

4. 总结

  1. 遇到如下报大量语法错误,原因是keil编译器问题,把编译器的版本设置为V5即可。
    在这里插入图片描述
    在这里插入图片描述
  2. 最后把程序烧到开发板中,如果LED灯没有亮,复位几次,观察LED是否亮。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_306630.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是可视化开发平台?拥有什么优势?

随着科技的进步和发展&#xff0c;可视化开发平台拥有广阔的市场前景&#xff0c;在提升企业办公企业效率、做好数据管理等方面具有自身的特色和优势。在办公自动化发展的年代&#xff0c;低代码开发平台是助力企业实现提质增效办公效率的得力助手&#xff0c;其可视化、易操作…

淘宝层级改版,五力模型上线!

最近临近618&#xff0c;淘系又各种功能改版&#xff0c;现在店铺层级也开始陆续改版了。从原来的只需要提升销售金额&#xff0c;到现在的五力模型。我们先说一下原来的店铺层级考核&#xff0c;跟现在的区别主要是哪&#xff1f; 1.原来店铺层级的考核升级特别简单&#xff0…

论文解读 | IROS 2022:MV6D:在RGB-D图像上使用深度逐点投票网络进行多视角6D姿态估计

原创 | 文 BFT机器人 01 研究背景 在计算机视觉领域&#xff0c;6D姿态估计是一种重要的任务&#xff0c;用于确定物体在3D空间中的位置和方向。它在许多应用领域具有广泛的应用&#xff0c;如机器人操作、虚拟现实、增强现实、物体跟踪等。 然而&#xff0c;传统的6D姿态估计方…

Windows Copilot,来了!

公众号关注 “GitHubDaily” 设为 “星标”&#xff0c;每天带你逛 GitHub&#xff01; 5 月 23 日&#xff0c;微软 2023 Build 开发者大会正式开幕&#xff0c;跟 Google I/O 和 Apple WWDC 一样&#xff0c;每年微软都会在 Build 大会上发布各种新产品。 由于最近几个月 Cha…

webpack简单的搭建和使用

随便创建一个空的文件夹&#xff0c;例如说&#xff1a;explore 然后我们测试一下我们的node是否存在 可以正确打印出版本 我们再次输入&#xff1a;npm init -y 创建一个package.json文件 出现这样的情况就成功了 然后我们要安装webpack在终端上输入命令&#xff1a; npm i …

智能排班系统 【管理系统功能、操作说明——下篇】

文章目录 页面与功能展示排班日历月视图&#xff08;按职位查询&#xff09;月视图&#xff08;按员工查询&#xff09;周视图 排班任务管理创建排班计算任务设置任务的排班规则设置工作日客流量导入任务计算查看任务结果发布任务任务多算法计算 页面与功能展示 排班日历 在排…

LiveGBS流媒体平台国标GB/T28181功能-作为下级级联到海康大华宇视华为等第三方国标平台同样支持对接政务公安内网国标视频平台

LiveGBS流媒体平台国标GB/T28181功能-作为下级级联到海康大华宇视华为等第三方国标平台同样支持对接政务公安内网国标视频平台 1、什么是GB/T28181级联2、搭建GB28181国标流媒体平台3、获取上级平台接入信息3.1、如何提供信息给上级3.2、上级国标平台如何添加下级域3.2、接入Li…

注意力Transformer

注意力 注意力分为两步&#xff1a; 计算注意力分布 α \alpha α 其实就是&#xff0c;打分函数进行打分&#xff0c;然后softmax进行归一化 根据 α \alpha α来计算输入信息的加权平均&#xff08;软注意力&#xff09; 其选择的信息是所有输入向量在注意力下的分布 打…

如何快速搭建SpringBoot+Vue前后端分离的开发环境

唠嗑部分 今天我们来说一说&#xff0c;如何快速搭建SpringBootVue前后端分离的开发环境 需要前置环境nodejs&#xff0c;请自行安装(傻瓜式安装) SpringBoot采用2.4.2版本&#xff0c;Vue采用Vue2版本 言归正传 创建Vue项目 1、安装vue npm install -g vue/cli2、检查v…

当二叉树遇上递归:如何判断单值二叉树?

本篇博客会讲解力扣“965. 单值二叉树”的解题思路&#xff0c;这是题目链接。 先来审题&#xff1a; 以下是输出示例&#xff1a; 以下是提示&#xff1a; 本题非常适合使用递归实现。分以下情况讨论&#xff1a; 若是空树&#xff0c;则符合单值二叉树的性质。若非空&am…

【亲测有效】idea部署jrebel插件

idea部署jrebel插件 1.背景 最近在维护tomcat项目&#xff0c;工程修改代码后需要rebuild才能更新class文件&#xff0c;进而运行生效。 同事介绍jrebel可以实现热部署&#xff0c;于是接入使用。 2.简介 JRebel是一套JavaEE开发工具。 Jrebel 可快速实现热部署&#xff0c…

软考A计划-2022年05月软件设计师下午真题及答案解析

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

Axure教程—水平方向多色图(中继器)

本文将教大家如何用AXURE制作动态水平方向多色图 一、效果介绍 如图&#xff1a; 预览地址&#xff1a;https://l83ucp.axshare.com 下载地址&#xff1a;https://download.csdn.net/download/weixin_43516258/87822666 二、功能介绍 简单填写中继器内容即可生成动态水平多色…

类和对象 --- 封装+对象特性

&#x1f442; 快乐E调 - 林澜叶 - 单曲 - 网易云音乐 &#x1f442; Plain Jane (Freestyle) - Ombre2Choc Nation - 单曲 - 网易云音乐 1.5倍速&#xff0c;跟着敲&#xff0c;初识C 目录 &#x1f3c6;封装 &#x1f333;属性和行为作为整体 &#x1f333;案例 -- 设置…

操作系统层面下——进程状态讲解

目录 一.进程的状态&#xff1a;运行态 1.什么是运行状态&#xff1f; 2.进程进入内存的详细图解&#xff1a; 总结&#xff1a; 二.进程的状态&#xff1a;阻塞态 1.什么是阻塞状态&#xff1f; 三.进程的状态&#xff1a;挂起态 1.什么是挂起态&#xff1f; 2.阻塞与挂起的…

网络安全是一个好专业吗?

前言 网络安全作为一个专业领域&#xff0c;在当今数字时代正变得越发重要和关键。无论是企业还是个人&#xff0c;面对着越来越频繁的网络威胁和攻击&#xff0c;网络安全领域的专业人员扮演着至关重要的角色。那么&#xff0c;从一个资深网安工程师的角度来看&#xff0c;网…

11-FastDFS文件服务器 和 Nginx

1、什么是FastDFS 1、开源的轻量级分布式文件系统,用于解决大数据量存储和负载均衡等问题。 2、优点: 支持HTTP协议传输文件(结合Nginx); 对文件内容做Hash处理,节约磁盘空间; 支持负载均衡、整体性能较佳。 3、FastDFS的二个角色:跟踪服务器(Tracker)、存储服务器…

书评 | 《新程序员005:开源深度指南 新金融背后的科技力量》

目录 书评 | 《新程序员005&#xff1a;开源深度指南 & 新金融背后的科技力量》 内容介绍 书籍优点 书评 书评 | 《新程序员005&#xff1a;开源深度指南 & 新金融背后的科技力量》 内容介绍 《新程序员005&#xff1a;开源深度指南&amp;新金融背后的科技力量》特…

手动创建django项目和python虚拟环境

在使用pycharm创建django项目的时候&#xff0c;报错如下&#xff1a; C:\Users\12051\AppData\Local\Temp\tmplkz609ucpycharm-management\setuptools-40.8.0\setup.py install Traceback (most recent call last):File "C:\Users\12051\AppData\Local\Temp\tmpqphl…

Sui基金会联合Tencent Cloud和Numen在香港举办的生态交流会圆满结束

5月24日&#xff0c;由Sui基金会、Tencent Cloud和Numen Cyber联合举办的Sui生态交流会在香港圆满结束。感谢Tencent Cloud为本次活动提供了场地支持。本次活动共吸引了60余名行业同仁线上和线下的参与。 本次活动旨在提升Web3产业对Sui生态的认识&#xff0c;并为生态中的开发…