rt-thread-official/bsp/tms320f28379d/libraries/common/deprecated/driverlib/sysctl.c

842 lines
29 KiB
C

//###########################################################################
//
// FILE: sysctl.c
//
// TITLE: Stellaris style wrapper driver for F2837x system control.
//
//###########################################################################
// $TI Release: F2837xD Support Library v3.05.00.00 $
// $Release Date: Tue Jun 26 03:15:23 CDT 2018 $
// $Copyright:
// Copyright (C) 2013-2018 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the
// distribution.
//
// Neither the name of Texas Instruments Incorporated nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//###########################################################################
//*****************************************************************************
//
//! \addtogroup sysctl_api
//! @{
//
//*****************************************************************************
#include "F28x_Project.h"
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/sysctl.h"
//*****************************************************************************
//
//! \internal
//! Checks a peripheral identifier.
//!
//! \param ui32Peripheral is the peripheral identifier.
//!
//! This function determines if a peripheral identifier is valid.
//!
//! \return Returns \b true if the peripheral identifier is valid and \b false
//! otherwise.
//
//*****************************************************************************
#ifdef DEBUG
static bool
_SysCtlPeripheralValid(uint32_t ui32Peripheral)
{
return((ui32Peripheral == SYSCTL_PERIPH_CLA1) ||
(ui32Peripheral == SYSCTL_PERIPH_DMA) ||
(ui32Peripheral == SYSCTL_PERIPH_TIMER0) ||
(ui32Peripheral == SYSCTL_PERIPH_TIMER1) ||
(ui32Peripheral == SYSCTL_PERIPH_TIMER2) ||
(ui32Peripheral == SYSCTL_PERIPH_HRPWM) ||
(ui32Peripheral == SYSCTL_PERIPH_TBCLKSYNC) ||
(ui32Peripheral == SYSCTL_PERIPH_GTBCLKSYNC) ||
(ui32Peripheral == SYSCTL_PERIPH_EMIF1) ||
(ui32Peripheral == SYSCTL_PERIPH_EMIF2) ||
(ui32Peripheral == SYSCTL_PERIPH_EPWM1) ||
(ui32Peripheral == SYSCTL_PERIPH_EPWM2) ||
(ui32Peripheral == SYSCTL_PERIPH_EPWM3) ||
(ui32Peripheral == SYSCTL_PERIPH_EPWM4) ||
(ui32Peripheral == SYSCTL_PERIPH_EPWM5) ||
(ui32Peripheral == SYSCTL_PERIPH_EPWM6) ||
(ui32Peripheral == SYSCTL_PERIPH_EPWM7) ||
(ui32Peripheral == SYSCTL_PERIPH_EPWM8) ||
(ui32Peripheral == SYSCTL_PERIPH_EPWM9) ||
(ui32Peripheral == SYSCTL_PERIPH_EPWM10) ||
(ui32Peripheral == SYSCTL_PERIPH_EPWM11) ||
(ui32Peripheral == SYSCTL_PERIPH_EPWM12) ||
(ui32Peripheral == SYSCTL_PERIPH_ECAP1) ||
(ui32Peripheral == SYSCTL_PERIPH_ECAP2) ||
(ui32Peripheral == SYSCTL_PERIPH_ECAP3) ||
(ui32Peripheral == SYSCTL_PERIPH_ECAP4) ||
(ui32Peripheral == SYSCTL_PERIPH_ECAP5) ||
(ui32Peripheral == SYSCTL_PERIPH_ECAP6) ||
(ui32Peripheral == SYSCTL_PERIPH_EQEP1) ||
(ui32Peripheral == SYSCTL_PERIPH_EQEP2) ||
(ui32Peripheral == SYSCTL_PERIPH_EQEP3) ||
(ui32Peripheral == SYSCTL_PERIPH_SD1) ||
(ui32Peripheral == SYSCTL_PERIPH_SD2) ||
(ui32Peripheral == SYSCTL_PERIPH_SCI1) ||
(ui32Peripheral == SYSCTL_PERIPH_SCI2) ||
(ui32Peripheral == SYSCTL_PERIPH_SCI3) ||
(ui32Peripheral == SYSCTL_PERIPH_SCI4) ||
(ui32Peripheral == SYSCTL_PERIPH_SPI1) ||
(ui32Peripheral == SYSCTL_PERIPH_SPI2) ||
(ui32Peripheral == SYSCTL_PERIPH_SPI3) ||
(ui32Peripheral == SYSCTL_PERIPH_I2C1) ||
(ui32Peripheral == SYSCTL_PERIPH_I2C2) ||
(ui32Peripheral == SYSCTL_PERIPH_CAN1) ||
(ui32Peripheral == SYSCTL_PERIPH_CAN2) ||
(ui32Peripheral == SYSCTL_PERIPH_MCBSP1) ||
(ui32Peripheral == SYSCTL_PERIPH_MCBSP2) ||
(ui32Peripheral == SYSCTL_PERIPH_UPP1) ||
(ui32Peripheral == SYSCTL_PERIPH_ADC1) ||
(ui32Peripheral == SYSCTL_PERIPH_ADC2) ||
(ui32Peripheral == SYSCTL_PERIPH_ADC3) ||
(ui32Peripheral == SYSCTL_PERIPH_ADC4) ||
(ui32Peripheral == SYSCTL_PERIPH_CMPSS1) ||
(ui32Peripheral == SYSCTL_PERIPH_CMPSS2) ||
(ui32Peripheral == SYSCTL_PERIPH_CMPSS3) ||
(ui32Peripheral == SYSCTL_PERIPH_CMPSS4) ||
(ui32Peripheral == SYSCTL_PERIPH_CMPSS5) ||
(ui32Peripheral == SYSCTL_PERIPH_CMPSS6) ||
(ui32Peripheral == SYSCTL_PERIPH_CMPSS7) ||
(ui32Peripheral == SYSCTL_PERIPH_CMPSS8) ||
(ui32Peripheral == SYSCTL_PERIPH_BUFFDAC1) ||
(ui32Peripheral == SYSCTL_PERIPH_BUFFDAC2) ||
(ui32Peripheral == SYSCTL_PERIPH_BUFFDAC3));
}
#endif
//*****************************************************************************
//
//! Determines if a peripheral is present.
//!
//! \param ui32Peripheral is the peripheral in question.
//!
//! This function determines if a particular peripheral is present in the
//! device. Each member of the family has a different peripheral
//! set; this function determines which peripherals are present on this device.
//!
//! \return Returns \b true if the specified peripheral is present and \b false
//! if it is not.
//
//*****************************************************************************
bool
SysCtlPeripheralPresent(uint32_t ui32Peripheral)
{
uint16_t regIndex;
uint16_t bitIndex;
//
// Check the arguments.
//
ASSERT(_SysCtlPeripheralValid(ui32Peripheral));
regIndex = ui32Peripheral & SYSCTL_PERIPH_REG_M;
bitIndex = (ui32Peripheral & SYSCTL_PERIPH_BIT_M) >> SYSCTL_PERIPH_BIT_S;
if(HWREG(&(DevCfgRegs.DC0.all) + (2 * regIndex)) & (1 << bitIndex)){
return true;
}else{
return false;
}
}
//*****************************************************************************
//
//! Determines if a peripheral is ready.
//!
//! \param ui32Peripheral is the peripheral in question.
//!
//! This function determines if a particular peripheral is ready to be
//! accessed. The peripheral may be in a non-ready state if it is not enabled,
//! is being held in reset, or is in the process of becoming ready after being
//! enabled or taken out of reset.
//!
//! \note The ability to check for a peripheral being ready varies based on the
//! part in use. Please consult the data sheet for the part you are
//! using to determine if this feature is available.
//!
//! \return Returns \b true if the specified peripheral is ready and \b false
//! if it is not.
//
//*****************************************************************************
bool
SysCtlPeripheralReady(uint32_t ui32Peripheral)
{
uint16_t regIndex;
uint16_t bitIndex;
//
// Check the arguments.
//
ASSERT(_SysCtlPeripheralValid(ui32Peripheral));
regIndex = ui32Peripheral & SYSCTL_PERIPH_REG_M;
bitIndex = (ui32Peripheral & SYSCTL_PERIPH_BIT_M) >> SYSCTL_PERIPH_BIT_S;
// Is the peripheral there?
if(HWREG((uint32_t)&(DevCfgRegs.DC0.all) + (2 * regIndex)) & ((uint32_t)1 << bitIndex)){
// Is the peripheral enabled?
if(HWREG((uint32_t)&(CpuSysRegs.PCLKCR0.all) + (2 * regIndex)) & ((uint32_t)1 << bitIndex)){
// Is the peripheral in reset?
if((HWREG((uint32_t)&(DevCfgRegs.SOFTPRES0.all) + (2 * regIndex)) & ((uint32_t)1 << bitIndex)) == 0){
// No? Ok cool
return true;
}
}
}else{
return false;
}
return false;
}
//*****************************************************************************
//
//! Resets a peripheral
//!
//! \param ui32Peripheral is the peripheral to reset.
//!
//! The f2837x devices do not have a means of resetting peripherals via
//! via software. This is a dummy function that does nothing.
//!
//!
//! \return None.
//
//*****************************************************************************
void SysCtlPeripheralReset(uint32_t ui32Peripheral)
{
uint16_t regIndex;
uint16_t bitIndex;
regIndex = ui32Peripheral & SYSCTL_PERIPH_REG_M;
bitIndex = (ui32Peripheral & SYSCTL_PERIPH_BIT_M) >> SYSCTL_PERIPH_BIT_S;
EALLOW;
HWREG((uint32_t)&(DevCfgRegs.SOFTPRES0.all) + (2 * regIndex)) |= ((uint32_t)1 << bitIndex);
asm(" nop");
asm(" nop");
asm(" nop");
asm(" nop");
HWREG((uint32_t)&(DevCfgRegs.SOFTPRES0.all) + (2 * regIndex)) &= ~((uint32_t)1 << bitIndex);
EDIS;
}
//*****************************************************************************
//
//! Enables a peripheral.
//!
//! \param ui32Peripheral is the peripheral to enable.
//!
//! Peripherals are enabled with this function. At power-up, all peripherals
//! are disabled; they must be enabled in order to operate or respond to
//! register reads/writes.
//!
//! The \e ui32Peripheral parameter must be only one of the following values:
//! \b SYSCTL_PERIPH_UART_A, \b SYSCTL_PERIPH_UART_B, \b SYSCTL_PERIPH_UART_C,
//! \b SYSCTL_PERIPH_UART_D, \b SYSCTL_PERIPH_SPI_A, \b SYSCTL_PERIPH_SPI_B,
//! \b SYSCTL_PERIPH_SPI_C, \b SYSCTL_PERIPH_MCBSP_A, \b SYSCTL_PERIPH_MCBSP_B,
//! \b SYSCTL_PERIPH_DMA, \b SYSCTL_PERIPH_USB_A
//!
//! \return None.
//
//*****************************************************************************
void
SysCtlPeripheralEnable(uint32_t ui32Peripheral)
{
uint16_t regIndex;
uint16_t bitIndex;
volatile uint32_t test1, test2, test3, test4;
regIndex = (ui32Peripheral & SYSCTL_PERIPH_REG_M);
bitIndex = (ui32Peripheral & SYSCTL_PERIPH_BIT_M) >> SYSCTL_PERIPH_BIT_S;
EALLOW;
HWREG((uint32_t)&(CpuSysRegs.PCLKCR0.all) + (2 * regIndex)) |= ((uint32_t)1 << bitIndex);
EDIS;
}
//*****************************************************************************
//
//! Disables a peripheral.
//!
//! \param ui32Peripheral is the peripheral to disable.
//!
//! Peripherals are disabled with this function. Once disabled, they will not
//! operate or respond to register reads/writes.
//!
//! The \e ui32Peripheral parameter must be only one of the following values:
//! \b SYSCTL_PERIPH_UART_A, \b SYSCTL_PERIPH_UART_B, \b SYSCTL_PERIPH_UART_C,
//! \b SYSCTL_PERIPH_UART_D, \b SYSCTL_PERIPH_SPI_A, \b SYSCTL_PERIPH_SPI_B,
//! \b SYSCTL_PERIPH_SPI_C, \b SYSCTL_PERIPH_MCBSP_A, \b SYSCTL_PERIPH_MCBSP_B,
//! \b SYSCTL_PERIPH_DMA, \b SYSCTL_PERIPH_USB_A
//!
//! \return None.
//
//*****************************************************************************
void
SysCtlPeripheralDisable(uint32_t ui32Peripheral)
{
uint16_t regIndex;
uint16_t bitIndex;
regIndex = ui32Peripheral & SYSCTL_PERIPH_REG_M;
bitIndex = (ui32Peripheral & SYSCTL_PERIPH_BIT_M) >> SYSCTL_PERIPH_BIT_S;
EALLOW;
HWREG((uint32_t)&(CpuSysRegs.PCLKCR0.all) + (2 * regIndex)) &= ~((uint32_t)1 << bitIndex);
EDIS;
}
//*****************************************************************************
//
//! Resets the device.
//!
//! This function performs a software reset of the entire device. The
//! processor and all peripherals are reset and all device registers are
//! returned to their default values (with the exception of the reset cause
//! register, which maintains its current value but has the software reset
//! bit set as well).
//!
//! \return This function does not return.
//
//*****************************************************************************
void
SysCtlReset(void)
{
//
// Write an incorrect check value to the watchdog control register
// This will cause a device reset
//
EALLOW;
// Enable the watchdog
HWREG(&(WdRegs.WDCR.all)) = 0x0028;
// Write a bad check value
HWREG(&(WdRegs.WDCR.all)) = 0xFFFF;
EDIS;
//
// The device should have reset, so this should never be reached. Just in
// case, loop forever.
//
while(1)
{
}
}
//*****************************************************************************
//
//! 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 takes 5 cycles/loop + 9.
//!
//! \return None.
//
//*****************************************************************************
#ifdef __TI_COMPILER_VERSION__
#if __TI_COMPILER_VERSION__ >= 15009000
__asm(" .def _SysCtlDelay\n"
" .sect \".TI.ramfunc\"\n"
" .global _SysCtlDelay\n"
"_SysCtlDelay:\n"
" SUB ACC,#1\n"
" BF _SysCtlDelay,GEQ\n"
" LRETR\n");
#else
__asm(" .def _SysCtlDelay\n"
" .sect \"ramfuncs\"\n"
" .global _SysCtlDelay\n"
"_SysCtlDelay:\n"
" SUB ACC,#1\n"
" BF _SysCtlDelay,GEQ\n"
" LRETR\n");
#endif
#endif
//*****************************************************************************
//
//! Gets the processor clock rate.
//!
//! This function determines the clock rate of the processor clock.
//!
//! \note Because of the many different clocking options available, this
//! function cannot determine the clock speed of the processor. This function
//! should be modified to return the actual clock speed of the processor in
//! your specific application.
//!
//! \return The processor clock rate.
//
//*****************************************************************************
uint32_t
SysCtlClockGet(uint32_t u32ClockIn)
{
if((ClkCfgRegs.CLKSRCCTL1.bit.OSCCLKSRCSEL == 0) ||
(ClkCfgRegs.CLKSRCCTL1.bit.OSCCLKSRCSEL == 2)){
//10MHz Internal Clock
u32ClockIn = 10000000;
}
//If the pll is enabled calculate its effect on the clock
// if((HWREG(SYSCTL_SYSPLLCTL) &
// (SYSCTL_SYSPLLCTL_SPLLEN | SYSCTL_SYSPLLCTL_SPLLCLKEN)) == 3)
if(ClkCfgRegs.SYSPLLCTL1.bit.PLLEN && ClkCfgRegs.SYSPLLCTL1.bit.PLLCLKEN)
{
//Calculate integer multiplier and fixed divide by 2
// ulClockIn = ulClockIn *
// (HWREG(SYSCTL_SYSPLLMULT) & SYSCTL_SYSPLLMULT_SPLLIMULT_M);
u32ClockIn = u32ClockIn * ClkCfgRegs.SYSPLLMULT.bit.IMULT;
//Calculate fractional multiplier
// switch((HWREG(SYSCTL_SYSPLLMULT) & SYSCTL_SYSPLLMULT_SPLLFMULT_M) >>
// SYSCTL_SYSPLLMULT_SPLLFMULT_S)
switch(ClkCfgRegs.SYSPLLMULT.bit.FMULT)
{
default:
case 0:
break;
case 1:
u32ClockIn += u32ClockIn / 4;
break;
case 2:
u32ClockIn += u32ClockIn / 2;
break;
case 3:
u32ClockIn += (u32ClockIn * 3) / 4;
break;
}
}
if(ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV != 0){
u32ClockIn /= (2 * ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV);
}
return u32ClockIn;
}
//*****************************************************************************
//
//! Gets the low speed peripheral clock rate.
//!
//! This function determines the clock rate of the low speed peripherals.
//!
//! \note Because of the many different clocking options available, this
//! function cannot determine the clock speed of the processor. This function
//! should be modified to return the actual clock speed of the processor in
//! your specific application.
//!
//! \return The low speed peripheral clock rate.
//
//*****************************************************************************
uint32_t
SysCtlLowSpeedClockGet(uint32_t u32ClockIn)
{
// Get the main system clock
u32ClockIn = SysCtlClockGet(u32ClockIn);
// Apply the divider to the main clock
if(ClkCfgRegs.LOSPCP.bit.LSPCLKDIV != 0){
u32ClockIn /= (2 * ClkCfgRegs.LOSPCP.bit.LSPCLKDIV);
}
return u32ClockIn;
}
//*****************************************************************************
//
//! Sets the clocking of the device.
//!
//! \param ui32Config is the required configuration of the device clocking.
//!
//! This function configures the clocking of the device. The oscillator to be
//! used, SYSPLL fractional and integer multiplier, and the system clock
//! divider are all configured with this function.
//!
//! The \e ui32Config parameter is the logical OR of four values:
//! Clock divider, Integer multiplier, Fractional multiplier, and oscillator
//! source.
//!
//! The system clock divider is chosen with using the following macro:
//! \b SYSCTL_SYSDIV(x) - "x" is an integer of value 1 or any even value
//! up to 126
//!
//! The System PLL fractional multiplier is chosen with one of the following
//! values:
//! \b SYSCTL_FMULT_0, \b SYSCTL_FMULT_1_4, \b SYSCTL_FMULT_1_2,
//! \b SYSCTL_FMULT_3_4
//!
//! The System PLL integer multiplier is chosen with using the following macro:
//! \b SYSCTL_IMULT(x) - "x" is an integer from 0 to 127
//!
//! The oscillator source is chosen with one of the following values:
//! \b SYSCTL_OSCSRC_OSC2, \b SYSCTL_OSCSRC_XTAL, \b SYSCTL_OSCSRC_OSC1
//!
//! \note 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 is prevented by the hardware.
//!
//! \return None.
//
//*****************************************************************************
void
SysCtlClockSet(uint32_t ui32Config)
{
uint32_t clock_source = (ui32Config & SYSCTL_OSCSRC_M) >> SYSCTL_OSCSRC_S;
uint32_t imult = (ui32Config & SYSCTL_IMULT_M);
uint32_t fmult = (ui32Config & SYSCTL_FMULT_M) >> SYSCTL_FMULT_S;
uint32_t divsel = (ui32Config & SYSCTL_SYSDIV_M) >> SYSCTL_SYSDIV_S;
if((clock_source == ClkCfgRegs.CLKSRCCTL1.bit.OSCCLKSRCSEL) &&
(imult == ClkCfgRegs.SYSPLLMULT.bit.IMULT) &&
(fmult == ClkCfgRegs.SYSPLLMULT.bit.FMULT) &&
(divsel == ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV))
{
//everything is set as required, so just return
return;
}
if(clock_source != ClkCfgRegs.CLKSRCCTL1.bit.OSCCLKSRCSEL)
{
//Configure Oscillator
EALLOW;
switch (clock_source)
{
case ((uint32_t)SYSCTL_OSCSRC_OSC2 >> SYSCTL_OSCSRC_S):
ClkCfgRegs.CLKSRCCTL1.bit.INTOSC2OFF=0; // Turn on INTOSC2
ClkCfgRegs.CLKSRCCTL1.bit.OSCCLKSRCSEL = 0; // Clk Src = INTOSC2
ClkCfgRegs.CLKSRCCTL1.bit.XTALOFF=1; // Turn off XTALOSC
break;
case ((uint32_t)SYSCTL_OSCSRC_XTAL >> SYSCTL_OSCSRC_S):
ClkCfgRegs.CLKSRCCTL1.bit.XTALOFF=0; // Turn on XTALOSC
ClkCfgRegs.CLKSRCCTL1.bit.OSCCLKSRCSEL = 1; // Clk Src = XTAL
break;
case ((uint32_t)SYSCTL_OSCSRC_OSC1 >> SYSCTL_OSCSRC_S):
ClkCfgRegs.CLKSRCCTL1.bit.OSCCLKSRCSEL = 2; // Clk Src = INTOSC1
ClkCfgRegs.CLKSRCCTL1.bit.XTALOFF=1; // Turn off XTALOSC
break;
}
EDIS;
}
EALLOW;
// first modify the PLL multipliers
if(imult != ClkCfgRegs.SYSPLLMULT.bit.IMULT ||
fmult != ClkCfgRegs.SYSPLLMULT.bit.FMULT)
{
// Bypass PLL and set dividers to /1
ClkCfgRegs.SYSPLLCTL1.bit.PLLCLKEN = 0;
ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV = 0;
// Program PLL multipliers
uint32_t temp_syspllmult = ClkCfgRegs.SYSPLLMULT.all;
ClkCfgRegs.SYSPLLMULT.all = ((temp_syspllmult & ~(0x37FU)) |
((fmult << 8U) | imult));
ClkCfgRegs.SYSPLLCTL1.bit.PLLEN = 1; // Enable SYSPLL
// Wait for the SYSPLL lock
while(ClkCfgRegs.SYSPLLSTS.bit.LOCKS != 1)
{
// Uncomment to service the watchdog
//WdRegs.WDKEY.bit.WDKEY = 0x0055;
//WdRegs.WDKEY.bit.WDKEY = 0x00AA;
}
// Write a multiplier again to ensure proper PLL initialization
// This will force the PLL to lock a second time
ClkCfgRegs.SYSPLLMULT.bit.IMULT = imult; // Setting integer multiplier
// Wait for the SYSPLL re-lock
while(ClkCfgRegs.SYSPLLSTS.bit.LOCKS != 1)
{
// Uncomment to service the watchdog
//WdRegs.WDKEY.bit.WDKEY = 0x0055;
//WdRegs.WDKEY.bit.WDKEY = 0x00AA;
}
}
// Set divider to produce slower output frequency to limit current increase
if(divsel != (126/2))
{
ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV = divsel + 1;
}
else
{
ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV = divsel;
}
// Enable PLLSYSCLK is fed from system PLL clock
ClkCfgRegs.SYSPLLCTL1.bit.PLLCLKEN = 1;
// Small 100 cycle delay
asm(" RPT #100 || NOP");
// Set the divider to user value
ClkCfgRegs.SYSCLKDIVSEL.bit.PLLSYSCLKDIV = divsel;
EDIS;
}
//*****************************************************************************
//
//! Sets the clocking of the device.
//!
//! \param ui32Config 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 ui32Config 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.
//!
//! 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_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,
//! \b SYSCTL_XTAL_8_19MHZ, \b SYSCTL_XTAL_10MHZ, \b SYSCTL_XTAL_12MHZ,
//! \b SYSCTL_XTAL_12_2MHZ, \b SYSCTL_XTAL_13_5MHZ, \b SYSCTL_XTAL_14_3MHZ,
//! \b SYSCTL_XTAL_16MHZ, \b SYSCTL_XTAL_16_3MHZ, \b SYSCTL_XTAL_18MHZ,
//! \b SYSCTL_XTAL_20MHZ, \b SYSCTL_XTAL_24MHZ, or \b SYSCTL_XTAL_25MHz.
//! Values below \b SYSCTL_XTAL_5MHZ 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. \b SYSCTL_OSC_EXT32 is only
//! available on 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 is 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 polls 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 delays until its timeout has occurred
//! instead of completing as soon as PLL lock is achieved.
//!
//! \return None.
//
//*****************************************************************************
void
SysCtlAuxClockSet(uint32_t ui32Config)
{
uint16_t ui16TempDivsel;
//Bypass PLL
//Ensure the PLL is out of our clock tree
EALLOW;
ClkCfgRegs.AUXPLLCTL1.bit.PLLCLKEN = 0;
EDIS;
__asm( " RPT #255 || NOP");
//Configure Oscillator
EALLOW;
switch (ui32Config & SYSCTL_OSCSRC_M)
{
default:
case SYSCTL_OSCSRC_OSC2:
ClkCfgRegs.CLKSRCCTL1.bit.INTOSC2OFF=0; // Turn on INTOSC2
ClkCfgRegs.CLKSRCCTL2.bit.AUXOSCCLKSRCSEL = 0; // Clk Src = INTOSC2
ClkCfgRegs.CLKSRCCTL1.bit.XTALOFF=1; // Turn off XTALOSC
break;
case SYSCTL_OSCSRC_XTAL:
ClkCfgRegs.CLKSRCCTL1.bit.XTALOFF=0; // Turn on XTALOSC
ClkCfgRegs.CLKSRCCTL2.bit.AUXOSCCLKSRCSEL = 1; // Clk Src = XTAL
break;
case SYSCTL_OSCSRC_OSC1:
ClkCfgRegs.CLKSRCCTL2.bit.AUXOSCCLKSRCSEL = 2; // Clk Src = INTOSC1
ClkCfgRegs.CLKSRCCTL1.bit.XTALOFF=1; // Turn off XTALOSC
break;
}
EDIS;
__asm( " RPT #255 || NOP");
//Configure PLL if enabled
if(ui32Config & SYSCTL_PLL_ENABLE)
{
EALLOW;
//modify dividers to maximum to reduce the inrush current
//set the integer fractional multipliers in one single write
ClkCfgRegs.AUXPLLMULT.all = ((ui32Config & SYSCTL_IMULT_M) >> SYSCTL_IMULT_S) |
(((ui32Config & SYSCTL_FMULT_M) >> SYSCTL_FMULT_S) << 8);
EDIS;
__asm( " RPT #255 || NOP");
//Wait for the SYSPLL lock
while(ClkCfgRegs.AUXPLLSTS.bit.LOCKS != 1)
{
// Uncomment to service the watchdog
// ServiceDog();
}
}
//Configure Dividers
//increase the freq. of operation in steps to avoid any VDD fluctuations
ui16TempDivsel = 3;
while(ClkCfgRegs.AUXCLKDIVSEL.bit.AUXPLLDIV != ((ui32Config & SYSCTL_SYSDIV_M) >> SYSCTL_SYSDIV_S))
{
EALLOW;
ClkCfgRegs.AUXCLKDIVSEL.bit.AUXPLLDIV = ui16TempDivsel;
EDIS;
ui16TempDivsel -= 1;
if(ClkCfgRegs.AUXCLKDIVSEL.bit.AUXPLLDIV != ((ui32Config & SYSCTL_SYSDIV_M) >> SYSCTL_SYSDIV_S))
{
SysCtlDelay(15);
}
}
//Enable PLLSYSCLK is fed from system PLL clock
EALLOW;
ClkCfgRegs.AUXPLLCTL1.bit.PLLCLKEN = 1;
EDIS;
}
//*****************************************************************************
//
//! Powers up the USB PLL.
//!
//! This function will enable the USB controller's PLL.
//!
//! \note Because every application is different, the user will likely have to
//! modify this function to ensure the PLL multiplier is set correctly to
//! achieve the 60 MHz required by the USB controller.
//!
//! \return None.
//
//*****************************************************************************
void
SysCtlUSBPLLEnable(void)
{
// // Turn on INTOSC2
// ClkCfgRegs.CLKSRCCTL1.bit.INTOSC2OFF=0;
// //Select INTOSC2 as USB PLL Clk In
// ClkCfgRegs.CLKSRCCTL2.bit.AUXOSCCLKSRCSEL = 0;
// // Set Aux PLL divider
// ClkCfgRegs.AUXCLKDIVSEL.bit.AUXPLLDIV = 1;
// // Set Aux PLL multiplier
// ClkCfgRegs.AUXPLLMULT.bit.IMULT = 12;
// // Set Aux PLL fractional multiplier to 0.0
// ClkCfgRegs.AUXPLLMULT.bit.FMULT = 0;
// //Enable AUXPLL
// ClkCfgRegs.AUXPLLCTL1.bit.PLLEN = 1;
//
// //Wait for the AUXPLL lock
// while(ClkCfgRegs.AUXPLLSTS.bit.LOCKS != 1)
// {
// // Uncomment to service the watchdog
// // ServiceDog();
// }
// // AUXPLLCLK is fed from the AUXPLL
// ClkCfgRegs.AUXPLLCTL1.bit.PLLCLKEN = 1;
}
//*****************************************************************************
//
//! Powers down the USB PLL.
//!
//! This function will disable the USB controller's PLL. The USB registers
//! are still accessible, but the physical layer will no longer function.
//!
//! \return None.
//
//*****************************************************************************
void
SysCtlUSBPLLDisable(void)
{
//Disable the PLL
// ClkCfgRegs.AUXPLLCTL1.bit.PLLCLKEN = 0;
}
//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************