SPNA233B May 2016 – February 2020 RM41L232 , RM41L232 , RM42L432 , RM42L432 , RM44L520 , RM44L520 , RM44L920 , RM44L920 , RM46L430 , RM46L430 , RM46L440 , RM46L440 , RM46L450 , RM46L450 , RM46L830 , RM46L830 , RM46L840 , RM46L840 , RM46L850 , RM46L850 , RM46L852 , RM46L852 , RM48L530 , RM48L530 , RM48L540 , RM48L540 , RM48L730 , RM48L730 , RM48L740 , RM48L740 , RM48L940 , RM48L940 , RM48L950 , RM48L950 , RM48L952 , RM48L952 , RM57L843 , RM57L843 , TMS570LC4357 , TMS570LC4357 , TMS570LC4357-EP , TMS570LC4357-EP , TMS570LC4357-SEP , TMS570LC4357-SEP , TMS570LS0232 , TMS570LS0232 , TMS570LS0332 , TMS570LS0332 , TMS570LS0432 , TMS570LS0432 , TMS570LS0714 , TMS570LS0714 , TMS570LS0714-S , TMS570LS0714-S , TMS570LS0914 , TMS570LS0914 , TMS570LS1114 , TMS570LS1114 , TMS570LS1115 , TMS570LS1115 , TMS570LS1224 , TMS570LS1224 , TMS570LS1225 , TMS570LS1225 , TMS570LS1227 , TMS570LS1227 , TMS570LS2124 , TMS570LS2124 , TMS570LS2125 , TMS570LS2125 , TMS570LS2134 , TMS570LS2134 , TMS570LS2135 , TMS570LS2135 , TMS570LS3134 , TMS570LS3134 , TMS570LS3135 , TMS570LS3135 , TMS570LS3137 , TMS570LS3137
The purpose of the workaround routines is to get the PLL to successfully lock one time after power-on reset. The workaround routine does not initialize the PLL to the desired frequency nor does it leave the PLL enabled. After the PLL has locked once, it successfully locks each time using the desired settings until the next loss of power.
The workaround routine polls for either the clock source to be valid (PLL lock) or for a PLL slip, as indicated in the ESM register. In the case of the function that locks both PLLs simultaneously, it checks for a lock or slip in each PLL. Then, if the PLL indicates that it has locked, the frequency of the PLL is checked using the Dual Clock Compare (DCC) module. Since the DCC measures the ratio of the PLL frequency to the oscillator frequency, the routine can be used with any valid oscillator frequency without modification.
The following function is the workaround for both PLLs.
uint32 _errata_SSWF021_45_both_plls(uint32 count)
{
uint32 failCode,retries,clkCntlSav;
/* save CLKCNTL, */
clkCntlSav = systemREG1->CLKCNTL;
/* First set VCLK2 = HCLK */
systemREG1->CLKCNTL = clkCntlSav & 0x000F0100U;
/* Now set VCLK = HCLK and enable peripherals */
systemREG1->CLKCNTL = SYS_CLKCNTRL_PENA;
failCode = 0U;
for(retries = 0U;(retries < count); retries++)
{
failCode = 0U;
/* Disable PLL1 and PLL2 */
failCode = disable_plls(SYS_CLKSRC_PLL1 | SYS_CLKSRC_PLL2);
if(failCode != 0U)
{
break;
}
/* Clear Global Status Register */
systemREG1->GBLSTAT = 0x00000301U;
/* Clear the ESM PLL slip flags */
esmREG->SR1[0U] = ESM_SR1_PLL1SLIP;
esmREG->SR4[0U] = ESM_SR4_PLL2SLIP;
/* set both PLLs to OSCIN/1*27/(2*4) */
systemREG1->PLLCTL1 = 0x23001A00U;
systemREG1->PLLCTL2 = 0x3FC0723DU;
systemREG2->PLLCTL3 = 0x23001A00U;
systemREG1->CSDISCLR = SYS_CLKSRC_PLL1 | SYS_CLKSRC_PLL2;
/* Check for (PLL1 valid or PLL1 slip) and (PLL2 valid or PLL2 slip) */
while ((((systemREG1->CSVSTAT & SYS_CLKSRC_PLL1) == 0U) && ((esmREG->SR1[0U] & ESM_SR1_PLL1SLIP) == 0U)) ||
(((systemREG1->CSVSTAT & SYS_CLKSRC_PLL2) == 0U) && ((esmREG->SR4[0U] & ESM_SR4_PLL2SLIP) == 0U)))
{
/* Wait */
}
/* If PLL1 valid, check the frequency */
if(((esmREG->SR1[0U] & ESM_SR1_PLL1SLIP) != 0U) || ((systemREG1->GBLSTAT & 0x00000300U) != 0U))
{
failCode |= 1U;
}
else
{
failCode |= check_frequency(dcc1CNT1_CLKSRC_PLL1);
}
/* If PLL2 valid, check the frequency */
if(((esmREG->SR4[0U] & ESM_SR4_PLL2SLIP) != 0U) || ((systemREG1->GBLSTAT & 0x00000300U) != 0U))
{
failCode |= 2U;
}
else
{
failCode |= (check_frequency(dcc1CNT1_CLKSRC_PLL2) << 1U);
}
if (failCode == 0U)
{
break;
}
}
/* To avoid MISRA violation 382S
(void)missing for discarded return value */
failCode = disable_plls(SYS_CLKSRC_PLL1 | SYS_CLKSRC_PLL2);
/* restore CLKCNTL, VCLKR and PENA first */
systemREG1->CLKCNTL = (clkCntlSav & 0x000F0100U);
/* restore CLKCNTL, VCLK2R */
systemREG1->CLKCNTL = clkCntlSav;
return failCode;
}
The check_frequency function is used to measure the PLL frequency using an on-chip Dual-Clock-Comparator before the PLL is used as a clock source.
static uint32 check_frequency(uint32 cnt1_clksrc)
{
/* Setup DCC1 */
/* DCC1 Global Control register configuration */
dccREG1->GCTRL = (uint32)0x5U | /** Disable DCC1 */
(uint32)((uint32)0x5U << 4U) | /** No Error Interrupt */
(uint32)((uint32)0xAU << 8U) | /** Single Shot mode */
(uint32)((uint32)0x5U << 12U); /** No Done Interrupt *//* Clear ERR and DONE bits */
dccREG1->STAT = 3U;
/** DCC1 Clock0 Counter Seed value configuration */
dccREG1->CNT0SEED = 138U;
/** DCC1 Clock0 Valid Counter Seed value configuration */
dccREG1->VALID0SEED = 10U;
/** DCC1 Clock1 Counter Seed value configuration */
dccREG1->CNT1SEED = 489U;
/** DCC1 Clock1 Source 1 Select */
dccREG1->CNT1CLKSRC = (uint32)((uint32)10U << 12U) | /** DCC Enable/Disable Key */
(uint32) cnt1_clksrc; /** DCC1 Clock Source 1 */
dccREG1->CNT0CLKSRC = (uint32)DCC1_CNT0_OSCIN; /** DCC1 Clock Source 0 *//** DCC1 Global Control register configuration */
dccREG1->GCTRL = (uint32)0xAU | /** Enable DCC1 */
(uint32)((uint32)0x5U << 4U) | /** No Error Interrupt */
(uint32)((uint32)0xAU << 8U) | /** Single Shot mode */
(uint32)((uint32)0x5U << 12U); /** No Done Interrupt */
while(dccREG1->STAT == 0U)
{
/* Wait */
}
return (dccREG1->STAT & 0x01U);
}