6.5.9. UART

UART is used by the gateway to translate packets between PAN and LAN. Hence, the interface is not applicable for non-gateways. The interface has to be enabled using the compile-time flags PLTFRM_UART_ENA and PAN_COORD.

6.5.9.1. Functions

void UART_init(void)

Initializes the UART interface including baud rate configuration. Baud rate is set based on compile-time flags that must be one of UART_BAUD_RATE_9600, UART_BAUD_RATE_56000 or UART_BAUD_RATE_115200. Global variable UART_cntxt is also cleared in this function. This function is typically called during platform initialization.

void UART_start(void)

This is usually called when the system boots up. It starts the UART interface by enabling interrupts. The use of interrupts on the transmit path is optional and can be enabled by defining compile-time flag UART_TX_INT_ENA. On the receive path, UART_usci0RxISR() is the function that services the interrupts. Similar function on the transmit path is named UART_usci0TxISR().

Use of interrupt on the transmit path is not preferred since it is known to interfere with SPI communication between MSP430 and CC2520.

void UART_checkRcvdFramePyld(void)

The receive ISR UART_usci0RxISR() collects payload bytes in the global variable UART_cntxt. When the entire payload as noted in the header is received, the ISR sets the flag SYS_GLOBAL_EVT_UART_FRAME_PYLD_RCVD in SYS_globalEvtMsk1. This triggers the main system loop to call this function to process the payload.

This function calls the gateway interface to process the received header. Where relevant, the gateway will form the response and add this to the UART transmit queue.

The ISR disables the receive interrupt. This function enables the interrupt before returning.

void UART_checkRcvdFrameHdr(void)

A UART frame consists of UART_FRAME_HDR_LEN bytes. When each byte is received on UART, the receive ISR UART_usci0RxISR() collects header bytes in the global variable UART_cntxt. When UART_FRAME_HDR_LEN bytes have been received, SYS_GLOBAL_EVT_UART_FRAME_HDR_RCVD flag is set in SYS_globalEvtMsk1. This triggers the main system loop to call this function to process the header.

For messages that don’t have a payload, this function calls the gateway interface to process the received header. Where relevant, the gateway will form the response and add this to the UART transmit queue. For messages that have a payload, this function will allocate memory to receive the payload. An acknowledgement will be sent over UART. Note that on the UART receive path, only after the header is acknowledged, the sender will send the payload.

The ISR disables the receive interrupt. This function enables the interrupt before returning.

void UART_checkRcvrState(void)

This function is primarily for error recovery. Sometimes it’s possible that some bytes have been received on UART and the rest are lost. This function detects this scenario and sets the flag SYS_GLOBAL_EVT_UART_FRAME_HDR_RCVD in SYS_globalEvtMsk1. As a result, the main system loop will call UART_checkRcvdFrameHdr(), which will clear the buffers and send a NACK to the sender.

void UART_buildMsgHdr(UINT16_t msgType, UINT8_t *buff_p, UINT16_t pyldLen)

This is typically called by gateway code to build a UART message header. The header is returned in network byte order. Checksum is calculated and included in the header.

Parameters:
  • msgType – Message type.
  • buff_p – Pre-allocated buffer where the header must be stored. This buffer must be at least UART_FRAME_HDR_LEN bytes.
  • pyldLen – Length of the payload. This is one of the required fields in the header.
void UART_addToTxPendQ(UINT8_t bdHndl)

When a message is ready to be transmitted on UART, this function can be called to add the message to the transmit queue. If the queue is empty, the message is immediately transmitted by calling UART_wrBlock(), which transmits only the first byte of data.

Parameters:
  • bdHndl – Handle to where the message is stored.
UINT8_t UART_wrBlock(UINT8_t *buff_p, UINT16_t buffLen)

Function triggers transmission of data on UART. Only the first byte of data is transmitted.

Parameters:
  • buff_p – Points to memory where data to be transmitted is stored.
  • buffLen – Number of bytes of data to be written.
Returns:

If write is okay, returns UART_STS_TX_IN_PROGRESS. If input parameters are wrong, it returns UART_STS_INV_PARAMS.

void UART_pollTx(void)

When transmit interrupt for UART communication is not used, polling is the method. This function is usually called via the macro UART_POLL_TX(). It picks up the next byte pending transmission from global variable UART_cntxt. It calls UART_wrBlock() to transmit the byte.

void UART_blockTxDoneEvtHndlr(void)

This function is called once a message has been completely transmitted on the UART. The function frees the memory. If there is another message pending transmission, it initiates the transmission.

If transmit interrupt is enabled, this function is called from the main system loop based on the setting of event flag SYS_GLOBAL_EVT_UART_BLOCK_TX_DONE in SYS_globalEvtMsk1. The flag is set from the transmit ISR, UART_usci0TxISR(). If transmit interrupt is not enabled, it is called from UART_pollTx().

void UART_log(char *fmt_p, ...)

To use this function, compile-time flag PLTFRM_LOG_ENA has to be defined.

Parameters:
  • fmt_p – Function takes in a variable number of argument just like the standard printf() function. This pointer gives the formatting of the message to be logged.

6.5.9.2. Globals

UART_cntxt_s UART_cntxt

Stores the UART context.

SINT8_t[UART_LOG_BUFF_LEN] UART_logBuff

UART log is stored in this buffer. It is accessed via UART_log() function. Logging has to be enabled by the compile-time flag PLTFRM_LOG_ENA.

6.5.9.3. Macros

#define UART_LOG_BUFF_LEN   256

#define UART_STS_SUCCESS         0x0
#define UART_STS_DEV_BUSY        0x1
#define UART_STS_HW_TX_ERR       0x2
#define UART_STS_INV_PARAMS      0x3
#define UART_STS_TX_IN_PROGRESS  0x4
#define UART_STS_IDLE            0x5

#define UART_STATS_EN

#define UART_MSG_TYPE_ACK   0x0


// Bit definitions of the flags field in the message header
#define UART_HDR_ACK_BM  (1 << 7)
#define UART_PYLD_ACK_BM  (~(1 << 7))

#define UART_ACK_STS_OK_BM               (1 << 0)
#define UART_ACK_STS_OOM_BM              (1 << 1)
#define UART_ACK_STS_FRAME_TOO_LONG_BM   (1 << 2)
#define UART_ACK_STS_INV_CRC             (1 << 3)
#define UART_ACK_STS_RELAY_IN_PROGRESS   (1 << 4)
#define UART_ACK_STS_HDR_BYTES_MISSING   (1 << 5)
#define UART_ACK_STS_PYLD_BYTES_MISSING  (1 << 6)

#define UART_FRAME_HDR_MSG_TYPE_FIELD_LEN   2
#define UART_FRAME_HDR_FLAGS_FIELD_LEN      1
#define UART_FRAME_HDR_SEQ_NR_FIELD_LEN     1
#define UART_FRAME_HDR_PYLD_LEN_FIELD_LEN   2
#define UART_FRAME_HDR_CRC_FIELD_LEN        2

#define UART_FRAME_HDR_HDR_CRC_FIELD_LEN   UART_FRAME_HDR_CRC_FIELD_LEN
#define UART_FRAME_HDR_PYLD_CRC_FIELD_LEN  UART_FRAME_HDR_CRC_FIELD_LEN

#define UART_FRAME_HDR_MSG_TYPE_FIELD_OFF   0

#define UART_FRAME_HDR_FLAGS_FIELD_OFF \
        UART_FRAME_HDR_MSG_TYPE_FIELD_LEN

#define UART_FRAME_HDR_SEQ_NR_FIELD_OFF \
        (UART_FRAME_HDR_FLAGS_FIELD_OFF + UART_FRAME_HDR_FLAGS_FIELD_LEN)

#define UART_FRAME_HDR_PYLD_LEN_FIELD_OFF \
        (UART_FRAME_HDR_SEQ_NR_FIELD_OFF + UART_FRAME_HDR_SEQ_NR_FIELD_LEN)

#define UART_FRAME_HDR_HDR_CRC_FIELD_OFF  \
        (UART_FRAME_HDR_PYLD_LEN_FIELD_OFF + UART_FRAME_HDR_PYLD_LEN_FIELD_LEN)

#define UART_FRAME_HDR_PYLD_CRC_FIELD_OFF \
        (UART_FRAME_HDR_HDR_CRC_FIELD_OFF + UART_FRAME_HDR_HDR_CRC_FIELD_LEN)

#define UART_FRAME_MAX_PYLD_LEN  128

#define UART_FRAME_HDR_LEN  (UART_FRAME_HDR_MSG_TYPE_FIELD_LEN \
                             + UART_FRAME_HDR_FLAGS_FIELD_LEN \
                             + UART_FRAME_HDR_SEQ_NR_FIELD_LEN \
                             + UART_FRAME_HDR_PYLD_LEN_FIELD_LEN \
                             + UART_FRAME_HDR_HDR_CRC_FIELD_LEN \
                             + UART_FRAME_HDR_PYLD_CRC_FIELD_LEN)

#ifndef UART_TX_INT_ENA
#define UART_POLL_TX( )  \
do { \
  if (UART_cntxt.txBuffLen > 0) \
      UART_pollTx(); \
} while (0)
#endif

6.5.9.4. Type Definitions

typedef void (*UART_txDoneCbFunc_t)(UINT8_t sts);

typedef struct
{
  UINT8_t rxFrameBdHndl;
  UINT8_t txSeqNr;
  UINT8_t rcvrStuckFlag;
  UINT8_t *txBuff_p;
  UINT16_t txBuffLen;
  UINT16_t txBuffOff;
  UINT16_t currRcvdFrameSeqNr;
  UINT16_t lastCheckedRcvdFrameSeqNr;
  UINT8_t stsTxPending;
  UINT8_t rxFramePyldLen;
  UINT8_t rxFrameOff;
  UINT8_t *rxFrameBuff_p;
  UINT8_t rxHdrBuff[UART_FRAME_HDR_LEN];
  SYS_trscnQ_s pendTxtrscnQ;
#ifdef UART_STATS_EN
  UINT16_t UART_txIntCnt;
  UINT16_t UART_rxIntCnt;
  UINT16_t UART_ucb0RxIntCnt;
  UINT16_t byteTxCnt;
  UINT16_t spuriousTxIntCnt;
  UINT8_t pyldCrcBadCnt;
  UINT8_t pyldCrcOkCnt;
  UINT8_t hdrRcvdCnt;
  UINT8_t hdrCrcOkCnt;
  UINT8_t hdrCrcBadCnt;
  UINT8_t frameTxStartCnt;
  UINT8_t frameTxDoneCnt;
  UINT8_t ackMemAllocOk;
  UINT8_t ackMemAllocFlr;

#endif
} UART_cntxt_s;