1 /*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*
8 * @addtogroup t_uart_basic
9 * @{
10 * @defgroup t_uart_fifo test_uart_fifo
11 * @brief TestPurpose: verify UART works well in fifo mode
12 * @details
13 * - Test Steps
14 * - FIFO Output:
15 * -# Set UART IRQ callback using uart_irq_callback_set().
16 * -# Enable UART TX IRQ using uart_irq_tx_enable().
17 * -# Output the prepared data using uart_fifo_fill().
18 * -# Disable UART TX IRQ using uart_irq_tx_disable().
19 * -# Compare the number of characters sent out with the
20 * original data size.
21 * - FIFO Input:
22 * -# Set UART IRQ callback using uart_irq_callback_set().
23 * -# Enable UART RX IRQ using uart_irq_rx_enable().
24 * -# Wait for data sent to UART console and trigger RX IRQ.
25 * -# Read data from UART console using uart_fifo_read().
26 * -# Disable UART TX IRQ using uart_irq_rx_disable().
27 * - Expected Results
28 * -# When test UART FIFO output, the number of characters actually
29 * sent out will be equal to the original length of the characters.
30 * -# When test UART FIFO input, the app will wait for input from UART
31 * console and exit after receiving one character.
32 * @}
33 */
34
35 #include "test_uart.h"
36
37 static volatile bool data_transmitted;
38 static volatile bool data_received;
39 static int char_sent;
40 static const char fifo_data[] = "This is a FIFO test.\r\n";
41
42 #define DATA_SIZE (sizeof(fifo_data) - 1)
43
uart_fifo_callback(const struct device * dev,void * user_data)44 static void uart_fifo_callback(const struct device *dev, void *user_data)
45 {
46 uint8_t recvData;
47 static int tx_data_idx;
48 int ret;
49
50 ARG_UNUSED(user_data);
51
52 /* Verify uart_irq_update() */
53 if (!uart_irq_update(dev)) {
54 TC_PRINT("retval should always be 1\n");
55 return;
56 }
57
58 /* Verify uart_irq_tx_ready() */
59 /* Note that TX IRQ may be disabled, but uart_irq_tx_ready() may
60 * still return true when ISR is called for another UART interrupt,
61 * hence additional check for i < DATA_SIZE.
62 */
63 if (uart_irq_tx_ready(dev) && tx_data_idx < DATA_SIZE) {
64 /* We arrive here by "tx ready" interrupt, so should always
65 * be able to put at least one byte into a FIFO. If not,
66 * well, we'll fail test.
67 */
68 ret = uart_fifo_fill(dev, (uint8_t *)&fifo_data[tx_data_idx],
69 DATA_SIZE - char_sent);
70 if (ret > 0) {
71 data_transmitted = true;
72 char_sent += ret;
73 tx_data_idx += ret;
74 } else {
75 uart_irq_tx_disable(dev);
76 return;
77 }
78
79 if (tx_data_idx == DATA_SIZE) {
80 /* If we transmitted everything, stop IRQ stream,
81 * otherwise main app might never run.
82 */
83 uart_irq_tx_disable(dev);
84 }
85 }
86
87 /* Verify uart_irq_rx_ready() */
88 if (uart_irq_rx_ready(dev)) {
89 /* Verify uart_fifo_read() */
90 uart_fifo_read(dev, &recvData, 1);
91 TC_PRINT("%c", recvData);
92
93 if ((recvData == '\n') || (recvData == '\r')) {
94 data_received = true;
95 }
96 }
97 }
98
test_fifo_read(void)99 static int test_fifo_read(void)
100 {
101 const struct device *const uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
102
103 if (!device_is_ready(uart_dev)) {
104 TC_PRINT("UART device not ready\n");
105 return TC_FAIL;
106 }
107
108 /* Verify uart_irq_callback_set() */
109 uart_irq_callback_set(uart_dev, uart_fifo_callback);
110
111 /* Enable Tx/Rx interrupt before using fifo */
112 /* Verify uart_irq_rx_enable() */
113 uart_irq_rx_enable(uart_dev);
114
115 TC_PRINT("Please send characters to serial console\n");
116
117 data_received = false;
118 while (data_received == false) {
119 /* Allow other thread/workqueue to work. */
120 k_yield();
121 }
122
123 /* Verify uart_irq_rx_disable() */
124 uart_irq_rx_disable(uart_dev);
125
126 return TC_PASS;
127 }
128
test_fifo_fill(void)129 static int test_fifo_fill(void)
130 {
131 const struct device *const uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
132
133 if (!device_is_ready(uart_dev)) {
134 TC_PRINT("UART device not ready\n");
135 return TC_FAIL;
136 }
137
138 char_sent = 0;
139
140 /* Verify uart_irq_callback_set() */
141 uart_irq_callback_set(uart_dev, uart_fifo_callback);
142
143 /* Enable Tx/Rx interrupt before using fifo */
144 /* Verify uart_irq_tx_enable() */
145 uart_irq_tx_enable(uart_dev);
146
147 k_sleep(K_MSEC(500));
148
149 /* Verify uart_irq_tx_disable() */
150 uart_irq_tx_disable(uart_dev);
151
152 if (!data_transmitted) {
153 return TC_FAIL;
154 }
155
156 if (char_sent == DATA_SIZE) {
157 return TC_PASS;
158 } else {
159 return TC_FAIL;
160 }
161
162 }
163
164 #if CONFIG_SHELL
test_uart_fifo_fill(void)165 void test_uart_fifo_fill(void)
166 #else
167 ZTEST(uart_basic_api, test_uart_fifo_fill)
168 #endif
169 {
170 #ifndef CONFIG_UART_INTERRUPT_DRIVEN
171 ztest_test_skip();
172 #endif
173 zassert_true(test_fifo_fill() == TC_PASS);
174 }
175
176 #if CONFIG_SHELL
test_uart_fifo_read(void)177 void test_uart_fifo_read(void)
178 #else
179 ZTEST(uart_basic_api, test_uart_fifo_read)
180 #endif
181 {
182 #ifndef CONFIG_UART_INTERRUPT_DRIVEN
183 ztest_test_skip();
184 #endif
185 zassert_true(test_fifo_read() == TC_PASS);
186 }
187