配置RTX v5
“RTX_Config.h”文件。定义了CMSIS-RTOS RTX的配置参数,每一个使用CMSIS-RTOS RTX内核的项目的都必须有这个文件。下面几节将详细解释各个配置选项。
“RTX_Config文件”。包含空闲任务(osRtxIdleThread) 和异常报告函数(osRtxErrorNotify) 的默认实现。他们可以在用户代码中被重新定义。
配置文件使用 配置向导(Configuration Wizard Annotations)。窗口下方的注释让图形化界面操作更加友好。下图显示了在MDK5.29里打开的配置向导界面:
RTX_Config.h内的配置向导
1、系统配置
System Configuration
系统配置包括全局动态内存池、时钟节拍、ISR事件缓冲区和使能循环调度的任务调度算法 的系统层面的配置。
系统配置选项:
参数解释:
1.1 时钟节拍 与 时间片
时钟节拍: CPU以一定的频率进行中断,可以看成操作系统的心跳。利用时间节拍可以做到一些任务的时间管理,延时、定时、超时检测、时间片轮转调度。即时钟节拍的周期是系统总线周期的若干倍。时钟节拍频率越高,对系统的负担就越大。
时间片: 循环调度时,线程获得一个时间片的运行时间。也就是在同一优先级下,每个任务运行的时间,这个时间是 时钟节拍 的倍数。时间片过长,线程切换不及时,会造成资源利用率低;时间片过短,会造成频繁的任务切换,导致系统开销变大。
1.2 循环调度算法
Round-Robin Thread Switching
RTX5 可以使用 循环(Round-Robin)调度算法 来处理多任务切换。Round-Robin 可以让多个 相同优先级 的线程 近似同时(quasi-parallel) 执行。
线程并不是同时执行的,而是将可用的 CPU 时间轴划分为时间片,一个时间片内只运行一种用户线程(不发生高优先级抢占的情况下)。因为时间片通常很短(只有几毫秒),所以看起来好像线程是同时执行的。
循环调度流程如下:
当线程切换发生时,计数值(tick) 会被赋值为 超时值(timeout value)
执行同一个线程,计数值递减(时钟不为零)
当 计数值 递减至0时,标志这个时间片结束了。如果有其他同优先级的线程已经就绪,系统就会切换到该线程,并再次把 超时值 赋给 计数值。
换句话说就是,一个线程在一个时间片内执行。当前时间片结束时,RTX切换到下一个 优先级相同 且 处于就绪状态 的线程。如果没有其他具有相同优先级的线程准备运行,则继续执行当前运行的线程。
请注意:
当切换到高优先级线程时,计数值(tick) 将被重置为 循环超时值(timeout value)。
是否开启 循环调度 由 #define OS_ROBIN_ENABLE 控制。时间片长度 可在“RTX_Config.h”中使用 #define OS_ROBIN_TIMEOUT 配置
1.3 ISR FIFO队列
ISR FIFO Queue
ISR(Interrupt Service Routines),中断服务函数。
IRQ(Interrupt Request),中断请求
当在中断中调用RTX函数时,系统会把请求类型和可选参数存储到 ISR FIFO 队列缓冲区中,以便在退出中断后进行处理。
当IRQ中断处理(IRQ handler)完成了处理存储在FIFO队列缓冲区中的消息之后,将立即激活调度器。这个缓冲区所需的大小取决于在中断服务函数中调用的函数的数量。osRtxErrorNotify将使用错误代码osRtxErrorISRQueueOverflow来捕获不足的队列大小。
1.4 对象内存使用计数器
Object Memory Usage Counters
对象内存使用计数器有助于评估每种对象类型的最大内存池需求,就像堆栈水印用于线程一样。初始化设置从全局内存池开始。
在启用 对象内存使用计数器 的情况下连续运行应用程序,有助于为每种对象类型引入 对象特定的内存池 。通常,这对于需要功能性安全认证的应用程序是必需的,因为在这种情况下不允许使用全局内存池
2、线程配置
Thread Configuration
RTX5提供了几个参数来配置线程管理功能。
2.1 配置线程数和堆栈空间
Configuration of Thread Count and Stack Space
RTX5内核为每个线程使用一个单独的堆栈空间,并提供了两种定义堆栈需求的方法:
2.1.1、静态分配(Static allocation):
前提条件:结构体 osThreadAttr_t 中的 stack_mem 和 stack_size 成员指定了用于线程堆栈的内存区域。
注意:提供的堆栈内存必须是64位对齐的,即使用uint64_t进行声明。
2.1.2、动态分配(Dynamic allocation):
前提条件:结构体 osThreadAttr_t 是 NULL 或其中成员变量 stack_mem 为空。系统将按以下规则分配内存:
1、如果启用了“对象特定内存分配”,且“用户线程的默认堆栈大小” 不是0,且 osThreadAttr_t 中 stack_size 是0(或 osThreadAttr_t 为 NULL)。那么,将对象存储在 默认堆栈大小 的 对象特定内存池(Object-specific Memory Pool)。
2、如果启用了“对象特定内存分配”,且“ 用户自定义堆栈大小的线程的总堆栈大小 ”不为0,且osThreadAttr_t 中 stack_size 不为0。那么,将对象存储在 用户自定义堆栈大小 的 对象特定内存池
3.如果未启用“对象特定内存分配”,或( osThreadAttr_t 中 stack_size不为0,且“用户自定义堆栈大小的线程的总堆栈大小”为0)或(osThreadAttr_t::stack_size为0,且“具有默认堆栈大小的用户线程数”为0)
那么,将对象存储在 全局内存池。osThreadAttr_t 是 osThreadNew() 的一个参数。
3、栈溢出检查
Stack Overflow Checking
RTX5实现了一个软件堆栈溢出检查(software stack overflow checking),可以捕获堆栈溢出。堆栈(Stack),是用于暂存返回地址和自动变量的空间。堆栈配置不合理可能导致堆栈溢出。是否开启软件堆栈溢出检查由宏定义 OS_STACK_CHECK 决定。
如果检测到堆栈溢出,系统将调用函数 osRtxErrorNotify() ,函数参数为错误代码 osRtxErrorStackUnderflow 。默认情况下,这个函数被实现为一个无限循环,会终止代码执行。
4、堆栈使用水印
Stack Usage Watermark
RTX5在创建线程时使用水印模式(0xCC)初始化线程堆栈。这允许调试器确定每个线程的最大堆栈使用量。它通常在开发期间使用,然后在最终程序中删除。是否开启堆栈水印由宏定义OS_STACK_WATERMARK 决定。
启用此选项将显著增加 osThreadNew() 的执行时间(取决于线程堆栈大小)。
5、线程执行的处理器模式
Processor Mode for Thread Execution
RTX5允许以非特权或特权处理器模式执行线程。处理器模式由 OS_PRIVILEGE_MODE 决定。
在非特权处理模式下,应用软件:
1、只能访问MSR和MRS指令,不能使用CPS指令。
2、无法访问系统计时器、NVIC或系统控制块。
3、可能限制对内存或外设的访问。
在特权处理器模式下,应用程序软件可以使用所有指令并访问所有资源。
6、时钟配置
Timer Configuration
RTX5提供了几个参数来配置计时器管理功能。
6.1 用户定时器线程
User Timer Thread
当一个时间片结束时,函数osRtxTimerThread执行回调函数。完整RTOS系统中的计时器子系统的优先级继承自 osRtxTimerThread 的优先级。这是由 OS_TIMER_THREAD_PRIO 配置的。回调函数的堆栈由 osRtxTimerThread 提供。OS_TIMER_THREAD_STACK_SIZE必须满足具有最高堆栈使用率的回调函数的堆栈要求。
7、Event Flags配置
Event Flags Configuration
RTX5提供了几个参数来配置 事件标志(Event Flags) 功能。
7.1 Event Flags 的对象特定内存分配
Object-specific memory allocation
当使用对象特定内存时,所有 事件标记对象(Event object) 的内存池大小由OS_EVFLAGS_NUM指定。
8、互斥量 对象配置
Mutex Configuration
RTX5提供了几个参数来配置互斥量(Mutex)功能。
8.1 互斥量 的对象特定内存分配
Object-specific Memory Allocation
当使用对象特定内存时,所有 互斥量对象(Mutex object) 的内存池大小由 OS_MUTEX_NUM 指定。
9、信号量 配置
Semaphore Configuration
9.1 信号量 的对象特定内存分配
Object-specific Memory Allocation
当使用对象特定内存时,所有 信号量对象(Semaphore object) 的内存池大小由 OS_SEMAPHORE_NUM 指定。
10、内存池配置
Memory Pool Configuration
10.1 内存池 的对象特定内存分配
Object-specific memory allocation
当使用 对象特定的内存(object-specific memory) 时,所有 内存池对象(MemoryPool) 的数量由 OS_MEMPOOL_NUM 指定。所有内存池的存储总量大小由 OS_MEMPOOL_DATA_SIZE 中配置。
11、消息队列 配置
Message Queue Configuration
11.1 消息队列 的对象特定内存分配
Object-specific memory allocation
当使用对象特定的内存时,所有 消息队列对象( Message Queue objects) 的数量由 OS_MSGQUEUE_NUM 指定。所有队列的总存储容量在 OS_MSGQUEUE_DATA_SIZE 中配置。
12、事件记录器 配置
Event Recorder Configuration