Características del búfer FIFO UART en ESP32

ESP32 tiene tres UART. Cada uno de los cuales coloca el búfer FIFO del receptor y el búfer FIFO del transmisor en una memoria compartida de 1024 bytes (manual de referencia técnica ESP32 3.5):



Sin embargo, cuando intenté aumentar el tamaño del búfer FIFO del transmisor UART2 de 128 a 256 bytes, recibí un efecto inesperado: los datos transmitidos estropearon el búfer FIFO del receptor UART0, que, según la documentación, no debería serlo.


Desafortunadamente, en la documentación (manual de referencia técnica ESP32 3.5) no hay una descripción de los registros del búfer FIFO. Sin embargo, en los archivos de encabezado esp-idf (en uart_struct.h) se encontraron:


1) Registro de estado FIFO del búfer del transmisor (desplazamiento relativo a la dirección base 0x5c):


union { struct { uint32_t status:24; uint32_t reserved24: 8; }; uint32_t val; } mem_tx_status; 

2) Registro de estado FIFO del búfer del receptor (desplazamiento relativo a la dirección base 0x60):


  union { struct { uint32_t status: 24; uint32_t reserved24: 8; }; struct { uint32_t reserved0: 2; uint32_t rd_addr: 11; /*This register stores the rx mem read address.*/ uint32_t wr_addr: 11; /*This register stores the rx mem write address.*/ uint32_t reserved: 8; }; uint32_t val; } mem_rx_status; 

Suponiendo que mem_tx_status coincide con el propósito de los bits mem_rx_status, escribimos el siguiente código para obtener las direcciones de los búferes FIFO:


 #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include <driver/uart.h> void print_uart_st(uart_dev_t *u,int num) { printf("UART%d:\n",num); printf("rx_st=0x%X\n",(unsigned int)u->mem_rx_status.val); printf("rx_rd=0x%X\n",(unsigned int)u->mem_rx_status.rd_addr); printf("rx_wr=0x%X\n",(unsigned int)u->mem_rx_status.wr_addr); uint32_t tx_s = u->mem_tx_status.val; printf("tx_st=0x%X\n",tx_s); printf("tx_rd=0x%X\n",(tx_s>>2)&2047); printf("tx_wr=0x%X\n",(tx_s>>13)&2047); } uart_config_t uart_config = { .baud_rate = 115200, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE }; void UARTtest(void * param) { uart_param_config(UART_NUM_1,&uart_config); uart_param_config(UART_NUM_2,&uart_config); uart_driver_install(UART_NUM_1, 256, 0, 0, NULL, 0); uart_driver_install(UART_NUM_2, 256, 0, 0, NULL, 0); uart_set_pin(UART_NUM_1, UART_PIN_NO_CHANGE, GPIO_NUM_16, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); uart_set_pin(UART_NUM_2, UART_PIN_NO_CHANGE, GPIO_NUM_16, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); vTaskDelay(1000/portTICK_PERIOD_MS); while (1) { print_uart_st(&UART0,0); print_uart_st(&UART1,1); print_uart_st(&UART2,2); vTaskDelay(2000/portTICK_PERIOD_MS); char s[256]; uart_write_bytes(UART_NUM_1, s, 1); uart_write_bytes(UART_NUM_2, s, 2); if(gets(s)!=NULL) { printf("recived=%s\n",s); } } } void app_main(void) { xTaskCreate(UARTtest, "UARTtest", 4096, NULL, 5, NULL); } 

Después de comenzar, obtenemos:


UART0:
rx_st = 0x300600
rx_rd = 0x180
rx_wr = 0x180
tx_st = 0xCE058
tx_rd = 0x16
tx_wr = 0x67
UART1:
rx_st = 0x400800
rx_rd = 0x200
rx_wr = 0x200
tx_st = 0x100200
tx_rd = 0x80
tx_wr = 0x80
UART2:
rx_st = 0x500A00
rx_rd = 0x280
rx_wr = 0x280
tx_st = 0x200400
tx_rd = 0x100
tx_wr = 0x100

La salida se lleva a cabo a través de UART0, por lo tanto, tx_wr y tx_rd son diferentes de 0. Según los resultados obtenidos, la asignación de memoria entre las memorias intermedias FIFO UART0,1,2 es la siguiente:


DireccionesUART
0x00 ... 0x7FUART0 TX_FIFO
0x80 ... 0xFFUART1 TX_FIFO
0x100 ... 0x17FUART2 TX_FIFO
0x180 ... 0x1FFUART0 RX_FIFO
0x200 ... 0x27FUART1 RX_FIFO
0x280 ... 0x2FFUART2 RX_FIFO

Además, los registros de estado de las memorias intermedias FIFO tienen una resolución de 11 bits, lo que significa que es posible el tamaño de la memoria asignada a la memoria intermedia FIFO = 2K. Al configurar UART0.mem_conf.tx_size = 15 (la memoria se asigna en partes de 128 bytes de longitud), se asignarán 1920 bytes y el registro tx_wr se contará hasta 1919 durante la transmisión y continuará contando hasta 0. Sin embargo, la memoria se trata solo ml 10 bits, es decir memoria total real asignada para el búfer FIFO = 1Kb.


Total:

  1. La asignación de memoria compartida asignada a ESP32 para FIFO UART no coincide con el manual de referencia técnica 3.5;
  2. La cantidad de memoria compartida FIFO UART = 1Kb.

Source: https://habr.com/ru/post/es419955/


All Articles