📄 sysctl.c
字号:
//
// Clear the given reset reasons.
//
HWREG(SYSCTL_RESC) &= ~(ulCauses);
}
//*****************************************************************************
//
//! Configures the brown-out control.
//!
//! \param ulConfig is the desired configuration of the brown-out control.
//! Must be the logical OR of \b SYSCTL_BOR_RESET and/or
//! \b SYSCTL_BOR_RESAMPLE.
//! \param ulDelay is the number of internal oscillator cycles to wait before
//! resampling an asserted brown-out signal. This value only has meaning when
//! \b SYSCTL_BOR_RESAMPLE is set and must be less than 8192.
//!
//! This function configures how the brown-out control operates. It can detect
//! a brown-out by looking at only the brown-out output, or it can wait for it
//! to be active for two consecutive samples separated by a configurable time.
//! When it detects a brown-out condition, it can either reset the device or
//! generate a processor interrupt.
//!
//! \return None.
//
//*****************************************************************************
void
SysCtlBrownOutConfigSet(unsigned long ulConfig, unsigned long ulDelay)
{
//
// Check the arguments.
//
ASSERT(!(ulConfig & ~(SYSCTL_BOR_RESET | SYSCTL_BOR_RESAMPLE)));
ASSERT(ulDelay < 8192);
//
// Configure the brown-out reset control.
//
HWREG(SYSCTL_PBORCTL) = (ulDelay << SYSCTL_PBORCTL_BORTIM_S) | ulConfig;
}
//*****************************************************************************
//
//! \internal
//!
//! Provides a small delay.
//!
//! \param ulCount is the number of delay loop iterations to perform.
//!
//! This function provides a means of generating a constant length delay. It
//! is written in assembly to keep the delay consistent across tool chains,
//! avoiding the need to tune the delay based on the tool chain in use.
//!
//! The loop below takes 3 cycles/loop.
//!
//! \return None.
//
//*****************************************************************************
#if defined(ewarm)
static void
SysCtlDelay(unsigned long ulCount)
{
__asm(" subs r0, #1\n"
" bne.n SysCtlDelay\n"
" bx lr");
}
#endif
#if defined(gcc) || defined(sourcerygxx)
static void __attribute__((naked))
SysCtlDelay(unsigned long ulCount)
{
__asm(" subs r0, #1\n"
" bne SysCtlDelay\n"
" bx lr");
}
#endif
#if defined(rvmdk) || defined(__ARMCC_VERSION)
__asm void
SysCtlDelay(unsigned long ulCount)
{
subs r0, #1;
bne SysCtlDelay;
bx lr;
}
#endif
//*****************************************************************************
//
//! Sets the clocking of the device.
//!
//! \param ulConfig is the required configuration of the device clocking.
//!
//! This function configures the clocking of the device. The input crystal
//! frequency, oscillator to be used, use of the PLL, and the system clock
//! divider are all configured with this function.
//!
//! The \e ulConfig parameter is the logical OR of several different values,
//! many of which are grouped into sets where only one can be chosen.
//!
//! The system clock divider is chosen with one of the following values:
//! \b SYSCTL_SYSDIV_1, \b SYSCTL_SYSDIV_2, \b SYSCTL_SYSDIV_3, ...
//! \b SYSCTL_SYSDIV_64. Only \b SYSCTL_SYSDIV_1 through \b SYSCTL_SYSDIV_16
//! are valid on Sandstorm-class devices.
//!
//! The use of the PLL is chosen with either \b SYSCTL_USE_PLL or
//! \b SYSCTL_USE_OSC.
//!
//! The external crystal frequency is chosen with one of the following values:
//! \b SYSCTL_XTAL_1MHZ, \b SYSCTL_XTAL_1_84MHZ, \b SYSCTL_XTAL_2MHZ,
//! \b SYSCTL_XTAL_2_45MHZ, \b SYSCTL_XTAL_3_57MHZ, \b SYSCTL_XTAL_3_68MHZ,
//! \b SYSCTL_XTAL_4MHZ, \b SYSCTL_XTAL_4_09MHZ, \b SYSCTL_XTAL_4_91MHZ,
//! \b SYSCTL_XTAL_5MHZ, \b SYSCTL_XTAL_5_12MHZ, \b SYSCTL_XTAL_6MHZ,
//! \b SYSCTL_XTAL_6_14MHZ, \b SYSCTL_XTAL_7_37MHZ, \b SYSCTL_XTAL_8MHZ, or
//! \b SYSCTL_XTAL_8_19MHZ. Values below \b SYSCTL_XTAL_3_57MHZ are not valid
//! when the PLL is in operation.
//!
//! The oscillator source is chosen with one of the following values:
//! \b SYSCTL_OSC_MAIN, \b SYSCTL_OSC_INT, \b SYSCTL_OSC_INT4,
//! \b SYSCTL_OSC_INT30, or \b SYSCTL_OSC_EXT32. On Sandstorm-class devices,
//! \b SYSCTL_OSC_INT30 and \b SYSCTL_OSC_EXT32 are not valid.
//! \b SYSCTL_OSC_EXT32 is only available on Fury-class devices with the
//! hibernate module, and then only when the hibernate module has been enabled.
//!
//! The internal and main oscillators are disabled with the
//! \b SYSCTL_INT_OSC_DIS and \b SYSCTL_MAIN_OSC_DIS flags, respectively.
//! The external oscillator must be enabled in order to use an external clock
//! source. Note that attempts to disable the oscillator used to clock the
//! device will be prevented by the hardware.
//!
//! To clock the system from an external source (such as an external crystal
//! oscillator), use \b SYSCTL_USE_OSC \b | \b SYSCTL_OSC_MAIN. To clock the
//! system from the main oscillator, use \b SYSCTL_USE_OSC \b |
//! \b SYSCTL_OSC_MAIN. To clock the system from the PLL, use
//! \b SYSCTL_USE_PLL \b | \b SYSCTL_OSC_MAIN, and select the appropriate
//! crystal with one of the \b SYSCTL_XTAL_xxx values.
//!
//! \note If selecting the PLL as the system clock source (that is, via
//! \b SYSCTL_USE_PLL), this function will poll the PLL lock interrupt to
//! determine when the PLL has locked. If an interrupt handler for the
//! system control interrupt is in place, and it responds to and clears the
//! PLL lock interrupt, this function will delay until its timeout has occurred
//! instead of completing as soon as PLL lock is achieved.
//!
//! \return None.
//
//*****************************************************************************
void
SysCtlClockSet(unsigned long ulConfig)
{
unsigned long ulDelay, ulRCC, ulRCC2;
//
// See if this is a Sandstorm-class device and clocking features from newer
// devices were requested.
//
if(DEVICE_IS_SANDSTORM && (ulConfig & SYSCTL_RCC2_USERCC2))
{
//
// Return without changing the clocking since the requested
// configuration can not be achieved.
//
return;
}
//
// Get the current value of the RCC and RCC2 registers. If using a
// Sandstorm-class device, the RCC2 register will read back as zero and the
// writes to it from within this function will be ignored.
//
ulRCC = HWREG(SYSCTL_RCC);
ulRCC2 = HWREG(SYSCTL_RCC2);
//
// Bypass the PLL and system clock dividers for now.
//
ulRCC |= SYSCTL_RCC_BYPASS;
ulRCC &= ~(SYSCTL_RCC_USESYSDIV);
ulRCC2 |= SYSCTL_RCC2_BYPASS2;
//
// Write the new RCC value.
//
HWREG(SYSCTL_RCC) = ulRCC;
HWREG(SYSCTL_RCC2) = ulRCC2;
//
// See if either oscillator needs to be enabled.
//
if(((ulRCC & SYSCTL_RCC_IOSCDIS) && !(ulConfig & SYSCTL_RCC_IOSCDIS)) ||
((ulRCC & SYSCTL_RCC_MOSCDIS) && !(ulConfig & SYSCTL_RCC_MOSCDIS)))
{
//
// Make sure that the required oscillators are enabled. For now, the
// previously enabled oscillators must be enabled along with the newly
// requested oscillators.
//
ulRCC &= (~(SYSCTL_RCC_IOSCDIS | SYSCTL_RCC_MOSCDIS) |
(ulConfig & (SYSCTL_RCC_IOSCDIS | SYSCTL_RCC_MOSCDIS)));
//
// Write the new RCC value.
//
HWREG(SYSCTL_RCC) = ulRCC;
//
// Wait for a bit, giving the oscillator time to stabilize. The number
// of iterations is adjusted based on the current clock source; a
// smaller number of iterations is required for slower clock rates.
//
if((ulRCC2 & SYSCTL_RCC2_USERCC2) &&
(((ulRCC2 & SYSCTL_RCC2_OSCSRC2_M) == SYSCTL_RCC2_OSCSRC2_30) ||
((ulRCC2 & SYSCTL_RCC2_OSCSRC2_M) == SYSCTL_RCC2_OSCSRC2_32)))
{
//
// Delay for 4096 iterations.
//
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;
//
// 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.
//
//*******************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -