mirror of https://github.com/ARMmbed/mbed-os.git
Added MCGPLLFLL clock function, squished some 'bugs'
PWM bug mentioned here: https://mbed.org/questions/2315/BUG-Exporting-to-ARM-GCC-does-not-work-n/ Fast internal osc prescaler wasn't taken into account at us_ticker interrupt clock source, now it is.pull/145/head
parent
aa0f7a7026
commit
153a9ddb49
|
@ -72,8 +72,8 @@ static uint32_t extosc_frequency(void) {
|
|||
}
|
||||
} else { //PLL is selected
|
||||
divider = (1u + (MCG->C5 & MCG_C5_PRDIV0_MASK));
|
||||
multiplier = ((MCG->C6 & MCG_C6_VDIV0_MASK) + 24u);
|
||||
return MCGClock * divider / multiplier;
|
||||
multiplier = ((MCG->C6 & MCG_C6_VDIV0_MASK) + 24u);
|
||||
return MCGClock * divider / multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,23 @@ static uint32_t extosc_frequency(void) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
//Get MCG PLL/2 or FLL frequency, depending on which one is active, sets PLLFLLSEL bit
|
||||
static uint32_t mcgpllfll_frequency(void) {
|
||||
if ((MCG->C1 & MCG_C1_CLKS_MASK) != MCG_C1_CLKS(0)) //PLL/FLL is not selected
|
||||
return 0;
|
||||
|
||||
uint32_t MCGClock = SystemCoreClock * (1u + ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> SIM_CLKDIV1_OUTDIV1_SHIFT));
|
||||
if ((MCG->C6 & MCG_C6_PLLS_MASK) == 0x0u) { //FLL is selected
|
||||
SIM->SOPT2 &= ~SIM_SOPT2_PLLFLLSEL_MASK; //MCG peripheral clock is FLL output
|
||||
return MCGClock;
|
||||
} else { //PLL is selected
|
||||
SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK; //MCG peripheral clock is PLL output
|
||||
return (MCGClock >> 1);
|
||||
}
|
||||
|
||||
//It is possible the SystemCoreClock isn't running on the PLL, and the PLL is still active
|
||||
//for the peripherals, this is however an unlikely setup
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "error.h"
|
||||
#include "clk_freqs.h"
|
||||
|
||||
static const PinMap PinMap_PWM[] = {
|
||||
// LEDs
|
||||
|
@ -73,7 +74,14 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
|
|||
error("PwmOut pin mapping failed");
|
||||
|
||||
uint32_t clkdiv = 0;
|
||||
float clkval = SystemCoreClock / 1000000.0f;
|
||||
float clkval;
|
||||
if (mcgpllfll_frequency()) {
|
||||
SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); // Clock source: MCGFLLCLK or MCGPLLCLK
|
||||
clkval = mcgpllfll_frequency() / 1000000.0f;
|
||||
} else {
|
||||
SIM->SOPT2 |= SIM_SOPT2_TPMSRC(2); // Clock source: ExtOsc
|
||||
clkval = extosc_frequency() / 1000000.0f;
|
||||
}
|
||||
|
||||
while (clkval > 1) {
|
||||
clkdiv++;
|
||||
|
@ -89,7 +97,6 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
|
|||
|
||||
SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port);
|
||||
SIM->SCGC6 |= 1 << (SIM_SCGC6_TPM0_SHIFT + tpm_n);
|
||||
SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); // Clock source: MCGFLLCLK or MCGPLLCLK
|
||||
|
||||
TPM_Type *tpm = (TPM_Type *)(TPM0_BASE + 0x1000 * tpm_n);
|
||||
tpm->SC = TPM_SC_CMOD(1) | TPM_SC_PS(clkdiv); // (clock)MHz / clkdiv ~= (0.75)MHz
|
||||
|
|
|
@ -71,8 +71,8 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
|
|||
obj->uart = (UARTLP_Type *)uart;
|
||||
// enable clk
|
||||
switch (uart) {
|
||||
case UART_0: if ((MCG->C1 & MCG_C1_CLKS_MASK) == MCG_C1_CLKS(0)) //PLL/FLL is selected
|
||||
SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK | (1<<SIM_SOPT2_UART0SRC_SHIFT);
|
||||
case UART_0: if (mcgpllfll_frequency() != 0) //PLL/FLL is selected
|
||||
SIM->SOPT2 |= (1<<SIM_SOPT2_UART0SRC_SHIFT);
|
||||
else
|
||||
SIM->SOPT2 |= (2<<SIM_SOPT2_UART0SRC_SHIFT);
|
||||
SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK; SIM->SCGC4 |= SIM_SCGC4_UART0_MASK; break;
|
||||
|
@ -123,7 +123,14 @@ void serial_baud(serial_t *obj, int baudrate) {
|
|||
// Disable UART before changing registers
|
||||
obj->uart->C2 &= ~(UART_C2_RE_MASK | UART_C2_TE_MASK);
|
||||
|
||||
uint32_t PCLK = (obj->uart == UART0) ? SystemCoreClock : bus_frequency();
|
||||
uint32_t PCLK;
|
||||
if (obj->uart == UART0) {
|
||||
if (mcgpllfll_frequency() != 0)
|
||||
PCLK = mcgpllfll_frequency();
|
||||
else
|
||||
PCLK = extosc_frequency();
|
||||
} else
|
||||
PCLK = bus_frequency();
|
||||
|
||||
// First we check to see if the basic divide with no DivAddVal/MulVal
|
||||
// ratio gives us an integer result. If it does, we set DivAddVal = 0,
|
||||
|
|
|
@ -102,10 +102,22 @@ static void lptmr_init(void) {
|
|||
}
|
||||
}
|
||||
}
|
||||
//No suitable external oscillator clock -> Use fast internal oscillator (4MHz)
|
||||
//No suitable external oscillator clock -> Use fast internal oscillator (4MHz / divider)
|
||||
MCG->C1 |= MCG_C1_IRCLKEN_MASK;
|
||||
MCG->C2 |= MCG_C2_IRCS_MASK;
|
||||
LPTMR0->PSR = LPTMR_PSR_PCS(0) | LPTMR_PSR_PRESCALE(1);
|
||||
LPTMR0->PSR = LPTMR_PSR_PCS(0);
|
||||
switch (MCG->SC & MCG_SC_FCRDIV_MASK) {
|
||||
case MCG_SC_FCRDIV(0): //4MHz
|
||||
LPTMR0->PSR |= LPTMR_PSR_PRESCALE(1);
|
||||
break;
|
||||
case MCG_SC_FCRDIV(1): //2MHz
|
||||
LPTMR0->PSR |= LPTMR_PSR_PRESCALE(0);
|
||||
break;
|
||||
default: //1MHz or anything else, in which case we put it on 1MHz
|
||||
MCG->SC &= ~MCG_SC_FCRDIV_MASK;
|
||||
MCG->SC |= MCG_SC_FCRDIV(2);
|
||||
LPTMR0->PSR |= LPTMR_PSR_PBYP_MASK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue