SLAAEN0 September 2024 MSPM0L1227 , MSPM0L1228 , MSPM0L1228-Q1 , MSPM0L2227 , MSPM0L2228 , MSPM0L2228-Q1
This example exhibits a problem existing in water metering where LFXT is disabled due to the humidity. The LFXT is automatically disabled and transitions to use LFOSC to keep running the low-frequency clock at 32kHz. Many users have issues transitioning back to LFXT when the LFXTGOOD bit is true. This example illustrates how to transition back to LFXT.
The Code Composer Studio provides the clock tree options allowing configuration of the desired clock path. Set LFXT as the source for LFCLK and make sure both the LFCLK start-up monitor and LFCLK monitor are enabled. This monitors the failure of LFXT to transition to LFOSC. Set the clock output to the desire pin to measure the frequency to make sure that the clock is working properly. Ground LFX_Out to disable LFXT, this action toggles the LED PA 16 to indicate that LFXT is failed and is using LFOSC. LFOSC cannot auto transition back to LFXT; therefore, the process of setting the key to enable the STARTLFXT bit to true then takes us to the IRQHandler to set the key to enable the SETUSELFXT bit to true and turn on the clock monitor again. There the processes allows a transition from LFOSC back to LFXT again when LFXT is cleared and good to use again.
#include "ti_msp_dl_config.h"
bool clockFailed = false;
static const DL_SYSCTL_LFCLKConfig gLFCLKConfig = {
.lowCap = true,
.monitor = true,
.xt1Drive = DL_SYSCTL_LFXT_DRIVE_STRENGTH_HIGHEST,
};
int main(void)
{
SYSCFG_DL_init();
SYSCTL->SOCLOCK.LFCLKCFG |= SYSCTL_LFCLKCFG_MONITOR_ENABLE; /*enable LFCLK monitor*/
delay_cycles(32000);
DL_SYSCTL_enableSleepOnExit();
NVIC_EnableIRQ(SYSCTL_INT_IRQn);
while (1) {
if(clockFailed == 1){ //it wont hit this line of the code unless you pause the program
SYSCTL->SOCLOCK.LFXTCTL = (SYSCTL_LFXTCTL_KEY_VALUE | SYSCTL_LFXTCTL_STARTLFXT_TRUE); //this starts the STARTLFXT bit
delay_cycles(32000);
clockFailed = false;
}
}
}
void NMI_Handler(void)
{
switch (DL_SYSCTL_getPendingNonMaskableInterrupt()){
case SYSCTL_NMIIIDX_STAT_LFCLKFAIL: /*toggles LED as LFXT failed*/
DL_GPIO_togglePins(GPIO_LEDS_PORT, GPIO_LEDS_User_LED_2_PIN | GPIO_LEDS_USER_LED_1_PIN); /*toggle LED PA16*/
DL_SYSCTL_enableInterrupt(0x10); //enable the bit in the IMASK of LFXTGOOD
clockFailed = true;
break;
default:
break;
}
}
void GROUP0_IRQHandler(void){
volatile uint32_t PendingInterrupt = SYSCTL->SOCLOCK.IIDX;
switch(PendingInterrupt){
case 5:
DL_GPIO_togglePins(GPIO_LEDS_PORT, GPIO_LEDS_User_LED_2_PIN | GPIO_LEDS_USER_LED_1_PIN);
clockFailed = false;
SYSCTL->SOCLOCK.LFXTCTL = (SYSCTL_LFXTCTL_KEY_VALUE | SYSCTL_LFXTCTL_SETUSELFXT_TRUE); //this write the key and set it to use LFXT
SYSCTL->SOCLOCK.LFCLKCFG = SYSCTL->SOCLOCK.LFCLKCFG | SYSCTL_LFCLKCFG_MONITOR_MASK; //this turns on the clock monitor
break;
}
}