summaryrefslogtreecommitdiff
path: root/boot_loader/bl_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'boot_loader/bl_main.c')
-rw-r--r--boot_loader/bl_main.c913
1 files changed, 913 insertions, 0 deletions
diff --git a/boot_loader/bl_main.c b/boot_loader/bl_main.c
new file mode 100644
index 0000000..fbb7275
--- /dev/null
+++ b/boot_loader/bl_main.c
@@ -0,0 +1,913 @@
+//*****************************************************************************
+//
+// bl_main.c - The file holds the main control loop of the boot loader.
+//
+// Copyright (c) 2006-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 Tiva Firmware Development Package.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "inc/hw_gpio.h"
+#include "inc/hw_flash.h"
+#include "inc/hw_i2c.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_nvic.h"
+#include "inc/hw_ssi.h"
+#include "inc/hw_sysctl.h"
+#include "inc/hw_types.h"
+#include "inc/hw_uart.h"
+#include "bl_config.h"
+#include "boot_loader/bl_commands.h"
+#include "boot_loader/bl_decrypt.h"
+#include "boot_loader/bl_flash.h"
+#include "boot_loader/bl_hooks.h"
+#include "boot_loader/bl_i2c.h"
+#include "boot_loader/bl_packet.h"
+#include "boot_loader/bl_ssi.h"
+#include "boot_loader/bl_uart.h"
+#ifdef CHECK_CRC
+#include "boot_loader/bl_crc32.h"
+#endif
+
+//*****************************************************************************
+//
+// 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
+
+//*****************************************************************************
+//
+//! \addtogroup bl_main_api
+//! @{
+//
+//*****************************************************************************
+#if defined(I2C_ENABLE_UPDATE) || defined(SSI_ENABLE_UPDATE) || \
+ defined(UART_ENABLE_UPDATE) || defined(DOXYGEN)
+
+//*****************************************************************************
+//
+// A prototype for the function (in the startup code) for calling the
+// application.
+//
+//*****************************************************************************
+extern void CallApplication(uint32_t ui32Base);
+
+//*****************************************************************************
+//
+// A prototype for the function (in the startup code) for a predictable length
+// delay.
+//
+//*****************************************************************************
+extern void Delay(uint32_t ui32Count);
+
+//*****************************************************************************
+//
+// Holds the current status of the last command that was issued to the boot
+// loader.
+//
+//*****************************************************************************
+uint8_t g_ui8Status;
+
+//*****************************************************************************
+//
+// This holds the current remaining size in bytes to be downloaded.
+//
+//*****************************************************************************
+uint32_t g_ui32TransferSize;
+
+//*****************************************************************************
+//
+// This holds the total size of the firmware image being downloaded (if the
+// protocol in use provides this).
+//
+//*****************************************************************************
+#if (defined BL_PROGRESS_FN_HOOK) || (defined CHECK_CRC)
+uint32_t g_ui32ImageSize;
+#endif
+
+//*****************************************************************************
+//
+// This holds the current address that is being written to during a download
+// command.
+//
+//*****************************************************************************
+uint32_t g_ui32TransferAddress;
+#ifdef CHECK_CRC
+uint32_t g_ui32ImageAddress;
+#endif
+
+//*****************************************************************************
+//
+// This is the data buffer used during transfers to the boot loader.
+//
+//*****************************************************************************
+uint32_t g_pui32DataBuffer[BUFFER_SIZE];
+
+//*****************************************************************************
+//
+// This is an specially aligned buffer pointer to g_pui32DataBuffer to make
+// copying to the buffer simpler. It must be offset to end on an address that
+// ends with 3.
+//
+//*****************************************************************************
+uint8_t *g_pui8DataBuffer;
+
+//*****************************************************************************
+//
+// Converts a word from big endian to little endian. This macro uses compiler-
+// specific constructs to perform an inline insertion of the "rev" instruction,
+// which performs the byte swap directly.
+//
+//*****************************************************************************
+#if defined(ewarm)
+#include <intrinsics.h>
+#define SwapWord(x) __REV(x)
+#endif
+#if defined(codered) || defined(gcc) || defined(sourcerygxx)
+#define SwapWord(x) __extension__ \
+ ({ \
+ register uint32_t __ret, __inp = x; \
+ __asm__("rev %0, %1" : "=r" (__ret) : "r" (__inp)); \
+ __ret; \
+ })
+#endif
+#if defined(rvmdk) || defined(__ARMCC_VERSION)
+#define SwapWord(x) __rev(x)
+#endif
+#if defined(ccs)
+uint32_t
+SwapWord(uint32_t x)
+{
+ __asm(" rev r0, r0\n"
+ " bx lr\n"); // need this to make sure r0 is returned
+ return(x + 1); // return makes compiler happy - ignored
+}
+#endif
+
+//*****************************************************************************
+//
+//! 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)
+{
+#ifdef UART_ENABLE_UPDATE
+ uint32_t ui32ProcRatio;
+#endif
+
+#ifdef CRYSTAL_FREQ
+ //
+ // 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);
+#endif
+
+#ifdef I2C_ENABLE_UPDATE
+ //
+ // Enable the clocks to the I2C and GPIO modules.
+ //
+ HWREG(SYSCTL_RCGC2) |= SYSCTL_RCGC2_GPIOB;
+ HWREG(SYSCTL_RCGC1) |= SYSCTL_RCGC1_I2C0;
+
+ //
+ // Configure the GPIO pins for hardware control, open drain with pull-up,
+ // and enable them.
+ //
+ HWREG(GPIO_PORTB_BASE + GPIO_O_AFSEL) |= (1 << 7) | I2C_PINS;
+ HWREG(GPIO_PORTB_BASE + GPIO_O_DEN) |= (1 << 7) | I2C_PINS;
+ HWREG(GPIO_PORTB_BASE + GPIO_O_ODR) |= I2C_PINS;
+
+ //
+ // Enable the I2C Slave Mode.
+ //
+ HWREG(I2C0_BASE + I2C_O_MCR) = I2C_MCR_MFE | I2C_MCR_SFE;
+
+ //
+ // Setup the I2C Slave Address.
+ //
+ HWREG(I2C0_BASE + I2C_O_SOAR) = I2C_SLAVE_ADDR;
+
+ //
+ // Enable the I2C Slave Device on the I2C bus.
+ //
+ HWREG(I2C0_BASE + I2C_O_SCSR) = I2C_SCSR_DA;
+#endif
+
+#ifdef SSI_ENABLE_UPDATE
+ //
+ // Enable the clocks to the SSI and GPIO modules.
+ //
+ HWREG(SYSCTL_RCGC2) |= SYSCTL_RCGC2_GPIOA;
+ HWREG(SYSCTL_RCGC1) |= SYSCTL_RCGC1_SSI0;
+
+ //
+ // Make the pin be peripheral controlled.
+ //
+ HWREG(GPIO_PORTA_BASE + GPIO_O_AFSEL) |= SSI_PINS;
+ HWREG(GPIO_PORTA_BASE + GPIO_O_DEN) |= SSI_PINS;
+
+ //
+ // Set the SSI protocol to Motorola with default clock high and data
+ // valid on the rising edge.
+ //
+ HWREG(SSI0_BASE + SSI_O_CR0) = (SSI_CR0_SPH | SSI_CR0_SPO |
+ (DATA_BITS_SSI - 1));
+
+ //
+ // Enable the SSI interface in slave mode.
+ //
+ HWREG(SSI0_BASE + SSI_O_CR1) = SSI_CR1_MS | SSI_CR1_SSE;
+#endif
+
+#ifdef UART_ENABLE_UPDATE
+ //
+ // Enable the the clocks to the UART and GPIO modules.
+ //
+ HWREG(SYSCTL_RCGC2) |= SYSCTL_RCGC2_GPIOA;
+ HWREG(SYSCTL_RCGC1) |= SYSCTL_RCGC1_UART0;
+
+ //
+ // Keep attempting to sync until we are successful.
+ //
+#ifdef UART_AUTOBAUD
+ while(UARTAutoBaud(&ui32ProcRatio) < 0)
+ {
+ }
+#else
+ ui32ProcRatio = UART_BAUD_RATIO(UART_FIXED_BAUDRATE);
+#endif
+
+ //
+ // Set GPIO A0 and A1 as UART pins.
+ //
+ HWREG(GPIO_PORTA_BASE + GPIO_O_AFSEL) |= UART_PINS;
+
+ //
+ // Set the pin type.
+ //
+ HWREG(GPIO_PORTA_BASE + GPIO_O_DEN) |= UART_PINS;
+
+ //
+ // Set the baud rate.
+ //
+ HWREG(UART0_BASE + UART_O_IBRD) = ui32ProcRatio >> 6;
+ HWREG(UART0_BASE + UART_O_FBRD) = ui32ProcRatio & UART_FBRD_DIVFRAC_M;
+
+ //
+ // Set data length, parity, and number of stop bits to 8-N-1.
+ //
+ HWREG(UART0_BASE + UART_O_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN;
+
+ //
+ // Enable RX, TX, and the UART.
+ //
+ HWREG(UART0_BASE + UART_O_CTL) = (UART_CTL_UARTEN | UART_CTL_TXE |
+ UART_CTL_RXE);
+
+#ifdef UART_AUTOBAUD
+ //
+ // Need to ack in the UART case to hold it up while we get things set up.
+ //
+ AckPacket();
+#endif
+#endif
+}
+
+//*****************************************************************************
+//
+//! 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)
+{
+ uint32_t ui32Size, ui32Temp, ui32FlashSize;
+#ifdef CHECK_CRC
+ uint32_t ui32Retcode;
+#endif
+
+ //
+ // This ensures proper alignment of the global buffer so that the one byte
+ // size parameter used by the packetized format is easily skipped for data
+ // transfers.
+ //
+ g_pui8DataBuffer = ((uint8_t *)g_pui32DataBuffer) + 3;
+
+ //
+ // Insure that the COMMAND_SEND_DATA cannot be sent to erase the boot
+ // loader before the application is erased.
+ //
+ g_ui32TransferAddress = 0xffffffff;
+
+ //
+ // Read any data from the serial port in use.
+ //
+ while(1)
+ {
+ //
+ // Receive a packet from the port in use.
+ //
+ ui32Size = sizeof(g_pui32DataBuffer) - 3;
+ if(ReceivePacket(g_pui8DataBuffer, &ui32Size) != 0)
+ {
+ continue;
+ }
+
+ //
+ // The first byte of the data buffer has the command and determines
+ // the format of the rest of the bytes.
+ //
+ switch(g_pui8DataBuffer[0])
+ {
+ //
+ // This was a simple ping command.
+ //
+ case COMMAND_PING:
+ {
+ //
+ // This command always sets the status to COMMAND_RET_SUCCESS.
+ //
+ g_ui8Status = COMMAND_RET_SUCCESS;
+
+ //
+ // Just acknowledge that the command was received.
+ //
+ AckPacket();
+
+ //
+ // Go back and wait for a new command.
+ //
+ break;
+ }
+
+ //
+ // This command indicates the start of a download sequence.
+ //
+ case COMMAND_DOWNLOAD:
+ {
+ //
+ // Until determined otherwise, the command status is success.
+ //
+ g_ui8Status = COMMAND_RET_SUCCESS;
+
+ //
+ // A simple do/while(0) control loop to make error exits
+ // easier.
+ //
+ do
+ {
+ //
+ // See if a full packet was received.
+ //
+ if(ui32Size != 9)
+ {
+ //
+ // Indicate that an invalid command was received.
+ //
+ g_ui8Status = COMMAND_RET_INVALID_CMD;
+
+ //
+ // This packet has been handled.
+ //
+ break;
+ }
+
+ //
+ // Get the address and size from the command.
+ //
+ g_ui32TransferAddress = SwapWord(g_pui32DataBuffer[1]);
+ g_ui32TransferSize = SwapWord(g_pui32DataBuffer[2]);
+
+ //
+ // Depending upon the build options set, keep a copy of
+ // the original size and start address because we will need
+ // these later.
+ //
+#if (defined BL_PROGRESS_FN_HOOK) || (defined CHECK_CRC)
+ g_ui32ImageSize = g_ui32TransferSize;
+#endif
+#ifdef CHECK_CRC
+ g_ui32ImageAddress = g_ui32TransferAddress;
+#endif
+
+ //
+ // Check for a valid starting address and image size.
+ //
+ if(!BL_FLASH_AD_CHECK_FN_HOOK(g_ui32TransferAddress,
+ g_ui32TransferSize))
+ {
+ //
+ // Set the code to an error to indicate that the last
+ // command failed. This informs the updater program
+ // that the download command failed.
+ //
+ g_ui8Status = COMMAND_RET_INVALID_ADR;
+
+ //
+ // This packet has been handled.
+ //
+ break;
+ }
+
+
+ //
+ // Only erase the space that we need if we are not
+ // protecting the code, otherwise erase the entire flash.
+ //
+#ifdef FLASH_CODE_PROTECTION
+ ui32FlashSize = BL_FLASH_SIZE_FN_HOOK();
+#ifdef FLASH_RSVD_SPACE
+ if((ui32FlashSize - FLASH_RSVD_SPACE) !=
+ g_ui32TransferAddress)
+ {
+ ui32FlashSize -= FLASH_RSVD_SPACE;
+ }
+#endif
+#else
+ ui32FlashSize = g_ui32TransferAddress + g_ui32TransferSize;
+#endif
+
+ //
+ // Clear the flash access interrupt.
+ //
+ BL_FLASH_CL_ERR_FN_HOOK();
+
+ //
+ // Leave the boot loader present until we start getting an
+ // image.
+ //
+ for(ui32Temp = g_ui32TransferAddress;
+ ui32Temp < ui32FlashSize; ui32Temp += FLASH_PAGE_SIZE)
+ {
+ //
+ // Erase this block.
+ //
+ BL_FLASH_ERASE_FN_HOOK(ui32Temp);
+ }
+
+ //
+ // Return an error if an access violation occurred.
+ //
+ if(BL_FLASH_ERROR_FN_HOOK())
+ {
+ g_ui8Status = COMMAND_RET_FLASH_FAIL;
+ }
+ }
+ while(0);
+
+ //
+ // See if the command was successful.
+ //
+ if(g_ui8Status != COMMAND_RET_SUCCESS)
+ {
+ //
+ // Setting g_ui32TransferSize to zero makes
+ // COMMAND_SEND_DATA fail to accept any data.
+ //
+ g_ui32TransferSize = 0;
+ }
+
+ //
+ // Acknowledge that this command was received correctly. This
+ // does not indicate success, just that the command was
+ // received.
+ //
+ AckPacket();
+
+ //
+ // If we have a start notification hook function, call it
+ // now if everything is OK.
+ //
+#ifdef BL_START_FN_HOOK
+ if(g_ui32TransferSize)
+ {
+ BL_START_FN_HOOK();
+ }
+#endif
+
+ //
+ // Go back and wait for a new command.
+ //
+ break;
+ }
+
+ //
+ // This command indicates that control should be transferred to
+ // the specified address.
+ //
+ case COMMAND_RUN:
+ {
+ //
+ // Acknowledge that this command was received correctly. This
+ // does not indicate success, just that the command was
+ // received.
+ //
+ AckPacket();
+
+ //
+ // See if a full packet was received.
+ //
+ if(ui32Size != 5)
+ {
+ //
+ // Indicate that an invalid command was received.
+ //
+ g_ui8Status = COMMAND_RET_INVALID_CMD;
+
+ //
+ // This packet has been handled.
+ //
+ break;
+ }
+
+ //
+ // Get the address to which control should be transferred.
+ //
+ g_ui32TransferAddress = SwapWord(g_pui32DataBuffer[1]);
+
+ //
+ // This determines the size of the flash available on the
+ // device in use.
+ //
+ ui32FlashSize = BL_FLASH_SIZE_FN_HOOK();
+
+ //
+ // Test if the transfer address is valid for this device.
+ //
+ if(g_ui32TransferAddress >= ui32FlashSize)
+ {
+ //
+ // Indicate that an invalid address was specified.
+ //
+ g_ui8Status = COMMAND_RET_INVALID_ADR;
+
+ //
+ // This packet has been handled.
+ //
+ break;
+ }
+
+ //
+ // Make sure that the ACK packet has been sent.
+ //
+ FlushData();
+
+ //
+ // Reset and disable the peripherals used by the boot loader.
+ //
+#ifdef I2C_ENABLE_UPDATE
+ HWREG(SYSCTL_RCGC1) &= ~SYSCTL_RCGC1_I2C0;
+ HWREG(SYSCTL_SRCR1) = SYSCTL_SRCR1_I2C0;
+#endif
+#ifdef UART_ENABLE_UPDATE
+ HWREG(SYSCTL_RCGC1) &= ~SYSCTL_RCGC1_UART0;
+ HWREG(SYSCTL_SRCR1) = SYSCTL_SRCR1_UART0;
+#endif
+#ifdef SSI_ENABLE_UPDATE
+ HWREG(SYSCTL_RCGC1) &= ~SYSCTL_RCGC1_SSI0;
+ HWREG(SYSCTL_SRCR1) = SYSCTL_SRCR1_SSI0;
+#endif
+ HWREG(SYSCTL_SRCR1) = 0;
+
+ //
+ // Branch to the specified address. This should never return.
+ // If it does, very bad things will likely happen since it is
+ // likely that the copy of the boot loader in SRAM will have
+ // been overwritten.
+ //
+ ((void (*)(void))g_ui32TransferAddress)();
+
+ //
+ // In case this ever does return and the boot loader is still
+ // intact, simply reset the device.
+ //
+ 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)
+ {
+ }
+ }
+
+ //
+ // This command just returns the status of the last command that
+ // was sent.
+ //
+ case COMMAND_GET_STATUS:
+ {
+ //
+ // Acknowledge that this command was received correctly. This
+ // does not indicate success, just that the command was
+ // received.
+ //
+ AckPacket();
+
+ //
+ // Return the status to the updater.
+ //
+ SendPacket(&g_ui8Status, 1);
+
+ //
+ // Go back and wait for a new command.
+ //
+ break;
+ }
+
+ //
+ // This command is sent to transfer data to the device following
+ // a download command.
+ //
+ case COMMAND_SEND_DATA:
+ {
+ //
+ // Until determined otherwise, the command status is success.
+ //
+ g_ui8Status = COMMAND_RET_SUCCESS;
+
+ //
+ // If this is overwriting the boot loader then the application
+ // has already been erased so now erase the boot loader.
+ //
+ if(g_ui32TransferAddress == 0)
+ {
+ //
+ // Clear the flash access interrupt.
+ //
+ BL_FLASH_CL_ERR_FN_HOOK();
+
+ //
+ // Erase the boot loader.
+ //
+ for(ui32Temp = 0; ui32Temp < APP_START_ADDRESS;
+ ui32Temp += FLASH_PAGE_SIZE)
+ {
+ //
+ // Erase this block.
+ //
+ BL_FLASH_ERASE_FN_HOOK(ui32Temp);
+ }
+
+ //
+ // Return an error if an access violation occurred.
+ //
+ if(BL_FLASH_ERROR_FN_HOOK())
+ {
+ //
+ // Setting g_ui32TransferSize to zero makes
+ // COMMAND_SEND_DATA fail to accept any more data.
+ //
+ g_ui32TransferSize = 0;
+
+ //
+ // Indicate that the flash erase failed.
+ //
+ g_ui8Status = COMMAND_RET_FLASH_FAIL;
+ }
+ }
+
+ //
+ // Take one byte off for the command.
+ //
+ ui32Size = ui32Size - 1;
+
+ //
+ // Check if there are any more bytes to receive.
+ //
+ if(g_ui32TransferSize >= ui32Size)
+ {
+ //
+ // If we have been provided with a decryption hook function
+ // call it here.
+ //
+#ifdef BL_DECRYPT_FN_HOOK
+ BL_DECRYPT_FN_HOOK(g_pui8DataBuffer + 1, ui32Size);
+#endif
+
+ //
+ // Write this block of data to the flash
+ //
+ BL_FLASH_PROGRAM_FN_HOOK(g_ui32TransferAddress,
+ (uint8_t *) &g_pui32DataBuffer[1],
+ ((ui32Size + 3) & ~3));
+
+ //
+ // Return an error if an access violation occurred.
+ //
+ if(BL_FLASH_ERROR_FN_HOOK())
+ {
+ //
+ // Indicate that the flash programming failed.
+ //
+ g_ui8Status = COMMAND_RET_FLASH_FAIL;
+ }
+ else
+ {
+ //
+ // Now update the address to program.
+ //
+ g_ui32TransferSize -= ui32Size;
+ g_ui32TransferAddress += ui32Size;
+
+ //
+ // If a progress hook function has been provided, call
+ // it here.
+ //
+#ifdef BL_PROGRESS_FN_HOOK
+ BL_PROGRESS_FN_HOOK(g_ui32ImageSize -
+ g_ui32TransferSize,
+ g_ui32ImageSize);
+#endif
+
+#ifdef CHECK_CRC
+ //
+ // If we've reached the end, check the CRC in the
+ // image to determine whether or not we report an error
+ // back to the host.
+ //
+ if(g_ui32TransferSize == 0)
+ {
+ InitCRC32Table();
+ ui32Retcode = CheckImageCRC32(
+ (uint32_t *)g_ui32ImageAddress);
+
+ //
+ // Was the CRC good? We consider the CRC good if
+ // the header is found and the embedded CRC matches
+ // the calculated value or, if ENFORCE_CRC is not
+ // defined, if the header exists but is unpopulated.
+ //
+#ifdef ENFORCE_CRC
+ if(ui32Retcode == CHECK_CRC_OK)
+#else
+ if((ui32Retcode == CHECK_CRC_OK) ||
+ (ui32Retcode == CHECK_CRC_NO_LENGTH))
+#endif
+ {
+ //
+ // The calculated CRC didn't match the expected
+ // value or the image didn't contain an embedded
+ // CRC.
+ //
+ g_ui8Status = COMMAND_RET_SUCCESS;
+ }
+ else
+ {
+ //
+ // The calculated CRC agreed with the embedded
+ // value.
+ //
+ g_ui8Status = COMMAND_RET_CRC_FAIL;
+ }
+ }
+#endif
+ }
+ }
+ else
+ {
+ //
+ // This indicates that too much data is being sent to the
+ // device.
+ //
+ g_ui8Status = COMMAND_RET_INVALID_ADR;
+ }
+
+ //
+ // Acknowledge that this command was received correctly. This
+ // does not indicate success, just that the command was
+ // received.
+ //
+ AckPacket();
+
+ //
+ // If we have an end notification hook function, and we've
+ // reached the end, call it now.
+ //
+#ifdef BL_END_FN_HOOK
+ if(g_ui32TransferSize == 0)
+ {
+ BL_END_FN_HOOK();
+ }
+#endif
+
+ //
+ // Go back and wait for a new command.
+ //
+ break;
+ }
+
+ //
+ // This command is used to reset the device.
+ //
+ case COMMAND_RESET:
+ {
+ //
+ // Send out a one-byte ACK to ensure the byte goes back to the
+ // host before we reset everything.
+ //
+ AckPacket();
+
+ //
+ // Make sure that the ACK packet has been sent.
+ //
+ FlushData();
+
+ //
+ // 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)
+ {
+ }
+ }
+
+ //
+ // Just acknowledge the command and set the error to indicate that
+ // a bad command was sent.
+ //
+ default:
+ {
+ //
+ // Acknowledge that this command was received correctly. This
+ // does not indicate success, just that the command was
+ // received.
+ //
+ AckPacket();
+
+ //
+ // Indicate that a bad comand was sent.
+ //
+ g_ui8Status = COMMAND_RET_UNKNOWN_CMD;
+
+ //
+ // Go back and wait for a new command.
+ //
+ break;
+ }
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+#endif