diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index 4b19fb25c3e12..ef95b6b40a914 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -310,12 +310,19 @@ static inline enum uart_config_parity uart_stm32_ll2cfg_parity(uint32_t parity) } } -static inline uint32_t uart_stm32_cfg2ll_stopbits(enum uart_config_stop_bits sb) +static inline uint32_t uart_stm32_cfg2ll_stopbits(const struct uart_stm32_config *config, + enum uart_config_stop_bits sb) { switch (sb) { /* Some MCU's don't support 0.5 stop bits */ #ifdef LL_USART_STOPBITS_0_5 case UART_CFG_STOP_BITS_0_5: +#if HAS_LPUART_1 + if (IS_LPUART_INSTANCE(config->usart)) { + /* return the default */ + return LL_USART_STOPBITS_1; + } +#endif /* HAS_LPUART_1 */ return LL_USART_STOPBITS_0_5; #endif /* LL_USART_STOPBITS_0_5 */ case UART_CFG_STOP_BITS_1: @@ -323,6 +330,12 @@ static inline uint32_t uart_stm32_cfg2ll_stopbits(enum uart_config_stop_bits sb) /* Some MCU's don't support 1.5 stop bits */ #ifdef LL_USART_STOPBITS_1_5 case UART_CFG_STOP_BITS_1_5: +#if HAS_LPUART_1 + if (IS_LPUART_INSTANCE(config->usart)) { + /* return the default */ + return LL_USART_STOPBITS_2; + } +#endif return LL_USART_STOPBITS_1_5; #endif /* LL_USART_STOPBITS_1_5 */ case UART_CFG_STOP_BITS_2: @@ -455,7 +468,7 @@ static int uart_stm32_configure(const struct device *dev, const struct uart_stm32_config *config = dev->config; struct uart_stm32_data *data = dev->data; const uint32_t parity = uart_stm32_cfg2ll_parity(cfg->parity); - const uint32_t stopbits = uart_stm32_cfg2ll_stopbits(cfg->stop_bits); + const uint32_t stopbits = uart_stm32_cfg2ll_stopbits(config, cfg->stop_bits); const uint32_t databits = uart_stm32_cfg2ll_databits(cfg->data_bits, cfg->parity); const uint32_t flowctrl = uart_stm32_cfg2ll_hwctrl(cfg->flow_ctrl); @@ -475,35 +488,17 @@ static int uart_stm32_configure(const struct device *dev, return -ENOTSUP; } -#if defined(LL_USART_STOPBITS_0_5) && HAS_LPUART_1 - if (IS_LPUART_INSTANCE(config->usart) && - (cfg->stop_bits == UART_CFG_STOP_BITS_0_5)) { - return -ENOTSUP; - } -#else - if (cfg->stop_bits == UART_CFG_STOP_BITS_0_5) { - return -ENOTSUP; - } -#endif - -#if defined(LL_USART_STOPBITS_1_5) && HAS_LPUART_1 - if (IS_LPUART_INSTANCE(config->usart) && - (cfg->stop_bits == UART_CFG_STOP_BITS_1_5)) { - return -ENOTSUP; - } -#else - if (cfg->stop_bits == UART_CFG_STOP_BITS_1_5) { + /* When the transformed ll stop bits don't match with what was requested, then it's not + * supported + */ + if (uart_stm32_ll2cfg_stopbits(stopbits) != cfg->stop_bits) { return -ENOTSUP; } -#endif - /* Driver doesn't support 5 or 6 databits and potentially 7 or 9 */ - if ((cfg->data_bits == UART_CFG_DATA_BITS_5) || - (cfg->data_bits == UART_CFG_DATA_BITS_6) -#ifndef LL_USART_DATAWIDTH_7B - || (cfg->data_bits == UART_CFG_DATA_BITS_7) -#endif /* LL_USART_DATAWIDTH_7B */ - || (cfg->data_bits == UART_CFG_DATA_BITS_9)) { + /* When the transformed ll databits don't match with what was requested, then it's not + * supported + */ + if (uart_stm32_ll2cfg_databits(databits, parity) != cfg->data_bits) { return -ENOTSUP; } @@ -574,7 +569,11 @@ static int uart_stm32_config_get(const struct device *dev, } #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ -static int uart_stm32_poll_in(const struct device *dev, unsigned char *c) +typedef void (*poll_in_fn)( + const struct uart_stm32_config *config, + void *in); + +static int uart_stm32_poll_in_visitor(const struct device *dev, void *in, poll_in_fn get_fn) { const struct uart_stm32_config *config = dev->config; @@ -591,13 +590,15 @@ static int uart_stm32_poll_in(const struct device *dev, unsigned char *c) return -1; } - *c = (unsigned char)LL_USART_ReceiveData8(config->usart); + get_fn(config, in); return 0; } -static void uart_stm32_poll_out(const struct device *dev, - unsigned char c) +typedef void (*poll_out_fn)( + const struct uart_stm32_config *config, void *out); + +static void uart_stm32_poll_out_visitor(const struct device *dev, void *out, poll_out_fn set_fn) { const struct uart_stm32_config *config = dev->config; #ifdef CONFIG_PM @@ -640,10 +641,54 @@ static void uart_stm32_poll_out(const struct device *dev, } #endif /* CONFIG_PM */ - LL_USART_TransmitData8(config->usart, (uint8_t)c); + set_fn(config, out); irq_unlock(key); } +static void poll_in_u8(const struct uart_stm32_config *config, void *in) +{ + *((unsigned char *)in) = (unsigned char)LL_USART_ReceiveData8(config->usart); +} + +static void poll_out_u8(const struct uart_stm32_config *config, void *out) +{ + LL_USART_TransmitData8(config->usart, *((uint8_t *)out)); +} + +static int uart_stm32_poll_in(const struct device *dev, unsigned char *c) +{ + return uart_stm32_poll_in_visitor(dev, (void *)c, poll_in_u8); +} + +static void uart_stm32_poll_out(const struct device *dev, unsigned char c) +{ + uart_stm32_poll_out_visitor(dev, (void *)&c, poll_out_u8); +} + +#ifdef CONFIG_UART_WIDE_DATA + +static void poll_out_u9(const struct uart_stm32_config *config, void *out) +{ + LL_USART_TransmitData9(config->usart, *((uint16_t *)out)); +} + +static void poll_in_u9(const struct uart_stm32_config *config, void *in) +{ + *((uint16_t *)in) = LL_USART_ReceiveData9(config->usart); +} + +static int uart_stm32_poll_in_u16(const struct device *dev, uint16_t *in_u16) +{ + return uart_stm32_poll_in_visitor(dev, (void *)in_u16, poll_in_u9); +} + +static void uart_stm32_poll_out_u16(const struct device *dev, uint16_t out_u16) +{ + uart_stm32_poll_out_visitor(dev, (void *)&out_u16, poll_out_u9); +} + +#endif + static int uart_stm32_err_check(const struct device *dev) { const struct uart_stm32_config *config = dev->config; @@ -713,9 +758,11 @@ static inline void __uart_stm32_get_clock(const struct device *dev) #ifdef CONFIG_UART_INTERRUPT_DRIVEN -static int uart_stm32_fifo_fill(const struct device *dev, - const uint8_t *tx_data, - int size) +typedef void (*fifo_fill_fn)(const struct uart_stm32_config *config, const void *tx_data, + const uint8_t offset); + +static int uart_stm32_fifo_fill_visitor(const struct device *dev, const void *tx_data, int size, + fifo_fill_fn fill_fn) { const struct uart_stm32_config *config = dev->config; uint8_t num_tx = 0U; @@ -728,12 +775,12 @@ static int uart_stm32_fifo_fill(const struct device *dev, /* Lock interrupts to prevent nested interrupts or thread switch */ key = irq_lock(); - while ((size - num_tx > 0) && - LL_USART_IsActiveFlag_TXE(config->usart)) { + while ((size - num_tx > 0) && LL_USART_IsActiveFlag_TXE(config->usart)) { /* TXE flag will be cleared with byte write to DR|RDR register */ - /* Send a character (8bit , parity none) */ - LL_USART_TransmitData8(config->usart, tx_data[num_tx++]); + /* Send a character */ + fill_fn(config, tx_data, num_tx); + num_tx++; } irq_unlock(key); @@ -741,32 +788,111 @@ static int uart_stm32_fifo_fill(const struct device *dev, return num_tx; } -static int uart_stm32_fifo_read(const struct device *dev, uint8_t *rx_data, - const int size) +static void fifo_fill_with_u8(const struct uart_stm32_config *config, + const void *tx_data, const uint8_t offset) +{ + const uint8_t *data = (const uint8_t *)tx_data; + /* Send a character (8bit) */ + LL_USART_TransmitData8(config->usart, data[offset]); +} + +static int uart_stm32_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) +{ + if (uart_stm32_ll2cfg_databits(uart_stm32_get_databits(dev), uart_stm32_get_parity(dev)) == + UART_CFG_DATA_BITS_9) { + return -ENOTSUP; + } + return uart_stm32_fifo_fill_visitor(dev, (const void *)tx_data, size, + fifo_fill_with_u8); +} + +typedef void (*fifo_read_fn)(const struct uart_stm32_config *config, void *rx_data, + const uint8_t offset); + +static int uart_stm32_fifo_read_visitor(const struct device *dev, void *rx_data, const int size, + fifo_read_fn read_fn) { const struct uart_stm32_config *config = dev->config; uint8_t num_rx = 0U; - while ((size - num_rx > 0) && - LL_USART_IsActiveFlag_RXNE(config->usart)) { + while ((size - num_rx > 0) && LL_USART_IsActiveFlag_RXNE(config->usart)) { /* RXNE flag will be cleared upon read from DR|RDR register */ - /* Receive a character (8bit , parity none) */ - rx_data[num_rx++] = LL_USART_ReceiveData8(config->usart); + read_fn(config, rx_data, num_rx); + num_rx++; /* Clear overrun error flag */ if (LL_USART_IsActiveFlag_ORE(config->usart)) { LL_USART_ClearFlag_ORE(config->usart); - /* - * On stm32 F4X, F1X, and F2X, the RXNE flag is affected (cleared) by - * the uart_err_check function call (on errors flags clearing) - */ + /* + * On stm32 F4X, F1X, and F2X, the RXNE flag is affected (cleared) by + * the uart_err_check function call (on errors flags clearing) + */ } } return num_rx; } +static void fifo_read_with_u8(const struct uart_stm32_config *config, void *rx_data, + const uint8_t offset) +{ + uint8_t *data = (uint8_t *)rx_data; + + data[offset] = LL_USART_ReceiveData8(config->usart); +} + +static int uart_stm32_fifo_read(const struct device *dev, uint8_t *rx_data, const int size) +{ + if (uart_stm32_ll2cfg_databits(uart_stm32_get_databits(dev), uart_stm32_get_parity(dev)) == + UART_CFG_DATA_BITS_9) { + return -ENOTSUP; + } + return uart_stm32_fifo_read_visitor(dev, (void *)rx_data, size, + fifo_read_with_u8); +} + +#ifdef CONFIG_UART_WIDE_DATA + +static void fifo_fill_with_u16(const struct uart_stm32_config *config, + const void *tx_data, const uint8_t offset) +{ + const uint16_t *data = (const uint16_t *)tx_data; + + /* Send a character (9bit) */ + LL_USART_TransmitData9(config->usart, data[offset]); +} + +static int uart_stm32_fifo_fill_u16(const struct device *dev, const uint16_t *tx_data, int size) +{ + if (uart_stm32_ll2cfg_databits(uart_stm32_get_databits(dev), uart_stm32_get_parity(dev)) != + UART_CFG_DATA_BITS_9) { + return -ENOTSUP; + } + return uart_stm32_fifo_fill_visitor(dev, (const void *)tx_data, size, + fifo_fill_with_u16); +} + +static void fifo_read_with_u16(const struct uart_stm32_config *config, void *rx_data, + const uint8_t offset) +{ + uint16_t *data = (uint16_t *)rx_data; + + data[offset] = LL_USART_ReceiveData9(config->usart); +} + +static int uart_stm32_fifo_read_u16(const struct device *dev, uint16_t *rx_data, const int size) +{ + if (uart_stm32_ll2cfg_databits(uart_stm32_get_databits(dev), uart_stm32_get_parity(dev)) != + UART_CFG_DATA_BITS_9) { + return -ENOTSUP; + } + return uart_stm32_fifo_read_visitor(dev, (void *)rx_data, size, + fifo_read_with_u16); +} + +#endif + static void uart_stm32_irq_tx_enable(const struct device *dev) { const struct uart_stm32_config *config = dev->config; @@ -1609,11 +1735,36 @@ static int uart_stm32_async_init(const struct device *dev) return 0; } +#ifdef CONFIG_UART_WIDE_DATA + +static int uart_stm32_async_tx_u16(const struct device *dev, const uint16_t *tx_data, + size_t buf_size, int32_t timeout) +{ + return uart_stm32_async_tx(dev, (const uint8_t *)tx_data, buf_size * 2, timeout); +} + +static int uart_stm32_async_rx_enable_u16(const struct device *dev, uint16_t *buf, size_t len, + int32_t timeout) +{ + return uart_stm32_async_rx_enable(dev, (uint8_t *)buf, len * 2, timeout); +} + +static int uart_stm32_async_rx_buf_rsp_u16(const struct device *dev, uint16_t *buf, size_t len) +{ + return uart_stm32_async_rx_buf_rsp(dev, (uint8_t *)buf, len * 2); +} + +#endif + #endif /* CONFIG_UART_ASYNC_API */ static const struct uart_driver_api uart_stm32_driver_api = { .poll_in = uart_stm32_poll_in, .poll_out = uart_stm32_poll_out, +#ifdef CONFIG_UART_WIDE_DATA + .poll_in_u16 = uart_stm32_poll_in_u16, + .poll_out_u16 = uart_stm32_poll_out_u16, +#endif .err_check = uart_stm32_err_check, #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE .configure = uart_stm32_configure, @@ -1622,6 +1773,10 @@ static const struct uart_driver_api uart_stm32_driver_api = { #ifdef CONFIG_UART_INTERRUPT_DRIVEN .fifo_fill = uart_stm32_fifo_fill, .fifo_read = uart_stm32_fifo_read, +#ifdef CONFIG_UART_WIDE_DATA + .fifo_fill_u16 = uart_stm32_fifo_fill_u16, + .fifo_read_u16 = uart_stm32_fifo_read_u16, +#endif .irq_tx_enable = uart_stm32_irq_tx_enable, .irq_tx_disable = uart_stm32_irq_tx_disable, .irq_tx_ready = uart_stm32_irq_tx_ready, @@ -1634,7 +1789,7 @@ static const struct uart_driver_api uart_stm32_driver_api = { .irq_is_pending = uart_stm32_irq_is_pending, .irq_update = uart_stm32_irq_update, .irq_callback_set = uart_stm32_irq_callback_set, -#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ #ifdef CONFIG_UART_ASYNC_API .callback_set = uart_stm32_async_callback_set, .tx = uart_stm32_async_tx, @@ -1642,7 +1797,12 @@ static const struct uart_driver_api uart_stm32_driver_api = { .rx_enable = uart_stm32_async_rx_enable, .rx_disable = uart_stm32_async_rx_disable, .rx_buf_rsp = uart_stm32_async_rx_buf_rsp, -#endif /* CONFIG_UART_ASYNC_API */ +#ifdef CONFIG_UART_WIDE_DATA + .tx_u16 = uart_stm32_async_tx_u16, + .rx_enable_u16 = uart_stm32_async_rx_enable_u16, + .rx_buf_rsp_u16 = uart_stm32_async_rx_buf_rsp_u16, +#endif +#endif /* CONFIG_UART_ASYNC_API */ }; /** diff --git a/tests/drivers/uart/uart_async_api/CMakeLists.txt b/tests/drivers/uart/uart_async_api/CMakeLists.txt index d8166ba6136a1..cc8d51c851fa4 100644 --- a/tests/drivers/uart/uart_async_api/CMakeLists.txt +++ b/tests/drivers/uart/uart_async_api/CMakeLists.txt @@ -8,3 +8,4 @@ project(uart_high_level_api) target_sources(app PRIVATE src/test_uart_async.c ) +target_sources_ifdef(CONFIG_UART_WIDE_DATA app PRIVATE src/test_uart_wide.c) diff --git a/tests/drivers/uart/uart_async_api/src/test_uart_async.c b/tests/drivers/uart/uart_async_api/src/test_uart_async.c index 1cb7c351deaf4..af3a63b197dca 100644 --- a/tests/drivers/uart/uart_async_api/src/test_uart_async.c +++ b/tests/drivers/uart/uart_async_api/src/test_uart_async.c @@ -14,7 +14,7 @@ K_SEM_DEFINE(rx_buf_released, 0, 1); K_SEM_DEFINE(rx_disabled, 0, 1); ZTEST_BMEM volatile bool failed_in_isr; -ZTEST_BMEM static const struct device *const uart_dev = +static ZTEST_BMEM const struct device *const uart_dev = DEVICE_DT_GET(UART_NODE); static void read_abort_timeout(struct k_timer *timer); @@ -24,6 +24,13 @@ K_TIMER_DEFINE(read_abort_timer, read_abort_timeout, NULL); static void init_test(void) { __ASSERT_NO_MSG(device_is_ready(uart_dev)); + uart_rx_disable(uart_dev); + uart_tx_abort(uart_dev); + k_sem_reset(&tx_done); + k_sem_reset(&tx_aborted); + k_sem_reset(&rx_rdy); + k_sem_reset(&rx_buf_released); + k_sem_reset(&rx_disabled); } #ifdef CONFIG_USERSPACE @@ -39,6 +46,9 @@ static void uart_async_test_init(void) { static bool initialized; + __ASSERT_NO_MSG(device_is_ready(uart_dev)); + uart_rx_disable(uart_dev); + uart_tx_abort(uart_dev); k_sem_reset(&tx_done); k_sem_reset(&tx_aborted); k_sem_reset(&rx_rdy); @@ -46,14 +56,25 @@ static void uart_async_test_init(void) k_sem_reset(&rx_buf_released); k_sem_reset(&rx_disabled); +#ifdef CONFIG_UART_WIDE_DATA + const struct uart_config uart_cfg = { + .baudrate = 115200, + .parity = UART_CFG_PARITY_NONE, + .stop_bits = UART_CFG_STOP_BITS_1, + .data_bits = UART_CFG_DATA_BITS_9, + .flow_ctrl = UART_CFG_FLOW_CTRL_NONE + }; + __ASSERT_NO_MSG(uart_configure(uart_dev, &uart_cfg) == 0); +#endif + if (!initialized) { init_test(); initialized = true; - #ifdef CONFIG_USERSPACE set_permissions(); #endif } + } struct test_data { @@ -99,7 +120,6 @@ static void test_single_read_callback(const struct device *dev, default: break; } - } ZTEST_BMEM volatile uint32_t tx_aborted_count; @@ -122,7 +142,7 @@ ZTEST_USER(uart_async_single_read, test_single_read) uint8_t rx_buf[10] = {0}; /* Check also if sending from read only memory (e.g. flash) works. */ - static const uint8_t tx_buf[5] = "test"; + static const uint8_t tx_buf[5] = "test\0"; zassert_not_equal(memcmp(tx_buf, rx_buf, 5), 0, "Initial buffer check failed"); diff --git a/tests/drivers/uart/uart_async_api/src/test_uart_wide.c b/tests/drivers/uart/uart_async_api/src/test_uart_wide.c new file mode 100644 index 0000000000000..1540978d8eb0f --- /dev/null +++ b/tests/drivers/uart/uart_async_api/src/test_uart_wide.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2023 Jeroen van Dooren + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "test_uart.h" + +K_SEM_DEFINE(tx_wide_done, 0, 1); +K_SEM_DEFINE(tx_wide_aborted, 0, 1); +K_SEM_DEFINE(rx_wide_rdy, 0, 1); +K_SEM_DEFINE(rx_wide_buf_released, 0, 1); +K_SEM_DEFINE(rx_wide_disabled, 0, 1); + +static ZTEST_BMEM const struct device *const uart_dev = + DEVICE_DT_GET(UART_NODE); + +static void init_test(void) +{ + __ASSERT_NO_MSG(device_is_ready(uart_dev)); + uart_rx_disable(uart_dev); + uart_tx_abort(uart_dev); + k_sem_reset(&tx_wide_done); + k_sem_reset(&tx_wide_aborted); + k_sem_reset(&rx_wide_rdy); + k_sem_reset(&rx_wide_buf_released); + k_sem_reset(&rx_wide_disabled); +} + +#ifdef CONFIG_USERSPACE +static void set_permissions(void) +{ + k_thread_access_grant(k_current_get(), &tx_wide_done, &tx_wide_aborted, + &rx_wide_rdy, &rx_wide_buf_released, &rx_wide_disabled, + uart_dev); +} +#endif + +static void uart_async_test_init(void) +{ + init_test(); + +#ifdef CONFIG_USERSPACE + set_permissions(); +#endif +} + +static void test_single_read_callback(const struct device *dev, + struct uart_event *evt, void *user_data) +{ + ARG_UNUSED(dev); + + switch (evt->type) { + case UART_TX_DONE: + k_sem_give(&tx_wide_done); + break; + case UART_TX_ABORTED: + (*(uint32_t *)user_data)++; + break; + case UART_RX_RDY: + k_sem_give(&rx_wide_rdy); + break; + case UART_RX_BUF_RELEASED: + k_sem_give(&rx_wide_buf_released); + break; + case UART_RX_DISABLED: + k_sem_give(&rx_wide_disabled); + break; + default: + break; + } +} + +ZTEST_BMEM volatile uint32_t tx_wide_aborted_count; + +static void *single_read_setup_wide(void) +{ + uart_async_test_init(); + + uart_callback_set(uart_dev, + test_single_read_callback, + (void *) &tx_wide_aborted_count); + + return NULL; +} + +ZTEST_USER(uart_async_single_read_wide, test_single_read_wide) +{ + uint16_t rx_buf[10] = {0}; + + /* Check also if sending from read only memory (e.g. flash) works. */ + static const uint16_t tx_buf[5] = {0x74, 0x65, 0x73, 0x74, 0x0D}; + + zassert_not_equal(memcmp(tx_buf, rx_buf, 5), 0, + "Initial buffer check failed"); + + uart_rx_enable_u16(uart_dev, rx_buf, 10, 50 * USEC_PER_MSEC); + zassert_equal(k_sem_take(&rx_wide_rdy, K_MSEC(100)), -EAGAIN, + "RX_RDY not expected at this point"); + + uart_tx_u16(uart_dev, tx_buf, sizeof(tx_buf)/sizeof(uint16_t), 100 * USEC_PER_MSEC); + zassert_equal(k_sem_take(&tx_wide_done, K_MSEC(100)), 0, "TX_DONE timeout"); + zassert_equal(k_sem_take(&rx_wide_rdy, K_MSEC(100)), 0, "RX_RDY timeout"); + zassert_equal(k_sem_take(&rx_wide_rdy, K_MSEC(100)), -EAGAIN, + "Extra RX_RDY received"); + + zassert_equal(memcmp(tx_buf, rx_buf, 5), 0, "Buffers not equal"); + zassert_not_equal(memcmp(tx_buf, rx_buf+5, 5), 0, "Buffers not equal"); + + uart_tx_u16(uart_dev, tx_buf, sizeof(tx_buf)/sizeof(uint16_t), 100 * USEC_PER_MSEC); + zassert_equal(k_sem_take(&tx_wide_done, K_MSEC(100)), 0, "TX_DONE timeout"); + zassert_equal(k_sem_take(&rx_wide_rdy, K_MSEC(100)), 0, "RX_RDY timeout"); + zassert_equal(k_sem_take(&rx_wide_buf_released, K_MSEC(100)), + 0, + "RX_BUF_RELEASED timeout"); + zassert_equal(k_sem_take(&rx_wide_disabled, K_MSEC(1000)), 0, + "RX_DISABLED timeout"); + zassert_equal(k_sem_take(&rx_wide_rdy, K_MSEC(100)), -EAGAIN, + "Extra RX_RDY received"); + + zassert_equal(memcmp(tx_buf, rx_buf+5, 5), 0, "Buffers not equal"); + zassert_equal(tx_wide_aborted_count, 0, "TX aborted triggered"); +} + +ZTEST_SUITE(uart_async_single_read_wide, NULL, single_read_setup_wide, + NULL, NULL, NULL); diff --git a/tests/drivers/uart/uart_async_api/testcase.yaml b/tests/drivers/uart/uart_async_api/testcase.yaml index 324c9a9083189..bd8e3dfce71b1 100644 --- a/tests/drivers/uart/uart_async_api/testcase.yaml +++ b/tests/drivers/uart/uart_async_api/testcase.yaml @@ -31,6 +31,18 @@ tests: harness_config: fixture: gpio_loopback depends_on: gpio + drivers.uart.wide: + filter: CONFIG_UART_CONSOLE and CONFIG_SERIAL_SUPPORT_ASYNC and not CONFIG_UART_MCUX_LPUART + harness: ztest + harness_config: + fixture: gpio_loopback + depends_on: gpio + extra_configs: + - CONFIG_UART_WIDE_DATA=y + arch_allow: arm + platform_allow: nucleo_h743zi + integration_platforms: + - nucleo_h743zi drivers.uart.async_api.nrf_uart: filter: CONFIG_UART_CONSOLE and CONFIG_SERIAL_SUPPORT_ASYNC harness: ztest diff --git a/tests/drivers/uart/uart_basic_api/CMakeLists.txt b/tests/drivers/uart/uart_basic_api/CMakeLists.txt index 79b6260d8e984..6dc07cc9c06b8 100644 --- a/tests/drivers/uart/uart_basic_api/CMakeLists.txt +++ b/tests/drivers/uart/uart_basic_api/CMakeLists.txt @@ -11,3 +11,4 @@ target_sources(app PRIVATE ) target_sources_ifdef(CONFIG_UART_INTERRUPT_DRIVEN app PRIVATE src/test_uart_fifo.c) target_sources_ifdef(CONFIG_UART_INTERRUPT_DRIVEN app PRIVATE src/test_uart_pending.c) +target_sources_ifdef(CONFIG_UART_WIDE_DATA app PRIVATE src/test_uart_config_wide.c) diff --git a/tests/drivers/uart/uart_basic_api/boards/nucleo_h743zi.overlay b/tests/drivers/uart/uart_basic_api/boards/nucleo_h743zi.overlay new file mode 100644 index 0000000000000..64cddf91b85a7 --- /dev/null +++ b/tests/drivers/uart/uart_basic_api/boards/nucleo_h743zi.overlay @@ -0,0 +1,10 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + */ + +dut: &usart2 { + pinctrl-0 = <&usart2_tx_pd5 &usart2_rx_pd6>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; diff --git a/tests/drivers/uart/uart_basic_api/src/test_uart.h b/tests/drivers/uart/uart_basic_api/src/test_uart.h index 2d2377d47be9a..2a17f397cd0ac 100644 --- a/tests/drivers/uart/uart_basic_api/src/test_uart.h +++ b/tests/drivers/uart/uart_basic_api/src/test_uart.h @@ -23,11 +23,16 @@ void test_uart_configure(void); void test_uart_config_get(void); void test_uart_poll_out(void); void test_uart_poll_in(void); +#if CONFIG_UART_WIDE_DATA +void test_uart_configure_wide(void); +void test_uart_config_get_wide(void); +#endif #if CONFIG_UART_INTERRUPT_DRIVEN void test_uart_fifo_fill(void); void test_uart_fifo_read(void); void test_uart_pending(void); #endif + #endif #endif /* __TEST_UART_H__ */ diff --git a/tests/drivers/uart/uart_basic_api/src/test_uart_config.c b/tests/drivers/uart/uart_basic_api/src/test_uart_config.c index 0e5216a115d45..d2a9836ad46e4 100644 --- a/tests/drivers/uart/uart_basic_api/src/test_uart_config.c +++ b/tests/drivers/uart/uart_basic_api/src/test_uart_config.c @@ -25,7 +25,6 @@ */ #include "test_uart.h" -struct uart_config uart_cfg_check; const struct uart_config uart_cfg = { .baudrate = 115200, .parity = UART_CFG_PARITY_NONE, @@ -58,6 +57,7 @@ static int test_configure(void) /* test UART configure get (retrieve configuration) */ static int test_config_get(void) { + struct uart_config uart_cfg_check; const struct device *const uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); if (!device_is_ready(uart_dev)) { diff --git a/tests/drivers/uart/uart_basic_api/src/test_uart_config_wide.c b/tests/drivers/uart/uart_basic_api/src/test_uart_config_wide.c new file mode 100644 index 0000000000000..9e880f95fa7aa --- /dev/null +++ b/tests/drivers/uart/uart_basic_api/src/test_uart_config_wide.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2023 Jeroen van Dooren + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * @addtogroup t_uart_basic + * @{ + * @defgroup t_uart_config test_uart_config_wide + * @brief TestPurpose: verify UART configure API settings for wide data support + * @details + * - Test Steps + * - Configure: test_uart_configure_wide( ) + * - Configure Get: test_uart_config_get_wide( ) + * - Expected Results + * -# When test UART CONFIG Configure, the value of configurations actually + * set will be equal to the original configuration values (from device + * tree or run-time configuration to modify those loaded initially from + * device tree) + * -# When test UART CONFIG Configure Get, the app will get/retrieve the + * value of configurations stored at location and to be passed to UART + * CONFIG Configure + * @} + */ + +#include "test_uart.h" +const struct uart_config uart_cfg_wide = { + .baudrate = 115200, + .parity = UART_CFG_PARITY_NONE, + .stop_bits = UART_CFG_STOP_BITS_1, + .data_bits = UART_CFG_DATA_BITS_9, + .flow_ctrl = UART_CFG_FLOW_CTRL_NONE + }; + +static int test_configure_wide(void) +{ + const struct device *const uart_dev = DEVICE_DT_GET(DT_NODELABEL(dut)); + + if (!device_is_ready(uart_dev)) { + TC_PRINT("UART device not ready\n"); + return TC_FAIL; + } + + /* Verify configure() - set device configuration using data in cfg */ + int ret = uart_configure(uart_dev, &uart_cfg_wide); + + if (ret == -ENOSYS) { + return TC_SKIP; + } + + /* 0 if successful, - error code otherwise */ + return (ret == 0) ? TC_PASS : TC_FAIL; + +} + +/* test UART configure get (retrieve configuration) */ +static int test_config_get_wide(void) +{ + struct uart_config uart_cfg_check; + const struct device *const uart_dev = DEVICE_DT_GET(DT_NODELABEL(dut)); + + if (!device_is_ready(uart_dev)) { + TC_PRINT("UART device not ready\n"); + return TC_FAIL; + } + + TC_PRINT("This is a configure_get_wide test.\n"); + + /* Verify configure() - set device configuration using data in cfg */ + /* 0 if successful, - error code otherwise */ + int ret = uart_configure(uart_dev, &uart_cfg_wide); + + if (ret == -ENOSYS) { + return TC_SKIP; + } + + zassert_true(ret == 0, "set config error"); + + /* Verify config_get() - get device configuration, put in cfg */ + /* 0 if successful, - error code otherwise */ + /* so get the configurations from the device and check */ + ret = uart_config_get(uart_dev, &uart_cfg_check); + zassert_true(ret == 0, "get config error"); + + /* Confirm the values from device are the values put in cfg*/ + if (memcmp(&uart_cfg_wide, &uart_cfg_check, sizeof(uart_cfg_wide)) != 0) { + return TC_FAIL; + } else { + return TC_PASS; + } +} + +#if CONFIG_SHELL +void test_uart_configure_wide(void) +#else +ZTEST(uart_basic_api, test_uart_configure_wide) +#endif +{ + int ret = test_configure_wide(); + + zassert_true((ret == TC_PASS) || (ret == TC_SKIP)); +} + +#if CONFIG_SHELL +void test_uart_config_get_wide(void) +#else +ZTEST(uart_basic_api, test_uart_config_get_wide) +#endif +{ + int ret = test_config_get_wide(); + + zassert_true((ret == TC_PASS) || (ret == TC_SKIP)); +} diff --git a/tests/drivers/uart/uart_basic_api/testcase.yaml b/tests/drivers/uart/uart_basic_api/testcase.yaml index 9394b902559da..17f0b5a798670 100644 --- a/tests/drivers/uart/uart_basic_api/testcase.yaml +++ b/tests/drivers/uart/uart_basic_api/testcase.yaml @@ -7,6 +7,16 @@ tests: harness: keyboard integration_platforms: - mps2_an385 + drivers.uart.basic_api.wide: + extra_configs: + - CONFIG_UART_WIDE_DATA=y + tags: drivers uart + filter: CONFIG_UART_CONSOLE + arch_allow: arm + platform_allow: nucleo_h743zi + integration_platforms: + - nucleo_h743zi + extra_args: DTC_OVERLAY_FILE="boards/nucleo_h743zi.overlay" drivers.uart.basic_api.poll: extra_args: CONF_FILE=prj_poll.conf tags: