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

📄 hal_uart.c

📁 一些基于IRA环境开发的zigbee实例程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/**************************************************************************************************
  Filename:       _hal_uart.c
  Revised:        $Date: 2007-11-01 08:44:53 -0700 (Thu, 01 Nov 2007) $
  Revision:       $Revision: 15821 $

  Description: This file contains the interface to the H/W UART driver.


  Copyright 2006-2007 Texas Instruments Incorporated. All rights reserved.

  IMPORTANT: Your use of this Software is limited to those specific rights
  granted under the terms of a software license agreement between the user
  who downloaded the software, his/her employer (which must be your employer)
  and Texas Instruments Incorporated (the "License").  You may not use this
  Software unless you agree to abide by the terms of the License. The License
  limits your use, and you acknowledge, that the Software may not be modified,
  copied or distributed unless embedded on a Texas Instruments microcontroller
  or used solely and exclusively in conjunction with a Texas Instruments radio
  frequency transceiver, which is integrated into your product.  Other than for
  the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  works of, modify, distribute, perform, display or sell this Software and/or
  its documentation for any purpose.

  YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  PROVIDED 揂S IS?WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.

  Should you have any questions regarding your right to use this Software,
  contact Texas Instruments Incorporated at www.TI.com.
**************************************************************************************************/

/*********************************************************************
 * INCLUDES
 */

#include "hal_types.h"
#include "hal_assert.h"
#include "hal_board.h"
#include "hal_defs.h"
#if defined( HAL_UART_DMA ) && HAL_UART_DMA
  #include "hal_dma.h"
#endif
#include "hal_mcu.h"
#include "hal_uart.h"
#include "osal.h"

/*********************************************************************
 * MACROS
 */

#if !defined ( HAL_UART_DEBUG )
  #define HAL_UART_DEBUG  FALSE
#endif

#if !defined ( HAL_UART_CLOSE )
  #define HAL_UART_CLOSE  FALSE
#endif

#if !defined ( HAL_UART_BIG_TX_BUF )
  #define HAL_UART_BIG_TX_BUF  FALSE
#endif

/*
 *  The MAC_ASSERT macro is for use during debugging.
 *  The given expression must evaluate as "true" or else fatal error occurs.
 *  At that point, the call stack feature of the debugger can pinpoint where
 *  the problem occurred.
 *
 *  To disable this feature and save code size, the project should define
 *  HAL_UART_DEBUG to FALSE.
 */
#if ( HAL_UART_DEBUG )
  #define HAL_UART_ASSERT( expr)        HAL_ASSERT( expr )
#else
  #define HAL_UART_ASSERT( expr )
#endif

#define P2DIR_PRIPO               0xC0
#if HAL_UART_0_ENABLE
  #define HAL_UART_PRIPO          0x00
#else
  #define HAL_UART_PRIPO          0x40
#endif

#define HAL_UART_0_PERCFG_BIT     0x01  // USART0 on P0, so clear this bit.
#define HAL_UART_0_P0_RX_TX       0x0c  // Peripheral I/O Select for Rx/Tx.
#define HAL_UART_0_P0_RTS         0x10  // Peripheral I/O Select for RTS.
#define HAL_UART_0_P0_CTS         0x20  // Peripheral I/O Select for CTS.

#define HAL_UART_1_PERCFG_BIT     0x02  // USART1 on P1, so set this bit.
#define HAL_UART_1_P1_RTS         0x10  // Peripheral I/O Select for RTS.
#define HAL_UART_1_P1_CTS         0x20  // Peripheral I/O Select for CTS.
#define HAL_UART_1_P1_RX_TX       0xC0  // Peripheral I/O Select for Rx/Tx.

#define TX_AVAIL( cfg ) \
  ((cfg->txTail == cfg->txHead) ? (cfg->txMax-1) : \
  ((cfg->txTail >  cfg->txHead) ? (cfg->txTail - cfg->txHead - 1) : \
                     (cfg->txMax - cfg->txHead + cfg->txTail)))

#define RX0_FLOW_ON  ( P0 &= ~HAL_UART_0_P0_CTS )
#define RX0_FLOW_OFF ( P0 |= HAL_UART_0_P0_CTS )
#define RX1_FLOW_ON  ( P1 &= ~HAL_UART_1_P1_CTS)
#define RX1_FLOW_OFF ( P1 |= HAL_UART_1_P1_CTS )

#define RX_STOP_FLOW( cfg ) { \
  if ( !(cfg->flag & UART_CFG_U1F) ) \
  { \
    RX0_FLOW_OFF; \
  } \
  else \
  { \
    RX1_FLOW_OFF; \
  } \
  if ( cfg->flag & UART_CFG_DMA ) \
  { \
    cfg->rxTick = DMA_RX_DLY; \
  } \
  cfg->flag |= UART_CFG_RXF; \
}

#define RX_STRT_FLOW( cfg ) { \
  if ( !(cfg->flag & UART_CFG_U1F) ) \
  { \
    RX0_FLOW_ON; \
  } \
  else \
  { \
    RX1_FLOW_ON; \
  } \
  cfg->flag &= ~UART_CFG_RXF; \
}

#define UART_RX_AVAIL( cfg ) \
  ( (cfg->rxHead >= cfg->rxTail) ? (cfg->rxHead - cfg->rxTail) : \
                                   (cfg->rxMax - cfg->rxTail + cfg->rxHead +1 ) )

/* Need to leave enough of the Rx buffer free to handle the incoming bytes
 * after asserting flow control, but before the transmitter has obeyed it.
 * At the max expected baud rate of 115.2k, 16 bytes will only take ~1.3 msecs,
 * but at the min expected baud rate of 38.4k, they could take ~4.2 msecs.
 * SAFE_RX_MIN and DMA_RX_DLY must both be consistent according to
 * the min & max expected baud rate.
 */
#if !defined( SAFE_RX_MIN )
  #define SAFE_RX_MIN  48  // bytes - max expected per poll @ 115.2k
  // 16 bytes @ 38.4 kBaud -> 4.16 msecs -> 138 32-kHz ticks.
  #define DMA_RX_DLY  140
  //  2 bytes @ 38.4 kBaud -> 0.52 msecs ->  17 32-kHz ticks.
  #define DMA_TX_DLY   20
#endif

// The timeout tick is at 32-kHz, so multiply msecs by 33.
#define RX_MSECS_TO_TICKS  33

// The timeout only supports 1 byte.
#if !defined( HAL_UART_RX_IDLE )
  #define HAL_UART_RX_IDLE  (6 * RX_MSECS_TO_TICKS)
#endif

// Only supporting 1 of the 2 USART modules to be driven by DMA at a time.
#if HAL_UART_DMA == 1
  #define DMATRIG_RX  HAL_DMA_TRIG_URX0
  #define DMATRIG_TX  HAL_DMA_TRIG_UTX0
  #define DMA_UDBUF   HAL_DMA_U0DBUF
  #define DMA_PAD     U0BAUD
#elif HAL_UART_DMA == 2
  #define DMATRIG_RX  HAL_DMA_TRIG_URX1
  #define DMATRIG_TX  HAL_DMA_TRIG_UTX1
  #define DMA_UDBUF   HAL_DMA_U1DBUF
  #define DMA_PAD     U1BAUD
#endif

#define DMA_RX( cfg ) { \
  volatile uint8 ft2430 = U0DBUF; \
  \
  halDMADesc_t *ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_RX ); \
  \
  HAL_DMA_SET_DEST( ch, cfg->rxBuf ); \
  \
  HAL_DMA_SET_LEN( ch, cfg->rxMax ); \
  \
  HAL_DMA_CLEAR_IRQ( HAL_DMA_CH_RX ); \
  \
  HAL_DMA_ARM_CH( HAL_DMA_CH_RX ); \
}

#define DMA_TX( cfg ) { \
  halDMADesc_t *ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_TX ); \
  \
  HAL_DMA_SET_SOURCE( ch, (cfg->txBuf + cfg->txTail) ); \
  \
  HAL_DMA_SET_LEN( ch, cfg->txCnt ); \
  \
  HAL_DMA_CLEAR_IRQ( HAL_DMA_CH_TX ); \
  \
  HAL_DMA_ARM_CH( HAL_DMA_CH_TX ); \
  \
  HAL_DMA_START_CH( HAL_DMA_CH_TX ); \
}

/*********************************************************************
 * TYPEDEFS
 */

typedef struct
{
  uint8 *rxBuf;
  uint8 rxHead;
  uint8 rxTail;
  uint8 rxMax;
  uint8 rxCnt;
  uint8 rxTick;
  uint8 rxHigh;

  uint8 *txBuf;
#if HAL_UART_BIG_TX_BUF
  uint16 txHead;
  uint16 txTail;
  uint16 txMax;
  uint16 txCnt;
#else
  uint8 txHead;
  uint8 txTail;
  uint8 txMax;
  uint8 txCnt;
#endif
  uint8 txTick;

  uint8 flag;

  halUARTCBack_t rxCB;
} uartCfg_t;

/*********************************************************************
 * CONSTANTS
 */

// Used by DMA macros to shift 1 to create a mask for DMA registers.
#define HAL_DMA_CH_TX    3
#define HAL_DMA_CH_RX    4

#define HAL_DMA_U0DBUF  0xDFC1
#define HAL_DMA_U1DBUF  0xDFF9

// UxCSR - USART Control and Status Register.
#define CSR_MODE      0x80
#define CSR_RE        0x40
#define CSR_SLAVE     0x20
#define CSR_FE        0x10
#define CSR_ERR       0x08
#define CSR_RX_BYTE   0x04
#define CSR_TX_BYTE   0x02
#define CSR_ACTIVE    0x01

// UxUCR - USART UART Control Register.
#define UCR_FLUSH     0x80
#define UCR_FLOW      0x40
#define UCR_D9        0x20
#define UCR_BIT9      0x10
#define UCR_PARITY    0x08
#define UCR_SPB       0x04
#define UCR_STOP      0x02
#define UCR_START     0x01

#define UTX0IE        0x04
#define UTX1IE        0x08

#define UART_CFG_U1F  0x80  // USART1 flag bit.
#define UART_CFG_DMA  0x40  // Port is using DMA.
#define UART_CFG_FLW  0x20  // Port is using flow control.
#define UART_CFG_SP4  0x10
#define UART_CFG_SP3  0x08
#define UART_CFG_SP2  0x04
#define UART_CFG_RXF  0x02  // Rx flow is disabled.
#define UART_CFG_TXF  0x01  // Tx is in process.

/*********************************************************************
 * GLOBAL VARIABLES
 */

/*********************************************************************
 * GLOBAL FUNCTIONS
 */

/*********************************************************************
 * LOCAL VARIABLES
 */

#if HAL_UART_0_ENABLE
static uartCfg_t *cfg0;
#endif
#if HAL_UART_1_ENABLE
static uartCfg_t *cfg1;
#endif

/*********************************************************************
 * LOCAL FUNCTIONS
 */

#if HAL_UART_DMA
static void pollDMA( uartCfg_t *cfg );
#endif
#if HAL_UART_ISR
static void pollISR( uartCfg_t *cfg );
#endif

#if HAL_UART_DMA
/******************************************************************************
 * @fn      pollDMA
 *
 * @brief   Poll a USART module implemented by DMA.
 *
 * @param   cfg - USART configuration structure.
 *
 * @return  none
 *****************************************************************************/
static void pollDMA( uartCfg_t *cfg )
{
  const uint8 cnt = cfg->rxHead;
  uint8 *pad = cfg->rxBuf+(cfg->rxHead*2);

  // Pack the received bytes to the front of the queue.
  while ( (*pad == DMA_PAD) && (cfg->rxHead < cfg->rxMax) )
  {
    cfg->rxBuf[cfg->rxHead++] = *(pad+1);
    pad += 2;
  }

  if ( !(cfg->flag & UART_CFG_RXF) )
  {
    /* It is necessary to stop Rx flow and wait for H/W-enqueued bytes still
     * incoming to stop before resetting the DMA Rx engine. If DMA Rx is
     * aborted during incoming data, a byte may be lost inside the engine
     * during the 2-step transfer process of read/write.
     */
    if ( cfg->rxHead >= (cfg->rxMax - SAFE_RX_MIN) )
    {
      RX_STOP_FLOW( cfg );
    }
    // If anything received, reset the Rx idle timer.
    else if ( cfg->rxHead != cnt )
    {
      cfg->rxTick = HAL_UART_RX_IDLE;
    }
  }
  else if ( !cfg->rxTick && (cfg->rxHead == cfg->rxTail) )
  {
    HAL_DMA_ABORT_CH( HAL_DMA_CH_RX );
    cfg->rxHead = cfg->rxTail = 0;
    osal_memset( cfg->rxBuf, ~DMA_PAD, cfg->rxMax*2 );
    DMA_RX( cfg );
    RX_STRT_FLOW( cfg );
  }

  if ( HAL_DMA_CHECK_IRQ( HAL_DMA_CH_TX ) )
  {
    HAL_DMA_CLEAR_IRQ( HAL_DMA_CH_TX );
    cfg->flag &= ~UART_CFG_TXF;
    cfg->txTick = DMA_TX_DLY;

    if ( (cfg->txMax - cfg->txCnt) < cfg->txTail )
    {
      cfg->txTail = 0;  // DMA can only run to the end of the Tx buffer.
    }
    else
    {
      cfg->txTail += cfg->txCnt;
    }
  }
  else if ( !(cfg->flag & UART_CFG_TXF) && !cfg->txTick )
  {
    if ( cfg->txTail != cfg->txHead )
    {
      if ( cfg->txTail < cfg->txHead )
      {
        cfg->txCnt = cfg->txHead - cfg->txTail;
      }
      else  // Can only run DMA engine up to max, then restart at zero.
      {
        cfg->txCnt = cfg->txMax - cfg->txTail + 1;
      }

      cfg->flag |= UART_CFG_TXF;
      DMA_TX( cfg );
    }
  }
}
#endif

#if HAL_UART_ISR
/******************************************************************************
 * @fn      pollISR
 *
 * @brief   Poll a USART module implemented by ISR.

⌨️ 快捷键说明

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