main.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. * Copyright (c) 2020, Alex Taradov <alex@taradov.com>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. The name of the author may not be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  20. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  23. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  24. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  25. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  26. * POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. /*- Includes ----------------------------------------------------------------*/
  29. #include <stdlib.h>
  30. #include <stdint.h>
  31. #include <stdbool.h>
  32. #include <stdalign.h>
  33. #include <string.h>
  34. #include "same70.h"
  35. #include "hal_gpio.h"
  36. #include "timer.h"
  37. #include "usb.h"
  38. #include "dap.h"
  39. #include "dap_config.h"
  40. /*- Definitions -------------------------------------------------------------*/
  41. #define STATUS_TIMEOUT 250 // ms
  42. HAL_GPIO_PIN(LED, D, 8)
  43. /*- Variables ---------------------------------------------------------------*/
  44. static uint8_t app_request_buffer[DAP_CONFIG_PACKET_COUNT][DAP_CONFIG_PACKET_SIZE];
  45. static bool app_request_valid[DAP_CONFIG_PACKET_COUNT];
  46. static bool app_request_pending;
  47. static int app_request_wr_ptr;
  48. static int app_request_rd_ptr;
  49. static uint8_t app_response_buffer[DAP_CONFIG_PACKET_COUNT][DAP_CONFIG_PACKET_SIZE];
  50. static bool app_response_valid[DAP_CONFIG_PACKET_COUNT];
  51. static bool app_response_pending;
  52. static int app_response_wr_ptr;
  53. static int app_response_rd_ptr;
  54. static Timer app_status_timer;
  55. static bool app_dap_event = false;
  56. /*- Prototypes --------------------------------------------------------------*/
  57. static void receive_request(void);
  58. /*- Implementations ---------------------------------------------------------*/
  59. //-----------------------------------------------------------------------------
  60. static void sys_init(void)
  61. {
  62. // Disable watchdog
  63. WDT->WDT_MR = WDT_MR_WDDIS;
  64. // Set flash wait states to maximum for 150 MHz operation
  65. EFC->EEFC_FMR = EEFC_FMR_FWS(6) | EEFC_FMR_CLOE;
  66. // Enable 12 MHz clock
  67. PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY;
  68. PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY | CKGR_MOR_MOSCSEL;
  69. while (!(PMC->PMC_SR & PMC_SR_MOSCSELS));
  70. // Setup PLL (12 MHz * 25 = 300 MHz)
  71. PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(25-1) |
  72. CKGR_PLLAR_PLLACOUNT(0x3f) | CKGR_PLLAR_DIVA(1);
  73. while (!(PMC->PMC_SR & PMC_SR_LOCKA));
  74. // Switch main clock to PLL (two step process)
  75. PMC->PMC_MCKR = PMC_MCKR_CSS_MAIN_CLK | PMC_MCKR_MDIV_PCK_DIV2;
  76. while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
  77. PMC->PMC_MCKR = PMC_MCKR_CSS_PLLA_CLK | PMC_MCKR_MDIV_PCK_DIV2;
  78. while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
  79. // Enable PIOA, PIOB, PIOC, PIOD and PIOE
  80. PMC->PMC_PCER0 = PMC_PCER0_PID10 | PMC_PCER0_PID11 | PMC_PCER0_PID12 |
  81. PMC_PCER0_PID16 | PMC_PCER0_PID17;
  82. // Disable altenate functions on some pins
  83. MATRIX->CCFG_SYSIO |= CCFG_SYSIO_SYSIO4 | CCFG_SYSIO_SYSIO5;
  84. SCB_EnableICache();
  85. }
  86. //-----------------------------------------------------------------------------
  87. __attribute__ ((noinline, section(".ramfunc")))
  88. static void read_uid(uint32_t *uid)
  89. {
  90. uint32_t *flash = (uint32_t *)IFLASH_ADDR;
  91. __disable_irq();
  92. EFC->EEFC_FMR |= EEFC_FMR_SCOD;
  93. EFC->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_STUI;
  94. while (EEFC_FSR_FRDY == (EFC->EEFC_FSR & EEFC_FSR_FRDY));
  95. for (int i = 0; i < 4; i++)
  96. uid[i] = flash[i];
  97. EFC->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_SPUI;
  98. while (0 == (EFC->EEFC_FSR & EEFC_FSR_FRDY));
  99. EFC->EEFC_FMR &= ~EEFC_FMR_SCOD;
  100. __enable_irq();
  101. }
  102. //-----------------------------------------------------------------------------
  103. static void serial_number_init(void)
  104. {
  105. alignas(4) uint8_t uid[16];
  106. uint64_t sn = 0;
  107. read_uid((uint32_t *)uid);
  108. for (int i = 0; i < 16; i++)
  109. sn ^= (uint64_t)(uid[i] - 0x30) << (i * 3);
  110. for (int i = 0; i < 12; i++)
  111. usb_serial_number[i] = "0123456789ABCDEF"[(sn >> (i * 4)) & 0xf];
  112. usb_serial_number[12] = 0;
  113. }
  114. //-----------------------------------------------------------------------------
  115. bool usb_class_handle_request(usb_request_t *request)
  116. {
  117. return usb_hid_handle_request(request);
  118. }
  119. //-----------------------------------------------------------------------------
  120. void usb_configuration_callback(int config)
  121. {
  122. app_request_pending = false;
  123. app_request_wr_ptr = 0;
  124. app_request_rd_ptr = 0;
  125. app_response_pending = false;
  126. app_response_wr_ptr = 0;
  127. app_response_rd_ptr = 0;
  128. for (int i = 0; i < DAP_CONFIG_PACKET_COUNT; i++)
  129. {
  130. app_request_valid[i] = false;
  131. app_response_valid[i] = false;
  132. }
  133. receive_request();
  134. (void)config;
  135. }
  136. //-----------------------------------------------------------------------------
  137. static void receive_request(void)
  138. {
  139. if (app_request_pending)
  140. return;
  141. if (app_request_valid[app_request_wr_ptr])
  142. return;
  143. app_request_pending = true;
  144. usb_hid_recv(app_request_buffer[app_request_wr_ptr], DAP_CONFIG_PACKET_SIZE);
  145. }
  146. //-----------------------------------------------------------------------------
  147. void usb_hid_recv_callback(int size)
  148. {
  149. if (dap_filter_request(app_request_buffer[app_request_wr_ptr]))
  150. {
  151. app_request_valid[app_request_wr_ptr] = true;
  152. app_request_wr_ptr = (app_request_wr_ptr + 1) % DAP_CONFIG_PACKET_COUNT;
  153. }
  154. app_request_pending = false;
  155. receive_request();
  156. (void)size;
  157. }
  158. //-----------------------------------------------------------------------------
  159. static void send_response(void)
  160. {
  161. if (app_response_pending)
  162. return;
  163. if (!app_response_valid[app_response_rd_ptr])
  164. return;
  165. app_response_pending = true;
  166. usb_hid_send(app_response_buffer[app_response_rd_ptr], DAP_CONFIG_PACKET_SIZE);
  167. }
  168. //-----------------------------------------------------------------------------
  169. void usb_hid_send_callback(void)
  170. {
  171. app_response_pending = false;
  172. app_response_valid[app_response_rd_ptr] = false;
  173. app_response_rd_ptr = (app_response_rd_ptr + 1) % DAP_CONFIG_PACKET_COUNT;
  174. send_response();
  175. }
  176. //-----------------------------------------------------------------------------
  177. static void dap_task(void)
  178. {
  179. if (!app_request_valid[app_request_rd_ptr])
  180. return;
  181. dap_process_request(app_request_buffer[app_request_rd_ptr], DAP_CONFIG_PACKET_SIZE,
  182. app_response_buffer[app_response_wr_ptr], DAP_CONFIG_PACKET_SIZE);
  183. app_response_valid[app_response_wr_ptr] = true;
  184. app_response_wr_ptr = (app_response_wr_ptr + 1) % DAP_CONFIG_PACKET_COUNT;
  185. send_response();
  186. app_request_valid[app_request_rd_ptr] = false;
  187. app_request_rd_ptr = (app_request_rd_ptr + 1) % DAP_CONFIG_PACKET_COUNT;
  188. receive_request();
  189. app_dap_event = true;
  190. }
  191. //-----------------------------------------------------------------------------
  192. static void status_timer_task(void)
  193. {
  194. if (!app_status_timer.expired)
  195. return;
  196. if (app_dap_event)
  197. HAL_GPIO_LED_toggle();
  198. else
  199. HAL_GPIO_LED_clr();
  200. app_dap_event = false;
  201. app_status_timer.expired = false;
  202. }
  203. //-----------------------------------------------------------------------------
  204. int main(void)
  205. {
  206. sys_init();
  207. timer_init();
  208. serial_number_init();
  209. usb_init();
  210. usb_hid_init();
  211. dap_init();
  212. app_status_timer.interval = STATUS_TIMEOUT;
  213. app_status_timer.repeat = true;
  214. timer_start(&app_status_timer);
  215. HAL_GPIO_LED_out();
  216. HAL_GPIO_LED_clr();
  217. while (1)
  218. {
  219. dap_task();
  220. status_timer_task();
  221. }
  222. return 0;
  223. }