2
0

microbit-test.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  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. #include "qemu/osdep.h"
  16. #include "exec/hwaddr.h"
  17. #include "libqtest.h"
  18. #include "hw/arm/nrf51.h"
  19. #include "hw/char/nrf51_uart.h"
  20. #include "hw/gpio/nrf51_gpio.h"
  21. #include "hw/nvram/nrf51_nvm.h"
  22. #include "hw/timer/nrf51_timer.h"
  23. #include "hw/i2c/microbit_i2c.h"
  24. static bool uart_wait_for_event(QTestState *qts, uint32_t event_addr)
  25. {
  26. time_t now, start = time(NULL);
  27. while (true) {
  28. if (qtest_readl(qts, event_addr) == 1) {
  29. qtest_writel(qts, event_addr, 0x00);
  30. return true;
  31. }
  32. /* Wait at most 10 minutes */
  33. now = time(NULL);
  34. if (now - start > 600) {
  35. break;
  36. }
  37. g_usleep(10000);
  38. }
  39. return false;
  40. }
  41. static void uart_rw_to_rxd(QTestState *qts, int sock_fd, const char *in,
  42. char *out)
  43. {
  44. int i, in_len = strlen(in);
  45. g_assert_true(write(sock_fd, in, in_len) == in_len);
  46. for (i = 0; i < in_len; i++) {
  47. g_assert_true(uart_wait_for_event(qts, NRF51_UART_BASE +
  48. A_UART_RXDRDY));
  49. out[i] = qtest_readl(qts, NRF51_UART_BASE + A_UART_RXD);
  50. }
  51. out[i] = '\0';
  52. }
  53. static void uart_w_to_txd(QTestState *qts, const char *in)
  54. {
  55. int i, in_len = strlen(in);
  56. for (i = 0; i < in_len; i++) {
  57. qtest_writel(qts, NRF51_UART_BASE + A_UART_TXD, in[i]);
  58. g_assert_true(uart_wait_for_event(qts, NRF51_UART_BASE +
  59. A_UART_TXDRDY));
  60. }
  61. }
  62. static void test_nrf51_uart(void)
  63. {
  64. int sock_fd;
  65. char s[10];
  66. QTestState *qts = qtest_init_with_serial("-M microbit", &sock_fd);
  67. g_assert_true(write(sock_fd, "c", 1) == 1);
  68. g_assert_cmphex(qtest_readl(qts, NRF51_UART_BASE + A_UART_RXD), ==, 0x00);
  69. qtest_writel(qts, NRF51_UART_BASE + A_UART_ENABLE, 0x04);
  70. qtest_writel(qts, NRF51_UART_BASE + A_UART_STARTRX, 0x01);
  71. g_assert_true(uart_wait_for_event(qts, NRF51_UART_BASE + A_UART_RXDRDY));
  72. qtest_writel(qts, NRF51_UART_BASE + A_UART_RXDRDY, 0x00);
  73. g_assert_cmphex(qtest_readl(qts, NRF51_UART_BASE + A_UART_RXD), ==, 'c');
  74. qtest_writel(qts, NRF51_UART_BASE + A_UART_INTENSET, 0x04);
  75. g_assert_cmphex(qtest_readl(qts, NRF51_UART_BASE + A_UART_INTEN), ==, 0x04);
  76. qtest_writel(qts, NRF51_UART_BASE + A_UART_INTENCLR, 0x04);
  77. g_assert_cmphex(qtest_readl(qts, NRF51_UART_BASE + A_UART_INTEN), ==, 0x00);
  78. uart_rw_to_rxd(qts, sock_fd, "hello", s);
  79. g_assert_true(memcmp(s, "hello", 5) == 0);
  80. qtest_writel(qts, NRF51_UART_BASE + A_UART_STARTTX, 0x01);
  81. uart_w_to_txd(qts, "d");
  82. g_assert_true(read(sock_fd, s, 10) == 1);
  83. g_assert_cmphex(s[0], ==, 'd');
  84. qtest_writel(qts, NRF51_UART_BASE + A_UART_SUSPEND, 0x01);
  85. qtest_writel(qts, NRF51_UART_BASE + A_UART_TXD, 'h');
  86. qtest_writel(qts, NRF51_UART_BASE + A_UART_STARTTX, 0x01);
  87. uart_w_to_txd(qts, "world");
  88. g_assert_true(read(sock_fd, s, 10) == 5);
  89. g_assert_true(memcmp(s, "world", 5) == 0);
  90. close(sock_fd);
  91. qtest_quit(qts);
  92. }
  93. /* Read a byte from I2C device at @addr from register @reg */
  94. static uint32_t i2c_read_byte(QTestState *qts, uint32_t addr, uint32_t reg)
  95. {
  96. uint32_t val;
  97. qtest_writel(qts, NRF51_TWI_BASE + NRF51_TWI_REG_ADDRESS, addr);
  98. qtest_writel(qts, NRF51_TWI_BASE + NRF51_TWI_TASK_STARTTX, 1);
  99. qtest_writel(qts, NRF51_TWI_BASE + NRF51_TWI_REG_TXD, reg);
  100. val = qtest_readl(qts, NRF51_TWI_BASE + NRF51_TWI_EVENT_TXDSENT);
  101. g_assert_cmpuint(val, ==, 1);
  102. qtest_writel(qts, NRF51_TWI_BASE + NRF51_TWI_TASK_STOP, 1);
  103. qtest_writel(qts, NRF51_TWI_BASE + NRF51_TWI_TASK_STARTRX, 1);
  104. val = qtest_readl(qts, NRF51_TWI_BASE + NRF51_TWI_EVENT_RXDREADY);
  105. g_assert_cmpuint(val, ==, 1);
  106. val = qtest_readl(qts, NRF51_TWI_BASE + NRF51_TWI_REG_RXD);
  107. qtest_writel(qts, NRF51_TWI_BASE + NRF51_TWI_TASK_STOP, 1);
  108. return val;
  109. }
  110. static void test_microbit_i2c(void)
  111. {
  112. uint32_t val;
  113. QTestState *qts = qtest_init("-M microbit");
  114. /* We don't program pins/irqs but at least enable the device */
  115. qtest_writel(qts, NRF51_TWI_BASE + NRF51_TWI_REG_ENABLE, 5);
  116. /* MMA8653 magnetometer detection */
  117. val = i2c_read_byte(qts, 0x3A, 0x0D);
  118. g_assert_cmpuint(val, ==, 0x5A);
  119. val = i2c_read_byte(qts, 0x3A, 0x0D);
  120. g_assert_cmpuint(val, ==, 0x5A);
  121. /* LSM303 accelerometer detection */
  122. val = i2c_read_byte(qts, 0x3C, 0x4F);
  123. g_assert_cmpuint(val, ==, 0x40);
  124. qtest_writel(qts, NRF51_TWI_BASE + NRF51_TWI_REG_ENABLE, 0);
  125. qtest_quit(qts);
  126. }
  127. #define FLASH_SIZE (256 * NRF51_PAGE_SIZE)
  128. static void fill_and_erase(QTestState *qts, hwaddr base, hwaddr size,
  129. uint32_t address_reg)
  130. {
  131. hwaddr i;
  132. /* Erase Page */
  133. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
  134. qtest_writel(qts, NRF51_NVMC_BASE + address_reg, base);
  135. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
  136. /* Check memory */
  137. for (i = 0; i < size / 4; i++) {
  138. g_assert_cmpuint(qtest_readl(qts, base + i * 4), ==, 0xFFFFFFFF);
  139. }
  140. /* Fill memory */
  141. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x01);
  142. for (i = 0; i < size / 4; i++) {
  143. qtest_writel(qts, base + i * 4, i);
  144. g_assert_cmpuint(qtest_readl(qts, base + i * 4), ==, i);
  145. }
  146. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
  147. }
  148. static void test_nrf51_nvmc(void)
  149. {
  150. uint32_t value;
  151. hwaddr i;
  152. QTestState *qts = qtest_init("-M microbit");
  153. /* Test always ready */
  154. value = qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_READY);
  155. g_assert_cmpuint(value & 0x01, ==, 0x01);
  156. /* Test write-read config register */
  157. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x03);
  158. g_assert_cmpuint(qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG),
  159. ==, 0x03);
  160. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
  161. g_assert_cmpuint(qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG),
  162. ==, 0x00);
  163. /* Test PCR0 */
  164. fill_and_erase(qts, NRF51_FLASH_BASE, NRF51_PAGE_SIZE,
  165. NRF51_NVMC_ERASEPCR0);
  166. fill_and_erase(qts, NRF51_FLASH_BASE + NRF51_PAGE_SIZE,
  167. NRF51_PAGE_SIZE, NRF51_NVMC_ERASEPCR0);
  168. /* Test PCR1 */
  169. fill_and_erase(qts, NRF51_FLASH_BASE, NRF51_PAGE_SIZE,
  170. NRF51_NVMC_ERASEPCR1);
  171. fill_and_erase(qts, NRF51_FLASH_BASE + NRF51_PAGE_SIZE,
  172. NRF51_PAGE_SIZE, NRF51_NVMC_ERASEPCR1);
  173. /* Erase all */
  174. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
  175. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEALL, 0x01);
  176. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
  177. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x01);
  178. for (i = 0; i < FLASH_SIZE / 4; i++) {
  179. qtest_writel(qts, NRF51_FLASH_BASE + i * 4, i);
  180. g_assert_cmpuint(qtest_readl(qts, NRF51_FLASH_BASE + i * 4), ==, i);
  181. }
  182. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
  183. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
  184. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEALL, 0x01);
  185. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
  186. for (i = 0; i < FLASH_SIZE / 4; i++) {
  187. g_assert_cmpuint(qtest_readl(qts, NRF51_FLASH_BASE + i * 4),
  188. ==, 0xFFFFFFFF);
  189. }
  190. /* Erase UICR */
  191. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
  192. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEUICR, 0x01);
  193. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
  194. for (i = 0; i < NRF51_UICR_SIZE / 4; i++) {
  195. g_assert_cmpuint(qtest_readl(qts, NRF51_UICR_BASE + i * 4),
  196. ==, 0xFFFFFFFF);
  197. }
  198. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x01);
  199. for (i = 0; i < NRF51_UICR_SIZE / 4; i++) {
  200. qtest_writel(qts, NRF51_UICR_BASE + i * 4, i);
  201. g_assert_cmpuint(qtest_readl(qts, NRF51_UICR_BASE + i * 4), ==, i);
  202. }
  203. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
  204. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x02);
  205. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_ERASEUICR, 0x01);
  206. qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x00);
  207. for (i = 0; i < NRF51_UICR_SIZE / 4; i++) {
  208. g_assert_cmpuint(qtest_readl(qts, NRF51_UICR_BASE + i * 4),
  209. ==, 0xFFFFFFFF);
  210. }
  211. qtest_quit(qts);
  212. }
  213. static void test_nrf51_gpio(void)
  214. {
  215. size_t i;
  216. uint32_t actual, expected;
  217. struct {
  218. hwaddr addr;
  219. uint32_t expected;
  220. } const reset_state[] = {
  221. {NRF51_GPIO_REG_OUT, 0x00000000}, {NRF51_GPIO_REG_OUTSET, 0x00000000},
  222. {NRF51_GPIO_REG_OUTCLR, 0x00000000}, {NRF51_GPIO_REG_IN, 0x00000000},
  223. {NRF51_GPIO_REG_DIR, 0x00000000}, {NRF51_GPIO_REG_DIRSET, 0x00000000},
  224. {NRF51_GPIO_REG_DIRCLR, 0x00000000}
  225. };
  226. QTestState *qts = qtest_init("-M microbit");
  227. /* Check reset state */
  228. for (i = 0; i < ARRAY_SIZE(reset_state); i++) {
  229. expected = reset_state[i].expected;
  230. actual = qtest_readl(qts, NRF51_GPIO_BASE + reset_state[i].addr);
  231. g_assert_cmpuint(actual, ==, expected);
  232. }
  233. for (i = 0; i < NRF51_GPIO_PINS; i++) {
  234. expected = 0x00000002;
  235. actual = qtest_readl(qts, NRF51_GPIO_BASE +
  236. NRF51_GPIO_REG_CNF_START + i * 4);
  237. g_assert_cmpuint(actual, ==, expected);
  238. }
  239. /* Check dir bit consistency between dir and cnf */
  240. /* Check set via DIRSET */
  241. expected = 0x80000001;
  242. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRSET, expected);
  243. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
  244. g_assert_cmpuint(actual, ==, expected);
  245. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START)
  246. & 0x01;
  247. g_assert_cmpuint(actual, ==, 0x01);
  248. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
  249. g_assert_cmpuint(actual, ==, 0x01);
  250. /* Check clear via DIRCLR */
  251. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRCLR, 0x80000001);
  252. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
  253. g_assert_cmpuint(actual, ==, 0x00000000);
  254. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START)
  255. & 0x01;
  256. g_assert_cmpuint(actual, ==, 0x00);
  257. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
  258. g_assert_cmpuint(actual, ==, 0x00);
  259. /* Check set via DIR */
  260. expected = 0x80000001;
  261. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, expected);
  262. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
  263. g_assert_cmpuint(actual, ==, expected);
  264. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START)
  265. & 0x01;
  266. g_assert_cmpuint(actual, ==, 0x01);
  267. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
  268. g_assert_cmpuint(actual, ==, 0x01);
  269. /* Reset DIR */
  270. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, 0x00000000);
  271. /* Check Input propagates */
  272. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x00);
  273. qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
  274. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
  275. g_assert_cmpuint(actual, ==, 0x00);
  276. qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
  277. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
  278. g_assert_cmpuint(actual, ==, 0x01);
  279. qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, -1);
  280. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
  281. g_assert_cmpuint(actual, ==, 0x01);
  282. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
  283. /* Check pull-up working */
  284. qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
  285. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000);
  286. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
  287. g_assert_cmpuint(actual, ==, 0x00);
  288. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b1110);
  289. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
  290. g_assert_cmpuint(actual, ==, 0x01);
  291. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
  292. /* Check pull-down working */
  293. qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
  294. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000);
  295. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
  296. g_assert_cmpuint(actual, ==, 0x01);
  297. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0110);
  298. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
  299. g_assert_cmpuint(actual, ==, 0x00);
  300. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
  301. qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, -1);
  302. /* Check Output propagates */
  303. qtest_irq_intercept_out(qts, "/machine/nrf51");
  304. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0011);
  305. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
  306. g_assert_true(qtest_get_irq(qts, 0));
  307. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01);
  308. g_assert_false(qtest_get_irq(qts, 0));
  309. /* Check self-stimulation */
  310. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01);
  311. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
  312. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
  313. g_assert_cmpuint(actual, ==, 0x01);
  314. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01);
  315. actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
  316. g_assert_cmpuint(actual, ==, 0x00);
  317. /*
  318. * Check short-circuit - generates an guest_error which must be checked
  319. * manually as long as qtest can not scan qemu_log messages
  320. */
  321. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01);
  322. qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
  323. qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
  324. qtest_quit(qts);
  325. }
  326. static void timer_task(QTestState *qts, hwaddr task)
  327. {
  328. qtest_writel(qts, NRF51_TIMER_BASE + task, NRF51_TRIGGER_TASK);
  329. }
  330. static void timer_clear_event(QTestState *qts, hwaddr event)
  331. {
  332. qtest_writel(qts, NRF51_TIMER_BASE + event, NRF51_EVENT_CLEAR);
  333. }
  334. static void timer_set_bitmode(QTestState *qts, uint8_t mode)
  335. {
  336. qtest_writel(qts, NRF51_TIMER_BASE + NRF51_TIMER_REG_BITMODE, mode);
  337. }
  338. static void timer_set_prescaler(QTestState *qts, uint8_t prescaler)
  339. {
  340. qtest_writel(qts, NRF51_TIMER_BASE + NRF51_TIMER_REG_PRESCALER, prescaler);
  341. }
  342. static void timer_set_cc(QTestState *qts, size_t idx, uint32_t value)
  343. {
  344. qtest_writel(qts, NRF51_TIMER_BASE + NRF51_TIMER_REG_CC0 + idx * 4, value);
  345. }
  346. static void timer_assert_events(QTestState *qts, uint32_t ev0, uint32_t ev1,
  347. uint32_t ev2, uint32_t ev3)
  348. {
  349. g_assert(qtest_readl(qts, NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_0)
  350. == ev0);
  351. g_assert(qtest_readl(qts, NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_1)
  352. == ev1);
  353. g_assert(qtest_readl(qts, NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_2)
  354. == ev2);
  355. g_assert(qtest_readl(qts, NRF51_TIMER_BASE + NRF51_TIMER_EVENT_COMPARE_3)
  356. == ev3);
  357. }
  358. static void test_nrf51_timer(void)
  359. {
  360. uint32_t steps_to_overflow = 408;
  361. QTestState *qts = qtest_init("-M microbit");
  362. /* Compare Match */
  363. timer_task(qts, NRF51_TIMER_TASK_STOP);
  364. timer_task(qts, NRF51_TIMER_TASK_CLEAR);
  365. timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_0);
  366. timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_1);
  367. timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_2);
  368. timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_3);
  369. timer_set_bitmode(qts, NRF51_TIMER_WIDTH_16); /* 16 MHz Timer */
  370. timer_set_prescaler(qts, 0);
  371. /* Swept over in first step */
  372. timer_set_cc(qts, 0, 2);
  373. /* Barely miss on first step */
  374. timer_set_cc(qts, 1, 162);
  375. /* Spot on on third step */
  376. timer_set_cc(qts, 2, 480);
  377. timer_assert_events(qts, 0, 0, 0, 0);
  378. timer_task(qts, NRF51_TIMER_TASK_START);
  379. qtest_clock_step(qts, 10000);
  380. timer_assert_events(qts, 1, 0, 0, 0);
  381. /* Swept over on first overflow */
  382. timer_set_cc(qts, 3, 114);
  383. qtest_clock_step(qts, 10000);
  384. timer_assert_events(qts, 1, 1, 0, 0);
  385. qtest_clock_step(qts, 10000);
  386. timer_assert_events(qts, 1, 1, 1, 0);
  387. /* Wrap time until internal counter overflows */
  388. while (steps_to_overflow--) {
  389. timer_assert_events(qts, 1, 1, 1, 0);
  390. qtest_clock_step(qts, 10000);
  391. }
  392. timer_assert_events(qts, 1, 1, 1, 1);
  393. timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_0);
  394. timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_1);
  395. timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_2);
  396. timer_clear_event(qts, NRF51_TIMER_EVENT_COMPARE_3);
  397. timer_assert_events(qts, 0, 0, 0, 0);
  398. timer_task(qts, NRF51_TIMER_TASK_STOP);
  399. /* Test Proposal: Stop/Shutdown */
  400. /* Test Proposal: Shortcut Compare -> Clear */
  401. /* Test Proposal: Shortcut Compare -> Stop */
  402. /* Test Proposal: Counter Mode */
  403. qtest_quit(qts);
  404. }
  405. int main(int argc, char **argv)
  406. {
  407. g_test_init(&argc, &argv, NULL);
  408. qtest_add_func("/microbit/nrf51/uart", test_nrf51_uart);
  409. qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio);
  410. qtest_add_func("/microbit/nrf51/nvmc", test_nrf51_nvmc);
  411. qtest_add_func("/microbit/nrf51/timer", test_nrf51_timer);
  412. qtest_add_func("/microbit/microbit/i2c", test_microbit_i2c);
  413. return g_test_run();
  414. }