⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dloaduart.c

📁 在高通的手机平台下,一个下载手机.bin文件到手机的flash中的工具,包含PC端的程序代码和运行在基带处理器中的代码.
💻 C
字号:
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*

                   U A R T   D R I V E R

GENERAL DESCRIPTION
  This module contains a very simple-minded polling UART driver
  for the DMSS boot downloader facility.  This version supports
  the MSM 3.0 UART.

EXTERNALIZED FUNCTIONS
   dload_uart_init
      Initializes the UART for transmit and receive.

   uart_receive_byte
      Receives a single byte from the UART.

   uart_transmit_byte
      Transmits a single byte to the UART.

INITIALIZATION AND SEQUENCING REQUIREMENTS
  All necessary initialization for normal CPU operation must have
  been performed before entering this module.  dload_uart_init() should
  be called before any other functions.

  Copyright (c) 1995,1996,1997,1998,1999 by QUALCOMM Incorporated.
  All Rights Reserved.
*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/


/*===========================================================================

                           EDIT HISTORY FOR FILE
  This section contains comments describing changes made to the module.
  Notice that changes are listed in reverse chronological order.

$Header:   L:/src/asw/MSM5105/vcs/dloaduart.c_v   1.9   22 Mar 2001 09:26:28   robertom  $
   
when       who     what, where, why
--------   ---     ----------------------------------------------------------
03/21/01   rmd     In dload_uart_init(), replaced call to clk_rgm_sel() with the 
                   code inside the function to avoid dependency to code outside 
                   the boot code memory area.
03/21/01   rmd     Moved the micro clock switching code from dload_uart_init()
                   to boot_downloader() to make sure that the wait states get 
                   updated at the right time.
02/22/01   rmd     In dload_uart_init(), Added clk_regime_set_mclk_tcxo() to 
                   support MSM5100.
02/12/01   rmd     In dload_uart_init(), replaced clk_regime_switch_mclk_to_tcxo 
                   with mclk_switching_throttle() and eliminated call to 
                   clk_regime_init.
12/04/00   rmd     Modified clk_rgm_sel() call. this function uses 
                   a parameter of type clk_regime_clk_sel_type to recognize
                   which clk source we want to initialize.
11/23/00    et     changed MSM_OUTHM to clk_rgm_sel for the new clock API changes
11/22/00   rmd     Added clk_regime_switch_mclk_to_tcxo() call into dloaduart_init()
                   to switch MCLK source from 4/3 TCXO to TCXO before we get to 
                   download mode. 
09/03/00   rmd     Selecting TCXO/4 clock to drive UART in MSM_CLK_CTL5_WH
08/31/00   jcw     Merge of MSM5000 and MSM3300 versions
08/28/00   rmd     Replaced KICK_WATCHDOG with BOOTHW_KICK_WATCHDOG.
04/06/00   hrk     Selecting TCXO/4 clock to drive UART in MSM_CLK_CTL5_WH
03/31/00   hrk     Selecting TCXO clock to drive RXDSP in MSM_CLK_CTL5_WH
09/13/99   lcc     Merged from MSM5000PLT archive:
                   1. Changes to support UART clocks for MSM5000
                   2. Checkin of changes for initial port to MSM5000
                   3. Made changes necessary so that the uart drivers will work
                      under MSM5000. MR1, TFWR, RFWR and IPR register changed in width
                      as result of the increase in FIFO size.
08/11/99   kk      Merge from SS baseline.
03/17/99    ms     Renamed bb_uart_init to dload_uart_init
                   due to Virtual Boot Block changes.
08/08/98   hcg     Removed inline asm polling loop - Moved some stuff to header files.
07/26/98   hcg     Revised for coding standard, removed unused code
06/01/98   hcg     Ported from Flashprg by ptw

===========================================================================*/


/*===========================================================================

                     INCLUDE FILES FOR MODULE

===========================================================================*/



#include  "dloaduart.h"


dword MSM_image_H[ MSM_MAX_INX ];


/*-------------------------------------------------------------------------*/


/*===========================================================================

FUNCTION uart_drain

DESCRIPTION
  This function waits for the last character in the UART's transmit
  FIFO to be transmitted.  This allows the caller to be sure that all
  characters are transmitted.

DEPENDENCIES
  If the transmit FIFO is not empty, the UART must be initialized enough
  for it to eventually empty itself, or else this routine will wait
  forever.

RETURN VALUE
  None.

SIDE EFFECTS
  The watchdog is reset.

===========================================================================*/

void uart_drain(void)
{
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

   /* Wait while the UART's transmitter drains.  This lets the ACK to
      the GO command that started FLASHPRG get back to the PC before
      we reset the UART. */
   while ( ( inp(UART_SR) & UART_SR_TXEMT ) == 0)
      {
        BOOTHW_KICK_WATCHDOG();     /* Don't let the watchdog expire while we wait  */
      }

}/* uart_drain() */


/*===========================================================================

FUNCTION dload_uart_init

DESCRIPTION
  This function initializes the MSM 3000 UART to 115,200 bps, 8N1, with
  no interrupts enabled but both receiver and transmitter running.

  Before initializing the UART, this function waits for the UART's
  transmit buffer to empty out.  This permits the ACK to the GO
  command that started the program (or any other pending transmission)
  to get back to the host, instead of being lost when the UART is
  reset.

DEPENDENCIES
  If the transmit FIFO is not empty, the UART must be initialized enough
  for it to eventually empty itself, or else this routine will wait
  forever.

RETURN VALUE
  None.

SIDE EFFECTS
  The watchdog is reset.

===========================================================================*/

void dload_uart_init(word baud_rate)
{
  int chr; /* character variable for RX FIFO drain */

/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  /* Code copied from clk_rgm_sel(). We do not want to depend on code outside
     the boot code memory area. */
  MSM_OUTHM( UART_CLK_SEL_REG, UART_CLK_SEL_M, UART_CLK_SEL_TCXO4);

  /* drain anything in the UART */
  uart_drain();

  
 (void) MSMU_OUT(UART_MVR, UART_MVR_V);         /* M register LSB       */  
  (void) MSMU_OUT(UART_NVR, UART_NVR_V);         /* N register LSB       */
  (void) MSMU_OUT(UART_DVR, UART_DVR_V);         /* D register LSB       */
  (void) MSMU_OUT(UART_MNDR, UART_MNDR_V);       /* MSBs of M, N, and D  */

  (void) MSMU_OUT(UART_IMR, 0);                  /* Mask all interrupts off */

  /* Receive watermark at zero.  This means an interrupt would be generated 
   * whenever any (more than zero) characters are in the Rx FIFO.  Since we 
   * don't use Rx interrupts, this doesn't really matter.
   */
  (void) MSMU_RXWAT_OUT(0);
  
  /* Transmit watermark.  We DO use this, to determine if there is
   * room for one more character in the Tx FIFO.
   */
  (void) MSMU_TXWAT_OUT(UART_TXWAT_VAL);  
  
  /* Do not enable hardware flow control.  It works, but it causes
   * more trouble than it's worth with improperly-wired cables.
   * There's really no need for it anyway, since the main data flow
   * is from the host to the phone, and the phone (having nothing
   * better to do than service the UART) will always keep up.
   */

  (void) MSMU_MR1_OUT(0);
  
  (void) MSMU_OUT(UART_MR2, UART_MR2_8BPC | UART_MR2_1SB); /* 8N1 */


//switch(baud_rate)
//{
   // case UART_1152K_BPS:
   
        (void) MSMU_OUT(UART_CSR, UART_CSR_1152K_BPS); /* 115,200 baud rate   */

  //      break;
    //case UART_2304K_BPS:
    //    (void) MSMU_OUT(UART_CSR, UART_CSR_2304K_BPS); /* 230,400 baud rate   */
     //   break;
    //case UART_4608K_BPS:
     //   (void) MSMU_OUT(UART_CSR, UART_CSR_4608K_BPS); /* 460,800 baud rate   */
     //   break;
    //default:
      //  (void) MSMU_OUT(UART_CSR, UART_CSR_1152K_BPS); /* 115,200 baud rate   */
 //}




  //(void) MSMU_OUT(UART_CSR, UART_CSR_1152K_BPS); /* 115,200 baud rate   */





  (void) MSMU_OUT(UART_CR, UART_CR_RESET_ERR);   /* Reset error status     */
  (void) MSMU_OUT(UART_CR, UART_CR_RESET_RX);    /* Reset the receiver     */
  (void) MSMU_OUT(UART_CR, UART_CR_RESET_RX);    /* Reset the receiver     */
  (void) MSMU_OUT(UART_CR, UART_CR_RESET_TX);    /* Reset the transmitter  */
  (void) MSMU_OUT(UART_CR, UART_CR_RESET_TX);    /* Reset the transmitter  */
  (void) MSMU_OUT(UART_CR, UART_CR_RX_ENA);      /* Enable the receiver    */
  (void) MSMU_OUT(UART_CR, UART_CR_TX_ENA);      /* Enable the transmitter */

   /* Wait while the UART's reciever drains.  After resetting the UART, we
    * may have a couple of spurrious characters in the RX FIFO.  This can
    * happen especially when the phone is not plugged into a DIP, thus 
    * causing the UART to re-recognize the start of break condtion.
    */
   while ( ( inp(UART_SR) & UART_SR_RXRDY ) != 0)
      {
    chr = inp(UART_RFIFO);    /* Get the received character */  
        BOOTHW_KICK_WATCHDOG();    /* Don't let the watchdog expire while we wait  */
      }
} /* dload_uart_init() */



/*===========================================================================

FUNCTION dload_uart_poll

DESCRIPTION
  This function polls the UART for the presence of recieved data

DEPENDENCIES
  The UART must be initialized and enabled, or else this routine will
  wait forever.

RETURN VALUE
  If the RXRDY bit goes high (indicating the presence of data), we return
  the entire status register.  If timeout_enabled is true, we only wait for
  a few seconds.  Otherwise, we will wait forever for data to arrive

SIDE EFFECTS
  The watchdog timer will be kicked _very_ often.

===========================================================================*/
int dload_uart_poll(boolean timeout_enabled)
{
  int status;
  int countdown;

  /* if we're going to have a timeout */
  if (timeout_enabled)
    { 
      /* only loop a limited number of times */
      for (countdown = 1000000; countdown > 0; countdown--)
    {
      /* for each loop, get the status, and return it if data is present */
      status = inp(UART_SR);
      if ( (status & UART_SR_RXRDY) != 0)
        return status;

      /* kick the watchdog periodically */
      BOOTHW_KICK_WATCHDOG();
    }
      return UART_TIMEOUT;
    }
  else
    /* loop forever waiting for data */
    for (;;)
      {
    /* for each loop, get the status, and return it if data is present */
    status = inp(UART_SR);
    if ( (status & UART_SR_RXRDY) != 0)
      return status;

    /* kick the watchdog periodically */
    BOOTHW_KICK_WATCHDOG();
      }
} /* dload_uart_poll() */

/*===========================================================================

FUNCTION uart_receive_byte

DESCRIPTION
  This function receives a single byte from the UART by polling.

DEPENDENCIES
  The UART must be initialized and enabled, or else this routine will
  wait forever.

RETURN VALUE
  If a character is received without error, returns the value of the
  character received.  If an error occurs, returns UART_RX_ERR.  If a
  timeout occurs, returns UART_TIMEOUT.

SIDE EFFECTS

===========================================================================*/
int uart_receive_byte(void)
{
  int   status;
    /* Return value from the UART's status register */

  int   chr;
    /* The character received from the UART */

  static boolean init_boot = TRUE;
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /* poll the UART to receive a character if it is the initial 
   * communication with the PST we need to enable a timeout of 3 seconds.
   * otherwise, simply poll the UART indefinitely 
   */
  if (init_boot)
  {
    status = dload_uart_poll(TIMEOUT_ENABLED);
  }
  else
  {
    status = dload_uart_poll(TIMEOUT_DISABLED);
  }
      
  /* a timeout has occurred, return error */
  if ( (status == UART_TIMEOUT) && init_boot)
    return UART_TIMEOUT;
  
  /* There are three types of errors we can detect here:  Parity/Framing,
   * Break, and Overrun.  For a overrun, we just clear the error.  For 
   * parity/framing errors, we throw away that character.  For a break, we
   * ignore it.  We basically ignore conditions we can't do anything about.
   */
  if ((status & UART_SR_BREAK_RXD) != 0)
    {
      chr = inp(UART_RFIFO);           
      return UART_RX_ERR;
    }

  /* Check for an overrun error -- if one occurs, there isn't anything
   * we can do about it.  So, we'll just clear the error condition.  Since
   * this is character mode, the only other error we could be clearing is 
   * the hunt character, which we should never get.
   */
  /*  if ((status & UART_SR_OVR_ERR) != 0)
    (void) MSMU_OUT(UART_CR, UART_CR_RESET_ERR);*/

  /* Check for parity framing error -- if one occurs, discard the character
   * and return an error.  We can't trust that this character is valid.  It
   * might even be because of a break, so we leave init_boot true (or it's
   * current state, at least).
   */
  if ((status & UART_SR_PF_ERR) != 0)
    {
      chr = inp(UART_RFIFO);           
      return UART_RX_ERR;
    }

  /* Get the received character */
  chr = inp(UART_RFIFO);           
  init_boot = FALSE;
  return chr;                 /* All OK, return the received character */
} /* uart_receive_byte() */


/*===========================================================================

FUNCTION uart_transmit_byte

DESCRIPTION
  This function transmits a single byte through the UART.

DEPENDENCIES
  The UART transmitter must be initialized and enabled, or this routine
  will wait forever.

RETURN VALUE
  None.

SIDE EFFECTS
  The watchdog may be reset.

===========================================================================*/

void uart_transmit_byte
(
  byte  chr
    /* Character to be transmitted */
)

{
  
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  
  /* Wait until the transmit FIFO is not too full */
  while ((inp(UART_ISR) & UART_ISR_TXLEV) == 0)
  {
    /* Don't let the watchdog expire while we wait */
    BOOTHW_KICK_WATCHDOG();
  }

  /* Put the byte into the Tx FIFO  */
  (void) MSMU_OUT(UART_TFIFO, (int) chr);    

} /* uart_transmit_byte() */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -