Added serial_get_src_clock() function into serial_api.c and fastirc_frequency() function into clk_freqs.h for better portability.

pull/805/head
Martin Olejar 2014-12-19 10:55:37 +01:00
parent bb969921ec
commit 1eb8d7cab4
2 changed files with 38 additions and 11 deletions

View File

@ -38,6 +38,29 @@ static uart_irq_handler irq_handler;
int stdio_uart_inited = 0;
serial_t stdio_uart;
static inline uint32_t serial_get_src_clock(serial_t *obj) {
uint32_t mux, srcclk;
switch ((int)obj->uart) {
case UART_0:
mux = (SIM->SOPT2 & SIM_SOPT2_LPUART0SRC_MASK) >> SIM_SOPT2_LPUART0SRC_SHIFT;
break;
case UART_1:
mux = (SIM->SOPT2 & SIM_SOPT2_LPUART1SRC_MASK) >> SIM_SOPT2_LPUART1SRC_SHIFT;
break;
case UART_2: /* TODO: add UART2 support */ break;
}
switch (mux) {
case 1: srcclk = fastirc_frequency(); break;
case 2: srcclk = extosc_frequency(); break;
case 3: srcclk = mcgirc_frequency(); break;
default: srcclk = 0; break;
}
return srcclk;
}
void serial_init(serial_t *obj, PinName tx, PinName rx) {
// determine the UART to use
UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
@ -103,8 +126,8 @@ void serial_baud(serial_t *obj, int baudrate) {
int calcBaudrate;
uint32_t i, sbr, sbrTemp, osr, temp, baud, baudDiff;
/* Use Fast IRC Clock 48Mhz (set in serial_init(...)) */
uint32_t PCLK = CPU_INT_FAST_CLK_HZ;
/* get value of serial source clock */
uint32_t PCLK = serial_get_src_clock(obj);
/* loop to find the best osr value possible, one that generates minimum baudDiff
* iterate through the rest of the supported values of osr */

View File

@ -33,6 +33,10 @@ static inline uint32_t extosc_frequency(void) {
return CPU_XTAL_CLK_HZ;
}
static inline uint32_t fastirc_frequency(void) {
return CPU_INT_FAST_CLK_HZ;
}
static inline uint32_t mcgirc_frequency(void) {
uint32_t mcgirc_clock = 0;
@ -53,7 +57,7 @@ static uint32_t extosc_frequency(void) {
if ((MCG->C1 & MCG_C1_CLKS_MASK) == MCG_C1_CLKS(2)) //MCG clock = external reference clock
return MCGClock;
uint32_t divider, multiplier;
#ifdef MCG_C5_PLLCLKEN0_MASK //PLL available
if ((MCG->C1 & MCG_C1_CLKS_MASK) == MCG_C1_CLKS(0)) { //PLL/FLL is selected
@ -91,18 +95,18 @@ static uint32_t extosc_frequency(void) {
multiplier = 2929u;
break;
}
return MCGClock * divider / multiplier;
}
#ifdef MCG_C5_PLLCLKEN0_MASK
} 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;
}
}
#endif
//In all other cases either there is no crystal or we cannot determine it
//For example when the FLL is running on the internal reference, and there is also an
//external crystal. However these are unlikely situations
@ -110,10 +114,10 @@ static uint32_t extosc_frequency(void) {
}
//Get MCG PLL/2 or FLL frequency, depending on which one is active, sets PLLFLLSEL bit
static uint32_t mcgpllfll_frequency(void) {
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));
#ifdef MCG_C5_PLLCLKEN0_MASK
if ((MCG->C6 & MCG_C6_PLLS_MASK) == 0x0u) { //FLL is selected
@ -126,8 +130,8 @@ static uint32_t mcgpllfll_frequency(void) {
return (MCGClock >> 1);
}
#endif
//It is possible the SystemCoreClock isn't running on the PLL, and the PLL is still active
//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
}