mirror of https://github.com/ARMmbed/mbed-os.git
Added serial_get_src_clock() function into serial_api.c and fastirc_frequency() function into clk_freqs.h for better portability.
parent
bb969921ec
commit
1eb8d7cab4
|
@ -38,6 +38,29 @@ static uart_irq_handler irq_handler;
|
||||||
int stdio_uart_inited = 0;
|
int stdio_uart_inited = 0;
|
||||||
serial_t stdio_uart;
|
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) {
|
void serial_init(serial_t *obj, PinName tx, PinName rx) {
|
||||||
// determine the UART to use
|
// determine the UART to use
|
||||||
UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
|
UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
|
||||||
|
@ -103,8 +126,8 @@ void serial_baud(serial_t *obj, int baudrate) {
|
||||||
int calcBaudrate;
|
int calcBaudrate;
|
||||||
uint32_t i, sbr, sbrTemp, osr, temp, baud, baudDiff;
|
uint32_t i, sbr, sbrTemp, osr, temp, baud, baudDiff;
|
||||||
|
|
||||||
/* Use Fast IRC Clock 48Mhz (set in serial_init(...)) */
|
/* get value of serial source clock */
|
||||||
uint32_t PCLK = CPU_INT_FAST_CLK_HZ;
|
uint32_t PCLK = serial_get_src_clock(obj);
|
||||||
|
|
||||||
/* loop to find the best osr value possible, one that generates minimum baudDiff
|
/* loop to find the best osr value possible, one that generates minimum baudDiff
|
||||||
* iterate through the rest of the supported values of osr */
|
* iterate through the rest of the supported values of osr */
|
||||||
|
|
|
@ -33,6 +33,10 @@ static inline uint32_t extosc_frequency(void) {
|
||||||
return CPU_XTAL_CLK_HZ;
|
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) {
|
static inline uint32_t mcgirc_frequency(void) {
|
||||||
uint32_t mcgirc_clock = 0;
|
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
|
if ((MCG->C1 & MCG_C1_CLKS_MASK) == MCG_C1_CLKS(2)) //MCG clock = external reference clock
|
||||||
return MCGClock;
|
return MCGClock;
|
||||||
|
|
||||||
uint32_t divider, multiplier;
|
uint32_t divider, multiplier;
|
||||||
#ifdef MCG_C5_PLLCLKEN0_MASK //PLL available
|
#ifdef MCG_C5_PLLCLKEN0_MASK //PLL available
|
||||||
if ((MCG->C1 & MCG_C1_CLKS_MASK) == MCG_C1_CLKS(0)) { //PLL/FLL is selected
|
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;
|
multiplier = 2929u;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MCGClock * divider / multiplier;
|
return MCGClock * divider / multiplier;
|
||||||
}
|
}
|
||||||
#ifdef MCG_C5_PLLCLKEN0_MASK
|
#ifdef MCG_C5_PLLCLKEN0_MASK
|
||||||
} else { //PLL is selected
|
} else { //PLL is selected
|
||||||
divider = (1u + (MCG->C5 & MCG_C5_PRDIV0_MASK));
|
divider = (1u + (MCG->C5 & MCG_C5_PRDIV0_MASK));
|
||||||
multiplier = ((MCG->C6 & MCG_C6_VDIV0_MASK) + 24u);
|
multiplier = ((MCG->C6 & MCG_C6_VDIV0_MASK) + 24u);
|
||||||
return MCGClock * divider / multiplier;
|
return MCGClock * divider / multiplier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//In all other cases either there is no crystal or we cannot determine it
|
//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
|
//For example when the FLL is running on the internal reference, and there is also an
|
||||||
//external crystal. However these are unlikely situations
|
//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
|
//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
|
if ((MCG->C1 & MCG_C1_CLKS_MASK) != MCG_C1_CLKS(0)) //PLL/FLL is not selected
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint32_t MCGClock = SystemCoreClock * (1u + ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> SIM_CLKDIV1_OUTDIV1_SHIFT));
|
uint32_t MCGClock = SystemCoreClock * (1u + ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> SIM_CLKDIV1_OUTDIV1_SHIFT));
|
||||||
#ifdef MCG_C5_PLLCLKEN0_MASK
|
#ifdef MCG_C5_PLLCLKEN0_MASK
|
||||||
if ((MCG->C6 & MCG_C6_PLLS_MASK) == 0x0u) { //FLL is selected
|
if ((MCG->C6 & MCG_C6_PLLS_MASK) == 0x0u) { //FLL is selected
|
||||||
|
@ -126,8 +130,8 @@ static uint32_t mcgpllfll_frequency(void) {
|
||||||
return (MCGClock >> 1);
|
return (MCGClock >> 1);
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
//for the peripherals, this is however an unlikely setup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue