I have inherited a custom Bootloader application that was designed for a 2272 uC that I have ported to a 58891. The customer bootloader accepts the downloaded image from a LabVIEW application running on the serial port (eUSCI_A). The image successfully loads into the 58891 uC's FRAM (0x8000 -0xdfff) and is verified. After a successful verification I jump to the CStart (0x8a38) location in the downloaded image.
// __asm( "mov.w &0xdffe, PC" ); //lnk430fr58891_Operational.xcl -Z(CODE)RESET=dffe-dfff
__asm( "mov.w #0x8a38, PC" ); //lnk430fr58891_Operational.xcl -Z(CODE)RESET=dffe-dfff
This action generates a RESET and the uC fetches the CStart (0x45fe) from my Bootloader application RESET vector( 0xFFFE) and proceeds to execute the custom Bootloader. I have the MPU disabled by calling MPU_Initialize() immediate at the beginning of main() (see below). I have a __intrinsic int __low_level_init(void) routine that I understand is executed by CStart and it is also set to disable the MPU. The bootloader is located at FRAM addresses 0x400-63ff. The Bootloader has the default interrupt vector table at the top of the 64k address space( RESET 0xFFFE).
------------------------------------------------------------------------------------------------------------------------------
Filename: MPU.c
------------------------------------------------------------------------------------------------------------------------------
void MPU_Initialize( void ) {
MPUCTL0 = MPUPW; // 0xa500; // PWD, GIE =Disabled, LOCK =Open, ENA =Disabled
}
// This is example code from
// MSP430™ FRAM Technology – How To and Best Practices SLAA628–June 2014
// p.10
/* see intrinsics.h
* If the application provides this function, it is called by the
* startup code before variables are initialized. If the function
* returns 0 the data segments will not be initialized.
*/
// __intrinsic int __low_level_init(void);
//#include "msp430.h"
__intrinsic int __low_level_init(void)
{
/* Insert your low-level initializations here */
WDTCTL = WDTPW+WDTHOLD;
// Configure MPU
MPUCTL0 = MPUPW; // Write PWD to access MPU registers
//MPUSEGB1 = 0x0480; // B1 = 0x4800; B2 = 0x4C00
//MPUSEGB2 = 0x04c0; // Borders are assigned to segments
// Segment 1 – Allows read and write only
// Segment 2 – Allows read only
// Segment 3 – Allows read and execute only
//MPUSAM = (MPUSEG1WE | MPUSEG1RE | MPUSEG2RE | MPUSEG3RE | MPUSEG3XE);
//MPUCTL0 = MPUPW | MPUENA | MPUSEGIE; // Enable MPU protection
// MPU registers locked until BOR
/*
* Return value:
*
* 1 - Perform data segment initialization.
* 0 - Skip data segment initialization.
*/
return 1;
------------------------------------------------------------------------------------------------------------------------------
Filename: lnk430fr58891_Operational.xcl
------------------------------------------------------------------------------------------------------------------------------
// ****************************** 8000-dfff
//
// XLINK configuration file for MSP430FR58891
//
// Copyright 1996-2016 IAR Systems AB.
//
// See the file 430/doc/licenses/IARSourceLicense.txt for detailed
// license information.
//
// $Revision: 13610 $
//
// ************************************************
// ---------------------------------------------------------
// Description
//
//
// Usage:
//
// xlink [file file ...] -f lnk430fr58891.xcl
//
// -----------------------------------------------
// Device summary
//
//
// Core: MSP430Xv2
//
// Interrupt vectors: 56
//
// Signature memory: 16 Bytes
//
// JTAG Signature memory: 4 Bytes
//
// BSL Signature memory: 4 Bytes
//
// IPE Signature memory: 8 Bytes
//
// Peripheral units: 00100-00FFF
//
// Information memory (FRAM): 01800-019FF
//
// Read/write memory (RAM): 01C00-023FF
//
// Read/write memory (TINYRAM): 00006-0001F
//
// Persistent memory (FRAM): 04400-0FFFF
// 10000-23FFF
//
// -----------------------------------------------
// Segments
//
// -------------------------------------
// Data read/write segments
//
//
// The following segments are available for both
// the DATA16 and DATA20 segment groups.
//
// segment Usage
// ------- --------------------------
// DATA<nn>_Z Data initialized to zero
// DATA<nn>_I Data initialized by copying from DATA<nn>_ID
// DATA<nn>_N Data defined using __no_init
// DATA<nn>_P Data defined using __persistent
// DATA<nn>_HEAP The heap used by 'malloc' and 'free'
//
// segment Usage
// ------- --------------------------
// CSTACK Runtime stack
// TLS16_I Thread-local storage for main thread
//
// -------------------------------------
// Program and data read-only segments
//
//
// The following segments are available for both
// the DATA16 and DATA20 segment groups.
//
// segment Usage
// ------- --------------------------
// DATA<nn>_C Constant data, including string literals
// DATA<nn>_ID Initializers for DATA<nn>_I
//
// segment Usage
// ------- --------------------------
// INFO Information memory
// INFOA Information memory, bank A
// INFOB Information memory, bank B
// INFOC Information memory, bank C
// INFOD Information memory, bank D
// CSTART Program startup code
// CODE Program code
// ISR_CODE Program code for interrupt service routines
// DIFUNCT Dynamic initialization vector used by C++
// CHECKSUM Checksum byte(s) generated by the -J option
// SIGNATURE Signature memory
// JTAGSIGNATURE JTAG Signature memory
// BSLSIGNATURE BSL Signature memory
// IPESIGNATURE IPE Signature memory
// INTVEC Interrupt vectors
// RESET The reset vector
// TLS16_ID Thread-local initializers for main thread
// MPU_B<N> Memory Protection Unit border
// IPE_B<N> Intellectual Property Encapsulation border
// IPECODE16 IPE code
// IPEDATA16_C IPE constant data
//
// Notes:
//
// * The segments CSTART, ISR_CODE, and DIFUNCT, as well as the segments in
// the DATA16 and TLS16 segment groups must be placed in in the range
// 0000-FFFD.
//
// * The INFOx and INFO segments overlap, this allows data either to be
// placed in a specific bank or anywhere in the info memory.
//
// * The INTVEC and RESET segments overlap. This allows an application to
// either use the reset vector provided by the runtime library, or
// provide a reset function by defining an interrupt function associated
// with the reset vector.
//
// * To use the Memory Protection Unit, the symbol ?mpu2_init should be
// included in the application. The symbol '__iar_430_MPU_base' should be
// defined to the location of the MPU peripheral registers, and the
// registers '__iar_430_MPUSAM_value' and '__iar_430_MPUCTL0_value' to
// the value the registers MPUSAM and MPUCTL0 should be initialized to,
// respectively.
//
// * To include Intellectual Property Encapsulation (IPE), the library
// label '__iar_430_ipe_signature' must be included in the application.
// (One way to do this is to use the -g XLINK command-line option.) The
// symbol '__iar_430_MPUIPC0_value' must be defined to the value the
// MPUIPC0 register should be initialized to.
//
// * To include custom segments in the Intellectual Property Encapsulation
// (IPE) area, place them between the segments IPE_B1 and IPE_B2.
//
// ---------------------------------------------------------
// Configuation
//
// -----------------------------------------------
// Stack and heap sizes
//
// Uncomment for command line use
//-D_STACK_SIZE=160
//-D_DATA16_HEAP_SIZE=160
//-D_DATA20_HEAP_SIZE=160
//-g?mpu2_init
//-g__iar_430_ipe_signature
// -----------------------------------------------
// Define cpu
//
-cmsp430
// -----------------------------------------------
// Support for placing functions in read/write memory
//
-QCODE_I=CODE_ID
// -----------------------------------------------
// Support for thread local storage
//
-QTLS16_I=TLS16_ID
// -----------------------------------------------
// Hardware multiplier location
//
-D__iar_HWMUL=4C0
// ---------------------------------------------------------
// Placement directives
//
// -----------------------------------------------
// Information memory
//
-Z(CONST)INFO=1800-19FF
-Z(CONST)INFOA=1980-19FF
-Z(CONST)INFOB=1900-197F
-Z(CONST)INFOC=1880-18FF
-Z(CONST)INFOD=1800-187F
// -----------------------------------------------
// RAM memory
//
-Z(DATA)BOOTLOADER_MESSAGE=1c00-1c05
-Z(DATA)TINYRAM=0006-001F
-Z(DATA)DATA16_I,DATA16_Z,DATA16_N,TLS16_I=1c06-23FF
//-Z(DATA)TINYRAM=0006-001F
//-Z(DATA)DATA16_I,DATA16_Z,DATA16_N,TLS16_I=1C00-23FF
-Z(DATA)CODE_I
-Z(DATA)DATA20_I,DATA20_Z,DATA20_N
-Z(DATA)CSTACK+_STACK_SIZE#
// -----------------------------------------------
// FRAM memory
//
// -------------------------------------
// Low memory 0-0FFFF
//
// ---------------------------
// Read/write data in FRAM
//
-Z(CONST)DATA16_P,DATA20_P=8000-dfff
-Z(DATA)DATA16_HEAP+_DATA16_HEAP_SIZE
-Z(DATA)DATA20_HEAP+_DATA20_HEAP_SIZE
// ---------------------------
// Memory Protection Unit (MPU) border
//
-Z(CONST)MPU_B1
// ---------------------------
// Intellectual Property Encapsulation (IPE)
//
-Z(CONST)IPE_B1=8000-dfff
-Z(DATA)IPEDATA16_N
-Z(CODE)IPECODE16
-Z(CONST)IPEDATA16_C,IPE_B2
// ---------------------------
// Memory Protection Unit (MPU) border
//
-Z(CONST)MPU_B2
// ---------------------------
// Constant data
//
-Z(CONST)DATA16_C,DATA16,TLS16_ID,DIFUNCT_ID,CHECKSUM=8000-dfff
// ---------------------------
// Code
//
-Z(CODE)CSTART,ISR_CODE,CODE16=8000-dfff
// -------------------------------------
// All memory 0-FFFFF
//
// ---------------------------
// Code
//
-P(CODE)CODE=8000-dfff,10000-23FFF
-Z(CODE)CODE_PAD
// ---------------------------
// Constant data
//
-Z(CONST)DATA20_C,DATA20_ID,CODE_ID=8000-dfff,10040-23FFF
// -------------------------------------
// Signature memory and interrupt vectors
//
-Z(CONST)SIGNATURE=DF80-DF8F
-Z(CONST)JTAGSIGNATURE=DF80-DF83
-Z(CONST)BSLSIGNATURE=DF84-DF87
-Z(CONST)IPESIGNATURE=DF88-DF8F
-Z(CODE)INTVEC=DF90-DFFF
-Z(CODE)RESET=DFFE-DFFF