Untitled diff

Created Diff never expires
5 rimozioni
Linee
Totale
Rimosso
Parole
Totale
Rimosso
Per continuare a utilizzare questa funzione, aggiorna a
Diffchecker logo
Diffchecker Pro
354 linee
7 aggiunte
Linee
Totale
Aggiunto
Parole
Totale
Aggiunto
Per continuare a utilizzare questa funzione, aggiorna a
Diffchecker logo
Diffchecker Pro
356 linee
uint32_t
uint32_t
SysCtlClockFreqSet(uint32_t ui32Config, uint32_t ui32SysClock)
SysCtlClockFreqSet(uint32_t ui32Config, uint32_t ui32SysClock)
{
{
int32_t i32Timeout, i32VCOIdx, i32XtalIdx;
int32_t i32Timeout, i32VCOIdx, i32XtalIdx;
uint32_t ui32MOSCCTL;
uint32_t ui32MOSCCTL;
uint32_t ui32SysDiv, ui32Osc, ui32OscSelect, ui32RSClkConfig;
uint32_t ui32SysDiv, ui32Osc, ui32OscSelect, ui32RSClkConfig;
bool bNewPLL;
bool bNewPLL;


//
//
// TM4C123 devices should not use this function.
// TM4C123 devices should not use this function.
//
//
if(CLASS_IS_TM4C123)
if(CLASS_IS_TM4C123)
{
{
return(0);
return(0);
}
}


//
//
// Get the index of the crystal from the ui32Config parameter.
// Get the index of the crystal from the ui32Config parameter.
//
//
i32XtalIdx = SysCtlXtalCfgToIndex(ui32Config);
i32XtalIdx = SysCtlXtalCfgToIndex(ui32Config);


//
//
// Determine which non-PLL source was selected.
// Determine which non-PLL source was selected.
//
//
if((ui32Config & 0x38) == SYSCTL_OSC_INT)
if((ui32Config & 0x38) == SYSCTL_OSC_INT)
{
{
//
//
// Use the nominal frequency for the PIOSC oscillator and set the
// Use the nominal frequency for the PIOSC oscillator and set the
// crystal select.
// crystal select.
//
//
ui32Osc = 16000000;
ui32Osc = 16000000;
ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_PIOSC;
ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_PIOSC;
ui32OscSelect |= SYSCTL_RSCLKCFG_PLLSRC_PIOSC;
ui32OscSelect |= SYSCTL_RSCLKCFG_PLLSRC_PIOSC;


//
//
// Force the crystal index to the value for 16-MHz.
// Force the crystal index to the value for 16-MHz.
//
//
i32XtalIdx = SysCtlXtalCfgToIndex(SYSCTL_XTAL_16MHZ);
i32XtalIdx = SysCtlXtalCfgToIndex(SYSCTL_XTAL_16MHZ);
}
}
else if((ui32Config & 0x38) == SYSCTL_OSC_INT30)
else if((ui32Config & 0x38) == SYSCTL_OSC_INT30)
{
{
//
//
// Use the nominal frequency for the low frequency oscillator.
// Use the nominal frequency for the low frequency oscillator.
//
//
ui32Osc = 30000;
ui32Osc = 30000;
ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_LFIOSC;
ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_LFIOSC;
}
}
else if((ui32Config & 0x38) == (SYSCTL_OSC_EXT32 & 0x38))
else if((ui32Config & 0x38) == (SYSCTL_OSC_EXT32 & 0x38))
{
{
//
//
// Use the RTC frequency.
// Use the RTC frequency.
//
//
ui32Osc = 32768;
ui32Osc = 32768;
ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_RTC;
ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_RTC;
}
}
else if((ui32Config & 0x38) == SYSCTL_OSC_MAIN)
else if((ui32Config & 0x38) == SYSCTL_OSC_MAIN)
{
{
//
//
// Bounds check the source frequency for the main oscillator. The is
// Bounds check the source frequency for the main oscillator. The is
// because the PLL tables in the g_pppui32XTALtoVCO structure range
// because the PLL tables in the g_pppui32XTALtoVCO structure range
// from 5MHz to 25MHz.
// from 5MHz to 25MHz.
//
//
if((i32XtalIdx > (SysCtlXtalCfgToIndex(SYSCTL_XTAL_25MHZ))) ||
if((i32XtalIdx > (SysCtlXtalCfgToIndex(SYSCTL_XTAL_25MHZ))) ||
(i32XtalIdx < (SysCtlXtalCfgToIndex(SYSCTL_XTAL_5MHZ))))
(i32XtalIdx < (SysCtlXtalCfgToIndex(SYSCTL_XTAL_5MHZ))))
{
{
return(0);
return(0);
}
}


ui32Osc = g_pui32Xtals[i32XtalIdx];
ui32Osc = g_pui32Xtals[i32XtalIdx];


//
//
// Set the PLL source select to MOSC.
// Set the PLL source select to MOSC.
//
//
ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_MOSC;
ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_MOSC;
ui32OscSelect |= SYSCTL_RSCLKCFG_PLLSRC_MOSC;
ui32OscSelect |= SYSCTL_RSCLKCFG_PLLSRC_MOSC;


//
//
// Clear MOSC power down, high oscillator range setting, and no crystal
// Clear MOSC power down, high oscillator range setting, and no crystal
// present setting.
// present setting.
//
//
ui32MOSCCTL = HWREG(SYSCTL_MOSCCTL) &
ui32MOSCCTL = HWREG(SYSCTL_MOSCCTL) &
~(SYSCTL_MOSCCTL_OSCRNG | SYSCTL_MOSCCTL_PWRDN |
~(SYSCTL_MOSCCTL_OSCRNG | SYSCTL_MOSCCTL_PWRDN |
SYSCTL_MOSCCTL_NOXTAL);
SYSCTL_MOSCCTL_NOXTAL);


//
//
// Increase the drive strength for MOSC of 10 MHz and above.
// Increase the drive strength for MOSC of 10 MHz and above.
//
//
if(i32XtalIdx >= (SysCtlXtalCfgToIndex(SYSCTL_XTAL_10MHZ) -
if(i32XtalIdx >= (SysCtlXtalCfgToIndex(SYSCTL_XTAL_10MHZ) -
(SysCtlXtalCfgToIndex(SYSCTL_XTAL_5MHZ))))
(SysCtlXtalCfgToIndex(SYSCTL_XTAL_5MHZ))))
{
{
ui32MOSCCTL |= SYSCTL_MOSCCTL_OSCRNG;
ui32MOSCCTL |= SYSCTL_MOSCCTL_OSCRNG;
}
}


HWREG(SYSCTL_MOSCCTL) = ui32MOSCCTL;
HWREG(SYSCTL_MOSCCTL) = ui32MOSCCTL;
}
}
else
else
{
{
//
//
// This was an invalid request because no oscillator source was
// This was an invalid request because no oscillator source was
// indicated.
// indicated.
//
//
ui32Osc = 0;
ui32Osc = 0;
ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_PIOSC;
ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_PIOSC;
}
}


//
//
// Check if the running with the PLL enabled was requested.
// Check if the running with the PLL enabled was requested.
//
//
if((ui32Config & SYSCTL_USE_OSC) == SYSCTL_USE_PLL)
if((ui32Config & SYSCTL_USE_OSC) == SYSCTL_USE_PLL)
{
{
//
//
// ui32Config must be SYSCTL_OSC_MAIN or SYSCTL_OSC_INT.
// ui32Config must be SYSCTL_OSC_MAIN or SYSCTL_OSC_INT.
//
//
if(((ui32Config & 0x38) != SYSCTL_OSC_MAIN) &&
if(((ui32Config & 0x38) != SYSCTL_OSC_MAIN) &&
((ui32Config & 0x38) != SYSCTL_OSC_INT))
((ui32Config & 0x38) != SYSCTL_OSC_INT))
{
{
return(0);
return(0);
}
}


//
//
// Get the VCO index out of the ui32Config parameter.
// Get the VCO index out of the ui32Config parameter.
//
//
i32VCOIdx = (ui32Config >> 24) & 7;
i32VCOIdx = (ui32Config >> 24) & 7;


//
//
// Check that the VCO index is not out of bounds.
// Check that the VCO index is not out of bounds.
//
//
ASSERT(i32VCOIdx < MAX_VCO_ENTRIES);
ASSERT(i32VCOIdx < MAX_VCO_ENTRIES);


//
//
// Set the memory timings for the maximum external frequency since
// Set the memory timings for the maximum external frequency since
// this could be a switch to PIOSC or possibly to MOSC which can be
// this could be a switch to PIOSC or possibly to MOSC which can be
// up to 25MHz.
// up to 25MHz.
//
//
HWREG(SYSCTL_MEMTIM0) = _SysCtlMemTimingGet(25000000);
HWREG(SYSCTL_MEMTIM0) = _SysCtlMemTimingGet(25000000);


//
//
// Clear the old PLL divider and source in case it was set.
// Clear the old PLL divider and source in case it was set.
//
//
ui32RSClkConfig = HWREG(SYSCTL_RSCLKCFG) &
ui32RSClkConfig = HWREG(SYSCTL_RSCLKCFG) &
~(SYSCTL_RSCLKCFG_PSYSDIV_M |
~(SYSCTL_RSCLKCFG_PSYSDIV_M |
SYSCTL_RSCLKCFG_OSCSRC_M |
SYSCTL_RSCLKCFG_OSCSRC_M |
SYSCTL_RSCLKCFG_PLLSRC_M | SYSCTL_RSCLKCFG_USEPLL);
SYSCTL_RSCLKCFG_PLLSRC_M | SYSCTL_RSCLKCFG_USEPLL);


//
//
// Update the memory timings to match running from PIOSC.
// Update the memory timings to match running from PIOSC.
//
//
ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIMU;
ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIMU;


//
//
// Update clock configuration to switch back to PIOSC.
// Update clock configuration to switch back to PIOSC.
//
//
HWREG(SYSCTL_RSCLKCFG) = ui32RSClkConfig;
HWREG(SYSCTL_RSCLKCFG) = ui32RSClkConfig;


//
//
// The table starts at 5 MHz so modify the index to match this.
// The table starts at 5 MHz so modify the index to match this.
//
//
i32XtalIdx -= SysCtlXtalCfgToIndex(SYSCTL_XTAL_5MHZ);
i32XtalIdx -= SysCtlXtalCfgToIndex(SYSCTL_XTAL_5MHZ);


//
//
// If there were no changes to the PLL do not force the PLL to lock by
// If there were no changes to the PLL do not force the PLL to lock by
// writing the PLL settings.
// writing the PLL settings.
//
//
if((HWREG(SYSCTL_PLLFREQ1) !=
if((HWREG(SYSCTL_PLLFREQ1) !=
g_pppui32XTALtoVCO[i32VCOIdx][i32XtalIdx][1]) ||
g_pppui32XTALtoVCO[i32VCOIdx][i32XtalIdx][1]) ||
(HWREG(SYSCTL_PLLFREQ0) !=
(HWREG(SYSCTL_PLLFREQ0) !=
(g_pppui32XTALtoVCO[i32VCOIdx][i32XtalIdx][0] |
(g_pppui32XTALtoVCO[i32VCOIdx][i32XtalIdx][0] |
SYSCTL_PLLFREQ0_PLLPWR)))
SYSCTL_PLLFREQ0_PLLPWR)))
{
{
bNewPLL = true;
bNewPLL = true;
}
}
else
else
{
{
bNewPLL = false;
bNewPLL = false;
}
}


//
//
// If there are new PLL settings write them.
// If there are new PLL settings write them.
//
//
if(bNewPLL)
if(bNewPLL)
{
{
//
//
// Set the oscillator source.
// Set the oscillator source.
//
//
HWREG(SYSCTL_RSCLKCFG) |= ui32OscSelect;
HWREG(SYSCTL_RSCLKCFG) |= ui32OscSelect;


//
//
// Set the M, N and Q values provided from the table and preserve
// Set the M, N and Q values provided from the table and preserve
// the power state of the main PLL.
// the power state of the main PLL.
//
//
HWREG(SYSCTL_PLLFREQ1) =
HWREG(SYSCTL_PLLFREQ1) =
g_pppui32XTALtoVCO[i32VCOIdx][i32XtalIdx][1];
g_pppui32XTALtoVCO[i32VCOIdx][i32XtalIdx][1];
HWREG(SYSCTL_PLLFREQ1) |=
g_pppui32XTALtoVCO[i32VCOIdx][i32XtalIdx][2];
HWREG(SYSCTL_PLLFREQ0) =
HWREG(SYSCTL_PLLFREQ0) =
(g_pppui32XTALtoVCO[i32VCOIdx][i32XtalIdx][0] |
(g_pppui32XTALtoVCO[i32VCOIdx][i32XtalIdx][0] |
(HWREG(SYSCTL_PLLFREQ0) & SYSCTL_PLLFREQ0_PLLPWR));
(HWREG(SYSCTL_PLLFREQ0) & SYSCTL_PLLFREQ0_PLLPWR));
}
}


//
//
// Calculate the System divider such that we get a frequency that is
// Calculate the System divider such that we get a frequency that is
// the closest to the requested frequency without going over.
// the closest to the requested frequency without going over.
//
//
ui32SysDiv = (g_pui32VCOFrequencies[i32VCOIdx] + ui32SysClock - 1) /
ui32SysDiv = (g_pui32VCOFrequencies[i32VCOIdx] + ui32SysClock - 1) /
ui32SysClock;
ui32SysClock;


//
//
// Calculate the actual system clock.
// Calculate the actual system clock.
//
//
ui32SysClock = _SysCtlFrequencyGet(ui32Osc) / ui32SysDiv;
ui32SysClock = _SysCtlFrequencyGet(ui32Osc) / ui32SysDiv;


//
//
// Set the Flash and EEPROM timing values.
// Set the Flash and EEPROM timing values.
//
//
HWREG(SYSCTL_MEMTIM0) = _SysCtlMemTimingGet(ui32SysClock);
HWREG(SYSCTL_MEMTIM0) = _SysCtlMemTimingGet(ui32SysClock);


//
//
// Check if the PLL is already powered up.
// Check if the PLL is already powered up.
//
//
if(HWREG(SYSCTL_PLLFREQ0) & SYSCTL_PLLFREQ0_PLLPWR)
if(HWREG(SYSCTL_PLLFREQ0) & SYSCTL_PLLFREQ0_PLLPWR)
{
{
if(bNewPLL == true)
if(bNewPLL == true)
{
{
//
//
// Trigger the PLL to lock to the new frequency.
// Trigger the PLL to lock to the new frequency.
//
//
HWREG(SYSCTL_RSCLKCFG) |= SYSCTL_RSCLKCFG_NEWFREQ;
HWREG(SYSCTL_RSCLKCFG) |= SYSCTL_RSCLKCFG_NEWFREQ;
}
}
}
}
else
else
{
{
//
//
// Power up the PLL.
// Power up the PLL.
//
//
HWREG(SYSCTL_PLLFREQ0) |= SYSCTL_PLLFREQ0_PLLPWR;
HWREG(SYSCTL_PLLFREQ0) |= SYSCTL_PLLFREQ0_PLLPWR;
}
}


//
//
// Wait until the PLL has locked.
// Wait until the PLL has locked.
//
//
for(i32Timeout = 32768; i32Timeout > 0; i32Timeout--)
for(i32Timeout = 32768; i32Timeout > 0; i32Timeout--)
{
{
if((HWREG(SYSCTL_PLLSTAT) & SYSCTL_PLLSTAT_LOCK))
if((HWREG(SYSCTL_PLLSTAT) & SYSCTL_PLLSTAT_LOCK))
{
{
break;
break;
}
}
}
}


//
//
// If the loop above did not timeout then switch over to the PLL
// If the loop above did not timeout then switch over to the PLL
//
//
if(i32Timeout)
if(i32Timeout)
{
{
ui32RSClkConfig = HWREG(SYSCTL_RSCLKCFG);
ui32RSClkConfig = HWREG(SYSCTL_RSCLKCFG);
ui32RSClkConfig |= ((ui32SysDiv - 1) <<
ui32RSClkConfig |= ((ui32SysDiv - 1) <<
SYSCTL_RSCLKCFG_PSYSDIV_S) | ui32OscSelect |
SYSCTL_RSCLKCFG_PSYSDIV_S) | ui32OscSelect |
SYSCTL_RSCLKCFG_USEPLL;
SYSCTL_RSCLKCFG_USEPLL;
ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIMU;
ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIMU;


//
//
// Set the new clock configuration.
// Set the new clock configuration.
//
//
HWREG(SYSCTL_RSCLKCFG) = ui32RSClkConfig;
HWREG(SYSCTL_RSCLKCFG) = ui32RSClkConfig;
}
}
else
else
{
{
ui32SysClock = 0;
}
}
else
{
//
//
// Set the Flash and EEPROM timing values for PIOSC.
// Set the Flash and EEPROM timing values for PIOSC.
//
//
HWREG(SYSCTL_MEMTIM0) = _SysCtlMemTimingGet(16000000);
HWREG(SYSCTL_MEMTIM0) = _SysCtlMemTimingGet(16000000);


//
//
// Make sure that the PLL is powered down since it is not being used.
// Make sure that the PLL is powered down since it is not being used.
//
//
HWREG(SYSCTL_PLLFREQ0) &= ~SYSCTL_PLLFREQ0_PLLPWR;
HWREG(SYSCTL_PLLFREQ0) &= ~SYSCTL_PLLFREQ0_PLLPWR;


//
//
// Clear the old PLL divider and source in case it was set.
// Clear the old PLL divider and source in case it was set.
//
//
ui32RSClkConfig = HWREG(SYSCTL_RSCLKCFG);
ui32RSClkConfig = HWREG(SYSCTL_RSCLKCFG);
ui32RSClkConfig &= ~(SYSCTL_RSCLKCFG_OSYSDIV_M |
ui32RSClkConfig &= ~(SYSCTL_RSCLKCFG_OSYSDIV_M |
SYSCTL_RSCLKCFG_OSCSRC_M |
SYSCTL_RSCLKCFG_OSCSRC_M |
SYSCTL_RSCLKCFG_USEPLL);
SYSCTL_RSCLKCFG_USEPLL);


//
//
// Update the memory timings.
// Update the memory timings.
//
//
ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIMU;
ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIMU;


//
//
// Set the new clock configuration.
// Set the new clock configuration.
//
//
HWREG(SYSCTL_RSCLKCFG) = ui32RSClkConfig;
HWREG(SYSCTL_RSCLKCFG) = ui32RSClkConfig;


//
//
// If zero given as the system clock then default to divide by 1.
// If zero given as the system clock then default to divide by 1.
//
//
if(ui32SysClock == 0)
if(ui32SysClock == 0)
{
{
ui32SysDiv = 0;
ui32SysDiv = 0;
}
}
else
else
{
{
//
//
// Calculate the System divider based on the requested
// Calculate the System divider based on the requested
// frequency.
// frequency.
//
//
ui32SysDiv = ui32Osc / ui32SysClock;
ui32SysDiv = ui32Osc / ui32SysClock;


//
//
// If the system divisor is not already zero, subtract one to
// If the system divisor is not already zero, subtract one to
// set the value in the register which requires the value to
// set the value in the register which requires the value to
// be n-1.
// be n-1.
//
//
if(ui32SysDiv != 0)
if(ui32SysDiv != 0)
{
{
ui32SysDiv -= 1;
ui32SysDiv -= 1;
}
}


//
//
// Calculate the system clock.
// Calculate the system clock.
//
//
ui32SysClock = ui32Osc / (ui32SysDiv + 1);
ui32SysClock = ui32Osc / (ui32SysDiv + 1);
}
}


//
//
// Set the memory timing values for the new system clock.
// Set the memory timing values for the new system clock.
//
//
HWREG(SYSCTL_MEMTIM0) = _SysCtlMemTimingGet(ui32SysClock);
HWREG(SYSCTL_MEMTIM0) = _SysCtlMemTimingGet(ui32SysClock);


//
//
// Set the new system clock values.
// Set the new system clock values.
//
//
ui32RSClkConfig = HWREG(SYSCTL_RSCLKCFG);
ui32RSClkConfig = HWREG(SYSCTL_RSCLKCFG);
ui32RSClkConfig |= (ui32SysDiv << SYSCTL_RSCLKCFG_OSYSDIV_S) |
ui32RSClkConfig |= (ui32SysDiv << SYSCTL_RSCLKCFG_OSYSDIV_S) |
ui32OscSelect;
ui32OscSelect;


//
//
// Update the memory timings.
// Update the memory timings.
//
//
ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIMU;
ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIMU;


//
//
// Set the new clock configuration.
// Set the new clock configuration.
//
//
HWREG(SYSCTL_RSCLKCFG) = ui32RSClkConfig;
HWREG(SYSCTL_RSCLKCFG) = ui32RSClkConfig;
}
}


//
// Finally change the OSCSRC back to PIOSC
//
HWREG(SYSCTL_RSCLKCFG) &= ~(SYSCTL_RSCLKCFG_OSCSRC_M);

return(ui32SysClock);
return(ui32SysClock);
}
}