一、概念
(1)任务(线程):根据功能的不同,将一个系统分割成一个个独立且无法返回的函数,这个函数就被称为任务
(2)任务栈:静态创建的任务保存在栈中
(3)TCB:任务控制块,保存了一个任务节点
(4)任务就绪列表:初始化的一个列表数组,每个数组元素的列表可以保存多个任务列表项
(5)任务调度器:实现任务切换,从就绪列表中找到任务优先级最高的任务执行
(6)临界段:执行的时候不能被中断的代码段,实际就是中断的开关控制
(7)空闲任务:在CPU空闲时才会运行的任务
(8)阻塞延时:任务调用此延时函数后,任务会被剥离CPU使用权,然后进入阻塞状态,直到延时结束,任务重新获取CPU使用权才可以继续运行
(9)时间片:同一优先级下的多个任务,轮流享有CPU使用权,享有CPU的时间叫做时间片
(10)free rtos官网
二、移植
(1)一级文件夹介绍
FreeRTOS:freertos系统文件夹
FreeRTOS-Plus:第三方组件
(2)二级文件夹
Demo:官方例程
License:放置开源协议文件
Source:系统源码文件(重要)
(3)三级文件夹
include:头文件
portable:硬件接口文件
.c:源文件
(4)在STM32项目下创建freertos文件夹,然后在文件夹下创建inc、src、port文件夹
(5)将FreeRTOS源码目录下的FreeRTOS/Source/include文件夹下的.h头文件全部复制到STM32项目的freertos/inc文件夹下
(6)将FreeRTOS源码目录下的FreeRTOS/Source文件夹下的.c源文件全部复制到STM32项目的freertos/src文件夹下
(7)将FreeRTOS源码目录下的FreeRTOS/Source/portable文件夹下的MemMang和RVDS文件夹复制到STM32项目的freertos/port文件夹下,其中MemMang文件夹下是不同的内存管理文件,一般选择heap_4.c文件,RVDS/ARM_CM3文件夹下存放的是单片机m3内核,不同单片机根据不同内核进行选择
(8)打开STM32项目,创建分组,将freertos的.c源文件添加进项目中,.h头文件路径添加到魔术棒中
(9)复制freertos源码的Demo文件夹下找到对应的单片机和编译器文件夹,将下边的FreeRTOSConfig.h文件复制到项目的头文件文件夹中
(10)FreeRTOSConfig.h配置文件
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/**
* 基础配置
*/
#define configUSE_PREEMPTION 1 //1使用抢占式调度器 0使用协作式调度器(时间片)
#define configUSE_TIME_SLICING 1 //使能时间片调度
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 //任务选择方法,0通用方法 1优化方法,一般为计算前导零[CLZ]指令
#define configUSE_TICKLESS_IDLE 0 //1进入低功耗模式,下载代码可能会出错,0保持系统节拍(tick)中断一直运行
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 ) //定义系统时钟
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) //系统节拍中断频率,即1s中断的次数
#define configMAX_PRIORITIES ( 32 ) //可使用的最大优先级
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 ) //空闲任务栈大小
#define configMAX_TASK_NAME_LEN ( 16 ) //任务名字最大长度
#define configUSE_16_BIT_TICKS 0 //系统节拍计数器变量数据类型,1表示16位无符号整型,0表示32位无符号整型
#define configIDLE_SHOULD_YIELD 1 //1表示空闲任务会放弃CPU使用权给其他同优先级的任务
#define configUSE_QUEUE_SETS 0 //1表示使能队列集合
#define configUSE_TASK_NOTIFICATIONS 1 //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
/*
* 内存申请相关配置
*/
#define configSUPPORT_DYNAMIC_ALLOCATION 1 //支持动态内存申请
#define configSUPPORT_STATIC_ALLOCATION 0 //支持静态内存
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) ) //系统所有总的堆大小
/*
* 钩子函数相关的配置
*/
#define configUSE_IDLE_HOOK 0 //1使用空闲钩子 0忽略空闲钩子 freertos规定了函数名,需要用户自己实现void vApplicationIdleHook(void)
#define configUSE_TICK_HOOK 0 //1使用时间片钩子 0忽略时间片钩子 freertos规定了函数名,需要用户自己实现void vApplicationTickHook(void)
#define configUSE_MALLOC_FAILED_HOOK 0 //1使用内存申请失败钩子函数
#define configCHECK_FOR_STACK_OVERFLOW 0 //1/2表示使用堆栈溢出检测功能 要使用此功能用户需要提供一个栈溢出钩子函数
/*
* 运行时间和任务状态收集的配置
*/
#define configGENERATE_RUN_TIME_STATS 0 //运行时间统计功能
#define configUSE_TRACE_FACILITY 0 //可视化跟踪调试功能
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
/*
* 协程有关的配置
*/
#define configUSE_CO_ROUTINES 0 //协程启用状态位,启动协程必须添加croutine.c文件
#define configMAX_CO_ROUTINE_PRIORITIES (2) //协程的有效优先级数目
/*
* 软件定时器相关配置
*/
#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) //软件定时器的任务堆栈大小
/*
* 可选配置,是否编译对应的函数
*/
#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
/*
* 中断相关配置
*/
#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
/* This is the raw value as per the Cortex-M3 NVIC. Values can be 255*/
#define configKERNEL_INTERRUPT_PRIORITY 255
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!*/
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */
/* 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
#define xPortPendSVHandler PendSV_Handler //挂起中断,进行任务切换
#define vPortSVCHandler SVC_Handler //实现跳转到第一个任务的中断
#endif /* FREERTOS_CONFIG_H */
(11)打开stm32f103x_it.c文件,注释掉已经实现的中断函数PendSV_Handler和SVC_Handler,修改SysTick_Handler内容为以下
extern void xPortSysTickHandler(void);
void SysTick_Handler(void)
{
#if (INCLUDE_xTaskGetSchedulerState == 1)
if( xTaskGetSchedulerState() != taskSCHEDULER_NOT_SATRTED)
{
#endif
xPortSysTickHandler();
#if (INCLUDE_xTaskGetSchedulerState == 1)
}
#endif
}