跳转至

外挂MCU以及SOC 上下电方案


REVISION HISTORY

Revision No.
Description
Date
1.0
  • Initial release
  • 06/07/2024

    1 概述

    本文档用于说明在SOC未下电完成而上电事件触发导致的系统异常问题以及解决方案。主要介绍 SOC上下电流程、问题产生原因以及解决方案。

    2 SOC 上下电流程


    图1 SOC 上下电流程
    1. SOC suspend 状态:此时 SOC 处于下电状态,RTCIO 0/1以及RTC alarm事件触发可将SOC 唤醒
    2. SOC 上电流程:该阶段为 SOC 硬件上电流程,RTCIO 0/1以及RTC alarm事件触发后,RTCIO4会被拉高,而后唤醒SOC
    3. SOC resume流程:该阶段为 SOC 软件 resume 流程
    4. SOC alive 状态:SOC 正常工作阶段
    5. SOC suspend 流程:该阶段为软件 suspend 流程
    6. SOC 下电流程:该阶段为 SOC 硬件下电流程,通过软件操作将RTCIO4拉低,SOC 进入下电流程,该阶段结束RTC 事件可正常将SOC 唤醒

    3 存在问题

    1. SOC 对于电源上电有严格的时序要求,当 RTCIO0/1 事件在SOC 处于硬件下电流程时(图1阶段6)触发,会导致SOC 并未完全下电而又要走上电流程,最终导致上电时序异常。
    2. 由于RTC wakeup 节点只会在 RTCIO4 被拉高之后才会被更新,因此在 RTCIO4 为 HIGH 的阶段(阶段2 / 3 / 5)触发的 RTCIO0/1 事件就无法被AOV demo 获取到,导致 RTCIO0/1(pir/wifi) 事件会丢失。
    3. RTC 每天 8万余次,是否可靠,如何防呆问题

    4 解决方案

    4.1 方案一(当前使用方案)


    图2 方案1事件流程图

    图3 SOC 硬件修改方案

    需要按照图3 进行硬件修改,硬件修改方案如下:

    1. 3.3V_GPIO:从SSC30XXE 芯片端任意选择一个3.3V且默认内部PU的GPIO
    2. PQ1: 增强型NMOS,建议VthGS越小越好
    3. MCU_INT: MCU外部事件中断输出脚
    4. RTC_IO1:自带按键防抖功能,有8ms delay才会拉高RTC_IO4
    5. R3: 该电阻值根据MCU IO 输出特性自行调整阻值

    基本原理:Vg大于VthGS 则NMOS 保持导通,RTC_IO1保持低电平相当于会屏蔽掉MCU_INT 的信号,Vg 小于VthGS则NMOS保持关断,RTC_IO1相当于直连MCU_INT,可以正常接收MCU中断,无论何时MCU_INT 拉高都只能在此阶段被 RTC_IO1 响应,响应8ms之后,内部POC模块才会拉高RTC_IO4,硬件上有8ms给系统更多掉电时间,同时也能保证二次上电时序正常。

    将 RTC IO0 的输入源由 RTC ALARM 修改为 MCU timer ,将RTC_IO1 的输入源按如下修改


    图4 方案1硬件连接示意图

    原理:在gpio2 电平为 HIGH 时,根据 CMOS 原理,即使此时 MCU 拉高RTC_IO1,此时 SOC 也无法响应RTC_IO1上升沿中断,根据CMOS 管特性(导通电压是0.7v),图中的gpio2 下降沿时的电压为 0.7v,此外由于 RTCIO1 的防抖措施(拉高RTCIO1 8ms 之后才会拉高RTCIO4 )的存在,在 gpio 2下降沿后拉高 RTCIO1 一定是安全的。gpio2 上升沿事件是 SOC 软件 resume 时将其拉高,gpio2 下降沿事件是 SOC 硬件下电流程中 GPIO 电源域的电压拉低触发。

    具体实现 flow :

    1. MCU 通过timer 唤醒 SOC,MCU alive,在此后任意阶段,若发生 Pir & WiFi 事件,MCU 将 gpio1 举高,然后直接拉高 RTCIO1 即可

    2. SOC 上电启动到阶段 2 到 gpio2 上升沿时,MCU 拉高 RTCIO1,此时由于gpio2 为 LOW ,SOC 虽然会响应,但是由于RTCIO4已经为高,SOC 无事发生

    3. SOC 启动处于 gpio2 上升沿 至 gpio2 下降沿阶段内时,gpio2 为 HIGH,由于 CMOS 的原因,即使 MCU 拉高 RTCIO1,SOC 看到的 RTCIO1依旧为低

      SOC 启动到阶段 4,通过查询 gpio1 电平状态确认是否有 Pir & WiFi 事件发生,若有则切换高帧模式,然后修改 gpio3 状态(比如连续多个上升沿)告知 MCU 已经查询过事件,MCU 获取gpio3状态后,将gpio 1 拉低

      此后 SOC 在阶段4会持续 polling MCU gpio1 电平状态以及时响应阶段 4 发生的 Pir & WiFi 事件

    4. SOC 启动到 gpio2 下降沿到 阶段1,此时gpio2 为 LOW ,MCU 拉高 RTCIO1 后 RTCIO1会在 8ms 之后才会真正将RTCIO4拉高(8ms 足够让gpio2 由0.7v 掉电到零),这时 SOC 会被直接唤醒。

    注意:

    1、若有多个外部唤醒事件的话,则 gpio1 的功能需要多根 gpio 实现

    2、使用 gpio3 告知 MCU 状态已经被获取的方式,也可以由业务逻辑实现,此时只是用 gpio 举例而已

    4.2 方案二


    图5 方案2事件流程图

    修改 RTCPOC 模块的输入信号源为下图所示


    图6 方案2硬件连接示意图

    将 RTC IO0 的输入源由 RTC ALARM 修改为 MCU timer ,将RTC_IO1 的输入源 修改为 Pir & WiFi。

    原理:MCU 通过 timer 唤醒 SOC 时,在 SOC 处于 2、3、4、5、6 阶段时,MCU 同样处于 ALIVE 状态,此时加上 1fps 的控制源修改,MCU 可以清楚地知道 SOC 的上下电时间点,就可以将 图4 的阶段 2、3、5、6 发生的 Pir & WiFi事件保存在 MCU 内部,在阶段 4 通过串口将事件状态发送给 SOC 。

    具体实现 flow:

    1. MCU 通过timer 唤醒 SOC,然后等待SOC通过串口发送的 suspend 信号或者是 询问信号,

      suspend 信号:表示 SOC 开始下电

      询问信号:询问 MCU 在 2、3、5、6 阶段是否发生 Pir & WiFi 事件,事件发生意味着 SOC 进入阶段 4

    2. SOC 上电启动到阶段 2、3,此时若发生 Pir & WiFi 事件,MCU 保留事件发生状态,不去触发 RTCIO0/1事件

    3. SOC 启动到阶段 4,通过串口发送问询信号给 MCU,MCU 通过串口回复有或者没有,若此时接收到了 MCU 有 Pir & WiFi 事件发生,那切换高帧模式

      此后 SOC 在阶段4会持续等待 MCU 串口的发送信息,等待接收 MCU 串口的发送信息是为了响应阶段 4 发生的 Pir & WiFi 事件,当阶段 4 发生 Pir & WiFi 事件,直接通过串口告诉 SOC 即可。

      SOC 阶段4进入 STR 之前,通过串口告诉 MCU 准备下电

    4. SOC 启动到阶段 5、6,此时若发生 Pir & WiFi 事件,MCU 保留事件发生状态,不去触发 RTCIO0/1事件,阶段 6 SOC 硬件下电流程中 GPIO 电源域的电压拉低之后,GPIO 会被拉低,此时 MCU 会收到一个下降沿中断

    5. MCU 接收到 下降沿中断后,延时一个 t 的时间等到 SOC 完全下电进入阶段 1

      MCU 下电完成后,若在 SOC 阶段 5、6 有 Pir & WiFi 事件触发就立刻唤醒 SOC。回到步骤2

    让 MCU 能够知道当前 SOC 下电完成时间节点,在下电之后再去响应 pir/wifi 事件唤醒SOC 即可。

    t =  𝒉𝒘_𝒑𝒐𝒘𝒆𝒓𝒅𝒐𝒘𝒏
    𝒉𝒘_𝒑𝒐𝒘𝒆𝒓𝒅𝒐𝒘𝒏:硬件开始掉电(RTC_IO4 为0)直到到板子完全掉电时间
    

    4.2.1 伪代码

    4.2.1.1 SOC AOV demo 部分
    init 阶段:pull up 指定的GPIO 引脚
        // 创建新线程等待接收 MCU 串口信息
        creat_new_thred( func)
        // 创建新线程检测心跳包
        creat_new_thred( heart_beat)
        uart_recive_count=0
    
    处理阶段:
        uart_trans( Querying )
        uart_recive(event_flag)
        uart_recive_count++;
        if(event_flag==TRUE)
        {
            //切换高帧
            .
            .
            .
        }
        else
        {
            //维持现状
            .
            .
            .
        }
    
        // SOC ALIVE 处理完成
        uart_trans( suspend )
        //进入 suspend
    
    
    heart_beat()
    {
       temp_count = uart_recive_count
       sleep( 500ms )
       if(uart_recive_count<=temp_count)
       {
           // MCU 异常
       }
    }
    
    //线程处理函数 func
     func()
     {
         uart_recive()
         if(MCU 有事件触发)
         {
             //检查当前模式
             if(mode=低帧)
             {
                 //切换到高帧
             }else{
                 sleep()
             }
    
         }else{
             sleep()
         }
     }
    
    4.2.1.2 MCU demo 部分
    init 阶段:
        // 创建新线程等待接收 SOC 串口信息
        creat_new_thred( func)
        // 创建新线程检测心跳包
        creat_new_thred( heart_beat)
        Querying=false
        suspend=false
        uart_recive_count=0
    
    处理阶段:
    send_pir_event_flag=true
    
        if(PIR || WIFI)
        {
            if(Querying=false )
            {
                // 保存事件到变量
                save_event()
    
            }
            else if(Querying=true&& suspend=false)
            {
               uart_trans(true)
            }
            else if(Querying=true&& suspend=true)
            {
               // 保存事件到变量
                save_event()
                sleep( t )
                pull_up(RTC_IO1)
            }
        }
    
    
    heart_beat()
    {
       temp_count = uart_recive_count
       sleep( 500ms )
       if(uart_recive_count<=temp_count)
       {
           // MCU 异常
       }
    }
    
    //线程处理函数 func
     func()
     {
         while(uart_recive())
         {
              if(Querying)
             {
                 uart_recive_count++
                 if(PIR || WIFI)
                 {
                   uart_trans(true)
                 }else
                 {
                     uart_trans(false)
                 }
                 Querying=true
             }else if(suspend)
             {
                 // 此时开始不要响应 IO0/1 事件
                 suspend=true
                 break;
             }
         }
     }
    

    4.3 RTC 如何防呆问题

    方案1:基于上面的功能实现,可直接将问询信号或者 GPIO 下降沿中断作为 SOC 心跳包使用,在规定时间内没有接到 SOC 的心跳包,则认为 SOC 出现异常,

    同理将 MCU 对问询信号的回复信息作为 MCU 的心跳包,在规定时间内没有接到 MCU 的心跳包,则认为 MCU 出现异常。