FreeRTOS学习笔记 & FreeRTOS移植

FreeRTOS 移植前的准备

  1.  FreeRTOS 官网下载源码压缩包文件
  2.  准备一块STM32开发板

FreeRTOS 文件介绍

FreeRTOS学习笔记 & FreeRTOS移植_第1张图片

Demo 文件夹: 里面包含了 FreeRTOS 官方为各个单片机移植好的工程代码,
FreeRTOS 为了推广自己,会给各种半导体厂商的评估板写好完整的工程程序,
这些程序就放在 Demo 这个目录下,这部分 Demo 非常有参考价值
Source 文件夹: 里面包含的是 FreeRTOS 内核的源代码,我们移植 FreeRTOS
的时候就需要这部分源代码
License 文件夹: 这个文件夹里面就是相关的许可信息,要用 FreeRTOS 做产
品的得仔细看看,尤其是要出口的产品

Source 文件夹

FreeRTOS学习笔记 & FreeRTOS移植_第2张图片

编号①和②包含的是 FreeRTOS 的通用的头文件和 C 文件,这两部分的文件适用于各种编译器和处理器,是通用的。

需要移植的头文件和 C 文件放在编号③portble 这个文件夹

portble 文件夹

FreeRTOS学习笔记 & FreeRTOS移植_第3张图片 

编号①中的 KEIL 就是我们就是我们使用的编译器,打开 KEIL 文件夹的时 候,你会看到一句话“See-also-the-RVDS-directory.txt”,其实 KEIL 里面
的内容跟 RVDS 里面的内容一样,所以,我们只需要编号③RVDS 文件夹里面的内容即可

RVDS 文件夹

FreeRTOS学习笔记 & FreeRTOS移植_第4张图片

FreeRTOS 为我们提供了 cortex-m0、m3、m4 和 m7 等内核的单片机的接口文件,只要是使用了这些内核的 mcu 都可以使用里面的接口文件
我们这里以 ARM_CM3 这个文件夹为例,看看里面的文件,里面只有“port.c”与“portmacro.h”两个文件,port.c 文件里面的内容是 FreeRTOS 官方的技术
人员为 Cortex-M3 内核的处理器写的接口文件,里面核心的上下文切换代码是由汇编语言编写而成

MemMang 文件夹

编号②MemMang 文件夹下存放的是跟内存管理相关的,总共有五个 heap 文件以及一个 readme 说明文件,这五个 heap 文件在移植的时候必须使用一个, 因为 FreeRTOS 在创建内核对象的时候使用的是动态分配内存,而这些动态内存分配的函数则在这几个文件里面实现,不同的分配算法会导致不同的效率与结果后面在内存管理中我们会讲解每个文件的区别,所以我们选用 heap4.c 即可

Demo 文件夹

这个目录下内容就是 Deme 例程,我们可以直接打开里面的工程文件,各种开发平台的完整 Demo,开发者可以方便的以此搭建出自己的项目,甚至直接使
用。FreeRTOS 当然也为 ST 写了很多 Demo,其中就有 F1、F4、F7 等工程,这对我们学习 FreeRTOS 是非常方便的,当遇到不懂的直接就可以参考官方的
Demo。

接下来开始移植FreeRTOS

在前面创建的好的基础工程“FreeRTOS 移植模板”内新建一个“FreeRTOS” 文件夹用于保存 FreeRTOS 移植所需源码
FreeRTOS学习笔记 & FreeRTOS移植_第5张图片

创建好 FreeRTOS 文件夹后,就可以将 FreeRTOS 源码添加到该文件中 

可直接将源码“ FreeRTOS\Source ”内容全部拷贝到新建的“FreeRTOS”文件夹中
FreeRTOS学习笔记 & FreeRTOS移植_第6张图片

编号①和②不需要修改

编号③portable保留3个文件夹,其余的可以删除,因为用不上

FreeRTOS学习笔记 & FreeRTOS移植_第7张图片

 在Keil 工程中添加FreeRTOS源码

FreeRTOS学习笔记 & FreeRTOS移植_第8张图片

FreeRTOS_port 分组中的 port.c 和 heap_4.c 是怎么来 的,port.c 是 RVDS 文件夹下的 ARM_CM3 中的文件,因为 STM32F103 是
Cortex-M3 内核的,因此要选择 ARM_CM3 中的 port.c 文件。假如使用的是其它内核芯片,则选择对应内核文件夹内的 port.c 文件
heap_4.c 是 MemMang 文件夹中的,前面说了 MemMang 是跟内存管理相关的,里面有 5 个 c 文件:
heap_1.c、heap_2.c、heap_3.c、heap_4.c 和 heap_5.c。
这 5 个 c 文件是五种不同的内存管理方法。这 5 个文件都可以用来作为 FreeRTOS 的内存管理文
件,只是它们的实现原理不同,各有利弊。这里我们选择 heap_4.c

FreeRTOSConfig.h

此文件是 FreeRTOS 的配置文件,一般的操作系统都有裁剪、配置功能,而这些裁剪及配置都是通过一个文件来完成的,基本都是通过宏定义来完成对系统的配置和裁剪的

FreeRTOSconfig.h文件基本配置

修改Keil 工程中的文件

FreeRTOS学习笔记 & FreeRTOS移植_第9张图片

 首先打开 stm32f10x_it.c 将下面3个中断服务函数都注释掉

PendSV_Handler()

SVC_Handler()
SysTick_Handler()
在打开 FreeRTOSConfig.h  将下面3个宏定义加进去
#define xPortPendSVHandler 	PendSV_Handler
#define vPortSVCHandler 	SVC_Handler

#define xPortSysTickHandler SysTick_Handler
FreeRTOS 帮我们实现了 SysTick 的启动的配置:在 port.c 文件中已经实现vPortSetupTimerInterrupt()函数,
并且 FreeRTOS 通用的 SysTick 中断服务函数也实现了:在 port.c 文件中已经实现 xPortSysTickHandler()函数,只需添加一条宏用 SysTick_Handler 代替掉或者在 SysTick_Handler 中调用xPortSysTickHandler()函数
PendSV_Handler()与 SVC_Handler()这两个很重要的函数都帮我们实现了,在 port.c 文件中已经实现
xPortPendSVHandler()与 vPortSVCHandler()函数,防止我们自己实现不了,那么在 stm32f10x_it.c 中就需要我们注释掉 PendSV_Handler()与SVC_Handler()这两个函数

HAL库开发需要注意 

HAL库也有自己的系统时机,也是利用SYStick来提供计数节拍,所以和RTOS会有冲突,因为都使用SYStick中断来计数

建议使用基本定时器,更新中断来给HAL库提供节拍

SYStick中断分配给FreeRTOS

可参考下面大概步骤,使用CUBE MX 可以直接自动配置

TIM_HandleTypeDef        htim1;
//初始化定时器
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  RCC_ClkInitTypeDef    clkconfig;
  uint32_t              uwTimclock = 0U;

  uint32_t              uwPrescalerValue = 0U;
  uint32_t              pFLatency;
  HAL_StatusTypeDef     status = HAL_OK;

  /* Enable TIM1 clock */
  __HAL_RCC_TIM1_CLK_ENABLE();

  /* Get clock configuration */
  HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);

  /* Compute TIM1 clock */
  uwTimclock = HAL_RCC_GetPCLK2Freq();

  /* Compute the prescaler value to have TIM1 counter clock equal to 1MHz */
  uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);

  /* Initialize TIM1 */
  htim1.Instance = TIM1;

  /* Initialize TIMx peripheral as follow:
  + Period = [(TIM1CLK/1000) - 1]. to have a (1/1000) s time base.
  + Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
  + ClockDivision = 0
  + Counter direction = Up
  */
  htim1.Init.Period = (1000000U / 1000U) - 1U;
  htim1.Init.Prescaler = uwPrescalerValue;
  htim1.Init.ClockDivision = 0;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

  status = HAL_TIM_Base_Init(&htim1);
  if (status == HAL_OK)
  {
    /* Start the TIM time Base generation in interrupt mode */
    status = HAL_TIM_Base_Start_IT(&htim1);
    if (status == HAL_OK)
    {
    /* Enable the TIM1 global Interrupt */
        HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
      /* Configure the SysTick IRQ priority */
      if (TickPriority < (1UL << __NVIC_PRIO_BITS))
      {
        /* Configure the TIM IRQ priority */
        HAL_NVIC_SetPriority(TIM1_UP_IRQn, TickPriority, 0U);
        uwTickPrio = TickPriority;
      }
      else
      {
        status = HAL_ERROR;
      }
    }
  }

 /* Return function status */
  return status;
}
//定时器更新中断回调
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{

  if (htim->Instance == TIM1) {
    HAL_IncTick();
  }

}

移植步骤已完成

FreeRTOSConfig.h基本配置 

通过配置 FreeRTOSConfig.h 文件中的宏 来配置和裁剪系统的功能及属性

你可能感兴趣的:(FreeRTOS学习笔记,学习,笔记,单片机)