Jump to main content

##

# 2.131 Universal Synchronous Asynchronous Receiver Transceiver (USART)

The USART peripheral library (PLIB) can be configured either in blocking (interrupt disabled), non-blocking (interrupt enabled) or ring buffer mode. It can also be configured to work as SPI in either blocking (interrupt disabled) or non-blocking (interrupt enabled) mode.

USART Mode

Blocking mode

In blocking mode, the USART peripheral interrupts are disabled and the transfer APIs block until the requested data is transferred.

Non-blocking mode

In non-blocking mode the peripheral interrupt is enabled. The transfer API initiates the transfer and returns immediately. The transfer is then completed from the peripheral interrupt. Application can either use a callback to get notified when the transfer is complete or can use the IsBusy API to check the completion status.

Ring buffer mode

In ring buffer mode, the receiver is always enabled, and the received data is saved in the internal receive ring buffer, size of which can be configured using MCC. The application can use the API calls to read the data out from the ring buffer. APIs are provided to query the number of (unread) bytes available in the receive buffer, free space in the receive buffer and size of the receive buffer. Similarly, during transmission, the application data is deep copied into the internal transmit ring buffer, size of which can be configured using MCC. This allows the use of local buffers for data transmission. APIs are provided to query the free space in the transmit buffer, number of bytes pending transmission and the size of the transmit buffer. Additionally, application can enable notifications to get notified when n bytes are available in the receive buffer or when n bytes of free space is available in the transmit buffer. The APIs allow application to set the threshold levels for notification in both receive and transmit buffers. Further, application can also choose to enable persistent notifications, whereby the application is notified until the threshold condition is met.

In all the modes, library provides API to change the baud, parity, data width and the number of stop bits at run time.

## Using The Library

Blocking Mode

    #define RX_BUFFER_SIZE 10
    char message[] = "USART Example in blocking mode";
    char receiveBuffer[RX_BUFFER_SIZE] = {0};
    USART_ERROR errorStatus;
    char rxData = 0;

    int main ( void )
    {
        /* Initialize all modules */
        SYS_Initialize ( NULL );

        /* Transmit buffer*/
        USART1_Write(message, sizeof(message));

    	/* Wait for a character to be received */
    	while(USART1_ReceiverIsReady() == false);

    	if(USART1_ErrorGet() == USART_ERROR_NONE)
    	{
    		/* Read a byte */
    		rxData = USART1_ReadByte();
    	}

    	/* Receive buffer */
        if (USART1_Read(receiveBuffer, RX_BUFFER_SIZE)) == false)
    	{
    		/* Read failed, get the error */
    		errorStatus USART1_ErrorGet();

    		/* Handle the error */
    	}
        else
    	{
    		/* Transmit the received buffer*/
    		USART1_Write(receiveBuffer, RX_BUFFER_SIZE);
    	}

    	...

        /* Execution should not come here during normal operation */

        return ( EXIT_FAILURE );
    }

Non-blocking Mode

    #define RX_BUFFER_SIZE 10

    char message[] = "**** Non-blocking Transfer with the interrupt  ****\r\n\
    **** Type 10 characters. The received characters are echoed back ****\r\n";

    char messageError[] = "**** USART error occurred ****\r\n";

    char receiveBuffer[RX_BUFFER_SIZE] = {0};
    char echoBuffer[RX_BUFFER_SIZE+4] = {0};

    bool errorStatus = false;
    bool writeStatus = false;
    bool readStatus = false;

    void APP_WriteCallback(uintptr_t context)
    {
        writeStatus = true;
    }

    void APP_ReadCallback(uintptr_t context)
    {
        if(USART1_ErrorGet() != USART_ERROR_NONE)
        {
            /* ErrorGet clears errors, set error flag to notify console */
            errorStatus = true;
        }
        else
        {
            readStatus = true;
        }
    }

    int main ( void )
    {
        /* Initialize all modules */
        SYS_Initialize ( NULL );

        /* Register callback functions and send start message */
        USART1_WriteCallbackRegister(APP_WriteCallback, 0);
        USART1_ReadCallbackRegister(APP_ReadCallback, 0);
        USART1_Write(&message[0], sizeof(message));

        while ( true )
        {
            if(errorStatus == true)
            {
                /* Send error message to console */
                errorStatus = false;
                USART1_Write(&messageError[0], sizeof(messageError));
            }
            else if(readStatus == true)
            {
                /* Echo back received buffer and Toggle LED */
                readStatus = false;

                echoBuffer[0] = '\n';
                echoBuffer[1] = '\r';
                memcpy(&echoBuffer[2], receiveBuffer,sizeof(receiveBuffer));
                echoBuffer[RX_BUFFER_SIZE+2] = '\n';
                echoBuffer[RX_BUFFER_SIZE+3] = '\r';

                USART1_Write(&echoBuffer[0], sizeof(echoBuffer));
            }
            else if(writeStatus == true)
            {
                /* Submit buffer to read user data */
                writeStatus = false;
                USART1_Read(&receiveBuffer[0], sizeof(receiveBuffer));
            }
            else
            {
                /* Repeat the loop */
                ;
            }
        }

        /* Execution should not come here during normal operation */

        return ( EXIT_FAILURE );
    }

Ring buffer Mode

    uint8_t txBuffer[50];
    uint8_t rxBuffer[10];
    volatile uint32_t nBytesRead = 0;
    volatile bool txThresholdEventReceived = false;
    volatile bool rxThresholdEventReceived = false;

    void USARTReadEventHandler(USART_EVENT event, uintptr_t context )
    {
        uint32_t nBytesAvailable = 0;

        if (event == USART_EVENT_READ_THRESHOLD_REACHED)
        {
            /* Receiver should atleast have the thershold number of bytes in the ring buffer */
            nBytesAvailable = USART1_ReadCountGet();

            nBytesRead += USART1_Read((uint8_t*)&rxBuffer[nBytesRead], nBytesAvailable);
        }
    }

    void USARTWriteEventHandler(USART_EVENT event, uintptr_t context )
    {
        txThresholdEventReceived = true;
    }

    int main ( void )
    {
        uint32_t nBytes = 0;

        /* Initialize all modules */
        SYS_Initialize ( NULL );

        /* Register a callback for write events */
        USART1_WriteCallbackRegister(USARTWriteEventHandler, (uintptr_t) NULL);

        /* Register a callback for read events */
        USART1_ReadCallbackRegister(USARTReadEventHandler, (uintptr_t) NULL);

        /* Print the size of the read buffer on the terminal */
        nBytes = sprintf((char*)txBuffer, "RX Buffer Size = %d\r\n", (int)USART1_ReadBufferSizeGet());

        USART1_Write((uint8_t*)txBuffer, nBytes);

        /* Print the size of the write buffer on the terminal */
        nBytes = sprintf((char*)txBuffer, "TX Buffer Size = %d\r\n", (int)USART1_WriteBufferSizeGet());

        USART1_Write((uint8_t*)txBuffer, nBytes);

        USART1_Write((uint8_t*)"Adding 10 characters to the TX buffer - ", sizeof("Adding 10 characters to the TX buffer - "));

        /* Wait for all bytes to be transmitted out */
        while (USART1_WriteCountGet() != 0);

        USART1_Write((uint8_t*)"0123456789", 10);

        /* Print the amount of free space available in the TX buffer. This should be 10 bytes less than the configured write buffer size. */
        nBytes = sprintf((char*)txBuffer, "\r\nFree Space in Transmit Buffer = %d\r\n", (int)USART1_WriteFreeBufferCountGet());

        USART1_Write((uint8_t*)txBuffer, nBytes);

        /* Let's enable notifications to get notified when the TX buffer is empty */
        USART1_WriteThresholdSet(USART1_WriteBufferSizeGet());

        /* Enable notifications */
        USART1_WriteNotificationEnable(true, false);

        /* Wait for the TX buffer to become empty. Flag "txThresholdEventReceived" is set in the callback. */
        while (txThresholdEventReceived == false);

        txThresholdEventReceived = false;

        /* Disable TX notifications */
        USART1_WriteNotificationEnable(false, false);

        USART1_Write((uint8_t*)"Enter 10 characters. The received characters are echoed back. \r\n>", sizeof("Enter 10 characters. The received characters are echoed back. \r\n>"));

        /* Wait till 10 (or more) characters are received */
        while (USART1_ReadCountGet() < 10);

        /* At-least 10 characters are available in the RX buffer. Read out into the application buffer */
        USART1_Read((uint8_t*)rxBuffer, 10);

        /* Echo the received data */
        USART1_Write((uint8_t*)rxBuffer, 10);

        /* Now demonstrating receiver notifications */
        USART1_Write((uint8_t*)"\r\n Now turning on RX notifications \r\n>", sizeof("\r\n Now turning on RX notifications \r\n>"));

        /* For demonstration purpose, set a threshold value to receive a callback after every 5 characters are received */
        USART1_ReadThresholdSet(5);

        /* Enable RX event notifications */
        USART1_ReadNotificationEnable(true, false);

        while(1)
        {
            /* Wait until at-least 10 characters are entered by the user */
            while (nBytesRead < 10);

            /* Echo the received data */
            USART1_Write((uint8_t*)rxBuffer, nBytesRead);

            USART1_Write((uint8_t*)"\r\n>", 3);

            nBytesRead = 0;
        }

        /* Execution should not come here during normal operation */

        return ( EXIT_FAILURE );
    }

SPI Mode

The SPI PLIB supports master mode

SPI master mode

In SPI master mode, the PLIB can be configured to run in blocking mode or non-blocking mode. In blocking mode the peripheral interrupt is disabled and the transfer API blocks until the transfer is complete. In non-blocking mode, the peripheral interrupt is enabled. The transfer API initiates the transfer and returns immediately. The transfer is completed from the peripheral interrupt. Application can either use a callback to get notified when the transfer is complete or can use the IsBusy API to check the completion status.

SPI Master in blocking (peripheral interrupt disabled) mode

    // Following code demonstrates SPI self loopback with the PLIB configured in blocking mode
    uint8_t txData[]  = "SELF LOOPBACK FOR SPI!";
    uint8_t rxData[sizeof(txData)];

    int main ( void )
    {
        /* Initialize all modules */
        SYS_Initialize ( NULL );

        /* SPI Write Read */
        USART1_SPI_WriteRead(&txData[0], sizeof(txData), &rxData[0], sizeof(rxData));

        /* Compare received data with the transmitted data */
        if ((memcmp(txData, rxData, sizeof(txData)) == 0))
        {
            /* Pass: Received data is same as transmitted data */
        }
        else
        {
            /* Fail: Received data is not same as transmitted data */
        }

        while ( true )
        {
        }

        /* Execution should not come here during normal operation */

        return ( EXIT_FAILURE );
    }

SPI Master in non-blocking (peripheral interrupt enabled) mode

    // Following code demonstrates SPI self loopback with the PLIB configured in non-blocking mode

    uint8_t txData[]  = "SELF LOOPBACK FOR SPI!";
    uint8_t rxData[sizeof(txData)];
    volatile bool transferStatus = false;

    /* This function will be called by SPI PLIB when transfer is completed */
    void APP_SPI_Callback(uintptr_t context )
    {
        transferStatus = true;
    }

    int main ( void )
    {
        /* Initialize all modules */
        SYS_Initialize ( NULL );

        /* Register callback function   */
        USART1_SPI_CallbackRegister(APP_SPI_Callback, 0);

        /* SPI Write Read */
        USART1_SPI_WriteRead(&txData[0], sizeof(txData), &rxData[0], sizeof(rxData));

    	while (1)
    	{
    		/* Perform other tasks here ...*/

    		/* Check if transfer has completed */
    		if(transferStatus == true)
    		{
    			/* Compare received data with the transmitted data */
    			if(memcmp(txData, rxData, sizeof(txData)) == 0)
    			{
    				/* Pass: Received data is same as transmitted data */
    			}
    			else
    			{
    				/* Fail: Received data is not same as transmitted data */
    			}
    		}
    	}

    }

## Library Interface

USART peripheral library provides the following interfaces:

USART Mode

Functions

Name | Description | Blocking mode | Non-blocking mode | Ring buffer mode
--- | --- | --- | --- | ---
USARTx_Initialize | Initializes given instance of the USART peripheral | Yes | Yes | Yes
USARTx_SerialSetup | Sets up serial configurations for USART peripheral | Yes | Yes | Yes
USARTx_Write | Writes data to the given USART peripheral instance | Yes | Yes | Yes
USARTx_Read | Reads data from the given USART peripheral instance | Yes | Yes | Yes
USARTx_WriteIsBusy | Returns the write request status associated with the given USART peripheral instance | No | Yes | No
USARTx_ReadIsBusy | Returns the read request status associated with the given USART peripheral instance | No | Yes | No
USARTx_WriteCountGet | Gets the byte count of processed bytes for a given USART read operation in non-blocking mode. Returns the number of bytes pending to be transmitted out in the transmit buffer in ring buffer mode. | No | Yes | Yes
USARTx_ReadCountGet | Gets the byte count of processed bytes for a given USART read operation in non-blocking mode. Returns the number of bytes available in the internal receive buffer of the PLIB in ring buffer mode. | No | Yes | Yes
USARTx_TransmitterIsReady | Returns the hardware status of the USART Transmitter | Yes | No | No
USARTx_ReceiverIsReady | Returns the hardware status of the USART Receiver | Yes | No | No
USARTx_ErrorGet | Gets the error of the given USART peripheral instance | Yes | Yes | Yes
USARTx_WriteCallbackRegister | Sets the pointer to the function (and it's context) to be called when the given USART's write events occur | No | Yes | Yes
USARTx_ReadCallbackRegister | Sets the pointer to the function (and it's context) to be called when the given USART's read events occur | No | Yes | Yes
USARTx_ReadByte | Submits request to read a byte of data to the given USART peripheral | Yes | No | No
USARTx_WriteByte | Submits a byte of data to the given USART peripheral to transfer | Yes | No | No
USARTx_ReadAbort | Aborts the ongoing read request | No | Yes | No
USARTx_WriteFreeBufferCountGet | Returns the number of bytes of free space available in the internal transmit buffer | No | No | Yes
USARTx_WriteBufferSizeGet | Returns the size of the internal transmit ring buffer | No | No | Yes
USARTx_WriteNotificationEnable | This API lets the application turn the transmit notifications on/off | No | No | Yes
USARTx_WriteThresholdSet | This API allows the application to set a threshold level on the number of free space available in the transmit buffer | No | No | Yes
USARTx_ReadFreeBufferCountGet | Returns the number of bytes of free space available in the internal receive buffer | No | No | Yes
USARTx_ReadBufferSizeGet | Returns the size of the receive ring buffer | No | No | Yes
USARTx_ReadNotificationEnable | This API lets the application turn the receive notifications on/off | No | No | Yes
USARTx_ReadThresholdSet | This API allows the application to set a threshold level on the number of bytes of data available in the receive buffer | No | No | Yes

Data types and constants

Name | Type | Description | Blocking mode | Non-blocking mode | Ring buffer mode
--- | --- | --- | --- | --- | ---
USART_ERROR | Macros and Typedef | Defines the macros and typedefs associated with the USART peripheral errors | Yes | Yes | Yes
USART_DATA | Enum | Defines the data width types for the USART peripheral | Yes | Yes | Yes
USART_PARITY | Enum | Defines the parity types for the USART peripheral | Yes | Yes | Yes
USART_STOP | Enum | Defines the data type for the USART peripheral stop bits | Yes | Yes | Yes
USART_SERIAL_SETUP | Struct | Defines the data structure which is used to configure USART serial parameters at run time | Yes | Yes | Yes
USART_CALLBACK | Typedef | Defines the data type and function signature of the USART peripheral library callback function | Yes | Yes | No
USART_EVENT | Enum | Defines the enums associated with the USART events in the ring buffer mode | Yes | Yes | Yes
USART_RING_BUFFER_CALLBACK | Typedef | Defines the data type and function signature for the USART peripheral callback function in the ring buffer mode | No | No | Yes

SPI Mode

Functions

Name | Description | Master (blocking/interrupt disabled) mode | Master (non-blocking/interrupt enabled) mode
--- | --- | --- | ---
USARTx_SPI_Initialize | Initializes USART peripheral in SPI mode | Yes | Yes
USARTx_SPI_TransferSetup | Configure SPI operational parameters at run time | Yes | Yes
USARTx_SPI_WriteRead | Write and Read data on SPI peripheral | Yes | Yes
USARTx_SPI_Write | Writes data to SPI peripheral | Yes | Yes
USARTx_SPI_Read | Reads data on the SPI peripheral | Yes | Yes
USARTx_SPI_CallbackRegister | Allows application to register a callback with the PLIB | No | Yes
USARTx_SPI_IsBusy | Returns transfer status of SPI | No | Yes

Data types and constants

Name | Description | Master (blocking/interrupt disabled) mode | Master (non-blocking/interrupt enabled) mode
--- | --- | --- | ---
USART_SPI_CLOCK_PHASE | Enum | Identifies SPI Clock Phase Options | Yes
USART_SPI_CLOCK_POLARITY | Enum | Identifies SPI Clock Polarity Options | Yes
USART_SPI_DATA_BITS | Enum | Identifies SPI bits per transfer | Yes
USART_SPI_TRANSFER_SETUP | Struct | Data structure containing the SPI parameters which can be changed at run time | Yes
USART_SPI_CALLBACK | Typedef | Defines the data type and function signature for the USART SPI peripheral callback function | No

LIN Mode

Functions

Name | Description | Host (blocking/interrupt disabled) mode | Host (non-blocking/interrupt enabled) mode | Client (blocking/interrupt disabled) mode | Client (non-blocking/interrupt enabled) mode
--- | --- | --- | --- | --- | ---
USARTx_LIN_ChecksumEnable Function | Enables hardware checksum for data transfer | Yes | Yes | Yes | Yes
USARTx_LIN_ChecksumTypeSet Function | Set the type of checksum to be used during data transfer. | Yes | Yes | Yes | Yes
USARTx_LIN_DataLenModeSet Function | Set Data Length Mode | Yes | Yes | Yes | Yes |  |
USARTx_LIN_FrameSlotEnable Function | Enable/Disable Frame Slot Mode | Yes | Yes | No | No |
USARTx_LIN_IdentifierRead Function | Helps the application to read LIN ID to corresponding hardware register | Yes | Yes | Yes | Yes
USARTx_LIN_IdentifierWrite Function | Helps the application to write LIN ID to corresponding hardware register | Yes | Yes | Yes | Yes
USARTx_LIN_NodeActionSet Function | Allows to set the Action to be performed by LIN Node (PUBLISH, SUBSCRIBE or IGNORE) | Yes | Yes | Yes | Yes
USARTx_LIN_ParityEnable Function | Allows to Enable/Disable LIN Identifier parity mode | Yes | Yes | Yes | Yes
USARTx_LIN_ResponseDataLenSet Function | Allowas to set the data length to be transferred | Yes | Yes | Yes | Yes |
USARTx_LIN_TransferComplete Function | Allows to check if the requested data transfer is completed or not | Yes | Yes | Yes | Yes
USARTx_LINBreakCallbackRegister Function | Allows to register a callback function for the PLIB to call back when the Break Field of the requested LIN header transfer operation has completed. | No | Yes | No | Yes
USARTx_LINIdCallbackRegister Function | Allows to register a callback function for the PLIB to call back when the requested LIN ID transfer operation has completed. | No | Yes | No | Yes
USARTx_LINTcCallbackRegister Function | Allows to register a callback function for the PLIB to call back when the requested LIN data transfer operation has completed | No | Yes | No | Yes |

Data types and constants

Name | Description | Master (blocking/interrupt disabled) mode | Master (non-blocking/interrupt enabled) mode | Client (blocking/interrupt disabled) mode | Client (non-blocking/interrupt enabled) mode
--- | --- | --- | --- | --- | ---
USART_LIN_CALLBACK Typedef | Defines the data type and function signature for the USART LIN peripheral callback function. | No | Yes | No | Yes
USART_LIN_CHECKSUM_TYPE Enum | Defines the data type for the USART LIN checksum type bits | Yes | Yes | Yes | Yes
USART_LIN_DATA_LEN Enum | Defines the data type for the USART LIN Data Length Mode bits | Yes | Yes | Yes | Yes
USART_LIN_NACT Enum | Defines the data type for the USART LIN node action bits | Yes | Yes | Yes | Yes

Note: Not all APIs maybe implemented. See the specific device family section for available APIs.