Skip to content

When using esp_ota_write it triggers UART (IDFGH-15519) #16158

Open
@juanpgg-git

Description

@juanpgg-git

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

General issue report

I'm developing a project using ESP-IDF 5.3 on Windows for the ESP32-C3.

This project has several features, among them, UART and OTA.

The UART code is based on the ESP-IDF example "uart-events". The OTA feature is based on the ESP-IDF example "ble-ota" which is in the esp-iot-solution.

So far, my project is working as expected, but SOMETIMES when I'm doing OTA, the UART peripheral is triggered. I can confirm the UART is not triggered by an external event, it's something that happens when I'm doing OTA.

I'm able to solve the issue by disabling the UART interrupts when using esp_ota_write(), but that's more of a band-aid than a real solution.

This is my UART code:
`static void dmx_rx_task(void *pvParameters)
{
uart_event_t event;

for (;;)
{
    // wait for data in the dmx_queue
    if (xQueueReceive(dmx_rx_queue, (void *)&event, portMAX_DELAY))
    {
        bzero(dtmp, BUF_SIZE);
        switch (event.type)
        {
        case UART_DATA:
            // read the received data
            uart_read_bytes(DMX_UART_NUM, dtmp, event.size, portMAX_DELAY);
            // ESP_LOGI(UART_TAG, "event size %d", event.size);
            // for (int i = 0; i < event.size; i++)
            //{
            //     ESP_LOGI(UART_TAG, "dtmp = 0x%02X", dtmp[i]);
            // }
            //   check if break detected

            if (dmx_state == DMX_BREAK)
            {
                if (dtmp[0] == 0) // if not 0, then RDM or custom protocol
                {
                    dmx_state = DMX_DATA;
                    // reset dmx adress to 0
                    current_rx_addr = 0;
                }
                else if (dtmp[0] == RDM_START_CODE)
                {
                    dmx_state = DMX_DATA;
                }
            }
            if (dmx_state == DMX_DATA) // check if in data receive mode
            {

                memcpy(dmx_data, dtmp, 512);
                current_rx_addr = 512;

                // for (int i = 0; i < event.size; i++) // copy received bytes to dmx data array
                //{
                //    if (current_rx_addr < 513)
                //    {
                //        dmx_data[current_rx_addr++] = dtmp[i];
                //    }
                // }

                if (dtmp[0] == RDM_START_CODE)
                {
                    // ESP_LOGI("UART", "data received");
                    // for (int i = 0; i < event.size; i++)
                    //{
                    //    ESP_LOGI("UART", "dtmp [%d] 0x%02X", i, dtmp[i]);
                    //}

                    // ESP_LOGI("UART", "dtmp 21 0x%02X", dtmp[21]);
                    // ESP_LOGI("UART", "dtmp 22 0x%02X", dtmp[22]);

                    transaction_counter = dtmp[15];

                    uint16_t pid = COMBINE_PID(dtmp[21], dtmp[22]);
                    // ESP_LOGI("UART", "combine pid 0x%02x", pid);

                    if (pid == RDM_PID_SUPPORTED_PARAMETERS)
                    {
                        // ESP_LOGI("UART", "RDM_PID_SUPPORTED_PARAMETERS_SECOND_BYTE");
                        if (rdm_tx_task_handle == NULL)
                        {
                            ESP_LOGW(UART_TAG, "rdm_tx_task_handle task handle is NULL!");
                        }
                        else
                        {
                            // ESP_LOGI("UART", "RDM_PID_SUPPORTED_PARAMETERS");
                            xTaskNotify(rdm_tx_task_handle, RMD_SEND_SUPPORTED_PARAMETERS, eSetValueWithOverwrite);
                        }
                    }
                    else if (pid == RDM_PID_PARAMETER_DESCRIPTION)
                    {
                        // xicato software only asks for the PID 0x8067 because Digital Dots asked them to do it. In the future other versions can ask for new PIDs
                        // ESP_LOGI("UART", "RDM_PID_PARAMETER_DESCRIPTION_SECOND_BYTE");
                        if (rdm_tx_task_handle == NULL)
                        {
                            ESP_LOGW(UART_TAG, "rdm_tx_task_handle is NULL!");
                        }
                        else
                        {
                            // xTaskNotify(dmx_send_task_handle, RMD_SEND_PARAMETER_DESCRIPTION, eSetValueWithOverwrite);
                            // ESP_LOGI("UART", "RDM_PID_PARAMETER_DESCRIPTION");
                            uint16_t requested_parameter_description = COMBINE_PID(dtmp[24], dtmp[25]);

                            if (requested_parameter_description == RDM_PID_DEVICE_POWER_CONSUMPTION)
                            {
                                // ESP_LOGI("UART", "RDM_PID_PARAMETER_DESCRIPTION & RDM_PID_DEVICE_POWER_CONSUMPTION");
                                xTaskNotify(rdm_tx_task_handle, RMD_SEND_DEVICE_POWER_CONSUMPTION_PARAMETER_DESCRIPTION, eSetValueWithOverwrite);
                            }
                            else if (requested_parameter_description == RDM_PID_DEVICE_INPUT_VOLTAGE)
                            {
                                xTaskNotify(rdm_tx_task_handle, RMD_SEND_DEVICE_INPUT_VOLTAGE_PARAMETER_DESCRIPTION, eSetValueWithOverwrite);
                            }
                        }
                    }
                    else if (pid == RDM_PID_DEVICE_INFO)
                    {
                        // ESP_LOGI("UART", "RMD_PID_DEVICE_INFO_SECOND_BYTE");
                        if (rdm_tx_task_handle == NULL)
                        {
                            ESP_LOGW(UART_TAG, "rdm_tx_task_handle is NULL!");
                        }
                        else
                        {
                            // ESP_LOGI("UART", "RDM_PID_DEVICE_INFO");
                            xTaskNotify(rdm_tx_task_handle, RDM_SEND_DEVICE_INFO, eSetValueWithOverwrite);
                        }
                    }
                    else if (pid == RDM_PID_SOFTWARE_VERSION_LABEL)
                    {
                        // ESP_LOGI("UART", "RDM_PID_SOFTWARE_VERSION_LABEL_SECOND_BYTE");
                        if (rdm_tx_task_handle == NULL)
                        {
                            ESP_LOGW(UART_TAG, "rdm_tx_task_handle is NULL!");
                        }
                        else
                        {
                            // ESP_LOGI("UART", "RDM_PID_SOFTWARE_VERSION_LABEL");
                            xTaskNotify(rdm_tx_task_handle, RDM_SEND_SOFTWARE_VERSION_LABEL, eSetValueWithOverwrite);
                        }
                    }
                    else if (pid == RDM_PID_DEVICE_POWER_CONSUMPTION)
                    {
                        // ESP_LOGI("UART", "RDM_PID_DEVICE_POWER_CONSUMPTION");
                        if (rdm_tx_task_handle == NULL)
                        {
                            ESP_LOGW(UART_TAG, "rdm_tx_task_handle is NULL!");
                        }
                        else
                        {
                            // ESP_LOGI("UART", "RDM_PID_DEVICE_POWER_CONSUMPTION");
                            xTaskNotify(rdm_tx_task_handle, RDM_SEND_DEVICE_POWER_CONSUMPTION, eSetValueWithOverwrite);
                        }
                    }
                    else if (pid == RDM_PID_RESET_DEVICE)
                    {
                        // ESP_LOGI("UART", "reset device");
                    }
                    else if (pid == RDM_PID_DEVICE_INPUT_VOLTAGE)
                    {

                        if (rdm_tx_task_handle == NULL)
                        {
                            ESP_LOGW(UART_TAG, "rdm_tx_task_handle is NULL!");
                        }
                        else
                        { // ESP_LOGI("UART", "RDM_PID_DEVICE_INPUT_VOLTAGE");
                            xTaskNotify(rdm_tx_task_handle, RMD_SEND_INPUT_VOLTAGE, eSetValueWithOverwrite);
                        }
                    }
                }
                else if (dtmp[0] == DMX_START_CODE)
                {

                    // normal DMX packet
                    // ESP_LOGI(UART_TAG, "dmx normal packet");

                    uint16_t ch1 = (dmx_read(1) << 8) | dmx_read(2);
                    double channel_1_dimming = (ch1 / 65536.0f) * 100.0f;

                    ESP_LOGI(UART_TAG, "channel 1 dimming %0.2f", channel_1_dimming);

                    led_driver_event_t led_driver_event_msg;
                    led_driver_event_msg.data_type = DMX_CHANNEL_1_RECEIVED;
                    led_driver_event_msg.data = channel_1_dimming;

                    if (led_driver_queue != NULL)
                    {
                        if (xQueueSend(led_driver_queue, &led_driver_event_msg, portMAX_DELAY) != pdPASS)
                        {
                            ESP_LOGE(UART_TAG, "Failed to send data to LED task");
                        }
                    }

                    if (hardware_dual_channel_enable_get())
                    {
                        uint16_t ch2 = (dmx_read(3) << 8) | dmx_read(4);
                        double channel_2_dimming = (ch2 / 65536.0f) * 100.0f;
                        ESP_LOGI(UART_TAG, "channel 2 dimming %0.2f", channel_2_dimming);

                        led_driver_event_msg.data_type = DMX_CHANNEL_2_RECEIVED;
                        led_driver_event_msg.data = channel_2_dimming;

                        if (led_driver_queue != NULL)
                        {

                            if (xQueueSend(led_driver_queue, &led_driver_event_msg, portMAX_DELAY) != pdPASS)
                            {
                                ESP_LOGE(UART_TAG, "Failed to send data to LED task");
                            }
                        }
                    }
                }
            }
            break;
        case UART_BREAK:
            // break detected
            // clear queue und flush received bytes

            // ESP_LOGI(UART_TAG, "break");

            uart_flush_input(DMX_UART_NUM);
            xQueueReset(dmx_rx_queue);
            dmx_state = DMX_BREAK;
            break;
        case UART_FRAME_ERR:
        case UART_PARITY_ERR:
        case UART_BUFFER_FULL:
        case UART_FIFO_OVF:
        default:
            // error recevied, going to idle mode
            ESP_LOGE(UART_TAG, "error recevied, going to idle mode");

            uart_flush_input(DMX_UART_NUM);
            xQueueReset(dmx_rx_queue);
            dmx_state = DMX_IDLE;
            break;
        }
    }
}

}

void uart_init(void)
{
// configure UART for DMX
uart_config_t uart_config = {
.baud_rate = 250000,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_2,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE};

uart_param_config(DMX_UART_NUM, &uart_config);

// Set pins for UART
uart_set_pin(DMX_UART_NUM, DMX_SERIAL_OUTPUT_PIN, DMX_SERIAL_INPUT_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

// install queue
uart_driver_install(DMX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &dmx_rx_queue, 0);

uart_flush_input(DMX_UART_NUM);

xTaskCreate(dmx_rx_task, "dmx_rx_task", 2048, NULL, 1, NULL);
xTaskCreate(rdm_tx_task, "rdm_tx_task", 2048, NULL, 1, &rdm_tx_task_handle);

}`

This is my OTA code:
`bool ble_ota_ringbuf_init(uint32_t ringbuf_size)
{
s_ringbuf = xRingbufferCreate(ringbuf_size, RINGBUF_TYPE_BYTEBUF);
if (s_ringbuf == NULL)
{
return false;
}

return true;

}

size_t write_to_ringbuf(const uint8_t *data, size_t size)
{
BaseType_t done = xRingbufferSend(s_ringbuf, (void *)data, size, (TickType_t)portMAX_DELAY);
// ESP_LOGI(TAG, "xRingbufferSend");
if (done)
{
return size;
}
else
{
return 0;
}
}

void ota_task(void *arg)
{
esp_partition_t *partition_ptr = NULL;
esp_partition_t partition;
const esp_partition_t *next_partition = NULL;

uint32_t recv_len = 0;
uint8_t *data = NULL;
size_t item_size = 0;
ESP_LOGI(TAG, "ota_task start");

notify_sem = xSemaphoreCreateCounting(100, 0);
xSemaphoreGive(notify_sem);

partition_ptr = (esp_partition_t *)esp_ota_get_boot_partition();
if (partition_ptr == NULL)
{
    ESP_LOGE(TAG, "boot partition NULL!\r\n");
    goto OTA_ERROR;
}

if (partition_ptr->type != ESP_PARTITION_TYPE_APP)
{
    ESP_LOGE(TAG, "esp_current_partition->type != ESP_PARTITION_TYPE_APP\r\n");
    goto OTA_ERROR;
}

if (partition_ptr->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY)
{
    partition.subtype = ESP_PARTITION_SUBTYPE_APP_OTA_0;
}
else
{
    next_partition = esp_ota_get_next_update_partition(partition_ptr);
    if (next_partition)
    {
        partition.subtype = next_partition->subtype;
    }
    else
    {
        partition.subtype = ESP_PARTITION_SUBTYPE_APP_OTA_0;
    }
}

partition.type = ESP_PARTITION_TYPE_APP;

partition_ptr = (esp_partition_t *)esp_partition_find_first(partition.type, partition.subtype, NULL);
if (partition_ptr == NULL)
{
    ESP_LOGE(TAG, "partition NULL!\r\n");
    goto OTA_ERROR;
}

uart_disable_rx_intr(UART_NUM_1);

memcpy(&partition, partition_ptr, sizeof(esp_partition_t));
if (esp_ota_begin(&partition, OTA_SIZE_UNKNOWN, &out_handle) != ESP_OK)
{
    ESP_LOGE(TAG, "esp_ota_begin failed!\r\n");
    goto OTA_ERROR;
}

uart_enable_rx_intr(UART_NUM_1);

// ESP_LOGI(TAG, "Stack watermark before waiting: %u", uxTaskGetStackHighWaterMark(NULL));
// ESP_LOGI(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size());

ESP_LOGI(TAG, "wait for data from ringbuf! fw_len = %u", ble_ota_get_fw_length());
// deal with all receive packet*
for (;;)
{
    data = (uint8_t *)xRingbufferReceive(s_ringbuf, &item_size, (TickType_t)portMAX_DELAY);

    xSemaphoreTake(notify_sem, portMAX_DELAY);

    // ESP_LOGI(TAG, "recv: %u, recv_total:%" PRIu32 "\n", item_size, recv_len + item_size);

    if (item_size != 0)
    {
        uart_disable_rx_intr(UART_NUM_1);

        if (esp_ota_write(out_handle, (const void *)data, item_size) != ESP_OK)
        {
            ESP_LOGE(TAG, "esp_ota_write failed!\r\n");
            goto OTA_ERROR;
        }
        else
        {
            // ESP_LOGI(TAG, "esp_ota_write ok");
        }

        uart_disable_rx_intr(UART_NUM_1);

        recv_len += item_size;
        vRingbufferReturnItem(s_ringbuf, (void *)data);

        // ESP_LOGI(TAG, "recv_len: %" PRIu32, recv_len);
        // ESP_LOGI(TAG, "ble_ota_get_fw_length: %d", ble_ota_get_fw_length());

        if (recv_len >= ble_ota_get_fw_length())
        {
            xSemaphoreGive(notify_sem);
            break;
        }
    }

    xSemaphoreGive(notify_sem);
}

if (esp_ota_end(out_handle) != ESP_OK)
{
    ESP_LOGE(TAG, "esp_ota_end failed!\r\n");
    goto OTA_ERROR;
}

if (esp_ota_set_boot_partition(&partition) != ESP_OK)
{
    ESP_LOGE(TAG, "esp_ota_set_boot_partition failed!\r\n");
    goto OTA_ERROR;
}

vSemaphoreDelete(notify_sem);
ESP_LOGI(TAG, "ESP restart");
esp_restart();

OTA_ERROR:
ESP_LOGE(TAG, "OTA failed");
vTaskDelete(NULL);
}

void ota_init()
{

// ESP_LOGI(TAG, "Stack watermark before ringbuffer init: %u", uxTaskGetStackHighWaterMark(NULL));
// ESP_LOGI(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size());

if (!ble_ota_ringbuf_init(OTA_RINGBUF_SIZE))
{
    ESP_LOGE(TAG, "%s init ringbuf fail", __func__);
    return;
}

xTaskCreate(&ota_task, "ota_task", OTA_TASK_SIZE, NULL, 1, NULL);

}`

The ringbuffer is filled from the BLE module when it receives the data from the phone, same as on the ESP-IDF example.

I have been looking for errors on the chip that can be documented, but haven't found anything related to OTA/UART.

Any help for a real solution is greatly appreciated. Thanks in advance

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions