cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

microbit-test.c (18362B)


      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 "libqos/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(write(sock_fd, in, in_len) == 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(write(sock_fd, "c", 1) == 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(read(sock_fd, s, 10) == 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(read(sock_fd, s, 10) == 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 in first step */
    451    timer_set_cc(qts, 0, 2);
    452    /* Barely miss on first step */
    453    timer_set_cc(qts, 1, 162);
    454    /* Spot on on 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}