Acc 断电休眠流程

Acc 断电流程

屏幕常亮状态下,当我们锁车门发生Acc断电的,最终到车进入休眠状态,需要发生三次状态迁移

  • 1.Normal–>PartyWork 触发条件,收到BCM上报的PowerMode状态:OFF, HL, LOCAL
  • 2.PartyWork–>PreSleep 触发条件, 收到NM mode为0,或者NM报文超时
  • 3.PreSleep–> sleep 触发条件,高权锁与低权锁相加为0,presleep定时器超时.
    具体log:
    D/PowerStateMachineImpl( 1244): Power mode change: PowerMode: OFF, HL, LOCAL
    具体逻辑
    public void onBcmPowerModeChange(PowerMode newMode) {
        if (newMode.mMode < 0 || newMode.mMode > 2 ||
                newMode.mSrc < 0 || newMode.mSrc > 1 ||
                    newMode.mFlag < 0 || newMode.mFlag > 1) {
            Log.d(TAG, "Invalid power mode(" + newMode.mMode + ", "
                    + newMode.mSrc + ", " + newMode.mFlag + "). DROP !!!");
            return;
        }
        mLooper.addEvent(() -> {
            if (mCurrentMode.equals(newMode)) {
                return;
            }
            mCurrentMode = newMode;
            Log.d(TAG, "Power mode change: " + newMode);

            switch (newMode.mMode) {
                case CarPowerHalService.BCM_PWR_OFF:
                    mCore.powerOff(newMode.mSrc, newMode.mFlag);
                    break;
                case CarPowerHalService.BCM_PWR_ACC:
                case CarPowerHalService.BCM_PWR_ON:
                    mCore.powerOn(newMode.mSrc, newMode.mFlag);
                    break;
            }
        }, 1);
    }

1.首先获取BcmPowerMode,由MCU上报提供.根据PowerMode的状态,进行状态迁移,由于收到的状态 OFF, HL, LOCAL

  • 整车电源模式有3三种,分别ACC、ON、OFF三种对应整车不同电源状态。

ACC ACC模式时,整车接通动力电池,全部ECU唤醒。
ON ON模式时,整车接通动力电池,全部ECU唤醒。
OFF OFF模式下,整车切断动力电池,部分ECU断电,其余长电ECU均由蓄电池进行供电。

  • 整车电源模式获取策略
    整车电源模式可通过两种方式获取,分别为从CAN总线获取及从物理硬线获取。其中以CAN总线获取方式为准,
    当CAN总线异常或获取的整车电源模式为无效时通过物理硬线方式获取。通过物理硬线获取时,高电平代表线有效。
    现方案中,ACC硬线连接到820A-MCU,IGN硬线连接到J6-MCU。
    CAN can总线策略
    HL 硬线策略

  • 整车电源模式标志位
    整车电源模式标志位由BCM生成,只能通过CAN总线获取,是HMI电源管理的重要标志,此标志位共有两种,分别为本地供电模式及远程供电模式
    LOCAL 当整车电源模式切换原因为非远程控制时BCM生成本地供电模式标志,此时显示屏可被点亮。
    REMOTE 当整车电源模式切换原因为远程控制时BCM生成远程供电模式标志,此时不允许特殊显示需求之外任何显示屏点亮。

接下来继续分析Poweroff方法

        @Override
        protected void powerOff(PowerStateMachine context, int src, int flag)
        {
            Log.d(" shiph "," PowerStateMachineMap_PM_STATE_NORMAL powerOff src "+src +" flag ");
            PowerStateMachineImpl ctxt = context.getOwner();

            (context.getState()).exit(context);
            context.clearState();
            try
            {
				//释放所有三方应用
                ctxt.freezeAll3rdApps();
                //设置关屏幕接口
                ctxt.turnOffDisplayInternal(null, POWER, PM_PID_SELF);
                ctxt.enclose(PowerStateMachine::deferredAction, "deferredAction");
            }
            finally
            {
                context.setState(PowerStateMachineMap.PM_STATE_PARTLYWORK);
                (context.getState()).entry(context);
            }

            return;
        }
  • 1.释放第三放应用app
  • 2.关闭屏幕准备进入sleep状态
  • 3.进入状态迁移,Normal迁移到PARTLYWORK状态

接下来看下partywork的状态迁移逻辑

  @Override
        protected void deferredAction(PowerStateMachine context)
        {
            PowerStateMachineImpl ctxt = context.getOwner();

            PowerStateMachineImplState endState = context.getState();
            context.clearState();
            try
            {
                ctxt.pubSleepProcessingOrFSMTransitionBack();
                ctxt.blockSuspendIfNecessaryInternel();
                ctxt.resetOrRestartTimer(PM_TIMER_SLPBLK, 2, PowerStateMachine::sleepBlockerTimeout);
                ctxt.startTimer(PM_TIMER_NM, 100, PowerStateMachine::timeout);
                ctxt.goToTargetIfNecessary();
            }
            finally
            {
                context.setState(endState);
            }

            return;
        }
  • 1.更新HU状态信息,并重置CE
  • 2.创建WakeLock 锁,防止系统休眠挂起
  • 3.创建2秒的定时器,2s之后释放wakelock
  • 4.设置一个100秒超时的定时器,接受NM 报文
  • 5.如果电源模式为off状态,不进行处理

NM报文每10秒上传一次


        @Override
        protected void recvNm(PowerStateMachine context, int mode)
        {
            PowerStateMachineImpl ctxt = context.getOwner();

            if (mode == MCU_NM_SLEEP)
            {
                (context.getState()).exit(context);
                context.clearState();
                try
                {
                    Log.d("shiph","PowerStateMachineMap_PM_STATE_PARTLYWORK recvNm mode "+mode);
                    ctxt.stopTimerIfNecessary(PM_TIMER_NM);
                    ctxt.enclose(PowerStateMachine::deferredAction, "deferredAction");
                }
                finally
                {
                    context.setState(PowerStateMachineMap.PM_STATE_PRESLEEP);
                    (context.getState()).entry(context);
                }

            }
            else
            {
                PowerStateMachineImplState endState = context.getState();
                context.clearState();
                try
                {
                    ctxt.resetOrRestartTimer(PM_TIMER_NM, 100, PowerStateMachine::timeout);
                }
                finally
                {
                    context.setState(endState);
                }

            }

            return;
        }
  • 1.上报的NM mode为0时候,进入PM_STATE_PRESLEEP状态
  • 2.重置can报文上报定时器为100秒。100秒以后进行超时处理

NM mode 状态

  • BUS_SLEEP 0 Uninitialized State
  • PREPARE_BUS_SLEEP 1 Bus -sleep State
  • SYNCHRONIZE 2 Prepare Bus-Sleep State
  • NETWORK 3 Ready Sleep State
  • reserve 4 Normal Operation State

如果NM mode接受的值为3, 所以看下timeout的状态逻辑

        @Override
        protected void timeout(PowerStateMachine context)
        {
            PowerStateMachineImpl ctxt = context.getOwner();

            (context.getState()).exit(context);
            context.clearState();
            try
            {
                ctxt.stopTimer(PM_TIMER_NM);
                ctxt.enclose(PowerStateMachine::deferredAction, "deferredAction");
            }
            finally
            {
                context.setState(PowerStateMachineMap.PM_STATE_PRESLEEP);
                (context.getState()).entry(context);
            }

            return;
        }

1.上报NMmode的定时器为10秒,当10秒以后,NM上报超时进入PM_STATE_PRESLEEP状态。


        @Override
        protected void recvMcuPowerQuery(PowerStateMachine context, int mode)
        {
            PowerStateMachineImpl ctxt = context.getOwner();

            if (mode == MCU_PWR_QUERY_SLEEP)
            {
                PowerStateMachineImplState endState = context.getState();
                context.clearState();
                try
                {	//强制激活MCU
                    ctxt.forceMcuAlive();
                    //1秒后调用postpone方法
                    ctxt.startTimerIfNecessary(PM_TIMER_POSTPONE, 1, PowerStateMachine::postpone);
                }
                finally
                {
                    context.setState(endState);
                }

            }
            else
            {
                PowerStateMachineImplState endState = context.getState();
                context.clearState();
                try
                {
                    ctxt.ackMcuKickOff(mode);
                }
                finally
                {
                    context.setState(endState);
                }

            }

            return;
        }

MCU power query状态为slee状态时候,进入postpone状态,1s,并进行循环处理


       @Override
        protected void postpone(PowerStateMachine context)
        {
            PowerStateMachineImpl ctxt = context.getOwner();

            PowerStateMachineImplState endState = context.getState();
            context.clearState();
            try
            {
                ctxt.forceMcuAlive();
                ctxt.resetOrRestartTimer(PM_TIMER_POSTPONE, 1, PowerStateMachine::postpone);
            }
            finally
            {
                context.setState(endState);
            }

            return;
        }

设置MCU强制激活
重新重置postpone定时器,1s后再次进入postpone状态

postpone意义就是强制激活MCU,防止MCU提前睡下去,因为状态机目前在PartyWork状态,接下来看下partywork下
向presleep的状态迁移

当NM mode为0,或者NM mode发送超时,会发生partywork向presleep状态迁移

       @Override
        protected void deferredAction(PowerStateMachine context)
        {
            PowerStateMachineImpl ctxt = context.getOwner();

            PowerStateMachineImplState endState = context.getState();
            context.clearState();
            try
            {
                ctxt.pubSleepProcessingOrFSMTransitionBack();
                ctxt.startTimer(PM_TIMER_PRESLEEP, 600, PowerStateMachine::timeout);
                ctxt.triggerHome();
                ctxt.goToSleepIfNoLock(PM_WAKELOCK_HIGH + PM_WAKELOCK_NORMAL);
            }
            finally
            {
                context.setState(endState);
            }

            return;
        }
  • 1.设置HU状态为HU_POWER_STATE: 1, 0, 0.
  • 2.设置600秒的定时器,处理timeout
  • 3.返回到主home界面
  • 4.检查高权锁和低权锁,如果即没有高权锁和低权锁,这进入sleep的状态迁移

先看下timeout的状态逻辑


        @Override
        protected void timeout(PowerStateMachine context)
        {
            PowerStateMachineImpl ctxt = context.getOwner();

            PowerStateMachineImplState endState = context.getState();
            context.clearState();
            try
            {
                ctxt.goToSleepIfNoLock(PM_WAKELOCK_HIGH);
            }
            finally
            {
                context.setState(endState);
            }

            return;
        }

1.调用goToSleepIfNoLock进入wakeLock的检查,检查高权锁的集合是否为0

然后看下goToSleepIfNoLock逻辑

  public void goToSleepIfNoLock(int lockMask) {
        boolean isAnyLockHeld = false;

        switch (lockMask) {
            case PM_WAKELOCK_HIGH:
            case PM_WAKELOCK_NORMAL:
                isAnyLockHeld = mWakelocks[lockMask >> 1].size() != 0;
                break;
            case PM_WAKELOCK_HIGH + PM_WAKELOCK_NORMAL:
                isAnyLockHeld = (mWakelocks[0].size() + mWakelocks[1].size()) != 0;
                break;
        }

        if (isAnyLockHeld) {
            Log.d(TAG, "HIGH[" + mWakelocks[0].size() + "], NORMAL[" + mWakelocks[1].size() + "]");
            return;
        }

        stopTimer(PM_TIMER_PRESLEEP);
        enclose(PowerStateMachine::sleep, "sleep");
    }
  • 1,检查高权锁集合是否为0。如果不为0则继续处理timeout,不会进入sleep的状态迁移,这个时候一直在postpone一直在触发,激活MCU
  • 2.如果600秒以后,高权锁的集合为0,或者 高权锁和低权锁集合为0,就是全部释放,则进行presleep的状态迁移
        @Override
        protected void sleep(PowerStateMachine context)
        {
            PowerStateMachineImpl ctxt = context.getOwner();

            (context.getState()).exit(context);
            context.clearState();
            try
            {
                ctxt.enclose(PowerStateMachine::deferredAction, "deferredAction");
            }
            finally
            {
                context.setState(PowerStateMachineMap.PM_STATE_SLEEP);
                (context.getState()).entry(context);
            }

            return;
        }

最后看下sleep的状态迁移

     @Override
        protected void deferredAction(PowerStateMachine context)
        {
            PowerStateMachineImpl ctxt = context.getOwner();

            PowerStateMachineImplState endState = context.getState();
            context.clearState();
            try
            {
                ctxt.pubSleepProcessingOrFSMTransitionBack();
                ctxt.forceTurnOffDisplayIfNecessary();
                ctxt.startTimer(PM_TIMER_SLEEP, 2, PowerStateMachine::sleep);
                ctxt.forceRebootIfScheduled();
                ctxt.stopTimerIfNecessary(PM_TIMER_POSTPONE);
                ctxt.forceMcuSleep();
            }
            finally
            {
                context.setState(endState);
            }

            return;
        }

1.检查HU状态
2.关闭屏幕
3.设置2秒定时期,2秒后调用sleep方法
4.是否需要重启
5.停止postpone
6.强制关闭MCU模式,中间有耗时500毫秒

接下来看下sleep方法

        @Override
        protected void sleep(PowerStateMachine context)
        {
            PowerStateMachineImpl ctxt = context.getOwner();

            (context.getState()).exit(context);
            context.clearState();
            try
            {
                ctxt.stopTimer(PM_TIMER_SLEEP);
                ctxt.scheduleRtcAlarmIfNecessary();
                ctxt.hostUSB();
                ctxt.pubNormalSleep();
                ctxt.suspendToRam();
                ctxt.pubSystemWakeUp();
                ctxt.pubWakeUpProcessing();
                ctxt.kickOffMcu();
                ctxt.obtainWakeupReason(WAKEUP_WAKE_LOCK_TIMEOUT);
                ctxt.peripheralUSB();
                ctxt.pubWakeUpComplete();
                ctxt.enableDisplayCtrl();
                ctxt.enclose(PowerStateMachine::deferredAction, "deferredAction");
            }
            finally
            {
                context.setState(PowerStateMachineMap.PM_STATE_PARTLYWORK);
                (context.getState()).entry(context);
            }

            return;
        }
  • 1.停止PM_TIMER_SLEEP定时器,
  • 2.设置alarm的RTC唤醒
  • 3.hostUSB,让usb失效(自己的理解)
  • 4.告知HU IPC正常休眠
  • 5.进行休眠挂起,kernel进入suspend(这块属于强制休眠)

你可能感兴趣的:(Android,Car,Power)