1 /* 2 * QTest testcase for Microbit board using the Nordic Semiconductor nRF51 SoC. 3 * 4 * nRF51: 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 7 * 8 * Microbit Board: http://microbit.org/ 9 * 10 * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de> 11 * 12 * This code is licensed under the GPL version 2 or later. See 13 * the COPYING file in the top-level directory. 14 */ 15 16 17 #include "qemu/osdep.h" 18 #include "exec/hwaddr.h" 19 #include "libqtest.h" 20 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" 27 28 static bool uart_wait_for_event(QTestState *qts, uint32_t event_addr) 29 { 30 time_t now, start = time(NULL); 31 32 while (true) { 33 if (qtest_readl(qts, event_addr) == 1) { 34 qtest_writel(qts, event_addr, 0x00); 35 return true; 36 } 37 38 /* Wait at most 10 minutes */ 39 now = time(NULL); 40 if (now - start > 600) { 41 break; 42 } 43 g_usleep(10000); 44 } 45 46 return false; 47 } 48 49 static void uart_rw_to_rxd(QTestState *qts, int sock_fd, const char *in, 50 char *out) 51 { 52 int i, in_len = strlen(in); 53 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 + 57 A_UART_RXDRDY)); 58 out[i] = qtest_readl(qts, NRF51_UART_BASE + A_UART_RXD); 59 } 60 out[i] = '\0'; 61 } 62 63 static void uart_w_to_txd(QTestState *qts, const char *in) 64 { 65 int i, in_len = strlen(in); 66 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 + 70 A_UART_TXDRDY)); 71 } 72 } 73 74 static void test_nrf51_uart(void) 75 { 76 int sock_fd; 77 char s[10]; 78 QTestState *qts = qtest_init_with_serial("-M microbit", &sock_fd); 79 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); 82 83 qtest_writel(qts, NRF51_UART_BASE + A_UART_ENABLE, 0x04); 84 qtest_writel(qts, NRF51_UART_BASE + A_UART_STARTRX, 0x01); 85 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'); 89 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); 94 95 uart_rw_to_rxd(qts, sock_fd, "hello", s); 96 g_assert_true(memcmp(s, "hello", 5) == 0); 97 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'); 102 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); 109 110 close(sock_fd); 111 112 qtest_quit(qts); 113 } 114 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) 117 { 118 uint32_t val; 119 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); 126 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); 132 133 return val; 134 } 135 136 static void test_microbit_i2c(void) 137 { 138 uint32_t val; 139 QTestState *qts = qtest_init("-M microbit"); 140 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); 143 144 /* MMA8653 magnetometer detection */ 145 val = i2c_read_byte(qts, 0x3A, 0x0D); 146 g_assert_cmpuint(val, ==, 0x5A); 147 148 val = i2c_read_byte(qts, 0x3A, 0x0D); 149 g_assert_cmpuint(val, ==, 0x5A); 150 151 /* LSM303 accelerometer detection */ 152 val = i2c_read_byte(qts, 0x3C, 0x4F); 153 g_assert_cmpuint(val, ==, 0x40); 154 155 qtest_writel(qts, NRF51_TWI_BASE + NRF51_TWI_REG_ENABLE, 0); 156 157 qtest_quit(qts); 158 } 159 160 #define FLASH_SIZE (256 * NRF51_PAGE_SIZE) 161 162 static void fill_and_erase(QTestState *qts, hwaddr base, hwaddr size, 163 uint32_t address_reg) 164 { 165 hwaddr i; 166 167 /* Erase Page */ 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); 171 172 /* Check memory */ 173 for (i = 0; i < size / 4; i++) { 174 g_assert_cmpuint(qtest_readl(qts, base + i * 4), ==, 0xFFFFFFFF); 175 } 176 177 /* Fill memory */ 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); 182 } 183 qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00); 184 } 185 186 static void test_nrf51_nvmc(void) 187 { 188 uint32_t value; 189 hwaddr i; 190 QTestState *qts = qtest_init("-M microbit"); 191 192 /* Test always ready */ 193 value = qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_READY); 194 g_assert_cmpuint(value & 0x01, ==, 0x01); 195 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), 199 ==, 0x03); 200 qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00); 201 g_assert_cmpuint(qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG), 202 ==, 0x00); 203 204 /* Test PCR0 */ 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); 209 210 /* Test PCR1 */ 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); 215 216 /* Erase all */ 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); 220 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); 225 } 226 qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00); 227 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); 231 232 for (i = 0; i < FLASH_SIZE / 4; i++) { 233 g_assert_cmpuint(qtest_readl(qts, NRF51_FLASH_BASE + i * 4), 234 ==, 0xFFFFFFFF); 235 } 236 237 /* Erase UICR */ 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); 241 242 for (i = 0; i < NRF51_UICR_SIZE / 4; i++) { 243 g_assert_cmpuint(qtest_readl(qts, NRF51_UICR_BASE + i * 4), 244 ==, 0xFFFFFFFF); 245 } 246 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); 251 } 252 qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00); 253 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); 257 258 for (i = 0; i < NRF51_UICR_SIZE / 4; i++) { 259 g_assert_cmpuint(qtest_readl(qts, NRF51_UICR_BASE + i * 4), 260 ==, 0xFFFFFFFF); 261 } 262 263 qtest_quit(qts); 264 } 265 266 static void test_nrf51_gpio(void) 267 { 268 size_t i; 269 uint32_t actual, expected; 270 271 struct { 272 hwaddr addr; 273 uint32_t 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} 279 }; 280 281 QTestState *qts = qtest_init("-M microbit"); 282 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); 288 } 289 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); 295 } 296 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) 304 & 0x01; 305 g_assert_cmpuint(actual, ==, 0x01); 306 actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01; 307 g_assert_cmpuint(actual, ==, 0x01); 308 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_cmpuint(actual, ==, 0x00000000); 313 actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) 314 & 0x01; 315 g_assert_cmpuint(actual, ==, 0x00); 316 actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01; 317 g_assert_cmpuint(actual, ==, 0x00); 318 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) 325 & 0x01; 326 g_assert_cmpuint(actual, ==, 0x01); 327 actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01; 328 g_assert_cmpuint(actual, ==, 0x01); 329 330 /* Reset DIR */ 331 qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, 0x00000000); 332 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_cmpuint(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_cmpuint(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_cmpuint(actual, ==, 0x01); 344 qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02); 345 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_cmpuint(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_cmpuint(actual, ==, 0x01); 354 qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02); 355 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_cmpuint(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_cmpuint(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); 366 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)); 374 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_cmpuint(actual, ==, 0x01); 380 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_cmpuint(actual, ==, 0x00); 384 385 /* 386 * Check short-circuit - generates an guest_error which must be checked 387 * manually as long as qtest can not scan qemu_log messages 388 */ 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); 392 393 qtest_quit(qts); 394 } 395 396 static void test_nrf51_gpio_detect(void) 397 { 398 QTestState *qts = qtest_init("-M microbit"); 399 int i; 400 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)); 405 } 406 407 qtest_irq_intercept_out_named(qts, "/machine/nrf51/gpio", "detect"); 408 409 for (i = 1; i <= 7; i++) { 410 /* Set pin high */ 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_cmpuint(actual, ==, 1 << i); 414 415 /* Check that DETECT is high */ 416 g_assert_true(qtest_get_irq(qts, 0)); 417 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_cmpuint(actual, ==, 0x0); 422 g_assert_false(qtest_get_irq(qts, 0)); 423 } 424 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); 429 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); 433 } 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)); 437 438 qtest_quit(qts); 439 } 440 441 static void timer_task(QTestState *qts, hwaddr task) 442 { 443 qtest_writel(qts, NRF51_TIMER_BASE + task, NRF51_TRIGGER_TASK); 444 } 445 446 static void timer_clear_event(QTestState *qts, hwaddr event) 447 { 448 qtest_writel(qts, NRF51_TIMER_BASE + event, NRF51_EVENT_CLEAR); 449 } 450 451 static void timer_set_bitmode(QTestState *qts, uint8_t mode) 452 { 453 qtest_writel(qts, NRF51_TIMER_BASE + NRF51_TIMER_REG_BITMODE, mode); 454 } 455 456 static void timer_set_prescaler(QTestState *qts, uint8_t prescaler) 457 { 458 qtest_writel(qts, NRF51_TIMER_BASE + NRF51_TIMER_REG_PRESCALER, prescaler); 459 } 460 461 static void timer_set_cc(QTestState *qts, size_t idx, uint32_t value) 462 { 463 qtest_writel(qts, NRF51_TIMER_BASE + NRF51_TIMER_REG_CC0 + idx * 4, value); 464 } 465 466 static void timer_assert_events(QTestState *qts, uint32_t ev0, uint32_t ev1, 467 uint32_t ev2, uint32_t ev3) 468 { 469 g_assert(qtest_readl(qts, NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_0) 470 == ev0); 471 g_assert(qtest_readl(qts, NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_1) 472 == ev1); 473 g_assert(qtest_readl(qts, NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_2) 474 == ev2); 475 g_assert(qtest_readl(qts, NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_3) 476 == ev3); 477 } 478 479 static void test_nrf51_timer(void) 480 { 481 uint32_t steps_to_overflow = 408; 482 QTestState *qts = qtest_init("-M microbit"); 483 484 /* Compare Match */ 485 timer_task(qts, NRF51_TIMER_TASK_STOP); 486 timer_task(qts, NRF51_TIMER_TASK_CLEAR); 487 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); 492 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); 501 502 timer_assert_events(qts, 0, 0, 0, 0); 503 504 timer_task(qts, NRF51_TIMER_TASK_START); 505 qtest_clock_step(qts, 10000); 506 timer_assert_events(qts, 1, 0, 0, 0); 507 508 /* Swept over on first overflow */ 509 timer_set_cc(qts, 3, 114); 510 511 qtest_clock_step(qts, 10000); 512 timer_assert_events(qts, 1, 1, 0, 0); 513 514 qtest_clock_step(qts, 10000); 515 timer_assert_events(qts, 1, 1, 1, 0); 516 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); 521 } 522 523 timer_assert_events(qts, 1, 1, 1, 1); 524 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); 530 531 timer_task(qts, NRF51_TIMER_TASK_STOP); 532 533 /* Test Proposal: Stop/Shutdown */ 534 /* Test Proposal: Shortcut Compare -> Clear */ 535 /* Test Proposal: Shortcut Compare -> Stop */ 536 /* Test Proposal: Counter Mode */ 537 538 qtest_quit(qts); 539 } 540 541 int main(int argc, char **argv) 542 { 543 g_test_init(&argc, &argv, NULL); 544 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); 551 552 return g_test_run(); 553 } 554