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

news2024/11/28 20:48:13

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用于定义系统文件夹是否支持OS
 2. 0,不支持OS
 3. 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();    
//#endif
    HAL_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.coloradmin.cn/o/572707.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

格式化输出Printf总结说明

一&#xff0c;简介 在C语言运行调试过程中&#xff0c;需要使用printf进行打印log信息&#xff0c;本文主要介绍常用的printf打印格式信息&#xff0c;方便提高调试的效率。 二&#xff0c;Printf转换说明 printf函数的转换说明由字符%和跟随其后的最多5个不同的选项构成&a…

PHP快速实战18-PHP使用PHPMailer来发送邮件

文章目录 前言安裝与实现步骤1&#xff1a;下载PHPMailer步骤2&#xff1a;包含PHPMailer文件步骤3&#xff1a;设置SMTP服务器和端口号步骤4&#xff1a;设置发件人和收件人步骤5&#xff1a;设置邮件主题和内容步骤6&#xff1a;添加附件&#xff08;可选&#xff09;步骤7&a…

深度学习-第T8周——猫狗识别

深度学习-第T8周——猫狗识别 深度学习-第T8周——猫狗识别一、前言二、我的环境三、前期工作1、导入数据集2、查看图片数目 四、数据预处理1、 加载数据1.1、设置图片格式1.2、划分训练集1.3、划分验证集1.4、查看标签1.5、再次检查数据1.6、配置数据集 2、数据可视化 五、搭建…

GMesh网格选项介绍

GMesh网格介绍 2D mesh algorithm MeshAdapt&#xff1a;这是一种自适应网格算法&#xff0c;可在需要更大的精度或在某些区域需要更密集的网格时自动添加额外的网格。该算法的优点包括较高的收敛性和灵活性&#xff0c;它可以让用户在需要的地方添加更多的网格&#xff0c;但…

隐形黑客潜入美国和关岛关键基础设施而未被发现

微软和“五眼联盟”国家周三表示&#xff0c;一个隐秘的组织成功地在美国和关岛的关键基础设施组织中建立了一个持久的立足点&#xff0c;而没有被发现。 这家科技巨头的威胁情报团队正在以伏特台风(Volt Typhoon)的名义跟踪这些活动&#xff0c;包括入侵后的凭证访问和网络系…

如何实现torna文档生成管理工具api接口从内网到外网的访问?

企业接口文档解决方案&#xff0c;目标是让文档管理变得更加方便、快捷。Torna采用团队协作的方式管理和维护项目API文档&#xff0c;将不同形式的文档纳入进来&#xff0c;形成一个统一的维护方式。下面简单给大家介绍一下torna接口文档管理工具都有哪些功能特性&#xff1a; …

【Java EE 初阶】TCP协议的安全效率机制

目录 1.应用层协议 2.传输层协议 3.UDP协议格式 4.TCP协议格式 5.TCP的安全效率机制 1.确认应答机制 2.超时重传机制 但是&#xff0c;主机A未收到B发来的确认应答&#xff0c;也可能是因为ACK丢失了&#xff1b; 3.连接管理机制 面试题&#xff1a;会不会有可能变成三…

【A卡,Windows】stable diffusion webui下载安装避坑指南

观前提醒 本文内容都是本人亲身经历的&#xff0c;一个一个安装下载测试所感&#xff0c;当然如果你更想用傻瓜式集成包的&#xff0c;那还是跳过这篇文章吧。 当然我不推荐这篇文章的操作&#xff0c;因为我用了差不多1h才有一副图&#xff0c;有N卡&#xff0c;就用N卡&…

jdk14——独立打包工具jpackage

jpackage是jdk14正式加入的一个用于独立打包的工具&#xff1b; 官网简介翻译&#xff1a; jpackage工具将以Java应用程序和Java运行时映像作为输入&#xff0c;并生成一个包含所有必要依赖项的Java应用程序映像。它可以生成特定于平台格式的本机软件包&#xff0c;例如Windo…

【UE】制作可拖动的UI

效果 步骤 1. 新建一个控件蓝图并打开 这里我在画布面板中加了一个垂直框&#xff0c;垂直框内包含一个按钮和一个图像控件 我设置图像控件占垂直框的2/3&#xff0c;按钮占1/3 添加按钮按压事件、松开事件 在控件蓝图的事件图表中添加如下节点&#xff0c;其中“Close”、“…

通达信三重滤网交易系统指标公式(含强力指数指标)

三重滤网交易系统由《以交易为生》的作者亚历山大埃尔德(Alexander Elder)发明的&#xff0c;1986年首次公开&#xff0c;后续又不断改进&#xff0c;增加或者改变了一些细节&#xff0c;但是使用多重时间周期和技术指标进行分析决策的原理没变。 一、强力指数指标 《以交易为…

Taro 项目怎么获取元素的高度和视口高度

最近做小程序&#xff0c;用的Taro&#xff0c;需要设置空状态居中显示&#xff0c;因为空状态出现的地方不一样&#xff0c;所以需要动态设置&#xff0c;那么就需要获取元素的高度来计算 文档翻了一遍也没有找到&#xff0c;原生js获取高度得到的是null&#xff0c;百度了下…

点云拟合平面原理和实现(Halcon)

最近学习了一下拟合平面的原理&#xff0c;看了这篇文章最小二乘拟合平面(C版) - 知乎 讲到了以下几种方法&#xff0c;我这里在halcon中对其一一实现。 一、算法原理 1&#xff0c;直接求解法 2.使用拉格朗日乘子法 3 SVD分解法 二、Halcon实现 1.各方法对比 在halcon中…

Python - 面向对象编程 - 类变量、实例变量/类属性、实例属性

什么是对象和类 什么是 Python 类、类对象、实例对象 类变量、实例变量/类属性、实例属性 前言 只是叫法不一样 实例属性 实例变量 类属性 类变量 个人认为叫属性更恰当 类属性和实例属性区别 类属性&#xff0c;所有实例对象共享该属性实例属性&#xff0c;属于某一…

win10系统如何设置虚拟回环

在日常生活中&#xff0c;人们(特别是IT行业者)通常需要在一台机上进行软件测试&#xff0c;而同一台计算上通常只能使用一个地址&#xff0c;而在需要同时使用两个地址进行测试的时候就显得捉襟见肘。此方法通过配置window10自带的环回适配器&#xff0c;达到上述目的。 win1…

如何用chatgpt写作论文 GPT写毕业论文的技巧

如何用chatgpt写作论文 GPT写论文的技巧 经常被问到为什么万事知天下小程序不能写论文。也不是不能写&#xff0c;只是GPT3.5的上下文只有4K&#xff0c;一般论文要写上万字&#xff0c;所以不可能你直接输入一个论文标题就直出结果的。 不过手工分一下步骤就可以了。先让写…

适用于中小企业的5种采购策略

与大企业不同&#xff0c;在采购管理方面&#xff0c;中小企业往往不得不在更有限的资源范围内运作&#xff0c;并且没有同等水平的经验丰富的采购专业人员或先进的采购技术。这会使优化采购流程并实现与大型企业相同水平的成本节约和风险管理变得更具挑战性。但是&#xff0c;…

docker idea直接部署到腾讯云镜像服务

首先创建一个Dockerfile 编写Dockerfile的信息 FROM java:8 MAINTAINER clarkshixxx.com RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai >/etc/timezone ENV ACTIVE"pre" ENV loggingpath"/zhibo/logs"…

【Flutter 工程】005-代码分离实践:flutter_hooks functional_widget

【Flutter 工程】005-代码分离实践&#xff1a;flutter_hooks & functional_widget 文章目录 【Flutter 工程】005-代码分离实践&#xff1a;flutter_hooks & functional_widget一、概述1、Flutter “嵌套地狱”2、代码分离实践 二、实践1、安装 flutter_hooks & f…

油猴脚本尝试

现在是这样的&#xff0c;我这边有个运维系统&#xff0c;里面有个日志&#xff0c;我们经常要复制&#xff0c;然后我们复制的时候需要打开内容&#xff0c;然后去选中复制。 类似于这种&#xff0c;我觉得这个时候&#xff0c;去选中复制就很麻烦&#xff0c;右边这里不是有…