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.

Garbled data on USB

Other Parts Discussed in Thread: MSP430FR5969, MSP-EXP430FR5969

Hello chaps.

I am facing a strange bug/problem with an MSP430FR5969.

I am using the MSP-EXP430FR5969 Launchpad.

The code I am using is a modified "Out Of The Box Demo". At the beginning it just prints some strings via the UART <-> USB bridge, a menu of sorts.

Here is the main()

int main(void) {
	mode = '0';
//	int i;
	unsigned int k;

    // Check if a wakeup from LPMx.5
    if (SYSRSTIV == SYSRSTIV_LPM5WU) {
    	// Button S2 pressed
        if (P1IFG & BIT1) {
        	// Clear P1.1 interrupt flag
        	GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN0);

        	// Exit FRAM Log Mode
        	mode = '0';

        	// Light up LED1 to indicate Exit from FRAM mode
        	Init_GPIO();
        	GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN6);
        	__delay_cycles(600000);
        }
        else
        {
        	// Continue FRAM data logging
            mode = '0';
            //bchris Init_RTC();
            Init_GPIO();
            //framLog();
        }
    }
    else
    {
    	Init_GPIO();
    	// Toggle LED1 and LED2 to indicate OutOfBox Demo start
    	int i;
    	for (i=10;i>0;i--)
    	{
            GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
            GPIO_toggleOutputOnPin(GPIO_PORT_P4, GPIO_PIN6);
            __delay_cycles(200000);
    	}
    }


    // Board initializations
    Init_GPIO();
//    Init_Clock();
    Init_ClockFast();
    Init_UART();

    // SEEPROM reset
    atTWIReset();

    // Main Loop
    while (1) {
//    	// Acknowledge PC GUI's ping request
//        if (pingHost)
//            sendAckToPC();

        switch (mode) {
        	case '0':
        		str = "\n *** AVAILABLE COMMANDS ***\n\0";
        		transmitString(str, strlen(str));

        		str = "\n 0: THIS MENU \n\0";
        		transmitString(str, strlen(str));

        		str = "\n 1: Z Test :) \n\0";
        		transmitString(str, strlen(str));

        		str = "\n 2: ORIGINAL SEEPROM HEX CONTENTS DUMP \n\0";
        		transmitString(str, strlen(str));

        		str = "\n 3: COPY ORIGINAL SEEPROM TO BACKUP \n\0";
        		transmitString(str, strlen(str));

        		str = "\n 4: COMPARE ORIGINAL TO BACKUP \n\0";
        		transmitString(str, strlen(str));

        		str = "\n\n AWAITING...\n\0";
        		transmitString(str, strlen(str));

        		__bis_SR_register(LPM3_bits | GIE);		// Sleep. Waiting for command
        		__no_operation();
        		break;
        	case '1':
                // Configure Timer
                TIMER_A_startUpMode(TIMER_A0_BASE,
                                    //TIMER_A_CLOCKSOURCE_ACLK,
                					TIMER_A_CLOCKSOURCE_SMCLK,
                                    TIMER_A_CLOCKSOURCE_DIVIDER_1,
                                    13,
                                    TIMER_A_TAIE_INTERRUPT_DISABLE,
                                    TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE,
                                    TIMER_A_DO_CLEAR);

                //__bis_SR_register(LPM3_bits | GIE);       // Enter LPM3. Delay for Ref to settle.

                // Change timer delay to 1/8 second
                TIMER_A_setCompareValue(TIMER_A0_BASE,
                                        TIMER_A_CAPTURECOMPARE_REGISTER_0,
                                        0x1000
                                        );

                __bis_SR_register(LPM3_bits | GIE);   // Enter LPM3, wait for ~1/8 sec timer


                // Light up LED1 for test
//            	Init_GPIO();
//            	GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN6);
//            	__delay_cycles(600000);
//            	GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN6);


//                __bis_SR_register(LPM3_bits | GIE);
//                __bic_SR_register(GIE);


        		// Select UART TXD on P2.0
        		GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN0, GPIO_SECONDARY_MODULE_FUNCTION);

        		//bchris
        		//EUSCI_A_UART_transmitData(EUSCI_A0_BASE, 0x46);

        		//EUSCI_A_UART_transmitData(EUSCI_A0_BASE, ADC12MEM0_H);             	// Send higher byte of temperature data
        		//EUSCI_A_UART_transmitData(EUSCI_A0_BASE, ADC12MEM0_L);             	// Send lower byte of temperature data

        		//bchris
        		EUSCI_A_UART_transmitData(EUSCI_A0_BASE, 0x5A);
        		//bchris_counter++;

        		GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0);

                while(EUSCI_A_UART_queryStatusFlags(EUSCI_A0_BASE, EUSCI_A_UART_BUSY));
                __no_operation();

                TIMER_A_stop(TIMER_A0_BASE);

                //Init_GPIO();
                GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
                break;
            case '2':
            	// Original SEEPROM dump
            	// for saving it to file.
            	bytesRead = 0;
            	for (k = 0; k < 256; k++) {
            		// Until original SEEPROM soldered to board
            		// work with the backup
//            		bytesRead = bytesRead + eepromReadSeq(SOURCE_EEPROM, k*32, testBuffer, 32);
            		bytesRead = bytesRead + eepromReadSeq(BACKUP_EEPROM, k*32, testBuffer, 32);
            		transmitData(testBuffer, 32);
            	}

            	if (bytesRead != 8192) {
            		str = "\n*** COULD NOT READ ALL SEEPROM CONTENTS ***\n\0";
            		transmitString(str, strlen(str));
            	}
            	mode = '0';
                break;
        	case '3':
            	str = "\nSTARTING MEMORY COPY...\n\0";
            	transmitString(str, strlen(str));

            	eepromWriteByte(BACKUP_EEPROM, 0x0099, 0x8C);
            	testVar1 = eepromReadByte(BACKUP_EEPROM, 0x0099);

            	eepromWriteByte(BACKUP_EEPROM, 0x0200, 0x9C);
            	testVar1 = eepromReadByte(BACKUP_EEPROM, 0x0200);

            	eepromWriteByte(BACKUP_EEPROM, 0x0150, 0xAC);
            	testVar1 = eepromReadByte(BACKUP_EEPROM, 0x0150);

            	for (k=0; k < 32; k++) {
            		testBytes[k] = k;
            	}

            	testVar2 = eepromWritePage(BACKUP_EEPROM, 0x0100, testBytes, 32);

            	mode = '0';							// do nothing else
                break;
            case '6':
            	str = "\nSTARTING PWM...\n\0";
            	transmitString(str, strlen(str));
            	PWMStart();
            	mode = '0';
            	//bchris sendCalibrationConstants();
            	//bchris sendTimeStamp();
                //transmitFRAMData();
                break;
            case '7':
            	str = "\nSTOPING PWM...\n\0";
            	transmitString(str, strlen(str));
            	PWMStop();
            	mode = '0';
            	//bchris sendCalibrationConstants();
            	//bchris sendTimeStamp();
                //transmitFRAMData();
                break;
        }

//        __bis_SR_register(LPM3_bits | GIE);       // Enter LPM3 and wait for PC commands
//        __no_operation();
    }
}

The clock init.

void Init_ClockFast() {
    // Set DCO frequency to 16 MHz
    CS_setDCOFreq(CS_DCORSEL_1, CS_DCOFSEL_4);
    //Set external clock frequency to 32.768 KHz
    CS_setExternalClockSource(32768, 0);
    //Set ACLK=LFXT
    CS_clockSignalInit(CS_ACLK, CS_LFXTCLK_SELECT, CS_CLOCK_DIVIDER_16);
    // Set SMCLK = DCO with frequency divider of 1
    CS_clockSignalInit(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_16);		// SMCLK = 1MHz
    // Set MCLK = DCO with frequency divider of 1
    CS_clockSignalInit(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_2);
    //Start XT1 with no time out
    CS_LFXTStart(CS_LFXTDRIVE_0);
}

the UART init

void Init_UART() {
	// Configure UART 9600 baud
	// http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html
    if ( STATUS_FAIL == EUSCI_A_UART_initAdvance(EUSCI_A0_BASE,
                                                 EUSCI_A_UART_CLOCKSOURCE_SMCLK,
                                                 6,							// clockPrescalar
                                                 8,							// firstModReg
                                                 17,						// secondModReg
                                                 EUSCI_A_UART_NO_PARITY,
                                                 EUSCI_A_UART_LSB_FIRST,
                                                 EUSCI_A_UART_ONE_STOP_BIT,
                                                 EUSCI_A_UART_MODE,
                                                 //EUSCI_A_UART_AUTOMATIC_BAUDRATE_DETECTION_MODE,
                                                 1 ))						// overSampling
        return;


    EUSCI_A_UART_enable(EUSCI_A0_BASE);

    EUSCI_A_UART_clearInterruptFlag(EUSCI_A0_BASE,
                                    EUSCI_A_UART_RECEIVE_INTERRUPT);

    // Enable USCI_A0 RX interrupt
    EUSCI_A_UART_enableInterrupt(EUSCI_A0_BASE,
                                 EUSCI_A_UART_RECEIVE_INTERRUPT); // Enable interrupt

    // Enable globale interrupt
    __enable_interrupt();
}

And my transmitString() function

void transmitString(char * str, unsigned int len) {
	// Select UART TXD on P2.0
    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN0, GPIO_SECONDARY_MODULE_FUNCTION);

    unsigned int i = 0;
    for (i = 0; i < len; i++) {
    	EUSCI_A_UART_transmitData(EUSCI_A0_BASE, str[i]);
    	while(EUSCI_A_UART_queryStatusFlags(EUSCI_A0_BASE, EUSCI_A_UART_BUSY));		// Wait for transmition to finish
    }
    GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0);
    GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0);
}

Everything else is either cut out or left as it was on the original TI code, which is why I left it out.
If you want, I 'll be more than happy to paste it as well.

Now, with the above strings in the case loop, the output (cat /dev/ttyACM! on Ubuntu) is this:

 *** AVAILABLE COMMANDS ***

 0: THIS MENU 

 1: Z Test :) 
 2: ORIGINAL SEEPROM HEX CONTENTS DUMP 
 3: COPY ORIGINAL SEEPROM TO BACKUP 
 4: COMPARE ORIGINAL TO BACKUP 


 AWAITING...

The fact that the half "\n" are missing, escaped my eye as well.

now if i change the 

str = "\n 2: ORIGINAL SEEPROM HEX CONTENTS DUMP \n\0";
to
str = "\n 2: ORIGINAL SEEPROM CONTENTS DUMP \n\0";


the output is this:

 *** AVAILABLE COMMANDS ***

 0: THIS MENU 

 1: Z Test :) 
��I%%91SEEPROM BYTES DUMP CONTENTS 
 3: COPY ORIGINAL SEEPROM TO BACKUP 
 4: COMPARE ORIGINAL TO BACKUP 


 AWAITING...

One other thing I noticed: If I go an step run it via the debugger, everything prints out fine, including the missing \n !!

I don't know what to make of this :)

BTW here are the settings for the ttyACM1:

stty -F /dev/ttyACM1 -a
speed 9600 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^H; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>;
start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 100; time = 2;
-parenb -parodd cs8 -hupcl -cstopb cread clocal -crtscts
-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl ixon -ixoff -iuclc -ixany -imaxbel
-iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon iexten -echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

Thanks in advance.

  • Hi Christos,

    Very interesting that stepping through it makes it work. That makes it seem like a timing problem perhaps.

    If you add enough artificial __delay_cycles(n) where you make n something nice and big (either between characters or between the strings) does this similarly help to "fix" the behavior?

    However I also double-checked your UART baud rate settings in EUSCI_A_UART_initAdvance(). I see you have set:

    UCOS16 = 1

    UCBRx = 6

    UCBRFx = 8

    UCBRSx = 17.

    Now, looking at the User's guide www.ti.com/lit/pdf/slau367 Table 21-5 Recommended settings for typical crystals and baudrates, I see that the recommended setting for 9600 baud from a 1MHz clock (like your SMCLK) is:

    UCOS16 = 1

    UCBRx = 6

    UCBRFx = 8

    UCBRSx = 0x20.


    Have you tried this baudrate setting instead and see if data comes through better for you?

    A likely unrelated note:

    I see your Init_ClockFast() function, where you set the DCO to 16MHz and then set it to divide by 2 so MCLK is not above 8MHz. I would recommend setting MCLK to source from DCO first and setting the divide by 2, before setting the DCO up to 16MHz. This is since you don't have FRAM wait states set up (and you shouldn't need them at 8MHz but would at 16MHz MCLK), by setting the divide by 2 first you'll ensure that you won't have any period of time where the FRAM is trying to be accessed at 16MHz with no waitstates. Right now there is some period of time where it does this - the time between when you set DCO = 16MHz but before you set MCLK to divide the DCO by 2. Does this make sense? It's nit-picky, but just to ensure best results and that the part is never running out of spec. Alternately, you can of course run MCLK at 16MHz the whole time if you wanted, just make sure to set up the FRAM waitstates first.

    Regards,

    Katie

  • You nailed it!

    I threw in 1000 delay cycles for starters and everything works sweet now.

    I also implemented your recommendations.

    Thanks alot.

    Cheers.

  • Hi Christos,

    Glad you were able to get everything up and running! :-)

    -Katie

**Attention** This is a public forum