移植教程
FreeRTOS简介
FreeRTOS 介绍
FreeRTOS 是市场领先的面向微控制器和小型微处理器的实时操作系统 (RTOS),与世界领先的芯片公司合作开发,现在每 170 秒下载一次。FreeRTOS 通过 MIT 开源许可免费分发,包括一个内核和一组不断丰富的 IoT 库,适用于所有行业领域。FreeRTOS 的构建突出可靠性和易用性。
省却这些繁琐的苦涩难懂的概念,我们来看个简单的:比如你现在用的裸机编程,那么你会用while(1)来监测,这样会导致一个现象:你在while(1)闪烁一颗灯后,在while(1)中又想实现手动控制舵机,那么加入在点亮一颗灯的函数后有很多代码才轮到控制舵机的函数,当你点击舵机旋转按钮,有肯能就会导致舵机按钮按过后,好久才会有反应。这就是弊端,不呢能够及时的响应。而如果使用FreeRTOS,则可完成实时的操作,把这几个操作看成一个一个任务,人物之间互不打扰的,这样就实现了实时的效果。
FreeRTOS优点
- 可移植:对于不同的开发板,均支持移植,提高了通用性。
- 开源 :开源能够节省很多成本,因为开源免费。
- 轻量级
- 可定制
FreeRTOS移植
FreeRTOS 下载
点击FreeRTOS官网下载连接下载FreeRTOS
下载完成后解压至就合适的位置,
FreeRTOS目录结构
但注意,只有上面的圈中的第一个才有有用,但也不要把删除其他的。
打开圈中的FreeRTOS的文件目录
打开存放内核的Source,查看有哪些文件即文件夹:
在portable文件夹内
有如下文件夹,选中我们所需的(圈中的即为我们所需的)
在MenMang文件夹
内有如下文件,我们要用到内存管理算法4:
在RVDS文件夹
选择要使用的开发板系列:
在ARM_CM3文件夹内
有如下文件:
移植开始
在之前STM32的模板中新建:没有模板的,可参考我的前篇文章:【STM32标准库开发 工程模板建立最强最详细总结,详细到炸裂,一顿狂输出,看完立刻起飞】 建立模板:我这里提供一个建立好的模板:
工程模板下载
工程模板下载完成后目录结构如下图:并将该文件夹改名为FreeRTOS工程模板
原始:
改名后:
我们在这个模板中新建文件夹FreeRTOS
在FreeRTOS文件夹内
建立三个文件夹存放上述的头文件夹和内存管理文件夹以及.c文件:
source文件夹
存放.c文件
完成后
portable文件夹
存放内存管理的文件夹
d.png)
include文件夹添加头文件
找到配置文件FreeRTOSConfig.h
:
1.找到目录
2.打开CORTEX_STM32F103_Keil 文件夹可查看到该FreeRTOSConfig.h
复制该文件至User
Keil5打开工程
点击“品”
添加必要文件
添加FreeRTOSConfig.h
:
完成后:
将头文件目录添加至编译器,让编译器知道.h文件路径在哪
,不要忘记点OK确定按钮:
修改FreeRTOSConfig.h文件
把FreeRTOSConfig.h里面的内容替换成我下面已经裁剪好的这个:
替换里面的内容
/*
* FreeRTOS V202212.01
* Copyright (C) 2020 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#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 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
*----------------------------------------------------------*/
#define configUSE_PREEMPTION 1
/***************************************************************
FreeRTOS与钩子函数有关的配置选项
**************************************************************/
/* 置1:使用空闲钩子(Idle Hook类似于回调函数);置0:忽略空闲钩子
*
* 空闲任务钩子是一个函数,这个函数由用户来实现,
* FreeRTOS规定了函数的名字和参数:void vApplicationIdleHook(void ),
* 这个函数在每个空闲任务周期都会被调用
* 对于已经删除的RTOS任务,空闲任务可以释放分配给它们的堆栈内存。
* 因此必须保证空闲任务可以被CPU执行
* 使用空闲钩子函数设置CPU进入省电模式是很常见的
* 不可以调用会引起空闲任务阻塞的API函数
*/
#define configUSE_IDLE_HOOK 0 //空闲时 钩子函数 回调函数
/* 置1:使用时间片钩子(Tick Hook);置0:忽略时间片钩子
*
*
* 时间片钩子是一个函数,这个函数由用户来实现,
* FreeRTOS规定了函数的名字和参数:void vApplicationTickHook(void )
* 时间片中断可以周期性的调用
* 函数必须非常短小,不能大量使用堆栈,
* 不能调用以”FromISR" 或 "FROM_ISR”结尾的API函数
*/
/*xTaskIncrementTick函数是在xPortSysTickHandler中断函数中被调用的。因此,vApplicationTickHook()函数执行的时间必须很短才行*/
#define configUSE_TICK_HOOK 0
//使用内存申请失败钩子函数
#define configUSE_MALLOC_FAILED_HOOK 0
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 32 ) //可使用的最大优先级
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 ) //是128字,并非字节 即128*4个字节,堆栈大小以字为单位
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 0
#define configUSE_16_BIT_TICKS 0 //系统节拍计数器变量数据类型,1表示为16位无符号整形,0表示为32位无符号整形
#define configIDLE_SHOULD_YIELD 1 //1:空闲任务放弃CPU使用权,给其他同优先级的用户任务 2:空闲优先级和其他优先级相同。避免2,多使用1
#define configUSE_TIME_SLICING 1 //时间片调度,当优先级相同时执行
#define configUSE_QUEUE_SETS 0 //队列 为1开启,为0关闭
#define configUSE_TASK_NOTIFICATIONS 1 //开启任务通知功能,默认开启
#define configUSE_MUTEXES 0 //互斥信号量开关
#define configUSE_RECURSIVE_MUTEXES 0 //使用递归互斥信号量
#define configUSE_COUNTING_SEMAPHORES 0 //为1时使用计数信号量
/* 设置可以注册的信号量和消息队列个数 */
#define configQUEUE_REGISTRY_SIZE 10
#define configUSE_APPLICATION_TASK_TAG 0
/*****************************************************************
FreeRTOS与内存申请有关配置选项
*****************************************************************/
//支持动态内存申请
#define configSUPPORT_DYNAMIC_ALLOCATION 1
//支持静态内存
#define configSUPPORT_STATIC_ALLOCATION 0
/*
* 大于0时启用堆栈溢出检测功能,如果使用此功能
* 用户必须提供一个栈溢出钩子函数,如果使用的话
* 此值可以为1或者2,因为有两种栈溢出检测方法 */
#define configCHECK_FOR_STACK_OVERFLOW 0
/********************************************************************
FreeRTOS与运行时间和任务状态收集有关的配置选项
**********************************************************************/
//启用运行时间统计功能
#define configGENERATE_RUN_TIME_STATS 0
//启用可视化跟踪调试
#define configUSE_TRACE_FACILITY 0
/* 与宏configUSE_TRACE_FACILITY同时为1时会编译下面3个函数
* prvWriteNameToBuffer()
* vTaskList(),
* vTaskGetRunTimeStats()
*/
/********************************************************************
FreeRTOS与协程有关的配置选项
*********************************************************************/
//启用协程,启用协程以后必须添加文件croutine.c
#define configUSE_CO_ROUTINES 0
//协程的有效优先级数目
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/***********************************************************************
FreeRTOS与软件定时器有关的配置选项
**********************************************************************/
//启用软件定时器
#define configUSE_TIMERS 0
//软件定时器优先级
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1)
//软件定时器队列长度
#define configTIMER_QUEUE_LENGTH 10
//软件定时器任务堆栈大小
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2)
/*
* 某些运行FreeRTOs的硬件有两种方法选择下一个要执行的任务:
*
* 通用方法和特定于硬件的方法(以下简称"特殊方法")。
* 通用方法:
* 1.configUSE_PORT_OPTIMISED_TASK_SELECTION为О或者硬件不支持这种特殊方法。
* 2.可以用于所有FreeRTOS支持的硬件
* 3.完全用c实现,效率略低于特殊方法。
* 4.不强制要求限制最大可用优先级数目
* 特殊方法:
* 1.必须将configUSE_PORT_OPTIMISED_TASK_SELECTION设置为1。
* 2.依赖一个或多个特定架构的汇编指令(一般是类似计算前导零[CLZ]指令)。
* 3.比通用方法更高效
* 4.一般强制限定最大可用优先级数目为32
* 一般是硬件计算前导零指令,如果所使用的,MCU没有这些硬件指令的话此宏应该设置为0 !
*/
#define configUSE_PORT_OPTIMISED_TASK SELECTION 1
/*
* configUSE_TICKLESS_IDLE
* 置1:使能低功耗tickless模式;置0:保持系统节拍(tick)中断一直运行
* 假设开启低功耗的话可能会导致下载出现问题,因为程序在睡眠中,可用以下办法解决
* 下载方法:
* 1.将开发版正常连接好
* 2.按住复位按键,点击下载瞬间松开复位按键
*
* 1.通过跳线帽将BO0T 0接高电平(3.3v)
* 2.重新上电,下载
* 1.使用FlyMcu擦除一下芯片,然后进行下载STMISP ->清除芯片(z)
*
*/
#define configUSE_TICKLESS_IDLE 0
/*配置必要的声明*/
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler
#define INCLUDE_xTaskGetSchedulerState 1
/************************************************************
FreeRTOS可选函数配置选项
************************************************************/
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTimerPendFunctionCall 0
//#define INCLUDE_xTaskGetCurrentTaskHandle 1
//#define INCLUDE_uxTaskGetStackHighWaterMark 0
//#define INCLUDE_xTaskGetIdleTaskHandle 0
/******************************************************************
FreeRTOS与中断有关的配置选项
******************************************************************/
#ifdef __NVIC_PRIO_BITS
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4
#endif
//中断最低优先级
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
//系统可管理的最高中断优先级,
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 //5指 中断优先级 0~5不被管控,中断5~15被freertos管控
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) /* 240 */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* This is the value being used as per the ST library which permits 16
priority values, 0 to 15. This must correspond to the
configKERNEL_INTERRUPT_PRIORITY setting. Here 15 corresponds to the lowest
NVIC value of 255. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15
#endif /* FREERTOS_CONFIG_H */
修改stm32f10x_it.c
1.添加头文件
/*引入FreeRTOS文件*/
#include "FreeRTOS.h"//引入FreeRTOS文件
#include "task.h"//引入task.h文件
2.注释:因为FreeRTOS.h已经有定义,要用FreeRTOS里的了,如果不替换,会报重复定义的错。
3.添加内容:在SysTick_Handler(void)函数中添加内容
/**
* @brief This function handles SysTick Handler.
* @param None
* @retval None
*/
void SysTick_Handler(void)
{
if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//如果开启了调度
{
xPortSysTickHandler();
}
}
编译:无警告,无问题
测试
FreeRTOS闪烁第一颗小灯
main.c
#include "stm32f10x.h" // Device header
#include "LED.h"
#include "FreeRTOS.h"
#include "task.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
LED_Init();
//创建开始任务
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 start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1_ON();
vTaskDelay(1000);
LED1_OFF();
vTaskDelay(1000);
}
}
现象便是小灯1s一次的闪烁。
注意:测试小灯闪烁仅仅是在上面创建好的FreeRTOS模板中的main.c代码中加了代码而已。
完整FreeRTOS模板及小灯闪烁代码链接:
小灯闪烁及FreeRTOS动态及静态创建任务工程模板以及点灯源码
完结 ------------------------------------------------------------------ 撒花
声明:仅供学习使用