aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/ports/KINETIS/K20x/hal_lld.c
diff options
context:
space:
mode:
Diffstat (limited to 'os/hal/ports/KINETIS/K20x/hal_lld.c')
-rw-r--r--os/hal/ports/KINETIS/K20x/hal_lld.c82
1 files changed, 56 insertions, 26 deletions
diff --git a/os/hal/ports/KINETIS/K20x/hal_lld.c b/os/hal/ports/KINETIS/K20x/hal_lld.c
index 1e10241..e6eeed8 100644
--- a/os/hal/ports/KINETIS/K20x/hal_lld.c
+++ b/os/hal/ports/KINETIS/K20x/hal_lld.c
@@ -39,7 +39,7 @@
#ifdef __CC_ARM
__attribute__ ((section(".ARM.__at_0x400")))
#else
-__attribute__ ((used, section(".cfmconfig")))
+__attribute__ ((used,section(".cfmconfig")))
#endif
const uint8_t _cfm[0x10] = {
0xFF, /* NV_BACKKEY3: KEY=0xFF */
@@ -84,7 +84,7 @@ void hal_lld_init(void) {
}
/**
- * @brief MK20D5 clock initialization.
+ * @brief K20x clock initialization.
* @note All the involved constants come from the file @p board.h.
* @note This function is meant to be invoked early during the system
* initialization, it is usually invoked from the file
@@ -93,16 +93,9 @@ void hal_lld_init(void) {
*
* @special
*/
-void mk20d50_clock_init(void) {
+void k20x_clock_init(void) {
#if !KINETIS_NO_INIT
-#if KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE
- uint32_t ratio, frdiv;
- uint32_t ratios[] = { 32, 64, 128, 256, 512, 1024, 1280, 1536 };
- int ratio_quantity = sizeof(ratios) / sizeof(ratios[0]);
- int i;
-#endif /* KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE */
-
/* Disable the watchdog */
WDOG->UNLOCK = 0xC520;
WDOG->UNLOCK = 0xD928;
@@ -115,14 +108,24 @@ void mk20d50_clock_init(void) {
SIM_SCGC5_PORTE;
#if KINETIS_MCG_MODE == KINETIS_MCG_MODE_FEI
+ /* This is the default mode at reset. */
/* Configure FEI mode */
MCG->C4 = MCG_C4_DRST_DRS(KINETIS_MCG_FLL_DRS) |
(KINETIS_MCG_FLL_DMX32 ? MCG_C4_DMX32 : 0);
-#endif /* KINETIS_MCG_MODE == KINETIS_MCG_MODE_FEI */
+ /* Set clock dividers */
+ SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1-1) |
+ SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2-1) |
+ SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4-1);
+ SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(0); /* not strictly necessary since usb_lld will set this */
-#if KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE
+#elif KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE
+
+ uint32_t ratio, frdiv;
+ uint32_t ratios[] = { 32, 64, 128, 256, 512, 1024, 1280, 1536 };
+ uint8_t ratio_quantity = sizeof(ratios) / sizeof(ratios[0]);
+ uint8_t i;
/* EXTAL0 and XTAL0 */
PORTA->PCR[18] = 0;
@@ -132,8 +135,13 @@ void mk20d50_clock_init(void) {
* Start in FEI mode
*/
- /* Disable capacitors for crystal */
- OSC->CR = 0;
+ /* Internal capacitors for crystal */
+#if defined(KINETIS_BOARD_OSCILLATOR_SETTING)
+ OSC0->CR = KINETIS_BOARD_OSCILLATOR_SETTING;
+#else /* KINETIS_BOARD_OSCILLATOR_SETTING */
+ /* Disable the internal capacitors */
+ OSC0->CR = 0;
+#endif /* KINETIS_BOARD_OSCILLATOR_SETTING */
/* TODO: need to add more flexible calculation, specially regarding
* divisors which may not be available depending on the XTAL
@@ -141,13 +149,13 @@ void mk20d50_clock_init(void) {
*/
/* Enable OSC, low power mode */
MCG->C2 = MCG_C2_LOCRE0 | MCG_C2_EREFS0;
- if (KINETIS_XTAL_FREQUENCY > 8000000)
+ if (KINETIS_XTAL_FREQUENCY > 8000000UL)
MCG->C2 |= MCG_C2_RANGE0(2);
else
MCG->C2 |= MCG_C2_RANGE0(1);
frdiv = 7;
- ratio = KINETIS_XTAL_FREQUENCY / 31250;
+ ratio = KINETIS_XTAL_FREQUENCY / 31250UL;
for (i = 0; i < ratio_quantity; ++i) {
if (ratio == ratios[i]) {
frdiv = i;
@@ -170,22 +178,42 @@ void mk20d50_clock_init(void) {
/*
* Now in FBE mode
*/
+ #define KINETIS_PLLIN_FREQUENCY 2000000UL
+ /*
+ * Config PLL input for 2 MHz
+ * TODO: Make sure KINETIS_XTAL_FREQUENCY >= 2Mhz && <= 50Mhz
+ */
+ MCG->C5 = MCG_C5_PRDIV0((KINETIS_XTAL_FREQUENCY/KINETIS_PLLIN_FREQUENCY) - 1);
- /* Config PLL input for 2 MHz */
- MCG->C5 = MCG_C5_PRDIV0((KINETIS_XTAL_FREQUENCY / 2000000) - 1);
-
- /* Config PLL for 96 MHz output */
- MCG->C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0);
+ /*
+ * Config PLL output to match KINETIS_SYSCLK_FREQUENCY
+ * TODO: make sure KINETIS_SYSCLK_FREQUENCY is a match
+ */
+ for(i = 24; i < 56; i++)
+ {
+ if(i == (KINETIS_PLLCLK_FREQUENCY/KINETIS_PLLIN_FREQUENCY))
+ {
+ /* Config PLL to match KINETIS_PLLCLK_FREQUENCY */
+ MCG->C6 = MCG_C6_PLLS | MCG_C6_VDIV0(i-24);
+ break;
+ }
+ }
- /* Wait for PLL to start using crystal as its input */
- while (!(MCG->S & MCG_S_PLLST));
+ if(i>=56) /* Config PLL for 96 MHz output as default setting */
+ MCG->C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0);
- /* Wait for PLL to lock */
- while (!(MCG->S & MCG_S_LOCK0));
+ /* Wait for PLL to start using crystal as its input, and to lock */
+ while ((MCG->S & (MCG_S_PLLST|MCG_S_LOCK0))!=(MCG_S_PLLST|MCG_S_LOCK0));
/*
* Now in PBE mode
*/
+ /* Set the PLL dividers for the different clocks */
+ SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1-1) |
+ SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2-1) |
+ SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4-1);
+ SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(0);
+ SIM->SOPT2 = SIM_SOPT2_PLLFLLSEL;
/* Switch to PLL as clock source */
MCG->C1 = MCG_C1_CLKS(0);
@@ -196,7 +224,9 @@ void mk20d50_clock_init(void) {
/*
* Now in PEE mode
*/
-#endif /* KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE */
+#else /* KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE */
+#error Unimplemented KINETIS_MCG_MODE
+#endif /* KINETIS_MCG_MODE == ... */
#endif /* !KINETIS_NO_INIT */
}