CC2538 ZigBee 芯片 两路UART串口同时使用

前言

  • 众所周知,CC2538 zigbee芯片物理上支持UART0和UART1,但是在Z-Stack协议栈里面只提供了UART1的代码支持,并没有提供UART0的代码支持,但是具体如何同时使用UART0,能不能两路同时使用,网上找不到任何介绍的,包括deyisupport网站在内。

  • 按照国外网站e2e.ti.com论坛提供的支持,TI技术人员说要自己修改hal_uart.c来实现支持两路UART,但是他自己也没有测试是否可行。

  • 经过我自己的验证证实,两路UART是可以同时工作的,只是代码需要做修改。

方法步骤

  • 首先定义宏UART_SIMULTANEOUS,来支持两路UART,修改C:\Texas Instruments\Z-Stack 3.0.0\Components\hal\target\CC2538目录下的hal_uart.c,内容如下:
/**************************************************************************************************
  Filename:       _hal_uart.c
  Revised:        $Date: 2013-05-17 11:25:11 -0700 (Fri, 17 May 2013) $
  Revision:       $Revision: 34355 $

  Description:    This file contains the interface to the UART.


  Copyright 2012-2013 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
 * ------------------------------------------------------------------------------------------------
 */

#if HAL_UART_USB
#include "_hal_uart_usb.c"
#else
#include "_hal_uart_isr.c"
#endif

/* ------------------------------------------------------------------------------------------------
 *                                           Global Functions
 * ------------------------------------------------------------------------------------------------
 */

/*************************************************************************************************
 * @fn      HalUARTInit()
 *
 * @brief   Initialize the UART
 *
 * @param   none
 *
 * @return  none
 *************************************************************************************************/
void HalUARTInit(void)
{
#if HAL_UART_USB
  HalUARTInitUSB();
#else
#if defined (UART_SIMULTANEOUS)
  HalUART0InitIsr();
  HalUART1InitIsr();
#else
  HalUART1InitIsr();                    //only initialize UART1
#endif /*UART_SIMULTANEOUS*/
#endif
}

/*************************************************************************************************
 * @fn      HalUARTOpen()
 *
 * @brief   Open a port based on the configuration
 *
 * @param   port   - UART port
 *          config - contains configuration information
 *          cBack  - Call back function where events will be reported back
 *
 * @return  Status of the function call
 *************************************************************************************************/
uint8 HalUARTOpen(uint8 port, halUARTCfg_t *config)
{
#if HAL_UART_USB
  (void)port;
  HalUARTOpenUSB(config);
  return HAL_UART_SUCCESS;
#else
#if defined (UART_SIMULTANEOUS)
  switch(port)
  {
  case HAL_UART_PORT_0:
    return(HalUART0OpenIsr(port, config));
    break;
  case HAL_UART_PORT_1:
    return(HalUART1OpenIsr(port, config));
    break;
  }
#else
  return(HalUART1OpenIsr(port, config));        //only open UART1
#endif /*UART_SIMULTANEOUS*/
#endif
}

/*************************************************************************************************
 * @fn      Hal_UARTPoll
 *
 * @brief   This routine simulate polling and has to be called by the main loop
 *
 * @param   void
 *
 * @return  void
 *************************************************************************************************/
void HalUARTPoll(void)
{
#ifdef HAL_UART_USB
  HalUARTPollUSB();
#else
#if defined (UART_SIMULTANEOUS)
  HalUART0PollIsr();
  HalUART1PollIsr();
#else
  HalUART1PollIsr();                            //only poll UART1
#endif /*UART_SIMULTANEOUS*/
#endif
}

/*************************************************************************************************
 * @fn      HalUARTClose()
 *
 * @brief   Close the UART
 *
 * @param   port - UART port (not used.)
 *
 * @return  none
 *************************************************************************************************/
void HalUARTClose(uint8 port)
{
#ifdef HAL_UART_USB

#else
#if defined (UART_SIMULTANEOUS)
  switch(port)
  {
  case HAL_UART_PORT_0:
    HalUART0CloseIsr(port);
    break;
  case HAL_UART_PORT_1:
    HalUART1CloseIsr(port);
    break;
  }
#else
 HalUART1CloseIsr(port);                        //only close UART1
#endif /*UART_SIMULTANEOUS*/
#endif
}

/*************************************************************************************************
 * @fn      HalUARTRead()
 *
 * @brief   Read a buffer from the UART
 *
 * @param   port - UART port (not used.)
 *          ppBuffer - pointer to a pointer that points to the data that will be read
 *          length - length of the requested buffer
 *
 * @return  length of buffer that was read
 *************************************************************************************************/
uint16 HalUARTRead ( uint8 port, uint8 *pBuffer, uint16 length )
{
#if HAL_UART_USB
  return HalUARTRx(pBuffer, length);
#else
#if defined (UART_SIMULTANEOUS)
  switch(port)
  {
  case HAL_UART_PORT_0:
    return (HalUART0ReadIsr( port, pBuffer, length ));
    break;
  case HAL_UART_PORT_1:
    return (HalUART1ReadIsr( port, pBuffer, length ));
    break;
  }
#else
  return (HalUART1ReadIsr( port, pBuffer, length ));            //only read UART1
#endif /*UART_SIMULTANEOUS*/
#endif
}

/*************************************************************************************************
 * @fn      HalUARTWrite()
 *
 * @brief   Write a buffer to the UART
 *
 * @param   port    - UART port (not used.)
 *          pBuffer - pointer to the buffer that will be written
 *          length  - length of
 *
 * @return  length of the buffer that was sent
 *************************************************************************************************/
uint16 HalUARTWrite(uint8 port, uint8 *pBuffer, uint16 length)
{
#if HAL_UART_USB
  return HalUARTTx(pBuffer, length);
#else
#if defined (UART_SIMULTANEOUS)
  switch(port)
  {
  case HAL_UART_PORT_0:
    return (HalUART0WriteIsr( port, pBuffer, length ));
    break;
  case HAL_UART_PORT_1:
    return (HalUART1WriteIsr( port, pBuffer, length ));
    break;
  }
#else
  return (HalUART1WriteIsr( port, pBuffer, length ));           //only write UART1
#endif /*UART_SIMULTANEOUS*/
#endif
}

/*************************************************************************************************
 * @fn      Hal_UART_RxBufLen()
 *
 * @brief   Calculate Rx Buffer length of a port
 *
 * @param   port - UART port (not used.)
 *
 * @return  length of current Rx Buffer
 *************************************************************************************************/
uint16 Hal_UART_RxBufLen (uint8 port)
{
#if HAL_UART_USB
  return HalUARTRxAvailUSB();
#else
#if defined (UART_SIMULTANEOUS)
  switch(port)
  {
  case HAL_UART_PORT_0:
    return (Hal_UART0_RxBufLenIsr(port));
    break;
  case HAL_UART_PORT_1:
    return (Hal_UART1_RxBufLenIsr(port));
    break;
  }
#else
  return (Hal_UART1_RxBufLenIsr(port));                         //only get UART1 length
#endif /*UART_SIMULTANEOUS*/
#endif
}

/**************************************************************************************************
*/
  • 其次继续修改C:\Texas Instruments\Z-Stack 3.0.0\Components\hal\target\CC2538\hal_uart_isr.c文件,内容如下:
/**************************************************************************************************
  Filename:       _hal_uart_isr.c
  Revised:        $Date: 2014-12-05 13:07:19 -0800 (Fri, 05 Dec 2014) $
  Revision:       $Revision: 41365 $

  Description:    This file contains the interface to the UART.


  Copyright 2013-2014 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_board.h"
#include "hal_types.h"
#include "hal_uart.h"
#include "OSAL.h"
#include "OSAL_Timers.h"
#include "hw_ioc.h"
#include "hw_uart.h"

/* ------------------------------------------------------------------------------------------------
 *                                           Constants
 * ------------------------------------------------------------------------------------------------
 */
#define HAL_UART0_PORT                      UART0_BASE
#define HAL_UART0_SYS_CTRL                  SYS_CTRL_PERIPH_UART0
#define HAL_UART0_INT_CTRL                  INT_UART0
#define HalUart0ISR                         interrupt_uart0

#define HAL_UART1_PORT                      UART1_BASE
#define HAL_UART1_SYS_CTRL                  SYS_CTRL_PERIPH_UART1
#define HAL_UART1_INT_CTRL                  INT_UART1
#define HalUart1ISR                         interrupt_uart1

/* ------------------------------------------------------------------------------------------------
 *                                           Local Variables
 * ------------------------------------------------------------------------------------------------
 */

const uint32 UBRRTable[] = {
  9600,
  19200,
  38400,
  57600,
  115200
};

static halUARTCfg_t uartRecord0;
static bool txMT0;

static halUARTCfg_t uartRecord1;
static bool txMT1;

/* ------------------------------------------------------------------------------------------------
 *                                           Local Functions
 * ------------------------------------------------------------------------------------------------
 */

static void recRstUART0(void);
static void procRxUART0(void);
static void procTxUART0(void);

/* ------------------------------------------------------------------------------------------------
 *                                           Global Functions
 * ------------------------------------------------------------------------------------------------
 */

void HalUART0InitIsr(void);
uint8 HalUART0OpenIsr(uint8 port, halUARTCfg_t *config);
void HalUART0PollIsr(void);
void HalUART0CloseIsr(uint8 port);
uint16 HalUART0ReadIsr ( uint8 port, uint8 *pBuffer, uint16 length );
uint16 HalUART0WriteIsr(uint8 port, uint8 *pBuffer, uint16 length);
uint16 Hal_UART0_RxBufLenIsr(uint8 port);
void HalUart0ISR(void);

/* ------------------------------------------------------------------------------------------------
 *                                           Local Functions
 * ------------------------------------------------------------------------------------------------
 */

static void recRstUART1(void);
static void procRxUART1(void);
static void procTxUART1(void);

/* ------------------------------------------------------------------------------------------------
 *                                           Global Functions
 * ------------------------------------------------------------------------------------------------
 */

void HalUART1InitIsr(void);
uint8 HalUART1OpenIsr(uint8 port, halUARTCfg_t *config);
void HalUART1PollIsr(void);
void HalUART1CloseIsr(uint8 port);
uint16 HalUART1ReadIsr ( uint8 port, uint8 *pBuffer, uint16 length );
uint16 HalUART1WriteIsr(uint8 port, uint8 *pBuffer, uint16 length);
uint16 Hal_UART1_RxBufLenIsr(uint8 port);
void HalUart1ISR(void);

/*************************************************************************************************
 * @fn      HalUART0InitIsr()
 *
 * @brief   Initialize the UART
 *
 * @param   none
 *
 * @return  none
 *************************************************************************************************/
void HalUART0InitIsr(void)
{
   SysCtrlPeripheralEnable(HAL_UART0_SYS_CTRL);

  /*  
   * PA5 as UART_TX and PA4 as UART_RX
   */ 
  IOCPinConfigPeriphOutput(GPIO_A_BASE, GPIO_PIN_5, IOC_MUX_OUT_SEL_UART0_TXD);
  IOCPinConfigPeriphInput(GPIO_A_BASE, GPIO_PIN_4, IOC_UARTRXD_UART0);
  GPIOPinTypeUARTInput(GPIO_A_BASE, GPIO_PIN_4);
  GPIOPinTypeUARTOutput(GPIO_A_BASE, GPIO_PIN_5);  
  recRstUART0();

}

/*************************************************************************************************
 * @fn      HalUART1InitIsr()
 *
 * @brief   Initialize the UART
 *
 * @param   none
 *
 * @return  none
 *************************************************************************************************/
void HalUART1InitIsr(void)
{
   SysCtrlPeripheralEnable(HAL_UART1_SYS_CTRL);

  /* Setup PB0 as UART_CTS, PD3 as UART_RTS  
   * PA1 as UART_TX and PA0 as UART_RX
   */ 
  IOCPinConfigPeriphOutput(GPIO_A_BASE, GPIO_PIN_1, IOC_MUX_OUT_SEL_UART1_TXD);
  IOCPinConfigPeriphInput(GPIO_A_BASE, GPIO_PIN_0, IOC_UARTRXD_UART1);
  GPIOPinTypeUARTInput(GPIO_A_BASE, GPIO_PIN_0);
  GPIOPinTypeUARTOutput(GPIO_A_BASE, GPIO_PIN_1);  
  recRstUART1();

}

/*************************************************************************************************
 * @fn      HalUART0OpenIsr()
 *
 * @brief   Open a port based on the configuration
 *
 * @param   port   - UART port
 *          config - contains configuration information
 *          cBack  - Call back function where events will be reported back
 *
 * @return  Status of the function call
 *************************************************************************************************/
uint8 HalUART0OpenIsr(uint8 port, halUARTCfg_t *config)
{
  if (uartRecord0.configured)
  {
    HalUARTClose(port);
  }

  if (config->baudRate > HAL_UART_BR_115200)
  {
    return HAL_UART_BAUDRATE_ERROR;
  }

  if (((uartRecord0.rx.pBuffer = osal_mem_alloc(config->rx.maxBufSize)) == NULL) ||
      ((uartRecord0.tx.pBuffer = osal_mem_alloc(config->tx.maxBufSize)) == NULL))
  {
    if (uartRecord0.rx.pBuffer != NULL)
    {
      osal_mem_free(uartRecord0.rx.pBuffer);
      uartRecord0.rx.pBuffer = NULL;
    }

    return HAL_UART_MEM_FAIL;
  }

#if 0
  //UART0 don't support RTS/CTS flowcontrol
  if(config->flowControl)
  {
    IOCPinConfigPeriphOutput(GPIO_D_BASE, GPIO_PIN_3, IOC_MUX_OUT_SEL_UART1_RTS);
    GPIOPinTypeUARTOutput(GPIO_D_BASE, GPIO_PIN_3);
    IOCPinConfigPeriphInput(GPIO_B_BASE, GPIO_PIN_0, IOC_UARTCTS_UART1);
    GPIOPinTypeUARTInput(GPIO_B_BASE, GPIO_PIN_0);
  }
#endif  
  IntEnable(HAL_UART0_INT_CTRL);

  uartRecord0.configured = TRUE;
  uartRecord0.baudRate = config->baudRate;
  uartRecord0.flowControl = config->flowControl;
  uartRecord0.flowControlThreshold = (config->flowControlThreshold > config->rx.maxBufSize) ? 0 :
                                     config->flowControlThreshold;
  uartRecord0.idleTimeout = config->idleTimeout;
  uartRecord0.rx.maxBufSize = config->rx.maxBufSize;
  uartRecord0.tx.maxBufSize = config->tx.maxBufSize;
  uartRecord0.intEnable = config->intEnable;
  uartRecord0.callBackFunc = config->callBackFunc;

  UARTConfigSetExpClk(HAL_UART0_PORT, SysCtrlClockGet(), UBRRTable[uartRecord0.baudRate],
                         (UART_CONFIG_WLEN_8 | UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE));

  /* FIFO level set to 1/8th for both RX and TX which is 2 bytes */
  UARTFIFOLevelSet(HAL_UART0_PORT, UART_FIFO_TX1_8, UART_FIFO_RX1_8);
  UARTFIFOEnable(HAL_UART0_PORT);

  /* Clear and enable UART TX, RX, CTS and Recieve Timeout interrupt */
  UARTIntClear(HAL_UART0_PORT, (UART_INT_RX | UART_INT_TX /*| UART_INT_CTS*/ | UART_INT_RT ));
  UARTIntEnable(HAL_UART0_PORT, (UART_INT_RX | UART_INT_TX /*| UART_INT_CTS*/ | UART_INT_RT ));

  //if(config->flowControl)
  //{
    /* Enable hardware flow control by enabling CTS and RTS */
  //  HWREG(HAL_UART0_PORT + UART_O_CTL) |= (UART_CTL_CTSEN | UART_CTL_RTSEN );
  //}

  UARTEnable(HAL_UART0_PORT);

  return HAL_UART_SUCCESS;
}

/*************************************************************************************************
 * @fn      HalUART1OpenIsr()
 *
 * @brief   Open a port based on the configuration
 *
 * @param   port   - UART port
 *          config - contains configuration information
 *          cBack  - Call back function where events will be reported back
 *
 * @return  Status of the function call
 *************************************************************************************************/
uint8 HalUART1OpenIsr(uint8 port, halUARTCfg_t *config)
{
  if (uartRecord1.configured)
  {
    HalUARTClose(port);
  }

  if (config->baudRate > HAL_UART_BR_115200)
  {
    return HAL_UART_BAUDRATE_ERROR;
  }

  if (((uartRecord1.rx.pBuffer = osal_mem_alloc(config->rx.maxBufSize)) == NULL) ||
      ((uartRecord1.tx.pBuffer = osal_mem_alloc(config->tx.maxBufSize)) == NULL))
  {
    if (uartRecord1.rx.pBuffer != NULL)
    {
      osal_mem_free(uartRecord1.rx.pBuffer);
      uartRecord1.rx.pBuffer = NULL;
    }

    return HAL_UART_MEM_FAIL;
  }

  //TODO: modify flowControl pins
  if(config->flowControl)
  {
    IOCPinConfigPeriphOutput(GPIO_D_BASE, GPIO_PIN_3, IOC_MUX_OUT_SEL_UART1_RTS);
    GPIOPinTypeUARTOutput(GPIO_D_BASE, GPIO_PIN_3);
    IOCPinConfigPeriphInput(GPIO_B_BASE, GPIO_PIN_0, IOC_UARTCTS_UART1);
    GPIOPinTypeUARTInput(GPIO_B_BASE, GPIO_PIN_0);
  }

  IntEnable(HAL_UART1_INT_CTRL);

  uartRecord1.configured = TRUE;
  uartRecord1.baudRate = config->baudRate;
  uartRecord1.flowControl = config->flowControl;
  uartRecord1.flowControlThreshold = (config->flowControlThreshold > config->rx.maxBufSize) ? 0 :
                                     config->flowControlThreshold;
  uartRecord1.idleTimeout = config->idleTimeout;
  uartRecord1.rx.maxBufSize = config->rx.maxBufSize;
  uartRecord1.tx.maxBufSize = config->tx.maxBufSize;
  uartRecord1.intEnable = config->intEnable;
  uartRecord1.callBackFunc = config->callBackFunc;

  UARTConfigSetExpClk(HAL_UART1_PORT, SysCtrlClockGet(), UBRRTable[uartRecord1.baudRate],
                         (UART_CONFIG_WLEN_8 | UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE));

  /* FIFO level set to 1/8th for both RX and TX which is 2 bytes */
  UARTFIFOLevelSet(HAL_UART1_PORT, UART_FIFO_TX1_8, UART_FIFO_RX1_8);
  UARTFIFOEnable(HAL_UART1_PORT);

  /* Clear and enable UART TX, RX, CTS and Recieve Timeout interrupt */
  UARTIntClear(HAL_UART1_PORT, (UART_INT_RX | UART_INT_TX | UART_INT_CTS | UART_INT_RT ));
  UARTIntEnable(HAL_UART1_PORT, (UART_INT_RX | UART_INT_TX | UART_INT_CTS | UART_INT_RT ));

  if(config->flowControl)
  {
    /* Enable hardware flow control by enabling CTS and RTS */
    HWREG(HAL_UART1_PORT + UART_O_CTL) |= (UART_CTL_CTSEN | UART_CTL_RTSEN );
  }
  UARTEnable(HAL_UART1_PORT);

  return HAL_UART_SUCCESS;
}

/*************************************************************************************************
 * @fn      HalUART0PollIsr
 *
 * @brief   This routine simulate polling and has to be called by the main loop
 *
 * @param   void
 *
 * @return  void
 *************************************************************************************************/
void HalUART0PollIsr(void)
{
  uint16 head = uartRecord0.tx.bufferHead;
  uint16 tail = uartRecord0.tx.bufferTail;
  /* If port is not configured, no point to poll it. */
  if (!uartRecord0.configured)  
  {
    return;
  }

  halIntState_t intState;
  HAL_ENTER_CRITICAL_SECTION(intState);
  procRxUART0();
  procTxUART0();
  HAL_EXIT_CRITICAL_SECTION(intState);

  uint8 evts = 0;
  /* Report if Rx Buffer is full. */
  if ((Hal_UART_RxBufLen(HAL_UART_PORT_0) + 1) >= uartRecord0.rx.maxBufSize)  
  {
    evts = HAL_UART_RX_FULL;
  }

  /* Report if Rx Buffer is idled. */
  if ((uartRecord0.rxChRvdTime != 0) &&  
     ((osal_GetSystemClock() - uartRecord0.rxChRvdTime) > uartRecord0.idleTimeout))
  {
    uartRecord0.rxChRvdTime = 0;
    evts |= HAL_UART_RX_TIMEOUT;
  }

  if (Hal_UART_RxBufLen(HAL_UART_PORT_0) >= uartRecord0.rx.maxBufSize - uartRecord0.flowControlThreshold)
  {
    evts |= HAL_UART_RX_ABOUT_FULL;
  }

  if (!txMT0 && (head == tail))
  {
    txMT0 = true;
    evts |= HAL_UART_TX_EMPTY;
  }

  if (evts && uartRecord0.callBackFunc)
  {
    (uartRecord0.callBackFunc)(HAL_UART_PORT_0, evts);
  }

}

/*************************************************************************************************
 * @fn      HalUART1PollIsr
 *
 * @brief   This routine simulate polling and has to be called by the main loop
 *
 * @param   void
 *
 * @return  void
 *************************************************************************************************/
void HalUART1PollIsr(void)
{
  uint16 head = uartRecord1.tx.bufferHead;
  uint16 tail = uartRecord1.tx.bufferTail;
  /* If port is not configured, no point to poll it. */
  if (!uartRecord1.configured)  
  {
    return;
  }

  halIntState_t intState;
  HAL_ENTER_CRITICAL_SECTION(intState);
  procRxUART1();
  procTxUART1();
  HAL_EXIT_CRITICAL_SECTION(intState);

  uint8 evts = 0;
  /* Report if Rx Buffer is full. */
  if ((Hal_UART_RxBufLen(HAL_UART_PORT_1) + 1) >= uartRecord1.rx.maxBufSize)  
  {
    evts = HAL_UART_RX_FULL;
  }

  /* Report if Rx Buffer is idled. */
  if ((uartRecord1.rxChRvdTime != 0) &&  
     ((osal_GetSystemClock() - uartRecord1.rxChRvdTime) > uartRecord1.idleTimeout))
  {
    uartRecord1.rxChRvdTime = 0;
    evts |= HAL_UART_RX_TIMEOUT;
  }

  if (Hal_UART_RxBufLen(HAL_UART_PORT_1) >= uartRecord1.rx.maxBufSize - uartRecord1.flowControlThreshold)
  {
    evts |= HAL_UART_RX_ABOUT_FULL;
  }

  if (!txMT1 && (head == tail))
  {
    txMT1 = true;
    evts |= HAL_UART_TX_EMPTY;
  }

  if (evts && uartRecord1.callBackFunc)
  {
    (uartRecord1.callBackFunc)(HAL_UART_PORT_1, evts);
  }

}

/*************************************************************************************************
 * @fn      HalUART0CloseIsr()
 *
 * @brief   Close the UART
 *
 * @param   port - UART port (not used.)
 *
 * @return  none
 *************************************************************************************************/
void HalUART0CloseIsr(uint8 port)
{
  (void)port;

  UARTDisable(HAL_UART0_PORT);

  if (uartRecord0.configured)
  {
    (void)osal_mem_free(uartRecord0.rx.pBuffer);
    (void)osal_mem_free(uartRecord0.tx.pBuffer);
    recRstUART0();
  }
}

/*************************************************************************************************
 * @fn      HalUART1CloseIsr()
 *
 * @brief   Close the UART
 *
 * @param   port - UART port (not used.)
 *
 * @return  none
 *************************************************************************************************/
void HalUART1CloseIsr(uint8 port)
{
  (void)port;

  UARTDisable(HAL_UART1_PORT);

  if (uartRecord1.configured)
  {
    (void)osal_mem_free(uartRecord1.rx.pBuffer);
    (void)osal_mem_free(uartRecord1.tx.pBuffer);
    recRstUART1();
  }
}

/*************************************************************************************************
 * @fn      HalUART0ReadIsr()
 *
 * @brief   Read a buffer from the UART
 *
 * @param   port - UART port (not used.)
 *          ppBuffer - pointer to a pointer that points to the data that will be read
 *          length - length of the requested buffer
 *
 * @return  length of buffer that was read
 *************************************************************************************************/
uint16 HalUART0ReadIsr ( uint8 port, uint8 *pBuffer, uint16 length )
{
  uint16 cnt, idx;
  (void)port;

  /* If port is not configured, no point to read it. */
  if (!uartRecord0.configured)
  {
    return 0;
  }

  /* If requested length is bigger than what in 
   * buffer, re-adjust it to the buffer length.
   */
  cnt = Hal_UART_RxBufLen(port);
  if (cnt < length)
  {
    length = cnt;
  }

  idx = uartRecord0.rx.bufferHead;
  for (cnt = 0; cnt < length; cnt++)
  {
    pBuffer[cnt] = uartRecord0.rx.pBuffer[idx++];

    if (idx >= uartRecord0.rx.maxBufSize)
    {
      idx = 0;
    }
  }
  uartRecord0.rx.bufferHead = idx;

  /* Return number of bytes read. */
  return length;  
}

/*************************************************************************************************
 * @fn      HalUART1ReadIsr()
 *
 * @brief   Read a buffer from the UART
 *
 * @param   port - UART port (not used.)
 *          ppBuffer - pointer to a pointer that points to the data that will be read
 *          length - length of the requested buffer
 *
 * @return  length of buffer that was read
 *************************************************************************************************/
uint16 HalUART1ReadIsr ( uint8 port, uint8 *pBuffer, uint16 length )
{
  uint16 cnt, idx;
  (void)port;

  /* If port is not configured, no point to read it. */
  if (!uartRecord1.configured)
  {
    return 0;
  }

  /* If requested length is bigger than what in 
   * buffer, re-adjust it to the buffer length.
   */
  cnt = Hal_UART_RxBufLen(port);
  if (cnt < length)
  {
    length = cnt;
  }

  idx = uartRecord1.rx.bufferHead;
  for (cnt = 0; cnt < length; cnt++)
  {
    pBuffer[cnt] = uartRecord1.rx.pBuffer[idx++];

    if (idx >= uartRecord1.rx.maxBufSize)
    {
      idx = 0;
    }
  }
  uartRecord1.rx.bufferHead = idx;

  /* Return number of bytes read. */
  return length;  
}

/*************************************************************************************************
 * @fn      HalUART0WriteIsr()
 *
 * @brief   Write a buffer to the UART
 *
 * @param   port    - UART port (not used.)
 *          pBuffer - pointer to the buffer that will be written
 *          length  - length of
 *
 * @return  length of the buffer that was sent
 *************************************************************************************************/
uint16 HalUART0WriteIsr(uint8 port, uint8 *pBuffer, uint16 length)
{
  (void)port;

  if (!uartRecord0.configured)
  {
    return 0;
  }

  uint16 idx = uartRecord0.tx.bufferHead;
  uint16 cnt = uartRecord0.tx.bufferTail;

  if (cnt == idx)
  {
    cnt = uartRecord0.tx.maxBufSize;
  }
  else if (cnt > idx)
  {
    cnt = uartRecord0.tx.maxBufSize - cnt + idx;
  }
  else /* (cnt < idx) */
  {
    cnt = idx - cnt;
  }

  /* Accept "all-or-none" on write request. */
  if (cnt < length)
  {
    return 0;
  }

  txMT0 = false;
  idx = uartRecord0.tx.bufferTail;

  for (cnt = 0; cnt < length; cnt++)
  {
    uartRecord0.tx.pBuffer[idx++] = pBuffer[cnt];

    if (idx >= uartRecord0.tx.maxBufSize)
    {
      idx = 0;
    }
  }

  halIntState_t intState;
  HAL_ENTER_CRITICAL_SECTION(intState);
  uartRecord0.tx.bufferTail = idx;
  procTxUART0();
  HAL_EXIT_CRITICAL_SECTION(intState);

  /* Return the number of bytes actually put into the buffer. */
  return length;  
}

/*************************************************************************************************
 * @fn      HalUART1WriteIsr()
 *
 * @brief   Write a buffer to the UART
 *
 * @param   port    - UART port (not used.)
 *          pBuffer - pointer to the buffer that will be written
 *          length  - length of
 *
 * @return  length of the buffer that was sent
 *************************************************************************************************/
uint16 HalUART1WriteIsr(uint8 port, uint8 *pBuffer, uint16 length)
{
  (void)port;

  if (!uartRecord1.configured)
  {
    return 0;
  }

  uint16 idx = uartRecord1.tx.bufferHead;
  uint16 cnt = uartRecord1.tx.bufferTail;

  if (cnt == idx)
  {
    cnt = uartRecord1.tx.maxBufSize;
  }
  else if (cnt > idx)
  {
    cnt = uartRecord1.tx.maxBufSize - cnt + idx;
  }
  else /* (cnt < idx) */
  {
    cnt = idx - cnt;
  }

  /* Accept "all-or-none" on write request. */
  if (cnt < length)
  {
    return 0;
  }

  txMT1 = false;
  idx = uartRecord1.tx.bufferTail;

  for (cnt = 0; cnt < length; cnt++)
  {
    uartRecord1.tx.pBuffer[idx++] = pBuffer[cnt];

    if (idx >= uartRecord1.tx.maxBufSize)
    {
      idx = 0;
    }
  }

  halIntState_t intState;
  HAL_ENTER_CRITICAL_SECTION(intState);
  uartRecord1.tx.bufferTail = idx;
  procTxUART1();
  HAL_EXIT_CRITICAL_SECTION(intState);

  /* Return the number of bytes actually put into the buffer. */
  return length;  
}

/*************************************************************************************************
 * @fn      Hal_UART0_RxBufLenIsr()
 *
 * @brief   Calculate Rx Buffer length of a port
 *
 * @param   port - UART port (not used.)
 *
 * @return  length of current Rx Buffer
 *************************************************************************************************/
uint16 Hal_UART0_RxBufLenIsr(uint8 port)
{
  int16 length = uartRecord0.rx.bufferTail;
  (void)port;

  length -= uartRecord0.rx.bufferHead;
  if  (length < 0)
    length += uartRecord0.rx.maxBufSize;

  return (uint16)length;
}

/*************************************************************************************************
 * @fn      Hal_UART1_RxBufLenIsr()
 *
 * @brief   Calculate Rx Buffer length of a port
 *
 * @param   port - UART port (not used.)
 *
 * @return  length of current Rx Buffer
 *************************************************************************************************/
uint16 Hal_UART1_RxBufLenIsr(uint8 port)
{
  int16 length = uartRecord1.rx.bufferTail;
  (void)port;

  length -= uartRecord1.rx.bufferHead;
  if  (length < 0)
    length += uartRecord1.rx.maxBufSize;

  return (uint16)length;
}

/*************************************************************************************************
 * @fn      Hal_UART0_TxBufLen()
 *
 * @brief   Calculate Tx Buffer length of a port
 *
 * @param   port - UART port (not used.)
 *
 * @return  length of current Tx buffer
 *************************************************************************************************/
uint16 Hal_UART0_TxBufLen( uint8 port )
{
  int16 length = uartRecord0.tx.bufferTail;
  (void)port;

  length -= uartRecord0.tx.bufferHead;
  if  (length < 0)
    length += uartRecord0.tx.maxBufSize;

  return (uint16)length;
}

/*************************************************************************************************
 * @fn      Hal_UART1_TxBufLen()
 *
 * @brief   Calculate Tx Buffer length of a port
 *
 * @param   port - UART port (not used.)
 *
 * @return  length of current Tx buffer
 *************************************************************************************************/
uint16 Hal_UART1_TxBufLen( uint8 port )
{
  int16 length = uartRecord1.tx.bufferTail;
  (void)port;

  length -= uartRecord1.tx.bufferHead;
  if  (length < 0)
    length += uartRecord1.tx.maxBufSize;

  return (uint16)length;
}

/*************************************************************************************************
 * @fn      recRstUART0()
 *
 * @brief   Reset the UART record.
 *
 * @param   none
 *
 * @return  none
 *************************************************************************************************/
static void recRstUART0(void)
{
  uartRecord0.configured        = FALSE;
  uartRecord0.rx.bufferHead     = 0;
  uartRecord0.rx.bufferTail     = 0;
  uartRecord0.rx.pBuffer        = (uint8 *)NULL;
  uartRecord0.tx.bufferHead     = 0;
  uartRecord0.tx.bufferTail     = 0;
  uartRecord0.tx.pBuffer        = (uint8 *)NULL;
  uartRecord0.rxChRvdTime       = 0;
  uartRecord0.intEnable         = FALSE;
}

/*************************************************************************************************
 * @fn      recRstUART1()
 *
 * @brief   Reset the UART record.
 *
 * @param   none
 *
 * @return  none
 *************************************************************************************************/
static void recRstUART1(void)
{
  uartRecord1.configured        = FALSE;
  uartRecord1.rx.bufferHead     = 0;
  uartRecord1.rx.bufferTail     = 0;
  uartRecord1.rx.pBuffer        = (uint8 *)NULL;
  uartRecord1.tx.bufferHead     = 0;
  uartRecord1.tx.bufferTail     = 0;
  uartRecord1.tx.pBuffer        = (uint8 *)NULL;
  uartRecord1.rxChRvdTime       = 0;
  uartRecord1.intEnable         = FALSE;
}

/*************************************************************************************************
 * @fn      procRxUART0
 *
 * @brief   Process Tx bytes.
 *
 * @param   void
 *
 * @return  void
 *************************************************************************************************/
static void procRxUART0(void)
{
  uint16 tail = uartRecord0.rx.bufferTail;

  while (UARTCharsAvail(HAL_UART0_PORT))
  {
    uartRecord0.rx.pBuffer[tail++] = UARTCharGetNonBlocking(HAL_UART0_PORT);

    if (tail >= uartRecord0.rx.maxBufSize)
    {
      tail = 0;
    }
  }

  if (uartRecord0.rx.bufferTail != tail)
  {
    uartRecord0.rx.bufferTail = tail;
    uartRecord0.rxChRvdTime = osal_GetSystemClock();
  }
}

/*************************************************************************************************
 * @fn      procRxUART1
 *
 * @brief   Process Tx bytes.
 *
 * @param   void
 *
 * @return  void
 *************************************************************************************************/
static void procRxUART1(void)
{
  uint16 tail = uartRecord1.rx.bufferTail;

  while (UARTCharsAvail(HAL_UART1_PORT))
  {
    uartRecord1.rx.pBuffer[tail++] = UARTCharGetNonBlocking(HAL_UART1_PORT);

    if (tail >= uartRecord1.rx.maxBufSize)
    {
      tail = 0;
    }
  }

  if (uartRecord1.rx.bufferTail != tail)
  {
    uartRecord1.rx.bufferTail = tail;
    uartRecord1.rxChRvdTime = osal_GetSystemClock();
  }
}

/*************************************************************************************************
 * @fn      procTxUART0
 *
 * @brief   Process Tx bytes.
 *
 * @param   void
 *
 * @return  void
 *************************************************************************************************/
static void procTxUART0(void)
{
  uint16 head = uartRecord0.tx.bufferHead;
  uint16 tail = uartRecord0.tx.bufferTail;

  while ((head != tail) && (UARTCharPutNonBlocking(HAL_UART0_PORT, uartRecord0.tx.pBuffer[head])))
  {
    if (++head >= uartRecord0.tx.maxBufSize)
    {
      head = 0;
    }
  }

  uartRecord0.tx.bufferHead = head;
}

/*************************************************************************************************
 * @fn      procTxUART1
 *
 * @brief   Process Tx bytes.
 *
 * @param   void
 *
 * @return  void
 *************************************************************************************************/
static void procTxUART1(void)
{
  uint16 head = uartRecord1.tx.bufferHead;
  uint16 tail = uartRecord1.tx.bufferTail;

  while ((head != tail) && (UARTCharPutNonBlocking(HAL_UART1_PORT, uartRecord1.tx.pBuffer[head])))
  {
    if (++head >= uartRecord1.tx.maxBufSize)
    {
      head = 0;
    }
  }

  uartRecord1.tx.bufferHead = head;
}

/*************************************************************************************************
 * @fn      UART Rx/Tx ISR
 *
 * @brief   Called when a serial byte is ready to read and/or write.
 * NOTE:   Assumes that uartRecord0.configured is TRUE if this interrupt is enabled.
 *
 * @param   void
 *
 * @return  void
**************************************************************************************************/
void HalUart0ISR(void)
{
  UARTIntClear(HAL_UART0_PORT, (UART_INT_RX/* |  UART_INT_RT*/));
  procRxUART0();

  UARTIntClear(HAL_UART0_PORT, (UART_INT_TX/* | UART_INT_CTS*/));
  procTxUART0();
}

/*************************************************************************************************
 * @fn      UART Rx/Tx ISR
 *
 * @brief   Called when a serial byte is ready to read and/or write.
 * NOTE:   Assumes that uartRecord1.configured is TRUE if this interrupt is enabled.
 *
 * @param   void
 *
 * @return  void
**************************************************************************************************/
void HalUart1ISR(void)
{
  UARTIntClear(HAL_UART1_PORT, (UART_INT_RX |  UART_INT_RT));
  procRxUART1();

  UARTIntClear(HAL_UART1_PORT, (UART_INT_TX | UART_INT_CTS));
  procTxUART1();
}

/**************************************************************************************************
*/
  • 修改完以上两个文件以后,很多人认为就可以使用两路UART了,其实不行,由于TI默认使用的是UART1,只有UART1的中断处理函数加入到了中断向量表中,UART0是没有加进去的,很多人可能就卡在这里,上去直接读写UART0总是莫名其妙导致OSAL死掉。解决方法就是我们必须修改中断向量表,打开文件C:\Texas Instruments\Z-Stack 3.0.0\Components\hal\target\CC2538\startup_ewarm.c,定位到221行,我们发现UART0中断被默认丢给了IntDefaultHandler函数处理,我们改为interrupt_uart0函数,同时在前面声明一下函数extern void interrupt_uart0(void);
    interrupt_uart0,                        // 21 UART0 Rx and Tx
#ifdef HAL_UART_USB   
    IntDefaultHandler,                      // 22 UART1 Rx and Tx
#else
    interrupt_uart1,                        // 22 UART1 Rx and Tx
#endif
    IntDefaultHandler,                      // 23 SSI0 Rx and Tx
  • 最后重新编译整个工程,测试,两个UART同时完美工作!

你可能感兴趣的:(嵌入式软件,嵌入式硬件)