diff options
| author | Yuval Adam <yuv.adm@gmail.com> | 2014-06-29 12:34:32 +0300 |
|---|---|---|
| committer | Yuval Adam <yuv.adm@gmail.com> | 2014-06-29 12:34:32 +0300 |
| commit | c3e4c9a25c2910d2d66d52215b3406b13d5b23d5 (patch) | |
| tree | added370d1e356901f8579f076e3263fb0464db7 /boards/dk-tm4c129x/usb_stick_update/usb_stick_update.c | |
| parent | 990090a4cc9070837d31e66b58d40f0c3d038741 (diff) | |
Add more board models
Diffstat (limited to 'boards/dk-tm4c129x/usb_stick_update/usb_stick_update.c')
| -rw-r--r-- | boards/dk-tm4c129x/usb_stick_update/usb_stick_update.c | 942 |
1 files changed, 942 insertions, 0 deletions
diff --git a/boards/dk-tm4c129x/usb_stick_update/usb_stick_update.c b/boards/dk-tm4c129x/usb_stick_update/usb_stick_update.c new file mode 100644 index 0000000..8281c2c --- /dev/null +++ b/boards/dk-tm4c129x/usb_stick_update/usb_stick_update.c @@ -0,0 +1,942 @@ +//*****************************************************************************
+//
+// usb_stick_update.c - Example to update flash from a USB memory stick.
+//
+// Copyright (c) 2013-2014 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.0.12573 of the DK-TM4C129X Firmware Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include "inc/hw_flash.h"
+#include "inc/hw_gpio.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_nvic.h"
+#include "inc/hw_sysctl.h"
+#include "inc/hw_types.h"
+#include "driverlib/gpio.h"
+#include "driverlib/pin_map.h"
+#include "driverlib/rom.h"
+#include "driverlib/rom_map.h"
+#include "driverlib/sysctl.h"
+#include "driverlib/udma.h"
+#include "usblib/usblib.h"
+#include "usblib/usbmsc.h"
+#include "usblib/host/usbhost.h"
+#include "usblib/host/usbhmsc.h"
+#include "simple_fs.h"
+
+//*****************************************************************************
+//
+//! \addtogroup example_list
+//! <h1>USB Memory Stick Updater (usb_stick_update)</h1>
+//!
+//! This example application behaves the same way as a boot loader. It resides
+//! at the beginning of flash, and will read a binary file from a USB memory
+//! stick and program it into another location in flash. Once the user
+//! application has been programmed into flash, this program will always start
+//! the user application until requested to load a new application.
+//!
+//! When this application starts, if there is a user application already in
+//! flash (at \b APP_START_ADDRESS), then it will just run the user application.
+//! It will attempt to load a new application from a USB memory stick under
+//! the following conditions:
+//!
+//! - no user application is present at \b APP_START_ADDRESS
+//! - the user application has requested an update by transferring control
+//! to the updater
+//! - the user holds down the eval board push button when the board is reset
+//!
+//! When this application is attempting to perform an update, it will wait
+//! forever for a USB memory stick to be plugged in. Once a USB memory stick
+//! is found, it will search the root directory for a specific file name, which
+//! is \e FIRMWARE.BIN by default. This file must be a binary image of the
+//! program you want to load (the .bin file), linked to run from the correct
+//! address, at \b APP_START_ADDRESS.
+//!
+//! The USB memory stick must be formatted as a FAT16 or FAT32 file system
+//! (the normal case), and the binary file must be located in the root
+//! directory. Other files can exist on the memory stick but they will be
+//! ignored.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Defines the number of times to call to check if the attached device is
+// ready.
+//
+//*****************************************************************************
+#define USBMSC_DRIVE_RETRY 4
+
+//*****************************************************************************
+//
+// The name of the binary firmware file on the USB stick. This is the user
+// application that will be searched for and loaded into flash if it is found.
+// Note that the name of the file must be 11 characters total, 8 for the base
+// name and 3 for the extension. If the actual file name has fewer characters
+// then it must be padded with spaces. This macro should not contain the dot
+// "." for the extension.
+//
+// Examples: firmware.bin --> "FIRMWAREBIN"
+// myfile.bn --> "MYFILE BN "
+//
+//*****************************************************************************
+#define USB_UPDATE_FILENAME "FIRMWAREBIN"
+
+//*****************************************************************************
+//
+// The size of the flash for this microcontroller.
+//
+//*****************************************************************************
+#define FLASH_SIZE (1 * 1024 * 1024)
+
+//*****************************************************************************
+//
+// The starting address for the application that will be loaded into flash
+// memory from the USB stick. This address must be high enough to be above
+// the USB stick updater, and must be on a 1K boundary.
+// Note that the application that will be loaded must also be linked to run
+// from this address.
+//
+//*****************************************************************************
+#define APP_START_ADDRESS 0x8000
+
+//*****************************************************************************
+//
+// A memory location and value that is used to indicate that the application
+// wants to force an update.
+//
+//*****************************************************************************
+#define FORCE_UPDATE_ADDR 0x20004000
+#define FORCE_UPDATE_VALUE 0x1234cdef
+
+//*****************************************************************************
+//
+// The prototype for the function that is used to call the user application.
+//
+//*****************************************************************************
+void CallApplication(uint_fast32_t ui32StartAddr);
+
+//*****************************************************************************
+//
+// The control table used by the uDMA controller. This table must be aligned
+// to a 1024 byte boundary. In this application uDMA is only used for USB,
+// so only the first 6 channels are needed.
+//
+//*****************************************************************************
+#if defined(ewarm)
+#pragma data_alignment=1024
+tDMAControlTable g_sDMAControlTable[6];
+#elif defined(ccs)
+#pragma DATA_ALIGN(g_sDMAControlTable, 1024)
+tDMAControlTable g_sDMAControlTable[6];
+#else
+tDMAControlTable g_sDMAControlTable[6] __attribute__ ((aligned(1024)));
+#endif
+
+//*****************************************************************************
+//
+// The global that holds all of the host drivers in use in the application.
+// In this case, only the MSC class is loaded.
+//
+//*****************************************************************************
+static tUSBHostClassDriver const * const g_ppHostClassDrivers[] =
+{
+ &g_sUSBHostMSCClassDriver
+};
+
+//*****************************************************************************
+//
+// This global holds the number of class drivers in the g_ppHostClassDrivers
+// list.
+//
+//*****************************************************************************
+#define NUM_CLASS_DRIVERS (sizeof(g_ppHostClassDrivers) / \
+ sizeof(g_ppHostClassDrivers[0]))
+
+//*****************************************************************************
+//
+// Hold the current state for the application.
+//
+//*****************************************************************************
+volatile enum
+{
+ //
+ // No device is present.
+ //
+ STATE_NO_DEVICE,
+
+ //
+ // Mass storage device is being enumerated.
+ //
+ STATE_DEVICE_ENUM,
+}
+g_eState;
+
+//*****************************************************************************
+//
+// The instance data for the MSC driver.
+//
+//*****************************************************************************
+tUSBHMSCInstance *g_psMSCInstance = 0;
+
+//*****************************************************************************
+//
+// The size of the host controller's memory pool in bytes.
+//
+//*****************************************************************************
+#define HCD_MEMORY_SIZE 128
+
+//*****************************************************************************
+//
+// The memory pool to provide to the Host controller driver.
+//
+//*****************************************************************************
+uint8_t g_pHCDPool[HCD_MEMORY_SIZE];
+
+//*****************************************************************************
+//
+// A buffer for holding sectors read from the storage device
+//
+//*****************************************************************************
+static uint8_t g_ui8SectorBuf[512];
+
+//*****************************************************************************
+//
+// Global to hold the clock rate. Set once read many.
+//
+//*****************************************************************************
+uint32_t g_ui32SysClock;
+
+//*****************************************************************************
+//
+// The error routine that is called if the driver library encounters an error.
+//
+//*****************************************************************************
+#ifdef DEBUG
+void
+__error__(char *pcFilename, uint32_t ui32Line)
+{
+}
+#endif
+
+//*****************************************************************************
+//
+// Read a sector from the USB mass storage device.
+//
+// \param ui32Sector is the sector to read from the connected USB mass storage
+// device (memory stick)
+// \param pui8Buf is a pointer to the buffer where the sector data should be
+// stored
+//
+// This is the application-specific implementation of a function to read
+// sectors from a storage device, in this case a USB mass storage device.
+// This function is called from the \e simple_fs.c file when it needs to read
+// data from the storage device.
+//
+// \return Non-zero if data was read from the device, 0 if no data was read.
+//
+//*****************************************************************************
+uint32_t
+SimpleFsReadMediaSector(uint_fast32_t ui32Sector, uint8_t *pui8Buf)
+{
+ //
+ // Return the requested sector from the connected USB mass storage
+ // device.
+ //
+ return(USBHMSCBlockRead(g_psMSCInstance, ui32Sector, pui8Buf, 1));
+}
+
+//*****************************************************************************
+//
+// This is the callback from the MSC driver.
+//
+// \param ui32Instance is the driver instance which is needed when communicating
+// with the driver.
+// \param ui32Event is one of the events defined by the driver.
+// \param pvData is a pointer to data passed into the initial call to register
+// the callback.
+//
+// This function handles callback events from the MSC driver. The only events
+// currently handled are the \b MSC_EVENT_OPEN and \b MSC_EVENT_CLOSE. This
+// allows the main routine to know when an MSC device has been detected and
+// enumerated and when an MSC device has been removed from the system.
+//
+// \return Returns \e true on success or \e false on failure.
+//
+//*****************************************************************************
+static void
+MSCCallback(tUSBHMSCInstance *psMSCInstance, uint32_t ui32Event, void *pvData)
+{
+ //
+ // Determine the event.
+ //
+ switch(ui32Event)
+ {
+ //
+ // Called when the device driver has successfully enumerated an MSC
+ // device.
+ //
+ case MSC_EVENT_OPEN:
+ {
+ //
+ // Proceed to the enumeration state.
+ //
+ g_eState = STATE_DEVICE_ENUM;
+ break;
+ }
+
+ //
+ // Called when the device driver has been unloaded due to error or
+ // the device is no longer present.
+ //
+ case MSC_EVENT_CLOSE:
+ {
+ //
+ // Go back to the "no device" state and wait for a new connection.
+ //
+ g_eState = STATE_NO_DEVICE;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// Read the application image from the file system and program it into flash.
+//
+// This function will attempt to open and read the firmware image file from
+// the mass storage device. If the file is found it will be programmed into
+// flash. The name of the file to be read is configured by the macro
+// \b USB_UPDATE_FILENAME. It will be programmed into flash starting at the
+// address specified by APP_START_ADDRESS.
+//
+// \return Zero if successful or non-zero if the file cannot be read or
+// programmed.
+//
+//*****************************************************************************
+uint32_t
+ReadAppAndProgram(void)
+{
+ uint_fast32_t ui32FlashEnd;
+ uint_fast32_t ui32FileSize;
+ uint_fast32_t ui32DataSize;
+ uint_fast32_t ui32Remaining;
+ uint_fast32_t ui32ProgAddr;
+ uint_fast32_t ui32SavedRegs[2];
+ volatile uint_fast32_t ui32Idx;
+ uint_fast32_t ui32DriveTimeout;
+
+ //
+ // Initialize the drive timeout.
+ //
+ ui32DriveTimeout = USBMSC_DRIVE_RETRY;
+
+ //
+ // Check to see if the mass storage device is ready. Some large drives
+ // take a while to be ready, so retry until they are ready.
+ //
+ while(USBHMSCDriveReady(g_psMSCInstance))
+ {
+ //
+ // Wait about 500ms before attempting to check if the
+ // device is ready again.
+ //
+ SysCtlDelay(g_ui32SysClock/(3*2));
+
+ //
+ // Decrement the retry count.
+ //
+ ui32DriveTimeout--;
+
+ //
+ // If the timeout is hit then return with a failure.
+ //
+ if(ui32DriveTimeout == 0)
+ {
+ return(1);
+ }
+ }
+
+ //
+ // Initialize the file system and return if error.
+ //
+ if(SimpleFsInit(g_ui8SectorBuf))
+ {
+ return(1);
+ }
+
+ //
+ // Attempt to open the firmware file, retrieving the file/image size.
+ // A file size of error means the file was not there, or there was an
+ // error.
+ //
+ ui32FileSize = SimpleFsOpen(USB_UPDATE_FILENAME);
+ if(ui32FileSize == 0)
+ {
+ return(1);
+ }
+
+ //
+ // Get the size of flash. This is the ending address of the flash.
+ // If reserved space is configured, then the ending address is reduced
+ // by the amount of the reserved block.
+ //
+ ui32FlashEnd = FLASH_SIZE;
+#ifdef FLASH_RSVD_SPACE
+ ui32FlashEnd -= FLASH_RSVD_SPACE;
+#endif
+
+ //
+ // If flash code protection is not used, then change the ending address
+ // to be the ending of the application image. This will be the highest
+ // flash page that will be erased and so only the necessary pages will
+ // be erased. If flash code protection is enabled, then all of the
+ // application area pages will be erased.
+ //
+#ifndef FLASH_CODE_PROTECTION
+ ui32FlashEnd = ui32FileSize + APP_START_ADDRESS;
+#endif
+
+ //
+ // Check to make sure the file size is not too large to fit in the flash.
+ // If it is too large, then return an error.
+ //
+ if((ui32FileSize + APP_START_ADDRESS) > ui32FlashEnd)
+ {
+ return(1);
+ }
+
+ //
+ // Enter a loop to erase all the requested flash pages beginning at the
+ // application start address (above the USB stick updater).
+ //
+ for(ui32Idx = APP_START_ADDRESS; ui32Idx < ui32FlashEnd; ui32Idx += 1024)
+ {
+ ROM_FlashErase(ui32Idx);
+ }
+
+ //
+ // Enter a loop to read sectors from the application image file and
+ // program into flash. Start at the user app start address (above the USB
+ // stick updater).
+ //
+ ui32ProgAddr = APP_START_ADDRESS;
+ ui32Remaining = ui32FileSize;
+ while(SimpleFsReadFileSector())
+ {
+ //
+ // Compute how much data was read from this sector and adjust the
+ // remaining amount.
+ //
+ ui32DataSize = ui32Remaining >= 512 ? 512 : ui32Remaining;
+ ui32Remaining -= ui32DataSize;
+
+ //
+ // Special handling for the first block of the application.
+ // This block contains as the first two location the application's
+ // initial stack pointer and instruction pointer. The USB updater
+ // relied on the values in these locations to determine if a valid
+ // application is present. When there is a valid application the
+ // updater runs the user application. Otherwise the updater attempts
+ // to load a new application.
+ // In order to prevent a partially programmed imaged (due to some
+ // error occurring while programming), the first two locations are
+ // not programmed until all of the rest of the image has been
+ // successfully loaded into the flash. This way if there is some error,
+ // the updater will detect that a user application is not present and
+ // will not attempt to run it.
+ //
+ // For the first block, do not program the first two word locations
+ // (8 bytes). These two words will be programmed later, after
+ // everything else.
+ //
+ if(ui32ProgAddr == APP_START_ADDRESS)
+ {
+ uint32_t *pui32Temp;
+
+ pui32Temp = (uint32_t *)g_ui8SectorBuf;
+ ui32SavedRegs[0] = pui32Temp[0];
+ ui32SavedRegs[1] = pui32Temp[1];
+
+ //
+ // Call the function to program a block of flash. Skip the first
+ // two words (8 bytes) since these contain the initial SP and PC.
+ //
+ ROM_FlashProgram((uint32_t *)&g_ui8SectorBuf[8],
+ ui32ProgAddr + 8,
+ ((ui32DataSize - 8) + 3) & ~3);
+ }
+
+ //
+ // All other blocks except the first block
+ //
+ else
+ {
+ //
+ // Call the function to program a block of flash. The length of the
+ // block passed to the flash function must be divisible by 4.
+ //
+ ROM_FlashProgram((uint32_t *)g_ui8SectorBuf, ui32ProgAddr,
+ (ui32DataSize + 3) & ~3);
+ }
+
+ //
+ // If there is more image to program, then update the programming
+ // address. Progress will continue to the next iteration of
+ // the while loop.
+ //
+ if(ui32Remaining)
+ {
+ ui32ProgAddr += ui32DataSize;
+ }
+
+ //
+ // Otherwise we are done programming so perform final steps.
+ // Program the first two words of the image that were saved earlier,
+ // and return a success indication.
+ //
+ else
+ {
+ ROM_FlashProgram((uint32_t *)ui32SavedRegs, APP_START_ADDRESS,
+ 8);
+
+ return(0);
+ }
+ }
+
+ //
+ // If we make it here, that means that an attempt to read a sector of
+ // data from the device was not successful. That means that the complete
+ // user app has not been programmed into flash, so just return an error
+ // indication.
+ //
+ return(1);
+}
+
+//*****************************************************************************
+//
+// This is the main routine for performing an update from a mass storage
+// device.
+//
+// This function forms the main loop of the USB stick updater. It polls for
+// a USB mass storage device to be connected, Once a device is connected
+// it will attempt to read a firmware image from the device and load it into
+// flash.
+//
+// \return None.
+//
+//*****************************************************************************
+void
+UpdaterUSB(void)
+{
+ //
+ // Loop forever, running the USB host driver.
+ //
+ while(1)
+ {
+ USBHCDMain();
+
+ //
+ // Check for a state change from the USB driver.
+ //
+ switch(g_eState)
+ {
+ //
+ // This state means that a mass storage device has been
+ // plugged in and enumerated.
+ //
+ case STATE_DEVICE_ENUM:
+ {
+ //
+ // Attempt to read the application image from the storage
+ // device and load it into flash memory.
+ //
+ if(ReadAppAndProgram())
+ {
+ //
+ // There was some error reading or programming the app,
+ // so reset the state to no device which will cause a
+ // wait for a new device to be plugged in.
+ //
+ g_eState = STATE_NO_DEVICE;
+ }
+ else
+ {
+ //
+ // User app load and programming was successful, so reboot
+ // the micro. Perform a software reset request. This
+ // will cause the microcontroller to reset; no further
+ // code will be executed.
+ //
+ HWREG(NVIC_APINT) = NVIC_APINT_VECTKEY |
+ NVIC_APINT_SYSRESETREQ;
+
+ //
+ // The microcontroller should have reset, so this should
+ // never be reached. Just in case, loop forever.
+ //
+ while(1)
+ {
+ }
+ }
+ break;
+ }
+
+ //
+ // This state means that there is no device present, so just
+ // do nothing until something is plugged in.
+ //
+ case STATE_NO_DEVICE:
+ {
+ break;
+ }
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// Configure the USB controller and power the bus.
+//
+// This function configures the USB controller for host operation.
+// It is assumed that the main system clock has been configured at this point.
+//
+// \return None.
+//
+//*****************************************************************************
+void
+ConfigureUSBInterface(void)
+{
+ //
+ // Enable the uDMA controller and set up the control table base.
+ // This is required by usblib.
+ //
+ SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
+ SysCtlDelay(80);
+ uDMAEnable();
+ uDMAControlBaseSet(g_sDMAControlTable);
+
+ //
+ // Enable the USB controller.
+ //
+ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
+
+ //
+ // Set the USB pins to be controlled by the USB controller.
+ //
+ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
+ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
+ ROM_GPIOPinConfigure(GPIO_PD6_USB0EPEN);
+ ROM_GPIOPinTypeUSBDigital(GPIO_PORTD_BASE, GPIO_PIN_6);
+ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
+ ROM_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_6 | GPIO_PIN_7);
+ ROM_GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
+
+ //
+ // Register the host class driver
+ //
+ USBHCDRegisterDrivers(0, g_ppHostClassDrivers, NUM_CLASS_DRIVERS);
+
+ //
+ // Open an instance of the mass storage class driver.
+ //
+ g_psMSCInstance = USBHMSCDriveOpen(0, MSCCallback);
+
+ //
+ // Initialize the power configuration. This sets the power enable signal
+ // to be active high and does not enable the power fault.
+ //
+ USBHCDPowerConfigInit(0, USBHCD_VBUS_AUTO_HIGH | USBHCD_VBUS_FILTER);
+
+ //
+ // Force the USB mode to host with no callback on mode changes since
+ // there should not be any.
+ //
+ USBStackModeSet(0, eUSBModeForceHost, 0);
+
+ //
+ // Wait 10ms for the pin to go low.
+ //
+ SysCtlDelay(g_ui32SysClock/100);
+
+ //
+ // Initialize the host controller.
+ //
+ USBHCDInit(0, g_pHCDPool, HCD_MEMORY_SIZE);
+}
+
+//*****************************************************************************
+//
+// Generic configuration is handled in this function.
+//
+// This function is called by the start up code to perform any configuration
+// necessary before calling the update routine. It is responsible for setting
+// the system clock to the expected rate and setting flash programming
+// parameters prior to calling ConfigureUSBInterface() to set up the USB
+// hardware.
+//
+// \return None.
+//
+//*****************************************************************************
+void
+UpdaterMain(void)
+{
+ //
+ // Make sure NVIC points at the correct vector table.
+ //
+ HWREG(NVIC_VTABLE) = 0;
+
+ //
+ // Run from the PLL at 120 MHz.
+ //
+ g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
+ SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
+ SYSCTL_CFG_VCO_480), 120000000);
+
+ //
+ // Enable lazy stacking for interrupt handlers. This allows floating-point
+ // instructions to be used within interrupt handlers, but at the expense of
+ // extra stack usage.
+ //
+ ROM_FPULazyStackingEnable();
+
+ //
+ // Configure the USB interface and power the bus.
+ //
+ ConfigureUSBInterface();
+
+ //
+ // Call the updater function. This will attempt to load a new image
+ // into flash from a USB memory stick.
+ //
+ UpdaterUSB();
+}
+
+//*****************************************************************************
+//
+// Main entry point for the USB stick update example.
+//
+// This function will check to see if a flash update should be performed from
+// the USB memory stick, or if the user application should just be run without
+// any update.
+//
+// The following checks are made, any of which mean that an update should be
+// performed:
+// - the PC and SP for the user app do not appear to be valid
+// - a memory location contains a certain value, meaning the user app wants
+// to force an update
+// - the user button on the eval board is being pressed, meaning the user wants
+// to force an update even if there is a valid user app in memory
+//
+// If any of the above checks are true, then that means that an update should
+// be attempted. The USB stick updater will then wait for a USB stick to be
+// plugged in, and once it is look for a firmware update file.
+//
+// If none of the above checks are true, then the user application that is
+// already in flash is run and no update is performed.
+//
+// \return None.
+//
+//*****************************************************************************
+int
+main(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))
+ {
+ //
+ // App starting stack pointer or PC is not valid, so force an update.
+ //
+ UpdaterMain();
+ }
+
+ //
+ // Check to see if the application has requested an update
+ //
+ if(HWREG(FORCE_UPDATE_ADDR) == FORCE_UPDATE_VALUE)
+ {
+ HWREG(FORCE_UPDATE_ADDR) = 0;
+ UpdaterMain();
+ }
+
+ //
+ // Enable the GPIO input for the SEL button.
+ //
+ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
+ ROM_GPIODirModeSet(GPIO_PORTP_BASE, GPIO_PIN_1, GPIO_DIR_MODE_IN);
+ MAP_GPIOPadConfigSet(GPIO_PORTP_BASE, GPIO_PIN_1, GPIO_STRENGTH_2MA,
+ GPIO_PIN_TYPE_STD_WPU);
+
+ //
+ // Check if the button is pressed, if so then force an update.
+ //
+ if(ROM_GPIOPinRead(GPIO_PORTP_BASE, GPIO_PIN_1) == 0)
+ {
+ UpdaterMain();
+ }
+
+ //
+ // If we get to here that means that none of the conditions that should
+ // cause an update are true. Therefore, call the application.
+ //
+ CallApplication(APP_START_ADDRESS);
+}
+
+//*****************************************************************************
+//
+// This function is called from the application to request an update. The
+// address of this function is stored in the SVC vector at offset 0x2C, so
+// the user application can call it by using a statement like this:
+//
+// (*((void (*)(void))(*(uint32_t *)0x2c)))();
+//
+//*****************************************************************************
+void
+AppForceUpdate(void)
+{
+ //
+ // Set a value in a memory location to indicate that the app requests
+ // an update. Then cause the processor to reset.
+ //
+ HWREG(FORCE_UPDATE_ADDR) = FORCE_UPDATE_VALUE;
+ HWREG(NVIC_APINT) = NVIC_APINT_VECTKEY | NVIC_APINT_SYSRESETREQ;
+}
+
+//*****************************************************************************
+//
+// This function is used to call the user application. It will set the NVIC
+// to point at the user app's vector table, load up the user app's stack
+// pointer, and then jump to the application.
+//
+// This function must be programmed in assembly since it needs to directly
+// manipulate the value in the stack pointer, and because it needs to perform
+// a direct branch to the user app and not a function call (bl).
+//
+//*****************************************************************************
+#if defined(codered) || defined(gcc) || defined(sourcerygxx)
+void __attribute__((naked))
+CallApplication(uint_fast32_t ui32StartAddr)
+{
+ //
+ // Set the vector table to the beginning of the app in flash.
+ //
+ HWREG(NVIC_VTABLE) = ui32StartAddr;
+
+ //
+ // Load the stack pointer from the application's vector table.
+ //
+ __asm(" ldr r1, [r0]\n"
+ " mov sp, r1");
+
+ //
+ // Load the initial PC from the application's vector table and branch to
+ // the application's entry point.
+ //
+ __asm(" ldr r0, [r0, #4]\n"
+ " bx r0\n");
+}
+#elif defined(ewarm)
+void
+CallApplication(uint_fast32_t ui32StartAddr)
+{
+ //
+ // Set the vector table to the beginning of the app in flash.
+ //
+ HWREG(NVIC_VTABLE) = ui32StartAddr;
+
+ //
+ // Load the stack pointer from the application's vector table.
+ //
+ __asm(" ldr r1, [r0]\n"
+ " mov sp, r1");
+
+ //
+ // Load the initial PC from the application's vector table and branch to
+ // the application's entry point.
+ //
+ __asm(" ldr r0, [r0, #4]\n"
+ " bx r0\n");
+}
+#elif defined(rvmdk) || defined(__ARMCC_VERSION)
+__asm void
+CallApplication(uint_fast32_t ui32StartAddr)
+{
+ //
+ // Set the vector table address to the beginning of the application.
+ //
+ ldr r1, =0xe000ed08
+ str r0, [r1]
+
+ //
+ // Load the stack pointer from the application's vector table.
+ //
+ ldr r1, [r0]
+ mov sp, r1
+
+ //
+ // Load the initial PC from the application's vector table and branch to
+ // the application's entry point.
+ //
+ ldr r0, [r0, #4]
+ bx r0
+}
+#elif defined(ccs)
+void
+CallApplication(uint_fast32_t ui32StartAddr)
+{
+ //
+ // Set the vector table to the beginning of the app in flash.
+ //
+ HWREG(NVIC_VTABLE) = ui32StartAddr;
+
+ //
+ // Load the stack pointer from the application's vector table.
+ //
+ __asm(" ldr r1, [r0]\n"
+ " mov sp, r1\n");
+
+ //
+ // Load the initial PC from the application's vector table and branch to
+ // the application's entry point.
+ //
+ __asm(" ldr r0, [r0, #4]\n"
+ " bx r0\n");
+}
+#else
+#error Undefined compiler!
+#endif
+
|
