ruuvi.drivers.c ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
Loading...
Searching...
No Matches
ruuvi_interface_communication_uart_test.c
Go to the documentation of this file.
2#if RUUVI_RUN_TESTS
4#include "ruuvi_driver_test.h"
10#include <stdbool.h>
11#include <string.h>
12#include <stdio.h>
13
27static ri_comm_channel_t m_channel;
28static uint8_t m_has_sent;
29static uint8_t m_has_received;
30static ri_comm_message_t rx_data;
31
32static rd_status_t uart_isr (ri_comm_evt_t evt,
33 void * p_data, size_t data_len)
34{
35 switch (evt)
36 {
38 // Will never trigger on UART
39 break;
40
42 // Will never trigger on UART
43 break;
44
45 case RI_COMM_SENT:
46 m_has_sent++;
47 break;
48
50 m_has_received++;
52 m_channel.read (&rx_data);
53 break;
54
55 default:
56 break;
57 }
58
59 return RD_SUCCESS;
60}
61
62/*
63 * Initializes UART hardware.
64 *
65 * @retval RD_SUCCESS on success,
66 * @retval RD_ERROR_INVALID_STATE if UART is already initialized
67 */
68static bool ri_uart_init_test (const rd_test_print_fp printfp)
69{
70 bool status = false;
71 rd_status_t err_code = RD_SUCCESS;
72 printfp ("\"init\":");
73 err_code |= ri_uart_init (&m_channel);
74
75 if (RD_SUCCESS == err_code)
76 {
77 err_code |= ri_uart_init (&m_channel);
78
79 if (RD_ERROR_INVALID_STATE == err_code)
80 {
81 err_code = ri_uart_uninit (&m_channel);
82 err_code = ri_uart_init (&m_channel);
83
84 if (RD_SUCCESS != err_code)
85 {
86 status = true;
87 }
88 }
89 else
90 {
91 status = true;
92 }
93 }
94 else
95 {
96 status = true;
97 }
98
99 if (status)
100 {
101 printfp ("\"fail\",\r\n");
102 }
103 else
104 {
105 printfp ("\"pass\",\r\n");
106 }
107
108 ri_uart_uninit (&m_channel);
109 return status;
110}
111
112static rd_status_t uart_init_test (const ri_gpio_id_t input,
113 const ri_gpio_id_t output)
114{
115 rd_status_t err_code = RD_SUCCESS;
116 m_has_sent = false;
117 m_has_received = false;
118 memset (&rx_data, 0, sizeof (rx_data));
119 ri_uart_init_t config =
120 {
121 .hwfc_enabled = false,
122 .parity_enabled = false,
123 .cts = RI_GPIO_ID_UNUSED,
124 .rts = RI_GPIO_ID_UNUSED,
125 .tx = output,
126 .rx = input,
127 .baud = RI_UART_BAUD_115200
128 };
129 err_code |= ri_uart_init (&m_channel);
130 m_channel.on_evt = uart_isr;
131 // TODO: Test different baudrates, parities etc.
132 err_code |= ri_uart_config (&config);
133 return err_code;
134}
135
136static bool uart_run_test (const char * const test_data)
137{
138 bool status = false;
139 bool timeout = false;
140 m_has_sent = false;
141 m_has_received = false;
142 memset (&rx_data, 0, sizeof (rx_data));
143 rd_status_t err_code = RD_SUCCESS;
144 ri_comm_message_t msg = { 0 };
145 msg.repeat_count = 1;
146 size_t written = 0;
147 written = snprintf ( (char *) & msg.data, RI_COMM_MESSAGE_MAX_LENGTH, "%s", test_data);
149 ? RI_COMM_MESSAGE_MAX_LENGTH : written;
150 ri_rtc_init();
151 err_code |= m_channel.send (&msg);
152
153 while (! (m_has_sent && m_has_received)
154 && (!timeout))
155 {
157 {
158 timeout = true;
159 }
160 }
161
162 if ( (RD_SUCCESS != err_code)
163 || memcmp (&rx_data, &msg, sizeof (ri_comm_message_t))
164 || timeout
165 || (m_has_received != 1))
166 {
167 status = true;
168 }
169
171 return status;
172}
173
177bool ri_uart_tx_test (const rd_test_print_fp printfp, const ri_gpio_id_t input,
178 const ri_gpio_id_t output)
179{
180 bool status = false;
181 rd_status_t err_code = RD_SUCCESS;
182 printfp ("\"tx_rx\":");
183 err_code |= uart_init_test (input, output);
184 char test_data[] =
185 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor"
186 " incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis "
187 "nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. "
188 "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu "
189 "fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
190 "sunt in culpa qui officia deserunt mollit anim id est laborum";
191 test_data[RI_COMM_MESSAGE_MAX_LENGTH] = '\n';
192
193 if (RD_SUCCESS == err_code)
194 {
195 status |= uart_run_test (test_data);
196 }
197 else
198 {
199 status = true;
200 }
201
202 if (status)
203 {
204 printfp ("\"fail\",\r\n");
205 }
206 else
207 {
208 printfp ("\"pass\",\r\n");
209 }
210
211 (void) ri_uart_uninit (&m_channel);
212 return status;
213}
214
218bool ri_uart_rx_test (const rd_test_print_fp printfp, const ri_gpio_id_t input,
219 const ri_gpio_id_t output)
220{
221 bool status = false;
222 bool timeout = false;
223 m_has_sent = 0;
224 m_has_received = 0;
225 rd_status_t err_code = RD_SUCCESS;
226 printfp ("\"rx_corrupt\":");
227 err_code |= uart_init_test (input, output);
228 const char test_data[] =
229 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor "
230 "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis "
231 "nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. "
232 "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu "
233 "fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in "
234 "culpa qui officia deserunt mollit anim id est laborum\n";
235 ri_comm_message_t msg = { 0 };
236 msg.repeat_count = 1;
237 memcpy (msg.data, test_data, RI_COMM_MESSAGE_MAX_LENGTH);
239
240 if (RD_SUCCESS == err_code)
241 {
242 m_channel.on_evt = uart_isr;
243 ri_rtc_init();
244 err_code |= m_channel.send (&msg);
245
246 while (! (m_has_sent && m_has_received)
247 && (!timeout))
248 {
250 {
251 timeout = true;
252 }
253 }
254
255 size_t written = snprintf ( (char *) msg.data, RI_COMM_MESSAGE_MAX_LENGTH, "%s",
256 test_data + RI_COMM_MESSAGE_MAX_LENGTH);
257 msg.data_length = written;
258 const char * cutoff_index = test_data + strlen (test_data) - written;
259 memset (&rx_data, 0, sizeof (rx_data));
260 err_code |= m_channel.send (&msg);
261
262 while ( ( (m_has_sent < 2) && (m_has_received < 2))
263 && (!timeout))
264 {
266 {
267 timeout = true;
268 }
269 }
270
271 if ( (RD_SUCCESS != err_code)
272 || memcmp (&rx_data.data, cutoff_index, rx_data.data_length)
273 || timeout
274 || (m_has_received != 2)
275 || (m_has_sent != 2))
276 {
277 status = true;
278 }
279
280 (void) ri_rtc_uninit();
281 }
282 else
283 {
284 status = true;
285 }
286
287 if (status)
288 {
289 printfp ("\"fail\",\r\n");
290 }
291 else
292 {
293 printfp ("\"pass\",\r\n");
294 }
295
296 (void) ri_uart_uninit (&m_channel);
297 return status;
298}
299
300bool ri_uart_rx_short_test (const rd_test_print_fp printfp, const ri_gpio_id_t input,
301 const ri_gpio_id_t output)
302{
303 bool status = false;
304 rd_status_t err_code = RD_SUCCESS;
305 printfp ("\"rx_short\":");
306 err_code |= uart_init_test (input, output);
307 const char test_data[] = "Lorem ipsum dolor sit amet\n";
308
309 if (RD_SUCCESS == err_code)
310 {
311 status |= uart_run_test (test_data);
312 }
313 else
314 {
315 status = true;
316 }
317
318 if (status)
319 {
320 printfp ("\"fail\"\r\n");
321 }
322 else
323 {
324 printfp ("\"pass\"\r\n");
325 }
326
327 (void) ri_uart_uninit (&m_channel);
328 return status;
329}
330
332 const ri_gpio_id_t input, const ri_gpio_id_t output)
333{
334 rd_status_t status = false;
335 printfp ("\"uart\":{\r\n");
336 status |= ri_uart_init_test (printfp);
337 status |= ri_uart_tx_test (printfp, input, output);
338 status |= ri_uart_rx_test (printfp, input, output);
339 status |= ri_uart_rx_short_test (printfp, input, output);
340 printfp ("},\r\n");
341 return status;
342}
343#endif
uint32_t rd_status_t
bitfield for representing errors
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
bool ri_communication_uart_run_integration_test(const rd_test_print_fp printfp, const ri_gpio_id_t input, const ri_gpio_id_t output)
void(* rd_test_print_fp)(const char *const msg)
function pointer to print test information
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
Functions for testing drivers.
#define RI_COMM_MESSAGE_MAX_LENGTH
The maximum length for the application message for sending over BLE, which depends on whether extende...
ri_comm_evt_t
Communication event type.
@ RI_COMM_CONNECTED
Connection established, OK to send, may receive data.
@ RI_COMM_RECEIVED
New data received, available to read with read function.
@ RI_COMM_SENT
One queued message was sent with all repetitions.
@ RI_COMM_DISCONNECTED
Connection lost, cannot send, may not receive data.
@ RI_UART_BAUD_115200
Run at 115200 baud.
rd_status_t ri_uart_uninit(ri_comm_channel_t *const channel)
rd_status_t ri_uart_config(const ri_uart_init_t *const config)
Configure UART.
rd_status_t ri_uart_init(ri_comm_channel_t *const channel)
Initialize UART.
#define TEST_TIMEOUT_MS
If TX/RX test not ready in this time, fail.
uint16_t ri_gpio_id_t
port<<8 + pin
#define RI_GPIO_ID_UNUSED
Enable implementation selected by application.
rd_status_t ri_rtc_init(void)
Initializes RTC at 0 ms.
rd_status_t ri_rtc_uninit(void)
Stop RTC if applicable.
uint64_t ri_rtc_millis(void)
Get milliseconds since init.
control API for communication via outside world
ri_comm_evt_handler_fp_t on_evt
Callback to application-level event handler, must be set in application.
ri_comm_xfer_fp_t send
Asynchronous send function.
ri_comm_xfer_fp_t read
Asynchronous read function.
Application message structure used for communication.
uint8_t data[RI_COMM_MESSAGE_MAX_LENGTH]
Data payload.
uint8_t repeat_count
Number of times to repeat the message,.
uint8_t data_length
Length of data.
UART initialization data.
bool hwfc_enabled
True to enable hardware flow control.