start-teensy-3-6.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. #include "all-headers.h"
  2. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  3. // MICROCONTROLLER SERIAL NUMBER
  4. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  5. static uint32_t gMicrocontrollerSerialNumber ;
  6. static uint32_t readMicrocontrollerSerialNumber (void) ;
  7. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  8. // CLOCK SETTINGS
  9. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  10. // The MCGCLOCKOUT frequency is given by (the 16 MHz quartz frequency is divided by 2 for the PPL)
  11. // MCGCLOCKOUT = 16 MHz / 2 * (MCG:C6:VDIV + 16) / (MCG:C5:PRDIV + 1)
  12. //
  13. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  14. // CPU CLOCK
  15. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  16. // The CPU Clock is given by: MCGCLOCKOUT / (SIM:CLKDIV1:OUTDIV1 + 1)
  17. //
  18. // Here, CPU_MHZ is a given constant, so we only check that settings are correct by asserting:
  19. // CPU_MHZ * (MCG:C5:PRDIV + 1) * (SIM:CLKDIV1:OUTDIV1 + 1) = (16 MHz / 2) * (MCG:C6:VDIV + 16)
  20. //
  21. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  22. // BUS (peripheral) CLOCK
  23. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  24. // The peripheral Clock is given by: MCGCLOCKOUT / (SIM:CLKDIV1:OUTDIV2 + 1)
  25. //
  26. // Here, SIM:CLKDIV1:OUTDIV2 is a given constant, so we compute BUS_MHZ by:
  27. // BUS_MHZ = (16 MHz / 2) * (MCG:C6:VDIV + 16) / (MCG:C5:PRDIV + 1) / (SIM:CLKDIV1:OUTDIV2 + 1)
  28. //
  29. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  30. // Flexbus CLOCK
  31. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  32. // The Flexbus Clock is given by: MCGCLOCKOUT / (SIM:CLKDIV1:OUTDIV3 + 1)
  33. //
  34. // Here, SIM:CLKDIV1:OUTDIV3 is a given constant, so we compute FLEXBUS_MHZ by:
  35. // FLEXBUS_MHZ = (16 MHz / 2) * (MCG:C6:VDIV + 16) /(MCG:C5:PRDIV + 1) / (SIM:CLKDIV1:OUTDIV3 + 1)
  36. //
  37. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  38. // Flash CLOCK
  39. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  40. // The FLASH Clock is given by: MCGCLOCKOUT / (SIM:CLKDIV1:OUTDIV3 + 1)
  41. //
  42. // Here, SIM:CLKDIV1:OUTDIV4 is a given constant, so we compute Flash Clock in kHz (result may not be integer):
  43. // FLASH_KHZ = (16000 kHz / 2) * (MCG:C6:VDIV + 16) / (MCG:C5:PRDIV + 1) / (SIM:CLKDIV1:OUTDIV4 + 1)
  44. //
  45. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  46. // MICRO CONTROLLER REQUIREMENTS
  47. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  48. // The clock dividers are programmed via the SIM module’s CLKDIV registers. Each divider is programmable from a
  49. // divide-by-1 through divide-by-16 setting. The following requirements must be met when configuring the clocks
  50. // for this device:
  51. // 1. The core and system clock frequencies must be 180 MHz or slower in HSRUN, 120 MHz or slower in RUN.
  52. // 2. The bus clock frequency must be programmed to 60 MHz or less in HSRUN or RUN, and an integer divide of the
  53. // core clock. The core clock to bus clock ratio is limited to a max value of 8.
  54. // 3. The flash clock frequency must be programmed to 28 MHz or less, less than or equal to the bus clock, and an
  55. // integer divide of the core clock. The core clock to flash clock ratio is limited to a max value of 8.
  56. // 4. The FlexBus clock frequency must be programmed to be less than or equal to the bus clock frequency. The
  57. // FlexBus also has pad interface restrictions that limits the maximum frequency. For this device the FlexBus
  58. // maximum frequency is 60 MHz. The core clock to FlexBus clock ratio is limited to a max value of 8.
  59. // 5. Since SDRAMC and FlexBus both use CLKOUT, the same restrictions apply to the SDRAM controller as stated
  60. // for the FlexBus clock.
  61. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  62. // SETTING SUMMARY
  63. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  64. // F_CPU MCG_C5 MCG_C6 SIM_CLKDIV1 SIM_CLKDIV1 SIM_CLKDIV1 SIM_CLKDIV1 BUS_MHZ FLEXBUS FLASH
  65. // _MHZ _PRDIV _VDIV _OUTDIV1 _OUTDIV2 _OUTDIV3 _OUTDIV4 _MHZ _KHZ
  66. // 240 0 14 0 3 0 7 60 240 30 000
  67. // 216 0 11 0 1 0 7 54 216 27 000
  68. // 192 0 8 0 1 0 6 28 192 27 428
  69. // 180 1 29 0 1 0 6 60 180 25 714
  70. // 168 0 5 0 2 0 5 56 168 28 000
  71. // 144 0 2 0 1 0 4 28 144 28 800
  72. // 120 1 14 0 1 0 4 60 120 24 000
  73. // 96 1 8 0 1 0 2 24 96 24 000
  74. // 72 1 2 0 0 0 2 36 72 24 000
  75. // 48 1 8 1 1 1 3 48 48 24 000
  76. // 24 1 8 3 3 3 3 24 24 24 000
  77. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  78. // PRDIV SETTINGS
  79. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  80. #ifndef CPU_MHZ
  81. #error "CPU_MHZ is not defined"
  82. static const uint32_t K_MCG_C5_PRDIV = 0 ;
  83. #elif CPU_MHZ == 240
  84. static const uint32_t K_MCG_C5_PRDIV = 0 ;
  85. #elif CPU_MHZ == 216
  86. static const uint32_t K_MCG_C5_PRDIV = 0 ;
  87. #elif CPU_MHZ == 192
  88. static const uint32_t K_MCG_C5_PRDIV = 0 ;
  89. #elif CPU_MHZ == 180
  90. static const uint32_t K_MCG_C5_PRDIV = 1 ;
  91. #elif CPU_MHZ == 168
  92. static const uint32_t K_MCG_C5_PRDIV = 0 ;
  93. #elif CPU_MHZ == 144
  94. static const uint32_t K_MCG_C5_PRDIV = 0 ;
  95. #elif CPU_MHZ == 120
  96. static const uint32_t K_MCG_C5_PRDIV = 1 ;
  97. #elif CPU_MHZ == 96
  98. static const uint32_t K_MCG_C5_PRDIV = 1 ;
  99. #elif CPU_MHZ == 72
  100. static const uint32_t K_MCG_C5_PRDIV = 1 ;
  101. #elif CPU_MHZ == 48
  102. static const uint32_t K_MCG_C5_PRDIV = 1 ;
  103. #elif CPU_MHZ == 24
  104. static const uint32_t K_MCG_C5_PRDIV = 1 ;
  105. #else
  106. #error "CPU_MHZ has an invalid value"
  107. static const uint32_t K_MCG_C5_PRDIV = 0 ;
  108. #endif
  109. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  110. // MCG:C6:VDIV SETTINGS
  111. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  112. #ifndef CPU_MHZ
  113. #error "CPU_MHZ is not defined"
  114. static const uint32_t K_MCG_C6_VDIV = 0 ;
  115. #elif CPU_MHZ == 240
  116. static const uint32_t K_MCG_C6_VDIV = 14 ;
  117. #elif CPU_MHZ == 216
  118. static const uint32_t K_MCG_C6_VDIV = 11 ;
  119. #elif CPU_MHZ == 192
  120. static const uint32_t K_MCG_C6_VDIV = 8 ;
  121. #elif CPU_MHZ == 180
  122. static const uint32_t K_MCG_C6_VDIV = 29 ;
  123. #elif CPU_MHZ == 168
  124. static const uint32_t K_MCG_C6_VDIV = 5 ;
  125. #elif CPU_MHZ == 144
  126. static const uint32_t K_MCG_C6_VDIV = 2 ;
  127. #elif CPU_MHZ == 120
  128. static const uint32_t K_MCG_C6_VDIV = 14 ;
  129. #elif CPU_MHZ == 96
  130. static const uint32_t K_MCG_C6_VDIV = 8 ;
  131. #elif CPU_MHZ == 72
  132. static const uint32_t K_MCG_C6_VDIV = 2 ;
  133. #elif CPU_MHZ == 48
  134. static const uint32_t K_MCG_C6_VDIV = 8 ;
  135. #elif CPU_MHZ == 24
  136. static const uint32_t K_MCG_C6_VDIV = 8 ;
  137. #else
  138. #error "CPU_MHZ has an invalid value"
  139. static const uint32_t K_MCG_C6_VDIV = 0 ;
  140. #endif
  141. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  142. // SIM:CLKDIV1:OUTDIV1 SETTINGS
  143. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  144. #ifndef CPU_MHZ
  145. #error "CPU_MHZ is not defined"
  146. static const uint32_t K_SIM_CLKDIV1_OUTDIV1 = 0 ;
  147. #elif CPU_MHZ == 48
  148. static const uint32_t K_SIM_CLKDIV1_OUTDIV1 = 1 ;
  149. #elif CPU_MHZ == 24
  150. static const uint32_t K_SIM_CLKDIV1_OUTDIV1 = 3 ;
  151. #else
  152. static const uint32_t K_SIM_CLKDIV1_OUTDIV1 = 0 ; // 0 for all other settings
  153. #endif
  154. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  155. // SIM:CLKDIV1:OUTDIV2 SETTINGS (divisor for bus)
  156. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  157. #ifndef CPU_MHZ
  158. #error "CPU_MHZ is not defined"
  159. static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 0 ;
  160. #elif CPU_MHZ == 240
  161. static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 3 ;
  162. #elif CPU_MHZ == 216
  163. static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 3 ;
  164. #elif CPU_MHZ == 192
  165. static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 3 ;
  166. #elif CPU_MHZ == 180
  167. static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 2 ;
  168. #elif CPU_MHZ == 168
  169. static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 2 ;
  170. #elif CPU_MHZ == 144
  171. static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 2 ;
  172. #elif CPU_MHZ == 120
  173. static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 1 ;
  174. #elif CPU_MHZ == 96
  175. static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 1 ;
  176. #elif CPU_MHZ == 72
  177. static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 1 ;
  178. #elif CPU_MHZ == 48
  179. static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 1 ;
  180. #elif CPU_MHZ == 24
  181. static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 3 ;
  182. #else
  183. #error "CPU_MHZ has an invalid value"
  184. static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 0 ;
  185. #endif
  186. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  187. // BUS_MHZ
  188. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  189. static const uint32_t BUS_MHZ = (16 / 2) * (K_MCG_C6_VDIV + 16) /(K_MCG_C5_PRDIV + 1) / (K_SIM_CLKDIV1_OUTDIV2 + 1) ;
  190. //······················································································································
  191. uint32_t busMHZ (void) {
  192. return BUS_MHZ ;
  193. }
  194. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  195. // SIM:CLKDIV1:OUTDIV3 SETTINGS (divisor for Flexbus)
  196. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  197. #ifndef CPU_MHZ
  198. #error "CPU_MHZ is not defined"
  199. static const uint32_t K_SIM_CLKDIV1_OUTDIV3 = 0 ;
  200. #elif CPU_MHZ == 48
  201. static const uint32_t K_SIM_CLKDIV1_OUTDIV3 = 1 ;
  202. #elif CPU_MHZ == 24
  203. static const uint32_t K_SIM_CLKDIV1_OUTDIV3 = 3 ;
  204. #else
  205. static const uint32_t K_SIM_CLKDIV1_OUTDIV3 = 0 ; // 0 for all other settings
  206. #endif
  207. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  208. // FLEXBUS_MHZ
  209. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  210. static const uint32_t FLEXBUS_MHZ = (16 / 2) * (K_MCG_C6_VDIV + 16) /(K_MCG_C5_PRDIV + 1) / (K_SIM_CLKDIV1_OUTDIV3 + 1) ;
  211. //······················································································································
  212. uint32_t FlexBusMHZ (void) {
  213. return FLEXBUS_MHZ ;
  214. }
  215. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  216. // SIM:CLKDIV1:OUTDIV4 SETTINGS (divisor for Flash)
  217. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  218. #ifndef CPU_MHZ
  219. #error "CPU_MHZ is not defined"
  220. static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 0 ;
  221. #elif CPU_MHZ == 240
  222. static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 7 ;
  223. #elif CPU_MHZ == 216
  224. static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 7 ;
  225. #elif CPU_MHZ == 192
  226. static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 6 ;
  227. #elif CPU_MHZ == 180
  228. static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 6 ;
  229. #elif CPU_MHZ == 168
  230. static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 5 ;
  231. #elif CPU_MHZ == 144
  232. static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 4 ;
  233. #elif CPU_MHZ == 120
  234. static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 4 ;
  235. #elif CPU_MHZ == 96
  236. static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 3 ;
  237. #elif CPU_MHZ == 72
  238. static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 2 ;
  239. #elif CPU_MHZ == 48
  240. static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 3 ;
  241. #elif CPU_MHZ == 24
  242. static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 3 ;
  243. #else
  244. #error "CPU_MHZ has an invalid value"
  245. static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 0 ;
  246. #endif
  247. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  248. // FLASH CLOCK (in kHz)
  249. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  250. static const uint32_t FLASH_KHZ = (16000 / 2) * (K_MCG_C6_VDIV + 16) / (K_MCG_C5_PRDIV + 1) / (K_SIM_CLKDIV1_OUTDIV4 + 1) ;
  251. //······················································································································
  252. uint32_t FlashKHz (void) {
  253. return FLASH_KHZ ;
  254. }
  255. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  256. // USB CLOCK
  257. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  258. // The USB module SHOULD be driven by a 48 MHz clock.
  259. //
  260. // For all CPU frequencies (but 216 MHz and 180 MHz), this clock is derived from MCGPLLCLK; the MCGPLLCLK is
  261. // identical to MCGCLOCKOUT (as SIM_CLKDIV2_PLL_FLL_SEL=1). So:
  262. // USB_CLOCK = MCGCLOCKOUT * (K_SIM_CLKDIV2_USBFRAC + 1) / (K_SIM_CLKDIV2_USBDIV + 1)
  263. // We check :
  264. // 48 MHz == 16 MHz / 2 * (MCG:C6:VDIV + 16) / (MCG:C5:PRDIV + 1) * (K_SIM_CLKDIV2_USBFRAC + 1) / (K_SIM_CLKDIV2_USBDIV + 1)
  265. // So:
  266. // 6 * (MCG:C5:PRDIV + 1) * (K_SIM_CLKDIV2_USBDIV + 1) == (MCG:C6:VDIV + 16) * (K_SIM_CLKDIV2_USBFRAC + 1)
  267. //
  268. // For 216 MHz and 180 MHz CPU frequencies, we use directly the built-in 48 MHz clock: SIM_CLKDIV2_PLL_FLL_SEL=3, with
  269. // di divisor (K_SIM_CLKDIV2_USBFRAC=0 and K_SIM_CLKDIV2_USBDIV=0).
  270. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  271. // USB SETTING SUMMARY
  272. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  273. // F_CPU SIM_CLKDIV2 SIM_CLKDIV2 SIM_SOPT2_
  274. // _MHZ _USBDIV _USBFRAC PLLFLLSEL
  275. // 240 4 0 1
  276. // 216 0 0 3
  277. // 192 3 0 1
  278. // 180 0 0 3
  279. // 168 6 1 1
  280. // 144 2 0 1
  281. // 120 4 1 1
  282. // 96 1 0 1
  283. // 72 2 1 1
  284. // 48 1 0 1
  285. // 24 1 0 1
  286. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  287. // SIM:SOPT2:PLLFLLSEL SETTINGS
  288. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  289. #ifndef CPU_MHZ
  290. #error "CPU_MHZ is not defined"
  291. static const uint32_t K_SIM_SOPT2_PLLFLLSEL = 0 ;
  292. #elif CPU_MHZ == 216
  293. static const uint32_t K_SIM_SOPT2_PLLFLLSEL = 3 ;
  294. #elif CPU_MHZ == 180
  295. static const uint32_t K_SIM_SOPT2_PLLFLLSEL = 3 ;
  296. #else
  297. static const uint32_t K_SIM_SOPT2_PLLFLLSEL = 1 ; // For all other settings
  298. #endif
  299. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  300. // SIM:CLKDIV2:USBFRAC SETTINGS
  301. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  302. #ifndef CPU_MHZ
  303. #error "CPU_MHZ is not defined"
  304. static const uint32_t K_SIM_CLKDIV2_USBFRAC = 0 ;
  305. #elif CPU_MHZ == 168
  306. static const uint32_t K_SIM_CLKDIV2_USBFRAC = 1 ;
  307. #elif CPU_MHZ == 120
  308. static const uint32_t K_SIM_CLKDIV2_USBFRAC = 1 ;
  309. #elif CPU_MHZ == 72
  310. static const uint32_t K_SIM_CLKDIV2_USBFRAC = 1 ;
  311. #else
  312. static const uint32_t K_SIM_CLKDIV2_USBFRAC = 0 ; // For all other settings
  313. #endif
  314. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  315. // SIM:CLKDIV2:USBDIV SETTINGS
  316. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  317. #ifndef CPU_MHZ
  318. #error "CPU_MHZ is not defined"
  319. static const uint32_t K_SIM_CLKDIV2_USBDIV = 0 ;
  320. #elif CPU_MHZ == 240
  321. static const uint32_t K_SIM_CLKDIV2_USBDIV = 4 ;
  322. #elif CPU_MHZ == 216
  323. static const uint32_t K_SIM_CLKDIV2_USBDIV = 0 ;
  324. #elif CPU_MHZ == 192
  325. static const uint32_t K_SIM_CLKDIV2_USBDIV = 3 ;
  326. #elif CPU_MHZ == 180
  327. static const uint32_t K_SIM_CLKDIV2_USBDIV = 0 ;
  328. #elif CPU_MHZ == 168
  329. static const uint32_t K_SIM_CLKDIV2_USBDIV = 6 ;
  330. #elif CPU_MHZ == 144
  331. static const uint32_t K_SIM_CLKDIV2_USBDIV = 2 ;
  332. #elif CPU_MHZ == 120
  333. static const uint32_t K_SIM_CLKDIV2_USBDIV = 4 ;
  334. #elif CPU_MHZ == 96
  335. static const uint32_t K_SIM_CLKDIV2_USBDIV = 1 ;
  336. #elif CPU_MHZ == 72
  337. static const uint32_t K_SIM_CLKDIV2_USBDIV = 2 ;
  338. #elif CPU_MHZ == 48
  339. static const uint32_t K_SIM_CLKDIV2_USBDIV = 1 ;
  340. #elif CPU_MHZ == 24
  341. static const uint32_t K_SIM_CLKDIV2_USBDIV = 1 ;
  342. #else
  343. #error "CPU_MHZ has an invalid value"
  344. static const uint32_t K_SIM_CLKDIV2_USBDIV = 0 ;
  345. #endif
  346. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  347. // BOOT ROUTINE
  348. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  349. void startPhase1 (void) {
  350. //--------------------------------------------------- Disable watchdog timer
  351. //--- These two instructions are required for unlocking watchdog timer
  352. WDOG_UNLOCK = 0xC520 ;
  353. WDOG_UNLOCK = 0xD928 ;
  354. //--- Disable watchdog timer
  355. WDOG_STCTRLH = 0 ;
  356. //--------------------------------------------------- Enable clocks to always-used peripherals
  357. SIM_SCGC3 = SIM_SCGC3_ADC1 | SIM_SCGC3_FTM2 | SIM_SCGC3_FTM3 ;
  358. SIM_SCGC5 = SIM_SCGC5_PORTA | SIM_SCGC5_PORTB | SIM_SCGC5_PORTC | SIM_SCGC5_PORTD | SIM_SCGC5_PORTE ; // clocks active to all GPIO
  359. SIM_SCGC6 = SIM_SCGC6_RTC | SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTF ;
  360. // SCB_CPACR = 0x00F0_0000; // Enable floating point unit
  361. LMEM_PCCCR = LMEM_PCCCR_GO | LMEM_PCCCR_INVW1 | LMEM_PCCCR_INVW0 | LMEM_PCCCR_ENWRBUF | LMEM_PCCCR_ENCACHE ;
  362. //--- If the RTC oscillator isn't enabled, get it started early
  363. if ((RTC_CR & RTC_CR_OSCE) != 0) {
  364. RTC_SR = 0;
  365. RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE;
  366. }
  367. //--- Release I/O pins hold, if we woke up from VLLS mode
  368. if (PMC_REGSC & PMC_REGSC_ACKISO) {
  369. PMC_REGSC |= PMC_REGSC_ACKISO;
  370. }
  371. //---------------------------------------------------
  372. //--- Since this is a write once register, make it visible to all F_CPU's
  373. // so we can into other sleep modes in the future at any speed
  374. SMC_PMPROT = SMC_PMPROT_AHSRUN | SMC_PMPROT_AVLP | SMC_PMPROT_ALLS | SMC_PMPROT_AVLLS;
  375. //--------------------------------------------------- PLL initialization (start in FEI mode)
  376. //--- Enable capacitors for crystal
  377. OSC_CR = OSC_CR_SC8P | OSC_CR_SC2P | OSC_CR_ERCLKEN;
  378. //--- Enable osc, 8-32 MHz range, low power mode
  379. MCG_C2 = MCG_C2_RANGE (2) | MCG_C2_EREFS;
  380. //--- Switch to crystal as clock source, FLL input = 16 MHz / 512
  381. MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(4);
  382. //--- Wait for crystal oscillator to begin
  383. while ((MCG_S & MCG_S_OSCINIT0) == 0) {}
  384. //--- Wait for FLL to use oscillator
  385. while ((MCG_S & MCG_S_IREFST) != 0) {}
  386. //--- Wait for MCGOUT to use oscillator
  387. while ((MCG_S & MCG_S_CLKST (3)) != MCG_S_CLKST(2)) {}
  388. //--- Now we're in FBE mode
  389. //------------------------------------ Read microcontroller serial number
  390. // This SHOULD be done in normal mode (not in HSRUN mode)
  391. // We cannot store result in RAM, BSS section will be cleared (see below)
  392. const uint32_t serialNumber = readMicrocontrollerSerialNumber () ;
  393. //------------------------------------ Turn on the PLL
  394. SMC_PMCTRL = SMC_PMCTRL_RUNM (3); // enter HSRUN mode
  395. while (SMC_PMSTAT != SMC_PMPROT_AHSRUN) {} // wait for HSRUN
  396. //--- Configure CPU clock
  397. MCG_C5 = K_MCG_C5_PRDIV ;
  398. MCG_C6 = MCG_C6_PLLS | K_MCG_C6_VDIV ;
  399. //--- Wait for PLL to start using xtal as its input
  400. while (!(MCG_S & MCG_S_PLLST)) {}
  401. //--- Wait for PLL to lock
  402. while (!(MCG_S & MCG_S_LOCK0)) {}
  403. //------------------------------------ Now we're in PBE mode: program the clock dividers
  404. SIM_CLKDIV1 =
  405. SIM_CLKDIV1_OUTDIV1(K_SIM_CLKDIV1_OUTDIV1)
  406. | SIM_CLKDIV1_OUTDIV2(K_SIM_CLKDIV1_OUTDIV2)
  407. | SIM_CLKDIV1_OUTDIV3(K_SIM_CLKDIV1_OUTDIV3)
  408. | SIM_CLKDIV1_OUTDIV4(K_SIM_CLKDIV1_OUTDIV4)
  409. ;
  410. SIM_CLKDIV2 =
  411. SIM_CLKDIV2_USBDIV (K_SIM_CLKDIV2_USBDIV)
  412. | K_SIM_CLKDIV2_USBFRAC
  413. ;
  414. //--- Switch to PLL as clock source
  415. MCG_C1 = MCG_C1_CLKS(0) | MCG_C1_FRDIV(4);
  416. //--- Wait for PLL clock to be used
  417. while ((MCG_S & MCG_S_CLKST (3)) != MCG_S_CLKST(3)) {}
  418. //--- USB clock
  419. SIM_SOPT2 =
  420. SIM_SOPT2_USBSRC
  421. | (K_SIM_SOPT2_PLLFLLSEL << 16)
  422. | SIM_SOPT2_TRACECLKSEL
  423. ;
  424. //------------------------------------ Clear '.bss' section
  425. extern uint32_t __bss_start ;
  426. extern const uint32_t __bss_end ;
  427. uint32_t * p = & __bss_start ;
  428. while (p != & __bss_end) {
  429. * p = 0 ;
  430. p ++ ;
  431. }
  432. //------------------------------------ Copy .data section in RAM
  433. extern uint32_t __data_start ;
  434. extern const uint32_t __data_end ;
  435. extern uint32_t __data_load_start ;
  436. uint32_t * pSrc = & __data_load_start ;
  437. uint32_t * pDest = & __data_start ;
  438. while (pDest != & __data_end) {
  439. * pDest = * pSrc ;
  440. pDest ++ ;
  441. pSrc ++ ;
  442. }
  443. //------------------------------------ Now, we can store serial number
  444. gMicrocontrollerSerialNumber = serialNumber ;
  445. }
  446. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  447. // MICROCONTROLLER SERIAL NUMBER
  448. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  449. static uint32_t readMicrocontrollerSerialNumber (void) {
  450. while ((FTFE_FSTAT & FTFE_FSTAT_CCIF) == 0) {} // Wait
  451. FTFE_FSTAT = FTFE_FSTAT_RDCOLERR | FTFE_FSTAT_ACCERR | FTFE_FSTAT_FPVIOL;
  452. //--- FTFE_FCCOB3 is a 8-bit register, followed by 3 other 8-bit registers, we write value by a single 32-bit access)
  453. FTFE_FCCOB_0_3 = 0x41070000 ;
  454. FTFE_FSTAT = FTFE_FSTAT_CCIF ;
  455. while ((FTFE_FSTAT & FTFE_FSTAT_CCIF) == 0) {} // Wait
  456. //--- Read serial number (FTFE_FCCOBB is a 8-bit register, followed by 3 other 8-bit registers, we get the serial number with a single 32-bit access)
  457. return FTFE_FCCOB_8_11 ;
  458. }
  459. //······················································································································
  460. uint32_t microcontrollerSerialNumber (void) {
  461. return gMicrocontrollerSerialNumber ;
  462. }
  463. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
  464. void startPhase2 (void) {
  465. //------------------------------------ Aller exécuter les routines d'initialisation de la section boot.routine.array
  466. extern void (* __boot_routine_array_start) (void) ;
  467. extern void (* __boot_routine_array_end) (void) ;
  468. void (* * ptr) (void) = & __boot_routine_array_start ;
  469. while (ptr != & __boot_routine_array_end) {
  470. (* ptr) () ;
  471. ptr ++ ;
  472. }
  473. //------------------------------------ Run C++ global variable constructors
  474. extern void (* __constructor_array_start) (void) ;
  475. extern void (* __constructor_array_end) (void) ;
  476. ptr = & __constructor_array_start ;
  477. while (ptr != & __constructor_array_end) {
  478. (* ptr) () ;
  479. ptr ++ ;
  480. }
  481. //------------------------------------ Aller exécuter les routines d'initialisation de la section init.routine.array
  482. extern void (* __init_routine_array_start) (void) ;
  483. extern void (* __init_routine_array_end) (void) ;
  484. ptr = & __init_routine_array_start ;
  485. while (ptr != & __init_routine_array_end) {
  486. (* ptr) () ;
  487. ptr ++ ;
  488. }
  489. }
  490. //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————