高通 RCINIT 框架简介
RCINIT:运行控制初始化模块
RCEVT:运行控制事件模块
在基于 QuRT™/REX 的系统中, RCINIT 框架可简化任务的创建和排序,并且可对初始化函数
进行序列化操作。该框架还负责关闭和终止任务,能够确保基于 QuRT/REX 的系统有序关
闭。
RCINIT 框架
定义好初始化函数和任务后,将执行以下动作:
- 定义任务和初始化函数,并使用RCINIT框架提供的结构分配堆栈大小和优先级等属性。
- 排序并同步任务和初始化函数的启动。
- 使用任务和出初始化函数的排序信息有序关闭MPSS 任务,从确保正常关闭。
一、多PD环境中的RCINIT
根据芯片的不同,某些运行于不同核心的进程现在可以组合,然后再同一个核心中运行,例如:音频和MPSS进程运行于同一个Q6核心中。
每个进程现在成为保护域(PD). 多PD支持允许MPSS PD 和音频 PD 在同一个 Hexagon 处理器上运行。
进程域具有独立的地址空间和保护,PD中运行多项任务。
Modem和内核在PD0中运行,音频在PD1中运行。
这些保护功能使得 MPSS PD 和音频PD可以在同一个Hexagon处理器上运行,而从逻辑仿真的角度来看,它们运行与单独的处理器上。
在多 PD 环境中, RCINIT 只对单个 PD 中的启动和关闭操作执行排序,并非跨 PD 进行启动控制。
每个 PD 对应的所有 RCINIT 输入和输出都是独立的。
二、序列化
序列组是一组任务和初始化函数。序列组为启动序列提供粗粒度。任务和初始化函数提供细粒度。
创建任务后,该任务的所有者可配置哪个任务进入哪个序列组。每个组中的任务都是按照逻
辑并行启动的。它们会并行运行并达到同步屏障。之后,这些任务将基于 HLOS 调度程序有
逻辑地运行。指定的 HLOS 优先级用于仲裁 CPU 资源利用。
完成初始化之后,序列组中的任务必须在进入运行循环之前与 RCINIT 框架握手。序列组中的
所有任务在全部执行所需的握手之后会收到启动指示。
所有任务和初始化函数分为八组(第 0 组到第 7 组)。
每个任务(除 rcinit_task 和 rcinit_worker 外)和初始化函数都必须位于其中一个组中。
所有初始化函数都在 rcinit_worker 任务的上下文中执行。它们根据编译时脚本所提供的依赖性
提示按顺序执行。第 0 组首先启动,第 7 组最后启动。
以下是描述任务和初始化函数如何在一个组中工作的序列图
三、添加任务
在创建任务之前,分析代码并确定依赖性,确定组和初始化函数。
例如:
在第 6 组和第 7 组中添加一个任务(最好在第 7 组中),以满足大部分依赖性并减少启动问题。
- 创建一个 SCONS 文件。
- 在 SCONS 文件中填写任务信息。
<build_id>/modem_proc/<your_path>/example.scons
env.AddRCInitTask(
RCINIT_IMG,
{
‘sequence_group’ :‘RCINIT_GROUP_7’ ,
‘thread_name’ :‘example’ ,
‘thread_entry’ :‘example_task’ ,
‘thread_type’ :‘RCINIT_TASK_QURTTASK’ ,
‘stack_size_bytes’ :‘6144’ ,
‘priority_amss_order’ :‘SHARED_DRIVER_SERVICE_PRI’
})
-
确保任务调用 rcinit_handshake_startup()。
-
编译软件。
-
在 rcinit_output_log.txt 中,确认满足依赖性。
该文件所处位置因芯片而异,有时会预先使用编译命令或编译定制作为文件名。如果映像
有多个保护域 (PD),则每个 PD 都有一个输出日志, RCINIT 控制启动顺序。
对于 MSM8909、 MSM8952: modem_proc\scripts\bsp\modem_proc_img\build\MODEM_PROC_IMG_<build_flavor>_rcinit_output_log.txt
SDM450位于: mpss_proc/core/debugtools/rcinit_playbook/build/modem_proc/qdsp6/8953.gen.prod/rcinit_output_log.txt -
刷写软件,并在握手后放置一个断点内联 (rcinit_handshake_startup())。
□ 确保到达该断点。
□ 确保满足所有依赖性。
四、创建初始化函数
example.scons
<build_id>/modem_proc/<your_path>/example.scons
添加以下代码:
if ‘USES_RCINIT’ in env:
RCINIT_IMG = [‘CORE_MODEM’ , ‘CORE_QDSP6_SW’ ]
env.AddRCInitFunc( # Code Fragment in TMC:YES
RCINIT_IMG, # define TMC_RCINIT_INIT_TIMER_TASK_INIT
{
‘sequence_group’ :‘RCINIT_GROUP_0’ , # required
‘init_name’ :‘timer’ , # required, MUST BE UNIQUE
‘init_function’ :‘timer_task_init’ , # required
‘dependencies’ :[‘clk_regime’ ,’ time’ ,]
}
)
五、更改任务的堆栈大小
在 SCONS 文件中,通过更改任务定义中的 stack_size_bytes 字段更改任务的堆栈大小。
- 更改 stack_size_bytes 字段
# <build_id>/modem_proc/<your_path>/example.scons
'stack_size_bytes' :'8192',
- 对于某些 Modem 任务,堆栈大小位于 modem_proc\config\default\modem_task_stksz.csv 中
# modem_proc\datamodem\interface\tasks\build\datacommon_tasks.scons
'stack_size_bytes' : env.subst('$DCC_STKSZ'),
# DCC_STKSZ 在 modem_task_stksz.csv 中定义
六、更改任务的优先级
- 更改 priority_amss_order 字段
# <build_id>/modem_proc/<your_path>/example.scons
'priority_amss_order' :'SLEEP_PRI_ORDER',
# SLEEP_PRI_ORDER 定义于 mpss_proc/config/default/rcinit_task_prio.csv 中
七、任务终止通知
所有由 RCINIT 创建的任务都可以注册终止通知。将终止通知视为软件异常并尽快处理。避免在关闭处理中进行阻断调用。
关闭运行时注册与初始化排序的联系并不紧密。 Qualcomm 建议,通过基于初始化组的 RCINIT框架为任务注册关闭通知。参与任务的硬性要求是必须在关闭处理之后调用rcinit_handshake_term()。将关闭处理视为异常并尽快处理。不得在终止处理中进行阻断调用。
使用以下函数进行注册通知:
void rcinit_register_term_group(
RCINIT_GROUP group,
RCEVT_SIGEX_TYPE type,
RCEVT_SIGEX sigex)
其中:
■ group 参数确定向任务发送终止信号的组。
■ type 参数是保存任务接收的信号类型的变量。
■ sigex 参数是要发送进行终止处理的信号掩码。
group 编号配置与启动时相同。
八、组超时处理
可以根据编程的超时终止组处理。技术领域必须在组超时之前握手,否则存在被跳过的风险。因此,将关闭通知视为异常并尽快处理。避免在关闭处理中进行阻断调用。
超时值是系统级常量,不能在运行时设置。超时值基于 HLOS 要求,切勿更改。
RCINIT 终止处理立即移动到下一组。所有任务必须在超时发生之前执行操作,否则存在因超时导致进入下一终止组的风险。
超时事件将被视为警告并打印在 F3 消息日志中。此警告可能会变成触发崩溃的致命错误。使
用 modem_proc\core\debugtools\example\build\rcinit_dalcfg.xml 中的编译标志配
置超时事件:
0
默认值为 0,其中超时被视为警告。
对于崩溃转储,将该值设置为 1。