sltb009a.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. /*
  2. * The MIT License (MIT)
  3. *
  4. * Copyright (c) 2021 Rafael Silva (@perigoso)
  5. * Copyright (c) 2021 Ha Thach (tinyusb.org)
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. *
  25. * This file is part of the TinyUSB stack.
  26. */
  27. #include "../board.h"
  28. #include "em_device.h"
  29. /*--------------------------------------------------------------------*/
  30. /* MACRO TYPEDEF CONSTANT ENUM */
  31. /*--------------------------------------------------------------------*/
  32. #define LED_PORT 0 // A
  33. #define LED_PIN_R 12 // 12
  34. #define LED_PIN_B 13 // 13
  35. #define LED_PIN_G 14 // 14
  36. #define LED_STATE_ON 0 // active-low
  37. #define BUTTON_PORT 3 // D
  38. #define BUTTON_PIN 5 // 5
  39. #define BUTTON_STATE_ACTIVE 0 // active-low
  40. /*--------------------------------------------------------------------*/
  41. /* Forward USB interrupt events to TinyUSB IRQ Handler */
  42. /*--------------------------------------------------------------------*/
  43. void USB_IRQHandler(void)
  44. {
  45. tud_int_handler(0);
  46. }
  47. /*--------------------------------------------------------------------*/
  48. /* Fault Handlers */
  49. /*--------------------------------------------------------------------*/
  50. void HardFault_Handler(void)
  51. {
  52. asm("bkpt");
  53. }
  54. void MemManage_Handler(void)
  55. {
  56. asm("bkpt");
  57. }
  58. void BusFault_Handler(void)
  59. {
  60. asm("bkpt");
  61. }
  62. void UsageFault_Handler(void)
  63. {
  64. asm("bkpt");
  65. }
  66. /*--------------------------------------------------------------------*/
  67. /* Startup */
  68. /*--------------------------------------------------------------------*/
  69. // Required by __libc_init_array in startup code if we are compiling using
  70. // -nostdlib/-nostartfiles.
  71. void _init(void)
  72. {
  73. }
  74. /*--------------------------------------------------------------------*/
  75. /* Initing Funcs */
  76. /*--------------------------------------------------------------------*/
  77. void emu_init(uint8_t immediate_switch)
  78. {
  79. EMU->PWRCTRL = (immediate_switch ? EMU_PWRCTRL_IMMEDIATEPWRSWITCH : 0) | EMU_PWRCTRL_REGPWRSEL_DVDD | EMU_PWRCTRL_ANASW_AVDD;
  80. }
  81. void emu_reg_init(float target_voltage)
  82. {
  83. if(target_voltage < 2300.f || target_voltage >= 3800.f)
  84. return;
  85. uint8_t level = ((target_voltage - 2300.f) / 100.f);
  86. EMU->R5VCTRL = EMU_R5VCTRL_INPUTMODE_AUTO;
  87. EMU->R5VOUTLEVEL = level; /* Reg output to 3.3V*/
  88. }
  89. void emu_dcdc_init(float target_voltage, float max_ln_current, float max_lp_current, float max_reverse_current)
  90. {
  91. if(target_voltage < 1800.f || target_voltage >= 3000.f)
  92. return;
  93. if(max_ln_current <= 0.f || max_ln_current > 200.f)
  94. return;
  95. if(max_lp_current <= 0.f || max_lp_current > 10000.f)
  96. return;
  97. if(max_reverse_current < 0.f || max_reverse_current > 160.f)
  98. return;
  99. // Low Power & Low Noise current limit
  100. uint8_t lp_bias = 0;
  101. if(max_lp_current < 75.f)
  102. lp_bias = 0;
  103. else if(max_lp_current < 500.f)
  104. lp_bias = 1;
  105. else if(max_lp_current < 2500.f)
  106. lp_bias = 2;
  107. else
  108. lp_bias = 3;
  109. EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~_EMU_DCDCMISCCTRL_LPCMPBIASEM234H_MASK) | ((uint32_t)lp_bias << _EMU_DCDCMISCCTRL_LPCMPBIASEM234H_SHIFT);
  110. EMU->DCDCMISCCTRL |= EMU_DCDCMISCCTRL_LNFORCECCM; // Force CCM to prevent reverse current
  111. EMU->DCDCLPCTRL |= EMU_DCDCLPCTRL_LPVREFDUTYEN; // Enable duty cycling of the bias for LP mode
  112. EMU->DCDCLNFREQCTRL = (EMU->DCDCLNFREQCTRL & ~_EMU_DCDCLNFREQCTRL_RCOBAND_MASK) | 4; // Set RCO Band to 7MHz
  113. uint8_t fet_count = 0;
  114. if(max_ln_current < 20.f)
  115. fet_count = 4;
  116. else if(max_ln_current >= 20.f && max_ln_current < 40.f)
  117. fet_count = 8;
  118. else
  119. fet_count = 16;
  120. EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~_EMU_DCDCMISCCTRL_NFETCNT_MASK) | ((uint32_t)(fet_count - 1) << _EMU_DCDCMISCCTRL_NFETCNT_SHIFT);
  121. EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~_EMU_DCDCMISCCTRL_PFETCNT_MASK) | ((uint32_t)(fet_count - 1) << _EMU_DCDCMISCCTRL_PFETCNT_SHIFT);
  122. uint8_t ln_current_limit = (((max_ln_current + 40.f) * 1.5f) / (5.f * fet_count)) - 1;
  123. uint8_t lp_current_limit = 1; // Recommended value
  124. EMU->DCDCMISCCTRL = (EMU->DCDCMISCCTRL & ~(_EMU_DCDCMISCCTRL_LNCLIMILIMSEL_MASK | _EMU_DCDCMISCCTRL_LPCLIMILIMSEL_MASK)) | ((uint32_t)ln_current_limit << _EMU_DCDCMISCCTRL_LNCLIMILIMSEL_SHIFT) | ((uint32_t)lp_current_limit << _EMU_DCDCMISCCTRL_LPCLIMILIMSEL_SHIFT);
  125. uint8_t z_det_limit = ((max_reverse_current + 40.f) * 1.5f) / (2.5f * fet_count);
  126. EMU->DCDCZDETCTRL = (EMU->DCDCZDETCTRL & ~_EMU_DCDCZDETCTRL_ZDETILIMSEL_MASK) | ((uint32_t)z_det_limit << _EMU_DCDCZDETCTRL_ZDETILIMSEL_SHIFT);
  127. EMU->DCDCCLIMCTRL |= EMU_DCDCCLIMCTRL_BYPLIMEN; // Enable bypass current limiter to prevent overcurrent when switching modes
  128. // Output Voltage
  129. if(target_voltage > 1800.f)
  130. {
  131. float max_vout = 3000.f;
  132. float min_vout = 1800.f;
  133. float diff_vout = max_vout - min_vout;
  134. uint8_t ln_vref_high = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_3V0LNATT1_MASK) >> _DEVINFO_DCDCLNVCTRL0_3V0LNATT1_SHIFT;
  135. uint8_t ln_vref_low = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_1V8LNATT1_MASK) >> _DEVINFO_DCDCLNVCTRL0_1V8LNATT1_SHIFT;
  136. uint8_t ln_vref = ((target_voltage - min_vout) * (float)(ln_vref_high - ln_vref_low)) / diff_vout;
  137. ln_vref += ln_vref_low;
  138. EMU->DCDCLNVCTRL = (ln_vref << _EMU_DCDCLNVCTRL_LNVREF_SHIFT) | EMU_DCDCLNVCTRL_LNATT;
  139. uint8_t lp_vref_low = 0;
  140. uint8_t lp_vref_high = 0;
  141. switch(lp_bias)
  142. {
  143. case 0:
  144. {
  145. lp_vref_high = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_SHIFT;
  146. lp_vref_low = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_SHIFT;
  147. }
  148. break;
  149. case 1:
  150. {
  151. lp_vref_high = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_SHIFT;
  152. lp_vref_low = (DEVINFO->DCDCLPVCTRL2 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_SHIFT;
  153. }
  154. break;
  155. case 2:
  156. {
  157. lp_vref_high = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_SHIFT;
  158. lp_vref_low = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_SHIFT;
  159. }
  160. break;
  161. case 3:
  162. {
  163. lp_vref_high = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_SHIFT;
  164. lp_vref_low = (DEVINFO->DCDCLPVCTRL3 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_SHIFT;
  165. }
  166. break;
  167. }
  168. uint8_t lp_vref = ((target_voltage - min_vout) * (float)(lp_vref_high - lp_vref_low)) / diff_vout;
  169. lp_vref += lp_vref_low;
  170. EMU->DCDCLPVCTRL = (lp_vref << _EMU_DCDCLPVCTRL_LPVREF_SHIFT) | EMU_DCDCLPVCTRL_LPATT;
  171. }
  172. else
  173. {
  174. float max_vout = 1800.f;
  175. float min_vout = 1200.f;
  176. float diff_vout = max_vout - min_vout;
  177. uint8_t ln_vref_high = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_1V8LNATT0_MASK) >> _DEVINFO_DCDCLNVCTRL0_1V8LNATT0_SHIFT;
  178. uint8_t ln_vref_low = (DEVINFO->DCDCLNVCTRL0 & _DEVINFO_DCDCLNVCTRL0_1V2LNATT0_MASK) >> _DEVINFO_DCDCLNVCTRL0_1V2LNATT0_SHIFT;
  179. uint8_t ln_vref = ((target_voltage - min_vout) * (float)(ln_vref_high - ln_vref_low)) / diff_vout;
  180. ln_vref += ln_vref_low;
  181. EMU->DCDCLNVCTRL = ln_vref << _EMU_DCDCLNVCTRL_LNVREF_SHIFT;
  182. uint8_t lp_vref_low = 0;
  183. uint8_t lp_vref_high = 0;
  184. switch(lp_bias)
  185. {
  186. case 0:
  187. {
  188. lp_vref_high = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS0_SHIFT;
  189. lp_vref_low = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS0_SHIFT;
  190. }
  191. break;
  192. case 1:
  193. {
  194. lp_vref_high = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_3V0LPATT1LPCMPBIAS1_SHIFT;
  195. lp_vref_low = (DEVINFO->DCDCLPVCTRL0 & _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_MASK) >> _DEVINFO_DCDCLPVCTRL2_1V8LPATT1LPCMPBIAS1_SHIFT;
  196. }
  197. break;
  198. case 2:
  199. {
  200. lp_vref_high = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS2_SHIFT;
  201. lp_vref_low = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS2_SHIFT;
  202. }
  203. break;
  204. case 3:
  205. {
  206. lp_vref_high = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_3V0LPATT1LPCMPBIAS3_SHIFT;
  207. lp_vref_low = (DEVINFO->DCDCLPVCTRL1 & _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_MASK) >> _DEVINFO_DCDCLPVCTRL3_1V8LPATT1LPCMPBIAS3_SHIFT;
  208. }
  209. break;
  210. }
  211. uint8_t lp_vref = ((target_voltage - min_vout) * (float)(lp_vref_high - lp_vref_low)) / diff_vout;
  212. lp_vref += lp_vref_low;
  213. EMU->DCDCLPVCTRL = lp_vref << _EMU_DCDCLPVCTRL_LPVREF_SHIFT;
  214. }
  215. EMU->DCDCLPCTRL = (EMU->DCDCLPCTRL & ~_EMU_DCDCLPCTRL_LPCMPHYSSELEM234H_MASK) | (((DEVINFO->DCDCLPCMPHYSSEL1 & (((uint32_t)0xFF) << (lp_bias * 8))) >> (lp_bias * 8)) << _EMU_DCDCLPCTRL_LPCMPHYSSELEM234H_SHIFT);
  216. while(EMU->DCDCSYNC & EMU_DCDCSYNC_DCDCCTRLBUSY); // Wait for configuration to write
  217. // Calibration
  218. //EMU->DCDCLNCOMPCTRL = 0x57204077; // Compensation for 1uF DCDC capacitor
  219. EMU->DCDCLNCOMPCTRL = 0xB7102137; // Compensation for 4.7uF DCDC capacitor
  220. // Enable DCDC converter
  221. EMU->DCDCCTRL = EMU_DCDCCTRL_DCDCMODEEM4_EM4LOWPOWER | EMU_DCDCCTRL_DCDCMODEEM23_EM23LOWPOWER | EMU_DCDCCTRL_DCDCMODE_LOWNOISE;
  222. // Switch digital domain to DVDD
  223. EMU->PWRCTRL = EMU_PWRCTRL_REGPWRSEL_DVDD | EMU_PWRCTRL_ANASW_AVDD;
  224. }
  225. void cmu_hfxo_startup_calib(uint16_t ib_trim, uint16_t c_tune)
  226. {
  227. if(CMU->STATUS & CMU_STATUS_HFXOENS)
  228. return;
  229. CMU->HFXOSTARTUPCTRL = (CMU->HFXOSTARTUPCTRL & ~(_CMU_HFXOSTARTUPCTRL_CTUNE_MASK | _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK)) | (((uint32_t)c_tune << _CMU_HFXOSTARTUPCTRL_CTUNE_SHIFT) & _CMU_HFXOSTARTUPCTRL_CTUNE_MASK) | (((uint32_t)ib_trim << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_SHIFT) & _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK);
  230. }
  231. void cmu_hfxo_steady_calib(uint16_t ib_trim, uint16_t c_tune)
  232. {
  233. if(CMU->STATUS & CMU_STATUS_HFXOENS)
  234. return;
  235. CMU->HFXOSTEADYSTATECTRL = (CMU->HFXOSTEADYSTATECTRL & ~(_CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK | _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK)) | (((uint32_t)c_tune << _CMU_HFXOSTEADYSTATECTRL_CTUNE_SHIFT) & _CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK) | (((uint32_t)ib_trim << _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_SHIFT) & _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK);
  236. }
  237. void cmu_hfrco_calib(uint32_t calibration)
  238. {
  239. if(CMU->STATUS & CMU_STATUS_DPLLENS)
  240. return;
  241. while(CMU->SYNCBUSY & CMU_SYNCBUSY_HFRCOBSY);
  242. CMU->HFRCOCTRL = calibration;
  243. while(CMU->SYNCBUSY & CMU_SYNCBUSY_HFRCOBSY);
  244. }
  245. void cmu_ushfrco_calib(uint8_t enable, uint32_t calibration)
  246. {
  247. if(CMU->USBCRCTRL & CMU_USBCRCTRL_USBCREN)
  248. return;
  249. if(!enable)
  250. {
  251. CMU->OSCENCMD = CMU_OSCENCMD_USHFRCODIS;
  252. while(CMU->STATUS & CMU_STATUS_USHFRCOENS);
  253. return;
  254. }
  255. while(CMU->SYNCBUSY & CMU_SYNCBUSY_USHFRCOBSY);
  256. CMU->USHFRCOCTRL = calibration | CMU_USHFRCOCTRL_FINETUNINGEN;
  257. while(CMU->SYNCBUSY & CMU_SYNCBUSY_USHFRCOBSY);
  258. if(enable && !(CMU->STATUS & CMU_STATUS_USHFRCOENS))
  259. {
  260. CMU->OSCENCMD = CMU_OSCENCMD_USHFRCOEN;
  261. while(!(CMU->STATUS & CMU_STATUS_USHFRCORDY));
  262. }
  263. }
  264. void cmu_auxhfrco_calib(uint8_t enable, uint32_t calibration)
  265. {
  266. if(!enable)
  267. {
  268. CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCODIS;
  269. while(CMU->STATUS & CMU_STATUS_AUXHFRCOENS);
  270. return;
  271. }
  272. while(CMU->SYNCBUSY & CMU_SYNCBUSY_AUXHFRCOBSY);
  273. CMU->AUXHFRCOCTRL = calibration;
  274. while(CMU->SYNCBUSY & CMU_SYNCBUSY_AUXHFRCOBSY);
  275. if(enable && !(CMU->STATUS & CMU_STATUS_AUXHFRCOENS))
  276. {
  277. CMU->OSCENCMD = CMU_OSCENCMD_AUXHFRCOEN;
  278. while(!(CMU->STATUS & CMU_STATUS_AUXHFRCORDY));
  279. }
  280. }
  281. void cmu_init(void)
  282. {
  283. // Change SDIO clock to HFXO if HFRCO selected and disable it
  284. CMU->SDIOCTRL = CMU_SDIOCTRL_SDIOCLKDIS | CMU_SDIOCTRL_SDIOCLKSEL_HFXO;
  285. while(CMU->STATUS & CMU_STATUS_SDIOCLKENS);
  286. // Change QSPI clock to HFXO if HFRCO selected and disable it
  287. CMU->QSPICTRL = CMU_QSPICTRL_QSPI0CLKDIS | CMU_QSPICTRL_QSPI0CLKSEL_HFXO;
  288. while(CMU->STATUS & CMU_STATUS_QSPI0CLKENS);
  289. // Disable DPLL if enabled
  290. if(CMU->STATUS & CMU_STATUS_DPLLENS)
  291. {
  292. CMU->OSCENCMD = CMU_OSCENCMD_DPLLDIS;
  293. while(CMU->STATUS & CMU_STATUS_DPLLENS);
  294. }
  295. // Disable HFXO if enabled
  296. if(CMU->STATUS & CMU_STATUS_HFXOENS)
  297. {
  298. CMU->OSCENCMD = CMU_OSCENCMD_HFXODIS;
  299. while(CMU->STATUS & CMU_STATUS_HFXOENS);
  300. }
  301. // Setup HFXO
  302. CMU->HFXOCTRL = CMU_HFXOCTRL_PEAKDETMODE_AUTOCMD | CMU_HFXOCTRL_MODE_XTAL;
  303. CMU->HFXOCTRL1 = CMU_HFXOCTRL1_PEAKDETTHR_DEFAULT;
  304. CMU->HFXOSTEADYSTATECTRL |= CMU_HFXOSTEADYSTATECTRL_PEAKMONEN;
  305. CMU->HFXOTIMEOUTCTRL = (7 << _CMU_HFXOTIMEOUTCTRL_PEAKDETTIMEOUT_SHIFT) | (8 << _CMU_HFXOTIMEOUTCTRL_STEADYTIMEOUT_SHIFT) | (12 << _CMU_HFXOTIMEOUTCTRL_STARTUPTIMEOUT_SHIFT);
  306. // Enable HFXO and wait for it to be ready
  307. CMU->OSCENCMD = CMU_OSCENCMD_HFXOEN;
  308. while(!(CMU->STATUS & CMU_STATUS_HFXORDY));
  309. // Switch main clock to HFXO and wait for it to be selected
  310. CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFXO;
  311. while((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) != CMU_HFCLKSTATUS_SELECTED_HFXO);
  312. // Calibrate HFRCO for 72MHz and enable tunning by PLL
  313. cmu_hfrco_calib((DEVINFO->HFRCOCAL16) | CMU_HFRCOCTRL_FINETUNINGEN);
  314. // Setup the PLL
  315. CMU->DPLLCTRL = CMU_DPLLCTRL_REFSEL_HFXO | CMU_DPLLCTRL_AUTORECOVER | CMU_DPLLCTRL_EDGESEL_RISE | CMU_DPLLCTRL_MODE_FREQLL;
  316. // 72MHz = 50MHz (HFXO) * 1.44 (144/100)
  317. CMU->DPLLCTRL1 = (143 << _CMU_DPLLCTRL1_N_SHIFT) | (99 << _CMU_DPLLCTRL1_M_SHIFT); // fHFRCO = fHFXO * (N + 1) / (M + 1)
  318. // Enable the DPLL and wait for it to be ready
  319. CMU->OSCENCMD = CMU_OSCENCMD_DPLLEN;
  320. while(!(CMU->STATUS & CMU_STATUS_DPLLRDY));
  321. // Config peripherals for the new frequency (freq > 32MHz)
  322. CMU->CTRL |= CMU_CTRL_WSHFLE;
  323. // Set prescalers
  324. CMU->HFPRESC = CMU_HFPRESC_HFCLKLEPRESC_DIV2 | CMU_HFPRESC_PRESC_NODIVISION;
  325. CMU->HFBUSPRESC = 1 << _CMU_HFBUSPRESC_PRESC_SHIFT;
  326. CMU->HFCOREPRESC = 0 << _CMU_HFCOREPRESC_PRESC_SHIFT;
  327. CMU->HFPERPRESC = 1 << _CMU_HFPERPRESC_PRESC_SHIFT;
  328. CMU->HFEXPPRESC = 0 << _CMU_HFEXPPRESC_PRESC_SHIFT;
  329. CMU->HFPERPRESCB = 0 << _CMU_HFPERPRESCB_PRESC_SHIFT;
  330. CMU->HFPERPRESCC = 1 << _CMU_HFPERPRESCC_PRESC_SHIFT;
  331. // Enable clock to peripherals
  332. CMU->CTRL |= CMU_CTRL_HFPERCLKEN;
  333. // Switch main clock to HFRCO and wait for it to be selected
  334. CMU->HFCLKSEL = CMU_HFCLKSEL_HF_HFRCO;
  335. while((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) != CMU_HFCLKSTATUS_SELECTED_HFRCO);
  336. // LFA Clock
  337. CMU->LFACLKSEL = CMU_LFACLKSEL_LFA_LFRCO;
  338. // LFB Clock
  339. CMU->LFBCLKSEL = CMU_LFBCLKSEL_LFB_LFRCO;
  340. // LFC Clock
  341. CMU->LFCCLKSEL = CMU_LFCCLKSEL_LFC_LFRCO;
  342. // LFE Clock
  343. CMU->LFECLKSEL = CMU_LFECLKSEL_LFE_ULFRCO;
  344. }
  345. void systick_init(void)
  346. {
  347. SysTick->LOAD = (72000000 / 1000) - 1;
  348. SysTick->VAL = 0;
  349. SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
  350. SCB->SHP[11] = 7 << (8 - __NVIC_PRIO_BITS); // Set priority 3,1 (min)
  351. }
  352. void gpio_init(void)
  353. {
  354. CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_GPIO;
  355. // NC - Not Connected (not available in mcu package)
  356. // NR - Not routed (no routing to pin on pcb, floating)
  357. // NU - Not used (not currently in use)
  358. // Port A
  359. GPIO->P[0].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT)
  360. | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT);
  361. GPIO->P[0].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NU
  362. | GPIO_P_MODEL_MODE1_DISABLED // NU
  363. | GPIO_P_MODEL_MODE2_DISABLED // NU
  364. | GPIO_P_MODEL_MODE3_DISABLED // NU
  365. | GPIO_P_MODEL_MODE4_DISABLED // NU
  366. | GPIO_P_MODEL_MODE5_DISABLED // NU
  367. | GPIO_P_MODEL_MODE6_DISABLED // NU
  368. | GPIO_P_MODEL_MODE7_DISABLED; // NC
  369. GPIO->P[0].MODEH = GPIO_P_MODEH_MODE8_DISABLED // GPIO - MIC_ENABLE
  370. | GPIO_P_MODEH_MODE9_DISABLED // NC
  371. | GPIO_P_MODEH_MODE10_DISABLED // NC
  372. | GPIO_P_MODEH_MODE11_DISABLED // NC
  373. | GPIO_P_MODEH_MODE12_WIREDAND // LED0R
  374. | GPIO_P_MODEH_MODE13_WIREDAND // LED0B
  375. | GPIO_P_MODEH_MODE14_WIREDAND // LED0G
  376. | GPIO_P_MODEH_MODE15_DISABLED; // NU
  377. GPIO->P[0].DOUT = 0x7000; // Leds off By default
  378. GPIO->P[0].OVTDIS = 0;
  379. // Port B
  380. GPIO->P[1].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT)
  381. | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT);
  382. GPIO->P[1].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NC
  383. | GPIO_P_MODEL_MODE1_DISABLED // NC
  384. | GPIO_P_MODEL_MODE2_DISABLED // NC
  385. | GPIO_P_MODEL_MODE3_DISABLED // NU
  386. | GPIO_P_MODEL_MODE4_DISABLED // NU
  387. | GPIO_P_MODEL_MODE5_DISABLED // NU
  388. | GPIO_P_MODEL_MODE6_DISABLED // NU
  389. | GPIO_P_MODEL_MODE7_DISABLED; // MAIN_LFXTAL_P
  390. GPIO->P[1].MODEH = GPIO_P_MODEH_MODE8_DISABLED // MAIN_LFXTAL_N
  391. | GPIO_P_MODEH_MODE9_DISABLED // NC
  392. | GPIO_P_MODEH_MODE10_DISABLED // NC
  393. | GPIO_P_MODEH_MODE11_DISABLED // PDM_DAT0 - MIC_DATA
  394. | GPIO_P_MODEH_MODE12_DISABLED // PDM_CLK - MIC_CLOCK
  395. | GPIO_P_MODEH_MODE13_DISABLED // MAIN_HFXTAL_P
  396. | GPIO_P_MODEH_MODE14_DISABLED // MAIN_HFXTAL_N
  397. | GPIO_P_MODEH_MODE15_DISABLED; // NC
  398. GPIO->P[1].DOUT = 0;
  399. GPIO->P[1].OVTDIS = 0;
  400. // Port C
  401. GPIO->P[2].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT)
  402. | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (7 << _GPIO_P_CTRL_SLEWRATE_SHIFT);
  403. GPIO->P[2].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NC
  404. | GPIO_P_MODEL_MODE1_DISABLED // NC
  405. | GPIO_P_MODEL_MODE2_DISABLED // NC
  406. | GPIO_P_MODEL_MODE3_DISABLED // NC
  407. | GPIO_P_MODEL_MODE4_DISABLED // NU
  408. | GPIO_P_MODEL_MODE5_DISABLED // NU
  409. | GPIO_P_MODEL_MODE6_DISABLED // NC
  410. | GPIO_P_MODEL_MODE7_DISABLED; // NC
  411. GPIO->P[2].MODEH = GPIO_P_MODEH_MODE8_DISABLED // NC
  412. | GPIO_P_MODEH_MODE9_DISABLED // NC
  413. | GPIO_P_MODEH_MODE10_DISABLED // NC
  414. | GPIO_P_MODEH_MODE11_DISABLED // NC
  415. | GPIO_P_MODEH_MODE12_DISABLED // NC
  416. | GPIO_P_MODEH_MODE13_DISABLED // NC
  417. | GPIO_P_MODEH_MODE14_DISABLED // NC
  418. | GPIO_P_MODEH_MODE15_DISABLED; // NC
  419. GPIO->P[2].DOUT = 0;
  420. GPIO->P[2].OVTDIS = 0;
  421. // Port D
  422. GPIO->P[3].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT)
  423. | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT);
  424. GPIO->P[3].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NU
  425. | GPIO_P_MODEL_MODE1_DISABLED // NU
  426. | GPIO_P_MODEL_MODE2_DISABLED // NU
  427. | GPIO_P_MODEL_MODE3_DISABLED // NU
  428. | GPIO_P_MODEL_MODE4_DISABLED // NU
  429. | GPIO_P_MODEL_MODE5_INPUT // GPIO - BTN0
  430. | GPIO_P_MODEL_MODE6_WIREDAND // LED1R
  431. | GPIO_P_MODEL_MODE7_DISABLED; // NU
  432. GPIO->P[3].MODEH = GPIO_P_MODEH_MODE8_INPUT // GPIO - BTN1
  433. | GPIO_P_MODEH_MODE9_DISABLED // NC
  434. | GPIO_P_MODEH_MODE10_DISABLED // NC
  435. | GPIO_P_MODEH_MODE11_DISABLED // NC
  436. | GPIO_P_MODEH_MODE12_DISABLED // NC
  437. | GPIO_P_MODEH_MODE13_DISABLED // NC
  438. | GPIO_P_MODEH_MODE14_DISABLED // NC
  439. | GPIO_P_MODEH_MODE15_DISABLED; // NC
  440. GPIO->P[3].DOUT = 0;
  441. GPIO->P[3].OVTDIS = 0;
  442. // Port E
  443. GPIO->P[4].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT)
  444. | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT);
  445. GPIO->P[4].MODEL = GPIO_P_MODEL_MODE0_DISABLED // NC
  446. | GPIO_P_MODEL_MODE1_DISABLED // NC
  447. | GPIO_P_MODEL_MODE2_DISABLED // NC
  448. | GPIO_P_MODEL_MODE3_DISABLED // NC
  449. | GPIO_P_MODEL_MODE4_DISABLED // NU
  450. | GPIO_P_MODEL_MODE5_DISABLED // NU
  451. | GPIO_P_MODEL_MODE6_DISABLED // NU
  452. | GPIO_P_MODEL_MODE7_DISABLED; // NU
  453. GPIO->P[4].MODEH = GPIO_P_MODEH_MODE8_DISABLED // NU
  454. | GPIO_P_MODEH_MODE9_DISABLED // NU
  455. | GPIO_P_MODEH_MODE10_DISABLED // NU
  456. | GPIO_P_MODEH_MODE11_DISABLED // NU
  457. | GPIO_P_MODEH_MODE12_WIREDAND // LED1B
  458. | GPIO_P_MODEH_MODE13_DISABLED // NU
  459. | GPIO_P_MODEH_MODE14_DISABLED // NU
  460. | GPIO_P_MODEH_MODE15_DISABLED; // NU
  461. GPIO->P[4].DOUT = 0;
  462. GPIO->P[4].OVTDIS = 0;
  463. // Port F
  464. GPIO->P[5].CTRL = GPIO_P_CTRL_DRIVESTRENGTHALT_STRONG | (6 << _GPIO_P_CTRL_SLEWRATEALT_SHIFT)
  465. | GPIO_P_CTRL_DRIVESTRENGTH_STRONG | (6 << _GPIO_P_CTRL_SLEWRATE_SHIFT);
  466. GPIO->P[5].MODEL = GPIO_P_MODEL_MODE0_PUSHPULL // SWCLK
  467. | GPIO_P_MODEL_MODE1_PUSHPULL // SWDIO
  468. | GPIO_P_MODEL_MODE2_PUSHPULL // SWO
  469. | GPIO_P_MODEL_MODE3_DISABLED // NC
  470. | GPIO_P_MODEL_MODE4_DISABLED // NC
  471. | GPIO_P_MODEL_MODE5_DISABLED // NU
  472. | GPIO_P_MODEL_MODE6_DISABLED // NC
  473. | GPIO_P_MODEL_MODE7_DISABLED; // NC
  474. GPIO->P[5].MODEH = GPIO_P_MODEH_MODE8_DISABLED // NC
  475. | GPIO_P_MODEH_MODE9_DISABLED // NC
  476. | GPIO_P_MODEH_MODE10_DISABLED // USB N
  477. | GPIO_P_MODEH_MODE11_DISABLED // USB P
  478. | GPIO_P_MODEH_MODE12_WIREDAND // LED1G
  479. | GPIO_P_MODEH_MODE13_DISABLED // NC
  480. | GPIO_P_MODEH_MODE14_DISABLED // NC
  481. | GPIO_P_MODEH_MODE15_DISABLED; // NC
  482. GPIO->P[5].DOUT = 0;
  483. GPIO->P[5].OVTDIS = 0;
  484. // Debugger Route
  485. GPIO->ROUTEPEN &= ~(GPIO_ROUTEPEN_TDIPEN | GPIO_ROUTEPEN_TDOPEN); // Disable JTAG
  486. GPIO->ROUTEPEN |= GPIO_ROUTEPEN_SWVPEN; // Enable SWO
  487. GPIO->ROUTELOC0 = GPIO_ROUTELOC0_SWVLOC_LOC0; // SWO on PF2
  488. // External interrupts
  489. GPIO->EXTIPSELL = GPIO_EXTIPSELL_EXTIPSEL0_PORTE // NU
  490. | GPIO_EXTIPSELL_EXTIPSEL1_PORTB // NU
  491. | GPIO_EXTIPSELL_EXTIPSEL2_PORTB // NU
  492. | GPIO_EXTIPSELL_EXTIPSEL3_PORTB // NU
  493. | GPIO_EXTIPSELL_EXTIPSEL4_PORTA // NU
  494. | GPIO_EXTIPSELL_EXTIPSEL5_PORTA // NU
  495. | GPIO_EXTIPSELL_EXTIPSEL6_PORTC // NU
  496. | GPIO_EXTIPSELL_EXTIPSEL7_PORTC; // NU
  497. GPIO->EXTIPSELH = GPIO_EXTIPSELH_EXTIPSEL8_PORTA // NU
  498. | GPIO_EXTIPSELH_EXTIPSEL9_PORTE // NU
  499. | GPIO_EXTIPSELH_EXTIPSEL10_PORTF // NU
  500. | GPIO_EXTIPSELH_EXTIPSEL11_PORTA // NU
  501. | GPIO_EXTIPSELH_EXTIPSEL12_PORTA // NU
  502. | GPIO_EXTIPSELH_EXTIPSEL13_PORTE // NU
  503. | GPIO_EXTIPSELH_EXTIPSEL14_PORTF // NU
  504. | GPIO_EXTIPSELH_EXTIPSEL15_PORTA; // NU
  505. GPIO->EXTIPINSELL = GPIO_EXTIPINSELL_EXTIPINSEL0_PIN3 // NU
  506. | GPIO_EXTIPINSELL_EXTIPINSEL1_PIN1 // NU
  507. | GPIO_EXTIPINSELL_EXTIPINSEL2_PIN2 // NU
  508. | GPIO_EXTIPINSELL_EXTIPINSEL3_PIN3 // NU
  509. | GPIO_EXTIPINSELL_EXTIPINSEL4_PIN6 // NU
  510. | GPIO_EXTIPINSELL_EXTIPINSEL5_PIN7 // NU
  511. | GPIO_EXTIPINSELL_EXTIPINSEL6_PIN4 // NU
  512. | GPIO_EXTIPINSELL_EXTIPINSEL7_PIN7; // NU
  513. GPIO->EXTIPINSELH = GPIO_EXTIPINSELH_EXTIPINSEL8_PIN8 // NU
  514. | GPIO_EXTIPINSELH_EXTIPINSEL9_PIN9 // NU
  515. | GPIO_EXTIPINSELH_EXTIPINSEL10_PIN11 // NU
  516. | GPIO_EXTIPINSELH_EXTIPINSEL11_PIN8 // NU
  517. | GPIO_EXTIPINSELH_EXTIPINSEL12_PIN13 // NU
  518. | GPIO_EXTIPINSELH_EXTIPINSEL13_PIN15 // NU
  519. | GPIO_EXTIPINSELH_EXTIPINSEL14_PIN12 // NU
  520. | GPIO_EXTIPINSELH_EXTIPINSEL15_PIN12; // NU
  521. }
  522. /*--------------------------------------------------------------------*/
  523. /* Board Init */
  524. /*--------------------------------------------------------------------*/
  525. void board_init(void)
  526. {
  527. emu_dcdc_init(1800.f, 50.f, 100.f, 0.f); // Init DC-DC converter (1.8 V, 50 mA active, 100 uA sleep, 0 mA reverse limit)
  528. emu_init(0);
  529. emu_reg_init(3300.f); // set output regulator to 3.3V
  530. cmu_hfxo_startup_calib(0x200, 0x145); // Config HFXO Startup for 1280 uA, 36 pF (18 pF + 2 pF CLOAD)
  531. cmu_hfxo_steady_calib(0x009, 0x145); // Config HFXO Steady for 12 uA, 36 pF (18 pF + 2 pF CLOAD)
  532. cmu_init(); // Init Clock Management Unit
  533. cmu_ushfrco_calib(1, DEVINFO->USHFRCOCAL13); // Enable and calibrate USHFRCO for 48 MHz
  534. cmu_auxhfrco_calib(1, DEVINFO->AUXHFRCOCAL11); // Enable and calibrate AUXHFRCO for 32 MHz
  535. CMU->USBCRCTRL = CMU_USBCRCTRL_USBCREN; // enable USB clock recovery
  536. CMU->USBCTRL = CMU_USBCTRL_USBCLKSEL_USHFRCO | CMU_USBCTRL_USBCLKEN; // select USHFRCO as USB Phy clock source and enable it
  537. CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_USB; // enable USB peripheral clock
  538. systick_init(); // Init system tick
  539. gpio_init(); // Init IOs
  540. }
  541. /*--------------------------------------------------------------------*/
  542. /* Board porting API */
  543. /*--------------------------------------------------------------------*/
  544. void board_led_write(bool state)
  545. {
  546. // Combine red and blue for pink Because it looks good :)
  547. GPIO->P[LED_PORT].DOUT = (GPIO->P[LED_PORT].DOUT & ~((1 << LED_PIN_R) | (1 << LED_PIN_B))) | (state << LED_PIN_R) | (state << LED_PIN_B);
  548. }
  549. uint32_t board_button_read(void)
  550. {
  551. return !!(GPIO->P[BUTTON_PORT].DIN & (1 << BUTTON_PIN));
  552. }
  553. int board_uart_read(uint8_t* buf, int len)
  554. {
  555. (void) buf; (void) len;
  556. return 0;
  557. }
  558. int board_uart_write(void const * buf, int len)
  559. {
  560. (void) buf; (void) len;
  561. return 0;
  562. }
  563. #if CFG_TUSB_OS == OPT_OS_NONE
  564. volatile uint32_t system_ticks = 0;
  565. void SysTick_Handler(void)
  566. {
  567. system_ticks++;
  568. }
  569. uint32_t board_millis(void)
  570. {
  571. return system_ticks;
  572. }
  573. #endif
  574. #ifdef USE_FULL_ASSERT
  575. /**
  576. * @brief Reports the name of the source file and the source line number
  577. * where the assert_param error has occurred.
  578. * @param file: pointer to the source file name
  579. * @param line: assert_param error line source number
  580. * @retval None
  581. */
  582. void assert_failed(char *file, uint32_t line)
  583. {
  584. /* USER CODE BEGIN 6 */
  585. /* User can add his own implementation to report the file name and line number,
  586. tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  587. /* USER CODE END 6 */
  588. }
  589. #endif /* USE_FULL_ASSERT */