2 * QTest testcase for Microbit board using the Nordic Semiconductor nRF51 SoC.
5 * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf
6 * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf
8 * Microbit Board: http://microbit.org/
10 * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
12 * This code is licensed under the GPL version 2 or later. See
13 * the COPYING file in the top-level directory.
17 #include "qemu/osdep.h"
18 #include "exec/hwaddr.h"
21 #include "hw/arm/nrf51.h"
22 #include "hw/char/nrf51_uart.h"
23 #include "hw/gpio/nrf51_gpio.h"
24 #include "hw/nvram/nrf51_nvm.h"
25 #include "hw/timer/nrf51_timer.h"
26 #include "hw/i2c/microbit_i2c.h"
28 static bool uart_wait_for_event(QTestState
*qts
, uint32_t event_addr
)
30 time_t now
, start
= time(NULL
);
33 if (qtest_readl(qts
, event_addr
) == 1) {
34 qtest_writel(qts
, event_addr
, 0x00);
38 /* Wait at most 10 minutes */
40 if (now
- start
> 600) {
49 static void uart_rw_to_rxd(QTestState
*qts
, int sock_fd
, const char *in
,
52 int i
, in_len
= strlen(in
);
54 g_assert_true(send(sock_fd
, in
, in_len
, 0) == in_len
);
55 for (i
= 0; i
< in_len
; i
++) {
56 g_assert_true(uart_wait_for_event(qts
, NRF51_UART_BASE
+
58 out
[i
] = qtest_readl(qts
, NRF51_UART_BASE
+ A_UART_RXD
);
63 static void uart_w_to_txd(QTestState
*qts
, const char *in
)
65 int i
, in_len
= strlen(in
);
67 for (i
= 0; i
< in_len
; i
++) {
68 qtest_writel(qts
, NRF51_UART_BASE
+ A_UART_TXD
, in
[i
]);
69 g_assert_true(uart_wait_for_event(qts
, NRF51_UART_BASE
+
74 static void test_nrf51_uart(void)
78 QTestState
*qts
= qtest_init_with_serial("-M microbit", &sock_fd
);
80 g_assert_true(send(sock_fd
, "c", 1, 0) == 1);
81 g_assert_cmphex(qtest_readl(qts
, NRF51_UART_BASE
+ A_UART_RXD
), ==, 0x00);
83 qtest_writel(qts
, NRF51_UART_BASE
+ A_UART_ENABLE
, 0x04);
84 qtest_writel(qts
, NRF51_UART_BASE
+ A_UART_STARTRX
, 0x01);
86 g_assert_true(uart_wait_for_event(qts
, NRF51_UART_BASE
+ A_UART_RXDRDY
));
87 qtest_writel(qts
, NRF51_UART_BASE
+ A_UART_RXDRDY
, 0x00);
88 g_assert_cmphex(qtest_readl(qts
, NRF51_UART_BASE
+ A_UART_RXD
), ==, 'c');
90 qtest_writel(qts
, NRF51_UART_BASE
+ A_UART_INTENSET
, 0x04);
91 g_assert_cmphex(qtest_readl(qts
, NRF51_UART_BASE
+ A_UART_INTEN
), ==, 0x04);
92 qtest_writel(qts
, NRF51_UART_BASE
+ A_UART_INTENCLR
, 0x04);
93 g_assert_cmphex(qtest_readl(qts
, NRF51_UART_BASE
+ A_UART_INTEN
), ==, 0x00);
95 uart_rw_to_rxd(qts
, sock_fd
, "hello", s
);
96 g_assert_true(memcmp(s
, "hello", 5) == 0);
98 qtest_writel(qts
, NRF51_UART_BASE
+ A_UART_STARTTX
, 0x01);
99 uart_w_to_txd(qts
, "d");
100 g_assert_true(recv(sock_fd
, s
, 10, 0) == 1);
101 g_assert_cmphex(s
[0], ==, 'd');
103 qtest_writel(qts
, NRF51_UART_BASE
+ A_UART_SUSPEND
, 0x01);
104 qtest_writel(qts
, NRF51_UART_BASE
+ A_UART_TXD
, 'h');
105 qtest_writel(qts
, NRF51_UART_BASE
+ A_UART_STARTTX
, 0x01);
106 uart_w_to_txd(qts
, "world");
107 g_assert_true(recv(sock_fd
, s
, 10, 0) == 5);
108 g_assert_true(memcmp(s
, "world", 5) == 0);
115 /* Read a byte from I2C device at @addr from register @reg */
116 static uint32_t i2c_read_byte(QTestState
*qts
, uint32_t addr
, uint32_t reg
)
120 qtest_writel(qts
, NRF51_TWI_BASE
+ NRF51_TWI_REG_ADDRESS
, addr
);
121 qtest_writel(qts
, NRF51_TWI_BASE
+ NRF51_TWI_TASK_STARTTX
, 1);
122 qtest_writel(qts
, NRF51_TWI_BASE
+ NRF51_TWI_REG_TXD
, reg
);
123 val
= qtest_readl(qts
, NRF51_TWI_BASE
+ NRF51_TWI_EVENT_TXDSENT
);
124 g_assert_cmpuint(val
, ==, 1);
125 qtest_writel(qts
, NRF51_TWI_BASE
+ NRF51_TWI_TASK_STOP
, 1);
127 qtest_writel(qts
, NRF51_TWI_BASE
+ NRF51_TWI_TASK_STARTRX
, 1);
128 val
= qtest_readl(qts
, NRF51_TWI_BASE
+ NRF51_TWI_EVENT_RXDREADY
);
129 g_assert_cmpuint(val
, ==, 1);
130 val
= qtest_readl(qts
, NRF51_TWI_BASE
+ NRF51_TWI_REG_RXD
);
131 qtest_writel(qts
, NRF51_TWI_BASE
+ NRF51_TWI_TASK_STOP
, 1);
136 static void test_microbit_i2c(void)
139 QTestState
*qts
= qtest_init("-M microbit");
141 /* We don't program pins/irqs but at least enable the device */
142 qtest_writel(qts
, NRF51_TWI_BASE
+ NRF51_TWI_REG_ENABLE
, 5);
144 /* MMA8653 magnetometer detection */
145 val
= i2c_read_byte(qts
, 0x3A, 0x0D);
146 g_assert_cmphex(val
, ==, 0x5A);
148 val
= i2c_read_byte(qts
, 0x3A, 0x0D);
149 g_assert_cmphex(val
, ==, 0x5A);
151 /* LSM303 accelerometer detection */
152 val
= i2c_read_byte(qts
, 0x3C, 0x4F);
153 g_assert_cmphex(val
, ==, 0x40);
155 qtest_writel(qts
, NRF51_TWI_BASE
+ NRF51_TWI_REG_ENABLE
, 0);
160 #define FLASH_SIZE (256 * NRF51_PAGE_SIZE)
162 static void fill_and_erase(QTestState
*qts
, hwaddr base
, hwaddr size
,
163 uint32_t address_reg
)
168 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x02);
169 qtest_writel(qts
, NRF51_NVMC_BASE
+ address_reg
, base
);
170 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x00);
173 for (i
= 0; i
< size
/ 4; i
++) {
174 g_assert_cmphex(qtest_readl(qts
, base
+ i
* 4), ==, 0xFFFFFFFF);
178 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x01);
179 for (i
= 0; i
< size
/ 4; i
++) {
180 qtest_writel(qts
, base
+ i
* 4, i
);
181 g_assert_cmpuint(qtest_readl(qts
, base
+ i
* 4), ==, i
);
183 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x00);
186 static void test_nrf51_nvmc(void)
190 QTestState
*qts
= qtest_init("-M microbit");
192 /* Test always ready */
193 value
= qtest_readl(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_READY
);
194 g_assert_cmphex(value
& 0x01, ==, 0x01);
196 /* Test write-read config register */
197 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x03);
198 g_assert_cmpuint(qtest_readl(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
),
200 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x00);
201 g_assert_cmpuint(qtest_readl(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
),
205 fill_and_erase(qts
, NRF51_FLASH_BASE
, NRF51_PAGE_SIZE
,
206 NRF51_NVMC_ERASEPCR0
);
207 fill_and_erase(qts
, NRF51_FLASH_BASE
+ NRF51_PAGE_SIZE
,
208 NRF51_PAGE_SIZE
, NRF51_NVMC_ERASEPCR0
);
211 fill_and_erase(qts
, NRF51_FLASH_BASE
, NRF51_PAGE_SIZE
,
212 NRF51_NVMC_ERASEPCR1
);
213 fill_and_erase(qts
, NRF51_FLASH_BASE
+ NRF51_PAGE_SIZE
,
214 NRF51_PAGE_SIZE
, NRF51_NVMC_ERASEPCR1
);
217 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x02);
218 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_ERASEALL
, 0x01);
219 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x00);
221 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x01);
222 for (i
= 0; i
< FLASH_SIZE
/ 4; i
++) {
223 qtest_writel(qts
, NRF51_FLASH_BASE
+ i
* 4, i
);
224 g_assert_cmpuint(qtest_readl(qts
, NRF51_FLASH_BASE
+ i
* 4), ==, i
);
226 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x00);
228 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x02);
229 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_ERASEALL
, 0x01);
230 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x00);
232 for (i
= 0; i
< FLASH_SIZE
/ 4; i
++) {
233 g_assert_cmpuint(qtest_readl(qts
, NRF51_FLASH_BASE
+ i
* 4),
238 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x02);
239 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_ERASEUICR
, 0x01);
240 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x00);
242 for (i
= 0; i
< NRF51_UICR_SIZE
/ 4; i
++) {
243 g_assert_cmpuint(qtest_readl(qts
, NRF51_UICR_BASE
+ i
* 4),
247 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x01);
248 for (i
= 0; i
< NRF51_UICR_SIZE
/ 4; i
++) {
249 qtest_writel(qts
, NRF51_UICR_BASE
+ i
* 4, i
);
250 g_assert_cmpuint(qtest_readl(qts
, NRF51_UICR_BASE
+ i
* 4), ==, i
);
252 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x00);
254 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x02);
255 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_ERASEUICR
, 0x01);
256 qtest_writel(qts
, NRF51_NVMC_BASE
+ NRF51_NVMC_CONFIG
, 0x00);
258 for (i
= 0; i
< NRF51_UICR_SIZE
/ 4; i
++) {
259 g_assert_cmpuint(qtest_readl(qts
, NRF51_UICR_BASE
+ i
* 4),
266 static void test_nrf51_gpio(void)
269 uint32_t actual
, expected
;
274 } const reset_state
[] = {
275 {NRF51_GPIO_REG_OUT
, 0x00000000}, {NRF51_GPIO_REG_OUTSET
, 0x00000000},
276 {NRF51_GPIO_REG_OUTCLR
, 0x00000000}, {NRF51_GPIO_REG_IN
, 0x00000000},
277 {NRF51_GPIO_REG_DIR
, 0x00000000}, {NRF51_GPIO_REG_DIRSET
, 0x00000000},
278 {NRF51_GPIO_REG_DIRCLR
, 0x00000000}
281 QTestState
*qts
= qtest_init("-M microbit");
283 /* Check reset state */
284 for (i
= 0; i
< ARRAY_SIZE(reset_state
); i
++) {
285 expected
= reset_state
[i
].expected
;
286 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ reset_state
[i
].addr
);
287 g_assert_cmpuint(actual
, ==, expected
);
290 for (i
= 0; i
< NRF51_GPIO_PINS
; i
++) {
291 expected
= 0x00000002;
292 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+
293 NRF51_GPIO_REG_CNF_START
+ i
* 4);
294 g_assert_cmpuint(actual
, ==, expected
);
297 /* Check dir bit consistency between dir and cnf */
298 /* Check set via DIRSET */
299 expected
= 0x80000001;
300 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_DIRSET
, expected
);
301 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_DIR
);
302 g_assert_cmpuint(actual
, ==, expected
);
303 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
)
305 g_assert_cmphex(actual
, ==, 0x01);
306 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_END
) & 0x01;
307 g_assert_cmphex(actual
, ==, 0x01);
309 /* Check clear via DIRCLR */
310 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_DIRCLR
, 0x80000001);
311 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_DIR
);
312 g_assert_cmphex(actual
, ==, 0x00000000);
313 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
)
315 g_assert_cmphex(actual
, ==, 0x00);
316 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_END
) & 0x01;
317 g_assert_cmphex(actual
, ==, 0x00);
319 /* Check set via DIR */
320 expected
= 0x80000001;
321 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_DIR
, expected
);
322 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_DIR
);
323 g_assert_cmpuint(actual
, ==, expected
);
324 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
)
326 g_assert_cmphex(actual
, ==, 0x01);
327 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_END
) & 0x01;
328 g_assert_cmphex(actual
, ==, 0x01);
331 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_DIR
, 0x00000000);
333 /* Check Input propagates */
334 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
, 0x00);
335 qtest_set_irq_in(qts
, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
336 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_IN
) & 0x01;
337 g_assert_cmphex(actual
, ==, 0x00);
338 qtest_set_irq_in(qts
, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
339 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_IN
) & 0x01;
340 g_assert_cmphex(actual
, ==, 0x01);
341 qtest_set_irq_in(qts
, "/machine/nrf51", "unnamed-gpio-in", 0, -1);
342 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_IN
) & 0x01;
343 g_assert_cmphex(actual
, ==, 0x01);
344 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
, 0x02);
346 /* Check pull-up working */
347 qtest_set_irq_in(qts
, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
348 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
, 0b0000);
349 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_IN
) & 0x01;
350 g_assert_cmphex(actual
, ==, 0x00);
351 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
, 0b1110);
352 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_IN
) & 0x01;
353 g_assert_cmphex(actual
, ==, 0x01);
354 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
, 0x02);
356 /* Check pull-down working */
357 qtest_set_irq_in(qts
, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
358 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
, 0b0000);
359 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_IN
) & 0x01;
360 g_assert_cmphex(actual
, ==, 0x01);
361 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
, 0b0110);
362 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_IN
) & 0x01;
363 g_assert_cmphex(actual
, ==, 0x00);
364 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
, 0x02);
365 qtest_set_irq_in(qts
, "/machine/nrf51", "unnamed-gpio-in", 0, -1);
367 /* Check Output propagates */
368 qtest_irq_intercept_out(qts
, "/machine/nrf51");
369 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
, 0b0011);
370 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_OUTSET
, 0x01);
371 g_assert_true(qtest_get_irq(qts
, 0));
372 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_OUTCLR
, 0x01);
373 g_assert_false(qtest_get_irq(qts
, 0));
375 /* Check self-stimulation */
376 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
, 0b01);
377 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_OUTSET
, 0x01);
378 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_IN
) & 0x01;
379 g_assert_cmphex(actual
, ==, 0x01);
381 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_OUTCLR
, 0x01);
382 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_IN
) & 0x01;
383 g_assert_cmphex(actual
, ==, 0x00);
386 * Check short-circuit - generates an guest_error which must be checked
387 * manually as long as qtest can not scan qemu_log messages
389 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
, 0b01);
390 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_OUTSET
, 0x01);
391 qtest_set_irq_in(qts
, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
396 static void test_nrf51_gpio_detect(void)
398 QTestState
*qts
= qtest_init("-M microbit");
401 /* Connect input buffer on pins 1-7, configure SENSE for high level */
402 for (i
= 1; i
<= 7; i
++) {
403 qtest_writel(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_CNF_START
+ i
* 4,
404 deposit32(0, 16, 2, 2));
407 qtest_irq_intercept_out_named(qts
, "/machine/nrf51/gpio", "detect");
409 for (i
= 1; i
<= 7; i
++) {
411 qtest_set_irq_in(qts
, "/machine/nrf51", "unnamed-gpio-in", i
, 1);
412 uint32_t actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_IN
);
413 g_assert_cmphex(actual
, ==, 1 << i
);
415 /* Check that DETECT is high */
416 g_assert_true(qtest_get_irq(qts
, 0));
418 /* Set pin low, check that DETECT goes low. */
419 qtest_set_irq_in(qts
, "/machine/nrf51", "unnamed-gpio-in", i
, 0);
420 actual
= qtest_readl(qts
, NRF51_GPIO_BASE
+ NRF51_GPIO_REG_IN
);
421 g_assert_cmphex(actual
, ==, 0x0);
422 g_assert_false(qtest_get_irq(qts
, 0));
425 /* Set pin 0 high, check that DETECT doesn't fire */
426 qtest_set_irq_in(qts
, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
427 g_assert_false(qtest_get_irq(qts
, 0));
428 qtest_set_irq_in(qts
, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
430 /* Set pins 1, 2, and 3 high, then set 3 low. Check DETECT is still high */
431 for (i
= 1; i
<= 3; i
++) {
432 qtest_set_irq_in(qts
, "/machine/nrf51", "unnamed-gpio-in", i
, 1);
434 g_assert_true(qtest_get_irq(qts
, 0));
435 qtest_set_irq_in(qts
, "/machine/nrf51", "unnamed-gpio-in", 3, 0);
436 g_assert_true(qtest_get_irq(qts
, 0));
441 static void timer_task(QTestState
*qts
, hwaddr task
)
443 qtest_writel(qts
, NRF51_TIMER_BASE
+ task
, NRF51_TRIGGER_TASK
);
446 static void timer_clear_event(QTestState
*qts
, hwaddr event
)
448 qtest_writel(qts
, NRF51_TIMER_BASE
+ event
, NRF51_EVENT_CLEAR
);
451 static void timer_set_bitmode(QTestState
*qts
, uint8_t mode
)
453 qtest_writel(qts
, NRF51_TIMER_BASE
+ NRF51_TIMER_REG_BITMODE
, mode
);
456 static void timer_set_prescaler(QTestState
*qts
, uint8_t prescaler
)
458 qtest_writel(qts
, NRF51_TIMER_BASE
+ NRF51_TIMER_REG_PRESCALER
, prescaler
);
461 static void timer_set_cc(QTestState
*qts
, size_t idx
, uint32_t value
)
463 qtest_writel(qts
, NRF51_TIMER_BASE
+ NRF51_TIMER_REG_CC0
+ idx
* 4, value
);
466 static void timer_assert_events(QTestState
*qts
, uint32_t ev0
, uint32_t ev1
,
467 uint32_t ev2
, uint32_t ev3
)
469 g_assert(qtest_readl(qts
, NRF51_TIMER_BASE
+ NRF51_TIMER_EVENT_COMPARE_0
)
471 g_assert(qtest_readl(qts
, NRF51_TIMER_BASE
+ NRF51_TIMER_EVENT_COMPARE_1
)
473 g_assert(qtest_readl(qts
, NRF51_TIMER_BASE
+ NRF51_TIMER_EVENT_COMPARE_2
)
475 g_assert(qtest_readl(qts
, NRF51_TIMER_BASE
+ NRF51_TIMER_EVENT_COMPARE_3
)
479 static void test_nrf51_timer(void)
481 uint32_t steps_to_overflow
= 408;
482 QTestState
*qts
= qtest_init("-M microbit");
485 timer_task(qts
, NRF51_TIMER_TASK_STOP
);
486 timer_task(qts
, NRF51_TIMER_TASK_CLEAR
);
488 timer_clear_event(qts
, NRF51_TIMER_EVENT_COMPARE_0
);
489 timer_clear_event(qts
, NRF51_TIMER_EVENT_COMPARE_1
);
490 timer_clear_event(qts
, NRF51_TIMER_EVENT_COMPARE_2
);
491 timer_clear_event(qts
, NRF51_TIMER_EVENT_COMPARE_3
);
493 timer_set_bitmode(qts
, NRF51_TIMER_WIDTH_16
); /* 16 MHz Timer */
494 timer_set_prescaler(qts
, 0);
495 /* Swept over, during the first step */
496 timer_set_cc(qts
, 0, 2);
497 /* Barely miss, after the second step */
498 timer_set_cc(qts
, 1, 162);
499 /* Spot on, after the third step */
500 timer_set_cc(qts
, 2, 480);
502 timer_assert_events(qts
, 0, 0, 0, 0);
504 timer_task(qts
, NRF51_TIMER_TASK_START
);
505 qtest_clock_step(qts
, 10000);
506 timer_assert_events(qts
, 1, 0, 0, 0);
508 /* Swept over on first overflow */
509 timer_set_cc(qts
, 3, 114);
511 qtest_clock_step(qts
, 10000);
512 timer_assert_events(qts
, 1, 1, 0, 0);
514 qtest_clock_step(qts
, 10000);
515 timer_assert_events(qts
, 1, 1, 1, 0);
517 /* Wrap time until internal counter overflows */
518 while (steps_to_overflow
--) {
519 timer_assert_events(qts
, 1, 1, 1, 0);
520 qtest_clock_step(qts
, 10000);
523 timer_assert_events(qts
, 1, 1, 1, 1);
525 timer_clear_event(qts
, NRF51_TIMER_EVENT_COMPARE_0
);
526 timer_clear_event(qts
, NRF51_TIMER_EVENT_COMPARE_1
);
527 timer_clear_event(qts
, NRF51_TIMER_EVENT_COMPARE_2
);
528 timer_clear_event(qts
, NRF51_TIMER_EVENT_COMPARE_3
);
529 timer_assert_events(qts
, 0, 0, 0, 0);
531 timer_task(qts
, NRF51_TIMER_TASK_STOP
);
533 /* Test Proposal: Stop/Shutdown */
534 /* Test Proposal: Shortcut Compare -> Clear */
535 /* Test Proposal: Shortcut Compare -> Stop */
536 /* Test Proposal: Counter Mode */
541 int main(int argc
, char **argv
)
543 g_test_init(&argc
, &argv
, NULL
);
545 qtest_add_func("/microbit/nrf51/uart", test_nrf51_uart
);
546 qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio
);
547 qtest_add_func("/microbit/nrf51/gpio_detect", test_nrf51_gpio_detect
);
548 qtest_add_func("/microbit/nrf51/nvmc", test_nrf51_nvmc
);
549 qtest_add_func("/microbit/nrf51/timer", test_nrf51_timer
);
550 qtest_add_func("/microbit/microbit/i2c", test_microbit_i2c
);