123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- #include "all-headers.h"
- // MICROCONTROLLER SERIAL NUMBER
- static uint32_t gMicrocontrollerSerialNumber ;
- static uint32_t readMicrocontrollerSerialNumber (void) ;
- // CLOCK SETTINGS
- // The MCGCLOCKOUT frequency is given by (the 16 MHz quartz frequency is divided by 2 for the PPL)
- // MCGCLOCKOUT = 16 MHz / 2 * (MCG:C6:VDIV + 16) / (MCG:C5:PRDIV + 1)
- // CPU CLOCK
- // The CPU Clock is given by: MCGCLOCKOUT / (SIM:CLKDIV1:OUTDIV1 + 1)
- //
- // Here, CPU_MHZ is a given constant, so we only check that settings are correct by asserting:
- // CPU_MHZ * (MCG:C5:PRDIV + 1) * (SIM:CLKDIV1:OUTDIV1 + 1) = (16 MHz / 2) * (MCG:C6:VDIV + 16)
- // BUS (peripheral) CLOCK
- // The peripheral Clock is given by: MCGCLOCKOUT / (SIM:CLKDIV1:OUTDIV2 + 1)
- //
- // Here, SIM:CLKDIV1:OUTDIV2 is a given constant, so we compute BUS_MHZ by:
- // BUS_MHZ = (16 MHz / 2) * (MCG:C6:VDIV + 16) / (MCG:C5:PRDIV + 1) / (SIM:CLKDIV1:OUTDIV2 + 1)
- // Flexbus CLOCK
- // The Flexbus Clock is given by: MCGCLOCKOUT / (SIM:CLKDIV1:OUTDIV3 + 1)
- //
- // Here, SIM:CLKDIV1:OUTDIV3 is a given constant, so we compute FLEXBUS_MHZ by:
- // FLEXBUS_MHZ = (16 MHz / 2) * (MCG:C6:VDIV + 16) /(MCG:C5:PRDIV + 1) / (SIM:CLKDIV1:OUTDIV3 + 1)
- // Flash CLOCK
- // The FLASH Clock is given by: MCGCLOCKOUT / (SIM:CLKDIV1:OUTDIV3 + 1)
- //
- // Here, SIM:CLKDIV1:OUTDIV4 is a given constant, so we compute Flash Clock in kHz (result may not be integer):
- // FLASH_KHZ = (16000 kHz / 2) * (MCG:C6:VDIV + 16) / (MCG:C5:PRDIV + 1) / (SIM:CLKDIV1:OUTDIV4 + 1)
- // MICRO CONTROLLER REQUIREMENTS
- // The clock dividers are programmed via the SIM module’s CLKDIV registers. Each divider is programmable from a
- // divide-by-1 through divide-by-16 setting. The following requirements must be met when configuring the clocks
- // for this device:
- // 1. The core and system clock frequencies must be 180 MHz or slower in HSRUN, 120 MHz or slower in RUN.
- // 2. The bus clock frequency must be programmed to 60 MHz or less in HSRUN or RUN, and an integer divide of the
- // core clock. The core clock to bus clock ratio is limited to a max value of 8.
- // 3. The flash clock frequency must be programmed to 28 MHz or less, less than or equal to the bus clock, and an
- // integer divide of the core clock. The core clock to flash clock ratio is limited to a max value of 8.
- // 4. The FlexBus clock frequency must be programmed to be less than or equal to the bus clock frequency. The
- // FlexBus also has pad interface restrictions that limits the maximum frequency. For this device the FlexBus
- // maximum frequency is 60 MHz. The core clock to FlexBus clock ratio is limited to a max value of 8.
- // 5. Since SDRAMC and FlexBus both use CLKOUT, the same restrictions apply to the SDRAM controller as stated
- // for the FlexBus clock.
- // SETTING SUMMARY
- // F_CPU MCG_C5 MCG_C6 SIM_CLKDIV1 SIM_CLKDIV1 SIM_CLKDIV1 SIM_CLKDIV1 BUS_MHZ FLEXBUS FLASH
- // _MHZ _PRDIV _VDIV _OUTDIV1 _OUTDIV2 _OUTDIV3 _OUTDIV4 _MHZ _KHZ
- // 240 0 14 0 3 0 7 60 240 30 000
- // 216 0 11 0 1 0 7 54 216 27 000
- // 192 0 8 0 1 0 6 28 192 27 428
- // 180 1 29 0 1 0 6 60 180 25 714
- // 168 0 5 0 2 0 5 56 168 28 000
- // 144 0 2 0 1 0 4 28 144 28 800
- // 120 1 14 0 1 0 4 60 120 24 000
- // 96 1 8 0 1 0 2 24 96 24 000
- // 72 1 2 0 0 0 2 36 72 24 000
- // 48 1 8 1 1 1 3 48 48 24 000
- // 24 1 8 3 3 3 3 24 24 24 000
- // PRDIV SETTINGS
- #ifndef CPU_MHZ
- #error "CPU_MHZ is not defined"
- static const uint32_t K_MCG_C5_PRDIV = 0 ;
- #elif CPU_MHZ == 240
- static const uint32_t K_MCG_C5_PRDIV = 0 ;
- #elif CPU_MHZ == 216
- static const uint32_t K_MCG_C5_PRDIV = 0 ;
- #elif CPU_MHZ == 192
- static const uint32_t K_MCG_C5_PRDIV = 0 ;
- #elif CPU_MHZ == 180
- static const uint32_t K_MCG_C5_PRDIV = 1 ;
- #elif CPU_MHZ == 168
- static const uint32_t K_MCG_C5_PRDIV = 0 ;
- #elif CPU_MHZ == 144
- static const uint32_t K_MCG_C5_PRDIV = 0 ;
- #elif CPU_MHZ == 120
- static const uint32_t K_MCG_C5_PRDIV = 1 ;
- #elif CPU_MHZ == 96
- static const uint32_t K_MCG_C5_PRDIV = 1 ;
- #elif CPU_MHZ == 72
- static const uint32_t K_MCG_C5_PRDIV = 1 ;
- #elif CPU_MHZ == 48
- static const uint32_t K_MCG_C5_PRDIV = 1 ;
- #elif CPU_MHZ == 24
- static const uint32_t K_MCG_C5_PRDIV = 1 ;
- #else
- #error "CPU_MHZ has an invalid value"
- static const uint32_t K_MCG_C5_PRDIV = 0 ;
- #endif
- // MCG:C6:VDIV SETTINGS
- #ifndef CPU_MHZ
- #error "CPU_MHZ is not defined"
- static const uint32_t K_MCG_C6_VDIV = 0 ;
- #elif CPU_MHZ == 240
- static const uint32_t K_MCG_C6_VDIV = 14 ;
- #elif CPU_MHZ == 216
- static const uint32_t K_MCG_C6_VDIV = 11 ;
- #elif CPU_MHZ == 192
- static const uint32_t K_MCG_C6_VDIV = 8 ;
- #elif CPU_MHZ == 180
- static const uint32_t K_MCG_C6_VDIV = 29 ;
- #elif CPU_MHZ == 168
- static const uint32_t K_MCG_C6_VDIV = 5 ;
- #elif CPU_MHZ == 144
- static const uint32_t K_MCG_C6_VDIV = 2 ;
- #elif CPU_MHZ == 120
- static const uint32_t K_MCG_C6_VDIV = 14 ;
- #elif CPU_MHZ == 96
- static const uint32_t K_MCG_C6_VDIV = 8 ;
- #elif CPU_MHZ == 72
- static const uint32_t K_MCG_C6_VDIV = 2 ;
- #elif CPU_MHZ == 48
- static const uint32_t K_MCG_C6_VDIV = 8 ;
- #elif CPU_MHZ == 24
- static const uint32_t K_MCG_C6_VDIV = 8 ;
- #else
- #error "CPU_MHZ has an invalid value"
- static const uint32_t K_MCG_C6_VDIV = 0 ;
- #endif
- // SIM:CLKDIV1:OUTDIV1 SETTINGS
- #ifndef CPU_MHZ
- #error "CPU_MHZ is not defined"
- static const uint32_t K_SIM_CLKDIV1_OUTDIV1 = 0 ;
- #elif CPU_MHZ == 48
- static const uint32_t K_SIM_CLKDIV1_OUTDIV1 = 1 ;
- #elif CPU_MHZ == 24
- static const uint32_t K_SIM_CLKDIV1_OUTDIV1 = 3 ;
- #else
- static const uint32_t K_SIM_CLKDIV1_OUTDIV1 = 0 ; // 0 for all other settings
- #endif
- // SIM:CLKDIV1:OUTDIV2 SETTINGS (divisor for bus)
- #ifndef CPU_MHZ
- #error "CPU_MHZ is not defined"
- static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 0 ;
- #elif CPU_MHZ == 240
- static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 3 ;
- #elif CPU_MHZ == 216
- static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 3 ;
- #elif CPU_MHZ == 192
- static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 3 ;
- #elif CPU_MHZ == 180
- static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 2 ;
- #elif CPU_MHZ == 168
- static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 2 ;
- #elif CPU_MHZ == 144
- static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 2 ;
- #elif CPU_MHZ == 120
- static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 1 ;
- #elif CPU_MHZ == 96
- static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 1 ;
- #elif CPU_MHZ == 72
- static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 1 ;
- #elif CPU_MHZ == 48
- static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 1 ;
- #elif CPU_MHZ == 24
- static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 3 ;
- #else
- #error "CPU_MHZ has an invalid value"
- static const uint32_t K_SIM_CLKDIV1_OUTDIV2 = 0 ;
- #endif
- // BUS_MHZ
- static const uint32_t BUS_MHZ = (16 / 2) * (K_MCG_C6_VDIV + 16) /(K_MCG_C5_PRDIV + 1) / (K_SIM_CLKDIV1_OUTDIV2 + 1) ;
- uint32_t busMHZ (void) {
- return BUS_MHZ ;
- }
- // SIM:CLKDIV1:OUTDIV3 SETTINGS (divisor for Flexbus)
- #ifndef CPU_MHZ
- #error "CPU_MHZ is not defined"
- static const uint32_t K_SIM_CLKDIV1_OUTDIV3 = 0 ;
- #elif CPU_MHZ == 48
- static const uint32_t K_SIM_CLKDIV1_OUTDIV3 = 1 ;
- #elif CPU_MHZ == 24
- static const uint32_t K_SIM_CLKDIV1_OUTDIV3 = 3 ;
- #else
- static const uint32_t K_SIM_CLKDIV1_OUTDIV3 = 0 ; // 0 for all other settings
- #endif
- // FLEXBUS_MHZ
- static const uint32_t FLEXBUS_MHZ = (16 / 2) * (K_MCG_C6_VDIV + 16) /(K_MCG_C5_PRDIV + 1) / (K_SIM_CLKDIV1_OUTDIV3 + 1) ;
- uint32_t FlexBusMHZ (void) {
- return FLEXBUS_MHZ ;
- }
- // SIM:CLKDIV1:OUTDIV4 SETTINGS (divisor for Flash)
- #ifndef CPU_MHZ
- #error "CPU_MHZ is not defined"
- static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 0 ;
- #elif CPU_MHZ == 240
- static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 7 ;
- #elif CPU_MHZ == 216
- static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 7 ;
- #elif CPU_MHZ == 192
- static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 6 ;
- #elif CPU_MHZ == 180
- static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 6 ;
- #elif CPU_MHZ == 168
- static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 5 ;
- #elif CPU_MHZ == 144
- static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 4 ;
- #elif CPU_MHZ == 120
- static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 4 ;
- #elif CPU_MHZ == 96
- static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 3 ;
- #elif CPU_MHZ == 72
- static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 2 ;
- #elif CPU_MHZ == 48
- static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 3 ;
- #elif CPU_MHZ == 24
- static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 3 ;
- #else
- #error "CPU_MHZ has an invalid value"
- static const uint32_t K_SIM_CLKDIV1_OUTDIV4 = 0 ;
- #endif
- // FLASH CLOCK (in kHz)
- static const uint32_t FLASH_KHZ = (16000 / 2) * (K_MCG_C6_VDIV + 16) / (K_MCG_C5_PRDIV + 1) / (K_SIM_CLKDIV1_OUTDIV4 + 1) ;
- uint32_t FlashKHz (void) {
- return FLASH_KHZ ;
- }
- // USB CLOCK
- // The USB module SHOULD be driven by a 48 MHz clock.
- //
- // For all CPU frequencies (but 216 MHz and 180 MHz), this clock is derived from MCGPLLCLK; the MCGPLLCLK is
- // identical to MCGCLOCKOUT (as SIM_CLKDIV2_PLL_FLL_SEL=1). So:
- // USB_CLOCK = MCGCLOCKOUT * (K_SIM_CLKDIV2_USBFRAC + 1) / (K_SIM_CLKDIV2_USBDIV + 1)
- // We check :
- // 48 MHz == 16 MHz / 2 * (MCG:C6:VDIV + 16) / (MCG:C5:PRDIV + 1) * (K_SIM_CLKDIV2_USBFRAC + 1) / (K_SIM_CLKDIV2_USBDIV + 1)
- // So:
- // 6 * (MCG:C5:PRDIV + 1) * (K_SIM_CLKDIV2_USBDIV + 1) == (MCG:C6:VDIV + 16) * (K_SIM_CLKDIV2_USBFRAC + 1)
- //
- // For 216 MHz and 180 MHz CPU frequencies, we use directly the built-in 48 MHz clock: SIM_CLKDIV2_PLL_FLL_SEL=3, with
- // di divisor (K_SIM_CLKDIV2_USBFRAC=0 and K_SIM_CLKDIV2_USBDIV=0).
- // USB SETTING SUMMARY
- // F_CPU SIM_CLKDIV2 SIM_CLKDIV2 SIM_SOPT2_
- // _MHZ _USBDIV _USBFRAC PLLFLLSEL
- // 240 4 0 1
- // 216 0 0 3
- // 192 3 0 1
- // 180 0 0 3
- // 168 6 1 1
- // 144 2 0 1
- // 120 4 1 1
- // 96 1 0 1
- // 72 2 1 1
- // 48 1 0 1
- // 24 1 0 1
- // SIM:SOPT2:PLLFLLSEL SETTINGS
- #ifndef CPU_MHZ
- #error "CPU_MHZ is not defined"
- static const uint32_t K_SIM_SOPT2_PLLFLLSEL = 0 ;
- #elif CPU_MHZ == 216
- static const uint32_t K_SIM_SOPT2_PLLFLLSEL = 3 ;
- #elif CPU_MHZ == 180
- static const uint32_t K_SIM_SOPT2_PLLFLLSEL = 3 ;
- #else
- static const uint32_t K_SIM_SOPT2_PLLFLLSEL = 1 ; // For all other settings
- #endif
- // SIM:CLKDIV2:USBFRAC SETTINGS
- #ifndef CPU_MHZ
- #error "CPU_MHZ is not defined"
- static const uint32_t K_SIM_CLKDIV2_USBFRAC = 0 ;
- #elif CPU_MHZ == 168
- static const uint32_t K_SIM_CLKDIV2_USBFRAC = 1 ;
- #elif CPU_MHZ == 120
- static const uint32_t K_SIM_CLKDIV2_USBFRAC = 1 ;
- #elif CPU_MHZ == 72
- static const uint32_t K_SIM_CLKDIV2_USBFRAC = 1 ;
- #else
- static const uint32_t K_SIM_CLKDIV2_USBFRAC = 0 ; // For all other settings
- #endif
- // SIM:CLKDIV2:USBDIV SETTINGS
- #ifndef CPU_MHZ
- #error "CPU_MHZ is not defined"
- static const uint32_t K_SIM_CLKDIV2_USBDIV = 0 ;
- #elif CPU_MHZ == 240
- static const uint32_t K_SIM_CLKDIV2_USBDIV = 4 ;
- #elif CPU_MHZ == 216
- static const uint32_t K_SIM_CLKDIV2_USBDIV = 0 ;
- #elif CPU_MHZ == 192
- static const uint32_t K_SIM_CLKDIV2_USBDIV = 3 ;
- #elif CPU_MHZ == 180
- static const uint32_t K_SIM_CLKDIV2_USBDIV = 0 ;
- #elif CPU_MHZ == 168
- static const uint32_t K_SIM_CLKDIV2_USBDIV = 6 ;
- #elif CPU_MHZ == 144
- static const uint32_t K_SIM_CLKDIV2_USBDIV = 2 ;
- #elif CPU_MHZ == 120
- static const uint32_t K_SIM_CLKDIV2_USBDIV = 4 ;
- #elif CPU_MHZ == 96
- static const uint32_t K_SIM_CLKDIV2_USBDIV = 1 ;
- #elif CPU_MHZ == 72
- static const uint32_t K_SIM_CLKDIV2_USBDIV = 2 ;
- #elif CPU_MHZ == 48
- static const uint32_t K_SIM_CLKDIV2_USBDIV = 1 ;
- #elif CPU_MHZ == 24
- static const uint32_t K_SIM_CLKDIV2_USBDIV = 1 ;
- #else
- #error "CPU_MHZ has an invalid value"
- static const uint32_t K_SIM_CLKDIV2_USBDIV = 0 ;
- #endif
- // BOOT ROUTINE
- void startPhase1 (void) {
- // Disable watchdog timer
- // These two instructions are required for unlocking watchdog timer
- WDOG_UNLOCK = 0xC520 ;
- WDOG_UNLOCK = 0xD928 ;
- // Disable watchdog timer
- WDOG_STCTRLH = 0 ;
- // Enable clocks to always-used peripherals
- SIM_SCGC3 = SIM_SCGC3_ADC1 | SIM_SCGC3_FTM2 | SIM_SCGC3_FTM3 ;
- SIM_SCGC5 = SIM_SCGC5_PORTA | SIM_SCGC5_PORTB | SIM_SCGC5_PORTC | SIM_SCGC5_PORTD | SIM_SCGC5_PORTE ; // clocks active to all GPIO
- SIM_SCGC6 = SIM_SCGC6_RTC | SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTF ;
- // SCB_CPACR = 0x00F0_0000; // Enable floating point unit
- LMEM_PCCCR = LMEM_PCCCR_GO | LMEM_PCCCR_INVW1 | LMEM_PCCCR_INVW0 | LMEM_PCCCR_ENWRBUF | LMEM_PCCCR_ENCACHE ;
- // If the RTC oscillator isn't enabled, get it started early
- if ((RTC_CR & RTC_CR_OSCE) != 0) {
- RTC_SR = 0;
- RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE;
- }
- // Release I/O pins hold, if we woke up from VLLS mode
- if (PMC_REGSC & PMC_REGSC_ACKISO) {
- PMC_REGSC |= PMC_REGSC_ACKISO;
- }
- // Since this is a write once register, make it visible to all F_CPU's
- // so we can into other sleep modes in the future at any speed
- SMC_PMPROT = SMC_PMPROT_AHSRUN | SMC_PMPROT_AVLP | SMC_PMPROT_ALLS | SMC_PMPROT_AVLLS;
- // PLL initialization (start in FEI mode)
- // Enable capacitors for crystal
- OSC_CR = OSC_CR_SC8P | OSC_CR_SC2P | OSC_CR_ERCLKEN;
- // Enable osc, 8-32 MHz range, low power mode
- MCG_C2 = MCG_C2_RANGE (2) | MCG_C2_EREFS;
- // Switch to crystal as clock source, FLL input = 16 MHz / 512
- MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(4);
- // Wait for crystal oscillator to begin
- while ((MCG_S & MCG_S_OSCINIT0) == 0) {}
- // Wait for FLL to use oscillator
- while ((MCG_S & MCG_S_IREFST) != 0) {}
- // Wait for MCGOUT to use oscillator
- while ((MCG_S & MCG_S_CLKST (3)) != MCG_S_CLKST(2)) {}
- // Now we're in FBE mode
- // Read microcontroller serial number
- // This SHOULD be done in normal mode (not in HSRUN mode)
- // We cannot store result in RAM, BSS section will be cleared (see below)
- const uint32_t serialNumber = readMicrocontrollerSerialNumber () ;
- // Turn on the PLL
- SMC_PMCTRL = SMC_PMCTRL_RUNM (3); // enter HSRUN mode
- while (SMC_PMSTAT != SMC_PMPROT_AHSRUN) {} // wait for HSRUN
- // Configure CPU clock
- MCG_C5 = K_MCG_C5_PRDIV ;
- MCG_C6 = MCG_C6_PLLS | K_MCG_C6_VDIV ;
- // Wait for PLL to start using xtal as its input
- while (!(MCG_S & MCG_S_PLLST)) {}
- // Wait for PLL to lock
- while (!(MCG_S & MCG_S_LOCK0)) {}
- // Now we're in PBE mode: program the clock dividers
- SIM_CLKDIV1 =
- SIM_CLKDIV1_OUTDIV1(K_SIM_CLKDIV1_OUTDIV1)
- | SIM_CLKDIV1_OUTDIV2(K_SIM_CLKDIV1_OUTDIV2)
- | SIM_CLKDIV1_OUTDIV3(K_SIM_CLKDIV1_OUTDIV3)
- | SIM_CLKDIV1_OUTDIV4(K_SIM_CLKDIV1_OUTDIV4)
- ;
- SIM_CLKDIV2 =
- SIM_CLKDIV2_USBDIV (K_SIM_CLKDIV2_USBDIV)
- | K_SIM_CLKDIV2_USBFRAC
- ;
- // Switch to PLL as clock source
- MCG_C1 = MCG_C1_CLKS(0) | MCG_C1_FRDIV(4);
- // Wait for PLL clock to be used
- while ((MCG_S & MCG_S_CLKST (3)) != MCG_S_CLKST(3)) {}
- // USB clock
- SIM_SOPT2 =
- SIM_SOPT2_USBSRC
- | (K_SIM_SOPT2_PLLFLLSEL << 16)
- | SIM_SOPT2_TRACECLKSEL
- ;
- // Clear '.bss' section
- extern uint32_t __bss_start ;
- extern const uint32_t __bss_end ;
- uint32_t * p = & __bss_start ;
- while (p != & __bss_end) {
- * p = 0 ;
- p ++ ;
- }
- // Copy .data section in RAM
- extern uint32_t __data_start ;
- extern const uint32_t __data_end ;
- extern uint32_t __data_load_start ;
- uint32_t * pSrc = & __data_load_start ;
- uint32_t * pDest = & __data_start ;
- while (pDest != & __data_end) {
- * pDest = * pSrc ;
- pDest ++ ;
- pSrc ++ ;
- }
- // Now, we can store serial number
- gMicrocontrollerSerialNumber = serialNumber ;
- }
- // MICROCONTROLLER SERIAL NUMBER
- static uint32_t readMicrocontrollerSerialNumber (void) {
- while ((FTFE_FSTAT & FTFE_FSTAT_CCIF) == 0) {} // Wait
- FTFE_FSTAT = FTFE_FSTAT_RDCOLERR | FTFE_FSTAT_ACCERR | FTFE_FSTAT_FPVIOL;
- // FTFE_FCCOB3 is a 8-bit register, followed by 3 other 8-bit registers, we write value by a single 32-bit access)
- FTFE_FCCOB_0_3 = 0x41070000 ;
- FTFE_FSTAT = FTFE_FSTAT_CCIF ;
- while ((FTFE_FSTAT & FTFE_FSTAT_CCIF) == 0) {} // Wait
- // 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)
- return FTFE_FCCOB_8_11 ;
- }
- uint32_t microcontrollerSerialNumber (void) {
- return gMicrocontrollerSerialNumber ;
- }
- void startPhase2 (void) {
- // Aller exécuter les routines d'initialisation de la section boot.routine.array
- extern void (* __boot_routine_array_start) (void) ;
- extern void (* __boot_routine_array_end) (void) ;
- void (* * ptr) (void) = & __boot_routine_array_start ;
- while (ptr != & __boot_routine_array_end) {
- (* ptr) () ;
- ptr ++ ;
- }
- // Run C++ global variable constructors
- extern void (* __constructor_array_start) (void) ;
- extern void (* __constructor_array_end) (void) ;
- ptr = & __constructor_array_start ;
- while (ptr != & __constructor_array_end) {
- (* ptr) () ;
- ptr ++ ;
- }
- // Aller exécuter les routines d'initialisation de la section init.routine.array
- extern void (* __init_routine_array_start) (void) ;
- extern void (* __init_routine_array_end) (void) ;
- ptr = & __init_routine_array_start ;
- while (ptr != & __init_routine_array_end) {
- (* ptr) () ;
- ptr ++ ;
- }
- }
|