testmode.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * testmode.c
  3. *
  4. * Written & released by Keir Fraser <keir.xen@gmail.com>
  5. *
  6. * This is free and unencumbered software released into the public domain.
  7. * See the file COPYING for more details, or visit <http://unlicense.org>.
  8. */
  9. #include "testmode.h"
  10. #define TEST_BIT(p,n) (!!((p)[(n)/8] & (1<<((n)&7))))
  11. #define SET_BIT(p,n) ((p)[(n)/8] |= (1<<((n)&7)))
  12. extern struct pin_mapping testmode_in_pins[];
  13. extern struct pin_mapping testmode_out_pins[];
  14. void testmode_get_option_bytes(void *buf);
  15. void testmode_wdat_osc_on(void);
  16. void testmode_wdat_osc_off(void);
  17. static void testmode_set_pin(unsigned int pin, bool_t level)
  18. {
  19. int rc;
  20. rc = write_mapped_pin(testmode_out_pins, pin, level);
  21. if (rc != ACK_OKAY)
  22. rc = write_mapped_pin(board_config->msel_pins, pin, level);
  23. if (rc != ACK_OKAY)
  24. rc = write_mapped_pin(board_config->user_pins, pin, level);
  25. }
  26. static bool_t testmode_get_pin(unsigned int pin)
  27. {
  28. bool_t level;
  29. int rc = read_mapped_pin(testmode_in_pins, pin, &level);
  30. if (rc != ACK_OKAY)
  31. level = FALSE;
  32. return level;
  33. }
  34. static void set_pins(uint8_t *pins)
  35. {
  36. int i;
  37. bool_t level;
  38. for (i = 0; i <= 34; i++) {
  39. level = TEST_BIT(pins, i);
  40. testmode_set_pin(i, level);
  41. }
  42. }
  43. static void get_pins(uint8_t *pins)
  44. {
  45. int i;
  46. bool_t level;
  47. for (i = 0; i <= 34; i++) {
  48. level = testmode_get_pin(i);
  49. if (level)
  50. SET_BIT(pins, i);
  51. }
  52. }
  53. static unsigned int testmode_test_headers(void)
  54. {
  55. int i, rc = TESTHEADER_success;
  56. bool_t keep_pa9_high = FALSE;
  57. #ifndef NDEBUG
  58. return rc;
  59. #endif
  60. #if MCU == AT32F4
  61. if (at32f4_series == AT32F415) {
  62. /* AT32F415: PA9 LOW trips OTG VbusBSen and drops the USB connection.
  63. * See Datasheet Table 5 Footnote 8. */
  64. keep_pa9_high = TRUE;
  65. }
  66. #endif
  67. /* Can RXI and TXO pull themselves up and down? */
  68. for (i = keep_pa9_high ? 1 : 0; i < 2; i++) {
  69. gpio_configure_pin(gpioa, 9+i, GPI_pull_down);
  70. delay_ms(1);
  71. rc++;
  72. if (gpio_read_pin(gpioa, 9+i) != LOW)
  73. goto out;
  74. gpio_configure_pin(gpioa, 9+i, GPI_pull_up);
  75. delay_ms(1);
  76. rc++;
  77. if (gpio_read_pin(gpioa, 9+i) != HIGH)
  78. goto out;
  79. }
  80. /* Are RXI and TXO shorted? */
  81. for (i = keep_pa9_high ? 1 : 0; i < 2; i++) {
  82. gpio_configure_pin(gpioa, 9+i, GPO_pushpull(IOSPD_LOW, LOW));
  83. delay_ms(1);
  84. rc++;
  85. if (gpio_read_pin(gpioa, 10-i) != HIGH)
  86. goto out;
  87. gpio_configure_pin(gpioa, 9+i, GPI_pull_up);
  88. }
  89. rc = TESTHEADER_success;
  90. out:
  91. for (i = 0; i < 2; i++)
  92. gpio_configure_pin(gpioa, 9+i, GPI_pull_up);
  93. return rc;
  94. }
  95. void testmode_process(void)
  96. {
  97. int len = ep_rx_ready(EP_RX);
  98. struct cmd cmd;
  99. struct rsp rsp;
  100. if (len < 0)
  101. return;
  102. len = min_t(int, len, 32);
  103. usb_read(EP_RX, &cmd, len);
  104. if (len < 32)
  105. return;
  106. memset(&rsp, 0, 32);
  107. switch (cmd.cmd) {
  108. case CMD_option_bytes: {
  109. testmode_get_option_bytes(rsp.u.opt);
  110. break;
  111. }
  112. case CMD_pins: {
  113. set_pins(cmd.u.pins);
  114. get_pins(rsp.u.pins);
  115. break;
  116. }
  117. case CMD_led: {
  118. act_led(!!cmd.u.pins[0]);
  119. break;
  120. }
  121. case CMD_test_headers: {
  122. rsp.u.x[0] = testmode_test_headers();
  123. break;
  124. }
  125. case CMD_wdat_osc_on: {
  126. testmode_wdat_osc_on();
  127. break;
  128. }
  129. case CMD_wdat_osc_off: {
  130. testmode_wdat_osc_off();
  131. break;
  132. }
  133. }
  134. usb_write(EP_TX, &rsp, 32);
  135. }
  136. /*
  137. * Local variables:
  138. * mode: C
  139. * c-file-style: "Linux"
  140. * c-basic-offset: 4
  141. * tab-width: 4
  142. * indent-tabs-mode: nil
  143. * End:
  144. */