目录

1.第一步准备好基础工程

2.软件仿真相关设置

3.软件仿真环境,printf重定向

4.移植FreeRtos源码

4.1 拷贝文件

5.增加freertos源码到keil工程中

5.1增加.c文件到工程:

5.2增加头文件到工程:

6.修改编译问题

7.修改SYSTEM文件和systick中断处理函数

7.1 修改sys.h文件

7.2 修改usart.c文件

7.3 修改delay.c文件

7.3 修改SysTick_Handler中断处理函数

7.修改main文件,创建freertos任务


1.第一步准备好基础工程

准备好基础工程,并且编译通过,这里使用正点原子STM32F411提供的“F411_标准例程-寄存器版本“中的”实验4 串口通信实验“为基础。

2.软件仿真相关设置

通过菜单project->Options for target,打开工程设置

修改外部时钟频率为8M:

设置软件仿真,初始化文件,以及STM32F411RC对应的调试DLL

 说明:

1.选择Use Simulator可以直接使用软件仿真,不需要硬件单板。

2.设置Initialization File是为.\DebugConfig\debug.ini,是为了避免出现

*** error 65: access violation at 0x40023800 : no 'read' permission错误。

对应文件内容为:

map 0x40000000, 0x40007FFF read write // APB1
map 0x40010000, 0x400157FF read write // APB2
map 0x40020000, 0x4007FFFF read write // AHB1
map 0x50000000, 0x50060BFF read write // AHB2
map 0x60000000, 0x60000FFF read write // AHB3
map 0xE0000000, 0xE00FFFFF read write // CORTEX-M4 internal peripherals

3.设置调试dll和参数,调试dll为DARMSTM.DLL,Parameter根据需要仿真的硬件单板来填。

3.软件仿真环境,printf重定向

3.1修改部分仿真环境下死循环问题

  • 在仿真环境下,设置时钟为HSE后,等待HSE READY一直等不到,具体原因不晓得。

修改的办法就是增加一个宏隔离,在#ifndef SIM情况下,不用死等。

3.2修改printf仿真环境下无法输出问题

主要参考教材:(4条消息) MDK下仿真实现printf功能_mytt2013的博客-CSDN博客_mdk中printf

基于原工程,只需要修改一个函数:

//重定义fputc函数
int fputc(int ch, FILE *f)
{
#ifdef SIM //仿真环境下printf重定向return ITM_SendChar(ch);
#else   while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   USART1->DR = (u8) ch;      return ch;
#endif
}

另外还有一个教程,是使用微库的版本,也可以参考:printf系列教程01_UART打印输出配置,基于STM32(Keil、IAR)_strongerHuang的博客-CSDN博客

4.移植FreeRtos源码

主要过程参考:(4条消息) FreeRTOS在STM32F4上移植_Zach_z的博客-CSDN博客

4.1 拷贝文件

1.在测试工程中建立两个文件夹,分别为Freertos_core和Freertos_port,

2.拷贝freertosv9.0.0\FreeRTOS\Source公共源码到工程目录Freertos_core下:

拷贝source目录下所有文件,除了portable文件到工程目录的Freertos_core目录下:

3.拷贝FreeRtos架构相关源码到工程目录Freertos_port下:

拷贝:FreeRTOS\Source\portable\MemMang\heap_4.c

拷贝:\freertosv9.0.0\FreeRTOS\Source\portable\RVDS\ARM_CM4F 下所有文件

另外,还需要一个FreeRTOSConfig.h,由于我们单板是STM32F411,所以选择FreeRTOS\Demo\CORTEX_M4F_STM32F407ZG-SK工程下的文件,将该文件拷贝到freertos_stm32f411\Freertos_port\include目录,拷贝后的文件结构:

5.增加freertos源码到keil工程中

5.1增加.c文件到工程:

打开keil工程,点击Manager Project item,增加

增加Group,并增加文件到Group后的状态:

点击OK后,可以看到工程中,已经增加了FreeRtos相关源码:

5.2增加头文件到工程:

点击Project->Options for "Target 1"

在C/C++选项卡中,增加相关头文件:

增加Freertos头文件后如图:

6.修改编译问题

1.修改SystemCoreClock条件编译,

Freertos_port\include\FreeRTOSConfig.h中

#ifdef __ICCARM__#include <stdint.h>extern uint32_t SystemCoreClock;
#endif

修改为

#if defined(__ICCARM__) || defined(__CC_ARM) ||defined(__GUNC__)#include <stdint.h>extern uint32_t SystemCoreClock;
#endif

2.重定义函数处理

PendSV_Handler,SVC_Handler ,SysTick_Handler三个函数有重复定义:

注释掉SYSTEM\delay\delay.c中的PendSV_Handler和SVC_Handler定义,

注释掉include\FreeRTOSConfig.h中的#define xPortSysTickHandler SysTick_Handler

3.关闭钩子函数

复制过来的FreeRTOSConfig.h文件中默认开启了一些钩子函数,都是以Hook结尾,但并未定义,在FreeRTOSConfig.h中把configUSE_IDLE_HOOK、configUSE_TICK_HOOK、configCHECK_FOR_STACK_OVERFLOW和configUSE_MALLOC_FAILED_HOOK的宏定义改为0

至此,应该能编译通过了。

7.修改SYSTEM文件和systick中断处理函数

因为原子的SYSTEM文件夹是针对UCOS编写的,所以要进行对应的修改

7.1 修改sys.h文件

把宏定义SYSTEM_SUPPORT_OS改为1即可,要支持OS,UCOS也一样的

//0,不支持os
//1,支持os
#define SYSTEM_SUPPORT_OS       1       //定义系统文件夹是否支持OS

调试过程中发现直接定义SYSTEM_SUPPORT_OS宏,更好一些,避免有些文件没有包含sys.h,导致一些异常难以发现。所以这里可以直接把这行去掉,然后在宏里面定义。

7.2 修改usart.c文件

打开SYSTEM文件夹下usart.c文件,添加FreeRTOS.h头文件

#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h"                   //FreeRtos
#endif

USART1的中断服务函数在使用UCOS时进出中断添加OSIntEnter()与OSIntExit(),使用FreeRTOS则不需要,故注释掉

//串口1中断服务程序
void USART1_IRQHandler(void)
{ u32 timeout=0;u32 maxDelay=0x1FFFF;
//#if SYSTEM_SUPPORT_OS     //使用OS
//  OSIntEnter();
//#endifHAL_UART_IRQHandler(&UART1_Handler);    //调用HAL库中断处理公用函数timeout=0;while (HAL_UART_GetState(&UART1_Handler) != HAL_UART_STATE_READY)//等待就绪{timeout++;超时处理if(timeout>maxDelay) break;        }timeout=0;while(HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)//一次处理完成之后,重新开启中断并设置RxXferCount为1{timeout++; //超时处理if(timeout>maxDelay) break;    }
//#if SYSTEM_SUPPORT_OS     //使用OS
//  OSIntExit();
//#endif
} 

7.3 修改delay.c文件

使用以下代码:

#include "delay.h"
#include "sys.h"
//
//如果需要使用OS,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h"                 //freertos 使用
#include "task.h"
#endif//  static u32 fac_us=0;                         //us延时倍乘数#if SYSTEM_SUPPORT_OS      static u16 fac_ms=0;                       //ms延时倍乘数,在os下,代表每个节拍的ms数
#endif//初始化延迟函数
//当使用ucos的时候,此函数会初始化ucos的时钟节拍
//SYSTICK的时钟固定为AHB时钟
//SYSCLK:系统时钟频率
void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS                       //如果需要支持OS.u32 reload;
#endifHAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick频率为HCLKfac_us=SYSCLK;                       //不论是否使用OS,fac_us都需要使用
#if SYSTEM_SUPPORT_OS                       //如果需要支持OS.reload=SYSCLK;                      //每秒钟的计数次数 单位为K    reload*=1000000/configTICK_RATE_HZ; //根据configTICK_RATE_HZ设定溢出时间//reload为24位寄存器,最大值:16777216,在72M下,约合0.233s左右   fac_ms=1000/configTICK_RATE_HZ;        //代表OS可以延时的最少单位    SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//开启SYSTICK中断SysTick->LOAD=reload;                   //每1/OS_TICKS_PER_SEC秒中断一次  SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
#else
#endif
}   #if SYSTEM_SUPPORT_OS                       //如果需要支持OS.
//延时nus
//nus:要延时的us数.
//nus:0~190887435(最大值即2^32/fac_us@fac_us=22.5)
void delay_us(u32 nus)
{       u32 ticks;u32 told,tnow,tcnt=0;u32 reload=SysTick->LOAD;               //LOAD的值             ticks=nus*fac_us;                       //需要的节拍数 told=SysTick->VAL;                      //刚进入时的计数器值while(1){tnow=SysTick->VAL;  if(tnow!=told){       if(tnow<told)tcnt+=told-tnow;   //这里注意一下SYSTICK是一个递减的计数器就可以了.else tcnt+=reload-tnow+told;        told=tnow;if(tcnt>=ticks)break;           //时间超过/等于要延迟的时间,则退出.}  };
}  //延时nms,会引起任务调度
//nms:要延时的ms数
//nms:0~65535
void delay_ms(u32 nms)
{   if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行{       if(nms>=fac_ms)                     //延时的时间大于OS的最少时间周期 { vTaskDelay(nms/fac_ms);         //FreeRTOS延时}nms%=fac_ms;                        //OS已经无法提供这么小的延时了,采用普通方式延时    }delay_us((u32)(nms*1000));              //普通方式延时
}//延时nms,不会引起任务调度
//nms:要延时的ms数
void delay_xms(u32 nms)
{u32 i;for(i=0;i<nms;i++) delay_us(1000);
}#else  //不用ucos时//延时nus
//nus为要延时的us数.
//nus:0~190887435(最大值即2^32/fac_us@fac_us=22.5)
void delay_us(u32 nus)
{       u32 ticks;u32 told,tnow,tcnt=0;u32 reload=SysTick->LOAD;               //LOAD的值             ticks=nus*fac_us;                         //需要的节拍数 told=SysTick->VAL;                     //刚进入时的计数器值while(1){tnow=SysTick->VAL;  if(tnow!=told){        if(tnow<told)tcnt+=told-tnow;  //这里注意一下SYSTICK是一个递减的计数器就可以了.else tcnt+=reload-tnow+told;        told=tnow;if(tcnt>=ticks)break;            //时间超过/等于要延迟的时间,则退出.}  };
}//延时nms
//nms:要延时的ms数
void delay_ms(u32 nms)
{u32 i;for(i=0;i<nms;i++) delay_us(1000);
}
#endif

7.3 修改SysTick_Handler中断处理函数

使用以下代码:

#ifdef SYSTEM_SUPPORT_OS
#include "FreeRTOS.h"                 //freertos 使用
#include "task.h"
extern void xPortSysTickHandler(void);
//systick中断服务函数,使用OS时用到
void SysTick_Handler(void)
{  if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行{xPortSysTickHandler();  }HAL_IncTick();
}
#else
void SysTick_Handler(void)
{HAL_IncTick();
}
#endif

7.修改main文件,创建freertos任务

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "beep.h"
#include "key.h"/************************************************ALIENTEK NANO板STM32F4开发板实验4串口通信实验-HAL库版本技术支持:www.openedv.com淘宝店铺:http://eboard.taobao.com 关注微信公众平台微信号:"正点原子",免费获取STM32资料。广州市星翼电子科技有限公司  作者:正点原子 @ALIENTEK
************************************************///说明,在工程宏定义中增加SYSTEM_SUPPORT_OS定义,则编译出来版本就是freertos创建任务的版本。否则就是普通的裸机版本。
#ifdef SYSTEM_SUPPORT_OS #include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"//500ms LED1灯状态翻转一次
static void led1Task( void * pvParameters )
{u8 len;    while(1){if(USART_RX_STA&0x8000){                      len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度printf("\r\n您发送的消息为:\r\n");HAL_UART_Transmit(&UART1_Handler,(uint8_t*)USART_RX_BUF,len,1000);   //发送接收到的数据while(__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_TC)!=SET);        //等待发送结束printf("\r\n\r\n");//插入换行USART_RX_STA=0;}vTaskDelay(1);}
}
//1000ms LED2灯状态翻转一次
static void led2Task( void * pvParameters )
{u32 times=0; while(1){if(times%5000==0){printf("\r\nALIENTEK NANO STM32开发板 Freertos串口实验\r\n");printf("正点原子@ALIENTEK\r\n\r\n\r\n");}times++;if(times%200==0)printf("请输入数据,以回车键结束\r\n");  if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.vTaskDelay(10);}
}void startTasks(void)
{xTaskCreate(led1Task,"LED1",256,NULL,100,(TaskHandle_t *)NULL);xTaskCreate(led2Task,"LED2",256,NULL,101,(TaskHandle_t *)NULL);/* 启动任务调度器. */vTaskStartScheduler();   }
#else
void startTasks(void)
{u8 len;    u32 times=0; while(1){if(USART_RX_STA&0x8000){                    len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度printf("\r\n您发送的消息为:\r\n");HAL_UART_Transmit(&UART1_Handler,(uint8_t*)USART_RX_BUF,len,1000);   //发送接收到的数据while(__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_TC)!=SET);        //等待发送结束printf("\r\n\r\n");//插入换行USART_RX_STA=0;}else{if(times%5000==0){printf("\r\nALIENTEK NANO STM32开发板 裸机串口实验\r\n");printf("正点原子@ALIENTEK\r\n\r\n\r\n");}times++;if(times%200==0)printf("请输入数据,以回车键结束\r\n");  if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.delay_ms(10);   } }
}
#endifint main(void)
{HAL_Init();                        //初始化HAL库    Stm32_Clock_Init(96,4,2,4);     //设置时钟,96Mhzdelay_init(96);                 //初始化延时函数LED_Init();                     //初始化LED uart_init(115200);               //初始化串口115200startTasks();}

其他参考文章:

2、STM32F407移植FreeRTOS步骤_nandycooh的博客-CSDN博客_stm32f407移植freertos

FreeRTOS的移植与初步使用_不吃鱼的猫丿的博客-CSDN博客

STM32F411移植FreeRtos教程相关推荐

  1. 基于STM32F103移植FreeRTOS教程

    前言 本教程只针对移植实操,关于理论部分请另行百度学习. 本教程移植实操基于正点原子源码.教程手册进程移植. 移植实操 1.将正点原子跑马灯程序源码复制一份,添加一个文件夹对FreeRTOS源码进行管 ...

  2. 【FreeRTOS】在Cortex-M4开发板上移植FreeRTOS并且实现LED灯闪烁(保姆级教程)

    相信有不少小伙伴手上只有M4的开发板,想要移植FreeRTOS:但是,网上大部分都是M3移植教程.因此,陷入深深的迷茫中,难不成只能使用仿真了???

  3. stm32f429igt6跑linux,TouchGFX在STM32F429IGT6上的移植(FreeRTOS版本)

    TouchGFX在STM32F429IGT6上的移植(FreeRTOS版本) TouchGFX在STM32F429IGT6上的移植(FreeRTOS版本) 目录 一.移植环境 二.应用框架 三.Tou ...

  4. STM32系列单片机标准库移植FreeRTOS V10.4.6详解

      文中所用到的资料下载地址 https://download.csdn.net/download/qq_20222919/87370679   最近看正点原子新录制了手把手教你学FreeRTOS的视 ...

  5. 转发:stm32 移植 freertos

    原链接:http://www.51hei.com/bbs/dpj-106526-1.html 看到一篇stm32移植freertos的文章,讲述的最完整. 前言: 由于之前听过太多人抱怨移植FreeR ...

  6. GD32F407 移植FreeRTOS+Lwip

    文章目录 移植过程 移植FreeRTOS 源码拷贝 FreeRTOSConfig.h 注意事项 移植LWIP 源码拷贝与编译 初始化 移植过程 freeRTOS V10.4.5 下载 https:// ...

  7. FreeRTOS学习及移植笔记之二:在IAR和STM32F103VET上移植FreeRTOS

     上一次,我们简单的测试了FreeRTOS的基于IAR EWARMv6.4和STM32F103VET6平台的Demo,对其有了一个基本认识.接下来我们开始自己移植FreeRTOS的过程. 1.创建 ...

  8. 2.STM32F407ZGT6 学习笔记-移植 FreeRTOS

    程序移植的代码: https://gitee.com/chejia12/free-rtos_-f407.git 1. 在工程下建议FreeRTOS文件夹 2. 在FreeRTOS文件夹下建立 src ...

  9. STM32F103移植FreeRTOS必须搞明白的系列知识---1(Cortex-CM3中断优先级)

    STM32F103移植FreeRTOS必须搞明白的系列知识---1(Cortex-CM3中断优先级) STM32F103移植FreeRTOS必须搞明白的系列知识---2(FreeRTOS任务优先级) ...

  10. 英飞凌TC397移植FreeRTOS

    英飞凌TC397移植FreeRTOS 一.准备工作 1.FreeRTOS源码 2.STM驱动代码 3.中断相关配置文件 4.AURIX Developement Studio初始工程(包含SDK) 二 ...

最新文章

  1. easyexcel怎么设置表头宽度_easyexcel 自动设置列宽
  2. Grub及MBR修复
  3. JS Map 简单实现
  4. DML数据操作语言练习
  5. JDK1.8的新特性详解
  6. Python之进程+线程+协程(并发与并行、GIL锁、同步锁、死锁、递归锁)
  7. HDU.1005 Number Sequence
  8. 服务器link系统命令,可以使用命令(7)来查看网络接口的运行情况。输入该命令后,系统的输出信息如下。...
  9. redis能模糊删除key吗_redis 模糊匹配和批量删除
  10. 啦啦外卖独立版七牛云配置失败解决方案
  11. 黑苹果卡在苹果logo_黑苹果的历史
  12. Overload 和 Override
  13. floor关键字用法:
  14. 【动手学习pytorch笔记】28.机器翻译数据集
  15. 坐标系旋转后的点坐标、坐标点旋转后的点坐标
  16. mac软件全屏时候最顶上任务栏保留_Mac菜单栏上必备的十款应用程序
  17. 收藏!2023年全年考证时间表!
  18. 背包问题记忆化函数实现!!(JavaScript可视化页面展示!)
  19. 基于matlab的16qam系统,基于MATLAB的16QAM通信系统的仿真精选.doc
  20. 天梯赛L2-3 深入虎穴 (25 分)

热门文章

  1. nicescroll参数
  2. tp5 生成二维码并与背景图合并
  3. HenCoder Android 开发进阶:自定义 View 1-4 Canvas 对绘制的辅助 clipXXX() 和 Matrix
  4. DS1302时钟模块介绍及与USRAT HMI通信
  5. linux字体使用教程,Ubuntu 字体设置:使用Windows 字体
  6. 录音文件下载_拒绝敲键盘,在线版免费好用的录音转文字工具
  7. solr为什么比MySQL快_Solr原理?为什么要用Solr?Solr为什么比较快?
  8. 通过Kali linux 模拟CC攻击进行WEB压力测试实战
  9. Hi3519A 接入 BT1120或BT656视频
  10. Opening My World——ESRI用户大会有感