📄 sysctl.c
字号:
//
SysCtlDelay(4096);
}
else
{
//
// Delay for 524,288 iterations.
//
SysCtlDelay(524288);
}
}
//
// Set the new crystal value, oscillator source, and PLL configuration.
// Since the OSCSRC2 field in RCC2 overlaps the XTAL field in RCC, the
// OSCSRC field has a special encoding within ulConfig to avoid the
// overlap.
//
ulRCC &= ~(SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M |
SYSCTL_RCC_PWRDN | SYSCTL_RCC_OEN);
ulRCC |= ulConfig & (SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M |
SYSCTL_RCC_PWRDN | SYSCTL_RCC_OEN);
ulRCC2 &= ~(SYSCTL_RCC2_USERCC2 | SYSCTL_RCC2_OSCSRC2_M |
SYSCTL_RCC2_PWRDN2);
ulRCC2 |= ulConfig & (SYSCTL_RCC2_USERCC2 | SYSCTL_RCC_OSCSRC_M |
SYSCTL_RCC2_PWRDN2);
ulRCC2 |= (ulConfig & 0x00000008) << 3;
//
// Clear the PLL lock interrupt.
//
HWREG(SYSCTL_MISC) = SYSCTL_INT_PLL_LOCK;
//
// Write the new RCC value.
//
if(ulRCC2 & SYSCTL_RCC2_USERCC2)
{
HWREG(SYSCTL_RCC2) = ulRCC2;
HWREG(SYSCTL_RCC) = ulRCC;
}
else
{
HWREG(SYSCTL_RCC) = ulRCC;
HWREG(SYSCTL_RCC2) = ulRCC2;
}
//
// Wait for a bit so that new crystal value and oscillator source can take
// effect.
//
SysCtlDelay(16);
//
// Set the requested system divider and disable the appropriate
// oscillators. This will not get written immediately.
//
ulRCC &= ~(SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV |
SYSCTL_RCC_IOSCDIS | SYSCTL_RCC_MOSCDIS);
ulRCC |= ulConfig & (SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV |
SYSCTL_RCC_IOSCDIS | SYSCTL_RCC_MOSCDIS);
ulRCC2 &= ~(SYSCTL_RCC2_SYSDIV2_M);
ulRCC2 |= ulConfig & SYSCTL_RCC2_SYSDIV2_M;
if(ulConfig & SYSCTL_RCC2_USEFRACT)
{
ulRCC |= SYSCTL_RCC_USESYSDIV;
ulRCC2 &= ~(SYSCTL_RCC_USESYSDIV);
ulRCC2 |= ulConfig & (SYSCTL_RCC2_USEFRACT | SYSCTL_RCC2_FRACT);
}
else
{
ulRCC2 &= ~(SYSCTL_RCC2_USEFRACT);
}
//
// See if the PLL output is being used to clock the system.
//
if(!(ulConfig & SYSCTL_RCC_BYPASS))
{
//
// Wait until the PLL has locked.
//
for(ulDelay = 32768; ulDelay > 0; ulDelay--)
{
if(HWREG(SYSCTL_RIS) & SYSCTL_INT_PLL_LOCK)
{
break;
}
}
//
// Enable use of the PLL.
//
ulRCC &= ~(SYSCTL_RCC_BYPASS);
ulRCC2 &= ~(SYSCTL_RCC2_BYPASS2);
}
//
// Write the final RCC value.
//
HWREG(SYSCTL_RCC) = ulRCC;
HWREG(SYSCTL_RCC2) = ulRCC2;
//
// Delay for a little bit so that the system divider takes effect.
//
SysCtlDelay(16);
}
//*****************************************************************************
//
//! Gets the processor clock rate.
//!
//! This function determines the clock rate of the processor clock. This is
//! also the clock rate of all the peripheral modules (with the exception of
//! PWM, which has its own clock divider).
//!
//! \note This will not return accurate results if SysCtlClockSet() has not
//! been called to configure the clocking of the device, or if the device is
//! directly clocked from a crystal (or a clock source) that is not one of the
//! supported crystal frequencies. In the later case, this function should be
//! modified to directly return the correct system clock rate.
//!
//! \return The processor clock rate.
//
//*****************************************************************************
unsigned long
SysCtlClockGet(void)
{
unsigned long ulRCC, ulRCC2, ulPLL, ulClk;
//
// Read RCC and RCC2. For Sandstorm-class devices (which do not have
// RCC2), the RCC2 read will return 0, which indicates that RCC2 is
// disabled (since the SYSCTL_RCC2_USERCC2 bit is clear).
//
ulRCC = HWREG(SYSCTL_RCC);
ulRCC2 = HWREG(SYSCTL_RCC2);
//
// Get the base clock rate.
//
switch((ulRCC2 & SYSCTL_RCC2_USERCC2) ?
(ulRCC2 & SYSCTL_RCC2_OSCSRC2_M) :
(ulRCC & SYSCTL_RCC_OSCSRC_M))
{
//
// The main oscillator is the clock source. Determine its rate from
// the crystal setting field.
//
case SYSCTL_RCC_OSCSRC_MAIN:
{
ulClk = g_pulXtals[(ulRCC & SYSCTL_RCC_XTAL_M) >>
SYSCTL_RCC_XTAL_S];
break;
}
//
// The internal oscillator is the source clock.
//
case SYSCTL_RCC_OSCSRC_INT:
{
//
// See if this is a Sandstorm-class or Fury-class device.
//
if(CLASS_IS_SANDSTORM)
{
//
// The internal oscillator on a Sandstorm-class device is
// 15 MHz +/- 50%.
//
ulClk = 15000000;
}
else if((CLASS_IS_FURY && REVISION_IS_A2) ||
(CLASS_IS_DUSTDEVIL && REVISION_IS_A0))
{
//
// The internal oscillator on a rev A2 Fury-class device and a
// rev A0 Dustdevil-class device is 12 MHz +/- 30%.
//
ulClk = 12000000;
}
else
{
//
// The internal oscillator on all other devices is 16 MHz.
//
ulClk = 16000000;
}
break;
}
//
// The internal oscillator divided by four is the source clock.
//
case SYSCTL_RCC_OSCSRC_INT4:
{
//
// See if this is a Sandstorm-class or Fury-class device.
//
if(CLASS_IS_SANDSTORM)
{
//
// The internal oscillator on a Sandstorm-class device is
// 15 MHz +/- 50%.
//
ulClk = 15000000 / 4;
}
else if((CLASS_IS_FURY && REVISION_IS_A2) ||
(CLASS_IS_DUSTDEVIL && REVISION_IS_A0))
{
//
// The internal oscillator on a rev A2 Fury-class device and a
// rev A0 Dustdevil-class device is 12 MHz +/- 30%.
//
ulClk = 12000000 / 4;
}
else
{
//
// The internal oscillator on a Tempest-class device is 16 MHz.
//
ulClk = 16000000 / 4;
}
break;
}
//
// The internal 30 KHz oscillator is the source clock.
//
case SYSCTL_RCC_OSCSRC_30:
{
//
// The internal 30 KHz oscillator has an accuracy of +/- 30%.
//
ulClk = 30000;
break;
}
//
// The 4.19 MHz clock from the hibernate module is the clock source.
//
case SYSCTL_RCC2_OSCSRC2_419:
{
ulClk = 4194304;
break;
}
//
// The 32 KHz clock from the hibernate module is the source clock.
//
case SYSCTL_RCC2_OSCSRC2_32:
{
ulClk = 32768;
break;
}
//
// An unknown setting, so return a zero clock (that is, an unknown
// clock rate).
//
default:
{
return(0);
}
}
//
// See if the PLL is being used.
//
if(((ulRCC2 & SYSCTL_RCC2_USERCC2) && !(ulRCC2 & SYSCTL_RCC2_BYPASS2)) ||
(!(ulRCC2 & SYSCTL_RCC2_USERCC2) && !(ulRCC & SYSCTL_RCC_BYPASS)))
{
//
// Get the PLL configuration.
//
ulPLL = HWREG(SYSCTL_PLLCFG);
//
// See if this is a Sandstorm-class or Fury-class device.
//
if(CLASS_IS_SANDSTORM)
{
//
// Compute the PLL output frequency based on its input frequency.
// The formula for a Sandstorm-class devices is
// "(xtal * (f + 2)) / (r + 2)".
//
ulClk = ((ulClk * (((ulPLL & SYSCTL_PLLCFG_F_M) >>
SYSCTL_PLLCFG_F_S) + 2)) /
(((ulPLL & SYSCTL_PLLCFG_R_M) >>
SYSCTL_PLLCFG_R_S) + 2));
}
else
{
//
// Compute the PLL output frequency based on its input frequency.
// The formula for a Fury-class device is
// "(xtal * f) / ((r + 1) * 2)".
//
ulClk = ((ulClk * ((ulPLL & SYSCTL_PLLCFG_F_M) >>
SYSCTL_PLLCFG_F_S)) /
((((ulPLL & SYSCTL_PLLCFG_R_M) >>
SYSCTL_PLLCFG_R_S) + 1) * 2));
}
//
// See if the optional output divide by 2 is being used.
//
if(ulPLL & SYSCTL_PLLCFG_OD_2)
{
ulClk /= 2;
}
//
// See if the optional output divide by 4 is being used.
//
if(ulPLL & SYSCTL_PLLCFG_OD_4)
{
ulClk /= 4;
}
//
// Force the system divider to be enabled. It is always used when
// using the PLL, but in some cases it will not read as being enabled.
//
ulRCC |= SYSCTL_RCC_USESYSDIV;
}
//
// See if the system divider is being used.
//
if(ulRCC & SYSCTL_RCC_USESYSDIV)
{
//
// Adjust the clock rate by the system clock divider.
//
if(ulRCC2 & SYSCTL_RCC2_USERCC2)
{
if((ulRCC2 & SYSCTL_RCC2_USEFRACT) &&
(((ulRCC2 & SYSCTL_RCC2_USERCC2) &&
!(ulRCC2 & SYSCTL_RCC2_BYPASS2)) ||
(!(ulRCC2 & SYSCTL_RCC2_USERCC2) &&
!(ulRCC & SYSCTL_RCC_BYPASS))))
{
ulClk = ((ulClk * 2) / (((ulRCC2 & (SYSCTL_RCC2_SYSDIV2_M |
SYSCTL_RCC2_FRACT)) >>
(SYSCTL_RCC2_SYSDIV2_S - 1)) + 1));
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -