embOS: switch off the PLL

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • embOS: switch off the PLL

    Hello,

    I'm using embOS version 3.62, IAR EW version 5.0, and ARM STR912FA.
    I want to switch off the PLL for my application, the purpose of this is to use the existing 25MHZ clock to reduce power. The PLL will be switched off at startup and not switched during runtime.

    The problem is the function lowlevel_init() which is within the file RTOSInit.C is not written to allow the PLL to be switched off. It is only written to work with the PLL being switched on.

    I changed the define values of OS_INIT_PLL 0, and tried OS_FSYS 25000000 on RTOSInit.C and the code would not compile due to the error directive in lowlevel_init() - #error "Unsupported PLL frequency, please modify PLL init function"

    I commented out the PLL setup code in lowlevel_init() and then got a problem in CStartup :
    OS_INTERWORK int __low_level_init(void) {
    OS_U32 CLKCNTR_Value;
    int i;
    //
    // Check if vector jump table is programmed at 0x0 for RAM targets
    //
    if ((GetPC() & 0x04000000) && ((*(OS_U32*) 0x18 != 0xE59FF010) || (*(OS_U32*) 0x30 != 0x04000018 )) {
    while(1) { // Fatal error! Vector jump table not programmed at 0x0. See ReadMe.txt for more info.
    }
    }
    //
    // Initialize Clock source and PLL
    //
    CLKCNTR_Value = _SCU_CLKCNTR; // Get the current Clock control value
    CLKCNTR_Value &= ~0x3; // Clear field MCLKSEL
    CLKCNTR_Value |= _SCU_CLKSEL_MAIN; // Select Main oscillator as source
    _SCU_CLKCNTR = CLKCNTR_Value; // Update CLKCNTR register value
    //
    // Write a write flash configuration register command and configure Flash configuration
    //
    *(volatile unsigned short *)(_FMI_NBBADR << 2) = 0x60;
    *(volatile unsigned short *)((_FMI_NBBADR << 2) | _FMI_READ_WAIT_STATE_2 | _FMI_PWD_ENABLE | _FMI_LVD_ENABLE | _FMI_FREQ_HIGH) = 0x03;

    #if OS_INIT_PLL==0
    _SCU_CLKCNTR &= _SCU_PCLK_Div1; // Clear APBDIV[1:0] field
    _SCU_CLKCNTR |= _SCU_PCLK_Div1; // Update field with PCLK Divisor
    #else
    //
    // Set the PCLK Clock to MCLK/2, because peripheral clock is limited to 48 MHz
    //
    _SCU_CLKCNTR &= _SCU_PCLK_Div1; // Clear APBDIV[1:0] field
    _SCU_CLKCNTR |= _SCU_PCLK_Div2; // Update field with PCLK Divisor
    //
    // Setup PLL config registers
    //
    #if (OS_FSYS == 48000000)
    #define _PLL_P 3
    #elif (OS_FSYS == 96000000)
    #define _PLL_P 2
    #else
    #error "Unsupported PLL frequency, please modify PLL init function"
    #endif

    #define _PLL_N (0x18 * 8 )
    #define _PLL_M (OS_XTAL_FREQUENCY / 1000000)


    if(_SCU_CLKCNTR & 0x3) { // Check if PLL not already selected as clock
    for(i = 10 ;i > 0; i--); // Add a short delay before disabling PLL
    _SCU_PLLCONF &= ~_SCU_PLLEN; // Disable PLL
    _SCU_PLLCONF =0; // Clear PLLCONF register
    _SCU_PLLCONF |= (_PLL_N << 8 ); // Update PLLN field
    _SCU_PLLCONF |= _PLL_M; // Update PLLM field
    _SCU_PLLCONF |= (_PLL_P << 16); // Update PLLP field
    }
    //
    // Enable PLL if not already enabled
    //
    if (((_SCU_PLLCONF & _SCU_PLLEN) && (_SCU_SYSSTATUS & _SCU_FLAG_LOCK)) == 0) {
    _SCU_SYSSTATUS |= _SCU_FLAG_LOCK; // Clear LOCK bit
    _SCU_PLLCONF |= _SCU_PLLEN; // Enable PLL
    while((_SCU_SYSSTATUS & _SCU_FLAG_LOCK) == 0); // Wait until PLL locks
    }
    //
    // Select PLL as clock source
    //
    CLKCNTR_Value = _SCU_CLKCNTR; // Get current CLKCNTR register value
    CLKCNTR_Value &= ~0x3; // Clear MCLKSEL
    //
    // Check if PLL is enabled & locked
    //
    if (((_SCU_PLLCONF & _SCU_PLLEN) && (_SCU_SYSSTATUS & _SCU_FLAG_LOCK))) {
    CLKCNTR_Value |= _SCU_CLKSEL_PLL; // Switch to PLL as clock source
    _SCU_CLKCNTR = CLKCNTR_Value; // Update CLKCNTR register
    }
    #endif
    //
    // Finally return 1 to force initialization of segments
    //
    return 1;
    }