mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
fix(lp_core): repair LP UART read_bytes RX handling
Fix read_bytes handling in lp_core_uart.c. Fix HP-side read_bounds guard checks in test_lp_core_uart.c: the ULP export header types shared symbols as uint32_t while the LP image maps a larger struct; avoid struct subscript on that symbol so GCC 14 -Warray-bounds= passes in CI (build_non_test_related_apps). Made-with: Cursor
This commit is contained in:
@@ -185,45 +185,49 @@ int lp_core_uart_read_bytes(uart_port_t lp_uart_num, void *buf, size_t size, int
|
||||
uint32_t to = 0;
|
||||
|
||||
while (remaining_bytes > 0) {
|
||||
/* Read from the Rx FIFO
|
||||
* We set rx_len to -1 to read all bytes in the Rx FIFO
|
||||
*/
|
||||
rx_len = -1;
|
||||
uart_hal_read_rxfifo(&hal, (uint8_t *)(buf + bytes_rcvd), &rx_len);
|
||||
/* Drain only as many bytes as fit in the remaining buffer space */
|
||||
int fifo_len = uart_ll_get_rxfifo_len(hal.dev);
|
||||
rx_len = (fifo_len < remaining_bytes) ? fifo_len : remaining_bytes;
|
||||
|
||||
if (rx_len) {
|
||||
/* We have some data to read from the Rx FIFO. Check Rx interrupt status */
|
||||
intr_status = uart_hal_get_intraw_mask(&hal);
|
||||
if ((intr_status & UART_INTR_RXFIFO_FULL) ||
|
||||
(intr_status & UART_INTR_RXFIFO_TOUT)) {
|
||||
/* This is expected. Clear interrupt status and break */
|
||||
uart_hal_clr_intsts_mask(&hal, intr_mask);
|
||||
if (rx_len > 0) {
|
||||
uart_hal_read_rxfifo(&hal, (uint8_t *)(buf + bytes_rcvd), &rx_len);
|
||||
bytes_rcvd += rx_len;
|
||||
remaining_bytes -= rx_len;
|
||||
|
||||
/* RXFIFO_FULL / RXFIFO_TOUT raw bits are sticky; acknowledge them
|
||||
* so they do not short-circuit the next iteration. */
|
||||
uart_hal_clr_intsts_mask(&hal, LP_UART_RX_INT_FLAG);
|
||||
|
||||
if (remaining_bytes <= 0) {
|
||||
break;
|
||||
} else if ((intr_status & UART_INTR_RXFIFO_OVF)) {
|
||||
/* We reset the Rx FIFO if it overflows */
|
||||
}
|
||||
|
||||
/* FIFO overflow and parity/framing errors are terminal */
|
||||
intr_status = uart_hal_get_intraw_mask(&hal);
|
||||
if (intr_status & UART_INTR_RXFIFO_OVF) {
|
||||
uart_hal_clr_intsts_mask(&hal, intr_mask);
|
||||
uart_hal_rxfifo_rst(&hal);
|
||||
break;
|
||||
} else if ((intr_status & LP_UART_ERR_INT_FLAG)) {
|
||||
/* Transaction error. Abort */
|
||||
} else if (intr_status & LP_UART_ERR_INT_FLAG) {
|
||||
uart_hal_clr_intsts_mask(&hal, intr_mask);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Update the byte counters */
|
||||
bytes_rcvd += rx_len;
|
||||
remaining_bytes -= rx_len;
|
||||
/* Progress was made; restart the timeout window so callers with
|
||||
* a finite timeout can tolerate gaps between bursts. */
|
||||
to = 0;
|
||||
} else {
|
||||
/* We have no data to read from the Rx FIFO. Check for transaction timeout */
|
||||
/* FIFO empty. Honour the caller's timeout. */
|
||||
ret = lp_core_uart_check_timeout(intr_mask, timeout, &to);
|
||||
if (ret == ESP_ERR_TIMEOUT) {
|
||||
/* Timeout. Clear interrupt status and break */
|
||||
uart_hal_clr_intsts_mask(&hal, intr_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the number of bytes received */
|
||||
return bytes_rcvd;
|
||||
if (bytes_rcvd > size) {
|
||||
bytes_rcvd = size;
|
||||
}
|
||||
return (int)bytes_rcvd;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "hal/uart_types.h"
|
||||
#include "lp_core_test_app_uart.h"
|
||||
@@ -30,6 +31,18 @@ extern const uint8_t lp_core_main_uart_bin_end[] asm("_binary_lp_core_test_app
|
||||
|
||||
static const char *TAG = "lp_core_uart_test";
|
||||
|
||||
/*
|
||||
* The LP-core binary exports shared symbols via a generated header that types
|
||||
* blobs as uint32_t placeholders. The HP test must still walk the real layout
|
||||
* (lp_uart_read_bounds_guard_t). Indexing through a struct pointer to
|
||||
* &ulp_read_bounds_guard_region triggers GCC -Warray-bounds= (object size 4).
|
||||
* Read bytes by absolute address so the compiler does not attach the wrong size.
|
||||
*/
|
||||
static __attribute__((noinline)) uint8_t lp_uart_test_read_shared_u8(uintptr_t addr)
|
||||
{
|
||||
return *(const volatile uint8_t *)addr;
|
||||
}
|
||||
|
||||
static void lp_core_uart_clear_buf(void)
|
||||
{
|
||||
uart_dev_t *dev = (uart_dev_t *)UART_LL_GET_HW(LP_UART_NUM_0);
|
||||
@@ -1057,13 +1070,16 @@ static void test_lp_uart_read_bytes_buffer_bounds(void)
|
||||
TEST_ASSERT_LESS_OR_EQUAL(LP_UART_READ_BOUNDS_USER_BUF_LEN, ret_val);
|
||||
TEST_ASSERT_GREATER_THAN(0, ret_val);
|
||||
|
||||
lp_uart_read_bounds_guard_t *region = (lp_uart_read_bounds_guard_t *)&ulp_read_bounds_guard_region;
|
||||
const uintptr_t guard_base = (uintptr_t)(void *)&ulp_read_bounds_guard_region;
|
||||
const size_t post_off = offsetof(lp_uart_read_bounds_guard_t, post_guard);
|
||||
for (int i = 0; i < LP_UART_READ_BOUNDS_GUARD_LEN; i++) {
|
||||
TEST_ASSERT_EQUAL_HEX8_MESSAGE(LP_UART_READ_BOUNDS_GUARD_PATTERN, region->pre_guard[i],
|
||||
TEST_ASSERT_EQUAL_HEX8_MESSAGE(LP_UART_READ_BOUNDS_GUARD_PATTERN,
|
||||
lp_uart_test_read_shared_u8(guard_base + (uintptr_t)i),
|
||||
"pre-guard memory corrupted");
|
||||
}
|
||||
for (int i = 0; i < LP_UART_READ_BOUNDS_GUARD_LEN; i++) {
|
||||
TEST_ASSERT_EQUAL_HEX8_MESSAGE(LP_UART_READ_BOUNDS_GUARD_PATTERN, region->post_guard[i],
|
||||
TEST_ASSERT_EQUAL_HEX8_MESSAGE(LP_UART_READ_BOUNDS_GUARD_PATTERN,
|
||||
lp_uart_test_read_shared_u8(guard_base + post_off + (uintptr_t)i),
|
||||
"post-guard memory corrupted");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user