From be8a0568c5ccd12bee2aa10ab39f0b84271485fe Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Fri, 26 Apr 2024 14:32:16 +0200 Subject: [PATCH 1/2] test(lp-core): Fixed unstable LP UART tests This commit fixes some flaky LP UART unit tests. --- .../lp_core/main/lp_core/test_main_uart.c | 28 ++++++++- .../lp_core/main/lp_core/test_shared.h | 1 + .../lp_core/main/test_lp_core_uart.c | 63 +++++++++++++++++-- 3 files changed, 84 insertions(+), 8 deletions(-) diff --git a/components/ulp/test_apps/lp_core/main/lp_core/test_main_uart.c b/components/ulp/test_apps/lp_core/main/lp_core/test_main_uart.c index ae331acb5c..a934aa607c 100644 --- a/components/ulp/test_apps/lp_core/main/lp_core/test_main_uart.c +++ b/components/ulp/test_apps/lp_core/main/lp_core/test_main_uart.c @@ -23,6 +23,7 @@ uint8_t rx_data[LP_UART_BUFFER_LEN] = {}; /* Data transmission length */ volatile uint8_t tx_len = 0; +volatile uint8_t rx_len = 0; int main(void) { @@ -39,13 +40,34 @@ int main(void) if (test_cmd == LP_CORE_LP_UART_READ_TEST) { /* Read data from LP UART */ - int bytes_remaining = tx_len; + int bytes_received = 0; + int idx = 0; + while (1) { + /* Read 1 byte at a time until we receive the end_pattern of 0xFEEDBEEF */ + bytes_received = lp_core_uart_read_bytes(LP_UART_PORT_NUM, rx_data + idx, 1, 100); + if (bytes_received < 0) { + break; + } + if (idx > 3 && rx_data[idx] == 0xEF && rx_data[idx - 1] == 0xBE && rx_data[idx - 2] == 0xED && rx_data[idx - 3] == 0xFE) { + /* Break and notify HP core of test completion */ + break; + } + idx += bytes_received; + } + } + + if (test_cmd == LP_CORE_LP_UART_MULTI_BYTE_READ_TEST) { + int bytes_remaining = rx_len; int bytes_received = 0; int idx = 0; while (bytes_remaining > 0) { - bytes_received = lp_core_uart_read_bytes(LP_UART_PORT_NUM, rx_data + idx, tx_len, LP_UART_TRANS_WAIT_FOREVER); - idx += bytes_received; + /* Read as much data as we can in one iteration */ + bytes_received = lp_core_uart_read_bytes(LP_UART_PORT_NUM, rx_data + idx, bytes_remaining, LP_UART_TRANS_WAIT_FOREVER); + if (bytes_received < 0) { + break; + } bytes_remaining -= bytes_received; + idx += bytes_received; } } diff --git a/components/ulp/test_apps/lp_core/main/lp_core/test_shared.h b/components/ulp/test_apps/lp_core/main/lp_core/test_shared.h index 8348c16c6d..e412e6de08 100644 --- a/components/ulp/test_apps/lp_core/main/lp_core/test_shared.h +++ b/components/ulp/test_apps/lp_core/main/lp_core/test_shared.h @@ -22,6 +22,7 @@ typedef enum { LP_CORE_DEEP_SLEEP_WAKEUP_LONG_DELAY_TEST, LP_CORE_LP_UART_WRITE_TEST, LP_CORE_LP_UART_READ_TEST, + LP_CORE_LP_UART_MULTI_BYTE_READ_TEST, LP_CORE_NO_COMMAND, } lp_core_test_commands_t; diff --git a/components/ulp/test_apps/lp_core/main/test_lp_core_uart.c b/components/ulp/test_apps/lp_core/main/test_lp_core_uart.c index 11a1b034f7..bfe1948369 100644 --- a/components/ulp/test_apps/lp_core/main/test_lp_core_uart.c +++ b/components/ulp/test_apps/lp_core/main/test_lp_core_uart.c @@ -91,6 +91,7 @@ static lp_core_uart_cfg_t lp_uart_cfg1 = { /* Global test data */ const uint8_t start_pattern[4] = {0xDE, 0xAD, 0xBE, 0xEF}; +const uint8_t end_pattern[4] = {0xFE, 0xED, 0xBE, 0xEF}; uint8_t expected_rx_data[UART_BUF_SIZE]; #define TEST_DATA_LEN 234 // Select a random number of bytes to transmit @@ -99,9 +100,15 @@ static void setup_test_data(uint8_t *tx_data, uint8_t *rx_data) if (tx_data) { /* Copy the start pattern followed by the test data */ memcpy(tx_data, start_pattern, sizeof(start_pattern)); - for (int i = sizeof(start_pattern); i < TEST_DATA_LEN + sizeof(start_pattern); i++) { + int i = 0; + for (i = sizeof(start_pattern); i < TEST_DATA_LEN + sizeof(start_pattern); i++) { tx_data[i] = i + 7 - sizeof(start_pattern); // We use test data which is i + 7 } + /* Copy the end pattern to mark the end of transmission. + * This is used by the LP core during read operations to + * notify the HP core of test completion. + */ + memcpy(tx_data + i, end_pattern, sizeof(end_pattern)); } if (rx_data) { @@ -327,7 +334,7 @@ static void hp_uart_write(void) unity_wait_for_signal("LP UART recv ready"); /* Write data to LP UART */ - uart_write_bytes(UART_NUM_1, (const char *)tx_data, TEST_DATA_LEN + sizeof(start_pattern)); + uart_write_bytes(UART_NUM_1, (const char *)tx_data, TEST_DATA_LEN + sizeof(start_pattern) + sizeof(end_pattern)); /* Uninstall the HP UART driver */ uart_driver_delete(UART_NUM_1); @@ -350,7 +357,6 @@ static void test_lp_uart_read(void) /* Setup test data */ setup_test_data(NULL, expected_rx_data); - ulp_tx_len = TEST_DATA_LEN + sizeof(start_pattern); /* Start the test */ ESP_LOGI(TAG, "Read test start"); @@ -414,7 +420,7 @@ static void hp_uart_write_options(void) unity_wait_for_signal("LP UART recv ready"); /* Write data to LP UART */ - uart_write_bytes(UART_NUM_1, (const char *)tx_data, TEST_DATA_LEN + sizeof(start_pattern)); + uart_write_bytes(UART_NUM_1, (const char *)tx_data, TEST_DATA_LEN + sizeof(start_pattern) + sizeof(end_pattern)); /* Uninstall the HP UART driver */ uart_driver_delete(UART_NUM_1); @@ -437,7 +443,6 @@ static void test_lp_uart_read_options(void) /* Setup test data */ setup_test_data(NULL, expected_rx_data); - ulp_tx_len = TEST_DATA_LEN + sizeof(start_pattern); /* Start the test */ ESP_LOGI(TAG, "Read test start"); @@ -466,6 +471,52 @@ static void test_lp_uart_read_options(void) TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_rx_data, rx_data + data_idx, TEST_DATA_LEN); } +static void test_lp_uart_read_multi_byte(void) +{ + /* Setup LP UART with updated configuration */ + TEST_ASSERT(ESP_OK == lp_core_uart_init(&lp_uart_cfg)); + + /* Wait for the HP UART device to be initialized */ + unity_wait_for_signal("HP UART init done"); + + /* Load and Run the LP core firmware */ + ulp_lp_core_cfg_t lp_cfg = { + .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU, + }; + load_and_start_lp_core_firmware(&lp_cfg, lp_core_main_uart_bin_start, lp_core_main_uart_bin_end); + + /* Setup test data */ + setup_test_data(NULL, expected_rx_data); + ulp_rx_len = TEST_DATA_LEN + sizeof(start_pattern); + + /* Start the test */ + ESP_LOGI(TAG, "Read test start"); + ulp_test_cmd = LP_CORE_LP_UART_MULTI_BYTE_READ_TEST; + vTaskDelay(10); + + /* Notify the HP UART to write data */ + unity_send_signal("LP UART recv ready"); + + /* Wait for test completion */ + while (ulp_test_cmd_reply != LP_CORE_COMMAND_OK) { + vTaskDelay(10); + } + + /* Check if we received the start pattern */ + uint8_t *rx_data = (uint8_t*)&ulp_rx_data; + int data_idx = -1; + for (int i = 0; i < UART_BUF_SIZE; i++) { + if (!memcmp(rx_data + i, start_pattern, sizeof(start_pattern))) { + data_idx = i + 4; // Index of byte just after the start_pattern + } + } + + /* Verify test data. We verify 10 bytes less because the multi-device can sometimes + * begin with garbage data which fills the initial part of the receive buffer. */ + ESP_LOGI(TAG, "Verify Rx data"); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_rx_data, rx_data + data_idx, TEST_DATA_LEN - 10); +} + /* Test LP UART write operation with default LP UART initialization configuration */ TEST_CASE_MULTIPLE_DEVICES("LP-Core LP-UART write test - default config", "[lp_core][test_env=generic_multi_device][timeout=150]", test_lp_uart_write, hp_uart_read); /* Test LP UART write operation with updated LP UART initialization configuration */ @@ -474,3 +525,5 @@ TEST_CASE_MULTIPLE_DEVICES("LP-Core LP-UART write test - optional config", "[lp_ TEST_CASE_MULTIPLE_DEVICES("LP-Core LP-UART read test - default config", "[lp_core][test_env=generic_multi_device][timeout=150]", test_lp_uart_read, hp_uart_write); /* Test LP UART read operation with updated LP UART initialization configuration */ TEST_CASE_MULTIPLE_DEVICES("LP-Core LP-UART read test - optional config", "[lp_core][test_env=generic_multi_device][timeout=150]", test_lp_uart_read_options, hp_uart_write_options); +/* Test LP UART multi-byte read operation */ +TEST_CASE_MULTIPLE_DEVICES("LP-Core LP-UART multi-byte read test", "[lp_core][test_env=generic_multi_device][timeout=150]", test_lp_uart_read_multi_byte, hp_uart_write); From 3cbe88427e92703dee0d4e26dbdaaeda44436fb4 Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Fri, 26 Apr 2024 16:52:31 +0200 Subject: [PATCH 2/2] test(lp-core): Added unit test for lp_core_printf This commit adds a unit test for the lp_core_printf API. --- .../lp_core/main/lp_core/test_main_uart.c | 21 +++ .../lp_core/main/lp_core/test_shared.h | 1 + .../lp_core/main/test_lp_core_uart.c | 122 ++++++++++++++++++ 3 files changed, 144 insertions(+) diff --git a/components/ulp/test_apps/lp_core/main/lp_core/test_main_uart.c b/components/ulp/test_apps/lp_core/main/lp_core/test_main_uart.c index a934aa607c..6dc5e3c167 100644 --- a/components/ulp/test_apps/lp_core/main/lp_core/test_main_uart.c +++ b/components/ulp/test_apps/lp_core/main/lp_core/test_main_uart.c @@ -9,6 +9,7 @@ #include "test_shared.h" #include "ulp_lp_core_utils.h" #include "ulp_lp_core_uart.h" +#include "ulp_lp_core_print.h" #define LP_UART_PORT_NUM LP_UART_NUM_0 #define LP_UART_BUFFER_LEN UART_BUF_SIZE @@ -25,6 +26,14 @@ uint8_t rx_data[LP_UART_BUFFER_LEN] = {}; volatile uint8_t tx_len = 0; volatile uint8_t rx_len = 0; +/* LP Core print test variables */ +volatile char test_string[25]; +volatile char test_long_string[200]; +volatile int test_signed_integer; +volatile uint32_t test_unsigned_integer; +volatile int test_hex; +volatile char test_character; + int main(void) { while (1) { @@ -71,6 +80,18 @@ int main(void) } } + if (test_cmd == LP_CORE_LP_UART_PRINT_TEST) { + /* Write various cases to test lp_core_printf to test various format specifiers */ + lp_core_printf("%s\r\n", test_string); + lp_core_printf("%s\r\n", test_long_string); + lp_core_printf("Test printf signed integer %d\r\n", test_signed_integer); + lp_core_printf("Test printf unsigned integer %u\r\n", test_unsigned_integer); + lp_core_printf("Test printf hex %x\r\n", test_hex); + lp_core_printf("Test printf character %c\r\n", test_character); + // TODO: Floating point prints are not supported + // lp_core_printf("Test printf float %f\r\n", (float)0.99); + } + /* Synchronize with the HP core running the test */ test_cmd = LP_CORE_NO_COMMAND; test_cmd_reply = LP_CORE_COMMAND_OK; diff --git a/components/ulp/test_apps/lp_core/main/lp_core/test_shared.h b/components/ulp/test_apps/lp_core/main/lp_core/test_shared.h index e412e6de08..8f27a65915 100644 --- a/components/ulp/test_apps/lp_core/main/lp_core/test_shared.h +++ b/components/ulp/test_apps/lp_core/main/lp_core/test_shared.h @@ -23,6 +23,7 @@ typedef enum { LP_CORE_LP_UART_WRITE_TEST, LP_CORE_LP_UART_READ_TEST, LP_CORE_LP_UART_MULTI_BYTE_READ_TEST, + LP_CORE_LP_UART_PRINT_TEST, LP_CORE_NO_COMMAND, } lp_core_test_commands_t; diff --git a/components/ulp/test_apps/lp_core/main/test_lp_core_uart.c b/components/ulp/test_apps/lp_core/main/test_lp_core_uart.c index bfe1948369..ac5c196fc9 100644 --- a/components/ulp/test_apps/lp_core/main/test_lp_core_uart.c +++ b/components/ulp/test_apps/lp_core/main/test_lp_core_uart.c @@ -94,6 +94,12 @@ const uint8_t start_pattern[4] = {0xDE, 0xAD, 0xBE, 0xEF}; const uint8_t end_pattern[4] = {0xFE, 0xED, 0xBE, 0xEF}; uint8_t expected_rx_data[UART_BUF_SIZE]; #define TEST_DATA_LEN 234 // Select a random number of bytes to transmit +char test_string[25]; +char test_long_string[200]; +int test_signed_integer; +uint32_t test_unsigned_integer; +int test_hex; +char test_character; static void setup_test_data(uint8_t *tx_data, uint8_t *rx_data) { @@ -118,6 +124,16 @@ static void setup_test_data(uint8_t *tx_data, uint8_t *rx_data) } } +static void setup_test_print_data(void) +{ + strcpy(test_string, "Test printf string"); + strcpy(test_long_string, "Print a very loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong string"); + test_signed_integer = -77; + test_unsigned_integer = 1234567890; + test_hex = 0xa; + test_character = 'n'; +} + static void hp_uart_read(void) { /* Configure HP UART driver */ @@ -517,6 +533,110 @@ static void test_lp_uart_read_multi_byte(void) TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_rx_data, rx_data + data_idx, TEST_DATA_LEN - 10); } +static void hp_uart_read_print(void) +{ + /* Configure HP UART driver */ + uart_config_t hp_uart_cfg = { + .baud_rate = lp_uart_cfg.uart_proto_cfg.baud_rate, + .data_bits = lp_uart_cfg.uart_proto_cfg.data_bits, + .parity = lp_uart_cfg.uart_proto_cfg.parity, + .stop_bits = lp_uart_cfg.uart_proto_cfg.stop_bits, + .flow_ctrl = lp_uart_cfg.uart_proto_cfg.flow_ctrl, + .source_clk = UART_SCLK_DEFAULT, + }; + int intr_alloc_flags = 0; + +#if CONFIG_UART_ISR_IN_IRAM + intr_alloc_flags = ESP_INTR_FLAG_IRAM; +#endif + + /* Install HP UART driver */ + ESP_ERROR_CHECK(uart_driver_install(UART_NUM_1, UART_BUF_SIZE, 0, 0, NULL, intr_alloc_flags)); + ESP_ERROR_CHECK(uart_param_config(UART_NUM_1, &hp_uart_cfg)); + + /* Cross-connect the HP UART pins and the LP UART pins for the test */ + ESP_ERROR_CHECK(uart_set_pin(UART_NUM_1, lp_uart_cfg.uart_pin_cfg.rx_io_num, lp_uart_cfg.uart_pin_cfg.tx_io_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); + + /* Notify the LP UART that the HP UART is initialized */ + unity_send_signal("HP UART init done"); + + /* Setup test data */ + setup_test_print_data(); + + /* Receive data from LP UART */ + uint8_t rx_data[UART_BUF_SIZE]; + int recv_idx = 0; + int idle_count = 0; + while (1) { + int bytes_received = uart_read_bytes(UART_NUM_1, rx_data + recv_idx, UART_BUF_SIZE, 10 / portTICK_PERIOD_MS); + if (bytes_received < 0) { + TEST_FAIL_MESSAGE("HP UART read error"); + } else if (bytes_received > 0) { + recv_idx += bytes_received; + } else if (bytes_received == 0) { + idle_count++; + vTaskDelay(10); + if (idle_count > 10) { + break; + } + } + } + rx_data[UART_BUF_SIZE - 1] = '\0'; + + /* Parse the rx_data to verify the printed data */ + /* Search for expected_string in rx_data. Report test pass if the string is found */ + char expected_string[TEST_DATA_LEN]; + snprintf(expected_string, TEST_DATA_LEN, "%s", test_string); + TEST_ASSERT_NOT_NULL(strstr((const char *)rx_data, expected_string)); + + snprintf(expected_string, TEST_DATA_LEN, "%s", test_long_string); + TEST_ASSERT_NOT_NULL(strstr((const char *)rx_data, expected_string)); + + snprintf(expected_string, TEST_DATA_LEN, "Test printf signed integer %d", test_signed_integer); + TEST_ASSERT_NOT_NULL(strstr((const char *)rx_data, expected_string)); + + snprintf(expected_string, TEST_DATA_LEN, "Test printf unsigned integer %lu", test_unsigned_integer); + TEST_ASSERT_NOT_NULL(strstr((const char *)rx_data, expected_string)); + + snprintf(expected_string, TEST_DATA_LEN, "Test printf hex %x", test_hex); + TEST_ASSERT_NOT_NULL(strstr((const char *)rx_data, expected_string)); + + snprintf(expected_string, TEST_DATA_LEN, "Test printf character %c", test_character); + TEST_ASSERT_NOT_NULL(strstr((const char *)rx_data, expected_string)); + + /* Uninstall the HP UART driver */ + uart_driver_delete(UART_NUM_1); + vTaskDelay(1); +} + +static void test_lp_uart_print(void) +{ + /* Setup LP UART with default configuration */ + TEST_ASSERT(ESP_OK == lp_core_uart_init(&lp_uart_cfg)); + + /* Wait for the HP UART device to be initialized */ + unity_wait_for_signal("HP UART init done"); + + /* Load and Run the LP core firmware */ + ulp_lp_core_cfg_t lp_cfg = { + .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU, + }; + load_and_start_lp_core_firmware(&lp_cfg, lp_core_main_uart_bin_start, lp_core_main_uart_bin_end); + + /* Setup test data */ + setup_test_print_data(); + strcpy((char *)&ulp_test_string, test_string); + strcpy((char *)&ulp_test_long_string, test_long_string); + ulp_test_signed_integer = test_signed_integer; + ulp_test_unsigned_integer = test_unsigned_integer; + ulp_test_hex = test_hex; + ulp_test_character = test_character; + + /* Start the test */ + ESP_LOGI(TAG, "LP Core print test start"); + ulp_test_cmd = LP_CORE_LP_UART_PRINT_TEST; +} + /* Test LP UART write operation with default LP UART initialization configuration */ TEST_CASE_MULTIPLE_DEVICES("LP-Core LP-UART write test - default config", "[lp_core][test_env=generic_multi_device][timeout=150]", test_lp_uart_write, hp_uart_read); /* Test LP UART write operation with updated LP UART initialization configuration */ @@ -527,3 +647,5 @@ TEST_CASE_MULTIPLE_DEVICES("LP-Core LP-UART read test - default config", "[lp_co TEST_CASE_MULTIPLE_DEVICES("LP-Core LP-UART read test - optional config", "[lp_core][test_env=generic_multi_device][timeout=150]", test_lp_uart_read_options, hp_uart_write_options); /* Test LP UART multi-byte read operation */ TEST_CASE_MULTIPLE_DEVICES("LP-Core LP-UART multi-byte read test", "[lp_core][test_env=generic_multi_device][timeout=150]", test_lp_uart_read_multi_byte, hp_uart_write); +/* Test LP Core print */ +TEST_CASE_MULTIPLE_DEVICES("LP-Core LP-UART print test", "[lp_core][test_env=generic_multi_device][timeout=150]", test_lp_uart_print, hp_uart_read_print);