Here, I present some information about the low-level operation of the
Universal Asynchronous Receiver/Transmitters (UARTs) on the ESP32-S3. I want to investigate how to use them without enabling
interrupts. I know that for some devices it is possible to enable an interrupt,
causing a flag to be set in the interrupt register, but leave the interrupt
table empty, such that no actual interrupt is generated. An important source of
information is Chapter 26: 'UART Controller' of the Technical Reference Manual. The ESP32-S3 has three UARTs each. The
transmit and receive buffers are taken from a shared 1024 byte region of RAM,
which is divided into 8 blocks of 128 bytes. The buffers start at fixed block.
This makes it possible to have larger transmit and receive buffers for some of
the UARTs, but limiting the buffers for others to zero, which basically
renders the UART (parly) unusable. The buffers of UART2 can be extended to
256 bytes without affecting the operations of UART0 and UART1 with at least
buffers of 128 bytes. (The use of the words 'Reserved' in Figure 26-3 are a
bit misleading, because the RAM regions can be used.) There is a possibility
to transfer large amounts of data by setting up a Direct Memory Access (DMA)
channel in the General Direct Memory Access (GDMA) device, which is described
in Chapter 3: 'GMDA Controller'. However the data goes through a Universal Host Controller Interface (UHCI), which, for example, is used
with USB. The UHCI performs some encoding and decoding to create a 'clean'
data stream surrounded with separators. It is not clear when an UART starts
sending data from the buffer. Is it as soon as a character is entered or only
when the buffer is filled with a certain number of characters and/or when a
certain character (such as a line-feed) is placed in the buffer. In the
reference manual it mentions that setting the UART_FORCE_XON bit
forces the transmitter to send data. This is only set in the
uart_ll_force_xon functions, which is called in
sleep_uart_resume function, which is called when the MCU returns from
sleep mode. This makes me wonder whether this is the only proper usage of it.
For the ESP32-S3 the function uart_ll_force_xon also the sets the
UART_SW_FLOW_CON_EN bit. In the reference manual it says: 'Set this
bit to enable software flow control.' That is maybe something you do not want
to be enabled, because it only works if the other side on the serial connection
also has it enabled with the same characters.
ESP-IDF offers various ways to control common LCDs according to the
documentation. For full screen updates, the theoretical maximum frame rate
is determined by the clock frequency multiplied by the bus width and divided by
the product of the number of pixela and the number of bits per pixel. In
practice it can be a bit lower, because most protocols also have some overhead.
Because for high resolution LCD the required screen buffer is usually too
large to fit in RAM, it means that it has to be placed in PSRAM. Depending on
the width of the SPI bus used to access PSRAM, this can pose limits on the
maximum clock frequency. Modifying the buffer in PSRAM also put some limits on
how often one can effectively update the display. ESP-IDF provides only a
limited number of LCD device controller drivers out of the box. More drivers
are available in the ESP Component Registry. A list of drivers that is supported by LVGL is given in Display and touchpad drivers for ESP32 using LVGL. For the ESP32-S3 there are several interfaces that can be used with displays, such
as I2C, SPI, several parallel interfaces, and (the newest) MIPI-DSI, which is
not supported by the ESP32-S3. (It is supported by the ESP32-P4, which is now
declared end-of-life and followed up by ESP32-P4X.) For the parallel
interfaces, I spend some time looking into the LCD controller of the ESP32-S3.
According to Chapter 29 '29 LCD and Camera Controller (LCD_CAM)' of the
Technical Reference Manual it has three parallel output formats: RGB,
MOTO6080, and I8080. There is a choice between 8 or 16 bits data bit. Besides
this, each requires a some other signals, 4 for the RGB, 2 for MOTO6800, and 3
for I8080. The number of bins thus ranges from 10 to 20. (It seems that the
with the LCD_DE signal in Figure 29-5 'LCD Timing (RGB Format)' is
refering to LCD_H_ENABLE.) The maximum data rate is the same for
both bus widths, because it is limited by GDMA and further if YUV-RGB format
conversion is used. If we assume that 2 bytes per pixel are used, it means
that the maximum frame rate for a 800×480 display is 104 without YUV-RGB
format conversion and 78 with. In practice this will be bit lower.
This months interesting links