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