MSP430 - G2xx BSL

From Texas Instruments Wiki
Jump to: navigation, search


This wiki describes a procedure of testing the MSP430G2xx BSL as described in the MSP430 Custom BSL Application Note (tidoc:slaa450), together with the open source TI-TXT-Parser. The target device used is MSP430G2xx3 (altough the MSP430G2xx3 has ROM BSL, but due to the pin assignment of hardware UART and BSL UART pin, application needs sometime to use the same pin for both purposes).


Another alternative for bootloader for MSP430G2xx is the OpenBSL.

BSL Code

The following code (modified from SLAA450 application code) is used for the BSL of MSP430G2xx3: File:G2xx3 INFO

NOTE: Since the G2xx3 has UART BSL on P1.1 and P1.2, the code size is smaller compared to Timer_A UART software BSL for MSP430G2xx1 or MSP430G2xx2, so that the BSL fits into INFOB,C, and D while INFOA containing the calibration data can be left intact.

MSP430G2xx BSL Protocol

The protocol used in this implementation of MSP430G2xx BSL is completely different than the one described in the main MSP430 BSL documentation tidoc:SLAU319.

The simple protocol of MSP430G2xx BSL works as follows:

BSL Entry

The reset vector points to the BSL code and right after reset the BSL code checks whether an input pin is pulled low (P1.3 connected to S2 push button on the MSP-EXP430G2 Launchpad board:

Reset vector:

;           Interrupt Vectors
            .sect   ".reset"                ; RESET Vector
            .short  RESET                   ; POR, ext. Reset

BSL entry checking:

            bit.b   #BSLPIN,&P1IN           ; Pin low invokes BSL
BslEntry?   jz      InvokeBsl
            br      #main                   ; Exit BSL if pin not set

BSL Init, Receiving CMD_SYNC

If the BSL code is invoked, the BSL will initialize the peripheral for BSL UART communication and then waits for the CMD_SYNC byte (0xBA) sent from the host. If other byte is received other than the CMD_SYNC, the BSL code will reset the device.

UART initialization:

;           BSL Invoked
InvokeBsl   mov.w   #280h,SP                ; Init Stackpointer to top of RAM
                                            ; RAM: 0x27f - 0x200
StopWDT     mov.w   #WDTPW+WDTHOLD,&WDTCTL  ; Stop Watchdog Timer
SetupDCO    ; Set DCO to calibrated 1 MHz:
            ;clr.b   &DCOCTL                 ; Lowest DCOx and MODx settings
            mov.b   &CALDCO_1MHZ,&DCOCTL    ; Copy from address 0x010FEh
            mov.b   &CALBC1_1MHZ,&BCSCTL1   ; Copy from address 0x010FFh
;OutputSMCLK bis.b   #BIT4,&P1DIR           ; Output SMCLK to check Frequency
;            bis.b   #BIT4,&P1SEL
SetupPins   bis.b   #(RXD+TXD),&P1SEL         ; setup USCI Rx/Tx pins
            bis.b   #(RXD+TXD),&P1SEL2
SetupUSCI	mov.b	#(UCSWRST+UCSSEL_2),&UCA0CTL1  ; USCI reset, clk source SMCLK
		mov.b 	#(104),&UCA0BR0
		mov.b 	#(0),&UCA0BR1
		mov.b 	#(UCBRS_1),&UCA0MCTL
		bic.b 	#(UCSWRST),&UCA0CTL1

CMD_SYNC check:

MainBsl             ; BSL Main Loop
Wait4sync   call    #RxOneByte
SyncCmd?    cmp     #CMD_SYNC,rxData        ; Sync command received?
            jne     BSLEnd                  ; Exit BSL if no Sync Byte

Erasing Flash Segments

After receiving CMD_SYNC, the BSL code will setup the Flash Memory Controller module to first erase every memory segment starting from the defined of .text memory section. The BSL will also erase the flash segment containing the interrupt vector, and re-write its own start address in the reset vector.

.text memory section:

            .text                           ; User Application
            ; ================================================================
            ; Never place any code / data between .text (RSEG CODE) and main
            ; label. This adress is used as start adress for user code
            ; ================================================================
            ; Customer Application starts here
main        mov.w   #WDTPW+WDTHOLD,&WDTCTL  ; Stop Watchdog Timer
Mainloop    jmp     Mainloop                ; Again
;           Flash Main Segment Start Adress (see datasheet)
FLASHSTART  .equ    main                    ; Lowest main flash address
(in the generated .map file):
 output                                  attributes/
section   page    origin      length       input sections
--------  ----  ----------  ----------   ----------------
.text      0    0000f800    00000008
                  0000f800    00000008     bsl.obj (.text)

Flash segment erase:

CmdFct_Erase        ; Erase main flash and restore interrupt vectors
            ; erase from bottom up
            mov.w   #FLASHSTART, rPoint     ; FLASH start address
EraseSeg    mov     &(FWKEY+ERASE),&FCTL1     ; ERASE=1. Erase Segment
            mov     &(FWKEY+FSSEL_2 + 2), &FCTL2
UnlockFlash ;mov.w   #FWKEY+00h,&FCTL3       ; LOCK=0, all others 0
	    mov.w   #FWKEY+LOCKA,&FCTL3       ; LOCK=0, LOCKA = 1, all others 0
            ; Start praying here that nothing happens during next CPU cycles
            mov.b   #0h,0(rPoint)           ; Start erase with dummy write
            cmp.w   #0FE00h, rPoint         ; Interrupt vector segment just erased?
            jge     WrtRstVec               ; Restore it!
            add.w   #512,rPoint             ; Next segment (add segment size)
            jmp     EraseSeg                ; Repeat segment erase
WrtRstVec   mov     #FWKEY+WRT,&FCTL1       ; WRT=1. Write to segment
            mov     #RESET,&0FFFEh          ; Point reset vector to BSL
            ; You can stop praying here. Everything went fine once PC is here

Writing Flash Memory

The BSL code needs sometime to erase the flash segments (for 2KB Flash about 20 ms), and after that it will start writing the new firmware into the flash memory (again starting from the defined .text memory section as above) based on every singla byte it receives from the host.

The BSL code will write the code up to address 0xFFFD since 0xFFFE is basically the beginning of reset vector which has been written with the BSL start address. Therefore the BSL code expects the following number of data bytes:

data bytes = flash memory size - 2

NOTE: flash memory size basically starts from address #FLASHSTART to address 0xFFFD.

The BSL code also calculates the checksum during downloading the new firmware, simply XOR-ing all the received bytes.

            ; ================================================================
            ; Erasing Flash and rewriting vectors take approx 16 ms
            ;  Make sure to wait this time before new data is sent to MSP430
            ;  The UART function is placed in flash thus preventing access
            ;  to it while flash erase / write.
            ; ================================================================
CmdFct_Write        ; Write 512 - 2 Byte to Main memory
            ;mov    #FWKEY+WRT,&FCTL1       ; Writing is still enabled
            ; Keeping WRT enabled w/o writing does not account into write time
            mov     #FLASHSTART,rPoint      ; Point to first position in FLASH
            clr     rCHKSUM                 ; Init Checksum
            ; ================================================================
            ; Ensure a minimum delay of 16 ms between SYNC and first byte
            ; ================================================================
CFW_w4d     call    #RxOneByte
CFW_Range   cmp     #0FFFEh, rPoint         ; Pointer to Reset Vector?
            jeq     CFW_Done                ; Skip and exit Write
            mov.b   rxData,0(rPoint)        ; Write 8 bit data to flash
CFW_Xor     xor.b   @rPoint+,rCHKSUM        ; xor checksum and inc pointer
            ;inc    rPoint                  ; inc done above w/ Auto increment
            jmp     CFW_w4d                 ; wait for next byte

Verifying Checksum

After receiving all data bytes up to address 0xFFFD the BSL code will wait for a checksum byte sent by the host, and then it compares with the calculated checksum to either send ACK byte( 0xF8) or NACK byte (0xFE). Finally the BSL will reset the device.

Checksum verification:

CFW_Done    ; ================================================================
            ; rx'ed byte for adress 0xffe (RESET) contains checksum
            ; ================================================================
            cmp.b   rxData, rCHKSUM         ; XOR'ing calc checksum with sent
            jeq     LoadAck                 ;  should result in ZERO if match
            ; send NACK
            mov.w   #NACK, &UCA0TXBUF 		; Copy byte
			jmp		SendAckNack
			; send ACK
LoadAck		mov.w   #ACK, &UCA0TXBUF 		; Copy byte
WaitTxBusy	bit.b 	#UCBUSY, &UCA0STAT
			jnz 	WaitTxBusy
            ; ================================================================
            ; Reset sequence required to exit BSL
            ; Do not jmp to main here - system is not in its initial state!
            ; ================================================================
BSLEnd      ;jmp     MainBsl                ; Start BSL over again
            clr     WDTCTL                  ; Exit BSL by issuing RESET
            ; ================================================================
            ; Reset sequence required to exit BSL
            ; Do not jmp to main here - system is not in its initial state!
            ; ================================================================

Test Procedure

Flashing BSL code

  • Compile the BSL code from above, and download to MSP430G2xx3 target on MSP-EXP430G2 Launchpad board. Make sure that P1.1 is connected to Launchpad UART RX line at J3 jumper connection, while P1.2 is connected to Launchpad TX line. On older version of MSP-EXP430G2 Launchpad board (v1.3 and v1.4), it is necessary to cross the UART TX-RX jumpers, but on v1.5 or newer this can be done by replacing the jumpers in horizontal position as shown below. Please refer to the Launchpad User's Guide documentation: tidoc:SLAU318C chapter 4.3. On Launchpad v1.3, it is also necessary to make sure that the pull-up resistor at P1.3 (push button S2) is available, otherwise the device will keep get into the BSL mode.
Msp430g2xx bsl uart conn.PNG

To be able compiling the code without error, make sure that the output format is "legacy COFF" as follows:

Msp430g2xx3 bsl output format.PNG

It is important to make sure that the access to info memory is activated in the debugger setting as follows:

Msp430g2xx3 bsl debug info mem.PNG

NOTE: It is important to ensure that the application code starts at the same address which the BSL code jumps into if the BSL is not to be executed.

            bit.b   #BSLPIN,&P1IN           ; Pin low invokes BSL
BslEntry?   jz      InvokeBsl
            br      #main                   ; Exit BSL if pin not set

As can be seen in the BSL code above if the BSL is not to be executed, the program will jump to main tag which is basically the beginning of .text section defined as 0xF800 in the linker command file:

    FLASH                   : origin = 0xF800, length = 0x07E0

    .text       : {} > FLASH              /* CODE                              */
  • After powering up the Launchpad via USB,press S2 (P1.3) button while resetting the device (pressing RESET button), to make sure device enters BSL mode after reset.

Running Test Script

  • Change the COM_PORT number in bsl_test.bat script file from the open source TI-TXT-Parser package found at ti-txt-parser\Examples\MSP430G2xx3 directory, and run the script file. The script will parse the example TI-TXT input file (test_blink.txt) and flash it via UART to the target device.

The output of executing bsl_test.bat looks like the following:

Simple example for flashing TI-TXT file to MSP430G2xx BSL
Input file : test_blink.txt
Device flash start address (MSP430G2xx3): 0xF800

!!Make sure that target device enters BSL mode!!
Press any key to continue . . .

== Parsing TI-TXT File: test_blink.txt  ==
Opening TI-TXT File:  test_blink.txt
Parsing data starting from address 0xf800 ( 63488 )
Parsing data starting from address 0xfee0 ( 65248 )
Parsing data starting from address 0xfffe ( 65534 )

== Filling memory range ==
Start Addr: 0xf800
End Addr: 0xffff
Fill byte: 0xff
Copying  68 bytes data from address  0xf800
Filling empty byte(s) from address 0xf844 to address  0xfee0
Copying  10 bytes data from address  0xfee0
Filling empty byte(s) from address 0xfeea to address  0xfffe
Copying  2 bytes data from address  0xfffe

== Flashing Target Device ==
Opening Serial Port: COM68
Sending SYNC byte ( 0xba )
Sending binary data - length: 2046 ( 0x7fe ) bytes
Sending checksum byte ( 0x94 )
Reading reply from target
received ACK

Press any key to continue . . .