USART Basic

Driver for basic USART functionality.

Revision History

  • v0.0.0.1 Initial Commit

The USART Basic driver provides basic USART functionality, that is:
  • Transmission of a character

  • Reception of a character

  • Optional support for redirecting printf() output to USART

The USART Basic driver has four modes of operation:
  • Asynchronous polled mode

  • Synchronous polled mode

  • Asynchronous interrupt-driven mode

  • Synchronous interrupt-driven mode

Driver Configuration

The USART Basic driver is configured using START. The user can choose from the four modes of operation (sync/async, polled/IRQ). START also allows the user to select desired baud rate, character size, number of stop bits, parity etc.

START allows the user to select whether or not to include support for redirecting printf() output to the USART. Enabling this feature adds appropriate API functionality so that printf() in the user code redirects to the USART TXD I/O pin.

START allows the user to select size of buffers used in IRQ driven mode, see IRQ mode(group__doc__driver__usart__basic_1doc_driver_usart_basic_irq) for details.

If several USART hardware instances are available on the device, the user can select which USART instance the driver shall use.

Functional Description

Async mode

When in asynchronous mode, the USART uses only the TXD and RXD I/O pins. The XCK I/O pin is not used. The receiver must be set up with the same baud rate as the transmitter in order to be able to receive data correctly.

Sync mode

When in synchronous mode, the USART uses the TXD, RXD and XCK I/O pins. The receiver uses the signal received on the XCK pin as a clock to sample data received on the RXD pin, and to clock data on the TXD pin. When synchronous mode is used, the XCK pin controls whether the transmission clock is input (slave mode) or output (master mode). The corresponding port pin must be set to output for master mode or to input for slave mode.

Polled mode

The polled mode version of the driver provides functions for transmitting and receiving one character of data. The read and write-functions are blocking: If the USART is not able to execute the desired operation immediately, the driver blocks until the operation has been performed.

Functions are provided to check if:
  • a character has been received

  • the USART can accept a new character for transmission

  • the previous character has been completely transmitted out of the USART shift register

These functions can be used to check if the USART is ready to process a <component_name>_read() or <component_name>_write() immediately. In applications where blocking must be avoided, the user must check the status of the USART hardware and call the <component_name>_read() or <component_name>_write() only if they will not block.

IRQ mode

The IRQ modes of the basic driver has the same API as the polled modes. The difference is that the <component_name>_read() and <component_name>_write() functions access ringbuffers instead of the USART data registers directly. The Interrupt Service Routines provided by the driver transfers data between the ringbuffers and the USART hardware whenever the hardware is ready to accept it. The size of the RX and TX ringbuffers can be configured in START. The optimal setting of the buffer size is dependent on the desired baud rate.

The <component_name>_read() function will block if there is no data to be read in the RX ringbuffer. The <component_name>_write()-function will block there is no room for more data in the TX ringbuffer.

Functions are provided to check if:
  • the RX ringbuffer contains received characters

  • the TX ringbuffer has room for a new character

  • the previous character has been completely transmitted out of the USART shift register

These functions can be used to check if the ringbuffers are ready to process a <component_name>_read() or <component_name>_write() immediately. In applications where blocking must be avoided, the user must check the status of the ringbuffers and call the <component_name>_read() or <component_name>_write() only if they will not block.

Hardware Dependencies

The USART Basic driver usually uses some sort of hardware that implements USART functionality, even though it is possible to impement a software USART implemented by bit-banging I/O pins.

Different MCUs have USART hardware with different names and functionalities, such as UART, USART, USI etc. In START, the user selects a device and adds the USART Basic driver. A device may have several possible hardware resources available for the driver, such as USART0, USART1 etc. In this case the user must select which one to use.

The configuration options in START displays options that are dependent on the hardware used to implement the USART driver. For example, an option may allow changing the baud rate used to drive the underlying USART hardware.

Software Dependencies

The interrupt-driven configurations use the interrupt functionality of the underlying USART hardware. Make sure that global interrupts are enabled (using sei()) and that the Interrupt Controller, if present, is configured so that any interrupts are serviced correctly.

Code example

          #include <stdio.h>
          #include <string.h>
          #include <atmel_start.h>
          uint8_t tx[16] = "data"; 
          uint8_t rx[16];
          void fail(void);
          void fail(){
              while(1);
          }
          int main(void)
          {
              uint8_t i;
              
              /* Initializes MCU, drivers and middleware */
              atmel_start_init();
              // If USART Basic driver is in IRQ-mode, enable global interrupts.
              sei();
              // Test driver functions, assumes that the USART RX and 
              // TX pins have been loopbacked, or that USART hardware 
              // is configured in loopback mode
              // Test printf() support
              printf("hello");
              // Check that "hello" was received on loopback RX.
              // Initialize rx buffer so strncmp() check will work
              memset(rx, 0, sizeof(rx));
              for (i=0;i<strlen("hello");i++)
                  rx[i]=USART_0_read(); // Blocks until character is available
              // Compare received and expected data
              if (strncmp("hello", (char*)rx, strlen("hello")) != 0)
                  fail();
              // If we get here, everything was OK
              printf("ok");
              /* Replace with your application code */
              while (1) {
              }
          }