系统主要的文件:
list.c: FreeRTOS内核调度大量使用了列表(list)和列表项(list item)数据结构。对于FreeRTOS内核来说,列表就是它最基础的部分。
queue.c:队列相关的函数。
task.c: 在task.c中,定义了一些静态列表变量,其中有就绪、阻塞、挂起列表,例如当某个任务处于就绪态时,调度器就将这个任务TCB的xStateListItem列表项挂接到就绪列表。事件列表项也与之类似,当队列满的情况下,任务因入队操作而阻塞时,就会将事件列表项挂接到队列的等待入队列表上。
Port.c: 硬件接口代码存储在这里面
内核控制的一些功能需要移植层提供,为了方便移植,这些API函数用宏来实现,比如上下文切换、进入和退出临界区、禁止和使能可屏蔽中断。内核控制函数还包括启动和停止调度器、挂起和恢复调度器以及用于低功耗模式的调整系统节拍函数。
它里面的宏主要调用 -》task.c中的函数(内核API函数)
Heap.c:官方定义的几种内存管理的方式,
FreeRtos.h:主要是根据freeRtosconfig中的定义来开启一些宏或者结构体。
这里面大都是以#ifndef portSET_INTERRUPT_MASK_FROM_ISR
#define portSET_INTERRUPT_MASK_FROM_ISR() 0
#endif
这种形式。
FreeRtosconfig.h: FreeRTOS内核是高度可定制的,使用配置文件FreeRTOSConfig.h进行定制。每个FreeRTOS应用都必须包含这个头文件,用户根据实际应用来裁剪定制FreeRTOS内核。这个配置文件是针对用户程序的,而非内核,因此配置文件一般放在应用程序目录下,不要放在RTOS内核源码目录下。
#define configUSE_PREEMPTION 1/*:为1时RTOS使用抢占式调度器,为0时RTOS使用协作式调度器(时间片)。注:在多任务管理机制上,操作系统可以分为抢占式和协作式两种。协作式操作系统是任务主动释放CPU后,切换到下一个任务。任务切换的时机完全取决于正在运行的任务。
#define configUSE_IDLE_HOOK 0/*设置为1使用空闲钩子(Idle Hook类似于回调函数),0忽略空闲钩子。
当RTOS调度器开始工作后,为了保证至少有一个任务在运行,空闲任务被自动创建,占用最低优先级(0优先级)。对于已经删除的RTOS任务,空闲任务可以释放分配给它们的堆栈内存。因此,在应用中应该注意,使用vTaskDelete()函数时要确保空闲任务获得一定的处理器时间。除此之外,空闲任务没有其它特殊功能,因此可以任意的剥夺空闲任务的处理器时间。应用程序也可能和空闲任务共享同个优先级。空闲任务钩子是一个函数,这个函数由用户来实现,RTOS规定了函数的名字和参数,这个函数在每个空闲任务周期都会被调用
configUSE_TICK_HOOK
设置为1使用时间片钩子(Tick Hook),0忽略时间片钩子。
注:时间片钩子函数(Tick Hook Function)
时间片中断可以周期性的调用一个被称为钩子函数(回调函数)的应用程序。时间片钩子函数可以很方便的实现一个定时器功能。
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 )/* 系统CPU频率,单位是Hz */配置此值是为了正确的配置系统节拍中断周期
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )/* 系统SYSTEM TICK每秒钟的发生次数, 数值越大系统反应越快,但是CPU用在任务切换的开销就越多 */
#define configMAX_PRIORITIES ( 5 )/* 系统任务优先级数。5 说明任务有5级优先度。这个数目越大耗费RAM越多 */
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 )/* 系统最小堆栈尺寸,注意128不是128字节,而是128个入栈。比如ARM32位,128个入栈就是512字节 */ (任务创建时用了,感觉类似于一个单位)
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) )/* 系统可用内存。仅在你使用官方下载包中附带的内存分配策略时,才有可能用到此值。每当创建任务、队列、互斥量、软件定时器或信号量时,RTOS内核会为此分配RAM.一般设成除了操作系统和你的程序所用RAM外的最大RAM。 比如20KRAM你用了2K,系统用了3K,剩下15就是最大HEAP 尺寸。你可以先设小然后看编译结果往大里加*/
#define configMAX_TASK_NAME_LEN ( 16 )/*调用任务函数时,需要设置描述任务信息的字符串,这个宏用来定义该字符串的最大长度。这里定义的长度包括字符串结束符’\0’。
#define configUSE_TRACE_FACILITY 0/* 设置成1表示启动可视化跟踪调试,会激活一些附加的结构体成员和函数。
#define configUSE_16_BIT_TICKS 0/*
定义系统节拍计数器的变量类型,即定义portTickType是表示16位变量还是32位变量。
定义configUSE_16_BIT_TICKS为1意味着portTickType代表16位无符号整形,定义configUSE_16_BIT_TICKS为0意味着portTickType代表32位无符号整形。
#define configIDLE_SHOULD_YIELD 1/
简单理解以下就是和空闲 TASK同样优先级的任务执行情况。设置configIDLE_SHOULD_YIELD为0将阻止空闲任务为用户任务让出CPU,直到空闲任务的时间片结束。这确保所有处在空闲优先级的任务分配到相同多的处理器时间,但是,这是以分配给空闲任务更高比例的处理器时间为代价的。默认设成1,对系统影响不大。
configUSE_CO_ROUTINES
主要用于资源发非常受限的嵌入式系统(RAM非常少),通常不会用于32位微处理器。 在当前嵌入式硬件环境下,不建议使用协程,FreeRTOS的开发者早已经停止开发协程。
#define configKERNEL_INTERRUPT_PRIORITY 255/*
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /*
参考文件:
http://blog.csdn.net/zhzht19861011/article/details/50134883
http://blog.sina.com.cn/s/blog_7fbb077f0102wrb1.html
http://blog.csdn.net/dyllove98/article/details/9271409
官方文档http://www.freertos.org/FreeRTOS_Support_Forum_Archive/July_2013/freertos_STM32F2_4_vs._vPortValidateInterruptPriority_8550890.html
If you want a simplified priority of 8, then you need to set configMAX_SYSCALL_INTERRUPT_PRIORITY to 0x8n, where n can be any value, but by convention, and for future proofing in case future STM32 parts implement more priority bits, should be set to f. Therefore, the priority you want is 0x8f.
“the code app-faults at "svc 0" in vPortStartFirstTask”
Presumably a hard fault because you are attempting a call to effectively a synchronous interrupt while simultaneously having that interrupt masked out.
大体意思就是,想要设置简化优先级为8 ,configMAX_SYSCALL_INTERRUPT_PRIORITY就要设置为0x8n,n可以为任何值,但是为了以后更多的优先级设置,通常设置为
f。
RTOS内核通过写configMAX_SYSCALL_INTERRUPT_PRIORITY的值到BASEPRI寄存器的方法创建临界区。中断优先级0(具有最高的逻辑优先级)不能被BASEPRI寄存器屏蔽,因此,configMAX_SYSCALL_INTERRUPT_PRIORITY绝不可以设置成0。
(2)191相当于(0xBF也即优先级11)
configMAX_SYSCALL_INTERRUPT_PRIORITY用来设置可以在中断服务程序中安全调用FreeRTOS API函数的最高中断优先级
也就是说RTOS中断嵌套方案将可用的中断优先级分成2组:会被RTOS临界区覆盖的和永远不会被覆盖的所以这些是一直被使能的。configMAX_SYSCALL_INTERRUPT_PRIORITY设置值是这两组的边界值。 (RTOS内核使用Cortex-M内核的BASEPRI寄存器来实现临界区(注:BASEPRI为优先级屏蔽寄存器,优先级数值大于或等于该寄存器的中断都会被屏蔽,优先级数值越大,逻辑优先级越低,但是为零时不屏蔽任何中断)。这允许RTOS内核可以只屏蔽一部分中断,因此可以提供一个灵活的中断嵌套模式 那些需要在中断调用时保护的API函数,FreeRTOS使用寄存器BASEPRI实现中断保护临界区。当进入临界区时,将寄存器BASEPRI的值设置成configMAX_SYSCALL_INTERRUPT_PRIORITY,当退出临界区时,将寄存器BASEPRI的值设置成0)
故在中断优先级为0~10的中断,表示FreeRTOS无法禁止这个中断,均不会被内核延迟,并且可嵌套但不能调用API函数。 (高于这个级别的中断都不会被RTOS接管,即使在临界区也不能完全禁止中断,也不会因为执行FreeRtos而被延时)
在11~15之间的中断程序可以在中断服务程序中安全的调用FreeRTOS API函数 (以FromISR结尾的API函数)
注意:在之前版本的FreeRtos 中即使你在一个高于configMAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断中调用的FreeRTOS的ISR API,代码往往也是可以执行的,只是可能带来优先级翻转,数据错误这样的潜在危险.
在新的版本中,FreeRTOS加入了vPortValidateInterruptPriority()这个函数来检查当前ISR的优先级是否合法,这里检查的结果是UART的中断优先级高于了configMAX_SYSCALL_INTERRUPT_PRIORITY,所以xSemaphoreGiveFromISR()成了一个非法调用,然后Assert Failed之后代码就停住了.
发现8.2.3版本bug任务创建的时候,句柄参数尽量不要直接设置为NULL,有可能在时间切换上出现问题(暂时没遇到,尽量注意一下)
在启动FreeRTOS的调度器之前必须先设定好系统的中断优先级分组. 一般设置为NVIC_PriorityGroup_4
,