1. 下载freertos源码FreeRTOS,准备一个stm32空工程。

  2. 解压后,FreeRTOS包含以下文件夹

​ demo:一些移植好的历程,包括stm32f103等,

​ license:略

source:源码,包括include(一些头文件),和portable(和编译器密切相关的文件,keil环境用RVDS)

  1. 将source下以.c结尾的文件移植到我们工程下面新建的src文件夹中,

    将portable下MemMang文件夹和RVDS文件夹下cm3文件夹移植到我们工程下面新建的prot文件夹中,

    将include文件夹移植到我们工程文件夹下。

  1. 拷贝freeRTOSConfig.s(demo工程下)到我们工程下

  2. 添加源码到工程组文件夹

  1. 指定头文件路径,主要是include文件夹,port文件夹和FreeRTOSConfig.h文件,

FreeRTOSConfig.h文件主要内容

断言, freertos定义了一些断言接口

1
2
#define vAssertCalled(char,int) printf("Error:%s,%d\r\n",char,int)
#define configASSERT(x) if((x)==0) vAssertCalled(__FILE__,__LINE__)

__FILE__, __LINE__是c语言几种特殊定义,__FILE__指正在编译文件的文件名, __LINE__指正在编译文件的行号。

抢占式,configUSE_PREEMPTION,高优先级任务就绪后,立刻抢占cpu使用

  • 时间片调度,configUSE_TIME_SLICING,置1时,系统节拍中断时运行优先级最高的任务,相同优先级任务互相切换。置0时,相同优先级任务不切换,执行完高优先级任务再切换。
  • 选择下一个任务,configUSE_PORT_OPTIMISED_TASK_SELECTION
    • 通用方法(软件),扫描就绪链表,完全由c实现,不依赖于硬件
    • 特殊方法(硬件),依赖于汇编指令(类似CLZ前导零指令,M3,M4,M7中有),受限于32位寄存器,导致只能用32个优先级

任务通知 configUSE_TASK_NOTIFICATIONS

​ 官方说明,使用任务通知,会比使用信号量更高效,

FreeRTOS 官方说明:Unblocking an RTOS task with a direct notification is 45% faster and uses less RAM than unblocking a task with a binary semaphore.

空闲钩子函数 configUSE_IDLE_HOOK

执行到空闲任务时,决定是否跳转到对应函数执行。freertos 规定了这个函数的名字和参数,void vApplicationIdleHook(void),我们可以增加他的内容。

软件定时器 configUSE_TIMERS

不依赖于硬件,理论上可以配置无限个,实际上由我们配置的configTIMER_QUEUE_LENGTH数量决定。

可选函数配置选项

如下,定义了INCLUDE_xabcdefg这个宏为一时,才能使用xabcdefg这个函数接口

1
2
3
4
5
6
7
8
9
10
#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

中断相关

中断最低优先级,configLIBRARY_LOWEST_INTERRUPT_PRIORITY ,stm32中断优先级有四位,最低是15。这个优先级是用来配置SYstick和pendsv的。

系统可管理的最高中断优先级,configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY,这是通过配置basepri寄存器实现的。如果这个值配置成5,那么理论上中断优先级位于0,1,2,3,4的中断是不受freertos管理的,位于5及5之上的可以被freertos使用basepri寄存器屏蔽。实际上这还和中断优先级分组有关,详见STM32 BASEPRI的作用

configMAX_SYSCALL_INTERRUPT_PRIORITY:让 configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 向左偏移四位,因为basepri高四位有效

除了basepri外,还有另外两个中断屏蔽寄存器:

名字 功能描述
PRIMASK 这是个只有单一比特的寄存器。 在它被置 1 后,就关掉所有可屏蔽的异常, 只剩下 NMI 和硬 FAULT可以响应。它的缺省值是 0,表示没有关中断。
FAULTMASK 这是个只有 1 个位的寄存器。当它置 1 时,只有 NMI 才能响应,所有其它的 异常,甚至是硬 FAULT,也通通闭嘴。它的缺省值也是 0,表示没有关异 常。
BASEPRI 这个寄存器最多有 9 位( 由表达优先级的位数决定)。它定义了被屏蔽优先 级的阈值。当它被设成某个值后,所有优先级号大于等于此值的中断都被关 (优先级号越大,优先级越低)。但若被设成 0,则不关闭任何中断, 0 也是 缺省值。

configUSE_TRACE_FACILITY,用于FreeRTOS可视化调试软件Tracealyzer。不用systemview了。

FreeRTOSConfig.h文件修改部分

增加对于开发板的头文件,增加对printf函数的支持,对很多宏定义可以选择性的打开或关闭。

stm32f10x_it.c文件修改部分

心跳♥——systick,port中已经实现了systick的配置(vPortSetupTimerInterrupt)

,实现了定时器增加函数(xPortSysTickHandler),我们只需要完成对systick中断函数的配置即可。如下。

1
2
3
4
5
6
7
8
9
10
11
extern void xPortSysTickHandler(void);
void SysTick_Handler(void)
{
#if (INCLUDE_xTaskGetSchedulerState == 1) //这个宏在前文中定义过
if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
#endif
xPortSysTickHandler();
#if (INCLUDE_xTaskGetSchedulerState == 1)
}
#endif
}

修改main.c

引用 FreeRTOS.h, task.h 头文件