M 平台按键强制升级流程分析

mstar 平台升级流程主要是在mboot 开机过程中进行,检测不通的触发条件从而进入升级流程。我们首先熟悉一个mboot的 启动流程。

启动流程

汇编部分不通方案也大致相同,我们主要以C部分启动流程为主,分析升级流程

  1. start.S 调转执行board_init_f
  2. 板级初始化 board_init_r (@\MBoot\u-boot-2011.06\arch\arm\lib\board.c)
  3. mstar 系统初始化MstarSysInit;
  4. board初始化board_init;
  5. nand,serial,eth,interrupt初始化;
  6. mstar 驱动初始化MstarDrvInit
  7. main_loop (MstarProcess ,MstarToKernel)初始化;
  8. MstarProcess ,MstarToKernel注册mboot 常用的功能(命令行指令);
    上面只是自动的大概枝干,抽出了该平台特殊的部分,其中
    vendor\mstar\mboot\MBoot\MstarApp\src\MsStart.c
BOOLEAN MstarProcess(void)
{
#if CONFIG_MINIUBOOT
    run_command("updatemiureg", 0);
    run_command("bootargs_set", 0);
#else
    ......
    Customer_Register_Process();  // MsCustomerRegister.c 中完成具体注册
    Customer_Register_ToKernel(); //  MsCustomerRegister.c 中完成具体注册
    pCmd=getFirstCmd();
    if(pCmd==NULL)
    {
        UBOOT_DEBUG("There are no any cmds in table\n");
        return TRUE;
    }
   // 从comand 中循环获取指令执行
    while(1)
    {        
        if(pCmd->stage == STAGE_PROCESS)
        {
            UBOOT_BOOTTIME("[AT][MB][%s][%lu]_start\n",pCmd->cmd, MsSystemGetBootTime());
            run_command(pCmd->cmd,  pCmd->flag);
            UBOOT_BOOTTIME("[AT][MB][%s][%lu]_end\n",pCmd->cmd, MsSystemGetBootTime());
        }
        pCmd=getNextCmd(pCmd);
        if(pCmd==NULL)
        {
            UBOOT_DEBUG("It's the last cmd\n");
            break;
        }
    }
    UBOOT_TRACE("OK\n");     
 #endif
    return TRUE;
}

MstarToKernel是在MstarProcess 注册的基础上,执行命令完成对应功能。

BOOLEAN MstarToKernel(void)
{
#if CONFIG_MINIUBOOT
    run_command("bootcheck", 0);    //  启动检测
    #if (CONFIG_PANEL_INIT)
    run_command("panel_pre_init", 0);   //  屏的预初始化
    #endif

    #if (ENABLE_HDMI_TX == 1)
    run_command("hdmi init", 0);   // hdmi 初始化
    #endif

    #ifdef CONFIG_DISPLAY_LOGO
    run_command("bootlogo", 0);  // 开机logo初始化
    #endif
#else
   ......
    pCmd=getFirstCmd();
    if(pCmd==NULL)
    {
        UBOOT_DEBUG("There are no any cmds in table\n");
        return TRUE;
    }
    
    while(1)
    {
        if(pCmd->stage == STAGE_TOKERNEL)
        {
            UBOOT_BOOTTIME("[AT][MB][%s][%lu]_start\n",pCmd->cmd, MsSystemGetBootTime());
            run_command(pCmd->cmd,  pCmd->flag);
            UBOOT_BOOTTIME("[AT][MB][%s][%lu]_end\n",pCmd->cmd, MsSystemGetBootTime());
        }
        pCmd=getNextCmd(pCmd);
        if(pCmd==NULL)
        {
            UBOOT_DEBUG("It's the last cmd\n");
            break;
        }
    }
    
    UBOOT_TRACE("OK\n");
 #endif
    return TRUE;
}

run_command 执行的指令就是在MsCustomerRegister.c文件中
通过Add_Command_Table注册的指令。
例如:
注册:Add_Command_Table (“bootcheck” , 0, STAGE_TOKERNEL);
执行:run_command(“bootcheck”, 0);
声明:

U_BOOT_CMD(
    bootcheck, CONFIG_SYS_MAXARGS, 1,    do_bootcheck,
    "bootcheck   - Do boot check\n",
    NULL
);

实现:

vendor\mstar\mboot\MBoot\MstarApp\src\MsBoot.c
int do_bootcheck (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
......
}

上面介绍了大致的初始化流程。接着看一下升级检测。

升级检测

int do_bootcheck (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{

#if (ENABLE_MODULE_BOOT_IR == 1)
     if(BootFlag == 0)
     {
        BootMode =get_boot_mode_from_ir();
        if(BootMode!=EN_BOOT_MODE_UNKNOWN)
        {
            //bootmode via IR
            BootFlag=1;
        }
     }
#endif

#if (ENABLE_MODULE_BOOT_KEYPAD == 1)
     if(BootFlag == 0)
     {
        BootMode =get_boot_mode_from_keypad();
        if(BootMode!=EN_BOOT_MODE_UNKNOWN)
        {
            //BootMode via KEYPAD
            BootFlag=1;
        }
     }
#endif

#if (ENABLE_MODULE_ANDROID_BOOT == 1)
    // NOTE: read BCB in mtd0 (misc) to decide what boot mode to go
    if(BootFlag == 0)
    {
        BootMode=get_boot_mode_from_mtd0();
        if(BootMode!=EN_BOOT_MODE_UNKNOWN)
        {
            //BootMode via MTD
            BootFlag=1;
        }
    }
#endif

#if (ENABLE_MODULE_ENV_BOOT == 1)
    if(BootFlag == 0)
    {
        BootMode=get_boot_mode_from_env();
        if(BootMode!=EN_BOOT_MODE_UNKNOWN)
            BootFlag = 1;
    }

    if(BootFlag == 0)
    {
        char* force_upgrade = getenv(ENV_FORCE_UPGRADE);
        if(force_upgrade)
        {
            int force_flag = simple_strtoul(force_upgrade,NULL,16);
            if((force_flag <= 0x0F)&&(force_flag > 0x00))
            {
               //last time force upgrade not finish,so continue upgrading
               BootMode = EN_BOOT_MODE_USB_UPGRADE;
            }
        }
    }
#endif
   ...... 
}

do_bootcheck会从IR, KEYPAD,MTD0,ENV 获取信息,标记当前的BootMode ,下一步就是甄别BootMode 决定进入升级,还是进入recovery等其他场景

int do_bootcheck (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	......

    switch(BootMode)
    {
#if CONFIG_RESCUE_ENV && CONFIG_RESCUE_ENV_IR_TRIGGER
        case EN_BOOT_MODE_BRICK_TERMINATOR:
            brick_terminator_recover_mode = 1;
            break;
#endif
#if (ENABLE_MODULE_ANDROID_BOOT == 1 )
        case EN_BOOT_MODE_RECOVERY:
            boot_mode_recovery();
            break;
        case EN_BOOT_MODE_RECOVRY_WIPE_DATA:
            run_command("recovery_wipe_partition data",0);
            boot_mode_recovery();
            break;
        case EN_BOOT_MODE_RECOVRY_WIPE_CACHE:
            run_command("recovery_wipe_partition cache",0);
            boot_mode_recovery();
            break;
        #if (ENABLE_MODULE_SYSTEM_RESTORE == 1)
        case EN_BOOT_MODE_SYSTEM_RESTORE:
            ret = run_command("SystemRestore",0);
            if (ret != -1)
            {
                boot_mode_recovery();
            }
            break;
        #endif
#endif
        #if (ENABLE_MODULE_USB == 1)
        case EN_BOOT_MODE_USB_UPGRADE:
            ret = run_command("custar",0);//usb upgrade
            break;
#if (ENABLE_MODULE_BOOT_IR == 1)
        case EN_BOOT_MODE_OTA_UPGRADE:
            ret = run_command("ota_zip_check",0);//ota upgrade
            if (ret != -1)
            {
                boot_mode_recovery();
            }
            break;
        case EN_BOOT_MODE_USB_RECOVRY_UPGRADE:
            ret = run_command("usb_bin_check",0);//usb upgrade
            if(ret == 0)
            {
                break;
            }
            ret = run_command("ota_zip_check",0);//ota upgrade
            if (ret != -1)
            {
                boot_mode_recovery();
            }
            break;
#endif
        #endif
        #if (ENABLE_MODULE_OAD == 1)
        case EN_BOOT_MODE_OAD_UPGRADE:
            ret = run_command("costar",0);//oad upgrade
            break;
        #endif
        #if (ENABLE_MODULE_ENV_UPGRADE_FROM_BANK == 1)
        case EN_BOOT_MODE_ENV_UPGRADE:
            ret = run_command("rstar",0);
        #endif
        #if (ENABLE_MODULE_NETUPDATE == 1)
        case EN_BOOT_MODE_NET_UPGRADE:
            _do_NetUpgrade_mode();
            break;
        #endif
        case EN_BOOT_MODE_UART_DEBUG:
            ret = run_command("setenv UARTOnOff on", 0);
            ret = run_command("saveenv", 0);
            printf("Opening UART now\n");
            break;
        case EN_BOOT_MODE_NORMAL:
            break;
        #if defined(CONFIG_AN_FASTBOOT_ENABLE)
        case EN_BOOT_MODE_FASTBOOT:
            ret = run_command("usb start 0",0);
            ret = run_command("fastboot", 0);
            break;
        #endif
        case EN_BOOT_MODE_UPDATE_BOOTLOGO:
            ret = run_command("setenv BootlogoFile /cache/boot0.jpg",0);
            ret = run_command("saveenv", 0);
            ret = run_command("dbtable_init 1", 0);
            ret = run_command("mmc erase.p misc", 0);
            break;
        default:
            //normal booting according bootcmd in main.c
            UBOOT_DEBUG("non available case\n");
            break;
    }
	......

    UBOOT_TRACE("OK\n");
    return ret;
}

从上面可以看出BooMode 为EN_BOOT_MODE_RECOVERY,EN_BOOT_MODE_RECOVRY_WIPE_DATA,EN_BOOT_MODE_RECOVRY_WIPE_CACHE,EN_BOOT_MODE_SYSTEM_RESTORE,EN_BOOT_MODE_OTA_UPGRADE,EN_BOOT_MODE_USB_RECOVRY_UPGRADE,都是进入recovery进行OTA升级,为EN_BOOT_MODE_USB_UPGRADE 时,在进入U盘的升级流程。对于按键板而言只需要将按键和BootMode(EN_BOOT_MODE_USB_UPGRADE) 关联起来,即可进入升级流程。

按键检测流程
在这里插入图片描述

按键捕获

EN_BOOT_MODE get_boot_mode_from_keypad(void)
{
     U8 u8KeyPad_KeyVal=0xFF;
     U8 u8KeyPad_RepFlag = 0;
     EN_BOOT_MODE mode = EN_BOOT_MODE_UNKNOWN;
     UBOOT_TRACE("IN\n");
     msKeypad_GetKey(&u8KeyPad_KeyVal,&u8KeyPad_RepFlag);
     printf("fore uup u8KeyPad_KeyVal [0x%x]\n",u8KeyPad_KeyVal);
     switch(u8KeyPad_KeyVal) // NOTE: read IR Key to decide what boot mode to go
    {
#if defined(CONFIG_AN_FASTBOOT_ENABLE)
        case KEYPAD_FASTBOOT_KEY:
            mode = EN_BOOT_MODE_FASTBOOT;
            break;
#endif
        case KEYPAD_RECOVERY_KEY:
            mode = EN_BOOT_MODE_RECOVERY;
            break;
        case KEYPAD_FORCEUGRADE_KEY:  // 强制升级键值
            // mode = check_usb_upgrade();
            mode = EN_BOOT_MODE_USB_UPGRADE;
            break;
        case KEYPAD_UART_DEBUG_KEY:
            mode = EN_BOOT_MODE_UART_DEBUG;
            break;
        #if (ENABLE_MODULE_SYSTEM_RESTORE == 1)
        case KEYPAD_SYSTEM_RESTORE_KEY:
            mode = EN_BOOT_MODE_SYSTEM_RESTORE;
            break;
        #endif
        default:
            mode = EN_BOOT_MODE_UNKNOWN;
            break;
    }
     UBOOT_TRACE("OK\n");
     return mode;
}

msKeypad_GetKey 获取按键板按键值,可以将u8KeyPad_KeyVal 的值分别对应上KEYPAD_FASTBOOT_KEY,KEYPAD_RECOVERY_KEY,KEYPAD_FORCEUGRADE_KEY,KEYPAD_UART_DEBUG_KEY,KEYPAD_SYSTEM_RESTORE_KEY。 此处USB升级使用的是power键那么对应的KEY是KEYPAD_FORCEUGRADE_KEY应该为多少?

按键映射
msKeypad_GetKey 虽然获取到的是具体的键值,但是主控检测到时按键板连接到sar口的adc 值,所以要找到sar 和 adc 值的映射关系。

BOOLEAN msKeypad_GetKey(U8 *pkey, U8 *pflag)
{
    U8 Channel;

    for (Channel=0; Channel<MAXKEYPADCH; Channel++)
    {
        if (msKeypad_CH_GetKey(Channel, pkey, pflag))
        {
            return MSRET_OK;
        }
    }
    return MSRET_ERROR;
}
static BOOLEAN msKeypad_CH_GetKey(U8 Channel, U8 *pkey, U8* pflag)
{
    U8 i, j, Key_Value;
    U8 u8ChIdx = msKeypad_GetChanIndex(Channel);

    if(u8ChIdx == 0xFF)
        return MSRET_ERROR;

    U8 u8KeyLevelNum = m_KpdConfig[u8ChIdx].u8KeyLevelNum;
    U8 KEY_LV[u8KeyLevelNum];
    memset(KEY_LV, 0x0, u8KeyLevelNum);

    *pkey = 0xFF;
    *pflag = 0;

    for ( i = 0; i < KEYPAD_STABLE_NUM; i++ )
    {
        Key_Value = MDrv_SAR_Adc_GetValue(m_KpdConfig[u8ChIdx].u8SARChID);
        for (j=0;j<u8KeyLevelNum;j++)
        {
            if (Key_Value < m_KpdConfig[u8ChIdx].u8KeyThreshold[j])
            {
                if((m_KpdConfig[u8ChIdx].u8KeyThreshold[j] - Key_Value) <= ADC_KEY_LEVEL_TOLERANCE)
        		{
	                KEY_LV[j]++;
	                break;
        		}
            }
        }
    }

    for(i=0; i<u8KeyLevelNum; i++)
    {
        if(KEY_LV[i] > KEYPAD_STABLE_NUM_MIN)
        {
            *pkey = m_KpdConfig[u8ChIdx].u8KeyCode[i];
            return MSRET_OK;
        }
    }
    return MSRET_ERROR;

}

获取的adc 结合结构体m_KpdConfig 的映射关系得到keycode

static SAR_KpdRegCfg_t m_KpdConfig[MAXKEYPADCH] = {
#include "keypad.h"
};

keypad 的映射关系如下:

//**********************************************************************
//** BOARD KEY PAD SAR SETTING
//**********************************************************************
//bEnable, u8SARChID, u8UpBnd, u8LoBnd, u8KeyLevelNum, u8KeyThreshold[8], u8KeyCode[8]
{0x00, 0x00, {0xFF, 0xF0}, 0x00, {0x10, 0x2F, 0x4D, 0x71, 0x92, 0xAB, 0xC3, 0xE7}, {0x46, 0xA1, 0xA2, 0xA4, 0xA3, 0xA6, 0xA8, 0xA5} },
{0x01, 0x01, {0xFF, 0x70}, 0x08, {0x13, 0x32, 0x52, 0x73, 0x92, 0xAE, 0xC6, 0xE8}, {0x82, 0x25, 0x26, 0x24, 0x32, 0x31, 0x23, 0x30} },
{0x00, 0x02, {0xFF, 0x80}, 0x00, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
{0x00, 0x03, {0xFF, 0xF0}, 0x08, {0x10, 0x2F, 0x4D, 0x71, 0x92, 0xAB, 0xC3, 0xE7}, {0x46, 0xA8, 0xA4, 0xA2, 0x00, 0x00, 0x00, 0x00} },

结合按键的power 的adc 值 为0x00,0x01 在区间,在u8KeyThreshold的
0x00 ~ 0x13 这个区间,对应的key 值应该是0x82 ,也即上面KEYPAD_FORCEUGRADE_KEY 的值。

发布了101 篇原创文章 · 获赞 19 · 访问量 33万+

猜你喜欢

转载自blog.csdn.net/kehyuanyu/article/details/102756245
M
^M