WCH CH57x 系列芯片有个内置的 TMOS 事件调度系统。其封装于蓝牙静态库中,无法看到对应代码。为了实现对任务的更精细的控制,在这里使用了Ghidra尝试反编译得到对应的逻辑。
反编译后可以看出,TMOS是一个基于轮询的任务事件调度系统,几乎所有的调度操作都是在TMOS_SystemProcess
方法中执行的,其简化后的代码如下:
void TMOS_SystemProcess(void)
{
/** 高优先级的事件 **/
// 第0号位是抢占式的事件,只会执行一次
if (pfnProcessCBs[0]) {
pfnProcessCBs[0]();
pfnProcessCBs[0] = 0;
}
// 始终执行1号位的事件
if (pfnProcessCBs[1])
pfnProcessCBs[1]();
// 如果有需要处理的中断,根据当前模式选择中断处理器处理
if (gBleIPPara.hasIRQ) {
gBleIPPara.hasIRQ = false;
ll_rx_wait_finish();
pfnProcessCBs[currentMode]();
}
// 处理跳频逻辑
if (rfInfo.hopFlag & HopRx) {
RF_FrequencyHoppingChange();
}
// 执行2号位的事件
if (pfnProcessCBs[2])
pfnProcessCBs[2]();
/** 处理普通事件 **/
for (; gTmosPara.evtIndex < gTmosPara.evtNum; gTmosPara.evtIndex++) {
if (EventsArr[gTmosPara.evtIndex] != 0)
break;
}
if (gTmosPara.evtIndex < gTmosPara.evtNum) {
EventsArr[gTmosPara.evtIndex] = CallbackArr[gTmosPara.evtIndex](EventsArr[gTmosPara.evtIndex]);
}
/** 处理定时事件 **/
int deltaTime = pfnTimerCBs();
if (deltaTime) {
gTmosPara.currentTime += deltaTime;
tmos_query_time(deltaTime);
}
}
在 TMOS_SystemProcess
方法中,会优先执行内置的一系列注册事件。然后再去尝试执行那些已经设定了Event的事件,最后处理定时事件。
这里的 tmos_query_time
方法名字有些怪,但它实际上是用来处理定时事件的方法。简化后的代码如下:
void tmos_query_system_time(uint deltaTime)
{
// 计算下次事件的时间
gTmosPara.nextEvtTime = -1;
for (int i = 0; i < eventNum; i++)
{
if (events[i].timeout >= deltaTime)
events[i].timeout -= deltaTime;
else
events[i].timeout = 0;
if (gTmosPara.nextEvtTime > events[i].timeout)
gTmosPara.nextEvtTime = events[i].timeout;
// 如果到点,则执行对应任务
if (events[i].timeout == 0) {
if (events[i].event != 0) {
tmos_set_event(events[i].taskID, events[i].event);
}
events[i].timeout = events[i].reloadTime;
}
}
// 准备睡眠
tmos_query_sleep_time();
}
tmos_query_sleep_time
方法中会根据当前系统状态决定是否要进入睡眠状态,简化代码如下:
void tmos_query_sleep_time()
{
// 当前有事件没处理,取消睡眠
for (int i = 0; i < gTmosPara.evtNum; i++)
if (EventsArr[i] != 0)
return;
// 当前处于特定模式,取消睡眠
if (gBleIPPara.currentMode > 4)
return;
// 当前处于跳频接收模式,取消休眠
if ((rfInfo.hopFlag & FlagHopRx) != FlagNone)
return;
// 获取下次连接时间
int sleepTime = LL_GetNextConnectEventTime(&bleSleepTime);
if (sleepTime == -1) {
if (gTmosPara.nextEvtTime == -1)
return;
sleepTime = gTmosPara.nextEvtTime * 20;
if (sleepTime < ble.WakeUpTime)
return;
// 计算唤醒时间点
sleepTime = RTC_Get32KClock() + sleepTime - ble.WakeUpTime;
} else {
// 蓝牙相关计算
if (gTmosPara.nextEvtTime != -1) {
sleepTime = gTmosPara.nextEvtTime * 20;
if (sleepTime < bleSleepTime)
bleSleepTime = sleepTime;
}
sleepTime = RTC_Get32KClock() + bleSleepTime - ble.WakeUpTime;
}
if (sleepTime == 0)
return;
// 执行实际睡眠操作
int result = ble.sleepCB(sleepTime);
// 睡眠成功,唤醒后重新初始化寄存器
if (result == 0) {
DMA_DevInit();
LLE_DevInit();
BB_DevInit();
}
}
0 条评论