Basic tests for nRF51 Timer Peripheral. Signed-off-by: Steffen Görtz <cont...@steffen-goertz.de> --- tests/microbit-test.c | 101 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+)
diff --git a/tests/microbit-test.c b/tests/microbit-test.c index e606221b58..f8731e7c00 100644 --- a/tests/microbit-test.c +++ b/tests/microbit-test.c @@ -21,6 +21,7 @@ #include "hw/arm/nrf51.h" #include "hw/nvram/nrf51_nvm.h" #include "hw/gpio/nrf51_gpio.h" +#include "hw/timer/nrf51_timer.h" #define FLASH_SIZE (256 * NRF51_PAGE_SIZE) @@ -239,6 +240,105 @@ static void test_nrf51_gpio(void) qtest_set_irq_in(global_qtest, "/machine/nrf51", "unnamed-gpio-in", 0, 0); } +static void timer_task(hwaddr task) +{ + writel(NRF51_TIMER_BASE + task, NRF51_TRIGGER_TASK); +} + +static void timer_clear_event(hwaddr event) +{ + writel(NRF51_TIMER_BASE + event, NRF51_EVENT_CLEAR); +} + +static void timer_set_bitmode(uint8_t mode) +{ + writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_BITMODE, mode); +} + +static void timer_set_prescaler(uint8_t prescaler) +{ + writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_PRESCALER, prescaler); +} + +static void timer_set_cc(size_t idx, uint32_t value) +{ + writel(NRF51_TIMER_BASE + NRF51_TIMER_REG_CC0 + idx * 4, value); +} + +static void timer_assert_events(uint32_t ev0, uint32_t ev1, uint32_t ev2, + uint32_t ev3) +{ + g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_0) == ev0); + g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_1) == ev1); + g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_2) == ev2); + g_assert(readl(NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_3) == ev3); +} + +static void test_nrf51_timer(void) +{ + int64_t prev_deadline, curr_deadline; + uint32_t steps_to_overflow = 405; + + /* Compare Match */ + timer_task(NRF51_TIMER_TASK_STOP); + timer_task(NRF51_TIMER_TASK_CLEAR); + + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_0); + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_1); + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_2); + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_3); + + timer_set_bitmode(NRF51_TIMER_WIDTH_16); + /* 16 MHz Timer */ + timer_set_prescaler(0); + /* Swept over in first step */ + timer_set_cc(0, 2); + /* Barely miss on first step */ + timer_set_cc(1, 162); + /* Spot on on third step */ + timer_set_cc(2, 483); + + timer_assert_events(0, 0, 0, 0); + + timer_task(NRF51_TIMER_TASK_START); + prev_deadline = clock_step_next(); + timer_assert_events(1, 0, 0, 0); + + /* Swept over on first overflow */ + timer_set_cc(3, 114); + + curr_deadline = clock_step_next(); + g_assert_cmpint(curr_deadline - prev_deadline, ==, 10000); + prev_deadline = curr_deadline; + timer_assert_events(1, 1, 0, 0); + + curr_deadline = clock_step_next(); + g_assert_cmpint(curr_deadline - prev_deadline, ==, 10000); + prev_deadline = curr_deadline; + timer_assert_events(1, 1, 1, 0); + + /* Wrap time until internal counter overflows */ + while (steps_to_overflow--) { + timer_assert_events(1, 1, 1, 0); + clock_step_next(); + } + + timer_assert_events(1, 1, 1, 1); + + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_0); + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_1); + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_2); + timer_clear_event(NRF51_TIMER_EVENT_COMPARE_3); + timer_assert_events(0, 0, 0, 0); + + timer_task(NRF51_TIMER_TASK_STOP); + + /* Test Proposal: Stop/Shutdown */ + /* Test Proposal: Shortcut Compare -> Clear */ + /* Test Proposal: Shortcut Compare -> Stop */ + /* Test Proposal: Counter Mode */ +} + int main(int argc, char **argv) { int ret; @@ -249,6 +349,7 @@ int main(int argc, char **argv) qtest_add_func("/microbit/nrf51/nvmc", test_nrf51_nvmc); qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio); + qtest_add_func("/microbit/nrf51/timer", test_nrf51_timer); ret = g_test_run(); -- 2.19.1