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.

MSP430F67691 - custom BSL

Other Parts Discussed in Thread: MSP430F67691

I am using MSP430F67691 and have created my own custom BSL. I have modified BSL430_Low_Level_Init.asm from TI and adapted it to always enter BSL application. In the BSL application, I initialize clock, UART...  and check if I receive one especial 'password' during a maximum time (1 s). I have used no interrupt to do this (only polling):

- In case it is not correct, I force a software reset and execute user code.

- In case it is correct, I enter into a routine that receive firmware via UART. I store it in BANK 2 and BANK 3 (I use them as temporal FLASH memory). I check CRC of this firmware and, in case it is correct, I copy it to BANK 0 and BANK 1. Interrupt vectors are included in BANK0. Finally I force a software reset and execute NEW user code.

While I debug, everything seems to be correct (I have checked that firmware has correctly be written in BANK 2 and BANK 3, and starts copy to BANK0 and BANK 1). In normal operation I can assure that I enter this special routine (via LEDs) but when it finishes receiving the firmware, I check that all the memory has been erased (0xFF)!! This includes main memory and information memory, but no BSL memory.

Attached you can find my code:

#define BSL_APP

#include  <msp430f67691.h>
#include  "BSL_APP.h"
#include  "crc.h"
#include  "flash.h"

//IMPORTANT!!! This must be deleted from TI_TXT output file
//@fffe
//42 10

void main (void)
{
	Uint64 aux_i=0;
	Uint8 data_buffer[8];
	Uint8 index=0;

	Uint32 address=0, address_temp=0;
	Uint8 fw_update_id = 0, fw_version_high = 0, fw_version_medium = 0, fw_version_low = 0;

	WDTCTL = WDTPW + WDTHOLD;   	//Stop WDT

	_delay_cycles (500000); //equivalent to 0.5 s

	//slau208, page 102
	//SVSMHCTL = SVSHRVL1 + SVSMHRRL1;
	//PMMRIE   = SVSHPE;

	__bic_SR_register(GIE); //interrupt disabled

	//init
	xtal_init();

	//Default parameters (communication 9600 bps)
	RS485_conf();

	//Transceiver configuration as RECEIVER (Default)
	ALL_RS485_DIR |= nRE_RS485 + DE_RS485;		// output configuration
	ALL_RS485_OUT &= ~(DE_RS485 + nRE_RS485);	// DE=0; nRE=0

	//LEDs (OFF)
	LED_ALL_DIR |= LED_GREEN_OUT + LED_RED_OUT;	// output configuration
	LED_ALL_OUT |= LED_GREEN_OUT + LED_RED_OUT;

	//Address
	address = (Uint32) flash_read(((Uint8 *) (SEGMENT_A_INIT))+25,  4);
	fw_update_id = 4; //(Uint8) flash_read(((Uint8 *) (SEGMENT_A_INIT))+29,  1);
	fw_version_high   = 3; //(Uint8) flash_read(((Uint8 *) (SEGMENT_A_INIT))+30,  1);
	fw_version_medium = 0; //(Uint8) flash_read(((Uint8 *) (SEGMENT_A_INIT))+31,  1);
	fw_version_low =    0; //(Uint8) flash_read(((Uint8 *) (SEGMENT_A_INIT))+32,  1);

	//LED_ALL_OUT &= ~LED_GREEN_OUT;
    index = 0;
    aux_i = 0;
    while ((aux_i < BSL_MAX_TIME) && (index < 8))                                 // main loop
    {
    	if (UCA2IFG & UCRXIFG)
    	{
    		data_buffer[index] = UCA2RXBUF;
    		index++;
       	}
    	aux_i++;
    }
    //LED_ALL_OUT |= LED_GREEN_OUT;

	if (aux_i >= BSL_MAX_TIME)
	{
		WDTCTL = 0; //Force SW reset
	}
	else
	{
	    address_temp = (data_buffer[0]) | ((Uint32) (data_buffer[1]) << 8) | ((Uint32) (data_buffer[2]) << 16) | ((Uint32) (data_buffer[3]) << 24);

	    if ((address_temp == address) || (address_temp == MY_ADDRESS_BROADCAST))
	    {
	    	if (data_buffer[4] == fw_update_id)
	    	{
	    		if (( data_buffer[7] <  fw_version_high) ||
	    			((data_buffer[7] == fw_version_high) && (data_buffer[6] <  fw_version_medium)) ||
	    			((data_buffer[7] == fw_version_high) && (data_buffer[6] == fw_version_medium)  && (data_buffer[5] <= fw_version_low)))
	    		{
	    			fw_update();
	    		}
	    		else
	    		{
	    			WDTCTL = 0; //Force SW reset
	    		}

	    	}
	    	else
	    	{
	    		WDTCTL = 0; //Force SW reset
	    	}
	    }
	    else
	    {
			WDTCTL = 0; //Force SW reset
	    }
	}
}

void xtal_init(void)
{
	//UCSCTL3 |= SELREF_2;		// FLL Ref = REFO
	//UCSCTL4 |= SELA_2;          // Set ACLK = REFO

	// Initialize LFXT1
	//P7SEL |= 0x03;                            // Select XT1
	UCSCTL6 &= ~(XT1OFF);                     // XT1 On
	UCSCTL6 |= XCAP_3;                        // Internal load cap

	// Loop until XT1 fault flag is cleared
	do
	{
		UCSCTL7 &= ~XT1LFOFFG;                  // Clear XT1 fault flags
	}while (UCSCTL7&XT1LFOFFG);               // Test XT1 fault flag

	// Initialize DCO to 16,777216MHz
	__bis_SR_register(SCG0); 	// Disable the FLL control loop
	UCSCTL0 = 0x0000;			// Set lowest possible DCOx, MODx
	UCSCTL1 = DCORSEL_5;		// Select DCO range 24MHz operation
	UCSCTL2 = FLLD_1 + (512 - 1);// Set DCO Multiplier for 16,777216MHzMHz apro
		                            // (N + 1) * FLLRef = Fdco
		                            // (487 + 1) * 32768 = 16,777216MHz
		                            // Set FLL Div = fDCOCLK/2
	__bic_SR_register(SCG0);    // Enable the FLL control loop

	// Worst-case settling time for the DCO when the DCO range bits have been
	// changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
	// UG for optimization.
	// 32 x 32 x 16,777216 MHz / 32,768 Hz = 524288 = MCLK cycles for DCO to settle
	__delay_cycles(524288);//

	// Loop until XT1,XT2 & DCO stabilizes
	do
	{
		UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
		                                          // Clear XT2,XT1,DCO fault flags
	    SFRIFG1 &= ~OFIFG;                    // Clear fault flags
	}while (SFRIFG1&OFIFG);                   // Test oscillator fault flag

	//UCSCTL4 = SELA_0 + SELS_4 + SELM_0;       // Select ACLK = LFXT1
	                                          //       SMCLK = DCO
	                                          //        MCLK = LFXT1
}

void fw_update (void)
{
	Int64 index=0, firmware_length=0;
	Uint8 data=0, i=0, tx_finished=0;
	Uint16 crc_temp=0;

	index=0;
	i=0;
	firmware_length = 0;
	tx_finished=0;

	WDTCTL = WDTPW + WDTHOLD;   	//Stop WDT

	__bic_SR_register(GIE); //interrupt disabled

	//LEDs (ON)
	LED_ALL_OUT &= ~LED_GREEN_OUT;
	LED_ALL_OUT &= ~LED_RED_OUT;

	crc_ccitt_init();
	flash_bank_erase(((Uint8 *) BANK_2_ADDRESS)); //Erase BANK 2
	flash_bank_erase(((Uint8 *) BANK_3_ADDRESS)); //Erase BANK 3

	while(!tx_finished)
	{
		if (UCA2IFG & UCRXIFG)
	    {
			data = UCA2RXBUF;
			if (index < 4)
			{
				firmware_length |= ((Uint32) data) << 8*index;
				crc_ccitt_update(data);
			}
			else if (((index - 4) >= 0) && ((index - 4) < firmware_length))
			{
				flash_write(((Uint8 *) BANK_2_ADDRESS) + (index-4), (Uint8) data, 1);
				//crc_ccitt_update(data);
			}
			else if ((index - 4) >= firmware_length)
			{
				crc_temp |= data << 8*i;
				i++;
				if (i == 2)
				{
					tx_finished = 1;
				}
			}
			else
			{
				WDTCTL=0; //Force Reset; something is wrong...
			}
			index++;
	    }
	}

	__delay_cycles(20000);

	index=0;
	for (index = 0; index < firmware_length; index++)
	{
		data = (Uint8) flash_read(((Uint8 *) (BANK_2_ADDRESS)) + index, 1);
		crc_ccitt_update(data);
	}

	if (crc_temp == crc)
	{
		index=0;
		flash_bank_erase(((Uint8 *) BANK_0_ADDRESS)); //Erase BANK 0
		flash_bank_erase(((Uint8 *) BANK_1_ADDRESS)); //Erase BANK 1
		__delay_cycles(20000);
		for (index = 0; index < firmware_length; index++)
		{
			data = (Uint8) flash_read(((Uint8 *) (BANK_2_ADDRESS)) + index, 1);
			flash_write(((Uint8 *) BANK_0_ADDRESS) + index, (Uint8) data, 1);
		}
		//LEDs (OFF)
		LED_ALL_OUT |= LED_RED_OUT;
		_delay_cycles (20000000); //equivalent to 5 s
		LED_ALL_OUT |= LED_GREEN_OUT;

		WDTCTL=0; //Force Reset

		//data = (Uint16) flash_read((Uint8 *) 0xFFFE, 2);

		//((void (*)())data)();

	}
	else
	{

	WDTCTL=0; //Force Reset
	}
}

void RS485_conf(void)
{
	/*
	The recommended USCI initialization/re-configuration process is:
	1) Set UCSWRST (BIS.B #UCSWRST,&UCAxCTL1)
	2) Initialize all USCI registers with UCSWRST = 1 (including UCAxCTL1)
	3) Configure ports.
	4) Clear UCSWRST via software (BIC.B #UCSWRST,&UCAxCTL1)
	5) Enable interrupts (optional) via UCAxRXIE and/or UCAxTXIE
	*/

	/*
// 	1)
	UCA2CTL1 |= UCSWRST;	// USCI logic held in reset state
//	2)
//	UCA2CTL0 = UCPEN + UCPAR + UCMODE_1;	// 1Parity enabled, Even parity, LSB first, 8-bit data, One stop bit, Idle-Line Multiprocessor Mode, Asynchronous mode
	UCA2CTL0 = UCMODE_0;// UCPEN + UCPAR + UCMODE;	// LSB first, 8-bit data, One stop bit, UART Mode, Asynchronous mode
	UCA2CTL1 = UCSSEL_2;	// SMCLK = 16.777216 MHz
	baud_rate_reg_calc((Uint32) BR19200, SYSTEM_CLK);
//	3)
	UCA2SEL |= UCA2TXD + UCA2RXD;
//	4)
	UCA2CTL1 &= ~UCSWRST;	// Initialize USCI state machine
//	5)
	UC2IE |= UCA2RXIE;		// USCI 1 Rx Interrupt Enable

	//Transceiver configuration as RECEIVER (Default)
	ALL_RS485_DIR |= nRE_RS485 + DE_RS485;		// output configuration
	ALL_RS485_OUT &= ~(DE_RS485 + nRE_RS485);	// DE=0; nRE=0
	*/

	UCA2IE &= ~UCRXIE;		// USCI 1 Rx Interrupt Disable
	UCA2IE &= ~UCTXIE;		// USCI 1 Tx Interrupt Disable

	UCA2CTL1 |= UCSWRST;	// USCI logic held in reset state

	/*UCA2CTL0 &= ~BIT7; //no parity
	UCA2CTL0 &= ~BIT4; //8 bits
	UCA2CTL0 &= ~BIT3; //1 stop bit
	UCA2CTL0 &= ~BIT5;	// LSB first
	UCA2CTL0 &= ~BIT2;	// UART Mode
	UCA2CTL0 &= ~BIT1;	// UART Mode
	UCA2CTL0 &= ~BIT0;	// Async Mode*/
	UCA2CTL0 = 0;

	UCA2CTL1 = UCSSEL_2;	// SMCLK = 16.777216 MHz

	//1200bps
	//UCA2BRW = 873;
	//UCA2MCTLW |= UCOS16 + (13<<4);
	//UCA2MCTLW |= (((Uint16) 0x00) << 8);

	//9600bps
	UCA2BRW = 109;
	UCA2MCTLW |= UCOS16 + ( 3<<4);
	UCA2MCTLW |= (((Uint16) 0xB5) << 8);

	UCA2SEL |= UCA2TXD + UCA2RXD;

	UCA2CTL1 &= ~UCSWRST;	// Initialize USCI state machine
}

Thank you

  • It's not clear from your description what your problem is when not running under debugger....

    At what step does the process fail?
  • While I debugg I have no problem. I receive password, check it is correct, and receive and store new firmware in BANK 2 and BANK3. I check that CRC is ok, so I finally copy firmware to BANK 0 and BANK1.

    The problem is that when I check it in normal operation (with no debug), I get no firmware update!! I read memory using ELPROTRONIC and I read 0xFF in all main and information memory. It is very strange...
  • I think first step is to figure out what goes wrong. If you have some unused I/O pins, try adding code to set different pins at different stages of the process, i.e. set test point 1 (TP1) when banks 2/3 erase, TP2 when firmware is received, TP3 if CRC passes, etc.

    There are some things that tend to behave differently when run within debugger.

**Attention** This is a public forum