Hi, all.
Board: Teensy 3.6
Basic idea is for Teensy to run at 24 MHz while doing some
non demanding background tasks until receiving request via HW Serial.
After that, clock is restored to 180 MHz and stays in that state until
requested tasks are done and then goes back to 24 MHz.
Teensy boots with 180 MHz clock.
Everything runs fine, but I have some questions.
Here's relevant code:
Code:
const int CPU_CLOCK = 180000000;
const int CPU_UNDERCLOCK = 24000000;
const int mainBusBaudRate = 250000;
const int SERIAL_DIV = (CPU_CLOCK * 2 + (mainBusBaudRate >> 1)) / mainBusBaudRate;
const int SERIAL_DIV_UNDERCLOCK = (CPU_UNDERCLOCK * 2 + (mainBusBaudRate >> 1)) / mainBusBaudRate;
Code:
FASTRUN void UnderClock24()
{
SMC_PMCTRL = SMC_PMCTRL_RUNM(0);
while (SMC_PMSTAT == SMC_PMSTAT_HSRUN) { ; }
MCG_C5 = MCG_C5_PRDIV0(1);
MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(8);
while (!(MCG_S & MCG_S_PLLST)) { ; }
while (!(MCG_S & MCG_S_LOCK0)) { ; }
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(3, 3, 3, 3);
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1);
MCG_C1 = MCG_C1_CLKS(0x00) | MCG_C1_FRDIV(0x04);
while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(0x03)) { ; }
SYST_RVR = CPU_UNDERCLOCK / 1000 - 1;
UART0_BDH = (SERIAL_DIV_UNDERCLOCK >> 13) & 0x1F;
UART0_BDL = (SERIAL_DIV_UNDERCLOCK >> 5) & 0xFF;
UART0_C4 = SERIAL_DIV_UNDERCLOCK & 0x1F;
UART0_C1 = UART_C1_ILT;
UART0_TWFIFO = 2;
UART0_RWFIFO = 4;
UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
}
Code:
FASTRUN void RestoreClock180()
{
SMC_PMCTRL = SMC_PMCTRL_RUNM(3);
while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) { ; }
MCG_C5 = MCG_C5_PRDIV0(1);
MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(29);
while (!(MCG_S & MCG_S_PLLST)) { ; }
while (!(MCG_S & MCG_S_LOCK0)) { ; }
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 6);
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0);
MCG_C1 = MCG_C1_CLKS(0) | MCG_C1_FRDIV(4);
while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) { ; }
SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_IRC48SEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(6);
SYST_RVR = CPU_CLOCK / 1000 - 1;
UART0_BDH = (SERIAL_DIV >> 13) & 0x1F;
UART0_BDL = (SERIAL_DIV >> 5) & 0xFF;
UART0_C4 = SERIAL_DIV & 0x1F;
UART0_C1 = UART_C1_ILT;
UART0_TWFIFO = 2;
UART0_RWFIFO = 4;
UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
}
Is PLL lock mandatory?
Code:
while (!(MCG_S & MCG_S_PLLST)) { ; }
while (!(MCG_S & MCG_S_LOCK0)) { ; }
Been testing it for some time now (~10000 requests and responses) and it seems to work fine if I omit it.
I mean, should it run correctly?
Can someone shed some light regarding this, please?
If I understood it correctly, this block of code reset FIFO buffer and status registers.
Code:
UART0_C1 = UART_C1_ILT;
UART0_TWFIFO = 2;
UART0_RWFIFO = 4;
UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
What is suggested procedure here, to reset it every time clock switch occurs or leave it as is?
And finally, should I be concerned about CPU longevity
and overall stability with all this frequent clock switching?
Many thanks.