SCP Firmware 为系统控制处理器提供电源、时钟、传感器等管理服务。在其 Framework 中,Module 通过 Event 和 Notification 协作。理解这些消息如何被调度,是阅读 Module 代码的基础。
获取源码:Arm 官方 SCP-firmware 仓库。本文使用
v2.16.0版本。
深入理解 ARM SCP Firmware 的 Event 与 Notification 机制
1、Threading 在这里指什么
本文的threading指 Framework 如何安排 Module 的事件处理工作。当前版本没有为每个 Module 创建独立线程:Framework 在一条事件处理路径上取出消息,调用目标 Module 的回调,待回调返回后再处理下一条。因此,Module 之间主要通过排队的消息协作,而非依赖线程调度器轮流运行。
这种单线程模型并不要求所有工作都同步完成。Module 可以启动一次硬件操作、结束当前回调,待操作完成后通过新事件继续处理。异步的是工作流程,不是同时运行了另一个 Module 线程。
2、主循环如何调度事件
在默认的独立运行模式下,/framework/src/fwk_arch.c进入__fwk_run_main_loop();/framework/src/fwk_core.c中的主循环反复处理待办事件,并在适当时机进入架构层的等待状态:
/* * framework\src\fwk_core.c */voidfwk_process_event_queue(void){for(;;){while(!fwk_list_is_empty(&ctx.event_queue)){process_next_event();}if(!process_isr()){break;}}}noreturnvoid__fwk_run_main_loop(void){for(;;){fwk_process_event_queue();if(fwk_log_unbuffer()==FWK_SUCCESS){fwk_arch_suspend();}}}Framework 维护三个相关队列(见/framework/include/internal/fwk_context.h)):free_event_queue保存可复用的 Event 对象,event_queue保存待分发的普通事件,isr_event_queue保存从中断上下文投递的事件。发送事件时,Framework 将事件内容放入其管理的对象,并依据当前上下文选取队列。队列里存放的是待处理的消息,不是线程或正在执行的任务。
fwk_process_event_queue()先逐条处理普通队列。process_next_event()根据事件的target_id找到目标 Module,调用其process_event()或process_notification();回调返回后,Framework 才取下一条。普通队列清空后,process_isr()每次从 ISR 队列搬入一条事件,再继续处理普通队列。这是 Framework 的事件分发顺序,不代表硬件中断的优先级。
3、中断与事件的边界
单线程不等于没有中断。硬件中断仍可打断主循环;ISR 完成必要的即时处理后,可以投递 Event。中断返回时,被打断的代码继续运行。新投递的 Event 要等主循环调度到它,才会调用目标 Module 的回调。由此,中断中的紧急工作与 Module 中较完整的后续处理分处两个阶段。
普通代码和 ISR 可能访问同一份队列等共享状态,因此仍需同步保护。Framework 在操作空闲事件对象和搬运 ISR 事件等关键位置使用短暂的中断屏蔽。这里需要防范的是主循环与中断之间的并发访问,而非多个 Module 线程之间的竞争。
4、对 Module 开发的影响
一次事件回调会占用主循环,直到它返回。若回调长时间忙等或等待硬件完成,其他 Module 的 Event、Notification 和响应也会随之延后。因此,耗时操作通常应拆成 “启动操作、返回、收到完成事件后继续处理” 几个阶段。
/module/sensor/src/mod_sensor.c的异步读取展示了这种组织方式:驱动读取尚未完成时,请求先以FWK_PENDING表示结果待返回;后续READ_COMPLETE事件到来,再处理结果及延迟响应。整个过程跨越多个事件,但不需要额外的 Sensor 线程。
5、历史演进与运行方式
2019 年的 SCP Firmware 架构演示 介绍过适用于 RTOS 环境的多线程模式。此后,Framework 在 v2.10 版本移除了多线程特性;本文所述版本的 Module Event 由单条事件处理路径串行分发。
/* * change_log.md */SCP-firmware-version2.10============================New features-------------Framework:-Removed multi-threading feature,all platforms are now single threaded There is no longer any thread concept,please see relevant commitsfordetails.-framework:Add fwk_string interface运行环境与 Module 的事件调度是两个不同层次。默认独立运行时,Framework 自己维持永久主循环;启用SCP_ENABLE_SUB_SYSTEM_MODE时,fwk_arch_init()初始化并处理当前待办事件后返回。此后,外层运行环境需要在出现新事件时调用fwk_process_event_queue(),并自行安排等待与唤醒。这种方式可用于将 SCP Firmware 集成到已有的 RTOS 或 TEE 环境,但不会改变 Framework 内部串行处理 Module Event 的方式,参见 框架运行阶段说明:/doc/framework.md。