1 /*
2  *  Copyright (c) 2023 Jeroen van Dooren
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "test_uart.h"
8 
9 K_SEM_DEFINE(tx_wide_done, 0, 1);
10 K_SEM_DEFINE(tx_wide_aborted, 0, 1);
11 K_SEM_DEFINE(rx_wide_rdy, 0, 1);
12 K_SEM_DEFINE(rx_wide_buf_released, 0, 1);
13 K_SEM_DEFINE(rx_wide_disabled, 0, 1);
14 
15 static ZTEST_BMEM const struct device *const uart_dev =
16 	DEVICE_DT_GET(UART_NODE);
17 
init_test(void)18 static void init_test(void)
19 {
20 	__ASSERT_NO_MSG(device_is_ready(uart_dev));
21 	uart_rx_disable(uart_dev);
22 	uart_tx_abort(uart_dev);
23 	k_sem_reset(&tx_wide_done);
24 	k_sem_reset(&tx_wide_aborted);
25 	k_sem_reset(&rx_wide_rdy);
26 	k_sem_reset(&rx_wide_buf_released);
27 	k_sem_reset(&rx_wide_disabled);
28 }
29 
30 #ifdef CONFIG_USERSPACE
set_permissions(void)31 static void set_permissions(void)
32 {
33 	k_thread_access_grant(k_current_get(), &tx_wide_done, &tx_wide_aborted,
34 			      &rx_wide_rdy, &rx_wide_buf_released, &rx_wide_disabled,
35 			      uart_dev);
36 }
37 #endif
38 
uart_async_test_init(void)39 static void uart_async_test_init(void)
40 {
41 	init_test();
42 
43 #ifdef CONFIG_USERSPACE
44 	set_permissions();
45 #endif
46 }
47 
test_single_read_callback(const struct device * dev,struct uart_event * evt,void * user_data)48 static void test_single_read_callback(const struct device *dev,
49 			       struct uart_event *evt, void *user_data)
50 {
51 	ARG_UNUSED(dev);
52 
53 	switch (evt->type) {
54 	case UART_TX_DONE:
55 		k_sem_give(&tx_wide_done);
56 		break;
57 	case UART_TX_ABORTED:
58 		(*(uint32_t *)user_data)++;
59 		break;
60 	case UART_RX_RDY:
61 		k_sem_give(&rx_wide_rdy);
62 		break;
63 	case UART_RX_BUF_RELEASED:
64 		k_sem_give(&rx_wide_buf_released);
65 		break;
66 	case UART_RX_DISABLED:
67 		k_sem_give(&rx_wide_disabled);
68 		break;
69 	default:
70 		break;
71 	}
72 }
73 
74 ZTEST_BMEM volatile uint32_t tx_wide_aborted_count;
75 
single_read_setup_wide(void)76 static void *single_read_setup_wide(void)
77 {
78 	uart_async_test_init();
79 
80 	uart_callback_set(uart_dev,
81 			  test_single_read_callback,
82 			  (void *) &tx_wide_aborted_count);
83 
84 	return NULL;
85 }
86 
ZTEST_USER(uart_async_single_read_wide,test_single_read_wide)87 ZTEST_USER(uart_async_single_read_wide, test_single_read_wide)
88 {
89 	uint16_t rx_buf[10] = {0};
90 
91 	/* Check also if sending from read only memory (e.g. flash) works. */
92 	static const uint16_t tx_buf[5] = {0x74, 0x65, 0x73, 0x74, 0x0D};
93 
94 	zassert_not_equal(memcmp(tx_buf, rx_buf, 5), 0,
95 			  "Initial buffer check failed");
96 
97 	uart_rx_enable_u16(uart_dev, rx_buf, 10, 50 * USEC_PER_MSEC);
98 	zassert_equal(k_sem_take(&rx_wide_rdy, K_MSEC(100)), -EAGAIN,
99 		      "RX_RDY not expected at this point");
100 
101 	uart_tx_u16(uart_dev, tx_buf, sizeof(tx_buf)/sizeof(uint16_t), 100 * USEC_PER_MSEC);
102 	zassert_equal(k_sem_take(&tx_wide_done, K_MSEC(100)), 0, "TX_DONE timeout");
103 	zassert_equal(k_sem_take(&rx_wide_rdy, K_MSEC(100)), 0, "RX_RDY timeout");
104 	zassert_equal(k_sem_take(&rx_wide_rdy, K_MSEC(100)), -EAGAIN,
105 		      "Extra RX_RDY received");
106 
107 	zassert_equal(memcmp(tx_buf, rx_buf, 5), 0, "Buffers not equal");
108 	zassert_not_equal(memcmp(tx_buf, rx_buf+5, 5), 0, "Buffers not equal");
109 
110 	uart_tx_u16(uart_dev, tx_buf, sizeof(tx_buf)/sizeof(uint16_t), 100 * USEC_PER_MSEC);
111 	zassert_equal(k_sem_take(&tx_wide_done, K_MSEC(100)), 0, "TX_DONE timeout");
112 	zassert_equal(k_sem_take(&rx_wide_rdy, K_MSEC(100)), 0, "RX_RDY timeout");
113 	zassert_equal(k_sem_take(&rx_wide_buf_released, K_MSEC(100)),
114 		      0,
115 		      "RX_BUF_RELEASED timeout");
116 	zassert_equal(k_sem_take(&rx_wide_disabled, K_MSEC(1000)), 0,
117 		      "RX_DISABLED timeout");
118 	zassert_equal(k_sem_take(&rx_wide_rdy, K_MSEC(100)), -EAGAIN,
119 		      "Extra RX_RDY received");
120 
121 	zassert_equal(memcmp(tx_buf, rx_buf+5, 5), 0, "Buffers not equal");
122 	zassert_equal(tx_wide_aborted_count, 0, "TX aborted triggered");
123 }
124 
125 ZTEST_SUITE(uart_async_single_read_wide, NULL, single_read_setup_wide,
126 		NULL, NULL, NULL);
127