Hi,
I am using lpc4357 custom board and taking LPC4357 driver file provided by keil. In which system_lpc43xx.c file has one code section is to setup PLL1(line no. 25 to 73) with external clock, here I also attached that section. In that section if your clock frequency is more than 110 MHz (let's say 192MHz) then first PLL1 will operate at an intermediate frequency then it shifted to high frequency. but in some board for 192 MHz frequency if I use set clock function once then code is not running. I am thinking code is not able to set PLL1 frequency and it is stuck there, since controller is able to give input to external clock and I checked clock output also reaches to controller. If I set the PLL1 first to 112MHz using "Setclock()" function and again I am setting 192MHz using the same function, then the code is running properly. So, is there any issue in this Setclock function so it is not setting intermediate clock as mentioned in code comment (line no. 44)? And if I go to debug mode every time it is working.
static void SetClock (void) { uint32_t x, i; uint32_t selp, seli; /* Set flash accelerator configuration for bank A and B to reset value */ LPC_CREG->FLASHCFGA |= (0xF << 12); LPC_CREG->FLASHCFGB |= (0xF << 12); /* Set flash wait states to maximum */ LPC_EMC->STATICWAITRD0 = 0x1F; /* Switch BASE_M4_CLOCK to IRC */ LPC_CGU->BASE_M4_CLK = (0x01 << 11) | /* Autoblock En */ (CLK_SRC_IRC << 24) ; /* Set clock source */ /* Configure input to crystal oscilator */ LPC_CGU->XTAL_OSC_CTRL = (0 << 0) | /* Enable oscillator-pad */ (0 << 1) | /* Operation with crystal connected */ (0 << 2) ; /* Low-frequency mode */ /* Wait ~250us @ 12MHz */ for (i = 1500; i; i--); #ifdef USE_SPIFI /* configure SPIFI clk to IRC via IDIVA (later IDIVA is configured to PLL1/3) */ LPC_CGU->IDIVA_CTRL = (0 << 0) | /* Disable Power-down */ (0 << 2) | /* IDIV */ (1 << 11) | /* Autoblock En */ (CLK_SRC_IRC << 24) ; /* Clock source */ LPC_CGU->BASE_SPIFI_CLK = (0 << 0) | /* Disable Power-down */ (0 << 2) | /* IDIV */ (1 << 11) | /* Autoblock En */ (CLK_SRC_IDIVA << 24) ; /* Clock source */ #endif /*---------------------------------------------------------------------------- PLL1 Setup *----------------------------------------------------------------------------*/ /* Power down PLL */ LPC_CGU->PLL1_CTRL |= 1; #if ((PLL1_FOUT > 110000000UL) && (CPU_CLK_SEL == CLK_SRC_PLL1)) /* To run at full speed, CPU must first run at an intermediate speed */ LPC_CGU->PLL1_CTRL = (0 << 0) | /* PLL1 Enabled */ (PLL1_BYPASS << 1) | /* CCO out sent to post-dividers */ (PLL1_FBSEL << 6) | /* PLL output used as feedback */ (0 << 7) | /* Direct on/off */ (PLL1_PSEL << 8) | /* PSEL */ (0 << 11)| /* Autoblock Disabled */ (PLL1_NSEL << 12)| /* NSEL */ (PLL1_MSEL << 16)| /* MSEL */ (PLL1_CLK_SEL << 24); /* Clock source */ /* Wait for lock */ while (!(LPC_CGU->PLL1_STAT & 1)); /* CPU base clock is in the mid frequency range before final clock set */ LPC_CGU->BASE_M4_CLK = (0x01 << 11) | /* Autoblock En */ (0x09 << 24) ; /* Clock source: PLL1 */ /* Max. BASE_M4_CLK frequency here is 102MHz, wait at least 20us */ for (i = 1050; i; i--); /* Wait minimum 2100 cycles */ #endif /* Configure PLL1 */ LPC_CGU->PLL1_CTRL = (0 << 0) | /* PLL1 Enabled */ (PLL1_BYPASS << 1) | /* CCO out sent to post-dividers */ (PLL1_FBSEL << 6) | /* PLL output used as feedback */ (PLL1_DIRECT << 7) | /* Direct on/off */ (PLL1_PSEL << 8) | /* PSEL */ (1 << 11)| /* Autoblock En */ (PLL1_NSEL << 12)| /* NSEL */ (PLL1_MSEL << 16)| /* MSEL */ (PLL1_CLK_SEL << 24); /* Clock source */ /* Wait for lock */ while (!(LPC_CGU->PLL1_STAT & 1)); /* Set CPU base clock source */ LPC_CGU->BASE_M4_CLK = (0x01 << 11) | /* Autoblock En */ (CPU_CLK_SEL << 24) ; /* Set clock source */ /* Set flash accelerator configuration for internal flash bank A and B */ LPC_CREG->FLASHCFGA = (LPC_CREG->FLASHCFGA & (~0x0000F000U)) | (FLASHCFG_FLASHTIM << 12); LPC_CREG->FLASHCFGB = (LPC_CREG->FLASHCFGB & (~0x0000F000U)) | (FLASHCFG_FLASHTIM << 12); /*---------------------------------------------------------------------------- PLL0USB Setup *----------------------------------------------------------------------------*/ /* Power down PLL0USB */ LPC_CGU->PLL0USB_CTRL |= 1; /* M divider */ x = 0x00004000; switch (PLL0USB_M) { case 0: x = 0xFFFFFFFF; break; case 1: x = 0x00018003; break; case 2: x = 0x00010003; break; default: for (i = PLL0USB_M; i <= 0x8000; i++) { x = (((x ^ (x >> 1)) & 1) << 14) | ((x >> 1) & 0x3FFF); } } if (PLL0USB_M < 60) selp = (PLL0USB_M >> 1) + 1; else selp = 31; if (PLL0USB_M > 16384) seli = 1; else if (PLL0USB_M > 8192) seli = 2; else if (PLL0USB_M > 2048) seli = 4; else if (PLL0USB_M >= 501) seli = 8; else if (PLL0USB_M >= 60) seli = 4 * (1024 / (PLL0USB_M + 9)); else seli = (PLL0USB_M & 0x3C) + 4; LPC_CGU->PLL0USB_MDIV = (selp << 17) | (seli << 22) | (x << 0); /* N divider */ x = 0x80; switch (PLL0USB_N) { case 0: x = 0xFFFFFFFF; break; case 1: x = 0x00000302; break; case 2: x = 0x00000202; break; default: for (i = PLL0USB_N; i <= 0x0100; i++) { x =(((x ^ (x >> 2) ^ (x >> 3) ^ (x >> 4)) & 1) << 7) | ((x >> 1) & 0x7F); } } LPC_CGU->PLL0USB_NP_DIV = (x << 12); /* P divider */ x = 0x10; switch (PLL0USB_P) { case 0: x = 0xFFFFFFFF; break; case 1: x = 0x00000062; break; case 2: x = 0x00000042; break; default: for (i = PLL0USB_P; i <= 0x200; i++) { x = (((x ^ (x >> 2)) & 1) << 4) | ((x >> 1) &0x0F); } } LPC_CGU->PLL0USB_NP_DIV |= x; LPC_CGU->PLL0USB_CTRL = (PLL0USB_CLK_SEL << 24) | /* Clock source sel */ (1 << 11) | /* Autoblock En */ (1 << 4 ) | /* PLL0USB clock en */ (PLL0USB_DIRECTO << 3 ) | /* Direct output */ (PLL0USB_DIRECTI << 2 ) | /* Direct input */ (PLL0USB_BYPASS << 1 ) | /* PLL bypass */ (0 << 0 ) ; /* PLL0USB Enabled */ while (!(LPC_CGU->PLL0USB_STAT & 1)); /*---------------------------------------------------------------------------- Integer divider Setup *----------------------------------------------------------------------------*/ /* Configure integer dividers */ LPC_CGU->IDIVA_CTRL = (0 << 0) | /* Disable Power-down */ (IDIVA_IDIV << 2) | /* IDIV */ (1 << 11) | /* Autoblock En */ (IDIVA_CLK_SEL << 24) ; /* Clock source */ LPC_CGU->IDIVB_CTRL = (0 << 0) | /* Disable Power-down */ (IDIVB_IDIV << 2) | /* IDIV */ (1 << 11) | /* Autoblock En */ (IDIVB_CLK_SEL << 24) ; /* Clock source */ LPC_CGU->IDIVC_CTRL = (0 << 0) | /* Disable Power-down */ (IDIVC_IDIV << 2) | /* IDIV */ (1 << 11) | /* Autoblock En */ (IDIVC_CLK_SEL << 24) ; /* Clock source */ LPC_CGU->IDIVD_CTRL = (0 << 0) | /* Disable Power-down */ (IDIVD_IDIV << 2) | /* IDIV */ (1 << 11) | /* Autoblock En */ (IDIVD_CLK_SEL << 24) ; /* Clock source */ LPC_CGU->IDIVE_CTRL = (0 << 0) | /* Disable Power-down */ (IDIVE_IDIV << 2) | /* IDIV */ (1 << 11) | /* Autoblock En */ (IDIVE_CLK_SEL << 24) ; /* Clock source */ }
Hi Jaga,
I just tried setting clock to 204 MHz, with following PLL1 dividers:
#define PLL1_NSEL 0 /* Range [0 - 3]: Pre-divider ratio N */#define PLL1_MSEL 16 /* Range [0 - 255]: Feedback-divider ratio M */#define PLL1_PSEL 0 /* Range [0 - 3]: Post-divider ratio P */
#define PLL1_NSEL 0 /* Range [0 - 3]: Pre-divider ratio N */
#define PLL1_MSEL 16 /* Range [0 - 255]: Feedback-divider ratio M */
#define PLL1_PSEL 0 /* Range [0 - 3]: Post-divider ratio P */
and it works as expected.
Best regards, Milorad
Hi Milorad,
thanks for your reply.
I have also some controllers in it is working fine. But it is not working in every controller. I also tried in development board it is working fine. In my custom board I am using 16MHz crystal in which same code with one-time setclock with internal RC oscillator upto 204MHz it is working fine. but when I use external clock then some board having this issue.
the only thing I could say is it looks like something is at limit which then behaves inconsistently, either hardware layout and routing for clocking part or crystal quality.
It does look like it is hardware related.
I fully agree with my colleague Milorad. This looks like a hardware-related issue. I've seen something like this before many years ago with a similar controller. The external crystal was oscillating on the first harmonic (which was 3 x the frequency if I remember correctly). I had to change the bypass caps around the crystal to make it work reliably. Just a guess.
I checked the crystal output it is fine. but still I replaced crystal and its load capacitance but no improvement.