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
check_nvic_pending(QTestState * qts,unsigned int n)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
clear_nvic_pending(QTestState * qts,unsigned int n)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 */
usart_wait_for_flag(QTestState * qts,uint32_t event_addr,uint32_t flag)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
usart_receive_string(QTestState * qts,int sock_fd,const char * in,char * out)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
usart_send_string(QTestState * qts,const char * in)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 */
init_clocks(QTestState * qts)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
init_uart(QTestState * qts)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
test_write_read(void)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
test_receive_char(void)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
test_send_char(void)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
test_receive_str(void)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
test_send_str(void)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
main(int argc,char ** argv)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