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