X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Flpc%2Fao_timer_lpc.c;h=44fb410e7f522b642d1a68f965f46681690a3d74;hb=2fa87754c5c11bb86e9b1878580c3d4f4b2463f5;hp=aa796acf9b0da1f2a7c84486a44e4ff8cfffd6bc;hpb=bcc65597d3d20f1d58df784100af766cee5f0f20;p=fw%2Faltos diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index aa796acf..44fb410e 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -61,7 +61,7 @@ ao_timer_set_adc_interval(uint8_t interval) } #endif -#define SYSTICK_RELOAD ((AO_LPC_CLKOUT / 2) / 100 - 1) +#define SYSTICK_RELOAD ((AO_LPC_SYSCLK / 2) / 100 - 1) /* Initialize our 100Hz clock */ void @@ -78,6 +78,14 @@ ao_timer_init(void) #define AO_LPC_FCCO_MIN 156000000 +static void +ao_clock_delay(void) +{ + uint32_t i; + for (i = 0; i < 200; i++) + ao_arch_nop(); +} + void ao_clock_init(void) { @@ -92,13 +100,32 @@ ao_clock_init(void) (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO) | (1 << LPC_SCB_SYSAHBCLKCTRL_IOCON)); + /* Enable the brown-out detection at the highest voltage to + * make sure the flash part remains happy + */ + + lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_BOD_PD); + lpc_scb.bodctrl = ((LPC_SCB_BOD_BODRSTLEV_2_63 << LPC_SCB_BOD_BODRSTLEV) | + (LPC_SCB_BOD_BODINTVAL_RESERVED << LPC_SCB_BOD_BODINTVAL) | + (1 << LPC_SCB_BOD_BODRSTENA)); + /* Turn the IRC clock back on */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_IRC_PD); + ao_clock_delay(); /* Switch to the IRC clock */ lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_IRC << LPC_SCB_MAINCLKSEL_SEL; lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA); lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); + while (!(lpc_scb.mainclkuen & (1 << LPC_SCB_MAINCLKUEN_ENA))) + ; + + /* Switch USB to the main clock */ + lpc_scb.usbclksel = (LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK << LPC_SCB_USBCLKSEL_SEL); + lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA); + lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA); + while (!(lpc_scb.usbclkuen & (1 << LPC_SCB_USBCLKUEN_ENA))) + ; /* Find a PLL post divider ratio that gets the FCCO in range */ for (p = 0; p < 4; p++) @@ -110,14 +137,15 @@ ao_clock_init(void) /* Power down the PLL before touching the registers */ lpc_scb.pdruncfg |= (1 << LPC_SCB_PDRUNCFG_SYSPLL_PD); + ao_clock_delay(); /* Set PLL divider values */ lpc_scb.syspllctrl = ((AO_LPC_M << LPC_SCB_SYSPLLCTRL_MSEL) | (p << LPC_SCB_SYSPLLCTRL_PSEL)); - /* Turn off the external crystal clock */ lpc_scb.pdruncfg |= (1 << LPC_SCB_PDRUNCFG_SYSOSC_PD); + ao_clock_delay(); /* Configure the crystal clock */ lpc_scb.sysoscctrl = ((0 << LPC_SCB_SYSOSCCTRL_BYPASS) | /* using a crystal */ @@ -125,12 +153,16 @@ ao_clock_init(void) /* Turn on the external crystal clock */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSOSC_PD); + ao_clock_delay(); /* Select crystal as PLL input */ lpc_scb.syspllclksel = (LPC_SCB_SYSPLLCLKSEL_SEL_SYSOSC << LPC_SCB_SYSPLLCLKSEL_SEL); - lpc_scb.syspllclkuen = 0; lpc_scb.syspllclkuen = (1 << LPC_SCB_SYSPLLCLKUEN_ENA); + lpc_scb.syspllclkuen = (0 << LPC_SCB_SYSPLLCLKUEN_ENA); + lpc_scb.syspllclkuen = (1 << LPC_SCB_SYSPLLCLKUEN_ENA); + while (!(lpc_scb.syspllclkuen & (1 << LPC_SCB_SYSPLLCLKUEN_ENA))) + ; /* Turn on the PLL */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSPLL_PD); @@ -145,21 +177,37 @@ ao_clock_init(void) /* Switch to the PLL */ lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_PLL_OUTPUT << LPC_SCB_MAINCLKSEL_SEL; - lpc_scb.mainclkuen = 0 << LPC_SCB_MAINCLKUEN_ENA; - lpc_scb.mainclkuen = 1 << LPC_SCB_MAINCLKUEN_ENA; + lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); + lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA); + lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); + while (!(lpc_scb.mainclkuen & (1 << LPC_SCB_MAINCLKUEN_ENA))) + ; /* Set system clock divider */ lpc_scb.sysahbclkdiv = AO_LPC_CLKOUT / AO_LPC_SYSCLK; - /* Set USB clock source */ - lpc_scb.usbclksel = (LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK << LPC_SCB_USBCLKSEL_SEL); - lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA); - lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA); - /* Shut down perhipheral clocks (enabled as needed) */ lpc_scb.ssp0clkdiv = 0; lpc_scb.uartclkdiv = 0; lpc_scb.ssp1clkdiv = 0; lpc_scb.usbclkdiv = 0; lpc_scb.clkoutdiv = 0; + + /* Switch USB PLL source to system osc so we can power down the IRC */ + lpc_scb.usbpllclksel = (LPC_SCB_USBPLLCLKSEL_SEL_SYSOSC << LPC_SCB_USBPLLCLKSEL_SEL); + lpc_scb.usbpllclkuen = (0 << LPC_SCB_USBPLLCLKUEN_ENA); + lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA); + while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA))) + ; + + /* Power down everything we don't need */ + lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) | + (1 << LPC_SCB_PDRUNCFG_IRC_PD) | + (0 << LPC_SCB_PDRUNCFG_BOD_PD) | + (1 << LPC_SCB_PDRUNCFG_ADC_PD) | + (1 << LPC_SCB_PDRUNCFG_WDTOSC_PD) | + (1 << LPC_SCB_PDRUNCFG_USBPLL_PD) | + (1 << LPC_SCB_PDRUNCFG_USBPAD_PD) | + (1 << 11) | + (7 << 13)); }