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

📄 hal_uart.c

📁 一些基于IRA环境开发的zigbee实例程序
💻 C
📖 第 1 页 / 共 3 页
字号:
 *
 * @param   cfg - USART configuration structure.
 *
 * @return  none
 *****************************************************************************/
static void pollISR( uartCfg_t *cfg )
{
  uint8 cnt = UART_RX_AVAIL( cfg );

  if ( !(cfg->flag & UART_CFG_RXF) )
  {
    // If anything received, reset the Rx idle timer.
    if ( cfg->rxCnt != cnt )
    {
      cfg->rxTick = HAL_UART_RX_IDLE;
      cfg->rxCnt = cnt;
    }

    /* It is necessary to stop Rx flow in advance of a full Rx buffer because
     * bytes can keep coming while sending H/W fifo flushes.
     */
    if ( cfg->rxCnt >= (cfg->rxMax - SAFE_RX_MIN) )
    {
      RX_STOP_FLOW( cfg );
    }
  }
}
#endif

/******************************************************************************
 * @fn      HalUARTInit
 *
 * @brief   Initialize the UART
 *
 * @param   none
 *
 * @return  none
 *****************************************************************************/
void HalUARTInit( void )
{
#if HAL_UART_DMA
  halDMADesc_t *ch;
#endif

  // Set P2 priority - USART0 over USART1 if both are defined.
  P2DIR &= ~P2DIR_PRIPO;
  P2DIR |= HAL_UART_PRIPO;

#if HAL_UART_0_ENABLE
  // Set UART0 I/O location to P0.
  PERCFG &= ~HAL_UART_0_PERCFG_BIT;

  /* Enable Tx and Rx on P0 */
  P0SEL |= HAL_UART_0_P0_RX_TX;

  /* Make sure ADC doesnt use this */
  ADCCFG &= ~HAL_UART_0_P0_RX_TX;

  /* Mode is UART Mode */
  U0CSR = CSR_MODE;

  /* Flush it */
  U0UCR = UCR_FLUSH;
#endif

#if HAL_UART_1_ENABLE
  // Set UART1 I/O location to P1.
  PERCFG |= HAL_UART_1_PERCFG_BIT;

  /* Enable Tx and Rx on P1 */
  P1SEL  |= HAL_UART_1_P1_RX_TX;

  /* Make sure ADC doesnt use this */
  ADCCFG &= ~HAL_UART_1_P1_RX_TX;

  /* Mode is UART Mode */
  U1CSR = CSR_MODE;

  /* Flush it */
  U1UCR = UCR_FLUSH;
#endif

#if HAL_UART_DMA
  // Setup Tx by DMA.
  ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_TX );

  // The start address of the destination.
  HAL_DMA_SET_DEST( ch, DMA_UDBUF );

  // Using the length field to determine how many bytes to transfer.
  HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN );

  // One byte is transferred each time.
  HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_BYTE );

  // The bytes are transferred 1-by-1 on Tx Complete trigger.
  HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE );
  HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_TX );

  // The source address is decremented by 1 byte after each transfer.
  HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_1 );

  // The destination address is constant - the Tx Data Buffer.
  HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_0 );

  // The DMA is to be polled and shall not issue an IRQ upon completion.
  HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_DISABLE );

  // Xfer all 8 bits of a byte xfer.
  HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS );

  // DMA Tx has shared priority for memory access - every other one.
  HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH );

  // Setup Rx by DMA.
  ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_RX );

  // The start address of the source.
  HAL_DMA_SET_SOURCE( ch, DMA_UDBUF );

  // Using the length field to determine how many bytes to transfer.
  HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN );

  /* The trick is to cfg DMA to xfer 2 bytes for every 1 byte of Rx.
   * The byte after the Rx Data Buffer is the Baud Cfg Register,
   * which always has a known value. So init Rx buffer to inverse of that
   * known value. DMA word xfer will flip the bytes, so every valid Rx byte
   * in the Rx buffer will be preceded by a DMA_PAD char equal to the
   * Baud Cfg Register value.
   */
  HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_WORD );

  // The bytes are transferred 1-by-1 on Rx Complete trigger.
  HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE );
  HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_RX );

  // The source address is constant - the Rx Data Buffer.
  HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_0 );

  // The destination address is incremented by 1 word after each transfer.
  HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_1 );

  // The DMA is to be polled and shall not issue an IRQ upon completion.
  HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_DISABLE );

  // Xfer all 8 bits of a byte xfer.
  HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS );

  // DMA has highest priority for memory access.
  HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH );
#endif
}

/******************************************************************************
 * @fn      HalUARTOpen
 *
 * @brief   Open a port according tp the configuration specified by parameter.
 *
 * @param   port   - UART port
 *          config - contains configuration information
 *
 * @return  Status of the function call
 *****************************************************************************/
uint8 HalUARTOpen( uint8 port, halUARTCfg_t *config )
{
  uartCfg_t **cfgPP = NULL;
  uartCfg_t *cfg;

#if HAL_UART_0_ENABLE
  if ( port == HAL_UART_PORT_0 )
  {
    cfgPP = &cfg0;
  }
#endif

#if HAL_UART_1_ENABLE
  if ( port == HAL_UART_PORT_1 )
  {
    cfgPP = &cfg1;
  }
#endif

  HAL_UART_ASSERT( cfgPP );

#if HAL_UART_CLOSE
  // Protect against user re-opening port before closing it.
  HalUARTClose( port );
#else
  HAL_UART_ASSERT( *cfgPP == NULL );
#endif

  HAL_UART_ASSERT( (config->baudRate == HAL_UART_BR_38400) ||
                   (config->baudRate == HAL_UART_BR_115200) );

  /* Whereas runtime heap alloc can be expected to fail - one-shot system
   * initialization must succeed, so no check for alloc fail.
   */
  *cfgPP = (uartCfg_t *)osal_mem_alloc( sizeof( uartCfg_t ) );
  cfg = *cfgPP;
  HAL_UART_ASSERT( cfg );

  cfg->rxMax = config->rx.maxBufSize;

#if !HAL_UART_BIG_TX_BUF
  HAL_UART_ASSERT( (config->tx.maxBufSize < 256) );
#endif
  cfg->txMax = config->tx.maxBufSize;
  cfg->txBuf = osal_mem_alloc( cfg->txMax+1 );

  cfg->rxHead = cfg->rxTail = 0;
  cfg->txHead = cfg->txTail = 0;
  cfg->rxHigh = config->rx.maxBufSize - config->flowControlThreshold;
  cfg->rxCB = config->callBackFunc;

#if HAL_UART_0_ENABLE
  if ( port == HAL_UART_PORT_0 )
  {
    // Only supporting 38400 or 115200 for code size - other is possible.
    U0BAUD = (config->baudRate == HAL_UART_BR_38400) ? 59 : 216;
    U0GCR = (config->baudRate == HAL_UART_BR_38400) ? 10 : 11;

    U0CSR |= CSR_RE;

#if HAL_UART_DMA == 1
    cfg->flag = UART_CFG_DMA;
    HAL_UART_ASSERT( (config->rx.maxBufSize <= 128) );
    HAL_UART_ASSERT( (config->rx.maxBufSize > SAFE_RX_MIN) );
    cfg->rxBuf = osal_mem_alloc( cfg->rxMax*2 );
    osal_memset( cfg->rxBuf, ~DMA_PAD, cfg->rxMax*2 );
    DMA_RX( cfg );
#else
    cfg->flag = 0;
    HAL_UART_ASSERT( (config->rx.maxBufSize < 256) );
    cfg->rxBuf = osal_mem_alloc( cfg->rxMax+1 );
    URX0IE = 1;
    IEN2 |= UTX0IE;
#endif

    // 8 bits/char; no parity; 1 stop bit; stop bit hi.
    if ( config->flowControl )
    {
      cfg->flag |= UART_CFG_FLW;
      U0UCR = UCR_STOP; //UCR_FLOW |
      // Must rely on H/W for RTS (i.e. Tx stops when receiver negates CTS.)
      //P0SEL |= HAL_UART_0_P0_RTS;
      // Cannot use H/W for CTS as DMA does not clear the Rx bytes properly.
      //P0DIR |= HAL_UART_0_P0_CTS;
      //RX0_FLOW_ON;
    }
    else
    {
      U0UCR = UCR_STOP;
    }
    }
#endif

#if HAL_UART_1_ENABLE
  if ( port == HAL_UART_PORT_1 )
  {
    // Only supporting 38400 or 115200 for code size - other is possible.
    U1BAUD = (config->baudRate == HAL_UART_BR_38400) ? 59 : 216;
    U1GCR = (config->baudRate == HAL_UART_BR_38400) ? 10 : 11;

    U1CSR |= CSR_RE;

#if HAL_UART_DMA == 2
    cfg->flag = (UART_CFG_U1F | UART_CFG_DMA);
    HAL_UART_ASSERT( (config->rx.maxBufSize <= 128) );
    HAL_UART_ASSERT( (config->rx.maxBufSize > SAFE_RX_MIN) );
    cfg->rxBuf = osal_mem_alloc( cfg->rxMax*2 );
    osal_memset( cfg->rxBuf, ~DMA_PAD, cfg->rxMax*2 );
    DMA_RX( cfg );
#else
    cfg->flag = UART_CFG_U1F;
    HAL_UART_ASSERT( (config->rx.maxBufSize < 256) );
    cfg->rxBuf = osal_mem_alloc( cfg->rxMax+1 );
    URX1IE = 1;
    IEN2 |= UTX1IE;
#endif

    // 8 bits/char; no parity; 1 stop bit; stop bit hi.
    if ( config->flowControl )
    {
      cfg->flag |= UART_CFG_FLW;
      U1UCR = UCR_STOP; //UCR_FLOW |
      // Must rely on H/W for RTS (i.e. Tx stops when receiver negates CTS.)
      //P1SEL |= HAL_UART_1_P1_RTS;
      // Cannot use H/W for CTS as DMA does not clear the Rx bytes properly.
     // P1DIR |= HAL_UART_1_P1_CTS;
      //RX1_FLOW_ON;
    }
    else
    {
      U1UCR = UCR_STOP;
    }
  }
#endif

  return HAL_UART_SUCCESS;
}

/******************************************************************************
 * @fn      HalUARTClose
 *
 * @brief   Close the UART
 *
 * @param   port - UART port
 *
 * @return  none
 *****************************************************************************/
void HalUARTClose( uint8 port )
{
#if HAL_UART_CLOSE
  uartCfg_t *cfg;

#if HAL_UART_0_ENABLE
  if ( port == HAL_UART_PORT_0 )
  {
    U0CSR &= ~CSR_RE;
#if HAL_UART_DMA == 1
    HAL_DMA_ABORT_CH( HAL_DMA_CH_RX );
    HAL_DMA_ABORT_CH( HAL_DMA_CH_TX );
#else
    URX0IE = 0;
#endif
    cfg = cfg0;
    cfg0 = NULL;
  }
#endif
#if HAL_UART_1_ENABLE
  if ( port == HAL_UART_PORT_1 )
  {
    U1CSR &= ~CSR_RE;
#if HAL_UART_DMA == 2
    HAL_DMA_ABORT_CH( HAL_DMA_CH_RX );
    HAL_DMA_ABORT_CH( HAL_DMA_CH_TX );
#else
    URX1IE = 0;
#endif
    cfg = cfg1;
    cfg1 = NULL;
  }
#endif

  if ( cfg )
  {
    if ( cfg->rxBuf )
    {
      osal_mem_free( cfg->rxBuf );
    }
    if ( cfg->txBuf )
    {
      osal_mem_free( cfg->txBuf );
    }
    osal_mem_free( cfg );
  }
#endif
}

/******************************************************************************
 * @fn      HalUARTPoll
 *
 * @brief   Poll the UART.
 *
 * @param   none
 *
 * @return  none
 *****************************************************************************/
void HalUARTPoll( void )
{
#if ( HAL_UART_0_ENABLE | HAL_UART_1_ENABLE )
  static uint8 tickShdw;
  uartCfg_t *cfg;
  uint8 tick;

#if HAL_UART_0_ENABLE
  if ( cfg0 )
  {
    cfg = cfg0;
  }
#endif
#if HAL_UART_1_ENABLE
  if ( cfg1 )
  {
    cfg = cfg1;
  }
#endif

  // Use the LSB of the sleep timer (ST0 must be read first anyway).
  tick = ST0 - tickShdw;
  tickShdw = ST0;

  do
  {
    if ( cfg->txTick > tick )
    {
      cfg->txTick -= tick;
    }
    else
    {
      cfg->txTick = 0;
    }

⌨️ 快捷键说明

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