当前位置:   article > 正文

移植CMSIS_FREERTOS_cmsis-freertos

cmsis-freertos

前言

这个文章其实是在去年3月份准备电赛期间研究TI CC3200时写的,当时并没有想着往网上发,随着RTOS发展的越来越火热,我也想在这方面出点力,所有把这篇文章上传一下,方便大家在移植FreeRTOS时有个参考

下载CMSIS_FREERTOS

https://github.com/ARM-software/CMSIS-FreeRTOS

image-20230409205303093
如果实在无法在github上下载,请使用网盘
链接:https://pan.baidu.com/s/1XwJRH5a3zSkUHfDS09k6qQ?pwd=lksc
提取码:lksc

创建一个FreeRTOS文件夹用来保存我们需要的文件,从CMSIS-FreeRTOS提取Source文件和Config/ARMCM文件夹(我们需要里面的FreeRTOSConfig.h)

根据编译器选择对应的portable文件

裁剪portable文件夹,必须留下对应编译器的文件夹(如果是keil就需要保留RVDS文件夹)GCC文件夹和MenMang文件夹,MenMang里我们需要里面的heap4.c文件

将FreeRTOSConfig.h文件复制到source/include里

对FreeRTOSConfig.h内的相关配置做修改

image-20230409211125073

1.首先修改堆大小,即configTOTAL_HEAP_SIZE这个宏,根据自己所使用的MCU RAM资源确定,一般不推荐将RAM空间全部分配给这个堆,我给我的STM32F411设置的大小为((size_t)(64*1024)),实际可以更大一些。其次修改configCPU_CLOCK_HZ这个宏为自己MCU的主频,如果你使用CUBEMX生成工程,这一个宏可以不改

2.开启软件定时器,将configUSE_TIMERS设置为1

image-20230410205329534

3.注意每个MCU设置中断优先级的bit不一定相同,例如STM32使用4个bit位,TI的CC3200使用3个bit位表示优先级,相应的configPRIO_BITS和configLIBRARY_LOWEST_INTERRUPT_PRIORITY这两个宏定义便需要修改,这里的宏的设置以STM32为例

image-20230410205432687

注释掉 #include “freertos_evr.h”

image-20230409212246629

添加常规文件

位于source文件夹中的croutine.c ,event_groups.c ,list.c ,queue.c ,stream_buffer.c,tasks.c,timers.c,位于portable文件夹中MemMang里的heap4.c和对应IDE编译器(以keil的ARMClang为例)的port.c文件

如下图所示

image-20230410201637355

关于CUBEMX生成的工程的一些注意事项

1.如果你是使用STM32CUBEMX生成的工程,请在stm32fxxx_it.c中将SVC、PendSV、Systic这三个中断函数给注释掉,port.c中定义了这三个中断函数,用于设置任务切换和恢复任务的栈空间

2.由于FreeRTOS使用Systick作为整个系统的时基,所以我们需要更换一个定时器作为STM32的时基,以便我们使用HAL_GetTick()等函数,如果使用CUBEMX配置的话,在SYS中更改Timebase Source,选择任意一个基本定时器即可,以下图为例

image-20230410204646464

添加头文件路径

以STM32F411和keil开发平台为例

添加/FREERTOS/Source/include和/FREERTOS/Source/portable/GCC/ARM_CM4F(此处为对应的内核),我这里使用的是相对路径。

image-20230410201230206

主函数实验

//FreeRTOS includes
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include <stdio.h>
#include "semphr.h"
#include "event_groups.h"
#include "timers.h"



TaskHandle_t  xHandleTask1;
TaskHandle_t  xHandleTask2;

void Task1Funtion(void *param)

{
volatile int i;while(1){}
}
void Task2Funtion(void *param)
{
volatile int i;while(1){}

}

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2*/

xTaskCreate(Task1Funtion,"TASK1",100,NULL,1,&xHandleTask1);
xTaskCreate(Task2Funtion,"TASK2",100,NULL,1,&xHandleTask2);

vTaskStartScheduler();//开启调度
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78

烧录好以后debug模式下在两个任务的while(1)里打断点,并全速运行,如果系统能在两个任务间切换即表示移植成功(以IAR平台为例)

若出现总是进入同一个任务的断点,可以先取消这个任务的断点,再全速运行,查看是否能进入另一个任务的断点(原因大概率是因为这个任务还没执行够1ms,所以并没有切换任务)

image-20230410202442527

如果系统能在两个任务间切换即表示移植成功(以IAR平台为例)

若出现总是进入同一个任务的断点,可以先取消这个任务的断点,再全速运行,查看是否能进入另一个任务的断点(原因大概率是因为这个任务还没执行够1ms,所以并没有切换任务)

[外链图片转存中…(img-rwXIfIDl-1710139206540)]

image-20230410202505287

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
  

闽ICP备14008679号