Mstar 平台(648)唤醒之串口唤醒

串口唤醒功能主要是从supernova 待机进入PM后,串口接收PC端口发送过来的特定字串,然后将主板唤醒的功能。与IR,KEYPAD,WOL,CEC,MHL 等等基本流程一致,触发源不一样而已。

待机前设置待机参数

    pstPMCfg->stPMWakeCfg.bPmWakeEnableIR = TRUE;
    pstPMCfg->stPMWakeCfg.bPmWakeEnableSAR = TRUE;
    pstPMCfg->stPMWakeCfg.bPmWakeEnableGPIO0 = FALSE;
    pstPMCfg->stPMWakeCfg.bPmWakeEnableGPIO1 = FALSE;
    pstPMCfg->stPMWakeCfg.bPmWakeEnableUART1 = TRUE;

bPmWakeEnableUART1 设置为FALSE,开启该口的唤醒功能,然后EnterSleepMode里面设置到PM里面

vendor\mstar\supernova\projects\msrv\control\src\MSrv_Control_common.cpp

mapi_interface::Get_mapi_system()->PowerDown(&stPMCfg,bTrigger);

PM 开启相关参数

  1. 开启PM_WK_UART_EN
vendor\mstar\pm\zenonia\Project\Mstar\Source\Configurations\cusProj_config.h

//-----Uart Wakeup---
#ifndef PM_WK_UART_EN
#define PM_WK_UART_EN 1
#endif
  1. 开启串口,设置串口波特率
vendor\mstar\pm\zenonia\Project\Mstar\Source\Configurations\cusProj_config.h
vendor\mstar\pm\zenonia\Project\Source\cus_config.h

#define UART1_BAUDRATE              19200//38400//9600//38400
#define ENABLE_UART0                    ENABLE

开启UART0 口,并设置串口波特率为19200(平台目前不支持115200)

  1. 设置UART口的寄存器CLK
    vendor\mstar\pm\zenonia\Project\Source\customer.c
void Cus_Sys_ChangeUartForPllClk(U32 u32Mcu_Clk)
{
    // Change MCU clock --> Change UART baud rate
#if ENABLE_UART0
    ADCON |= 0x80;
    S0RELL =  (UART_CLKREL(u32Mcu_Clk, UART0_BAUDRATE) & 0xff);
    S0RELH = ((UART_CLKREL(u32Mcu_Clk, UART0_BAUDRATE) >> 8) & 0x3);
    S0CON = 0x50;
    PCON |= 0x80;
    //S0BUF = (char)"*";
    TI0=1;
#endif

#if ENABLE_UART1
    S1RELL =  (UART1_CLKREL(u32Mcu_Clk, UART1_BAUDRATE) & 0xff);
    S1RELH = ((UART1_CLKREL(u32Mcu_Clk, UART1_BAUDRATE) >> 8) & 0x3);
    S1CON = 0x90;   // mode 1, 8-bit UART, enable receive
    S1CON |= BIT1;
#endif

#if PM_WK_UART_EN
    S1RELL =  (UART_CLKREL(u32Mcu_Clk, UART1_BAUDRATE) & 0xff);
    S1RELH = ((UART_CLKREL(u32Mcu_Clk, UART1_BAUDRATE) >> 8) & 0x3);
    S1CON = 0xd0;
    PCON |= 0x80;
    S1CON |= BIT1;
#endif
}

Cus_Sys_ChangeUartForPllClk 里面设置串口clk,配置好S1CON,PCON 否则后面无法获取到唤醒的字串。

  1. 设置唤醒字串
    vendor\mstar\pm\zenonia\Project\Mstar\Source\CusProj_Inf.h
#if PM_WK_UART_EN
#define UART_WAKEUP_COMMAND      "mstar"
#define UART_RECEIVED_TIMEOUT      0xFFFF
#endif

UART_WAKEUP_COMMAND 设置唤醒字串。

  1. 循环监听
BOOLEAN CusProj_InfUart1Polling(void)
{
    U8  u8UartWakeupCmd[32] = { 0 };
    U32 u32UartRxCount   = 0;
    U32 u32UartRxTimeout = 0;

    if(strlen(UART_WAKEUP_COMMAND) == 0)
        return TRUE;

    while((u32UartRxTimeout < UART_RECEIVED_TIMEOUT) && (u32UartRxCount < strlen(UART_WAKEUP_COMMAND)))
    {
        //WriteByte(0x0EEC, ReadByte(0x0EEC)&(~BIT1));//swtich gpio_pm[5] to 51's uart_rx1 and gpio_pm[1] to 51's uart_tx1
        //WriteByte(0x0EEC, ReadByte(0x0EEC)|(BIT0));//swtich gpio_pm[5] to 51's uart_rx1 and gpio_pm[1] to 51's uart_tx1
        if (S1CON & BIT0)       // UART1 have received a ascii data
        {
            //printf("S1BUF = 0x%x\n", S1BUF);
            u8UartWakeupCmd[u32UartRxCount++] = S1BUF;

            if(u32UartRxCount == strlen(UART_WAKEUP_COMMAND))
            {
                if (strcmp(u8UartWakeupCmd, UART_WAKEUP_COMMAND) == 0)
                {
                    u32UartRxCount = 0;
                    return TRUE;
                }
                else
                {
                    S1CON &= ~BIT0;     // clear received flag
                    return FALSE;
                }
            }

            S1CON &= ~BIT0;     // clear received flag
        }
        u32UartRxTimeout++;
    }

    if (u32UartRxTimeout >= u32UartRxTimeout)
    {
        u32UartRxCount = 0;
        memset(u8UartWakeupCmd, 0, 32);
        u32UartRxTimeout = 0;
    }

    return FALSE;
}

void CusProj_InfUart1Isr(void)
{
    if( Read2Byte(0x0F0A) & BIT8 )                       //gpio_pm_5_fiq_final_status
    {
        if(CusProj_InfUart1Polling() == TRUE)
        {
            WriteByte(0x0E6B, (ReadByte(0x0E6B)&(~BIT1)));// disable swtich gpio_pm[5] to HK51's uart_rx1 and gpio_pm[1] to HK51's uart_tx1

            MDrv_PM_PowerUp(PM_WKUP_UART);

            WriteByte(0x0F0A, (ReadByte(0x0F0A))|(BIT6));     //clear  PAD_GPIO_PM5
            WriteByte(0x0F0A, (ReadByte(0x0F0A))&(~BIT6));

            WriteByte(0x0F0A, ReadByte(0x0F0A)&(~BIT7)); //gpio_pm_5_fiq_pol
            WriteByte(0x0F0A, ReadByte(0x0F0A)|(BIT4));     //mask gpio_pm_5_fiq_mask
            WriteByte(0x0F0A, ReadByte(0x0F0A)& ~(BIT0));// gpio_pm[5] is output enable
            while(1);
        }
        else
        {
            WriteByte(0x0F0A, (ReadByte(0x0F0A))|(BIT6));     //clear  PAD_GPIO_PM5
            WriteByte(0x0F0A, (ReadByte(0x0F0A))&(~BIT6));
        }
    }
}

CusProj_InfUart1Polling 中通过S1BUF不停读取字串,与唤醒字串匹配后,就开是唤醒

  1. 唤醒
MDrv_PM_PowerUp(PM_WKUP_UART);

INTERFACE void MDrv_PM_PowerUp(PM_WkupSrc eWkupSrc);

PM 唤醒源如下:
typedef enum
{
    PM_WKUP_NONE    = 0,   ///No wakeup event happens
    PM_WKUP_IR      = 1,     ///Wakeup event IR
    PM_WKUP_DVI     = 2,    ///Wakeup event DVI
    PM_WKUP_DVI2 	= 3,   ///Wakeup event DVI2
    PM_WKUP_CEC     = 4,    ///Wakeup event CEC
    PM_WKUP_SAR     = 5,    ///Wakeup event SAR
    PM_WKUP_ESYNC   = 6,  ///Wakeup event ESYNC
    PM_WKUP_SYNC    = 7,   ///Wakeup event SYNC
    PM_WKUP_RTC     = 8,    ///Wakeup event RTC
    PM_WKUP_RTC2    = 9,   ///Wakeup event RTC2
    PM_WKUP_AVLINK  = 10,///Wakeup event AVLINK
    PM_WKUP_UART    = 11,  ///Wakeup event UART
    PM_WKUP_GPIO    = 12,   ///Wakeup event GPIO    
    PM_WKUP_MHL     = 13, ///Wakeup event MHL
    PM_WKUP_WOL     = 14  ///Wakeup event WOL
    //13~15: reserved
} PM_WkupSrc;

通过PM_WKUP_UART 事件唤醒。

你可能感兴趣的:(linux)