start-teensy-3-6.cpp 18 KB

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