diff options
| author | Carlos Maiolino <[email protected]> | 2025-07-10 22:55:07 +0200 |
|---|---|---|
| committer | Carlos Maiolino <[email protected]> | 2025-07-10 22:56:55 +0200 |
| commit | d98f46ce647846b0aa30b2e16a30fd4e152a1bf5 (patch) | |
| tree | 267474fcc77cf20b428f6f4c7f768ca09f4cfe0e /msp340/Timers/driverlib/MSP430FR5xx_6xx/cs.c | |
| parent | 869e68986aa8f69af6e7842260a68d1e5c6f796f (diff) | |
Add new code
Signed-off-by: Carlos Maiolino <[email protected]>
Diffstat (limited to 'msp340/Timers/driverlib/MSP430FR5xx_6xx/cs.c')
| -rwxr-xr-x | msp340/Timers/driverlib/MSP430FR5xx_6xx/cs.c | 939 |
1 files changed, 939 insertions, 0 deletions
diff --git a/msp340/Timers/driverlib/MSP430FR5xx_6xx/cs.c b/msp340/Timers/driverlib/MSP430FR5xx_6xx/cs.c new file mode 100755 index 0000000..5e49716 --- /dev/null +++ b/msp340/Timers/driverlib/MSP430FR5xx_6xx/cs.c @@ -0,0 +1,939 @@ +/* --COPYRIGHT--,BSD + * Copyright (c) 2014, Texas Instruments Incorporated + * All rights reserved. + * + * 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. + * --/COPYRIGHT--*/ +//***************************************************************************** +// +// cs.c - Driver for the cs Module. +// +//***************************************************************************** + +//***************************************************************************** +// +//! \addtogroup cs_api cs +//! @{ +// +//***************************************************************************** + +#include "inc/hw_regaccess.h" +#include "inc/hw_memmap.h" + +#if defined(__MSP430_HAS_CS__) || defined(__MSP430_HAS_SFR__) +#include "cs.h" + +#include <assert.h> + +//***************************************************************************** +// +// The following value is used by CS_getACLK, CS_getSMCLK, CS_getMCLK to +// determine the operating frequency based on the available DCO frequencies. +// +//***************************************************************************** +#define CS_DCO_FREQ_1 1000000 +#define CS_DCO_FREQ_2 2670000 +#define CS_DCO_FREQ_3 3330000 +#define CS_DCO_FREQ_4 4000000 +#define CS_DCO_FREQ_5 5330000 +#define CS_DCO_FREQ_6 6670000 +#define CS_DCO_FREQ_7 8000000 +#define CS_DCO_FREQ_8 16000000 +#define CS_DCO_FREQ_9 20000000 +#define CS_DCO_FREQ_10 24000000 + +//***************************************************************************** +// +// Internal very low power VLOCLK, low frequency oscillator with 10kHz typical +// frequency, internal low-power oscillator MODCLK with 5 MHz typical +// frequency and LFMODCLK is MODCLK divided by 128. +// +//***************************************************************************** +#define CS_VLOCLK_FREQUENCY 10000 +#define CS_MODCLK_FREQUENCY 5000000 +#define CS_LFMODCLK_FREQUENCY 39062 + +//***************************************************************************** +// +// The following value is used by CS_XT1Start, CS_bypassXT1, +// CS_XT1StartWithTimeout, CS_bypassXT1WithTimeout to properly set the XTS +// bit. This frequnecy threshold is specified in the User's Guide. +// +//***************************************************************************** +#define LFXT_FREQUENCY_THRESHOLD 50000 + +//***************************************************************************** +// +// LFXT crystal frequency. Should be set with +// CS_externalClockSourceInit if LFXT is used and user intends to invoke +// CS_getSMCLK, CS_getMCLK, CS_getACLK and +// CS_turnOnLFXT, CS_LFXTByPass, CS_turnOnLFXTWithTimeout, +// CS_LFXTByPassWithTimeout. +// +//***************************************************************************** +static uint32_t privateLFXTClockFrequency = 0; + +//***************************************************************************** +// +// The HFXT crystal frequency. Should be set with +// CS_externalClockSourceInit if HFXT is used and user intends to invoke +// CS_getSMCLK, CS_getMCLK, CS_getACLK, +// CS_turnOnLFXT, CS_LFXTByPass, CS_turnOnLFXTWithTimeout, +// CS_LFXTByPassWithTimeout. +// +//***************************************************************************** +static uint32_t privateHFXTClockFrequency = 0; + +static uint32_t privateCSASourceClockFromDCO(uint8_t clockdivider) +{ + uint32_t CLKFrequency = 0; + + if(HWREG16(CS_BASE + OFS_CSCTL1) & DCORSEL) + { + switch(HWREG16(CS_BASE + OFS_CSCTL1) & DCOFSEL_7) + { + case DCOFSEL_0: + CLKFrequency = CS_DCO_FREQ_1 / clockdivider; + break; + case DCOFSEL_1: + CLKFrequency = CS_DCO_FREQ_5 / clockdivider; + break; + case DCOFSEL_2: + CLKFrequency = CS_DCO_FREQ_6 / clockdivider; + break; + case DCOFSEL_3: + CLKFrequency = CS_DCO_FREQ_7 / clockdivider; + break; + case DCOFSEL_4: + CLKFrequency = CS_DCO_FREQ_8 / clockdivider; + break; + case DCOFSEL_5: + CLKFrequency = CS_DCO_FREQ_9 / clockdivider; + break; + case DCOFSEL_6: + case DCOFSEL_7: + CLKFrequency = CS_DCO_FREQ_10 / clockdivider; + break; + default: + CLKFrequency = 0; + break; + } + } + else + { + switch(HWREG16(CS_BASE + OFS_CSCTL1) & DCOFSEL_7) + { + case DCOFSEL_0: + CLKFrequency = CS_DCO_FREQ_1 / clockdivider; + break; + case DCOFSEL_1: + CLKFrequency = CS_DCO_FREQ_2 / clockdivider; + break; + case DCOFSEL_2: + CLKFrequency = CS_DCO_FREQ_3 / clockdivider; + break; + case DCOFSEL_3: + CLKFrequency = CS_DCO_FREQ_4 / clockdivider; + break; + case DCOFSEL_4: + CLKFrequency = CS_DCO_FREQ_5 / clockdivider; + break; + case DCOFSEL_5: + CLKFrequency = CS_DCO_FREQ_6 / clockdivider; + break; + case DCOFSEL_6: + case DCOFSEL_7: + CLKFrequency = CS_DCO_FREQ_7 / clockdivider; + break; + default: + CLKFrequency = 0; + break; + } + } + + return (CLKFrequency); +} + +static uint32_t privateCSAComputeCLKFrequency(uint16_t CLKSource, + uint16_t CLKSourceDivider) +{ + uint32_t CLKFrequency = 0; + uint8_t CLKSourceFrequencyDivider = 1; + uint8_t i = 0; + + // Determine Frequency divider + for(i = 0; i < CLKSourceDivider; i++) + { + CLKSourceFrequencyDivider *= 2; + } + + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + // Determine clock source based on CLKSource + switch(CLKSource) + { + // If LFXT is selected as clock source + case SELM__LFXTCLK: + CLKFrequency = (privateLFXTClockFrequency / + CLKSourceFrequencyDivider); + + //Check if LFXTOFFG is not set. If fault flag is set + //VLO is used as source clock + if(HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG) + { + HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG); + //Clear OFIFG fault flag + HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG; + + if(HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG) + { + CLKFrequency = CS_LFMODCLK_FREQUENCY; + } + } + break; + + case SELM__VLOCLK: + CLKFrequency = + (CS_VLOCLK_FREQUENCY / CLKSourceFrequencyDivider); + break; + + case SELM__LFMODOSC: + CLKFrequency = + (CS_LFMODCLK_FREQUENCY / CLKSourceFrequencyDivider); + + break; + + case SELM__DCOCLK: + CLKFrequency = + privateCSASourceClockFromDCO(CLKSourceFrequencyDivider); + + break; + + case SELM__MODOSC: + CLKFrequency = + (CS_MODCLK_FREQUENCY / CLKSourceFrequencyDivider); + + break; + + case SELM__HFXTCLK: + CLKFrequency = + (privateHFXTClockFrequency / CLKSourceFrequencyDivider); + + if(HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG) + { + HWREG8(CS_BASE + OFS_CSCTL5) &= ~HFXTOFFG; + //Clear OFIFG fault flag + HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG; + } + + if(HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG) + { + CLKFrequency = CS_MODCLK_FREQUENCY; + } + break; + } + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; + + return (CLKFrequency); +} + +void CS_setExternalClockSource(uint32_t LFXTCLK_frequency, + uint32_t HFXTCLK_frequency) +{ + privateLFXTClockFrequency = LFXTCLK_frequency; + privateHFXTClockFrequency = HFXTCLK_frequency; +} + +void CS_initClockSignal(uint8_t selectedClockSignal, + uint16_t clockSource, + uint16_t clockSourceDivider) +{ + //Verify User has selected a valid Frequency divider + assert( + (CS_CLOCK_DIVIDER_1 == clockSourceDivider) || + (CS_CLOCK_DIVIDER_2 == clockSourceDivider) || + (CS_CLOCK_DIVIDER_4 == clockSourceDivider) || + (CS_CLOCK_DIVIDER_8 == clockSourceDivider) || + (CS_CLOCK_DIVIDER_16 == clockSourceDivider) || + (CS_CLOCK_DIVIDER_32 == clockSourceDivider) + ); + + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + switch(selectedClockSignal) + { + case CS_ACLK: + assert( + (CS_LFXTCLK_SELECT == clockSource) || + (CS_VLOCLK_SELECT == clockSource) || + (CS_LFMODOSC_SELECT == clockSource) + ); + + clockSourceDivider = clockSourceDivider << 8; + clockSource = clockSource << 8; + + HWREG16(CS_BASE + OFS_CSCTL2) &= ~(SELA_7); + HWREG16(CS_BASE + OFS_CSCTL2) |= (clockSource); + HWREG16(CS_BASE + OFS_CSCTL3) &= ~(DIVA0 + DIVA1 + DIVA2); + HWREG16(CS_BASE + OFS_CSCTL3) |= clockSourceDivider; + break; + case CS_SMCLK: + assert( + (CS_LFXTCLK_SELECT == clockSource) || + (CS_VLOCLK_SELECT == clockSource) || + (CS_DCOCLK_SELECT == clockSource) || + (CS_HFXTCLK_SELECT == clockSource) || + (CS_LFMODOSC_SELECT == clockSource)|| + (CS_MODOSC_SELECT == clockSource) + ); + + clockSource = clockSource << 4; + clockSourceDivider = clockSourceDivider << 4; + + HWREG16(CS_BASE + OFS_CSCTL2) &= ~(SELS_7); + HWREG16(CS_BASE + OFS_CSCTL2) |= clockSource; + HWREG16(CS_BASE + OFS_CSCTL3) &= ~(DIVS0 + DIVS1 + DIVS2); + HWREG16(CS_BASE + OFS_CSCTL3) |= clockSourceDivider; + break; + case CS_MCLK: + assert( + (CS_LFXTCLK_SELECT == clockSource) || + (CS_VLOCLK_SELECT == clockSource) || + (CS_DCOCLK_SELECT == clockSource) || + (CS_HFXTCLK_SELECT == clockSource) || + (CS_LFMODOSC_SELECT == clockSource)|| + (CS_MODOSC_SELECT == clockSource) + ); + + HWREG16(CS_BASE + OFS_CSCTL2) &= ~(SELM_7); + HWREG16(CS_BASE + OFS_CSCTL2) |= clockSource; + HWREG16(CS_BASE + OFS_CSCTL3) &= ~(DIVM0 + DIVM1 + DIVM2); + HWREG16(CS_BASE + OFS_CSCTL3) |= clockSourceDivider; + break; + } + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; +} + +void CS_turnOnLFXT(uint16_t lfxtdrive) +{ + assert(privateLFXTClockFrequency != 0); + + assert((lfxtdrive == CS_LFXT_DRIVE_0) || + (lfxtdrive == CS_LFXT_DRIVE_1) || + (lfxtdrive == CS_LFXT_DRIVE_2) || + (lfxtdrive == CS_LFXT_DRIVE_3)); + + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + //Switch ON LFXT oscillator + HWREG16(CS_BASE + OFS_CSCTL4) &= ~LFXTOFF; + + //Highest drive setting for LFXTstartup + HWREG16(CS_BASE + OFS_CSCTL4_L) |= LFXTDRIVE1_L + LFXTDRIVE0_L; + + HWREG16(CS_BASE + OFS_CSCTL4) &= ~LFXTBYPASS; + + //Wait for Crystal to stabilize + while(HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG) + { + //Clear OSC flaut Flags fault flags + HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG); + + //Clear OFIFG fault flag + HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG; + } + + //set requested Drive mode + HWREG16(CS_BASE + OFS_CSCTL4) = (HWREG16(CS_BASE + OFS_CSCTL4) & + ~(LFXTDRIVE_3) + ) | + (lfxtdrive); + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; +} + +void CS_bypassLFXT(void) +{ + //Verify user has set frequency of LFXT with SetExternalClockSource + assert(privateLFXTClockFrequency != 0); + + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + assert(privateLFXTClockFrequency < LFXT_FREQUENCY_THRESHOLD); + + // Set LFXT in LF mode Switch off LFXT oscillator and enable BYPASS mode + HWREG16(CS_BASE + OFS_CSCTL4) |= (LFXTBYPASS + LFXTOFF); + + //Wait until LFXT stabilizes + while(HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG) + { + //Clear OSC flaut Flags fault flags + HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG); + + // Clear the global fault flag. In case the LFXT caused the global fault + // flag to get set this will clear the global error condition. If any + // error condition persists, global flag will get again. + HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG; + } + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; +} + +bool CS_turnOnLFXTWithTimeout(uint16_t lfxtdrive, + uint32_t timeout) +{ + assert(privateLFXTClockFrequency != 0); + + assert((lfxtdrive == CS_LFXT_DRIVE_0) || + (lfxtdrive == CS_LFXT_DRIVE_1) || + (lfxtdrive == CS_LFXT_DRIVE_2) || + (lfxtdrive == CS_LFXT_DRIVE_3)); + + assert(timeout > 0); + + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + //Switch ON LFXT oscillator + HWREG16(CS_BASE + OFS_CSCTL4) &= ~LFXTOFF; + + //Highest drive setting for LFXTstartup + HWREG16(CS_BASE + OFS_CSCTL4_L) |= LFXTDRIVE1_L + LFXTDRIVE0_L; + + HWREG16(CS_BASE + OFS_CSCTL4) &= ~LFXTBYPASS; + + while((HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG) && --timeout) + { + //Clear OSC fault Flags fault flags + HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG); + + // Clear the global fault flag. In case the LFXT caused the global fault + // flag to get set this will clear the global error condition. If any + // error condition persists, global flag will get again. + HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG; + } + + if(timeout) + { + //set requested Drive mode + HWREG16(CS_BASE + OFS_CSCTL4) = (HWREG16(CS_BASE + OFS_CSCTL4) & + ~(LFXTDRIVE_3) + ) | + (lfxtdrive); + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; + return (STATUS_SUCCESS); + } + else + { + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; + return (STATUS_FAIL); + } +} + +bool CS_bypassLFXTWithTimeout(uint32_t timeout) +{ + assert(privateLFXTClockFrequency != 0); + + assert(privateLFXTClockFrequency < LFXT_FREQUENCY_THRESHOLD); + + assert(timeout > 0); + + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + // Set LFXT in LF mode Switch off LFXT oscillator and enable BYPASS mode + HWREG16(CS_BASE + OFS_CSCTL4) |= (LFXTBYPASS + LFXTOFF); + + while((HWREG8(CS_BASE + OFS_CSCTL5) & LFXTOFFG) && --timeout) + { + //Clear OSC fault Flags fault flags + HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG); + + // Clear the global fault flag. In case the LFXT caused the global fault + // flag to get set this will clear the global error condition. If any + // error condition persists, global flag will get again. + HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG; + } + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; + + if(timeout) + { + return (STATUS_SUCCESS); + } + else + { + return (STATUS_FAIL); + } +} + +void CS_turnOffLFXT(void) +{ + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + //Switch off LFXT oscillator + HWREG16(CS_BASE + OFS_CSCTL4) |= LFXTOFF; + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; +} + +void CS_turnOnHFXT(uint16_t hfxtdrive) +{ + assert(privateHFXTClockFrequency != 0); + + assert((hfxtdrive == CS_HFXT_DRIVE_4MHZ_8MHZ) || + (hfxtdrive == CS_HFXT_DRIVE_8MHZ_16MHZ) || + (hfxtdrive == CS_HFXT_DRIVE_16MHZ_24MHZ)|| + (hfxtdrive == CS_HFXT_DRIVE_24MHZ_32MHZ)); + + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + // Switch ON HFXT oscillator + HWREG16(CS_BASE + OFS_CSCTL4) &= ~HFXTOFF; + + //Disable HFXTBYPASS mode and Switch on HFXT oscillator + HWREG16(CS_BASE + OFS_CSCTL4) &= ~HFXTBYPASS; + + //If HFFrequency is 16MHz or above + if(privateHFXTClockFrequency > 16000000) + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_3; + } + //If HFFrequency is between 8MHz and 16MHz + else if(privateHFXTClockFrequency > 8000000) + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_2; + } + //If HFFrequency is between 0MHz and 4MHz + else if(privateHFXTClockFrequency < 4000000) + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_0; + } + //If HFFrequency is between 4MHz and 8MHz + else + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_1; + } + + while(HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG) + { + //Clear OSC flaut Flags + HWREG8(CS_BASE + OFS_CSCTL5) &= ~(HFXTOFFG); + + //Clear OFIFG fault flag + HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG; + } + + HWREG16(CS_BASE + OFS_CSCTL4) = (HWREG16(CS_BASE + OFS_CSCTL4) & + ~(CS_HFXT_DRIVE_24MHZ_32MHZ) + ) | + (hfxtdrive); + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; +} + +void CS_bypassHFXT(void) +{ + //Verify user has initialized value of HFXTClock + assert(privateHFXTClockFrequency != 0); + + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + //Switch off HFXT oscillator and set it to BYPASS mode + HWREG16(CS_BASE + OFS_CSCTL4) |= (HFXTBYPASS + HFXTOFF); + + //Set correct HFFREQ bit for FR58xx/FR59xx devices + + //If HFFrequency is 16MHz or above + if(privateHFXTClockFrequency > 16000000) + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_3; + } + //If HFFrequency is between 8MHz and 16MHz + else if(privateHFXTClockFrequency > 8000000) + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_2; + } + //If HFFrequency is between 0MHz and 4MHz + else if(privateHFXTClockFrequency < 4000000) + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_0; + } + //If HFFrequency is between 4MHz and 8MHz + else + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_1; + } + + while(HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG) + { + //Clear OSC fault Flags + HWREG8(CS_BASE + OFS_CSCTL5) &= ~(HFXTOFFG); + + //Clear OFIFG fault flag + HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG; + } + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; +} + +bool CS_turnOnHFXTWithTimeout(uint16_t hfxtdrive, + uint32_t timeout) +{ + //Verify user has initialized value of HFXTClock + assert(privateHFXTClockFrequency != 0); + + assert(timeout > 0); + + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + //Switch on HFXT oscillator + HWREG16(CS_BASE + OFS_CSCTL4) &= ~HFXTOFF; + + // Disable HFXTBYPASS mode + HWREG16(CS_BASE + OFS_CSCTL4) &= ~HFXTBYPASS; + + //Set correct HFFREQ bit for FR58xx/FR59xx devices based + //on HFXTClockFrequency + + //If HFFrequency is 16MHz or above + if(privateHFXTClockFrequency > 16000000) + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_3; + } + //If HFFrequency is between 8MHz and 16MHz + else if(privateHFXTClockFrequency > 8000000) + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_2; + } + //If HFFrequency is between 0MHz and 4MHz + else if(privateHFXTClockFrequency < 4000000) + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_0; + } + //If HFFrequency is between 4MHz and 8MHz + else + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_1; + } + + while((HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG) && --timeout) + { + //Clear OSC fault Flags fault flags + HWREG8(CS_BASE + OFS_CSCTL5) &= ~(HFXTOFFG); + + // Clear the global fault flag. In case the LFXT caused the global fault + // flag to get set this will clear the global error condition. If any + // error condition persists, global flag will get again. + HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG; + } + + if(timeout) + { + //Set drive strength for HFXT + HWREG16(CS_BASE + OFS_CSCTL4) = (HWREG16(CS_BASE + OFS_CSCTL4) & + ~(CS_HFXT_DRIVE_24MHZ_32MHZ) + ) | + (hfxtdrive); + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; + return (STATUS_SUCCESS); + } + else + { + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; + return (STATUS_FAIL); + } +} + +bool CS_bypassHFXTWithTimeout(uint32_t timeout) +{ + //Verify user has initialized value of HFXTClock + assert(privateHFXTClockFrequency != 0); + + assert(timeout > 0); + + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + //If HFFrequency is 16MHz or above + if(privateHFXTClockFrequency > 16000000) + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_3; + } + //If HFFrequency is between 8MHz and 16MHz + else if(privateHFXTClockFrequency > 8000000) + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_2; + } + //If HFFrequency is between 0MHz and 4MHz + else if(privateHFXTClockFrequency < 4000000) + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_0; + } + //If HFFrequency is between 4MHz and 8MHz + else + { + HWREG16(CS_BASE + OFS_CSCTL4) = HFFREQ_1; + } + + //Switch off HFXT oscillator and enable BYPASS mode + HWREG16(CS_BASE + OFS_CSCTL4) |= (HFXTBYPASS + HFXTOFF); + + while((HWREG8(CS_BASE + OFS_CSCTL5) & HFXTOFFG) && --timeout) + { + //Clear OSC fault Flags fault flags + HWREG8(CS_BASE + OFS_CSCTL5) &= ~(HFXTOFFG); + + // Clear the global fault flag. In case the LFXT caused the global fault + // flag to get set this will clear the global error condition. If any + // error condition persists, global flag will get again. + HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG; + } + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; + + if(timeout) + { + return (STATUS_SUCCESS); + } + else + { + return (STATUS_FAIL); + } +} + +void CS_turnOffHFXT(void) +{ + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + //Switch off HFXT oscillator + HWREG16(CS_BASE + OFS_CSCTL4) |= HFXTOFF; + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; +} + +void CS_enableClockRequest(uint8_t selectClock) +{ + assert( + (CS_ACLK == selectClock)|| + (CS_SMCLK == selectClock)|| + (CS_MCLK == selectClock)|| + (CS_MODOSC == selectClock)); + + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + HWREG8(CS_BASE + OFS_CSCTL6) |= selectClock; + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; +} + +void CS_disableClockRequest(uint8_t selectClock) +{ + assert( + (CS_ACLK == selectClock)|| + (CS_SMCLK == selectClock)|| + (CS_MCLK == selectClock)|| + (CS_MODOSC == selectClock)); + + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + HWREG8(CS_BASE + OFS_CSCTL6) &= ~selectClock; + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; +} + +uint8_t CS_getFaultFlagStatus(uint8_t mask) +{ + assert( + (CS_HFXTOFFG == mask)|| + (CS_LFXTOFFG == mask) + ); + return (HWREG8(CS_BASE + OFS_CSCTL5) & mask); +} + +void CS_clearFaultFlag(uint8_t mask) +{ + assert( + (CS_HFXTOFFG == mask)|| + (CS_LFXTOFFG == mask) + ); + + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + HWREG8(CS_BASE + OFS_CSCTL5) &= ~mask; + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; +} + +uint32_t CS_getACLK(void) +{ + //Find ACLK source + uint16_t ACLKSource = (HWREG16(CS_BASE + OFS_CSCTL2) & SELA_7); + ACLKSource = ACLKSource >> 8; + + //Find ACLK frequency divider + uint16_t ACLKSourceDivider = HWREG16(CS_BASE + OFS_CSCTL3) & SELA_7; + ACLKSourceDivider = ACLKSourceDivider >> 8; + + return (privateCSAComputeCLKFrequency( + ACLKSource, + ACLKSourceDivider)); +} + +uint32_t CS_getSMCLK(void) +{ + //Find SMCLK source + uint16_t SMCLKSource = HWREG8(CS_BASE + OFS_CSCTL2) & SELS_7; + + SMCLKSource = SMCLKSource >> 4; + + //Find SMCLK frequency divider + uint16_t SMCLKSourceDivider = HWREG16(CS_BASE + OFS_CSCTL3) & SELS_7; + SMCLKSourceDivider = SMCLKSourceDivider >> 4; + + return (privateCSAComputeCLKFrequency( + SMCLKSource, + SMCLKSourceDivider) + ); +} + +uint32_t CS_getMCLK(void) +{ + //Find MCLK source + uint16_t MCLKSource = (HWREG16(CS_BASE + OFS_CSCTL2) & SELM_7); + //Find MCLK frequency divider + uint16_t MCLKSourceDivider = HWREG16(CS_BASE + OFS_CSCTL3) & SELM_7; + + return (privateCSAComputeCLKFrequency( + MCLKSource, + MCLKSourceDivider) + ); +} + +void CS_turnOffVLO(void) +{ + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + HWREG16(CS_BASE + OFS_CSCTL4) |= VLOOFF; + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; +} + +uint16_t CS_clearAllOscFlagsWithTimeout(uint32_t timeout) +{ + assert(timeout > 0); + + // Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + do + { + // Clear all osc fault flags + HWREG8(CS_BASE + OFS_CSCTL5) &= ~(LFXTOFFG + HFXTOFFG); + + // Clear the global osc fault flag. + HWREG8(SFR_BASE + OFS_SFRIFG1) &= ~OFIFG; + + // Check LFXT fault flags + } + while((HWREG8(SFR_BASE + OFS_SFRIFG1) & OFIFG) && --timeout); + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; + + return (HWREG8(CS_BASE + OFS_CSCTL5) & (LFXTOFFG + HFXTOFFG)); +} + +void CS_setDCOFreq(uint16_t dcorsel, + uint16_t dcofsel) +{ + assert( + (dcofsel == CS_DCOFSEL_0)|| + (dcofsel == CS_DCOFSEL_1)|| + (dcofsel == CS_DCOFSEL_2)|| + (dcofsel == CS_DCOFSEL_3)|| + (dcofsel == CS_DCOFSEL_4)|| + (dcofsel == CS_DCOFSEL_5)|| + (dcofsel == CS_DCOFSEL_6) + ); + + //Verify user has selected a valid DCO Frequency Range option + assert( + (dcorsel == CS_DCORSEL_0)|| + (dcorsel == CS_DCORSEL_1)); + + //Unlock CS control register + HWREG16(CS_BASE + OFS_CSCTL0) = CSKEY; + + // Set user's frequency selection for DCO + HWREG16(CS_BASE + OFS_CSCTL1) = (dcorsel + dcofsel); + + // Lock CS control register + HWREG8(CS_BASE + OFS_CSCTL0_H) = 0x00; +} + +#endif +//***************************************************************************** +// +//! Close the doxygen group for cs_api +//! @} +// +//***************************************************************************** |
