blob: 26c8de398978bce6b34ba2f0832de2ad27aeef45 [file] [log] [blame]
/*
* Copyright (c) 2019 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "test_uart.h"
K_SEM_DEFINE(tx_done, 0, 1);
K_SEM_DEFINE(tx_aborted, 0, 1);
K_SEM_DEFINE(rx_rdy, 0, 1);
K_SEM_DEFINE(rx_buf_coherency, 0, 255);
K_SEM_DEFINE(rx_buf_released, 0, 1);
K_SEM_DEFINE(rx_disabled, 0, 1);
ZTEST_BMEM volatile bool failed_in_isr;
static ZTEST_BMEM const struct device *const uart_dev =
DEVICE_DT_GET(UART_NODE);
static void read_abort_timeout(struct k_timer *timer);
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
static void set_permissions(void)
{
k_thread_access_grant(k_current_get(), &tx_done, &tx_aborted,
&rx_rdy, &rx_buf_coherency, &rx_buf_released,
&rx_disabled, uart_dev, &read_abort_timer);
}
#endif
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);
k_sem_reset(&rx_buf_coherency);
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 {
volatile uint32_t tx_aborted_count;
uint8_t rx_first_buffer[10];
uint32_t recv_bytes_first_buffer;
uint8_t rx_second_buffer[5];
uint32_t recv_bytes_second_buffer;
bool supply_second_buffer;
};
ZTEST_BMEM struct test_data tdata;
static void test_single_read_callback(const struct device *dev,
struct uart_event *evt, void *user_data)
{
ARG_UNUSED(dev);
struct test_data *data = (struct test_data *)user_data;
switch (evt->type) {
case UART_TX_DONE:
k_sem_give(&tx_done);
break;
case UART_TX_ABORTED:
data->tx_aborted_count++;
break;
case UART_RX_RDY:
if ((uintptr_t)evt->data.rx.buf < (uintptr_t)tdata.rx_second_buffer) {
data->recv_bytes_first_buffer += evt->data.rx.len;
} else {
data->recv_bytes_second_buffer += evt->data.rx.len;
}
k_sem_give(&rx_rdy);
break;
case UART_RX_BUF_RELEASED:
k_sem_give(&rx_buf_released);
break;
case UART_RX_BUF_REQUEST:
if (data->supply_second_buffer) {
/* Reply to one buffer request. */
uart_rx_buf_rsp(dev, data->rx_second_buffer,
sizeof(data->rx_second_buffer));
data->supply_second_buffer = false;
}
break;
case UART_RX_DISABLED:
k_sem_give(&rx_disabled);
break;
default:
break;
}
}
ZTEST_BMEM volatile uint32_t tx_aborted_count;
static void *single_read_setup(void)
{
uart_async_test_init();
memset(&tdata, 0, sizeof(tdata));
tdata.supply_second_buffer = true;
uart_callback_set(uart_dev,
test_single_read_callback,
(void *) &tdata);
return NULL;
}
static void tdata_check_recv_buffers(const uint8_t *tx_buf, uint32_t sent_bytes)
{
uint32_t recv_bytes_total;
recv_bytes_total = tdata.recv_bytes_first_buffer + tdata.recv_bytes_second_buffer;
zassert_equal(recv_bytes_total, sent_bytes, "Incorrect number of bytes received");
zassert_equal(memcmp(tx_buf, tdata.rx_first_buffer, tdata.recv_bytes_first_buffer), 0,
"Invalid data received in first buffer");
zassert_equal(memcmp(tx_buf + tdata.recv_bytes_first_buffer, tdata.rx_second_buffer,
tdata.recv_bytes_second_buffer),
0, "Invalid data received in second buffer");
/* check that the remaining bytes in the buffers are zero */
for (int i = tdata.recv_bytes_first_buffer; i < sizeof(tdata.rx_first_buffer); i++) {
zassert_equal(tdata.rx_first_buffer[i], 0,
"Received extra data to the first buffer");
}
for (int i = tdata.recv_bytes_second_buffer; i < sizeof(tdata.rx_second_buffer); i++) {
zassert_equal(tdata.rx_second_buffer[i], 0,
"Received extra data to the second buffer");
}
}
ZTEST_USER(uart_async_single_read, test_single_read)
{
/* Check also if sending from read only memory (e.g. flash) works. */
static const uint8_t tx_buf[] = "0123456789";
uint32_t sent_bytes = 0;
zassert_not_equal(memcmp(tx_buf, tdata.rx_first_buffer, 5), 0,
"Initial buffer check failed");
uart_rx_enable(uart_dev, tdata.rx_first_buffer, 10, 50 * USEC_PER_MSEC);
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN,
"RX_RDY not expected at this point");
uart_tx(uart_dev, tx_buf, 5, 100 * USEC_PER_MSEC);
sent_bytes += 5;
zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), 0, "RX_RDY timeout");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN,
"Extra RX_RDY received");
tdata_check_recv_buffers(tx_buf, sent_bytes);
uart_tx(uart_dev, tx_buf + sent_bytes, 5, 100 * USEC_PER_MSEC);
sent_bytes += 5;
zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), 0, "RX_RDY timeout");
zassert_equal(k_sem_take(&rx_buf_released, K_MSEC(100)),
0,
"RX_BUF_RELEASED timeout");
uart_rx_disable(uart_dev);
zassert_equal(k_sem_take(&rx_disabled, K_MSEC(1000)), 0,
"RX_DISABLED timeout");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN,
"Extra RX_RDY received");
tdata_check_recv_buffers(tx_buf, sent_bytes);
zassert_equal(tdata.tx_aborted_count, 0, "TX aborted triggered");
}
static void *multiple_rx_enable_setup(void)
{
uart_async_test_init();
memset(&tdata, 0, sizeof(tdata));
/* Reuse the callback from the single_read test case, as this test case
* does not need anything extra in this regard.
*/
uart_callback_set(uart_dev,
test_single_read_callback,
(void *)&tdata);
return NULL;
}
ZTEST_USER(uart_async_multi_rx, test_multiple_rx_enable)
{
/* Check also if sending from read only memory (e.g. flash) works. */
static const uint8_t tx_buf[] = "test";
const uint32_t rx_buf_size = sizeof(tx_buf);
int ret;
BUILD_ASSERT(sizeof(tx_buf) <= sizeof(tdata.rx_first_buffer), "Invalid buf size");
/* Enable RX without a timeout. */
ret = uart_rx_enable(uart_dev, tdata.rx_first_buffer, rx_buf_size, SYS_FOREVER_US);
zassert_equal(ret, 0, "uart_rx_enable failed");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN,
"RX_RDY not expected at this point");
zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), -EAGAIN,
"RX_DISABLED not expected at this point");
/* Disable RX before any data has been received. */
ret = uart_rx_disable(uart_dev);
zassert_equal(ret, 0, "uart_rx_disable failed");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN,
"RX_RDY not expected at this point");
zassert_equal(k_sem_take(&rx_buf_released, K_MSEC(100)), 0,
"RX_BUF_RELEASED timeout");
zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), 0,
"RX_DISABLED timeout");
k_sem_reset(&rx_buf_released);
k_sem_reset(&rx_disabled);
/* Check that RX can be reenabled after "manual" disabling. */
ret = uart_rx_enable(uart_dev, tdata.rx_first_buffer, rx_buf_size,
50 * USEC_PER_MSEC);
zassert_equal(ret, 0, "uart_rx_enable failed");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN,
"RX_RDY not expected at this point");
/* Send enough data to completely fill RX buffer, so that RX ends. */
ret = uart_tx(uart_dev, tx_buf, sizeof(tx_buf), 100 * USEC_PER_MSEC);
zassert_equal(ret, 0, "uart_tx failed");
zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), 0, "RX_RDY timeout");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN,
"Extra RX_RDY received");
zassert_equal(k_sem_take(&rx_buf_released, K_MSEC(100)), 0,
"RX_BUF_RELEASED timeout");
zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), 0,
"RX_DISABLED timeout");
zassert_equal(tx_aborted_count, 0, "Unexpected TX abort");
tdata_check_recv_buffers(tx_buf, sizeof(tx_buf));
k_sem_reset(&rx_rdy);
k_sem_reset(&rx_buf_released);
k_sem_reset(&rx_disabled);
k_sem_reset(&tx_done);
memset(&tdata, 0, sizeof(tdata));
/* Check that RX can be reenabled after automatic disabling. */
ret = uart_rx_enable(uart_dev, tdata.rx_first_buffer, rx_buf_size,
50 * USEC_PER_MSEC);
zassert_equal(ret, 0, "uart_rx_enable failed");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN,
"RX_RDY not expected at this point");
/* Fill RX buffer again to confirm that RX still works properly. */
ret = uart_tx(uart_dev, tx_buf, sizeof(tx_buf), 100 * USEC_PER_MSEC);
zassert_equal(ret, 0, "uart_tx failed");
zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), 0, "RX_RDY timeout");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), -EAGAIN,
"Extra RX_RDY received");
zassert_equal(k_sem_take(&rx_buf_released, K_MSEC(100)), 0,
"RX_BUF_RELEASED timeout");
zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), 0,
"RX_DISABLED timeout");
zassert_equal(tx_aborted_count, 0, "Unexpected TX abort");
tdata_check_recv_buffers(tx_buf, sizeof(tx_buf));
}
ZTEST_BMEM uint8_t chained_read_buf[2][8];
ZTEST_BMEM uint8_t chained_cpy_buf[10];
ZTEST_BMEM volatile uint8_t rx_data_idx;
ZTEST_BMEM uint8_t rx_buf_idx;
ZTEST_BMEM uint8_t *read_ptr;
static void test_chained_read_callback(const struct device *dev,
struct uart_event *evt, void *user_data)
{
int err;
switch (evt->type) {
case UART_TX_DONE:
k_sem_give(&tx_done);
break;
case UART_RX_RDY:
zassert_true(rx_data_idx + evt->data.rx.len <= sizeof(chained_cpy_buf));
memcpy(&chained_cpy_buf[rx_data_idx],
&evt->data.rx.buf[evt->data.rx.offset],
evt->data.rx.len);
rx_data_idx += evt->data.rx.len;
break;
case UART_RX_BUF_REQUEST:
err = uart_rx_buf_rsp(dev,
chained_read_buf[rx_buf_idx],
sizeof(chained_read_buf[0]));
zassert_equal(err, 0);
rx_buf_idx = !rx_buf_idx ? 1 : 0;
break;
case UART_RX_DISABLED:
k_sem_give(&rx_disabled);
break;
default:
break;
}
}
static void *chained_read_setup(void)
{
uart_async_test_init();
uart_callback_set(uart_dev, test_chained_read_callback, NULL);
return NULL;
}
ZTEST_USER(uart_async_chain_read, test_chained_read)
{
uint8_t tx_buf[10];
int iter = 6;
uint32_t rx_timeout_ms = 50;
int err;
err = uart_rx_enable(uart_dev,
chained_read_buf[rx_buf_idx++],
sizeof(chained_read_buf[0]),
rx_timeout_ms * USEC_PER_MSEC);
zassert_equal(err, 0);
for (int i = 0; i < iter; i++) {
zassert_not_equal(k_sem_take(&rx_disabled, K_MSEC(10)),
0,
"RX_DISABLED occurred");
snprintf(tx_buf, sizeof(tx_buf), "Message %d", i);
uart_tx(uart_dev, tx_buf, sizeof(tx_buf), 100 * USEC_PER_MSEC);
zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0,
"TX_DONE timeout");
k_msleep(rx_timeout_ms + 10);
zassert_equal(rx_data_idx, sizeof(tx_buf),
"Unexpected amount of data received %d exp:%d",
rx_data_idx, sizeof(tx_buf));
zassert_equal(memcmp(tx_buf, chained_cpy_buf, sizeof(tx_buf)), 0,
"Buffers not equal");
rx_data_idx = 0;
}
uart_rx_disable(uart_dev);
zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), 0,
"RX_DISABLED timeout");
}
ZTEST_BMEM uint8_t double_buffer[2][12];
ZTEST_DMEM uint8_t *next_buf = double_buffer[1];
static void test_double_buffer_callback(const struct device *dev,
struct uart_event *evt, void *user_data)
{
switch (evt->type) {
case UART_TX_DONE:
k_sem_give(&tx_done);
break;
case UART_RX_RDY:
read_ptr = evt->data.rx.buf + evt->data.rx.offset;
k_sem_give(&rx_rdy);
break;
case UART_RX_BUF_REQUEST:
uart_rx_buf_rsp(dev, next_buf, sizeof(double_buffer[0]));
break;
case UART_RX_BUF_RELEASED:
next_buf = evt->data.rx_buf.buf;
k_sem_give(&rx_buf_released);
break;
case UART_RX_DISABLED:
k_sem_give(&rx_disabled);
break;
default:
break;
}
}
static void *double_buffer_setup(void)
{
uart_async_test_init();
uart_callback_set(uart_dev, test_double_buffer_callback, NULL);
return NULL;
}
ZTEST_USER(uart_async_double_buf, test_double_buffer)
{
uint8_t tx_buf[4];
zassert_equal(uart_rx_enable(uart_dev,
double_buffer[0],
sizeof(double_buffer[0]),
50 * USEC_PER_MSEC),
0,
"Failed to enable receiving");
for (int i = 0; i < 100; i++) {
snprintf(tx_buf, sizeof(tx_buf), "%03d", i);
uart_tx(uart_dev, tx_buf, sizeof(tx_buf), 100 * USEC_PER_MSEC);
zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0,
"TX_DONE timeout");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), 0,
"RX_RDY timeout");
zassert_equal(memcmp(tx_buf, read_ptr, sizeof(tx_buf)),
0,
"Buffers not equal");
}
uart_rx_disable(uart_dev);
zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), 0,
"RX_DISABLED timeout");
}
ZTEST_BMEM uint8_t test_read_abort_rx_buf[2][100];
ZTEST_BMEM uint8_t test_read_abort_read_buf[100];
ZTEST_BMEM int test_read_abort_rx_cnt;
static void test_read_abort_callback(const struct device *dev,
struct uart_event *evt, void *user_data)
{
int err;
ARG_UNUSED(dev);
switch (evt->type) {
case UART_TX_DONE:
k_sem_give(&tx_done);
break;
case UART_RX_BUF_REQUEST:
{
static bool once;
if (!once) {
k_sem_give(&rx_buf_coherency);
uart_rx_buf_rsp(dev,
test_read_abort_rx_buf[1],
sizeof(test_read_abort_rx_buf[1]));
once = true;
}
break;
}
case UART_RX_RDY:
memcpy(&test_read_abort_read_buf[test_read_abort_rx_cnt],
&evt->data.rx.buf[evt->data.rx.offset],
evt->data.rx.len);
test_read_abort_rx_cnt += evt->data.rx.len;
k_sem_give(&rx_rdy);
break;
case UART_RX_BUF_RELEASED:
k_sem_give(&rx_buf_released);
err = k_sem_take(&rx_buf_coherency, K_NO_WAIT);
failed_in_isr |= (err < 0);
break;
case UART_RX_DISABLED:
err = k_sem_take(&rx_buf_released, K_NO_WAIT);
failed_in_isr |= (err < 0);
k_sem_give(&rx_disabled);
break;
default:
break;
}
}
static void read_abort_timeout(struct k_timer *timer)
{
int err;
err = uart_rx_disable(uart_dev);
zassert_equal(err, 0, "Unexpected err:%d", err);
}
static void *read_abort_setup(void)
{
uart_async_test_init();
failed_in_isr = false;
uart_callback_set(uart_dev, test_read_abort_callback, NULL);
return NULL;
}
ZTEST_USER(uart_async_read_abort, test_read_abort)
{
uint8_t rx_buf[100];
uint8_t tx_buf[100];
memset(rx_buf, 0, sizeof(rx_buf));
memset(tx_buf, 1, sizeof(tx_buf));
uart_rx_enable(uart_dev, rx_buf, sizeof(rx_buf), 50 * USEC_PER_MSEC);
k_sem_give(&rx_buf_coherency);
uart_tx(uart_dev, tx_buf, 5, 100 * USEC_PER_MSEC);
zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), 0, "RX_RDY timeout");
zassert_equal(memcmp(tx_buf, rx_buf, 5), 0, "Buffers not equal");
uart_tx(uart_dev, tx_buf, 95, 100 * USEC_PER_MSEC);
k_timer_start(&read_abort_timer, K_USEC(300), K_NO_WAIT);
/* RX will be aborted from k_timer timeout */
zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout");
zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), 0,
"RX_DISABLED timeout");
zassert_false(failed_in_isr, "Unexpected order of uart events");
zassert_not_equal(memcmp(tx_buf, test_read_abort_read_buf, 100), 0, "Buffers equal");
/* Read out possible other RX bytes
* that may affect following test on RX
*/
uart_rx_enable(uart_dev, rx_buf, sizeof(rx_buf), 50 * USEC_PER_MSEC);
while (k_sem_take(&rx_rdy, K_MSEC(1000)) != -EAGAIN) {
;
}
uart_rx_disable(uart_dev);
k_msleep(10);
zassert_not_equal(k_sem_take(&rx_buf_coherency, K_NO_WAIT), 0,
"All provided buffers are released");
}
ZTEST_BMEM volatile size_t sent;
ZTEST_BMEM volatile size_t received;
ZTEST_BMEM uint8_t test_rx_buf[2][100];
static void test_write_abort_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_done);
break;
case UART_TX_ABORTED:
sent = evt->data.tx.len;
k_sem_give(&tx_aborted);
break;
case UART_RX_RDY:
received = evt->data.rx.len;
k_sem_give(&rx_rdy);
break;
case UART_RX_BUF_REQUEST:
uart_rx_buf_rsp(dev, test_rx_buf[1], sizeof(test_rx_buf[1]));
break;
case UART_RX_BUF_RELEASED:
k_sem_give(&rx_buf_released);
break;
case UART_RX_DISABLED:
k_sem_give(&rx_disabled);
break;
default:
break;
}
}
static void *write_abort_setup(void)
{
uart_async_test_init();
uart_callback_set(uart_dev, test_write_abort_callback, NULL);
return NULL;
}
ZTEST_USER(uart_async_write_abort, test_write_abort)
{
uint8_t tx_buf[100];
memset(test_rx_buf, 0, sizeof(test_rx_buf));
memset(tx_buf, 1, sizeof(tx_buf));
uart_rx_enable(uart_dev, test_rx_buf[0], sizeof(test_rx_buf[0]), 50 * USEC_PER_MSEC);
uart_tx(uart_dev, tx_buf, 5, 100 * USEC_PER_MSEC);
zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), 0, "RX_RDY timeout");
zassert_equal(memcmp(tx_buf, test_rx_buf, 5), 0, "Buffers not equal");
uart_tx(uart_dev, tx_buf, 95, 100 * USEC_PER_MSEC);
uart_tx_abort(uart_dev);
zassert_equal(k_sem_take(&tx_aborted, K_MSEC(100)), 0,
"TX_ABORTED timeout");
if (sent != 0) {
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), 0,
"RX_RDY timeout");
zassert_equal(sent, received, "Sent is not equal to received.");
}
uart_rx_disable(uart_dev);
zassert_equal(k_sem_take(&rx_buf_released, K_MSEC(100)),
0,
"RX_BUF_RELEASED timeout");
zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), 0,
"RX_DISABLED timeout");
}
static void test_forever_timeout_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_done);
break;
case UART_TX_ABORTED:
sent = evt->data.tx.len;
k_sem_give(&tx_aborted);
break;
case UART_RX_RDY:
received = evt->data.rx.len;
k_sem_give(&rx_rdy);
break;
case UART_RX_BUF_RELEASED:
k_sem_give(&rx_buf_released);
break;
case UART_RX_DISABLED:
k_sem_give(&rx_disabled);
break;
default:
break;
}
}
static void *forever_timeout_setup(void)
{
uart_async_test_init();
uart_callback_set(uart_dev, test_forever_timeout_callback, NULL);
return NULL;
}
ZTEST_USER(uart_async_timeout, test_forever_timeout)
{
uint8_t rx_buf[100];
uint8_t tx_buf[100];
memset(rx_buf, 0, sizeof(rx_buf));
memset(tx_buf, 1, sizeof(tx_buf));
uart_rx_enable(uart_dev, rx_buf, sizeof(rx_buf), SYS_FOREVER_US);
uart_tx(uart_dev, tx_buf, 5, SYS_FOREVER_US);
zassert_not_equal(k_sem_take(&tx_aborted, K_MSEC(1000)), 0,
"TX_ABORTED timeout");
zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout");
zassert_not_equal(k_sem_take(&rx_rdy, K_MSEC(1000)), 0,
"RX_RDY timeout");
uart_tx(uart_dev, tx_buf, 95, SYS_FOREVER_US);
zassert_not_equal(k_sem_take(&tx_aborted, K_MSEC(1000)), 0,
"TX_ABORTED timeout");
zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), 0, "RX_RDY timeout");
zassert_equal(memcmp(tx_buf, rx_buf, 100), 0, "Buffers not equal");
uart_rx_disable(uart_dev);
zassert_equal(k_sem_take(&rx_buf_released, K_MSEC(100)),
0,
"RX_BUF_RELEASED timeout");
zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), 0,
"RX_DISABLED timeout");
}
ZTEST_DMEM uint8_t chained_write_tx_bufs[2][10] = {"Message 1", "Message 2"};
ZTEST_DMEM bool chained_write_next_buf = true;
ZTEST_BMEM volatile uint8_t tx_sent;
static void test_chained_write_callback(const struct device *dev,
struct uart_event *evt, void *user_data)
{
switch (evt->type) {
case UART_TX_DONE:
if (chained_write_next_buf) {
uart_tx(dev, chained_write_tx_bufs[1], 10, 100 * USEC_PER_MSEC);
chained_write_next_buf = false;
}
tx_sent = 1;
k_sem_give(&tx_done);
break;
case UART_TX_ABORTED:
sent = evt->data.tx.len;
k_sem_give(&tx_aborted);
break;
case UART_RX_RDY:
received = evt->data.rx.len;
k_sem_give(&rx_rdy);
break;
case UART_RX_BUF_RELEASED:
k_sem_give(&rx_buf_released);
break;
case UART_RX_DISABLED:
k_sem_give(&rx_disabled);
break;
default:
break;
}
}
static void *chained_write_setup(void)
{
uart_async_test_init();
uart_callback_set(uart_dev, test_chained_write_callback, NULL);
return NULL;
}
ZTEST_USER(uart_async_chain_write, test_chained_write)
{
uint8_t rx_buf[20];
memset(rx_buf, 0, sizeof(rx_buf));
uart_rx_enable(uart_dev, rx_buf, sizeof(rx_buf), 50 * USEC_PER_MSEC);
uart_tx(uart_dev, chained_write_tx_bufs[0], 10, 100 * USEC_PER_MSEC);
zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout");
zassert_equal(k_sem_take(&tx_done, K_MSEC(100)), 0, "TX_DONE timeout");
zassert_equal(chained_write_next_buf, false, "Sent no message");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(100)), 0, "RX_RDY timeout");
zassert_equal(memcmp(chained_write_tx_bufs[0], rx_buf, 10),
0,
"Buffers not equal");
zassert_equal(memcmp(chained_write_tx_bufs[1], rx_buf + 10, 10),
0,
"Buffers not equal");
uart_rx_disable(uart_dev);
zassert_equal(k_sem_take(&rx_buf_released, K_MSEC(100)),
0,
"RX_BUF_RELEASED timeout");
zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), 0,
"RX_DISABLED timeout");
}
ZTEST_BMEM uint8_t long_rx_buf[1024];
ZTEST_BMEM uint8_t long_rx_buf2[1024];
ZTEST_BMEM uint8_t long_tx_buf[1000];
ZTEST_BMEM volatile uint8_t evt_num;
ZTEST_BMEM size_t long_received[2];
static void test_long_buffers_callback(const struct device *dev,
struct uart_event *evt, void *user_data)
{
static uint8_t *next_buffer = long_rx_buf2;
switch (evt->type) {
case UART_TX_DONE:
k_sem_give(&tx_done);
break;
case UART_TX_ABORTED:
sent = evt->data.tx.len;
k_sem_give(&tx_aborted);
break;
case UART_RX_RDY:
long_received[evt_num] = evt->data.rx.len;
evt_num++;
k_sem_give(&rx_rdy);
break;
case UART_RX_BUF_RELEASED:
k_sem_give(&rx_buf_released);
break;
case UART_RX_DISABLED:
k_sem_give(&rx_disabled);
break;
case UART_RX_BUF_REQUEST:
uart_rx_buf_rsp(dev, next_buffer, 1024);
next_buffer = (next_buffer == long_rx_buf2) ? long_rx_buf : long_rx_buf2;
break;
default:
break;
}
}
static void *long_buffers_setup(void)
{
uart_async_test_init();
uart_callback_set(uart_dev, test_long_buffers_callback, NULL);
return NULL;
}
ZTEST_USER(uart_async_long_buf, test_long_buffers)
{
memset(long_rx_buf, 0, sizeof(long_rx_buf));
memset(long_tx_buf, 1, sizeof(long_tx_buf));
uart_rx_enable(uart_dev, long_rx_buf, sizeof(long_rx_buf), 10 * USEC_PER_MSEC);
uart_tx(uart_dev, long_tx_buf, 500, 200 * USEC_PER_MSEC);
zassert_equal(k_sem_take(&tx_done, K_MSEC(200)), 0, "TX_DONE timeout");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(200)), 0, "RX_RDY timeout");
zassert_equal(long_received[0], 500, "Wrong number of bytes received.");
zassert_equal(memcmp(long_tx_buf, long_rx_buf, 500),
0,
"Buffers not equal");
k_msleep(10);
/* Check if instance is releasing a buffer after the timeout. */
bool release_on_timeout = k_sem_take(&rx_buf_released, K_NO_WAIT) == 0;
evt_num = 0;
uart_tx(uart_dev, long_tx_buf, 1000, 200 * USEC_PER_MSEC);
zassert_equal(k_sem_take(&tx_done, K_MSEC(200)), 0, "TX_DONE timeout");
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(200)), 0, "RX_RDY timeout");
if (release_on_timeout) {
zassert_equal(long_received[0], 1000, "Wrong number of bytes received.");
zassert_equal(memcmp(long_tx_buf, long_rx_buf2, long_received[0]), 0,
"Buffers not equal");
} else {
zassert_equal(k_sem_take(&rx_rdy, K_MSEC(200)), 0, "RX_RDY timeout");
zassert_equal(long_received[0], 524, "Wrong number of bytes received.");
zassert_equal(long_received[1], 476, "Wrong number of bytes received.");
zassert_equal(memcmp(long_tx_buf, long_rx_buf + 500, long_received[0]), 0,
"Buffers not equal");
zassert_equal(memcmp(long_tx_buf, long_rx_buf2, long_received[1]), 0,
"Buffers not equal");
}
uart_rx_disable(uart_dev);
zassert_equal(k_sem_take(&rx_buf_released, K_MSEC(100)),
0,
"RX_BUF_RELEASED timeout");
zassert_equal(k_sem_take(&rx_disabled, K_MSEC(100)), 0,
"RX_DISABLED timeout");
}
ZTEST_SUITE(uart_async_single_read, NULL, single_read_setup,
NULL, NULL, NULL);
ZTEST_SUITE(uart_async_multi_rx, NULL, multiple_rx_enable_setup,
NULL, NULL, NULL);
ZTEST_SUITE(uart_async_chain_read, NULL, chained_read_setup,
NULL, NULL, NULL);
ZTEST_SUITE(uart_async_double_buf, NULL, double_buffer_setup,
NULL, NULL, NULL);
ZTEST_SUITE(uart_async_read_abort, NULL, read_abort_setup,
NULL, NULL, NULL);
ZTEST_SUITE(uart_async_chain_write, NULL, chained_write_setup,
NULL, NULL, NULL);
ZTEST_SUITE(uart_async_long_buf, NULL, long_buffers_setup,
NULL, NULL, NULL);
ZTEST_SUITE(uart_async_write_abort, NULL, write_abort_setup,
NULL, NULL, NULL);
ZTEST_SUITE(uart_async_timeout, NULL, forever_timeout_setup,
NULL, NULL, NULL);