117ff8e18SSteffen Görtz /* 217ff8e18SSteffen Görtz * QTest testcase for Microbit board using the Nordic Semiconductor nRF51 SoC. 317ff8e18SSteffen Görtz * 417ff8e18SSteffen Görtz * nRF51: 517ff8e18SSteffen Görtz * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.pdf 617ff8e18SSteffen Görtz * Product Spec: http://infocenter.nordicsemi.com/pdf/nRF51822_PS_v3.1.pdf 717ff8e18SSteffen Görtz * 817ff8e18SSteffen Görtz * Microbit Board: http://microbit.org/ 917ff8e18SSteffen Görtz * 1017ff8e18SSteffen Görtz * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de> 1117ff8e18SSteffen Görtz * 1217ff8e18SSteffen Görtz * This code is licensed under the GPL version 2 or later. See 1317ff8e18SSteffen Görtz * the COPYING file in the top-level directory. 1417ff8e18SSteffen Görtz */ 1517ff8e18SSteffen Görtz 1617ff8e18SSteffen Görtz 1717ff8e18SSteffen Görtz #include "qemu/osdep.h" 1817ff8e18SSteffen Görtz #include "exec/hwaddr.h" 1917ff8e18SSteffen Görtz #include "libqtest.h" 2017ff8e18SSteffen Görtz 2117ff8e18SSteffen Görtz #include "hw/arm/nrf51.h" 2217ff8e18SSteffen Görtz #include "hw/gpio/nrf51_gpio.h" 23*7ec543e4SSteffen Görtz #include "hw/timer/nrf51_timer.h" 2417ff8e18SSteffen Görtz 2517ff8e18SSteffen Görtz static void test_nrf51_gpio(void) 2617ff8e18SSteffen Görtz { 2717ff8e18SSteffen Görtz size_t i; 2817ff8e18SSteffen Görtz uint32_t actual, expected; 2917ff8e18SSteffen Görtz 3017ff8e18SSteffen Görtz struct { 3117ff8e18SSteffen Görtz hwaddr addr; 3217ff8e18SSteffen Görtz uint32_t expected; 3317ff8e18SSteffen Görtz } const reset_state[] = { 3417ff8e18SSteffen Görtz {NRF51_GPIO_REG_OUT, 0x00000000}, {NRF51_GPIO_REG_OUTSET, 0x00000000}, 3517ff8e18SSteffen Görtz {NRF51_GPIO_REG_OUTCLR, 0x00000000}, {NRF51_GPIO_REG_IN, 0x00000000}, 3617ff8e18SSteffen Görtz {NRF51_GPIO_REG_DIR, 0x00000000}, {NRF51_GPIO_REG_DIRSET, 0x00000000}, 3717ff8e18SSteffen Görtz {NRF51_GPIO_REG_DIRCLR, 0x00000000} 3817ff8e18SSteffen Görtz }; 3917ff8e18SSteffen Görtz 4017ff8e18SSteffen Görtz /* Check reset state */ 4117ff8e18SSteffen Görtz for (i = 0; i < ARRAY_SIZE(reset_state); i++) { 4217ff8e18SSteffen Görtz expected = reset_state[i].expected; 4317ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + reset_state[i].addr); 4417ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, expected); 4517ff8e18SSteffen Görtz } 4617ff8e18SSteffen Görtz 4717ff8e18SSteffen Görtz for (i = 0; i < NRF51_GPIO_PINS; i++) { 4817ff8e18SSteffen Görtz expected = 0x00000002; 4917ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START + i * 4); 5017ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, expected); 5117ff8e18SSteffen Görtz } 5217ff8e18SSteffen Görtz 5317ff8e18SSteffen Görtz /* Check dir bit consistency between dir and cnf */ 5417ff8e18SSteffen Görtz /* Check set via DIRSET */ 5517ff8e18SSteffen Görtz expected = 0x80000001; 5617ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRSET, expected); 5717ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR); 5817ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, expected); 5917ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01; 6017ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x01); 6117ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01; 6217ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x01); 6317ff8e18SSteffen Görtz 6417ff8e18SSteffen Görtz /* Check clear via DIRCLR */ 6517ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRCLR, 0x80000001); 6617ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR); 6717ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x00000000); 6817ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01; 6917ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x00); 7017ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01; 7117ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x00); 7217ff8e18SSteffen Görtz 7317ff8e18SSteffen Görtz /* Check set via DIR */ 7417ff8e18SSteffen Görtz expected = 0x80000001; 7517ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, expected); 7617ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR); 7717ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, expected); 7817ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START) & 0x01; 7917ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x01); 8017ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01; 8117ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x01); 8217ff8e18SSteffen Görtz 8317ff8e18SSteffen Görtz /* Reset DIR */ 8417ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, 0x00000000); 8517ff8e18SSteffen Görtz 8617ff8e18SSteffen Görtz /* Check Input propagates */ 8717ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x00); 8817ff8e18SSteffen Görtz qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0); 8917ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; 9017ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x00); 9117ff8e18SSteffen Görtz qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 1); 9217ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; 9317ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x01); 9417ff8e18SSteffen Görtz qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, -1); 9517ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; 9617ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x01); 9717ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02); 9817ff8e18SSteffen Görtz 9917ff8e18SSteffen Görtz /* Check pull-up working */ 10017ff8e18SSteffen Görtz qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0); 10117ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000); 10217ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; 10317ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x00); 10417ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b1110); 10517ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; 10617ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x01); 10717ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02); 10817ff8e18SSteffen Görtz 10917ff8e18SSteffen Görtz /* Check pull-down working */ 11017ff8e18SSteffen Görtz qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 1); 11117ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000); 11217ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; 11317ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x01); 11417ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0110); 11517ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; 11617ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x00); 11717ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02); 11817ff8e18SSteffen Görtz qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, -1); 11917ff8e18SSteffen Görtz 12017ff8e18SSteffen Görtz /* Check Output propagates */ 12117ff8e18SSteffen Görtz irq_intercept_out("/machine/nrf51"); 12217ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0011); 12317ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01); 12417ff8e18SSteffen Görtz g_assert_true(get_irq(0)); 12517ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01); 12617ff8e18SSteffen Görtz g_assert_false(get_irq(0)); 12717ff8e18SSteffen Görtz 12817ff8e18SSteffen Görtz /* Check self-stimulation */ 12917ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01); 13017ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01); 13117ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; 13217ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x01); 13317ff8e18SSteffen Görtz 13417ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01); 13517ff8e18SSteffen Görtz actual = readl(NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01; 13617ff8e18SSteffen Görtz g_assert_cmpuint(actual, ==, 0x00); 13717ff8e18SSteffen Görtz 13817ff8e18SSteffen Görtz /* 13917ff8e18SSteffen Görtz * Check short-circuit - generates an guest_error which must be checked 14017ff8e18SSteffen Görtz * manually as long as qtest can not scan qemu_log messages 14117ff8e18SSteffen Görtz */ 14217ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01); 14317ff8e18SSteffen Görtz writel(NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01); 14417ff8e18SSteffen Görtz qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0); 14517ff8e18SSteffen Görtz } 14617ff8e18SSteffen Görtz 147*7ec543e4SSteffen Görtz static void timer_task(hwaddr task) 148*7ec543e4SSteffen Görtz { 149*7ec543e4SSteffen Görtz writel(NRF51_TIMER_BASE + task, NRF51_TRIGGER_TASK); 150*7ec543e4SSteffen Görtz } 151*7ec543e4SSteffen Görtz 152*7ec543e4SSteffen Görtz static void timer_clear_event(hwaddr event) 153*7ec543e4SSteffen Görtz { 154*7ec543e4SSteffen Görtz writel(NRF51_TIMER_BASE + event, NRF51_EVENT_CLEAR); 155*7ec543e4SSteffen Görtz } 156*7ec543e4SSteffen Görtz 157*7ec543e4SSteffen Görtz static void timer_set_bitmode(uint8_t mode) 158*7ec543e4SSteffen Görtz { 159*7ec543e4SSteffen Görtz writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_BITMODE, mode); 160*7ec543e4SSteffen Görtz } 161*7ec543e4SSteffen Görtz 162*7ec543e4SSteffen Görtz static void timer_set_prescaler(uint8_t prescaler) 163*7ec543e4SSteffen Görtz { 164*7ec543e4SSteffen Görtz writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_PRESCALER, prescaler); 165*7ec543e4SSteffen Görtz } 166*7ec543e4SSteffen Görtz 167*7ec543e4SSteffen Görtz static void timer_set_cc(size_t idx, uint32_t value) 168*7ec543e4SSteffen Görtz { 169*7ec543e4SSteffen Görtz writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_CC0 + idx * 4, value); 170*7ec543e4SSteffen Görtz } 171*7ec543e4SSteffen Görtz 172*7ec543e4SSteffen Görtz static void timer_assert_events(uint32_t ev0, uint32_t ev1, uint32_t ev2, 173*7ec543e4SSteffen Görtz uint32_t ev3) 174*7ec543e4SSteffen Görtz { 175*7ec543e4SSteffen Görtz g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_0) == ev0); 176*7ec543e4SSteffen Görtz g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_1) == ev1); 177*7ec543e4SSteffen Görtz g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_2) == ev2); 178*7ec543e4SSteffen Görtz g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_3) == ev3); 179*7ec543e4SSteffen Görtz } 180*7ec543e4SSteffen Görtz 181*7ec543e4SSteffen Görtz static void test_nrf51_timer(void) 182*7ec543e4SSteffen Görtz { 183*7ec543e4SSteffen Görtz uint32_t steps_to_overflow = 408; 184*7ec543e4SSteffen Görtz 185*7ec543e4SSteffen Görtz /* Compare Match */ 186*7ec543e4SSteffen Görtz timer_task(NRF51_TIMER_TASK_STOP); 187*7ec543e4SSteffen Görtz timer_task(NRF51_TIMER_TASK_CLEAR); 188*7ec543e4SSteffen Görtz 189*7ec543e4SSteffen Görtz timer_clear_event(NRF51_TIMER_EVENT_COMPARE_0); 190*7ec543e4SSteffen Görtz timer_clear_event(NRF51_TIMER_EVENT_COMPARE_1); 191*7ec543e4SSteffen Görtz timer_clear_event(NRF51_TIMER_EVENT_COMPARE_2); 192*7ec543e4SSteffen Görtz timer_clear_event(NRF51_TIMER_EVENT_COMPARE_3); 193*7ec543e4SSteffen Görtz 194*7ec543e4SSteffen Görtz timer_set_bitmode(NRF51_TIMER_WIDTH_16); /* 16 MHz Timer */ 195*7ec543e4SSteffen Görtz timer_set_prescaler(0); 196*7ec543e4SSteffen Görtz /* Swept over in first step */ 197*7ec543e4SSteffen Görtz timer_set_cc(0, 2); 198*7ec543e4SSteffen Görtz /* Barely miss on first step */ 199*7ec543e4SSteffen Görtz timer_set_cc(1, 162); 200*7ec543e4SSteffen Görtz /* Spot on on third step */ 201*7ec543e4SSteffen Görtz timer_set_cc(2, 480); 202*7ec543e4SSteffen Görtz 203*7ec543e4SSteffen Görtz timer_assert_events(0, 0, 0, 0); 204*7ec543e4SSteffen Görtz 205*7ec543e4SSteffen Görtz timer_task(NRF51_TIMER_TASK_START); 206*7ec543e4SSteffen Görtz clock_step(10000); 207*7ec543e4SSteffen Görtz timer_assert_events(1, 0, 0, 0); 208*7ec543e4SSteffen Görtz 209*7ec543e4SSteffen Görtz /* Swept over on first overflow */ 210*7ec543e4SSteffen Görtz timer_set_cc(3, 114); 211*7ec543e4SSteffen Görtz 212*7ec543e4SSteffen Görtz clock_step(10000); 213*7ec543e4SSteffen Görtz timer_assert_events(1, 1, 0, 0); 214*7ec543e4SSteffen Görtz 215*7ec543e4SSteffen Görtz clock_step(10000); 216*7ec543e4SSteffen Görtz timer_assert_events(1, 1, 1, 0); 217*7ec543e4SSteffen Görtz 218*7ec543e4SSteffen Görtz /* Wrap time until internal counter overflows */ 219*7ec543e4SSteffen Görtz while (steps_to_overflow--) { 220*7ec543e4SSteffen Görtz timer_assert_events(1, 1, 1, 0); 221*7ec543e4SSteffen Görtz clock_step(10000); 222*7ec543e4SSteffen Görtz } 223*7ec543e4SSteffen Görtz 224*7ec543e4SSteffen Görtz timer_assert_events(1, 1, 1, 1); 225*7ec543e4SSteffen Görtz 226*7ec543e4SSteffen Görtz timer_clear_event(NRF51_TIMER_EVENT_COMPARE_0); 227*7ec543e4SSteffen Görtz timer_clear_event(NRF51_TIMER_EVENT_COMPARE_1); 228*7ec543e4SSteffen Görtz timer_clear_event(NRF51_TIMER_EVENT_COMPARE_2); 229*7ec543e4SSteffen Görtz timer_clear_event(NRF51_TIMER_EVENT_COMPARE_3); 230*7ec543e4SSteffen Görtz timer_assert_events(0, 0, 0, 0); 231*7ec543e4SSteffen Görtz 232*7ec543e4SSteffen Görtz timer_task(NRF51_TIMER_TASK_STOP); 233*7ec543e4SSteffen Görtz 234*7ec543e4SSteffen Görtz /* Test Proposal: Stop/Shutdown */ 235*7ec543e4SSteffen Görtz /* Test Proposal: Shortcut Compare -> Clear */ 236*7ec543e4SSteffen Görtz /* Test Proposal: Shortcut Compare -> Stop */ 237*7ec543e4SSteffen Görtz /* Test Proposal: Counter Mode */ 238*7ec543e4SSteffen Görtz } 239*7ec543e4SSteffen Görtz 24017ff8e18SSteffen Görtz int main(int argc, char **argv) 24117ff8e18SSteffen Görtz { 24217ff8e18SSteffen Görtz int ret; 24317ff8e18SSteffen Görtz 24417ff8e18SSteffen Görtz g_test_init(&argc, &argv, NULL); 24517ff8e18SSteffen Görtz 24617ff8e18SSteffen Görtz global_qtest = qtest_initf("-machine microbit"); 24717ff8e18SSteffen Görtz 24817ff8e18SSteffen Görtz qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio); 249*7ec543e4SSteffen Görtz qtest_add_func("/microbit/nrf51/timer", test_nrf51_timer); 25017ff8e18SSteffen Görtz 25117ff8e18SSteffen Görtz ret = g_test_run(); 25217ff8e18SSteffen Görtz 25317ff8e18SSteffen Görtz qtest_quit(global_qtest); 25417ff8e18SSteffen Görtz return ret; 25517ff8e18SSteffen Görtz } 256