ESP32中F​​IFO UART缓冲区的功能

ESP32具有三个UART。 每个都将接收器的FIFO缓冲区和发送器的FIFO缓冲区放置在1024个字节的共享内存中(ESP32技术参考手册3.5):



但是,当我尝试将UART2发送器缓冲区的FIFO大小从128字节增加到256个字节时,我得到了意想不到的效果-传输的数据破坏了UART0接收器的FIFO缓冲区,根据文档,这应该不是。


不幸的是,在文档(ESP32技术参考手册3.5)中,没有FIFO缓冲区寄存器的描述。 但是,在esp-idf头文件(在uart_struct.h中)中找到:


1)发送器缓冲区的FIFO状态寄存器(相对于基地址0x5c的偏移量):


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

2)接收器缓冲区的FIFO状态寄存器(相对于基地址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; 

假定mem_tx_status与mem_rx_status位的目的匹配,我们编写以下代码来获取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); } 

开始之后,我们得到:


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

输出是通过UART0执行的,因此tx_wr和tx_rd不同于0。根据获得的结果,FIFO缓冲区UART0,1,2之间的内存分配如下:


地址串口
0x00 ... 0x7FUART0 TX_FIFO
0x80 ... 0xFFUART1 TX_FIFO
0x100 ... 0x17FUART2 TX_FIFO
0x180 ... 0x1FFUART0的RX_FIFO
0x200 ... 0x27FUART1的RX_FIFO
0x280 ... 0x2FFUART2的RX_FIFO

另外,FIFO缓冲区的状态寄存器的位容量为11位,这意味着分配给FIFO缓冲区的内存大小= 2Kb是可能的。 当设置UART0.mem_conf.tx_size = 15(内存以128个字节的长度分配)时,将分配1920个字节,并且寄存器tx_wr在传输过程中将被计数为1919,并将继续从0开始计数。 但是,该内存仅寻址ml。 10位 分配给FIFO缓冲区的实际总内存= 1Kb。


总计:

  1. 分配给ESP32的FIFO UART的共享内存分配与技术参考手册3.5不匹配;
  2. 共享存储器FIFO UART的数量= 1Kb。

Source: https://habr.com/ru/post/zh-CN419955/


All Articles