PSoC® Creator™: ECO/EXCO Issue with Quartz Crystals and Ceramic Resonators Driving the PLL - KBA231127
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
Version: **
Translation - Japanese: PSoC®Creator™:PLLを駆動する水晶振動子とセラミック共振子に関するECO / EXCOの問題 - KBA231127 - Community Translated (JA)
Problem:
On the PSoC 4100S Plus, and PSoC 4500 device families when the ECO clock is configured via DWR or using cy_boot API, the redundant EXCO_PGM_CLK manipulation destabilizes the PLL. This then runs out of lock, and the output frequency fluctuation may result in a CPU hard fault.
Devices Impacted:
PSoC 4100S Plus, PSoC 4500
Software Impacted:
PSoC Creator 4.2 and 4.3
Example of the DWR configuration that may expose the issue:
Workarounds:
There are several workarounds you can apply depending on the software used, and method used for the clocks configuration.
Workaround #1 – Move to PSoC Creator 4.4 Once Available
Once available, the PSoC Creator 4.4 release will be used for the DWR approach for configuring clocks. It will package cy_boot 6.0, which addresses the issue when the configuration is done via the cy_boot API.
Workaround #2 – Disable Code Generation and Tweak the Generated Code
If using PSoC Creator 4.3 or 4.2, use this option for this or similar DWR configuration
Please note that if you do not disable code generation, the code will get re-generated, so use this workaround with caution.
Once you are done configuring the components and DWR, disable code generation. Go to the Project menu (or right click on the project in the workspace explorer) select Build Settings > Code Generation > Skip Code Generation > True.
The following code was generated in Generated_Source\PSoC4\cyfitter_cfg.c.
static void ClockSetup(void)
{
uint8 ecoStatus;
uint8 pllTimeout, i;
/* Set Flash Cycles based on max possible frequency in case a glitch occurs during ClockSetup(). */
CY_SET_REG32((void CYXDATA *)(CYREG_CPUSS_FLASH_CTL), (0x0012u));
/* Update IMO to new clock speed. */
CySysClkWriteImoFreq(24u);
/* Configure ECO trim */
CY_SET_REG32((void CYXDATA *)(CYREG_EXCO_ECO_CONFIG), (0x00000000u));
CY_SET_REG32((void CYXDATA *)(CYREG_EXCO_ECO_TRIM0), (0x0000001Fu));
CY_SET_REG32((void CYXDATA *)(CYREG_EXCO_ECO_TRIM1), (0x0000001Fu));
/* Start the ECO and check status since it is needed for HFCLK */
ecoStatus = CySysClkEcoStart(2000u);
if (ecoStatus != CYRET_SUCCESS)
{
CyClockStartupError(CYCLOCKSTART_XTAL_ERROR);
}
CyDelayUs(1500u); /* Wait to stabilize */
CySysClkPllSetSource(0u, CY_SYS_PLL_SOURCE_ECO);
CY_SET_REG32(CYREG_EXCO_PLL_CONFIG, 0x80020118u);
CyDelayCycles(120u);
CY_SET_REG32(CYREG_EXCO_PLL_CONFIG, 0xC0020118u);
for (pllTimeout = 0u; (pllTimeout < 25u) && (CY_GET_REG32(CYREG_EXCO_PLL_STATUS) == 0u); pllTimeout++)
{
CyDelayCycles(240u);
}
if (CY_GET_REG32(CYREG_EXCO_PLL_STATUS) == 0u)
{
CyClockStartupError(CYCLOCKSTART_PLL_ERROR);
}
CY_SET_REG32((void CYXDATA *)(CYREG_EXCO_CLK_SELECT), (0x00000001u));
/* Generate clock sequence to change clock source in CYREG_EXCO_CLK_SELECT */
CY_SYS_EXCO_PGM_CLK_REG |= CY_SYS_EXCO_PGM_CLK_ENABLE_MASK;
for(i = 0u; i < CY_SYS_EXCO_PGM_CLK_SEQ_GENERATOR; i++)
{
CY_SYS_EXCO_PGM_CLK_REG |= CY_SYS_EXCO_PGM_CLK_CLK_ECO_MASK;
CY_SYS_EXCO_PGM_CLK_REG &= ~CY_SYS_EXCO_PGM_CLK_CLK_ECO_MASK;
}
CY_SYS_EXCO_PGM_CLK_REG &= ~CY_SYS_EXCO_PGM_CLK_ENABLE_MASK;
/* Setup phase aligned clocks */
/* CYDEV_CLK_SELECT Starting address: CYDEV_CLK_SELECT */
CY_SET_REG32((void *)(CYREG_CLK_SELECT), 0x00000002u);
(void)CyIntSetVector(13u, &CySysTimerIsr);
CyIntEnable(13u);
CY_SET_REG32((void *)(CYREG_WCO_WDT_CONFIG), 0x00000000u);
CySysClkSetTimerSource(CY_SYS_CLK_TIMER_SRC_ILO);
}
It must be changed as follows (remove or comment out the code in red😞
static void ClockSetup(void)
{
uint8 ecoStatus;
uint8 pllTimeout, i;
/* Set Flash Cycles based on max possible frequency in case a glitch occurs during ClockSetup(). */
CY_SET_REG32((void CYXDATA *)(CYREG_CPUSS_FLASH_CTL), (0x0012u));
/* Update IMO to new clock speed. */
CySysClkWriteImoFreq(24u);
/* Configure ECO trim */
CY_SET_REG32((void CYXDATA *)(CYREG_EXCO_ECO_CONFIG), (0x00000000u));
CY_SET_REG32((void CYXDATA *)(CYREG_EXCO_ECO_TRIM0), (0x0000001Fu));
CY_SET_REG32((void CYXDATA *)(CYREG_EXCO_ECO_TRIM1), (0x0000001Fu));
/* Start the ECO and check status since it is needed for HFCLK */
ecoStatus = CySysClkEcoStart(2000u);
if (ecoStatus != CYRET_SUCCESS)
{
CyClockStartupError(CYCLOCKSTART_XTAL_ERROR);
}
CyDelayUs(1500u); /* Wait to stabilize */
CySysClkPllSetSource(0u, CY_SYS_PLL_SOURCE_ECO);
CY_SET_REG32(CYREG_EXCO_PLL_CONFIG, 0x80020118u);
CyDelayCycles(120u);
CY_SET_REG32(CYREG_EXCO_PLL_CONFIG, 0xC0020118u);
for (pllTimeout = 0u; (pllTimeout < 25u) && (CY_GET_REG32(CYREG_EXCO_PLL_STATUS) == 0u); pllTimeout++)
{
CyDelayCycles(240u);
}
if (CY_GET_REG32(CYREG_EXCO_PLL_STATUS) == 0u)
{
CyClockStartupError(CYCLOCKSTART_PLL_ERROR);
}
CY_SET_REG32((void CYXDATA *)(CYREG_EXCO_CLK_SELECT), (0x00000001u));
///* Generate clock sequence to change clock source in CYREG_EXCO_CLK_SELECT */
//CY_SYS_EXCO_PGM_CLK_REG |= CY_SYS_EXCO_PGM_CLK_ENABLE_MASK;
//for(i = 0u; i < CY_SYS_EXCO_PGM_CLK_SEQ_GENERATOR; i++)
//{
// CY_SYS_EXCO_PGM_CLK_REG |= CY_SYS_EXCO_PGM_CLK_CLK_ECO_MASK;
// CY_SYS_EXCO_PGM_CLK_REG &= ~CY_SYS_EXCO_PGM_CLK_CLK_ECO_MASK;
//}
//CY_SYS_EXCO_PGM_CLK_REG &= ~CY_SYS_EXCO_PGM_CLK_ENABLE_MASK;
/* Setup phase aligned clocks */
/* CYDEV_CLK_SELECT Starting address: CYDEV_CLK_SELECT */
CY_SET_REG32((void *)(CYREG_CLK_SELECT), 0x00000002u);
(void)CyIntSetVector(13u, &CySysTimerIsr);
CyIntEnable(13u);
CY_SET_REG32((void *)(CYREG_WCO_WDT_CONFIG), 0x00000000u);
CySysClkSetTimerSource(CY_SYS_CLK_TIMER_SRC_ILO);
}
Workaround #3 – Switch HFClk Clocks Manually, Use Updated cy_boot 5.81 in PSoC Creator 4.2 and cy_boot 6.0 in PSoC Creator 4.3 or 4.4
Suppose you want to configure the clocking as described in the following DWR snapshot: PLL sourced from ECO, the high-frequency clock is sourced from PLL:
Step 1: Switch the HFClk to IMO:
Step 2: Apply workaround in the main.c, with the CySysClkWriteHfclkDirect call from cy_boot v5.81 and v6.00:
int main()
{
/* Do some delay to let the PLL time to stabilize after the cyfitter_cfg execution */
CyDelay(1);
/* Set PLL #0 as source for HFCLK frequency (increasing) */
CySysFlashSetWaitCycles(CLK_PLL_MHZ);
CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_PLL0);
/* Adjustment for CyDelay function */
CyDelayFreq(CLK_PLL_MHZ * HZ_IN_MHZ);
/* Run the rest of the application code here */
for(;;)
{
Led_Blink();
}
}