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.

DK-TM4C123G: SD Card Bootloader, erratic behaviors with fatfs

Part Number: DK-TM4C123G


After numerous unsuccessful attempts at modifying the boot_serial project and using the assembly start up code provide; while seeing many strange behaviors, such as changing behaviors with levels of compiler optimization, strange sp and lr addresses, change the GPIO Forced Update assignment breaking the program at a different later point, and sometimes variables/pointers simply just not setting after stepping through the statement --

This is my latest attempt at creating a SD Card bootloader that is as simple as possible and easy to understand as possible.

This seems correct in theory and should be useful to someone else as well... 

The start up script is nothing special, just the one provided through Keil. fatfs files are the ones included with TivaWare. 

With this build:

I am seeing the SP changed to 0x1fffff60 right as I step to f_mount(0, &fatFs); 

so then I moved the following to a global area:

	FATFS 		fatFs;
	FIL 			fileObject;	
	FRESULT 	fResult;

This way they would not be allocated using the stack, just to see what happens, since this data shouldnt't be causing a stack overflow or any issues in the first place. I don't see the erratic stack pointer. But at some arbitrary point later LR is set to 0xfffffff9 and the program goes into HardFault_Handler. 

I really cannot explain this behavior any way.

The APP_START_ADDRESS 0x2800 was actually flashed with boot_demo2 using another program. I am able to jump from boot_demo2 back to the Bootloader program... but for some reason going into the fatfs functions, strange things occur. I know the problem is not with the fatfs code, it has work with other projects. 

//*****************************************************************************
//
// bl_main.c - The file holds the main control loop of the boot loader.
//
// Copyright (c) 2006-2016 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
// 
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
// 
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 2.1.3.156 of the Tiva Firmware Development Package.
//
//*****************************************************************************
//*****************************************************************************
//
// Convert to SD boot loader and test with boot  demo 1 and 2
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_gpio.h"
#include "inc/hw_nvic.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"

#include "fatfs/src/ff.h"
#include "fatfs/src/diskio.h"
//#include "pff3/src/pff.h"		/* Petit FatFs configurations and declarations */
//#include "pff3/src/diskio.h"		/* Declarations of low level disk I/O functions */
//#include "pff3/src/pffconf.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"

//*****************************************************************************
//
// Make sure that the application start address falls on a flash page boundary
//
//*****************************************************************************
#if (APP_START_ADDRESS & (FLASH_PAGE_SIZE - 1))
#error ERROR: APP_START_ADDRESS must be a multiple of FLASH_PAGE_SIZE bytes!
#endif

//*****************************************************************************
//
// Make sure that the flash reserved space is a multiple of flash pages.
//
//*****************************************************************************
#if (FLASH_RSVD_SPACE & (FLASH_PAGE_SIZE - 1))
#error ERROR: FLASH_RSVD_SPACE must be a multiple of FLASH_PAGE_SIZE bytes!
#endif

//*****************************************************************************
//
// The starting address of the application.  This must be a multiple of 1024
// bytes (making it aligned to a page boundary).  A vector table is expected at
// this location, and the perceived validity of the vector table (stack located
// in SRAM, reset vector located in flash) is used as an indication of the
// validity of the application image.
//
// The flash image of the boot loader must not be larger than this value.
//
// Depends on: None
// Exclusive of: None
// Requires: None
//
//*****************************************************************************
#define APP_START_ADDRESS       0x2800

//*****************************************************************************
//
// The address at which the application locates its exception vector table.
// This must be a multiple of 1024 bytes (making it aligned to a page
// boundary).  Typically, an application will start with its vector table and
// this value should be set to APP_START_ADDRESS.  This option is provided to
// cater for applications which run from external memory which may not be
// accessible by the NVIC (the vector table offset register is only 30 bits
// long).
//
// Depends on: None
// Exclusive of: None
// Requires: None
//
//*****************************************************************************
#define VTABLE_START_ADDRESS    0x2800

//*****************************************************************************
//
// The size of a single, erasable page in the flash.  This must be a power
// of 2.
//
// Depends on: None
// Exclusive of: None
// Requires: None
//
//*****************************************************************************
#define FLASH_PAGE_SIZE         0x00000400

//*****************************************************************************
//
// The GPIO module to enable in order to check for a forced update.  This will
// be one of the SYSCTL_RCGC2_GPIOx values, where "x" is replaced with the port
// name (such as B).  The value of "x" should match the value of "x" for
// FORCED_UPDATE_PORT.
//
// Depends on: ENABLE_UPDATE_CHECK
// Exclusive of: None
// Requries: None
//
//*****************************************************************************
//#define FORCED_UPDATE_PERIPH    SYSCTL_RCGC2_GPIOB 
#define FORCED_UPDATE_PERIPH    0x00000800 // for GPIOM

//*****************************************************************************
//
// The GPIO port to check for a forced update.  This will be one of the
// GPIO_PORTx_BASE values, where "x" is replaced with the port name (such as
// B).  The value of "x" should match the value of "x" for
// FORCED_UPDATE_PERIPH.
//
// Depends on: ENABLE_UPDATE_CHECK
// Exclusive of: None
// Requries: None
//
//*****************************************************************************
#define FORCED_UPDATE_PORT      GPIO_PORTM_BASE

//*****************************************************************************
//
// The pin to check for a forced update.  This is a value between 0 and 7.
//
// Depends on: ENABLE_UPDATE_CHECK
// Exclusive of: None
// Requries: None
//
//*****************************************************************************
#define FORCED_UPDATE_PIN       0

//*****************************************************************************
//
// The polarity of the GPIO pin that results in a forced update.  This value
// should be 0 if the pin should be low and 1 if the pin should be high.
//
// Depends on: ENABLE_UPDATE_CHECK
// Exclusive of: None
// Requries: None
//
//*****************************************************************************
#define FORCED_UPDATE_POLARITY  0

//*****************************************************************************
//
// This enables a weak pull-up or pull-down for the GPIO pin used in a forced
// update.  Only one of FORCED_UPDATE_WPU or FORCED_UPDATE_WPD should be
// defined, or neither if a weak pull-up or pull-down is not required.
//
// Depends on: ENABLE_UPDATE_CHECK
// Exclusive of: None
// Requries: None
//
//*****************************************************************************
#define FORCED_UPDATE_WPU
//#define FORCED_UPDATE_WPD

//*****************************************************************************
//
// This enables the use of the GPIO_LOCK mechanism for configuration of
// protected GPIO pins (for example JTAG pins).  If this value is not defined,
// the locking mechanism will not be used.  The only legal values for this
// feature are GPIO_LOCK_KEY for Fury devices and GPIO_LOCK_KEY_DD for all
// other devices except Sandstorm devices, which do not support this feature.
//
// Depends on: ENABLE_UPDATE_CHECK
// Exclusive of: None
// Requries: None
//
//*****************************************************************************
//#define FORCED_UPDATE_KEY       GPIO_LOCK_KEY
//#define FORCED_UPDATE_KEY       GPIO_LOCK_KEY_DD



#define Delay(n) ROM_SysCtlDelay((ROM_SysCtlClockGet()/3000000)*n)


//extern void CallApplication();

uint32_t g_ui32Forced = 0;

//*****************************************************************************
//
//! Checks a GPIO for a forced update.
//!
//! This function checks the state of a GPIO to determine if a update is being
//! requested.
//!
//! \return Returns a non-zero value if an update is being requested and zero
//! otherwise.
//
//*****************************************************************************
uint32_t
CheckGPIOForceUpdate(void)
{
    //
    // Enable the required GPIO module.
    //
    HWREG(SYSCTL_RCGCGPIO) |= FORCED_UPDATE_PERIPH;
	
    //
    // Wait a while before accessing the peripheral.
    //
    Delay(3);

#ifdef FORCED_UPDATE_KEY
    //
    // Unlock the GPIO Access.
    //
    HWREG(FORCED_UPDATE_PORT + GPIO_O_LOCK) = FORCED_UPDATE_KEY;
    HWREG(FORCED_UPDATE_PORT + GPIO_O_CR) = 1 << FORCED_UPDATE_PIN;
#endif

    //
    // Enable the pin used to see if an update is being requested.
    //
    HWREG(FORCED_UPDATE_PORT + GPIO_O_DEN) |= 1 << FORCED_UPDATE_PIN;
#ifdef FORCED_UPDATE_WPU
    //
    // Set the output drive strength.
    //
    HWREG(FORCED_UPDATE_PORT + GPIO_O_DR2R) |= 1 << FORCED_UPDATE_PIN;

    //
    // Enable the weak pull up.
    //
    HWREG(FORCED_UPDATE_PORT + GPIO_O_PUR) |= 1 << FORCED_UPDATE_PIN;

    //
    // Make sure that the analog mode select register is clear for this pin.
    //
    HWREG(FORCED_UPDATE_PORT + GPIO_O_AMSEL) &= ~(1 << FORCED_UPDATE_PIN);
#endif
#ifdef FORCED_UPDATE_WPD
    //
    // Set the output drive strength.
    //
    HWREG(FORCED_UPDATE_PORT + GPIO_O_DR2R) |= 1 << FORCED_UPDATE_PIN;

    //
    // Enable the weak pull down.
    //
    HWREG(FORCED_UPDATE_PORT + GPIO_O_PDR) |= 1 << FORCED_UPDATE_PIN;

    //
    // Make sure that the analog mode select register is clear for this pin.
    // This register only appears in DustDevil-class (and later) devices, but
    // is a harmless write on Sandstorm- and Fury-class devices.
    //
    HWREG(FORCED_UPDATE_PORT + GPIO_O_AMSEL) &= ~(1 << FORCED_UPDATE_PIN);
#endif

#ifdef FORCED_UPDATE_KEY
    //
    // Unlock the GPIO Access.
    //
    HWREG(FORCED_UPDATE_PORT + GPIO_O_LOCK) = FORCED_UPDATE_KEY;
    HWREG(FORCED_UPDATE_PORT + GPIO_O_CR) = 0;
#endif

    //
    // Wait a while before reading the pin.
    //
    Delay(1000);

    //
    // Check the pin to see if an update is being requested.
    //
    if(HWREG(FORCED_UPDATE_PORT + (1 << (FORCED_UPDATE_PIN + 2))) ==
       (FORCED_UPDATE_POLARITY << FORCED_UPDATE_PIN))
    {
        //
        // Remember that this was a forced update.
        //
        g_ui32Forced = 1;

        return(1);
    }

    //
    // No update is being requested so return 0.
    //
    return(0);
}


//*****************************************************************************
//
//! Checks if an update is needed or is being requested.
//!
//! This function detects if an update is being requested or if there is no
//! valid code presently located on the microcontroller.  This is used to tell
//! whether or not to enter update mode.
//!
//! \return Returns a non-zero value if an update is needed or is being
//! requested and zero otherwise.
//
//*****************************************************************************
uint32_t
CheckForceUpdate(void)
{

    uint32_t *pui32App;

    //
    // See if the first location is 0xfffffffff or something that does not
    // look like a stack pointer, or if the second location is 0xffffffff or
    // something that does not look like a reset vector.
    //
    pui32App = (uint32_t *)APP_START_ADDRESS;
    if((pui32App[0] == 0xffffffff) ||
       ((pui32App[0] & 0xfff00000) != 0x20000000) ||
       (pui32App[1] == 0xffffffff) ||
       ((pui32App[1] & 0xfff00001) != 0x00000001))
    {
        return(1);
    }

    //
    // If simple GPIO checking is configured, determine whether or not to force
    // an update.
    //
    return(CheckGPIOForceUpdate());
}

//*****************************************************************************
//
//! Configures the microcontroller.
//!
//! This function configures the peripherals and GPIOs of the microcontroller,
//! preparing it for use by the boot loader.  The interface that has been
//! selected as the update port will be configured, and auto-baud will be
//! performed if required.
//!
//! \return None.
//
//*****************************************************************************
void
ConfigureDevice(void)
{
    //
    // Since the crystal frequency was specified, enable the main oscillator
    // and clock the processor from it.
    //
//    HWREG(SYSCTL_RCC) &= ~(SYSCTL_RCC_MOSCDIS);
//    Delay(524288);
//    HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) & ~(SYSCTL_RCC_OSCSRC_M)) |
//                         SYSCTL_RCC_OSCSRC_MAIN);
//	ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_INT | SYSCTL_MAIN_OSC_DIS); //Enable for ROM_SysCtlDelay
	
    int nStatus;
	
	  HWREG(SYSCTL_RCGCGPIO) &= ~FORCED_UPDATE_PERIPH;
	
    ROM_SysCtlClockSet(SYSCTL_USE_OSC | SYSCTL_OSC_INT);
		nStatus = ROM_SysCtlClockGet();
 
    //
    // Configure SysTick for a 100Hz interrupt.  The FatFs driver wants a 10 ms
    // tick.
    //
    ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / 100);
    ROM_SysTickEnable();
    ROM_SysTickIntEnable();
		
		ROM_IntMasterEnable();
}


//*****************************************************************************
//
//! This function performs the update on the selected port.
//!
//! This function is called directly by the boot loader or it is called as a
//! result of an update request from the application.
//!
//! \return Never returns.
//
//*****************************************************************************
void
Updater(void)
{
	FATFS 		fatFs;
	FIL 			fileObject;	
	FRESULT 	fResult;
	
	uint32_t addr, count, data, temp;
	

	fResult = f_mount(0, &fatFs);
	//fResult = pf_mount(&fatFs);

  if(fResult == FR_OK)
	{
		fResult = f_open(&fileObject, "boot2.bin", FA_READ);
		//fResult = pf_open("boot2.bin");
		
//		temp = 0;
//		do
//		{
//			fResult = pf_open("boot2.bin");
//			temp++;
//		}	while (temp < 10 && (fResult != FR_OK) );
		
		if(fResult == FR_OK)
		{
			for(addr = APP_START_ADDRESS; addr < APP_START_ADDRESS + fileObject.fsize; addr += FLASH_PAGE_SIZE)
			//for(addr = APP_START_ADDRESS; addr < APP_START_ADDRESS + fatFs.fsize; addr += FLASH_PAGE_SIZE)
			{
					//
					// Erase this block.
					//
					ROM_FlashErase(addr);
			}

			for(addr = APP_START_ADDRESS; addr < APP_START_ADDRESS + fileObject.fsize; addr += 4)
			//for(addr = APP_START_ADDRESS; addr < APP_START_ADDRESS + fatFs.fsize; addr += 4)
			{
					//
					// Write data to the flash 4 bytes at a time
					//
					f_read(&fileObject, &data, 4, &count);
					//pf_read(&data, 4, &count);
					ROM_FlashProgram(&data, addr, 4);
			}
		}
	}
	
//	HWREG(NVIC_APINT) = (NVIC_APINT_VECTKEY | NVIC_APINT_SYSRESETREQ);
	
	while(1);
}

//*****************************************************************************
//
// This is the handler for this SysTick interrupt.  FatFs requires a timer tick
// every 10 ms for internal timing purposes.
//
//*****************************************************************************
void
SysTickHandler(void)
{
    //
    // Call the FatFs tick timer.
    //
    disk_timerproc();
}


void SVC_Handler (void)
{
	ConfigureDevice();
	Updater();
	while(1);
}

int
main(void)
{
	uint32_t t = 213 ;
	
	t = ROM_SysCtlClockGet();	

	if (CheckForceUpdate())
	{
	 ConfigureDevice();
	 Updater();
	}
	else
	{
    ROM_SysTickIntDisable(); 
    ROM_SysTickDisable(); 

    HWREG(NVIC_DIS0) = 0xffffffff;
    HWREG(NVIC_DIS1) = 0xffffffff;

    (*((void (*)(void))(*(uint32_t *)(APP_START_ADDRESS+4))))(); 
	}
	 
	while(1);
}

//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************

  • Hello Scott

    Did you update the VTABLE register to point to the Application Base Address for the new interrupt vector table to be used?
  • Good catch. I did correct that, but I don't think that was causing an issue, for now at least. Since VTABLE stays at 0 when the program jumps to APP_ADDRESS and jumps back to the bootloader. I suppose this would cause problems if the actual application were to run interrupts. 

    For some reason the line " rfs = FatFs[vol]; /* Get current fs object */ " in f_mount() causes rfs to be set to some 0x8000000 address, and the program later hard faults at  " if (fs) { " 
    These are seemly arbitrary lines...

    However, I did notice that my previous attempt with PetiteFS, was in fact having some issue due to defining the FATFS structure inside a function using stack space. Moving that outside seems to have corrected the problem.

    That is strange because the example I found here works fine, and it defines FatFs inside a function: github.com/.../Tiva-SD-Card-Boot-Loader

    Anyhow mine works now. If anyone wants to try it

    //*****************************************************************************
    //
    // bl_main.c - The file holds the main control loop of the boot loader.
    //
    // Copyright (c) 2006-2016 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.1.3.156 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************
    //*****************************************************************************
    //
    // Convert to SD boot loader and test with boot  demo 1 and 2
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_gpio.h"
    #include "inc/hw_nvic.h"
    #include "inc/hw_sysctl.h"
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    
    //#include "fatfs/src/ff.h"
    //#include "fatfs/src/diskio.h"
    #include "pff3/src/pff.h"		/* Petit FatFs configurations and declarations */
    #include "pff3/src/diskio.h"		/* Declarations of low level disk I/O functions */
    #include "pff3/src/pffconf.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    
    //*****************************************************************************
    //
    // Make sure that the application start address falls on a flash page boundary
    //
    //*****************************************************************************
    #if (APP_START_ADDRESS & (FLASH_PAGE_SIZE - 1))
    #error ERROR: APP_START_ADDRESS must be a multiple of FLASH_PAGE_SIZE bytes!
    #endif
    
    //*****************************************************************************
    //
    // Make sure that the flash reserved space is a multiple of flash pages.
    //
    //*****************************************************************************
    #if (FLASH_RSVD_SPACE & (FLASH_PAGE_SIZE - 1))
    #error ERROR: FLASH_RSVD_SPACE must be a multiple of FLASH_PAGE_SIZE bytes!
    #endif
    
    //*****************************************************************************
    //
    // The starting address of the application.  This must be a multiple of 1024
    // bytes (making it aligned to a page boundary).  A vector table is expected at
    // this location, and the perceived validity of the vector table (stack located
    // in SRAM, reset vector located in flash) is used as an indication of the
    // validity of the application image.
    //
    // The flash image of the boot loader must not be larger than this value.
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    #define APP_START_ADDRESS       0x2800
    
    //*****************************************************************************
    //
    // The address at which the application locates its exception vector table.
    // This must be a multiple of 1024 bytes (making it aligned to a page
    // boundary).  Typically, an application will start with its vector table and
    // this value should be set to APP_START_ADDRESS.  This option is provided to
    // cater for applications which run from external memory which may not be
    // accessible by the NVIC (the vector table offset register is only 30 bits
    // long).
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    #define VTABLE_START_ADDRESS    0x2800
    
    //*****************************************************************************
    //
    // The size of a single, erasable page in the flash.  This must be a power
    // of 2.
    //
    // Depends on: None
    // Exclusive of: None
    // Requires: None
    //
    //*****************************************************************************
    #define FLASH_PAGE_SIZE         0x00000400
    
    //*****************************************************************************
    //
    // The GPIO module to enable in order to check for a forced update.  This will
    // be one of the SYSCTL_RCGC2_GPIOx values, where "x" is replaced with the port
    // name (such as B).  The value of "x" should match the value of "x" for
    // FORCED_UPDATE_PORT.
    //
    // Depends on: ENABLE_UPDATE_CHECK
    // Exclusive of: None
    // Requries: None
    //
    //*****************************************************************************
    //#define FORCED_UPDATE_PERIPH    SYSCTL_RCGC2_GPIOB 
    #define FORCED_UPDATE_PERIPH    0x00000800 // for GPIOM
    
    //*****************************************************************************
    //
    // The GPIO port to check for a forced update.  This will be one of the
    // GPIO_PORTx_BASE values, where "x" is replaced with the port name (such as
    // B).  The value of "x" should match the value of "x" for
    // FORCED_UPDATE_PERIPH.
    //
    // Depends on: ENABLE_UPDATE_CHECK
    // Exclusive of: None
    // Requries: None
    //
    //*****************************************************************************
    #define FORCED_UPDATE_PORT      GPIO_PORTM_BASE
    
    //*****************************************************************************
    //
    // The pin to check for a forced update.  This is a value between 0 and 7.
    //
    // Depends on: ENABLE_UPDATE_CHECK
    // Exclusive of: None
    // Requries: None
    //
    //*****************************************************************************
    #define FORCED_UPDATE_PIN       0
    
    //*****************************************************************************
    //
    // The polarity of the GPIO pin that results in a forced update.  This value
    // should be 0 if the pin should be low and 1 if the pin should be high.
    //
    // Depends on: ENABLE_UPDATE_CHECK
    // Exclusive of: None
    // Requries: None
    //
    //*****************************************************************************
    #define FORCED_UPDATE_POLARITY  0
    
    //*****************************************************************************
    //
    // This enables a weak pull-up or pull-down for the GPIO pin used in a forced
    // update.  Only one of FORCED_UPDATE_WPU or FORCED_UPDATE_WPD should be
    // defined, or neither if a weak pull-up or pull-down is not required.
    //
    // Depends on: ENABLE_UPDATE_CHECK
    // Exclusive of: None
    // Requries: None
    //
    //*****************************************************************************
    #define FORCED_UPDATE_WPU
    //#define FORCED_UPDATE_WPD
    
    //*****************************************************************************
    //
    // This enables the use of the GPIO_LOCK mechanism for configuration of
    // protected GPIO pins (for example JTAG pins).  If this value is not defined,
    // the locking mechanism will not be used.  The only legal values for this
    // feature are GPIO_LOCK_KEY for Fury devices and GPIO_LOCK_KEY_DD for all
    // other devices except Sandstorm devices, which do not support this feature.
    //
    // Depends on: ENABLE_UPDATE_CHECK
    // Exclusive of: None
    // Requries: None
    //
    //*****************************************************************************
    //#define FORCED_UPDATE_KEY       GPIO_LOCK_KEY
    //#define FORCED_UPDATE_KEY       GPIO_LOCK_KEY_DD
    
    
    
    #define Delay(n) ROM_SysCtlDelay((ROM_SysCtlClockGet()/3000000)*n)
    
    
    //extern void CallApplication();
    
    uint32_t g_ui32Forced = 0;
    
    FATFS 		FatFs;
    //FIL 			FileObject;	
    
    //*****************************************************************************
    //
    //! Checks a GPIO for a forced update.
    //!
    //! This function checks the state of a GPIO to determine if a update is being
    //! requested.
    //!
    //! \return Returns a non-zero value if an update is being requested and zero
    //! otherwise.
    //
    //*****************************************************************************
    uint32_t
    CheckGPIOForceUpdate(void)
    {
        //
        // Enable the required GPIO module.
        //
        HWREG(SYSCTL_RCGCGPIO) |= FORCED_UPDATE_PERIPH;
    	
        //
        // Wait a while before accessing the peripheral.
        //
        Delay(3);
    
    #ifdef FORCED_UPDATE_KEY
        //
        // Unlock the GPIO Access.
        //
        HWREG(FORCED_UPDATE_PORT + GPIO_O_LOCK) = FORCED_UPDATE_KEY;
        HWREG(FORCED_UPDATE_PORT + GPIO_O_CR) = 1 << FORCED_UPDATE_PIN;
    #endif
    
        //
        // Enable the pin used to see if an update is being requested.
        //
        HWREG(FORCED_UPDATE_PORT + GPIO_O_DEN) |= 1 << FORCED_UPDATE_PIN;
    #ifdef FORCED_UPDATE_WPU
        //
        // Set the output drive strength.
        //
        HWREG(FORCED_UPDATE_PORT + GPIO_O_DR2R) |= 1 << FORCED_UPDATE_PIN;
    
        //
        // Enable the weak pull up.
        //
        HWREG(FORCED_UPDATE_PORT + GPIO_O_PUR) |= 1 << FORCED_UPDATE_PIN;
    
        //
        // Make sure that the analog mode select register is clear for this pin.
        //
        HWREG(FORCED_UPDATE_PORT + GPIO_O_AMSEL) &= ~(1 << FORCED_UPDATE_PIN);
    #endif
    #ifdef FORCED_UPDATE_WPD
        //
        // Set the output drive strength.
        //
        HWREG(FORCED_UPDATE_PORT + GPIO_O_DR2R) |= 1 << FORCED_UPDATE_PIN;
    
        //
        // Enable the weak pull down.
        //
        HWREG(FORCED_UPDATE_PORT + GPIO_O_PDR) |= 1 << FORCED_UPDATE_PIN;
    
        //
        // Make sure that the analog mode select register is clear for this pin.
        // This register only appears in DustDevil-class (and later) devices, but
        // is a harmless write on Sandstorm- and Fury-class devices.
        //
        HWREG(FORCED_UPDATE_PORT + GPIO_O_AMSEL) &= ~(1 << FORCED_UPDATE_PIN);
    #endif
    
    #ifdef FORCED_UPDATE_KEY
        //
        // Unlock the GPIO Access.
        //
        HWREG(FORCED_UPDATE_PORT + GPIO_O_LOCK) = FORCED_UPDATE_KEY;
        HWREG(FORCED_UPDATE_PORT + GPIO_O_CR) = 0;
    #endif
    
        //
        // Wait a while before reading the pin.
        //
        Delay(1000);
    
        //
        // Check the pin to see if an update is being requested.
        //
        if(HWREG(FORCED_UPDATE_PORT + (1 << (FORCED_UPDATE_PIN + 2))) ==
           (FORCED_UPDATE_POLARITY << FORCED_UPDATE_PIN))
        {
            //
            // Remember that this was a forced update.
            //
            g_ui32Forced = 1;
    
            return(1);
        }
    
        //
        // No update is being requested so return 0.
        //
        return(0);
    }
    
    
    //*****************************************************************************
    //
    //! Checks if an update is needed or is being requested.
    //!
    //! This function detects if an update is being requested or if there is no
    //! valid code presently located on the microcontroller.  This is used to tell
    //! whether or not to enter update mode.
    //!
    //! \return Returns a non-zero value if an update is needed or is being
    //! requested and zero otherwise.
    //
    //*****************************************************************************
    uint32_t
    CheckForceUpdate(void)
    {
    
        uint32_t *pui32App;
    
        //
        // See if the first location is 0xfffffffff or something that does not
        // look like a stack pointer, or if the second location is 0xffffffff or
        // something that does not look like a reset vector.
        //
        pui32App = (uint32_t *)APP_START_ADDRESS;
        if((pui32App[0] == 0xffffffff) ||
           ((pui32App[0] & 0xfff00000) != 0x20000000) ||
           (pui32App[1] == 0xffffffff) ||
           ((pui32App[1] & 0xfff00001) != 0x00000001))
        {
            return(1);
        }
    
        //
        // If simple GPIO checking is configured, determine whether or not to force
        // an update.
        //
        return(CheckGPIOForceUpdate());
    }
    
    //*****************************************************************************
    //
    //! Configures the microcontroller.
    //!
    //! This function configures the peripherals and GPIOs of the microcontroller,
    //! preparing it for use by the boot loader.  The interface that has been
    //! selected as the update port will be configured, and auto-baud will be
    //! performed if required.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    ConfigureDevice(void)
    {
        //
        // Since the crystal frequency was specified, enable the main oscillator
        // and clock the processor from it.
        //
    //    HWREG(SYSCTL_RCC) &= ~(SYSCTL_RCC_MOSCDIS);
    //    Delay(524288);
    //    HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) & ~(SYSCTL_RCC_OSCSRC_M)) |
    //                         SYSCTL_RCC_OSCSRC_MAIN);
    
    	  HWREG(SYSCTL_RCGCGPIO) &= ~FORCED_UPDATE_PERIPH;
    	
    //    ROM_SysCtlClockSet(SYSCTL_USE_OSC | SYSCTL_OSC_INT);//Enable for ROM_SysCtlDelay
     
    //    //
    //    // Configure SysTick for a 100Hz interrupt.  The FatFs driver wants a 10 ms
    //    // tick.
    //    //
    //    ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / 100);
    //    ROM_SysTickEnable();
    //    ROM_SysTickIntEnable();
    //		
    //		ROM_IntMasterEnable();
    }
    
    
    //*****************************************************************************
    //
    //! This function performs the update on the selected port.
    //!
    //! This function is called directly by the boot loader or it is called as a
    //! result of an update request from the application.
    //!
    //! \return Never returns.
    //
    //*****************************************************************************
    void
    Updater(void)
    {
    	FRESULT 	fResult;
    	
    	uint32_t addr, count, data;
    	
    	//fResult = f_mount(0, &FatFs);
    	fResult = pf_mount(&FatFs);
    
      if(fResult == FR_OK)
    	{
    		//fResult = f_open(&FileObject, "boot2.bin", FA_READ);
    		fResult = pf_open("boot2.bin");
    		
    		if(fResult == FR_OK)
    		{
    			//for(addr = APP_START_ADDRESS; addr < APP_START_ADDRESS + FileObject.fsize; addr += FLASH_PAGE_SIZE)
    			for(addr = APP_START_ADDRESS; addr < APP_START_ADDRESS + FatFs.fsize; addr += FLASH_PAGE_SIZE)
    			{
    					//
    					// Erase this block.
    					//
    					ROM_FlashErase(addr);
    			}
    
    			//for(addr = APP_START_ADDRESS; addr < APP_START_ADDRESS + FileObject.fsize; addr += 4)
    			for(addr = APP_START_ADDRESS; addr < APP_START_ADDRESS + FatFs.fsize; addr += 4)
    			{
    					//
    					// Write data to the flash 4 bytes at a time
    					//
    					//f_read(&FileObject, &data, 4, &count);
    					pf_read(&data, 4, &count);
    					ROM_FlashProgram(&data, addr, 4);
    			}
    		}
    	}
    	
    //	HWREG(NVIC_APINT) = (NVIC_APINT_VECTKEY | NVIC_APINT_SYSRESETREQ);
    	
    	while(1);
    }
    
    ////*****************************************************************************
    ////
    //// This is the handler for this SysTick interrupt.  FatFs requires a timer tick
    //// every 10 ms for internal timing purposes.
    ////
    ////*****************************************************************************
    //void
    //SysTick_Handler(void)
    //{
    //    //
    //    // Call the FatFs tick timer.
    //    //
    //    disk_timerproc();
    //}
    
    
    //void SVC_Handler (void)
    //{
    //	HWREG(NVIC_VTABLE) = 0;
    //  HWREG(NVIC_EN0) = 0xffffffff;
    //  HWREG(NVIC_EN1) = 0xffffffff;	
    //	ConfigureDevice();
    //	Updater();
    //	while(1);
    //}
    
    //int
    //main(void)
    //{
    //	uint32_t t = 213 ;
    //	
    //	t = ROM_SysCtlClockGet();	
    
    //	if (CheckForceUpdate())
    //	{
    //	 ConfigureDevice();
    //	 Updater();
    //	}
    //	else
    //	{
    //    ROM_SysTickIntDisable(); 
    //    ROM_SysTickDisable(); 
    //		ROM_IntMasterDisable();
    //		
    //    HWREG(NVIC_DIS0) = 0xffffffff;
    //    HWREG(NVIC_DIS1) = 0xffffffff;
    
    //		HWREG(NVIC_VTABLE) = APP_START_ADDRESS;
    //		
    //    (*((void (*)(void))(*(uint32_t *)(APP_START_ADDRESS+4))))(); 
    //	}
    //	 
    //	while(1);
    //}
    
    //*****************************************************************************
    //
    // Close the Doxygen group.
    //! @}
    //
    //*****************************************************************************
    

    start up script is

    ; <<< Use Configuration Wizard in Context Menu >>>
    ;******************************************************************************
    ;
    ; startup_rvmdk.S - Startup code for use with Keil's uVision.
    ;
    ; Copyright (c) 2013-2015 Texas Instruments Incorporated.  All rights reserved.
    ; Software License Agreement
    ; 
    ; Texas Instruments (TI) is supplying this software for use solely and
    ; exclusively on TI's microcontroller products. The software is owned by
    ; TI and/or its suppliers, and is protected under applicable copyright
    ; laws. You may not combine this software with "viral" open-source
    ; software in order to form a larger program.
    ; 
    ; THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    ; NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    ; NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    ; A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    ; CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    ; DAMAGES, FOR ANY REASON WHATSOEVER.
    ; 
    ; This is part of revision 2.1.2.111 of the DK-TM4C123G Firmware Package.
    ;
    ;******************************************************************************
    
    ;    include bl_config.inc
    ;_STACK_SIZE                     equ     128;0x00000100 ;48
    _APP_START_ADDRESS              equ     0x2800
    _VTABLE_START_ADDRESS           equ     0x2800
    	
    ;******************************************************************************
    ;
    ; A couple of defines that would normally be obtained from the appropriate C
    ; header file, but must be manually provided here since the Keil compiler does
    ; not have a mechanism for passing assembly source through the C preprocessor.
    ;
    ;******************************************************************************
    ;SYSCTL_RESC                     equ     0x400fe05c
    ;SYSCTL_RESC_MOSCFAIL            equ     0x00010000
    NVIC_VTABLE                     equ     0xe000ed08
    	
    ;******************************************************************************
    ;
    ; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
    ;
    ;******************************************************************************
    Stack   EQU     0x00000400
    
    ;******************************************************************************
    ;
    ; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
    ;
    ;******************************************************************************
    Heap    EQU     0x00000000
    
    ;******************************************************************************
    ;
    ; Allocate space for the stack.
    ;
    ;******************************************************************************
            AREA    STACK, NOINIT, READWRITE, ALIGN=3
    StackMem
            SPACE   Stack
    __initial_sp
    
    ;******************************************************************************
    ;
    ; Allocate space for the heap.
    ;
    ;******************************************************************************
            AREA    HEAP, NOINIT, READWRITE, ALIGN=3
    __heap_base
    HeapMem
            SPACE   Heap
    __heap_limit
    
    ;******************************************************************************
    ;
    ; Indicate that the code in this file preserves 8-byte alignment of the stack.
    ;
    ;******************************************************************************
            PRESERVE8
    
    ;******************************************************************************
    ;
    ; Place code into the reset code section.
    ;
    ;******************************************************************************
            AREA    RESET, CODE, READONLY
            THUMB
    
    ;******************************************************************************
    ;
    ; External declaration for the interrupt handler used by the application.
    ;
    ;******************************************************************************
    ;        EXTERN  SysTickHandler
    
    ;******************************************************************************
    ;
    ; The vector table.
    ;
    ;******************************************************************************
            EXPORT  __Vectors
    __Vectors
            DCD     StackMem + Stack            ; Top of Stack
            DCD     Reset_Handler               ; Reset Handler
            DCD     NmiSR                       ; NMI Handler
            DCD     FaultISR                    ; Hard Fault Handler
            DCD     IntDefaultHandler           ; The MPU fault handler
            DCD     IntDefaultHandler           ; The bus fault handler
            DCD     IntDefaultHandler           ; The usage fault handler
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     UpdateHandler           ; SVCall handler
            DCD     IntDefaultHandler           ; Debug monitor handler
            DCD     0                           ; Reserved
            DCD     IntDefaultHandler           ; The PendSV handler
            DCD     IntDefaultHandler           ; The SysTick handler
            DCD     IntDefaultHandler           ; GPIO Port A
            DCD     IntDefaultHandler           ; GPIO Port B
            DCD     IntDefaultHandler           ; GPIO Port C
            DCD     IntDefaultHandler           ; GPIO Port D
            DCD     IntDefaultHandler           ; GPIO Port E
            DCD     IntDefaultHandler           ; UART0 Rx and Tx
            DCD     IntDefaultHandler           ; UART1 Rx and Tx
            DCD     IntDefaultHandler           ; SSI0 Rx and Tx
            DCD     IntDefaultHandler           ; I2C0 Master and Slave
            DCD     IntDefaultHandler           ; PWM Fault
            DCD     IntDefaultHandler           ; PWM Generator 0
            DCD     IntDefaultHandler           ; PWM Generator 1
            DCD     IntDefaultHandler           ; PWM Generator 2
            DCD     IntDefaultHandler           ; Quadrature Encoder 0
            DCD     IntDefaultHandler           ; ADC Sequence 0
            DCD     IntDefaultHandler           ; ADC Sequence 1
            DCD     IntDefaultHandler           ; ADC Sequence 2
            DCD     IntDefaultHandler           ; ADC Sequence 3
            DCD     IntDefaultHandler           ; Watchdog timer
            DCD     IntDefaultHandler           ; Timer 0 subtimer A
            DCD     IntDefaultHandler           ; Timer 0 subtimer B
            DCD     IntDefaultHandler           ; Timer 1 subtimer A
            DCD     IntDefaultHandler           ; Timer 1 subtimer B
            DCD     IntDefaultHandler           ; Timer 2 subtimer A
            DCD     IntDefaultHandler           ; Timer 2 subtimer B
            DCD     IntDefaultHandler           ; Analog Comparator 0
            DCD     IntDefaultHandler           ; Analog Comparator 1
            DCD     IntDefaultHandler           ; Analog Comparator 2
            DCD     IntDefaultHandler           ; System Control (PLL, OSC, BO)
            DCD     IntDefaultHandler           ; FLASH Control
            DCD     IntDefaultHandler           ; GPIO Port F
            DCD     IntDefaultHandler           ; GPIO Port G
            DCD     IntDefaultHandler           ; GPIO Port H
            DCD     IntDefaultHandler           ; UART2 Rx and Tx
            DCD     IntDefaultHandler           ; SSI1 Rx and Tx
            DCD     IntDefaultHandler           ; Timer 3 subtimer A
            DCD     IntDefaultHandler           ; Timer 3 subtimer B
            DCD     IntDefaultHandler           ; I2C1 Master and Slave
            DCD     IntDefaultHandler           ; Quadrature Encoder 1
            DCD     IntDefaultHandler           ; CAN0
            DCD     IntDefaultHandler           ; CAN1
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     IntDefaultHandler           ; Hibernate
            DCD     IntDefaultHandler           ; USB0
            DCD     IntDefaultHandler           ; PWM Generator 3
            DCD     IntDefaultHandler           ; uDMA Software Transfer
            DCD     IntDefaultHandler           ; uDMA Error
            DCD     IntDefaultHandler           ; ADC1 Sequence 0
            DCD     IntDefaultHandler           ; ADC1 Sequence 1
            DCD     IntDefaultHandler           ; ADC1 Sequence 2
            DCD     IntDefaultHandler           ; ADC1 Sequence 3
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     IntDefaultHandler           ; GPIO Port J
            DCD     IntDefaultHandler           ; GPIO Port K
            DCD     IntDefaultHandler           ; GPIO Port L
            DCD     IntDefaultHandler           ; SSI2 Rx and Tx
            DCD     IntDefaultHandler           ; SSI3 Rx and Tx
            DCD     IntDefaultHandler           ; UART3 Rx and Tx
            DCD     IntDefaultHandler           ; UART4 Rx and Tx
            DCD     IntDefaultHandler           ; UART5 Rx and Tx
            DCD     IntDefaultHandler           ; UART6 Rx and Tx
            DCD     IntDefaultHandler           ; UART7 Rx and Tx
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     IntDefaultHandler           ; I2C2 Master and Slave
            DCD     IntDefaultHandler           ; I2C3 Master and Slave
            DCD     IntDefaultHandler           ; Timer 4 subtimer A
            DCD     IntDefaultHandler           ; Timer 4 subtimer B
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     IntDefaultHandler           ; Timer 5 subtimer A
            DCD     IntDefaultHandler           ; Timer 5 subtimer B
            DCD     IntDefaultHandler           ; Wide Timer 0 subtimer A
            DCD     IntDefaultHandler           ; Wide Timer 0 subtimer B
            DCD     IntDefaultHandler           ; Wide Timer 1 subtimer A
            DCD     IntDefaultHandler           ; Wide Timer 1 subtimer B
            DCD     IntDefaultHandler           ; Wide Timer 2 subtimer A
            DCD     IntDefaultHandler           ; Wide Timer 2 subtimer B
            DCD     IntDefaultHandler           ; Wide Timer 3 subtimer A
            DCD     IntDefaultHandler           ; Wide Timer 3 subtimer B
            DCD     IntDefaultHandler           ; Wide Timer 4 subtimer A
            DCD     IntDefaultHandler           ; Wide Timer 4 subtimer B
            DCD     IntDefaultHandler           ; Wide Timer 5 subtimer A
            DCD     IntDefaultHandler           ; Wide Timer 5 subtimer B
            DCD     IntDefaultHandler           ; FPU
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     IntDefaultHandler           ; I2C4 Master and Slave
            DCD     IntDefaultHandler           ; I2C5 Master and Slave
            DCD     IntDefaultHandler           ; GPIO Port M
            DCD     IntDefaultHandler           ; GPIO Port N
            DCD     IntDefaultHandler           ; Quadrature Encoder 2
            DCD     0                           ; Reserved
            DCD     0                           ; Reserved
            DCD     IntDefaultHandler           ; GPIO Port P (Summary or P0)
            DCD     IntDefaultHandler           ; GPIO Port P1
            DCD     IntDefaultHandler           ; GPIO Port P2
            DCD     IntDefaultHandler           ; GPIO Port P3
            DCD     IntDefaultHandler           ; GPIO Port P4
            DCD     IntDefaultHandler           ; GPIO Port P5
            DCD     IntDefaultHandler           ; GPIO Port P6
            DCD     IntDefaultHandler           ; GPIO Port P7
            DCD     IntDefaultHandler           ; GPIO Port Q (Summary or Q0)
            DCD     IntDefaultHandler           ; GPIO Port Q1
            DCD     IntDefaultHandler           ; GPIO Port Q2
            DCD     IntDefaultHandler           ; GPIO Port Q3
            DCD     IntDefaultHandler           ; GPIO Port Q4
            DCD     IntDefaultHandler           ; GPIO Port Q5
            DCD     IntDefaultHandler           ; GPIO Port Q6
            DCD     IntDefaultHandler           ; GPIO Port Q7
            DCD     IntDefaultHandler           ; GPIO Port R
            DCD     IntDefaultHandler           ; GPIO Port S
            DCD     IntDefaultHandler           ; PWM 1 Generator 0
            DCD     IntDefaultHandler           ; PWM 1 Generator 1
            DCD     IntDefaultHandler           ; PWM 1 Generator 2
            DCD     IntDefaultHandler           ; PWM 1 Generator 3
            DCD     IntDefaultHandler           ; PWM 1 Fault
    
    ;******************************************************************************
    ;
    ; This is the code that gets called when the processor first starts execution
    ; following a reset event.
    ;
    ;******************************************************************************
            ;EXPORT  Reset_Handler
    ;Reset_Handler
            ;;
            ;; Enable the floating-point unit.  This must be done here to handle the
            ;; case where main() uses floating-point and the function prologue saves
            ;; floating-point registers (which will fault if floating-point is not
            ;; enabled).  Any configuration of the floating-point unit using
            ;; DriverLib APIs must be done here prior to the floating-point unit
            ;; being enabled.
            ;;
            ;; Note that this does not use DriverLib since it might not be included
            ;; in this project.
            ;;
            ;MOVW    R0, #0xED88
            ;MOVT    R0, #0xE000
            ;LDR     R1, [R0]
            ;ORR     R1, #0x00F00000
            ;STR     R1, [R0]
    
            ;;
            ;; Call the C library enty point that handles startup.  This will copy
            ;; the .data section initializers from flash to SRAM and zero fill the
            ;; .bss section.
            ;;
            ;IMPORT  __main
            ;B       __main
    
    ;******************************************************************************
    ;
    ; This is the code that gets called when the processor receives a NMI.  This
    ; simply enters an infinite loop, preserving the system state for examination
    ; by a debugger.
    ;
    ;******************************************************************************
    NmiSR
            B       NmiSR
    
    ;******************************************************************************
    ;
    ; This is the code that gets called when the processor receives a fault
    ; interrupt.  This simply enters an infinite loop, preserving the system state
    ; for examination by a debugger.
    ;
    ;******************************************************************************
    FaultISR
            B       FaultISR
    
    ;******************************************************************************
    ;
    ; This is the code that gets called when the processor receives an unexpected
    ; interrupt.  This simply enters an infinite loop, preserving the system state
    ; for examination by a debugger.
    ;
    ;******************************************************************************
    IntDefaultHandler
            B       IntDefaultHandler
    
    
    
    ;******************************************************************************
    ;
    ; Initialize the processor by copying the boot loader from flash to SRAM, zero
    ; filling the .bss section, and moving the vector table to the beginning of
    ; SRAM.  The return address is modified to point to the SRAM copy of the boot
    ; loader instead of the flash copy, resulting in a branch to the copy now in
    ; SRAM.
    ;
    ;******************************************************************************
    	export  ProcessorInit
    ProcessorInit
    	;
    	; Copy the code image from flash to SRAM.
    	;
    	movs    r0, #0x0000
    	movs    r1, #0x0000
    	movt    r1, #0x2000
    	import  ||Image$$SRAM$$ZI$$Base||
    	ldr     r2, =||Image$$SRAM$$ZI$$Base||
    copy_loop
    		ldr     r3, [r0], #4
    		str     r3, [r1], #4
    		cmp     r1, r2
    		blt     copy_loop
    
    	;
    	; Zero fill the .bss section.
    	;
    	movs    r0, #0x0000
    	import  ||Image$$SRAM$$ZI$$Limit||
    	ldr     r2, =||Image$$SRAM$$ZI$$Limit||
    zero_loop
    		str     r0, [r1], #4
    		cmp     r1, r2
    		blt     zero_loop
    
    	;
    	; Set the vector table pointer to the beginning of SRAM.
    	;
    	movw    r0, #(NVIC_VTABLE & 0xffff)
    	movt    r0, #(NVIC_VTABLE >> 16)
    	movs    r1, #0x0000
    	movt    r1, #0x2000
    	str     r1, [r0]
    
    	;
    	; Return to the caller.
    	;
    	bx      lr
    
    ;******************************************************************************
    ;
    ; The reset handler, which gets called when the processor starts.
    ;
    ;******************************************************************************
    	export  Reset_Handler
    Reset_Handler
    
    	;
    	; Enable the floating-point unit.  This must be done here in case any
    	; later C functions use floating point.  Note that some toolchains will
    	; use the FPU registers for general workspace even if no explicit floating
    	; point data types are in use.
    	;
    	movw    r0, #0xED88
    	movt    r0, #0xE000
    	ldr     r1, [r0]
    	orr     r1, #0x00F00000
    	str     r1, [r0]
    
    	;
    	; Initialize the processor.
    	;
    	bl      ProcessorInit
    
    	;
    	; Branch to the SRAM copy of the reset handler.
    	;
    	ldr     pc, =Reset_Handler_In_SRAM
    
    
    ;******************************************************************************
    ;
    ; The update handler, which gets called when the application would like to
    ; start an update.
    ;
    ;******************************************************************************
    UpdateHandler
    	;
    	; Initialize the processor.
    	;
    	bl      ProcessorInit
    
    	;
    	; Branch to the SRAM copy of the update handler.
    	;
    	ldr     pc, =UpdateHandler_In_SRAM
    
    
    
    
    ;******************************************************************************
    ;
    ; Make sure the end of this section is aligned.
    ;
    ;******************************************************************************
            ALIGN
    
    ;******************************************************************************
    ;
    ; Some code in the normal code section for initializing the heap and stack.
    ;
    ;******************************************************************************
    		AREA    |.text|, CODE, READONLY
    
    Reset_Handler_In_SRAM
    	;
    	; See if an update should be performed.
    	;
    	import  CheckForceUpdate
    	bl      CheckForceUpdate
    	cbz     r0, CallApplication
    
    	;
    	; Configure the microcontroller.
    	;
    EnterBootLoader
    	import  ConfigureDevice
    	bl      ConfigureDevice
    
    	;
    	; Branch to the update handler.
    	;
    	import  Updater
    	b       Updater
    
    	;
    	; This is a second symbol to allow starting the application from the boot
    	; loader the linker may not like the perceived jump.
    	;
    	export StartApplication
    StartApplication
    	;
    	; Call the application via the reset handler in its vector table.  Load the
    	; address of the application vector table.
    	;
    CallApplication
    	;
    	; Copy the application's vector table to the target address if necessary.
    	; Note that incorrect boot loader configuration could cause this to
    	; corrupt the code!  Setting VTABLE_START_ADDRESS to 0x20000000 (the start
    	; of SRAM) is safe since this will use the same memory that the boot loader
    	; already uses for its vector table.  Great care will have to be taken if
    	; other addresses are to be used.
    	;
    	if (_APP_START_ADDRESS != _VTABLE_START_ADDRESS)
    	movw    r0, #(_VTABLE_START_ADDRESS & 0xffff)
    	if (_VTABLE_START_ADDRESS > 0xffff)
    	movt    r0, #(_VTABLE_START_ADDRESS >> 16)
    	endif
    	movw    r1, #(_APP_START_ADDRESS & 0xffff)
    	if (_APP_START_ADDRESS > 0xffff)
    	movt    r1, #(_APP_START_ADDRESS >> 16)
    	endif
    
    	;
    	; Calculate the end address of the vector table assuming that it has the
    	; maximum possible number of vectors.  We don't know how many the app has
    	; populated so this is the safest approach though it may copy some non
    	; vector data if the app table is smaller than the maximum.
    	;
    	movw    r2, #(70 * 4)
    	adds    r2, r2, r0
    VectorCopyLoop
    		ldr     r3, [r1], #4
    		str     r3, [r0], #4
    		cmp     r0, r2
    		blt     VectorCopyLoop
    	endif
    
    	;
    	; Set the vector table address to the beginning of the application.
    	;
    	movw    r0, #(_VTABLE_START_ADDRESS & 0xffff)
    	if (_VTABLE_START_ADDRESS > 0xffff)
    	movt    r0, #(_VTABLE_START_ADDRESS >> 16)
    	endif
    	movw    r1, #(NVIC_VTABLE & 0xffff)
    	movt    r1, #(NVIC_VTABLE >> 16)
    	str     r0, [r1]
    
    	;
    	; Load the stack pointer from the application's vector table.
    	;
    	if (_APP_START_ADDRESS != _VTABLE_START_ADDRESS)
    	movw    r0, #(_APP_START_ADDRESS & 0xffff)
    	if (_APP_START_ADDRESS > 0xffff)
    	movt    r0, #(_APP_START_ADDRESS >> 16)
    	endif
    	endif
    	ldr     sp, [r0]
    
    	;
    	; Load the initial PC from the application's vector table and branch to
    	; the application's entry point.
    	;
    	ldr     r0, [r0, #4]
    	bx      r0
    
    ;******************************************************************************
    ;
    ; The update handler, which gets called when the application would like to
    ; start an update.
    ;
    ;******************************************************************************
    UpdateHandler_In_SRAM
    	;
    	; Load the stack pointer from the vector table.
    	;
    	movs    r0, #0x0000
    	ldr     sp, [r0]
    
    	b       Updater
    
    ;;******************************************************************************
    ;;
    ;; The NMI handler.
    ;;
    ;;******************************************************************************
    	;if      :def:_ENABLE_MOSCFAIL_HANDLER
    ;NmiSR_In_SRAM
    	;;
    	;; Restore the stack frame.
    	;;
    	;mov     lr, r12
    	;stm     sp, {r4-r11}
    
    	;;
    	;; Save the link register.
    	;;
    	;mov     r9, lr
    
    	;;
    	;; Call the user-supplied low level hardware initialization function
    	;; if provided.
    	;;
    	;if      :def:_BL_HW_INIT_FN_HOOK
    	;bl      _BL_HW_INIT_FN_HOOK
    	;endif
    
    	;;
    	;; See if an update should be performed.
    	;;
    	;bl      CheckForceUpdate
    	;cbz     r0, EnterApplication
    
    		;;
    		;; Clear the MOSCFAIL bit in RESC.
    		;;
    		;movw    r0, #(SYSCTL_RESC & 0xffff)
    		;movt    r0, #(SYSCTL_RESC >> 16)
    		;ldr     r1, [r0]
    		;bic     r1, r1, #SYSCTL_RESC_MOSCFAIL
    		;str     r1, [r0]
    
    		;;
    		;; Fix up the PC on the stack so that the boot pin check is bypassed
    		;; (since it has already been performed).
    		;;
    		;ldr     r0, =EnterBootLoader
    		;bic     r0, #0x00000001
    		;str     r0, [sp, #0x18]
    
    		;;
    		;; Return from the NMI handler.  This will then start execution of the
    		;; boot loader.
    		;;
    		;bx      r9
    
    	;;
    	;; Restore the link register.
    	;;
    ;EnterApplication
    	;mov     lr, r9
    
    	;;
    	;; Copy the application's vector table to the target address if necessary.
    	;; Note that incorrect boot loader configuration could cause this to
    	;; corrupt the code!  Setting VTABLE_START_ADDRESS to 0x20000000 (the start
    	;; of SRAM) is safe since this will use the same memory that the boot loader
    	;; already uses for its vector table.  Great care will have to be taken if
    	;; other addresses are to be used.
    	;;
    	;if (_APP_START_ADDRESS != _VTABLE_START_ADDRESS)
    	;movw    r0, #(_VTABLE_START_ADDRESS & 0xffff)
    	;if (_VTABLE_START_ADDRESS > 0xffff)
    	;movt    r0, #(_VTABLE_START_ADDRESS >> 16)
    	;endif
    	;movw    r1, #(_APP_START_ADDRESS & 0xffff)
    	;if (_APP_START_ADDRESS > 0xffff)
    	;movt    r1, #(_APP_START_ADDRESS >> 16)
    	;endif
    
    	;;
    	;; Calculate the end address of the vector table assuming that it has the
    	;; maximum possible number of vectors.  We don't know how many the app has
    	;; populated so this is the safest approach though it may copy some non
    	;; vector data if the app table is smaller than the maximum.
    	;;
    	;movw    r2, #(70 * 4)
    	;adds    r2, r2, r0
    ;VectorCopyLoop2
    		;ldr     r3, [r1], #4
    		;str     r3, [r0], #4
    		;cmp     r0, r2
    		;blt     VectorCopyLoop2
    	;endif
    
    	;;
    	;; Set the application's vector table start address.  Typically this is the
    	;; application start address but in some cases an application may relocate
    	;; this so we can't assume that these two addresses are equal.
    	;;
    	;movw    r0, #(_VTABLE_START_ADDRESS & 0xffff)
    	;if (_VTABLE_START_ADDRESS > 0xffff)
    	;movt    r0, #(_VTABLE_START_ADDRESS >> 16)
    	;endif
    	;movw    r1, #(NVIC_VTABLE & 0xffff)
    	;movt    r1, #(NVIC_VTABLE >> 16)
    	;str     r0, [r1]
    
    	;;
    	;; Remove the NMI stack frame from the boot loader's stack.
    	;;
    	;ldmia   sp, {r4-r11}
    
    	;;
    	;; Get the application's stack pointer.
    	;;
    	;if (_APP_START_ADDRESS != _VTABLE_START_ADDRESS)
    	;movw    r0, #(_APP_START_ADDRESS & 0xffff)
    	;if (_APP_START_ADDRESS > 0xffff)
    	;movt    r0, #(_APP_START_ADDRESS >> 16)
    	;endif
    	;endif
    	;ldr     sp, [r0, #0x00]
    
    	;;
    	;; Fix up the NMI stack frame's return address to be the reset handler of
    	;; the application.
    	;;
    	;ldr     r10, [r0, #0x04]
    	;bic     r10, #0x00000001
    
    	;;
    	;; Store the NMI stack frame onto the application's stack.
    	;;
    	;stmdb   sp!, {r4-r11}
    
    	;;
    	;; Branch to the application's NMI handler.
    	;;
    	;ldr     r0, [r0, #0x08]
    	;bx      r0
    	;endif
    
    
    
    ;******************************************************************************
    ;
    ; The function expected of the C library startup code for defining the stack
    ; and heap memory locations.  For the C library version of the startup code,
    ; provide this function so that the C library initialization code can find out
    ; the location of the stack and heap.
    ;
    ;******************************************************************************
        IF :DEF: __MICROLIB
            EXPORT  __initial_sp
            EXPORT  __heap_base
            EXPORT  __heap_limit
        ELSE
            IMPORT  __use_two_region_memory
            EXPORT  __user_initial_stackheap
    __user_initial_stackheap
            LDR     R0, =HeapMem
            LDR     R1, =(StackMem + Stack)
            LDR     R2, =(HeapMem + Heap)
            LDR     R3, =StackMem
            BX      LR
        ENDIF
    
    ;******************************************************************************
    ;
    ; Make sure the end of this section is aligned.
    ;
    ;******************************************************************************
            ALIGN
    
    ;******************************************************************************
    ;
    ; Tell the assembler that we're done.
    ;
    ;******************************************************************************
            END
    

  • Hi Scott,
    If it's not too much trouble, you can share the project with me. I'm kind of lost about how to create one from zero.
    Thanks in advance
    Andrés
  • Sure. There's some extra files in there, but the project should be set up to work. 

    6607.Bootloader.zip