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

这篇具有很好参考价值的文章主要介绍了基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 资料准备

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

资料可以在正点原子官网下载,如下:
http://www.openedv.com/docs/boards/stm32/index.html
基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)
一定要下载最新的资料(开始用旧版本的移植不成功)。

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

2. 实验流程

  1. 添加 FreeRTOS 源码
  2. 添加FreeRTOSConfig.h配置文件
  3. 修改SYSTEM文件
  4. 修改中断相关文件
  5. 添加应用程序
    基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)

2.1 添加 FreeRTOS 源码

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

基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)
portable文件夹里面的东西是连接软件层面的FreeRTOS 操作系统和硬件层面的芯片的桥梁,这里只保留portable文件夹中的RVDS、MemMang、Keil三个文件夹(因为stm32F4只用到这三个文件夹)。
基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)

2.2 将文件添加到工程

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

基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)
将.c文件添加到Middlewares/FreeRTOS_CORE 分组中。
基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)
将MemMang文件夹下的heap_4.c添加到Middlewares/FreeRTOS_PORT分组中。
基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)
将RVDS文件夹下的ARM_CM4F下的port.c添加到Middlewares/FreeRTOS_PORT分组中。
基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)

2.3 添加头文件路径

添加头文件路径FreeRTOS/include和port.c的文件路径。
基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)

2.4 添加 FreeRTOSConfig.h文件

在FreeRTOS的例程中找到该文件FreeRTOSConfig.h,放到移植工程即可,这里放到user文件夹中。
基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)
基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)

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 调试组件,所以把这个组件删掉。
基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)

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

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

2.7 添加定时器驱动

把基本定时器工程中的TIMER文件夹,复制到移植工程中的BSP文件夹中。
基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)
基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)
将定时器的相关驱动文件添加到工程的 Drivers/BSP 文件分组中。
基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)

3. 实验验证

把FreeRTOS例程中的demo复制到移植工程中User中。
基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)
基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)

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

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

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

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移植文章来源地址https://www.toymoban.com/news/detail-460837.html

4. 总结

  1. 遇到如下报大量语法错误,原因是keil编译器问题,把编译器的版本设置为V5即可。
    基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)
    基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)
  2. 最后把程序烧到开发板中,如果LED灯没有亮,复位几次,观察LED是否亮。

到了这里,关于基于stm32F407的hal库,移植FreeRTOS的具体步骤和遇到的问题(看正点原子的视频)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • stm32f407单片机上通过HAL库实现can总线数据的收发

      最近在使用can总线,由于这个以前接触的比较少,所以调试代码的时候直接是下载的正点原子的例程,在这个基础上修改调试的。现在将调试中遇到的问题,总结一下,避免以后踩坑。目前写了一个查询方式的,一个中断方式的。项目代码下载地址: https://download.csdn.n

    2024年02月09日
    浏览(41)
  • 【STM32F407 ADC+DMA采集压力变送器数据(HAL库)】

    之前项目中需要对麦克传感器的mpm480隔爆压力变送器(4-20ma输出)的数据进行实时采集,使用STM32F407作为控制器,使用信号转换模块将压力变送器4-20ma的输出转换为0-3.3v的信号量,输入到STM32F407板子的ADC1的通道10,并使用DMA2通道0数据流0将采集的多个值从外设直接存入存储器

    2024年02月16日
    浏览(57)
  • stm32f407移植LVGL8.3.1实况(所有bug调试现场,最终成功点灯)

    声明: 本文主要参考 stm32移植lvgl_NULL_1969的博客-CSDN博客_lvgl stm32 及 STM32移植LVGL8.0.2超详细的保姆级教程附移植好的工程文件 ,底层驱动主要采用正点原子触摸屏实验和定时器实验 1.1 主要硬件接口 1.1.1 触摸屏 主要需要触摸屏来实现屏幕的显示及触摸。 触摸屏需要底层的接

    2024年01月16日
    浏览(49)
  • STM32F407单片机HAL库CAN2不能接收数据解决方法

      最近在使用stm32F407的片子调试can通信,直接在正点原子的代码上修改调试,调试can1的时候,基本没啥问题,收发都正常,使用查询模式和中断模式都可以。但是当修改到can2的时候,可以正常发送数据,但是中断函数始终进不去。折腾了一两个小时终于搞定了。下面将解

    2024年02月16日
    浏览(34)
  • EtherCAT主站源码 基于STM32F407和STM32H743两款芯片 通过移植开源SOME主站代码,使两款芯片具有EtherCAT主站功能,支持DC同步功能

    EtherCAT主站源码基于STM32F407和STM32H743两款芯片,通过移植开源SOME主站代码,使两款芯片具有EtherCAT主站功能,支持DC同步功能。可支持汇川IS620N、松下A5B/A6B、欧姆龙G5系列、埃斯顿ProNet、迈信EP3E、台达A2-E,伟创SD700这几款EtherCAT总线伺服。支持的这些驱动器可以混用,主站自动

    2024年02月04日
    浏览(37)
  • 基于STM32F407的智能门锁

            在消费升级渗透在各个领域的今天,国民消费发生着巨大的变化,与每个人息息相关的家居行业也是如此。现今,越来越多的智能家居产品出现在普通老百姓的生活中,智能照明、智能窗帘、智能扫地机器人等各种智能产品都给人们的生活带来了极大的便利。智能

    2024年02月11日
    浏览(57)
  • 基于stm32f407的示波器+FFT频谱分析

    1 设计思路 2 DMA传输ADC采样值 使用DMA直接将ADC-DR中的数据传输到ADC数据缓存区,节省cpu资源,高速AD采集,代码如下: 3 ADC定时器触发(可修改ADC采样率) 为了实现ADC采样率可调,我将AD的出发方式设置为定时器触发,使用TIM3来触发adc采集,首先初始化定时器,先预设几种初

    2024年02月05日
    浏览(44)
  • 基于STM32F407实现超声波测距(SR04)

    今天要实现的功能是超声波测距,这一功能在很多的地方都能用到,比如:在智能小车上可以添加超声波避障功能。今天需要用到SR04超声波模块,在使用这一模块的时候我很会接触到时序图。 模块如图所示: 模块有四个引脚 VCC 供 5V电源, GND 为地线, TRIG 触 发 控 制 信 号

    2024年02月11日
    浏览(46)
  • STM32CubeMX生成C代码及时钟树配置(基于stm32f407)

    近来对于stm32单片机编程中,HAL库逐渐取代标准库成为主流的库。标准库支持的芯片型号有限,而且目前已经停止支持,而HAL库支持所有类型的芯片,可移植性也很高,再加上有神器STM32Cube可以生成工程模板,越来越多的编程开始从使用标准库转到使用HAL库。 新建工程后,在

    2024年02月15日
    浏览(51)
  • stm32f407探索者开发板(二)——新建工程(基于固件库)

    说实话,我非常不想这篇文章,因为太长太长了,我看视频写都写了一个下午(虽然我下午一直在摸鱼,啊啊啊啊啊)害,不管了,赶紧开始写吧,不然今晚是写不完了,呜呜呜…… 把这个里面的文件放先给下好,我这里是没有光盘的,所以需要从百度网盘上下载好,这里面

    2023年04月08日
    浏览(73)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包