Uartlite Driver


Uartlite Driver

Introduction

The LogiCORE™ IP AXI Universal Asynchronous Receiver Transmitter (UART) Lite core provides between UART signals and the Advanced Microcontroller Bus Architecture (AMBA®) AXI interface and also provides a controller interface for asynchronous serial data transfer. This soft LogiCORE™ IP core is designed to interface with the AXI4-Lite protocol.

HW IP Features

  • AXI4-Lite interface for register access and data transfers
  • Full duplex
  • 16-character transmit and receive FIFOs
  • Configurable number of data bits (5-8) in a character
  • Configurable parity bit (odd or even or none)
  • Configurable baud rate

Features supported in driver

  • Supports 16-character transmit and receive FIFOs
  • Configurable number of data bits (5-8) in a character
  • Configurable parity bit (odd or even or none)

Missing Features, Known Issues and Limitations

  • None

Kernel Configuration

To enable the uartlite driver in the linux kernel you either have to integrate it or build it as kernel module (.ko). You can enable it with:
make menuconfig
---> Device Drivers ---> Character devices ---> Serial drivers ---> Xilinx uartlite serial port support
Or you can do this in the .config file with either of the following lines:
# integrate into the kernel
CONFIG_SERIAL_UARTLITE=y
# build as loadable module
CONFIG_SERIAL_UARTLITE=m
When using newer releases, and when more than one UART Lite is required in the system, the user should also configure the following configuration item
to increase the number of UART ports in the driver. The driver statically allocates port data structures based on this configuration item. The port-number device tree
property is used for each UART Lite device node and is used to index into a port data structure in the driver. The port-number is similar to the alias number such that
it is affected by the total number of UARTs in the system (including PS UARTs).
CONFIG_SERIAL_UARTLITE_NR_UARTS=<total number of UARTs in the system>

Devicetree


Here's how the devicetree entry could look like.

        uartlite_0@42C00000 {
            compatible = "xlnx,xps-uartlite-1.00.a";
            reg = <0x42C00000 0x10000>;
            interrupt-parent = <&gic>;
            interrupts = <0 59 4>;
            clock = <100000000>;
        };
 
        uartlite_1@42C10000 {
            compatible = "xlnx,xps-uartlite-1.00.a";
            reg = <0x42C10000 0x10000>;
            interrupt-parent = <&gic>;
            interrupts = <0 59 4>;
            clock = <100000000>;
        };
Note how you can use the same interrupt, but for that to work you must OR the interrupts from the uarts to the interrupt-input.

Vivado Block Design


Here's how the axi_uartlite can be instantiated twice in a Vivado Block Design.


Instead of connecting the interrupt outputs directly to IRQ_F2P they can also be OR-ed with the Utility Reduced Logic to connect them to only one interrupt channel. The interrupt outputs (irq_0, irq_1) generate a small positive going pulse for the rising edge sensitive interrupt input (IRQ_F2P).

Test procedure

The driver source file in the linux kernel at drivers/tty/serial/uartlite.c limits the number of supported UARTs to 16. If you need to increase that number, adjust this define near the top of the file:
#define ULITE_NR_UARTS 16
After that you of course have to rebuild the kernel and deploy it to your Zynq device.

Using the uartlite in Linux

With the FPGA binary loaded, the updated devicetree and updated kernel you should see one or more /dev/ttyULx devices.
Beware that linux puts all uarts in Canonical Mode, something you might not want in an embedded system. Chances are you want to use Non-Canonical or Raw Mode. Also don't use fopen / fprintf / fputs / etc. if you want raw access, use open / close / read / write instead.

$echo 123456789 > /dev/ttyUL0


Expected Output

root@Xilinx-ZC1751-DC2:~#
root@Xilinx-ZC1751-DC2:~# echo 123456789 > /dev/ttyUL0
[   70.634844] 123456789
root@Xilinx-ZC1751-DC2:~# echo 123456789abcd  > /dev/ttyUL0
[   75.774761] 123456789abcd

Mainline Status

This driver is currently in sync with mainline kernel driver.

Change Log

2024.1

Summary:

  • Use uart_xmit_advance()
  • Make uart_remove_one_port() return void
  • Explicitly include correct DT includes
  • Use dynamic allocation for major number when uart ports > 4

Commits:

852322fserial: uartlite: Use uart_xmit_advance()

d5b3d02serial: Make uart_remove_one_port() return void

29e5c44tty: Explicitly include correct DT includes

ff8f20aserial: uartlite: Use dynamic allocation for major number when uart ports > 4

2023.2

  • None

2023.1

Summary:

  • Make uart_console_write->putchar()'s character an unsigned char
  • serial: uartlite: Fix BRKINT clearing
  • serial: Make ->set_termios() old ktermios const

Commits:

3f8bab1serial: make uart_console_write->putchar()'s character an unsigned char

3f7fed4serial: uartlite: Fix BRKINT clearing

bec5b81serial: Make ->set_termios() old ktermios const


2022.2

Summary:

  • Revert da7ece39ff75 Remove an un-necessary read of control register

Commits:

80ca8ddserial-uartlite: Revert da7ece39ff75 Remove an un-necessary read of control register


2022.1

  • None

Related Links