mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
Merge branch 'test/uart_dma_ota_fix_v6.0' into 'release/v6.0'
refactor(uhci): refactor uart_dma_ota example (v6.0) See merge request espressif/esp-idf!48755
This commit is contained in:
@@ -626,6 +626,12 @@ examples/peripherals/twai/twai_utils:
|
||||
examples/peripherals/uart/uart_dma_ota:
|
||||
disable:
|
||||
- if: SOC_UHCI_SUPPORTED != 1
|
||||
depends_components:
|
||||
- esp_driver_uart
|
||||
- esp_driver_dma
|
||||
- app_update
|
||||
- esp_ringbuf
|
||||
- soc
|
||||
|
||||
examples/peripherals/uart/uart_echo_rs485:
|
||||
enable:
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
idf_component_register(SRCS "uart_dma_ota_example_main.c"
|
||||
REQUIRES esp_driver_uart app_update
|
||||
REQUIRES esp_driver_uart app_update esp_ringbuf
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/uhci.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
static const char *TAG = "uhci-example";
|
||||
|
||||
@@ -22,48 +24,36 @@ static const char *TAG = "uhci-example";
|
||||
#define EXAMPLE_UART_BAUD_RATE CONFIG_UART_BAUD_RATE
|
||||
#define EXAMPLE_UART_RX_IO CONFIG_UART_RX_IO
|
||||
#define UART_DMA_OTA_BUFFER_SIZE (10 * 1024)
|
||||
|
||||
typedef enum {
|
||||
UHCI_EVT_PARTIAL_DATA,
|
||||
UHCI_EVT_EOF,
|
||||
} uhci_event_t;
|
||||
#define UART_DMA_OTA_RINGBUF_SIZE (10 * 1024)
|
||||
|
||||
typedef struct {
|
||||
QueueHandle_t uhci_queue;
|
||||
size_t receive_size;
|
||||
uint8_t *ota_data1;
|
||||
uint8_t *ota_data2;
|
||||
bool use_ota_data1;
|
||||
} ota_example_context_t;
|
||||
RingbufHandle_t ringbuf;
|
||||
volatile bool rx_eof;
|
||||
volatile bool rx_overflow;
|
||||
} ota_rx_context_t;
|
||||
|
||||
static bool s_uhci_rx_event_cbs(uhci_controller_handle_t uhci_ctrl, const uhci_rx_event_data_t *edata, void *user_ctx)
|
||||
{
|
||||
ota_example_context_t *ctx = (ota_example_context_t *)user_ctx;
|
||||
BaseType_t xTaskWoken = 0;
|
||||
uhci_event_t evt = 0;
|
||||
ota_rx_context_t *ctx = (ota_rx_context_t *)user_ctx;
|
||||
BaseType_t xTaskWoken = pdFALSE;
|
||||
|
||||
if (xRingbufferSendFromISR(ctx->ringbuf, edata->data, edata->recv_size, &xTaskWoken) != pdTRUE) {
|
||||
ctx->rx_overflow = true;
|
||||
}
|
||||
if (edata->flags.totally_received) {
|
||||
evt = UHCI_EVT_EOF;
|
||||
} else {
|
||||
evt = UHCI_EVT_PARTIAL_DATA;
|
||||
ctx->rx_eof = true;
|
||||
}
|
||||
|
||||
// Choose the buffer to store received data
|
||||
ctx->receive_size = edata->recv_size;
|
||||
if (ctx->use_ota_data1) {
|
||||
ctx->ota_data1 = edata->data;
|
||||
} else {
|
||||
ctx->ota_data2 = edata->data;
|
||||
}
|
||||
|
||||
// Toggle the buffer for the next receive
|
||||
ctx->use_ota_data1 = !ctx->use_ota_data1;
|
||||
|
||||
xQueueSendFromISR(ctx->uhci_queue, &evt, &xTaskWoken);
|
||||
return xTaskWoken;
|
||||
return xTaskWoken == pdTRUE;
|
||||
}
|
||||
|
||||
static void perform_ota_update(uhci_controller_handle_t uhci_ctrl, ota_example_context_t *ctx)
|
||||
static bool rx_ringbuf_is_empty(RingbufHandle_t ringbuf)
|
||||
{
|
||||
UBaseType_t items_waiting = 0;
|
||||
vRingbufferGetInfo(ringbuf, NULL, NULL, NULL, NULL, &items_waiting);
|
||||
return items_waiting == 0;
|
||||
}
|
||||
|
||||
static void perform_ota_update(uhci_controller_handle_t uhci_ctrl, ota_rx_context_t *ctx)
|
||||
{
|
||||
const esp_partition_t *ota_partition = esp_ota_get_next_update_partition(NULL);
|
||||
if (!ota_partition) {
|
||||
@@ -75,25 +65,32 @@ static void perform_ota_update(uhci_controller_handle_t uhci_ctrl, ota_example_c
|
||||
ESP_ERROR_CHECK(esp_ota_begin(ota_partition, OTA_SIZE_UNKNOWN, &ota_handle));
|
||||
ESP_LOGI(TAG, "OTA process started");
|
||||
|
||||
uhci_event_t evt;
|
||||
uint32_t received_size = 0;
|
||||
uint8_t *pdata = heap_caps_calloc(1, UART_DMA_OTA_BUFFER_SIZE, MALLOC_CAP_DEFAULT);
|
||||
assert(pdata);
|
||||
ESP_ERROR_CHECK(uhci_receive(uhci_ctrl, pdata, UART_DMA_OTA_BUFFER_SIZE));
|
||||
while (1) {
|
||||
if (xQueueReceive(ctx->uhci_queue, &evt, portMAX_DELAY) == pdTRUE) {
|
||||
uint8_t *data_to_write = ctx->use_ota_data1 ? ctx->ota_data2 : ctx->ota_data1;
|
||||
ESP_ERROR_CHECK(esp_ota_write(ota_handle, data_to_write, ctx->receive_size));
|
||||
received_size += ctx->receive_size;
|
||||
if (evt == UHCI_EVT_EOF) {
|
||||
break;
|
||||
}
|
||||
|
||||
size_t total_received_size = 0;
|
||||
while (1) {
|
||||
size_t item_size = 0;
|
||||
uint8_t *data = xRingbufferReceive(ctx->ringbuf, &item_size, pdMS_TO_TICKS(1000));
|
||||
if (data) {
|
||||
ESP_ERROR_CHECK(esp_ota_write(ota_handle, data, item_size));
|
||||
vRingbufferReturnItem(ctx->ringbuf, data);
|
||||
total_received_size += item_size;
|
||||
}
|
||||
|
||||
if (ctx->rx_overflow) {
|
||||
ESP_LOGE(TAG, "RX ring buffer overflow, please reduce the baud rate or increase the ring buffer size");
|
||||
abort();
|
||||
}
|
||||
|
||||
if (ctx->rx_eof && rx_ringbuf_is_empty(ctx->ringbuf)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(pdata);
|
||||
|
||||
ESP_LOGI(TAG, "Total received size: %ld", received_size);
|
||||
ESP_LOGI(TAG, "Total received size: %zu", total_received_size);
|
||||
ESP_ERROR_CHECK(esp_ota_end(ota_handle));
|
||||
ESP_ERROR_CHECK(esp_ota_set_boot_partition(ota_partition));
|
||||
}
|
||||
@@ -126,25 +123,24 @@ void app_main(void)
|
||||
|
||||
ESP_LOGI(TAG, "UHCI initialized, baud rate is %d, rx pin is %d", uart_config.baud_rate, EXAMPLE_UART_RX_IO);
|
||||
|
||||
ota_example_context_t *ctx = calloc(1, sizeof(ota_example_context_t));
|
||||
assert(ctx);
|
||||
|
||||
ctx->uhci_queue = xQueueCreate(2, sizeof(uhci_event_t));
|
||||
assert(ctx->uhci_queue);
|
||||
|
||||
ctx->use_ota_data1 = true; // Start with ota_data1
|
||||
ota_rx_context_t ctx = {
|
||||
.ringbuf = xRingbufferCreate(UART_DMA_OTA_RINGBUF_SIZE, RINGBUF_TYPE_BYTEBUF),
|
||||
.rx_eof = false,
|
||||
.rx_overflow = false,
|
||||
};
|
||||
assert(ctx.ringbuf);
|
||||
|
||||
uhci_event_callbacks_t uhci_cbs = {
|
||||
.on_rx_trans_event = s_uhci_rx_event_cbs,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(uhci_register_event_callbacks(uhci_ctrl, &uhci_cbs, ctx));
|
||||
ESP_ERROR_CHECK(uhci_register_event_callbacks(uhci_ctrl, &uhci_cbs, &ctx));
|
||||
|
||||
perform_ota_update(uhci_ctrl, ctx);
|
||||
perform_ota_update(uhci_ctrl, &ctx);
|
||||
|
||||
ESP_ERROR_CHECK(uhci_del_controller(uhci_ctrl));
|
||||
|
||||
free(ctx);
|
||||
vRingbufferDelete(ctx.ringbuf);
|
||||
ESP_LOGI(TAG, "OTA update successful. Rebooting...");
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
@@ -48,9 +48,11 @@ def test_uart_dma_ota(dut: Dut) -> None:
|
||||
# We OTA the same binary to another partition and switch to there.
|
||||
binary_path = os.path.join(dut.app.binary_path, 'uart_dma_ota.bin')
|
||||
assert os.path.exists(binary_path), f'OTA binary not found at {binary_path}'
|
||||
binary_size = os.path.getsize(binary_path)
|
||||
|
||||
buad_rate = dut.app.sdkconfig.get('UART_BAUD_RATE')
|
||||
send_file_via_uart(FLASH_PORT, buad_rate, binary_path, PACKET_SIZE)
|
||||
dut.expect_exact(f'uhci-example: Total received size: {binary_size}')
|
||||
|
||||
dut.expect('OTA update successful. Rebooting', timeout=10)
|
||||
dut.expect('ESP-ROM:', timeout=10)
|
||||
|
||||
Reference in New Issue
Block a user