1395 字
7 分钟
ChibiOS/RT 系统管理与调度器
调度器配置
ChibiOS/RT 的调度器行为通过 chcfg.h 中的宏配置。这些配置在编译时确定,直接影响系统性能和资源占用。
优先级数量
#define CH_CFG_NUM_PRIORITIES 32- 默认值通常为 32,可按需调整
- 增加优先级数量会增加内核 RAM 占用
- 每增加 8 个优先级,约增加 256 字节 RAM
轮询时间片
#define CH_CFG_TIME_QUANTUM 20- 同优先级线程的时间片长度(单位:tick)
- 设为 0 表示禁用时间片轮转,仅使用时间片让出
- 建议值:10-100 tick
线程额外栈空间
#define CH_CFG_THREAD_EXTRA_STACK 128- 为每个线程额外分配的栈空间(字节)
- 用于存放线程局部存储、调试信息等
内核堆大小
#define CH_CFG_HEAP_SIZE (1024 * 2)- 动态内存分配使用的堆大小
chThdCreateFromHeap从该堆分配内存
其他关键配置
/* 虚拟定时器数量 */#define CH_CFG_VIRTUAL_TIMERS 16
/* 消息队列大小 */#define CH_CFG_MSG_CACHE_SIZE 2
/* 空闲钩子(用于低功耗) */#define CH_CFG_IDLE_ENTER_HOOK() idle_enter_hook()#define CH_CFG_IDLE_LEAVE_HOOK() idle_leave_hook()系统管理接口
系统锁与解锁
系统锁用于保护临界区,防止调度器抢占:
void critical_section(void) { chSysLock(); /* 锁定调度器,关闭中断 */
/* 临界区代码 */ volatile uint32_t count = 0; for (int i = 0; i < 1000; i++) { count++; }
chSysUnlock(); /* 解锁调度器,恢复中断 */}chSysLock/chSysUnlock 的作用:
| 操作 | 效果 |
|---|---|
chSysLock() | 禁用可屏蔽中断,阻止调度 |
chSysUnlock() | 恢复可屏蔽中断,允许调度 |
chSysLockFromISR() | 在 ISR 中锁定系统 |
chSysUnlockFromISR() | 在 ISR 中解锁系统 |
CPU 使用率测量
/* 启用 CPU 使用率测量(需配置 CH_CFG.GetCurrentMethodHook) */void sysinit(void) { /* 通常在空闲线程中调用 */}
/* 获取 CPU 使用率(百分比,0-100) */void idle_hook(void) { uint32_t usage = chSysGetCPUUsage(); /* usage 为 0-100 的整数百分比 */ if (usage > 80) { /* CPU 负载过高警告 */ }}空闲钩子
空闲钩子在空闲线程中周期性调用,可用于低功耗管理:
#define CH_CFG_IDLE_ENTER_HOOK() do { \ __WFI(); /* 进入低功耗等待 */ \} while(0)
#define CH_CFG_IDLE_LEAVE_HOOK() do { \ /* 从低功耗唤醒 */ \} while(0)功耗管理
结合空闲钩子实现动态功耗管理:
static void idle_enter_hook(void) { /* 关闭外设时钟 */ RCC->AHB1ENR &= ~RCC_AHB1ENR_GPIOAEN;
/* 进入 Sleep 模式 */ SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; __WFI();}
static void idle_leave_hook(void) { /* 恢复外设时钟 */ RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;}运行时专家模式
ChibiOS/RT 提供多种运行时诊断工具,帮助开发者调试和优化系统。
调试寄存器
启用内核调试器可检测运行时错误:
#define CH_CFG_USE_KERNEL_DEBUG TRUE检测的错误包括:
- 从非线程上下文调用线程 API
- 在 ISR 中调用非 ISR 安全的 API
- 无效的线程状态转换
栈溢出检查
#define CH_CFG_USE_STACKCHECK TRUE启用后,每次上下文切换时检查线程栈是否溢出工作区边界。栈溢出是嵌入式系统中最常见的 bug 之一,建议开发阶段始终启用。
栈使用测量
/* 获取线程栈使用量(已用字节) */thread_t *tp = chThdGetSelfX();size_t used = chThdGetStackUsed(tp);
/* 获取线程栈空间总量 */size_t total = chThdGetStackSize(tp);
/* 计算使用百分比 */uint32_t percent = (used * 100) / total;也可以统计所有线程的栈使用情况:
void check_all_stacks(void) { thread_descriptor_t *tdp;
/* 遍历所有已注册线程 */ for (tdp = chRegFirstThread(); tdp != NULL; tdp = chRegNextThread(tdp)) { size_t used = chThdGetStackUsed(tdp->get_stackp()); printf("Thread: %s, Stack used: %u bytes\n", tdp->get_name(), used); }}性能测量钩子
#define CH_CFG_USE_performance_hook TRUE
/* 上下文切换钩子 */void ctxsw_hook(thread_t *ntp, thread_t *otp) { /* ntp: 即将运行的线程 */ /* otp: 刚被换出的线程 */ /* 可用于记录切换频率、统计等 */}SMP 系统管理
多核配置
#define CH_CFG_SMP_NESTED_ENABLE FALSE#define CH_CFG_SMP_NUM_THREADS 4#define CH_CFG_SMP_REQUIRED_CORES 2CH_CFG_SMP_NUM_THREADS:SMP 系统中线程总数上限CH_CFG_SMP_REQUIRED_CORES:必须在线的核心数
OS 实例
每个核心需要独立的 OS 实例,包含自己的调度器和内核数据结构:
#include "ch.h"
/* 为每个核心定义 OS 实例 */static OS_INSTANCE(os_core0);static OS_INSTANCE(os_core1);
/* 核心 0 的主函数 */void core0_main(void) { os_instance_init(&os_core0); os_instance_set_active(true);
/* 创建核心 0 的线程 */ chThdCreateStatic(waThread0, sizeof(waThread0), NORMALPRIO, thread0_func, NULL);
chThdExit();}
/* 核心 1 的主函数 */void core1_main(void) { os_instance_init(&os_core1); os_instance_set_active(true);
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, thread1_func, NULL);
chThdExit();}核心 ID
/* 获取当前核心 ID */syscoreid_t core_id = os_instance_get_core_id();
/* 根据核心 ID 执行不同逻辑 */void per_core_init(void) { syscoreid_t id = os_instance_get_core_id(); if (id == 0) { /* 主核心初始化 */ } else { /* 从核心初始化 */ }}Tick 处理
频率配置
#define CH_CFG_ST_RESOLUTION 16#define CH_CFG_ST_FREQUENCY 1000 /* 1 kHz tick */CH_CFG_ST_FREQUENCY:系统 tick 频率(Hz)- 典型值:1000(1ms 分辨率)或 10000(100μs 分辨率)
虚拟定时器处理
虚拟定时器基于系统 tick 实现,用于超时管理:
/* 定义虚拟定时器 */static virtual_timer_t vt1;
/* 定时器回调函数 */static void vt1_callback(void *arg) { /* 超时处理 */ LED_Toggle();}
/* 启动定时器:500ms 后触发 */void start_timer(void) { chVTSet(&vt1, MS2ST(500), vt1_callback, NULL);}
/* 取消定时器 */void stop_timer(void) { chVTReset(&vt1);}延迟超前处理
ChibiOS/RT 支持延迟超前处理(Deferred Timeout Processing),在 tick ISR 中不直接处理超时,而是标记后延迟到线程上下文处理:
#define CH_CFG_USE_TM TRUE /* 启用时间管理 */这种机制减少了中断延迟,适用于超时处理较复杂或需要调用线程安全 API 的场景。
总结
ChibiOS/RT 的调度器和系统管理机制提供了丰富的配置选项和诊断工具。合理配置优先级数量、时间片、堆大小等参数,结合 CPU 使用率测量和栈检查,可以构建出高效、可靠的嵌入式实时系统。SMP 支持和虚拟定时器则为更复杂的应用场景提供了扩展能力。
部分信息可能已经过时