Особенности FIFO буфера UART в ESP32

    У ESP32 есть три UART-а. Каждый из которых размещает FIFO буфер приемника и FIFO буфер передатчика в общей памяти размером 1024 байта (ESP32 technical reference manual 3.5):



    Однако при попытке увеличить размер FIFO буфера передатчика UART2 с 128 до 256 байт получил неожиданный эффект — передаваемые данные портили FIFO буфер приемника UART0, чего согласно документации быть не должно.


    К сожалению в документации (ESP32 technical reference manual 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 следующее:


    Адреса UART
    0x00...0x7F UART0 TX_FIFO
    0x80...0xFF UART1 TX_FIFO
    0x100...0x17F UART2 TX_FIFO
    0x180...0x1FF UART0 RX_FIFO
    0x200...0x27F UART1 RX_FIFO
    0x280...0x2FF UART2 RX_FIFO

    Кроме того регистры состояния FIFO буферов имеют разрядность 11 бит, значит возможно размер памяти отводимой под FIFO буфера = 2Кб. При задании UART0.mem_conf.tx_size=15 (память выделяется кусками длинной 128 байт) будет выделено 1920 байт, и регистр tx_wr при передаче досчитает до 1919 и с последующим переходом через 0 продолжит счет. Однако память при этом адресуется только мл. 10 битами, т.е. реальный объем общей памяти отведенной под FIFO буфера = 1Кб.


    Итого:

    1. Распределение общей памяти, отводимой ESP32 под FIFO UART не соответствует приведенной в technical reference manual 3.5;
    2. Объем общей памяти FIFO UART = 1Кб.

    • +27
    • 6,3k
    • 2
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 2

      0
      Каким образом вы отлаживаете код для ESP32? Вы смогли подцепить gdb-сервер?
        0
        Отладка логами через uart. Про gdb пока не думал, логов хватает.

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое