USART Asynchronous Driver

The universal synchronous and asynchronous receiver and transmitter (USART) is normally used to transfer data from one device to the other.

The USART driver uses a ring buffer to store received data. When the USART raise the data received interrupt, this data will be stored in the ring buffer at the next free location. When the ring buffer is full, the next reception will overwrite the oldest data stored in the ring buffer. There is one USART_BUFFER_SIZE macro per used hardware instance, e.g. for SERCOM0 the macro is called SERCOM0_USART_BUFFER_SIZE.

On the other hand, when sending data over USART, the data is not copied to an internal buffer, but the data buffer supplied by the user is used. The callback will only be generated at the end of the buffer and not for each byte.

The user can set an action for flow control pins by usart_async_set_flow_control function, if the flow control is enabled. All the available states are defined in usart_async_flow_control_status union.

Note that user can set state of flow control pins only if automatic support of the flow control is not supported by the hardware.

Summary of the API's Functional Features

The API provides functions to:
  • Initialize and deinitialize the driver and associated hardware

  • Register I/O descriptor

  • Enable or disable USART

  • Hookup callback handlers on transfer complete, or error events

  • Data transfer: transmission and reception

Summary of Configuration Options

Below is a list of the main USART parameters that can be configured in START. Many of these are used by the usart_async_init function when initializing the driver and underlying hardware. Most of the initial values can be overridden and changed runtime by calling the appropriate API functions.
  • Set USART baudrate

  • Select UART or USART communication mode

  • Select character size

  • Set Data order

  • Flow control

  • Which clock source is used

Driver Implementation Description

After USART hardware initialization, the usart_async_get_io_descriptor function is needed to register an I/O descriptor. Then use usart_async_register_callback to register the callback function for transfer, and enable the USART hardware. After that, start the read/write operation.

Concurrency

  • The write buffer should not be changed while data is being sent

Limitations

  • The driver does not support 9-bit character size

  • The "USART with ISO7816" mode can be used only in ISO7816 capable devices, and the SCK pin can't be set directly. The application can use a GCLK output pin to generate SCK. For example, to communicate with a SMARTCARD with ISO7816 (F = 372; D = 1), and baudrate=9600, the SCK pin output frequency should be configured as 372*9600=3571200Hz. For more information, refer to the ISO7816 Specification.

Example of Usage

The following shows a simple example of using the USART. The USART master must have been initialized by usart_async_init. This initialization will configure the operation of the USART.

The example registers an I/O descriptor and enables the hardware. Then it registers a callback, and finally starts a writing operation.

          /**
           * Example of using USART_0 to write "Hello World" using the I/O abstraction.
            
           * Since the driver is asynchronous we need to use statically allocated memory for string
           * because driver initiates transfer and then returns before the transmission is completed.
            
           * Once transfer has been completed the tx_cb function will be called.
           */
          static uint8_t example_USART_0[12] = "Hello World!";
          static void tx_cb_USART_0(const struct usart_async_descriptor *const io_descr)
          {
              /* Transfer completed */
          }
          void USART_0_example(void)
          {
              struct io_descriptor *io;
              usart_async_register_callback(&USART_0, USART_ASYNC_TXC_CB, tx_cb_USART_0);
              /*usart_async_register_callback(&USART_0, USART_ASYNC_RXC_CB, rx_cb);
              usart_async_register_callback(&USART_0, USART_ASYNC_ERROR_CB, err_cb);*/
              usart_async_get_io_descriptor(&USART_0, &io);
              usart_async_enable(&USART_0);
              io_write(io, example_USART_0, 12);
          }
        

Dependencies

  • The USART peripheral and its related I/O lines and clocks

  • The NVIC must be configured so that USART interrupt requests are periodically serviced