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