Raspberry Pi 4 mini UART driver example
You can find a mini UART sample driver in the RPi4 BSP download package, com.qnx.qnx800.bsp.hw.raspberrypi_bcm2711_rpi4, under src/hardware/devc/serminiuart.
- Sends and receives data from the mini UART.
- Supports multiple devices.
-
Is implemented using many functions in multiple source files:
-
externs.c - defines the global data.
-
externs.h - includes the required headers, defines device-specific data structure, and declares the global data.
-
init.c - initialization code.
-
intr.c - interrupt handler routines.
-
main.c - the main entry point of the driver and device clean-up code.
-
mini_uart.h - defines macros containing RPi4 mini UART-specific values.
-
options.c - defines initial parameters and parses the driver's command-line arguments.
-
proto.h - prototypes for the driver's interface routines and logging utility macros.
-
tto.c - a routine to transmit data, called by io-char. It also provides support to control and read hardware-control lines status, and provides support for the stty utility. If there's no TX FIFO, tto() writes only a single character.
-
Interrupts
Different chips use interrupts in different ways. Typically, interrupts occur when:
-
the RX FIFO's receive level/threshold is reached.
-
the TX FIFO empties.
-
a change in the modem status lines occurs.
The driver code adds characters only to the input queue/buffer. The io-char module handles the canonical buffer, which is manipulated when the client read request is handled.
Customizing a serial driver
-
Your hardware is almost compatible with the mini UART, you might have to change the register addresses.
-
Compatibility is in question, you may have to change the source code.
You might not need to make any changes if:
-
Your serial hardware is completely compatible with the mini UART.
Implementation
The mini UART sample driver:
-
has a main() function that:
-
uses TTC_INIT_PROC to initialize the io-char library and set its priority,
-
uses the options() function, which:
-
initializes the TTYINIT struct.
-
calls the ttc() function to set device to raw mode.
-
uses TTC_SET_OPTION to parse default devc-* and devc-ser* options.
-
parses custom options.
-
calls create_device() function for all serial devices specified, which:
-
initializes the TTYDEV struct.
-
uses TTC_INIT_TTYNAME to setup device name.
-
calls the ser_attach_intr() function to setup interrupt handling.
-
calls the stty() function to initialize mini UART hardware communication.
-
uses TTC_INIT_ATTACH to register driver device path.
-
-
-
uses TTC_INIT_START to run the driver.
-
-
provides implementation of the tto() function which:
-
sets the baud rate.
-
sets line control.
-
checks the line status.
-
uses tto_getchar() to get data from output buffer.
-
sends data to UART.
-
uses tto_checkclients() to check if clients need to be notified.
-
-
provides implementation that receives data from mini UART when woken by an interrupt:
-
reads data from mini UART.
-
uses tti() to send data to input buffer.
-
notifies clients.
-
Functions
The devc-serminiuart driver includes the following functions, declared in proto.h:
create_device(TTYINIT *dip)-
Gets a device entry and its input/output buffers and creates a new device based on the options passed in.
-
Called by options().
-
Calls ttc() with an argument of TTC_INIT_CC to initialize TTYDEV instance.
-
Calls ttc() with an argument of TTC_INIT_TTYNAME to setup device name.
-
Calls ser_attach_intr() to setup interrupt handling.
-
Calls ser_stty() to initialize mini UART hardware.
-
void ser_stty(DEV_MINIUART *dev)-
Configures registers that can be changed dynamically at runtime (baud, parity, stop bits, etc.).
-
Called by create_device() and by tto() function when called with TTO_STTY.
-
Don't use this function for any initialization that you need to do when first setting up the driver; use create_device() instead.
-
void ser_attach_intr(DEV_MINIUART *dev)-
Configures hardware interrupt handler.
-
Called by create_device().
-
void ser_detach_intr(DEV_MINIUART *dev)-
Disables hardware interrupt and cleans-up the interrupt handler.
-
Called by dev_cleanup(), which is called by io-char’s clean-up thread.
-
unsigned options(int argc, char *argv[])-
Parses the driver's command-line arguments. For information about the arguments, refer to devc-*, devc-ser* options.
-
Depending on the options specified, this function may call:
-
ttc() with an argument of TTC_INIT_RAW to configure the terminal to RAW mode.
-
ttc() with an argument of TTC_SET_OPTION to pass standard terminal configuration options to io-char to be executed.
-
create_device() to create a device.
-
-
Returns the number of ports that are enabled.
-
The driver's main() routine (defined in main.c) calls:
-
ttc() with an argument of TTC_INIT_PROC to allocate and configure the resources shared by all devices, e.g., the resource manager
-
ttc() with an argument of TTC_INIT_START to allow the driver to start accepting messages, i.e., work.
-
options() to parse the driver's command-line options.
