1 /*
2 * QTest testcase for STML4X5_USART
3 *
4 * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
5 * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
6 *
7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8 * See the COPYING file in the top-level directory.
9 */
10
11 #include "qemu/osdep.h"
12 #include "libqtest.h"
13 #include "hw/misc/stm32l4x5_rcc_internals.h"
14 #include "hw/registerfields.h"
15 #include "stm32l4x5.h"
16
17 #define RCC_BASE_ADDR 0x40021000
18 /* Use USART 1 ADDR, assume the others work the same */
19 #define USART1_BASE_ADDR 0x40013800
20
21 /* See stm32l4x5_usart for definitions */
22 REG32(CR1, 0x00)
23 FIELD(CR1, M1, 28, 1)
24 FIELD(CR1, OVER8, 15, 1)
25 FIELD(CR1, M0, 12, 1)
26 FIELD(CR1, PCE, 10, 1)
27 FIELD(CR1, TXEIE, 7, 1)
28 FIELD(CR1, RXNEIE, 5, 1)
29 FIELD(CR1, TE, 3, 1)
30 FIELD(CR1, RE, 2, 1)
31 FIELD(CR1, UE, 0, 1)
32 REG32(CR2, 0x04)
33 REG32(CR3, 0x08)
34 FIELD(CR3, OVRDIS, 12, 1)
35 REG32(BRR, 0x0C)
36 REG32(GTPR, 0x10)
37 REG32(RTOR, 0x14)
38 REG32(RQR, 0x18)
39 REG32(ISR, 0x1C)
40 FIELD(ISR, REACK, 22, 1)
41 FIELD(ISR, TEACK, 21, 1)
42 FIELD(ISR, TXE, 7, 1)
43 FIELD(ISR, RXNE, 5, 1)
44 FIELD(ISR, ORE, 3, 1)
45 REG32(ICR, 0x20)
46 REG32(RDR, 0x24)
47 REG32(TDR, 0x28)
48
49 #define NVIC_ISPR1 0XE000E204
50 #define NVIC_ICPR1 0xE000E284
51 #define USART1_IRQ 37
52
check_nvic_pending(QTestState * qts,unsigned int n)53 static bool check_nvic_pending(QTestState *qts, unsigned int n)
54 {
55 /* No USART interrupts are less than 32 */
56 assert(n > 32);
57 n -= 32;
58 return qtest_readl(qts, NVIC_ISPR1) & (1 << n);
59 }
60
clear_nvic_pending(QTestState * qts,unsigned int n)61 static bool clear_nvic_pending(QTestState *qts, unsigned int n)
62 {
63 /* No USART interrupts are less than 32 */
64 assert(n > 32);
65 n -= 32;
66 qtest_writel(qts, NVIC_ICPR1, (1 << n));
67 return true;
68 }
69
70 /*
71 * Wait indefinitely for the flag to be updated.
72 * If this is run on a slow CI runner,
73 * the meson harness will timeout after 10 minutes for us.
74 */
usart_wait_for_flag(QTestState * qts,uint32_t event_addr,uint32_t flag)75 static bool usart_wait_for_flag(QTestState *qts, uint32_t event_addr,
76 uint32_t flag)
77 {
78 while (true) {
79 if ((qtest_readl(qts, event_addr) & flag)) {
80 return true;
81 }
82 g_usleep(1000);
83 }
84
85 return false;
86 }
87
usart_receive_string(QTestState * qts,int sock_fd,const char * in,char * out)88 static void usart_receive_string(QTestState *qts, int sock_fd, const char *in,
89 char *out)
90 {
91 int i, in_len = strlen(in);
92
93 g_assert_true(send(sock_fd, in, in_len, 0) == in_len);
94 for (i = 0; i < in_len; i++) {
95 g_assert_true(usart_wait_for_flag(qts,
96 USART1_BASE_ADDR + A_ISR, R_ISR_RXNE_MASK));
97 out[i] = qtest_readl(qts, USART1_BASE_ADDR + A_RDR);
98 }
99 out[i] = '\0';
100 }
101
usart_send_string(QTestState * qts,const char * in)102 static void usart_send_string(QTestState *qts, const char *in)
103 {
104 int i, in_len = strlen(in);
105
106 for (i = 0; i < in_len; i++) {
107 qtest_writel(qts, USART1_BASE_ADDR + A_TDR, in[i]);
108 g_assert_true(usart_wait_for_flag(qts,
109 USART1_BASE_ADDR + A_ISR, R_ISR_TXE_MASK));
110 }
111 }
112
113 /* Init the RCC clocks to run at 80 MHz */
init_clocks(QTestState * qts)114 static void init_clocks(QTestState *qts)
115 {
116 uint32_t value;
117
118 /* MSIRANGE can be set only when MSI is OFF or READY */
119 qtest_writel(qts, (RCC_BASE_ADDR + A_CR), R_CR_MSION_MASK);
120
121 /* Clocking from MSI, in case MSI was not the default source */
122 qtest_writel(qts, (RCC_BASE_ADDR + A_CFGR), 0);
123
124 /*
125 * Update PLL and set MSI as the source clock.
126 * PLLM = 1 --> 000
127 * PLLN = 40 --> 40
128 * PPLLR = 2 --> 00
129 * PLLDIV = unused, PLLP = unused (SAI3), PLLQ = unused (48M1)
130 * SRC = MSI --> 01
131 */
132 qtest_writel(qts, (RCC_BASE_ADDR + A_PLLCFGR), R_PLLCFGR_PLLREN_MASK |
133 (40 << R_PLLCFGR_PLLN_SHIFT) |
134 (0b01 << R_PLLCFGR_PLLSRC_SHIFT));
135
136 /* PLL activation */
137
138 value = qtest_readl(qts, (RCC_BASE_ADDR + A_CR));
139 qtest_writel(qts, (RCC_BASE_ADDR + A_CR), value | R_CR_PLLON_MASK);
140
141 /* RCC_CFGR is OK by defaut */
142 qtest_writel(qts, (RCC_BASE_ADDR + A_CFGR), 0);
143
144 /* CCIPR : no periph clock by default */
145 qtest_writel(qts, (RCC_BASE_ADDR + A_CCIPR), 0);
146
147 /* Switches on the PLL clock source */
148 value = qtest_readl(qts, (RCC_BASE_ADDR + A_CFGR));
149 qtest_writel(qts, (RCC_BASE_ADDR + A_CFGR), (value & ~R_CFGR_SW_MASK) |
150 (0b11 << R_CFGR_SW_SHIFT));
151
152 /* Enable SYSCFG clock enabled */
153 qtest_writel(qts, (RCC_BASE_ADDR + A_APB2ENR), R_APB2ENR_SYSCFGEN_MASK);
154
155 /* Enable the IO port B clock (See p.252) */
156 qtest_writel(qts, (RCC_BASE_ADDR + A_AHB2ENR), R_AHB2ENR_GPIOBEN_MASK);
157
158 /* Enable the clock for USART1 (cf p.259) */
159 /* We rewrite SYSCFGEN to not disable it */
160 qtest_writel(qts, (RCC_BASE_ADDR + A_APB2ENR),
161 R_APB2ENR_SYSCFGEN_MASK | R_APB2ENR_USART1EN_MASK);
162
163 /* TODO: Enable usart via gpio */
164
165 /* Set PCLK as the clock for USART1(cf p.272) i.e. reset both bits */
166 qtest_writel(qts, (RCC_BASE_ADDR + A_CCIPR), 0);
167
168 /* Reset USART1 (see p.249) */
169 qtest_writel(qts, (RCC_BASE_ADDR + A_APB2RSTR), 1 << 14);
170 qtest_writel(qts, (RCC_BASE_ADDR + A_APB2RSTR), 0);
171 }
172
init_uart(QTestState * qts)173 static void init_uart(QTestState *qts)
174 {
175 uint32_t cr1;
176
177 init_clocks(qts);
178
179 /*
180 * For 115200 bauds, see p.1349.
181 * The clock has a frequency of 80Mhz,
182 * for 115200, we have to put a divider of 695 = 0x2B7.
183 */
184 qtest_writel(qts, (USART1_BASE_ADDR + A_BRR), 0x2B7);
185
186 /*
187 * Set the oversampling by 16,
188 * disable the parity control and
189 * set the word length to 8. (cf p.1377)
190 */
191 cr1 = qtest_readl(qts, (USART1_BASE_ADDR + A_CR1));
192 cr1 &= ~(R_CR1_M1_MASK | R_CR1_M0_MASK | R_CR1_OVER8_MASK | R_CR1_PCE_MASK);
193 qtest_writel(qts, (USART1_BASE_ADDR + A_CR1), cr1);
194
195 /* Enable the transmitter, the receiver and the USART. */
196 qtest_writel(qts, (USART1_BASE_ADDR + A_CR1),
197 cr1 | R_CR1_UE_MASK | R_CR1_RE_MASK | R_CR1_TE_MASK);
198 }
199
test_write_read(void)200 static void test_write_read(void)
201 {
202 QTestState *qts = qtest_init("-M b-l475e-iot01a");
203
204 /* Test that we can write and retrieve a value from the device */
205 qtest_writel(qts, USART1_BASE_ADDR + A_TDR, 0xFFFFFFFF);
206 const uint32_t tdr = qtest_readl(qts, USART1_BASE_ADDR + A_TDR);
207 g_assert_cmpuint(tdr, ==, 0x000001FF);
208
209 qtest_quit(qts);
210 }
211
test_receive_char(void)212 static void test_receive_char(void)
213 {
214 int sock_fd;
215 uint32_t cr1;
216 QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
217
218 init_uart(qts);
219
220 /* Try without initializing IRQ */
221 g_assert_true(send(sock_fd, "a", 1, 0) == 1);
222 usart_wait_for_flag(qts, USART1_BASE_ADDR + A_ISR, R_ISR_RXNE_MASK);
223 g_assert_cmphex(qtest_readl(qts, USART1_BASE_ADDR + A_RDR), ==, 'a');
224 g_assert_false(check_nvic_pending(qts, USART1_IRQ));
225
226 /* Now with the IRQ */
227 cr1 = qtest_readl(qts, (USART1_BASE_ADDR + A_CR1));
228 cr1 |= R_CR1_RXNEIE_MASK;
229 qtest_writel(qts, USART1_BASE_ADDR + A_CR1, cr1);
230 g_assert_true(send(sock_fd, "b", 1, 0) == 1);
231 usart_wait_for_flag(qts, USART1_BASE_ADDR + A_ISR, R_ISR_RXNE_MASK);
232 g_assert_cmphex(qtest_readl(qts, USART1_BASE_ADDR + A_RDR), ==, 'b');
233 g_assert_true(check_nvic_pending(qts, USART1_IRQ));
234 clear_nvic_pending(qts, USART1_IRQ);
235
236 close(sock_fd);
237
238 qtest_quit(qts);
239 }
240
test_send_char(void)241 static void test_send_char(void)
242 {
243 int sock_fd;
244 char s[1];
245 uint32_t cr1;
246 QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
247
248 init_uart(qts);
249
250 /* Try without initializing IRQ */
251 qtest_writel(qts, USART1_BASE_ADDR + A_TDR, 'c');
252 g_assert_true(recv(sock_fd, s, 1, 0) == 1);
253 g_assert_cmphex(s[0], ==, 'c');
254 g_assert_false(check_nvic_pending(qts, USART1_IRQ));
255
256 /* Now with the IRQ */
257 cr1 = qtest_readl(qts, (USART1_BASE_ADDR + A_CR1));
258 cr1 |= R_CR1_TXEIE_MASK;
259 qtest_writel(qts, USART1_BASE_ADDR + A_CR1, cr1);
260 qtest_writel(qts, USART1_BASE_ADDR + A_TDR, 'd');
261 g_assert_true(recv(sock_fd, s, 1, 0) == 1);
262 g_assert_cmphex(s[0], ==, 'd');
263 g_assert_true(check_nvic_pending(qts, USART1_IRQ));
264 clear_nvic_pending(qts, USART1_IRQ);
265
266 close(sock_fd);
267
268 qtest_quit(qts);
269 }
270
test_receive_str(void)271 static void test_receive_str(void)
272 {
273 int sock_fd;
274 char s[10];
275 QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
276
277 init_uart(qts);
278
279 usart_receive_string(qts, sock_fd, "hello", s);
280 g_assert_true(memcmp(s, "hello", 5) == 0);
281
282 close(sock_fd);
283
284 qtest_quit(qts);
285 }
286
test_send_str(void)287 static void test_send_str(void)
288 {
289 int sock_fd;
290 char s[10];
291 QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
292
293 init_uart(qts);
294
295 usart_send_string(qts, "world");
296 g_assert_true(recv(sock_fd, s, 10, 0) == 5);
297 g_assert_true(memcmp(s, "world", 5) == 0);
298
299 close(sock_fd);
300
301 qtest_quit(qts);
302 }
303
test_ack(void)304 static void test_ack(void)
305 {
306 uint32_t cr1;
307 uint32_t isr;
308 QTestState *qts = qtest_init("-M b-l475e-iot01a");
309
310 init_uart(qts);
311
312 cr1 = qtest_readl(qts, (USART1_BASE_ADDR + A_CR1));
313
314 /* Disable the transmitter and receiver. */
315 qtest_writel(qts, (USART1_BASE_ADDR + A_CR1),
316 cr1 & ~(R_CR1_RE_MASK | R_CR1_TE_MASK));
317
318 /* Test ISR ACK for transmitter and receiver disabled */
319 isr = qtest_readl(qts, (USART1_BASE_ADDR + A_ISR));
320 g_assert_false(isr & R_ISR_TEACK_MASK);
321 g_assert_false(isr & R_ISR_REACK_MASK);
322
323 /* Enable the transmitter and receiver. */
324 qtest_writel(qts, (USART1_BASE_ADDR + A_CR1),
325 cr1 | (R_CR1_RE_MASK | R_CR1_TE_MASK));
326
327 /* Test ISR ACK for transmitter and receiver disabled */
328 isr = qtest_readl(qts, (USART1_BASE_ADDR + A_ISR));
329 g_assert_true(isr & R_ISR_TEACK_MASK);
330 g_assert_true(isr & R_ISR_REACK_MASK);
331
332 qtest_quit(qts);
333 }
334
check_clock(QTestState * qts,const char * path,uint32_t rcc_reg,uint32_t reg_offset)335 static void check_clock(QTestState *qts, const char *path, uint32_t rcc_reg,
336 uint32_t reg_offset)
337 {
338 g_assert_cmpuint(get_clock_period(qts, path), ==, 0);
339 qtest_writel(qts, rcc_reg, qtest_readl(qts, rcc_reg) | (0x1 << reg_offset));
340 g_assert_cmpuint(get_clock_period(qts, path), ==, SYSCLK_PERIOD);
341 }
342
test_clock_enable(void)343 static void test_clock_enable(void)
344 {
345 /*
346 * For each USART device, enable its clock in RCC
347 * and check that its clock frequency is SYSCLK_PERIOD
348 */
349 QTestState *qts = qtest_init("-M b-l475e-iot01a");
350
351 check_clock(qts, "machine/soc/usart[0]/clk", RCC_APB2ENR, 14);
352 check_clock(qts, "machine/soc/usart[1]/clk", RCC_APB1ENR1, 17);
353 check_clock(qts, "machine/soc/usart[2]/clk", RCC_APB1ENR1, 18);
354 check_clock(qts, "machine/soc/uart[0]/clk", RCC_APB1ENR1, 19);
355 check_clock(qts, "machine/soc/uart[1]/clk", RCC_APB1ENR1, 20);
356 check_clock(qts, "machine/soc/lpuart1/clk", RCC_APB1ENR2, 0);
357
358 qtest_quit(qts);
359 }
360
main(int argc,char ** argv)361 int main(int argc, char **argv)
362 {
363 int ret;
364
365 g_test_init(&argc, &argv, NULL);
366 g_test_set_nonfatal_assertions();
367
368 qtest_add_func("stm32l4x5/usart/write_read", test_write_read);
369 qtest_add_func("stm32l4x5/usart/receive_char", test_receive_char);
370 qtest_add_func("stm32l4x5/usart/send_char", test_send_char);
371 qtest_add_func("stm32l4x5/usart/receive_str", test_receive_str);
372 qtest_add_func("stm32l4x5/usart/send_str", test_send_str);
373 qtest_add_func("stm32l4x5/usart/ack", test_ack);
374 qtest_add_func("stm32l4x5/usart/clock_enable", test_clock_enable);
375 ret = g_test_run();
376
377 return ret;
378 }
379
380