qemu/tests/qtest/microbit-test.c
<<
>>
Prefs
   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
  28static 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
  49static 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
  63static 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
  74static 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 */
 116static 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
 136static 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
 162static 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
 186static 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
 266static 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
 396static void timer_task(QTestState *qts, hwaddr task)
 397{
 398    qtest_writel(qts, NRF51_TIMER_BASE + task, NRF51_TRIGGER_TASK);
 399}
 400
 401static void timer_clear_event(QTestState *qts, hwaddr event)
 402{
 403    qtest_writel(qts, NRF51_TIMER_BASE + event, NRF51_EVENT_CLEAR);
 404}
 405
 406static void timer_set_bitmode(QTestState *qts, uint8_t mode)
 407{
 408    qtest_writel(qts, NRF51_TIMER_BASE + NRF51_TIMER_REG_BITMODE, mode);
 409}
 410
 411static void timer_set_prescaler(QTestState *qts, uint8_t prescaler)
 412{
 413    qtest_writel(qts, NRF51_TIMER_BASE + NRF51_TIMER_REG_PRESCALER, prescaler);
 414}
 415
 416static void timer_set_cc(QTestState *qts, size_t idx, uint32_t value)
 417{
 418    qtest_writel(qts, NRF51_TIMER_BASE + NRF51_TIMER_REG_CC0 + idx * 4, value);
 419}
 420
 421static void timer_assert_events(QTestState *qts, uint32_t ev0, uint32_t ev1,
 422                                uint32_t ev2, uint32_t ev3)
 423{
 424    g_assert(qtest_readl(qts, NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_0)
 425             == ev0);
 426    g_assert(qtest_readl(qts, NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_1)
 427             == ev1);
 428    g_assert(qtest_readl(qts, NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_2)
 429             == ev2);
 430    g_assert(qtest_readl(qts, NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_3)
 431             == ev3);
 432}
 433
 434static void test_nrf51_timer(void)
 435{
 436    uint32_t steps_to_overflow = 408;
 437    QTestState *qts = qtest_init("-M microbit");
 438
 439    /* Compare Match */
 440    timer_task(qts, NRF51_TIMER_TASK_STOP);
 441    timer_task(qts, NRF51_TIMER_TASK_CLEAR);
 442
 443    timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_0);
 444    timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_1);
 445    timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_2);
 446    timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_3);
 447
 448    timer_set_bitmode(qts, NRF51_TIMER_WIDTH_16); /* 16 MHz Timer */
 449    timer_set_prescaler(qts, 0);
 450    /* Swept over, during the first step */
 451    timer_set_cc(qts, 0, 2);
 452    /* Barely miss, after the second step */
 453    timer_set_cc(qts, 1, 162);
 454    /* Spot on, after the third step */
 455    timer_set_cc(qts, 2, 480);
 456
 457    timer_assert_events(qts, 0, 0, 0, 0);
 458
 459    timer_task(qts, NRF51_TIMER_TASK_START);
 460    qtest_clock_step(qts, 10000);
 461    timer_assert_events(qts, 1, 0, 0, 0);
 462
 463    /* Swept over on first overflow */
 464    timer_set_cc(qts, 3, 114);
 465
 466    qtest_clock_step(qts, 10000);
 467    timer_assert_events(qts, 1, 1, 0, 0);
 468
 469    qtest_clock_step(qts, 10000);
 470    timer_assert_events(qts, 1, 1, 1, 0);
 471
 472    /* Wrap time until internal counter overflows */
 473    while (steps_to_overflow--) {
 474        timer_assert_events(qts, 1, 1, 1, 0);
 475        qtest_clock_step(qts, 10000);
 476    }
 477
 478    timer_assert_events(qts, 1, 1, 1, 1);
 479
 480    timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_0);
 481    timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_1);
 482    timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_2);
 483    timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_3);
 484    timer_assert_events(qts, 0, 0, 0, 0);
 485
 486    timer_task(qts, NRF51_TIMER_TASK_STOP);
 487
 488    /* Test Proposal: Stop/Shutdown */
 489    /* Test Proposal: Shortcut Compare -> Clear */
 490    /* Test Proposal: Shortcut Compare -> Stop */
 491    /* Test Proposal: Counter Mode */
 492
 493    qtest_quit(qts);
 494}
 495
 496int main(int argc, char **argv)
 497{
 498    g_test_init(&argc, &argv, NULL);
 499
 500    qtest_add_func("/microbit/nrf51/uart", test_nrf51_uart);
 501    qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio);
 502    qtest_add_func("/microbit/nrf51/nvmc", test_nrf51_nvmc);
 503    qtest_add_func("/microbit/nrf51/timer", test_nrf51_timer);
 504    qtest_add_func("/microbit/microbit/i2c", test_microbit_i2c);
 505
 506    return g_test_run();
 507}
 508