STM32F103移植FreeRTOS
1. 源码下载
- 在https://www.freertos.org/中下载源码,这里下载的是FreeRTOSv202212.01版本,源码内容解释可参考:
https://rtos.100ask.net/zh/FreeRTOS/DShanMCU-F103/chapter7.html#_7-1-freertos%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84
- 拷贝一个最简单的所使用cubeMX+HAL的LED实验工程作为待移植工程文件,并在基础工程中新建一个名为 FreeRTOS 的文件夹
注意这里的工程的timebase source时(即HAL_Delay的时钟源),默认cubeMX新建工程时使用的systick,不能使用SysTick,因为SysTick被FreeRTOS使用了,可以使用其他的(如TIM1、TIM2……)另外,假设使用了TIM2作为timebase source,记得修改其优先级为较高或最高,比如0或1
Systick的优先级由FreeRTOS设置,我们不用管
- 创建FreeRTOS文件夹之后将步骤1获取到的FreeRTOS文件下的FreeRTOSv202212.01->FreeRTOS->Source中的全部文件全部拷贝到创建文件夹下
- 其中为了工程轻简,protable文件夹下只留下以下三个文件夹:
2.Keil添加文件
-
用keil打开工程文件,点击所示图标新建两个分组FreeRTOS_CORE 和 FreeRTOS_PORTABLE
-
其中FreeRTOS_CORE中的文件为源码直接打开可看到的.c文件
-
FreeRTOS_PORTABLE中的文件为port.c 是 RVDS 文件 夹下的 ARM_CM3 中的文件,因为 STM32F103 是 Cortex-M3 内核的,因此要选择 ARM_CM3 中的 port.c 文件,heap_4.c 是 MemMang 文件夹中的,因为heap_4 提供了一个最优的匹配算法,选择heap_4相关API进行内存管理。
-
在工程文件夹中创建USER文件夹,用于存放自己的任务代码,这里使用最简单的闪烁LED任务,在USER文件夹中新建led.c和led.h,Keil中新建USER分组并添加led.c文件,这两个文件暂时空白,最后会说。
-
keil添加include目录,一个是include,一个是ARM_CM3(自己所使用芯片内核对应的名称,一个是led.h即自己任务函数存放的位置)
-
这里还缺少缺少FreeRTOSConfig.h,他是FreeRTOS 的配置文件,一般的操作系统都有裁剪、配置功能,而这些裁剪及配置都是通过一个文件来完成的,基本都是通过宏定 义来完成对系统的配置和裁剪的。可以到FreeRTOS的demo里面相关的,但是不同硬件和环境配置不同,本操作韦东山瑞士军刀F103的板子,直接拷贝一份freertos示例代码中的FreeRTOSConfig.h到FreeRTOS的include目录下,如果有则进入章节3
如果没有这个头文件则看看源码Demo文件夹中有没有自己芯片内核名称的文件夹,如CORTEX_CM3…等,复制里面的FreeRTOSConfig.h,我所使用的这个源码在章节五。 -
3.代码修改
- 在stm32f1xx_it.c文件中,注释掉这两个函数定义
void SVC_Handler(void)
void PendSV_Handler(void)
- 如果此时编译报错systick_Handler重定义(在port.c和stm32f1xx_it.c中定义),则把stm32f1xx_it.c中的注释掉,如果没有报错则在stm32f1xx_it.c中改写这个函数:
#include "FreeRTOS.h"
#include "task.h"
extern void xPortSysTickHandler(void);
//systick中断服务函数,使用ucos时用到
void SysTick_Handler(void)
{
if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
{
xPortSysTickHandler();
}
}
- 如果报错:Error: L6218E: Undefined symbol vApplicationGetIdleTaskMemory (referred from tasks.o),#define configSUPPORT_STATIC_ALLOCATION 改为0 ,取消静态内存申请
4.自定义的任务函数
- 之前新建的任务函数存放的地方led.h:
#ifndef LED_H__
#define LED_H__
void task_led(void *argument);
#endif
- led.c
#include "led.h"
#include "main.h"
#include "stm32f1xx_hal.h"
#include "FreeRTOS.h"
#include "task.h"
void task_led(void *argument){
// taskENTER_CRITICAL(); 进入临界区的代码会被保护(不会被打断)
while(1){
HAL_GPIO_WritePin(LEDR_GPIO_Port, LEDR_Pin, GPIO_PIN_RESET);//灯闪烁
vTaskDelay(pdMS_TO_TICKS(1500)); // 1500ms
HAL_GPIO_WritePin(LEDR_GPIO_Port, LEDR_Pin, GPIO_PIN_SET);
vTaskDelay(pdMS_TO_TICKS(1500));
}
}
5.代码验证
- main.c函数中
#include "led.h"
#include "FreeRTOS.h"
#include "Task.h"
- main函数中初始化结束后添加两行代码创建任务和启动任务调度器
- 此时编译运行LED灯闪烁
5.附录
- 用于STM32F103C8T6 CM3内核的FreeRTOSConfig.h,不同芯片的内容有细微不同,区别在堆栈大小设置等
/* USER CODE BEGIN Header */
/*
* FreeRTOS Kernel V10.0.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/* USER CODE END Header */
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* These parameters and more are described within the 'configuration' section of the
* FreeRTOS API documentation available on the FreeRTOS.org web site.
*
* See http://www.freertos.org/a00110.html
*----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* Section where include file can be added */
/* USER CODE END Includes */
/* Ensure definitions are only used by the compiler, and not by the assembler. */
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
#include <stdint.h>
extern uint32_t SystemCoreClock;
#endif
#define configUSE_PREEMPTION 1
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configTICK_RATE_HZ ((TickType_t)1000)
#define configMAX_PRIORITIES ( 56 )
#define configMINIMAL_STACK_SIZE ((uint16_t)128)
#define configTOTAL_HEAP_SIZE ((size_t)3072)
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Software timer definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( 2 )
#define configTIMER_QUEUE_LENGTH 10
#define configTIMER_TASK_STACK_DEPTH 256
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_xQueueGetMutexHolder 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_eTaskGetState 1
/*
* The CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation used
* by the application thus the correct define need to be enabled below
*/
#define USE_FreeRTOS_HEAP_4
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
/* USER CODE BEGIN 1 */
#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
/* USER CODE END 1 */
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
/* IMPORTANT: This define is commented when used with STM32Cube firmware, when the timebase source is SysTick,
to prevent overwriting SysTick_Handler defined within STM32Cube HAL */
#define xPortSysTickHandler SysTick_Handler
/* USER CODE BEGIN Defines */
/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */
/* USER CODE END Defines */
#endif /* FREERTOS_CONFIG_H */