This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Initialization order

Other Parts Discussed in Thread: MSP430FR5969

I ran into an unexpected issue with the MSP430fr5969. Please bear with me if this is "common knowledge". 

I'm doing a very simple test program that just uses PWM to control LED brightness. I took the example source, modified it to suit my application and it didn't work. After perusing the original and the modified code side by side I finally spotted the difference. I had clock initialized before ports. And it wouldn't work. After I reverse clock init after ports, it works as expected. 

Why is that?

init is called from main immediately after watchdog and LPM5 are switched off.  

void init(void){

    //Set DCO frequency to 16 MHz
    CS_setDCOFreq(CS_DCORSEL_1,CS_DCOFSEL_4);
    //Set SMCLK = DCO with frequency divider of 32 = 500kHz
    CS_initClockSignal(CS_SMCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_32);
    //Set MCLK = DCO with frequency divider of 1
    CS_initClockSignal(CS_MCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_1);

    //P1.4 as PWM output
    GPIO_setAsPeripheralModuleFunctionOutputPin(
        GPIO_PORT_P1,
        GPIO_PIN4,
        GPIO_PRIMARY_MODULE_FUNCTION
        );
    //P2.6 as PWM output
    GPIO_setAsPeripheralModuleFunctionOutputPin(
        GPIO_PORT_P2,
        GPIO_PIN6,
        GPIO_PRIMARY_MODULE_FUNCTION
        );

  • I do not know the reason either. But:

    Olli Mannisto said:
    init is called from main immediately after watchdog and LPM5 are switched off

    May be, just may be, Vcc is not high enough immediately for 16 MHz operation. And setting up the port pins first added just enough delay, in your particular case, for the CPU to operate without crash. 

  • Hmm.  Now that was an interesting idea. I was playing around with this a bit and yes the processor (MSP430FR5969) does indeed crash. I cannot see anything too obvious about it however. I checked with oscilloscope and there's no significant voltage dip present on the VCC when you start the program. Also on the debugger it seems to croak just like that without any obvious reason. If I reduce the clockspeed to 8MHz it works just fine. 16MHz or above = DOA. 

    Going after the fine print a bit more, it seems 16MHz is pushing things. 1st I have to add an FRAM waitstate. No joy, still crash. 2nd, there's errata about 16MHz DCO clock with workaround code. Added that. No joy, still crash. 3rd, there's errata about setting SMCLK higher than MCLK causes a crash. Changed clock inits around. No joy, still crash.

    I'm frankly out of ammunition here. Cranking FRAM wait states to max 7 didn't help either. If I set MCLK divider to 2, it'll work but it's not that helpful to set DCO to 16MHz and then halve that.. 

  • After some trial and error I stumbled upon a "solution". If I change the master clock to 16MHz outside the init function it will work. A little bit. But it's highly unstable. Add more than 0xE cycles of delay in front of it and it will die again. The code here works but if you change that delay to 0xF it will start crashing again. 

    Perhaps this should be reported.

    #include "driverlib.h"
    
    #define TIMER_PERIOD  2
    #define DUTY_CYCLE  1
    
    void init(void);
    
    void main(void)
    {
        //Stop WDT
        WDT_A_hold(WDT_A_BASE);
    
    
        /*
         * Disable the GPIO power-on default high-impedance mode to activate
         * previously configured port settings
         */
    
    
        init();
        __delay_cycles(0xE);
        CS_initClockSignal(CS_MCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_1);
        //Enter LPM0
        __bis_SR_register(LPM0_bits);
    
        //For debugger
        __no_operation();
    
    }
    
    void init(void){
    	FRAMCtl_configureWaitStateControl(1);
        //Set DCO frequency to 1 MHz
        CS_setDCOFreq(CS_DCORSEL_1,CS_DCOFSEL_0);
        __delay_cycles(0xFF);
        CS_initClockSignal(CS_MCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_2);
        //Set SMCLK = DCO with frequency divider of 32 = 500kHz
        CS_initClockSignal(CS_SMCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_32);
    
    	uint16_t tempCSCTL3 = 0;
    	CSCTL0_H = CSKEY_H; // Unlock CS registers
    	// Assuming SMCLK and MCLK are sourced from DCO
    	// Store CSCTL3 settings to recover later
    	tempCSCTL3 = CSCTL3;
    	/* Keep overshoot transient within specification by setting clk sources
    	to divide by 4*/
    	// Clear the DIVS & DIVM masks (~0x77)and set both fields to 4 divider
    	CSCTL3 = CSCTL3 & (~(0x77)) | DIVS__4 | DIVM__4;
    	CSCTL1 = DCOFSEL_4 | DCORSEL; // Set DCO to 16MHz
    	/* Delay by ~10us to let DCO settle. 60 cycles = 20 cycles buffer +
    	(10us / (1/4MHz))*/
    	__delay_cycles(0x60);
    	CSCTL3 = tempCSCTL3; // Set all dividers
    	CSCTL0_H = 0; // Lock CS registers
    
        //P1.4 as PWM output
        GPIO_setAsPeripheralModuleFunctionOutputPin(
            GPIO_PORT_P1,
            GPIO_PIN4,
            GPIO_PRIMARY_MODULE_FUNCTION
            );
        //P2.6 as PWM output
        GPIO_setAsPeripheralModuleFunctionOutputPin(
            GPIO_PORT_P2,
            GPIO_PIN6,
            GPIO_PRIMARY_MODULE_FUNCTION
            );
        PMM_unlockLPM5();
    
        //Generate PWM - Timer runs in Up mode
        Timer_B_outputPWMParam param = {0};
        param.clockSource = TIMER_B_CLOCKSOURCE_SMCLK;
        //PWM = 25kHz
        param.clockSourceDivider = TIMER_B_CLOCKSOURCE_DIVIDER_32;
        param.timerPeriod = TIMER_PERIOD;
        param.compareRegister = TIMER_B_CAPTURECOMPARE_REGISTER_1;
        param.compareOutputMode = TIMER_B_OUTPUTMODE_RESET_SET;
        param.dutyCycle = DUTY_CYCLE;
        Timer_B_outputPWM(TIMER_B0_BASE, &param);
    

**Attention** This is a public forum