diff options
Diffstat (limited to 'boot_loader')
42 files changed, 16981 insertions, 0 deletions
diff --git a/boot_loader/bl_autobaud.c b/boot_loader/bl_autobaud.c new file mode 100644 index 0000000..1600c71 --- /dev/null +++ b/boot_loader/bl_autobaud.c @@ -0,0 +1,279 @@ +//*****************************************************************************
+//
+// bl_autobaud.c - Automatic baud rate detection code.
+//
+// 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 "inc/hw_gpio.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_nvic.h"
+#include "inc/hw_types.h"
+#include "bl_config.h"
+#include "boot_loader/bl_uart.h"
+
+//*****************************************************************************
+//
+// If using auto-baud, make sure that the data buffer is large enough.
+//
+//*****************************************************************************
+#if defined(UART_ENABLE_UPDATE) && defined(UART_AUTOBAUD) && (BUFFER_SIZE < 20)
+#error ERROR: BUFFER_SIZE must be >= 20!
+#endif
+
+//*****************************************************************************
+//
+//! \addtogroup bl_autobaud_api
+//! @{
+//
+//*****************************************************************************
+#if defined(UART_ENABLE_UPDATE) && defined(UART_AUTOBAUD) || defined(DOXYGEN)
+
+//*****************************************************************************
+//
+// This define holds the multiplier for the pulse detection algorithm. The
+// value is used to generate a fractional difference detection of
+// 1 / PULSE_DETECTION_MULT.
+//
+//*****************************************************************************
+#define PULSE_DETECTION_MULT 3
+
+//*****************************************************************************
+//
+// This define holds the minimum number of edges to successfully sync to a
+// pattern of 2 bytes.
+//
+//*****************************************************************************
+#define MIN_EDGE_COUNT 18
+
+//*****************************************************************************
+//
+// This global holds the number of edges that have been stored in the global
+// buffer g_pui32DataBuffer.
+//
+//*****************************************************************************
+static volatile uint32_t g_ui32TickIndex;
+
+//*****************************************************************************
+//
+// The data buffer that is used for receiving packets is used to hold the edge
+// times during auto-baud. The buffer is not used for receiving packets while
+// auto-baud is in progress, so this does not present problems.
+//
+//*****************************************************************************
+extern uint32_t g_pui32DataBuffer[];
+
+//*****************************************************************************
+//
+//! Handles the UART Rx GPIO interrupt.
+//!
+//! When an edge is detected on the UART Rx pin, this function is called to
+//! save the time of the edge. These times are later used to determine the
+//! ratio of the UART baud rate to the processor clock rate.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+GPIOIntHandler(void)
+{
+ uint32_t ui32Temp;
+
+ //
+ // Clear the GPIO interrupt source.
+ //
+ HWREG(GPIO_PORTA_BASE + GPIO_O_ICR) = UART_RX;
+
+ //
+ // While we still have space in our buffer, store the current system tick
+ // count and return from interrupt.
+ //
+ if(g_ui32TickIndex < 20)
+ {
+ ui32Temp = HWREG(NVIC_ST_CURRENT);
+ g_pui32DataBuffer[g_ui32TickIndex++] = ui32Temp;
+ }
+}
+
+//*****************************************************************************
+//
+//! Performs auto-baud on the UART port.
+//!
+//! \param pui32Ratio is the ratio of the processor's crystal frequency to the
+//! baud rate being used by the UART port for communications.
+//!
+//! This function attempts to synchronize to the updater program that is trying
+//! to communicate with the boot loader. The UART port is monitored for edges
+//! using interrupts. Once enough edges are detected, the boot loader
+//! determines the ratio of baud rate and crystal frequency needed to program
+//! the UART.
+//!
+//! \return Returns a value of 0 to indicate that this call successfully
+//! synchronized with the other device communicating over the UART, and a
+//! negative value to indicate that this function did not successfully
+//! synchronize with the other UART device.
+//
+//*****************************************************************************
+int
+UARTAutoBaud(uint32_t *pui32Ratio)
+{
+ int32_t i32Pulse, i32ValidPulses, i32Temp, i32Total;
+ volatile int32_t i32Delay;
+
+ //
+ // Configure and enable SysTick. Set the reload value to the maximum;
+ // there are only 24 bits in the register but loading 32 bits of ones is
+ // more efficient.
+ //
+ HWREG(NVIC_ST_RELOAD) = 0xffffffff;
+ HWREG(NVIC_ST_CTRL) = NVIC_ST_CTRL_CLK_SRC | NVIC_ST_CTRL_ENABLE;
+
+ //
+ // Reset the counters that control the pulse detection.
+ //
+ i32ValidPulses = 0;
+ i32Total = 0;
+ g_ui32TickIndex = 0;
+
+ //
+ // Set the pad(s) for standard push-pull operation.
+ //
+ HWREG(GPIO_PORTA_BASE + GPIO_O_PUR) |= UART_RX;
+ HWREG(GPIO_PORTA_BASE + GPIO_O_DEN) |= UART_RX;
+
+ //
+ // Interrupt on both edges.
+ //
+ HWREG(GPIO_PORTA_BASE + GPIO_O_IBE) = UART_RX;
+
+ //
+ // Clear out all of the gpio interrupts in this register.
+ //
+ HWREG(GPIO_PORTA_BASE + GPIO_O_ICR) = UART_RX;
+
+ //
+ // Enable the GPIO pin corresponding to the UART RX pin.
+ //
+ HWREG(GPIO_PORTA_BASE + GPIO_O_IM) = UART_RX;
+
+ //
+ // Enable GPIOA Interrupt.
+ //
+ HWREG(NVIC_EN0) = 1;
+
+ //
+ // Wait for MIN_EDGE_COUNT to pass to collect enough edges.
+ //
+ while(g_ui32TickIndex < MIN_EDGE_COUNT)
+ {
+ }
+
+ //
+ // Disable GPIOA Interrupt.
+ //
+ HWREG(NVIC_DIS0) = 1;
+
+ //
+ // Calculate the pulse widths from the array of tick times.
+ //
+ for(i32Pulse = 0; i32Pulse < (MIN_EDGE_COUNT - 1); i32Pulse++)
+ {
+ i32Temp = (((int32_t)g_pui32DataBuffer[i32Pulse] -
+ (int32_t)g_pui32DataBuffer[i32Pulse + 1]) & 0x00ffffff);
+ g_pui32DataBuffer[i32Pulse] = i32Temp;
+ }
+
+ //
+ // This loops handles checking for consecutive pulses that have pulse
+ // widths that are within an acceptable margin.
+ //
+ for(i32Pulse = 0; i32Pulse < (MIN_EDGE_COUNT - 1); i32Pulse++)
+ {
+ //
+ // Calculate the absolute difference between two consecutive pulses.
+ //
+ i32Temp = (int32_t)g_pui32DataBuffer[i32Pulse];
+ i32Temp -= (int32_t)g_pui32DataBuffer[i32Pulse + 1];
+ if(i32Temp < 0)
+ {
+ i32Temp *= -1;
+ }
+
+ //
+ // This pulse detection code uses the following algorithm:
+ // If the following is true then we have consecutive acceptable pulses
+ // abs(Pulse[n] - Pulse[n + 1]) < Pulse[n + 1] / PULSE_DETECTION_MULT
+ // or
+ // PULSE_DETECTION_MULT * abs(Pulse[n] - Pulse[n + 1]) < Pulse[n + 1]
+ //
+ if((i32Temp * PULSE_DETECTION_MULT) <
+ (int32_t)g_pui32DataBuffer[i32Pulse + 1])
+ {
+ i32Total += (int32_t)g_pui32DataBuffer[i32Pulse];
+ i32ValidPulses++;
+ }
+ else
+ {
+ i32ValidPulses = 0;
+ i32Total = 0;
+ }
+
+ //
+ // Once we have 7 pulses calculate the ratio needed to program the
+ // UART.
+ //
+ if(i32ValidPulses == 7)
+ {
+ //
+ // Add in the last pulse and calculate the ratio.
+ //
+ i32Total += (int32_t)g_pui32DataBuffer[i32Pulse];
+ *pui32Ratio = i32Total >> 1;
+
+ //
+ // Wait for at least 2 UART clocks since we only wait for 18 of 20
+ // that are coming from the host. If we don't wait, we can turn
+ // on the UART while the last two pulses come down.
+ //
+ for(i32Delay = i32Total; i32Delay; i32Delay--)
+ {
+ }
+
+ //
+ // Indicate a successful auto baud operation.
+ //
+ return(0);
+ }
+ }
+
+ //
+ // Automatic baud rate detection failed.
+ //
+ return(-1);
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+#endif
diff --git a/boot_loader/bl_can.c b/boot_loader/bl_can.c new file mode 100644 index 0000000..9cf5c0b --- /dev/null +++ b/boot_loader/bl_can.c @@ -0,0 +1,1403 @@ +//*****************************************************************************
+//
+// bl_can.c - Functions to transfer data via the CAN port.
+//
+// Copyright (c) 2008-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 "inc/hw_can.h"
+#include "inc/hw_gpio.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_nvic.h"
+#include "inc/hw_flash.h"
+#include "inc/hw_sysctl.h"
+#include "inc/hw_types.h"
+#include "inc/hw_uart.h"
+#include "bl_config.h"
+#include "boot_loader/bl_can.h"
+#include "boot_loader/bl_can_timing.h"
+#include "boot_loader/bl_check.h"
+#include "boot_loader/bl_crystal.h"
+#include "boot_loader/bl_flash.h"
+#include "boot_loader/bl_hooks.h"
+#include "boot_loader/bl_uart.h"
+
+//*****************************************************************************
+//
+//! \addtogroup bl_can_api
+//! @{
+//
+//*****************************************************************************
+#if defined(CAN_ENABLE_UPDATE) || defined(DOXYGEN)
+
+//*****************************************************************************
+//
+// The results that can be returned by the CAN APIs.
+//
+//*****************************************************************************
+#define CAN_CMD_SUCCESS 0x00
+#define CAN_CMD_FAIL 0x01
+
+//*****************************************************************************
+//
+// Macros used to generate correct pin definitions.
+//
+//*****************************************************************************
+#define CAN_RX_PIN_M (1 << CAN_RX_PIN)
+#define CAN_TX_PIN_M (1 << CAN_TX_PIN)
+
+//*****************************************************************************
+//
+// Convenience macros for accessing CAN registers.
+//
+//*****************************************************************************
+#define CANRegWrite(ui32Address, ui32Value) \
+ HWREG(ui32Address) = ui32Value
+
+#define CANRegRead(ui32Address) \
+ HWREG(ui32Address)
+
+//*****************************************************************************
+//
+// The message object number and index to the local message object memory to
+// use when accessing the messages.
+//
+//*****************************************************************************
+#define MSG_OBJ_BCAST_RX_ID 1
+#define MSG_OBJ_BCAST_TX_ID 2
+
+//*****************************************************************************
+//
+// A prototype for the function (in the startup code) for calling the
+// application.
+//
+//*****************************************************************************
+extern void StartApplication(void);
+
+//*****************************************************************************
+//
+// A prototype for the function (in the startup code) for a predictable length
+// delay.
+//
+//*****************************************************************************
+extern void Delay(uint32_t ui32Count);
+
+//*****************************************************************************
+//
+// Holds the current address to write to when data is received via the Send
+// Data Command.
+//
+//*****************************************************************************
+static uint32_t g_ui32TransferAddress;
+
+//*****************************************************************************
+//
+// Holds the remaining bytes expected to be received.
+//
+//*****************************************************************************
+static uint32_t g_ui32TransferSize;
+
+//*****************************************************************************
+//
+// The buffer used to receive data from the update.
+//
+//*****************************************************************************
+static uint8_t g_pui8CommandBuffer[8];
+
+//*****************************************************************************
+//
+// These globals are used to store the first two words to prevent a partial
+// image from being booted.
+//
+//*****************************************************************************
+static uint32_t g_ui32StartValues[2];
+static uint32_t g_ui32StartSize;
+static uint32_t g_ui32StartAddress;
+
+//*****************************************************************************
+//
+// The active interface when the UART bridge is enabled.
+//
+//*****************************************************************************
+#ifdef CAN_UART_BRIDGE
+static uint32_t g_ui32Interface;
+#define IFACE_UNKNOWN 0
+#define IFACE_CAN 1
+#define IFACE_UART 2
+#endif
+
+//*****************************************************************************
+//
+//! Initializes the CAN controller after reset.
+//!
+//! After reset, the CAN controller is left in the disabled state. However,
+//! the memory used for message objects contains undefined values and must be
+//! cleared prior to enabling the CAN controller the first time. This prevents
+//! unwanted transmission or reception of data before the message objects are
+//! configured. This function must be called before enabling the controller
+//! the first time.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+CANInit(void)
+{
+ int iMsg;
+
+ //
+ // Place CAN controller in init state, regardless of previous state. This
+ // will put the controller in idle, and allow the message object RAM to be
+ // programmed.
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_CTL, CAN_CTL_INIT | CAN_CTL_CCE);
+
+ //
+ // Loop through to program all 32 message objects
+ //
+ for(iMsg = 1; iMsg <= 32; iMsg++)
+ {
+ //
+ // Wait for busy bit to clear.
+ //
+ while(CANRegRead(CAN0_BASE + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
+ {
+ }
+
+ //
+ // Clear the message value bit in the arbitration register. This
+ // indicates the message is not valid and is a "safe" condition to
+ // leave the message object.
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_IF1CMSK,
+ CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_ARB | CAN_IF1CMSK_CONTROL);
+ CANRegWrite(CAN0_BASE + CAN_O_IF1ARB2, 0);
+ CANRegWrite(CAN0_BASE + CAN_O_IF1MCTL, 0);
+
+ //
+ // Initiate programming of the message object
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_IF1CRQ, iMsg);
+ }
+
+ //
+ // Acknowledge any pending status interrupts.
+ //
+ CANRegRead(CAN0_BASE + CAN_O_STS);
+}
+
+//*****************************************************************************
+//
+//! This function configures the message object used to receive commands.
+//!
+//! This function configures the message object used to receive all firmware
+//! update messages. This will not actually read the data from the message it
+//! is used to prepare the message object to receive the data when it is sent.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+CANMessageSetRx(void)
+{
+ uint16_t ui16CmdMaskReg;
+ uint16_t ui16MaskReg[2];
+ uint16_t ui16ArbReg[2];
+ uint16_t ui16MsgCtrl;
+
+ //
+ // Wait for busy bit to clear
+ //
+ while(CANRegRead(CAN0_BASE + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
+ {
+ }
+
+ //
+ // This is always a write to the Message object as this call is setting a
+ // message object. This call will also always set all size bits so it sets
+ // both data bits. The call will use the CONTROL register to set control
+ // bits so this bit needs to be set as well.
+ //
+ // Set the MASK bit so that this gets transferred to the Message Object.
+ // Set the Arb bit so that this gets transferred to the Message object.
+ //
+ ui16CmdMaskReg = (CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_DATAA |
+ CAN_IF1CMSK_DATAB | CAN_IF1CMSK_CONTROL |
+ CAN_IF1CMSK_MASK | CAN_IF1CMSK_ARB);
+
+ //
+ // Set the UMASK bit to enable using the mask register.
+ // Set the data length since this is set for all transfers. This is also a
+ // single transfer and not a FIFO transfer so set EOB bit.
+ //
+ ui16MsgCtrl = CAN_IF1MCTL_UMASK | CAN_IF1MCTL_EOB;
+
+ //
+ // Configure the Mask Registers.
+ //
+ //
+ // Set the 29 bits of Identifier mask that were requested.
+ //
+ ui16MaskReg[0] = (uint16_t)LM_API_UPD;
+
+ //
+ // If the caller wants to filter on the extended ID bit then set it.
+ //
+ ui16MaskReg[1] =
+ (uint16_t)(CAN_IF1MSK2_MXTD | (LM_API_UPD >> 16));
+
+ //
+ // Set the 29 bit version of the Identifier for this message object.
+ // Mark the message as valid and set the extended ID bit.
+ //
+ ui16ArbReg[0] = LM_API_UPD & CAN_IF1ARB1_ID_M;
+ ui16ArbReg[1] = (((LM_API_UPD >> 16) & CAN_IF1ARB2_ID_M) |
+ (CAN_IF1ARB2_MSGVAL | CAN_IF1ARB2_XTD));
+
+ //
+ // Write out the registers to program the message object.
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_IF1CMSK, ui16CmdMaskReg);
+ CANRegWrite(CAN0_BASE + CAN_O_IF1MSK1, ui16MaskReg[0]);
+ CANRegWrite(CAN0_BASE + CAN_O_IF1MSK2, ui16MaskReg[1]);
+ CANRegWrite(CAN0_BASE + CAN_O_IF1ARB1, ui16ArbReg[0]);
+ CANRegWrite(CAN0_BASE + CAN_O_IF1ARB2, ui16ArbReg[1]);
+ CANRegWrite(CAN0_BASE + CAN_O_IF1MCTL, ui16MsgCtrl);
+
+ //
+ // Transfer the message object to the message object specific by
+ // MSG_OBJ_BCAST_RX_ID.
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_IF1CRQ,
+ MSG_OBJ_BCAST_RX_ID & CAN_IF1CRQ_MNUM_M);
+}
+
+//*****************************************************************************
+//
+//! This function reads data from the receive message object.
+//!
+//! \param pui8Data is a pointer to the buffer to store the data read from the
+//! CAN controller.
+//! \param pui32MsgID is a pointer to the ID that was received with the data.
+//!
+//! This function will reads and acknowledges the data read from the message
+//! object used to receive all CAN firmware update messages. It will also
+//! return the message identifier as this holds the API number that was
+//! attached to the data. This message identifier should be one of the
+//! LM_API_UPD_* definitions.
+//!
+//! \return The number of valid bytes returned in the \e pui8Data buffer or
+//! 0xffffffff if data was overwritten in the buffer.
+//
+//*****************************************************************************
+static uint32_t
+CANMessageGetRx(uint8_t *pui8Data, uint32_t *pui32MsgID)
+{
+ uint16_t ui16CmdMaskReg;
+ uint16_t ui16ArbReg0, ui16ArbReg1;
+ uint16_t ui16MsgCtrl;
+ uint32_t ui32Bytes;
+ uint16_t *pui16Data;
+
+ //
+ // This is always a read to the Message object as this call is setting a
+ // message object.
+ // Clear a pending interrupt and new data in a message object.
+ //
+ ui16CmdMaskReg = (CAN_IF2CMSK_DATAA | CAN_IF2CMSK_DATAB |
+ CAN_IF1CMSK_CONTROL | CAN_IF2CMSK_CLRINTPND |
+ CAN_IF2CMSK_ARB);
+
+ //
+ // Set up the request for data from the message object.
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_IF2CMSK, ui16CmdMaskReg);
+
+ //
+ // Transfer the message object to the message object specific by
+ // MSG_OBJ_BCAST_RX_ID.
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_IF2CRQ,
+ MSG_OBJ_BCAST_RX_ID & CAN_IF1CRQ_MNUM_M);
+
+ //
+ // Wait for busy bit to clear
+ //
+ while(CANRegRead(CAN0_BASE + CAN_O_IF2CRQ) & CAN_IF1CRQ_BUSY)
+ {
+ }
+
+ //
+ // Read out the IF Registers.
+ //
+ ui16ArbReg0 = CANRegRead(CAN0_BASE + CAN_O_IF2ARB1);
+ ui16ArbReg1 = CANRegRead(CAN0_BASE + CAN_O_IF2ARB2);
+ ui16MsgCtrl = CANRegRead(CAN0_BASE + CAN_O_IF2MCTL);
+
+ //
+ // Set the 29 bit version of the Identifier for this message object.
+ //
+ *pui32MsgID = ((ui16ArbReg1 & CAN_IF1ARB2_ID_M) << 16) | ui16ArbReg0;
+
+ //
+ // See if there is new data available.
+ //
+ if((ui16MsgCtrl & (CAN_IF1MCTL_NEWDAT | CAN_IF1MCTL_MSGLST)) ==
+ CAN_IF1MCTL_NEWDAT)
+ {
+ //
+ // Get the amount of data needed to be read.
+ //
+ ui32Bytes = ui16MsgCtrl & CAN_IF1MCTL_DLC_M;
+
+ //
+ // Read out the data from the CAN registers 16 bits at a time.
+ //
+ pui16Data = (uint16_t *)pui8Data;
+
+ pui16Data[0] = CANRegRead(CAN0_BASE + CAN_O_IF2DA1);
+ pui16Data[1] = CANRegRead(CAN0_BASE + CAN_O_IF2DA2);
+ pui16Data[2] = CANRegRead(CAN0_BASE + CAN_O_IF2DB1);
+ pui16Data[3] = CANRegRead(CAN0_BASE + CAN_O_IF2DB2);
+
+ //
+ // Now clear out the new data flag.
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_IF2CMSK, CAN_IF1CMSK_NEWDAT);
+
+ //
+ // Transfer the message object to the message object specific by
+ // MSG_OBJ_BCAST_RX_ID.
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_IF2CRQ, MSG_OBJ_BCAST_RX_ID);
+
+ //
+ // Wait for busy bit to clear
+ //
+ while(CANRegRead(CAN0_BASE + CAN_O_IF2CRQ) & CAN_IF2CRQ_BUSY)
+ {
+ }
+ }
+ else
+ {
+ //
+ // Data was lost so inform the caller.
+ //
+ ui32Bytes = 0xffffffff;
+ }
+ return(ui32Bytes);
+}
+
+//*****************************************************************************
+//
+//! This function sends data using the transmit message object.
+//!
+//! \param ui32Id is the ID to use with this message.
+//! \param pui8Data is a pointer to the buffer with the data to be sent.
+//! \param ui32Size is the number of bytes to send and should not be more than
+//! 8 bytes.
+//!
+//! This function will reads and acknowledges the data read from the message
+//! object used to receive all CAN firmware update messages. It will also
+//! return the message identifier as this holds the API number that was
+//! attached to the data. This message identifier should be one of the
+//! LM_API_UPD_* definitions.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+CANMessageSetTx(uint32_t ui32Id, const uint8_t *pui8Data, uint32_t ui32Size)
+{
+ uint16_t ui16CmdMaskReg;
+ uint16_t ui16ArbReg0, ui16ArbReg1;
+ uint16_t ui16MsgCtrl;
+ uint16_t *pui16Data;
+
+ //
+ // Wait for busy bit to clear
+ //
+ while(CANRegRead(CAN0_BASE + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
+ {
+ }
+
+ //
+ // This is always a write to the Message object as this call is setting a
+ // message object. This call will also always set all size bits so it sets
+ // both data bits. The call will use the CONTROL register to set control
+ // bits so this bit needs to be set as well.
+ //
+ ui16CmdMaskReg = (CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_DATAA |
+ CAN_IF1CMSK_DATAB | CAN_IF1CMSK_CONTROL |
+ CAN_IF1CMSK_ARB);
+
+ //
+ // Set the 29 bit version of the Identifier for this message object.
+ //
+ ui16ArbReg0 = ui32Id & CAN_IF1ARB1_ID_M;
+
+ //
+ // Mark the message as valid and set the extended ID bit.
+ //
+ ui16ArbReg1 = (((ui32Id >> 16) & CAN_IF1ARB2_ID_M) |
+ (CAN_IF1ARB2_DIR | CAN_IF1ARB2_MSGVAL | CAN_IF1ARB2_XTD));
+
+ //
+ // Set the TXRQST bit and the reset the rest of the register.
+ // Set the data length since this is set for all transfers. This is also a
+ // single transfer and not a FIFO transfer so set EOB bit.
+ //
+ //
+ ui16MsgCtrl = (CAN_IF1MCTL_TXRQST | CAN_IF1MCTL_EOB |
+ (ui32Size & CAN_IF1MCTL_DLC_M));
+
+ pui16Data = (uint16_t *)pui8Data;
+
+ //
+ // Write the data out to the CAN Data registers if needed.
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_IF1DA1, pui16Data[0]);
+ CANRegWrite(CAN0_BASE + CAN_O_IF1DA2, pui16Data[1]);
+ CANRegWrite(CAN0_BASE + CAN_O_IF1DB1, pui16Data[2]);
+ CANRegWrite(CAN0_BASE + CAN_O_IF1DB2, pui16Data[3]);
+
+ //
+ // Write out the registers to program the message object.
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_IF1CMSK, ui16CmdMaskReg);
+ CANRegWrite(CAN0_BASE + CAN_O_IF1ARB1, ui16ArbReg0);
+ CANRegWrite(CAN0_BASE + CAN_O_IF1ARB2, ui16ArbReg1);
+ CANRegWrite(CAN0_BASE + CAN_O_IF1MCTL, ui16MsgCtrl);
+
+ //
+ // Transfer the message object to the message object specifiec by
+ // MSG_OBJ_BCAST_RX_ID.
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_IF1CRQ,
+ (MSG_OBJ_BCAST_TX_ID) & CAN_IF1CRQ_MNUM_M);
+}
+
+//*****************************************************************************
+//
+//! Configures the CAN interface.
+//!
+//! \param ui32SetTiming determines if the CAN bit timing should be configured.
+//!
+//! This function configures the CAN controller, preparing it for use by
+//! the boot loader. If the \e ui32SetTiming parameter is 0, the bit timing
+//! for the CAN bus will be left alone. This occurs when the boot loader was
+//! entered from a running application that already has configured the timing
+//! for the system. When \e ui32SetTiming is non-zero the bit timing will be
+//! set to the defaults defined in the <tt>bl_config.h</tt> file in the
+//! project.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+ConfigureCANInterface(uint32_t ui32SetTiming)
+{
+ //
+ // Reset the state of all the message object and the state of the CAN
+ // module to a known state.
+ //
+ CANInit();
+
+ //
+ // If a device identifier was specified then this was due to an update from
+ // a running CAN application so don't change the CAN bit timing.
+ //
+ if(ui32SetTiming != 0)
+ {
+ //
+ // Set the bit fields of the bit timing register according to the
+ // parms.
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_BIT, CAN_BIT_TIMING);
+
+ //
+ // Set the divider upper bits in the extension register.
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_BRPE, 0);
+ }
+
+ //
+ // Take the CAN0 device out of INIT state.
+ //
+ CANRegWrite(CAN0_BASE + CAN_O_CTL, 0);
+
+ //
+ // Configure the broadcast receive message object.
+ //
+ CANMessageSetRx();
+}
+
+//*****************************************************************************
+//
+// Reads the next packet that is sent to the boot loader.
+//
+//*****************************************************************************
+static uint32_t
+PacketRead(uint8_t *pui8Data, uint32_t *pui32Size)
+{
+ uint32_t ui32MsgID;
+
+#ifdef CAN_UART_BRIDGE
+ uint32_t ui32Size, ui32Length, ui32Mode, ui32Char;
+ uint8_t pui8Buffer[12];
+
+ //
+ // Initialize the size and length of the packet.
+ //
+ ui32Length = 0;
+ ui32Size = 0;
+
+ //
+ // If no interface has been determined then wait for either CAN or UART
+ // data until either responds.
+ //
+ if(g_ui32Interface == IFACE_UNKNOWN)
+ {
+ //
+ // Wait for CAN or UART data.
+ //
+ while((CANRegRead(CAN0_BASE + CAN_O_NWDA1) == 0) &&
+ ((HWREG(UART0_BASE + UART_O_FR) & UART_FR_RXFE) == UART_FR_RXFE))
+ {
+ }
+
+ //
+ // If the UART FIFO was empty then the loop exited due to a CAN
+ // message.
+ //
+ if((HWREG(UART0_BASE + UART_O_FR) & UART_FR_RXFE) == UART_FR_RXFE)
+ {
+ g_ui32Interface = IFACE_CAN;
+ }
+ else
+ {
+ //
+ // The UART FIFO was not empty so the UART interface was used.
+ //
+ g_ui32Interface = IFACE_UART;
+ }
+ }
+
+ //
+ // Read a data packet from the CAN controller.
+ //
+ if(g_ui32Interface == IFACE_CAN)
+ {
+#endif
+ //
+ // Wait until a packet has been received.
+ //
+ while(CANRegRead(CAN0_BASE + CAN_O_NWDA1) == 0)
+ {
+ }
+
+ //
+ // Read the packet.
+ //
+ *pui32Size = CANMessageGetRx(pui8Data, &ui32MsgID);
+#ifdef CAN_UART_BRIDGE
+ }
+ else
+ {
+ //
+ // Read a data packet from the UART controller.
+ //
+ ui32Mode = 0;
+
+ while(1)
+ {
+ //
+ // Wait until a char is available.
+ //
+ while(HWREG(UART0_BASE + UART_O_FR) & UART_FR_RXFE)
+ {
+ }
+
+ //
+ // Now get the char.
+ //
+ ui32Char = HWREG(UART0_BASE + UART_O_DR);
+
+ if(ui32Char == 0xff)
+ {
+ ui32Mode = 1;
+ ui32Length = 0;
+ }
+ else if(ui32Mode == 1)
+ {
+ if(ui32Char > 12)
+ {
+ ui32Mode = 0;
+ }
+ else
+ {
+ ui32Size = ui32Char;
+ ui32Mode = 2;
+ }
+ }
+ else if(ui32Mode == 3)
+ {
+ if(ui32Char == 0xfe)
+ {
+ pui8Buffer[ui32Length++] = 0xff;
+ ui32Mode = 2;
+ }
+ else if(ui32Char == 0xfd)
+ {
+ pui8Buffer[ui32Length++] = 0xfe;
+ ui32Mode = 2;
+ }
+ else
+ {
+ ui32Mode = 0;
+ }
+ }
+ else if(ui32Mode == 2)
+ {
+ if(ui32Char == 0xfe)
+ {
+ ui32Mode = 3;
+ }
+ else
+ {
+ pui8Buffer[ui32Length++] = ui32Char;
+ }
+ }
+
+ if((ui32Length == ui32Size) && (ui32Mode == 2))
+ {
+ ui32MsgID = *(uint32_t *)pui8Buffer;
+
+ if((ui32MsgID & (CAN_MSGID_MFR_M | CAN_MSGID_DTYPE_M)) ==
+ LM_API_UPD)
+ {
+ *(uint32_t *)pui8Data =
+ *(uint32_t *)(pui8Buffer + 4);
+ *(uint32_t *)(pui8Data + 4) =
+ *(uint32_t *)(pui8Buffer + 8);
+ *pui32Size = ui32Size - 4;
+ break;
+ }
+ }
+ }
+ }
+#endif
+
+ //
+ // Return the message ID of the packet that was received.
+ //
+ return(ui32MsgID);
+}
+
+//*****************************************************************************
+//
+// This function writes out an individual character over the UART and
+// handles sending out special sequences for handling 0xff and 0xfe values.
+//
+//*****************************************************************************
+#ifdef CAN_UART_BRIDGE
+static void
+UARTBridgeWrite(uint32_t ui32Char)
+{
+ //
+ // See if the character being sent is 0xff.
+ //
+ if(ui32Char == 0xff)
+ {
+ //
+ // Send 0xfe 0xfe, the escaped version of 0xff. A sign extended
+ // version of 0xfe is used to avoid the check below for 0xfe, thereby
+ // avoiding an infinite loop. Only the lower 8 bits are actually sent,
+ // so 0xfe is what is actually transmitted.
+ //
+ UARTBridgeWrite(0xfffffffe);
+ UARTBridgeWrite(0xfffffffe);
+ }
+
+ //
+ // Otherwise, see if the character being sent is 0xfe.
+ //
+ else if(ui32Char == 0xfe)
+ {
+ //
+ // Send 0xfe 0xfd, the escaped version of 0xfe. A sign extended
+ // version of 0xfe is used to avoid the check above for 0xfe, thereby
+ // avoiding an infinite loop. Only the lower 8 bits are actually sent,
+ // so 0xfe is what is actually transmitted.
+ //
+ UARTBridgeWrite(0xfffffffe);
+ UARTBridgeWrite(0xfd);
+ }
+
+ //
+ // Otherwise, simply send this character.
+ //
+ else
+ {
+ //
+ // Wait until space is available in the UART transmit FIFO.
+ //
+ while(HWREG(UART0_BASE + UART_O_FR) & UART_FR_TXFF)
+ {
+ }
+
+ //
+ // Send the char.
+ //
+ HWREG(UART0_BASE + UART_O_DR) = ui32Char & 0xff;
+ }
+}
+#endif
+
+//*****************************************************************************
+//
+// Sends a packet to the controller that is communicating with the boot loader.
+//
+//*****************************************************************************
+static void
+PacketWrite(uint32_t ui32Id, const uint8_t *pui8Data, uint32_t ui32Size)
+{
+ uint32_t ui32Idx;
+
+#ifdef CAN_UART_BRIDGE
+ //
+ // Check if the boot loader is in CAN mode.
+ //
+ if(g_ui32Interface == IFACE_CAN)
+ {
+#endif
+ //
+ // Wait until the previous packet has been sent, providing a time out so
+ // that the boot loader does not hang here.
+ //
+ for(ui32Idx = 1000;
+ (ui32Idx != 0) && (CANRegRead(CAN0_BASE + CAN_O_TXRQ1) != 0);
+ ui32Idx--)
+ {
+ }
+
+ //
+ // If the previous packet was sent, then send this packet.
+ //
+ if(ui32Idx != 0)
+ {
+ CANMessageSetTx(ui32Id, pui8Data, ui32Size);
+ }
+#ifdef CAN_UART_BRIDGE
+ }
+ else
+ {
+ //
+ // The boot loader is in UART modes so write the packet using the UART
+ // functions. Write the start pattern followed by the size, and the ID.
+ //
+ UARTBridgeWrite(0xffffffff);
+ UARTBridgeWrite(ui32Size + 4);
+ UARTBridgeWrite(ui32Id & 0xff);
+ UARTBridgeWrite((ui32Id >> 8) & 0xff);
+ UARTBridgeWrite((ui32Id >> 16) & 0xff);
+ UARTBridgeWrite((ui32Id >> 24) & 0xff);
+
+ //
+ // Now write out the remaining data bytes.
+ //
+ while(ui32Size--)
+ {
+ UARTBridgeWrite(*pui8Data++);
+ }
+ }
+#endif
+}
+
+//*****************************************************************************
+//
+//! This is the main routine for handling updating over CAN.
+//!
+//! This function accepts boot loader commands over CAN to perform a firmware
+//! update over the CAN bus. This function assumes that the CAN bus timing
+//! and message objects have been configured elsewhere.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+UpdaterCAN(void)
+{
+ uint32_t ui32Bytes;
+ uint32_t ui32Cmd;
+ uint32_t ui32FlashSize;
+ uint32_t ui32Temp;
+ uint8_t ui8Status;
+
+#ifdef ENABLE_UPDATE_CHECK
+ //
+ // Check the application is valid and check the pin to see if an update is
+ // being requested.
+ //
+ if(g_ui32Forced == 1)
+ {
+ //
+ // Send out the CAN request.
+ //
+#ifdef CAN_UART_BRIDGE
+ g_ui32Interface = IFACE_CAN;
+#endif
+ PacketWrite(LM_API_UPD_REQUEST, 0, 0);
+
+ //
+ // Send out the UART request.
+ //
+#ifdef CAN_UART_BRIDGE
+ g_ui32Interface = IFACE_UART;
+ PacketWrite(LM_API_UPD_REQUEST, 0, 0);
+ g_ui32Interface = IFACE_UNKNOWN;
+#endif
+
+ //
+ // Wait only 50ms for the response and move on otherwise.
+ //
+ Delay(CRYSTAL_FREQ / 20);
+
+ //
+ // Wait until a packet has been received.
+ //
+#ifdef CAN_UART_BRIDGE
+ if((CANRegRead(CAN0_BASE + CAN_O_NWDA1) == 0) &&
+ ((HWREG(UART0_BASE + UART_O_FR) & UART_FR_RXFE) == UART_FR_RXFE))
+#else
+ if(CANRegRead(CAN0_BASE + CAN_O_NWDA1) == 0)
+#endif
+ {
+ //
+ // Call the application.
+ //
+ StartApplication();
+ }
+ }
+#endif
+
+ //
+ // Loop forever processing packets.
+ //
+ while(1)
+ {
+ //
+ // Read the next packet.
+ //
+ ui32Bytes = 0;
+ ui32Cmd = PacketRead(g_pui8CommandBuffer, &ui32Bytes);
+
+ //
+ // Handle this packet.
+ //
+ ui8Status = CAN_CMD_SUCCESS;
+ switch(ui32Cmd)
+ {
+ //
+ // This is an update request packet.
+ //
+ case LM_API_UPD_REQUEST:
+ {
+ //
+ // This packet is ignored (other than generating an ACK).
+ //
+ break;
+ }
+
+ //
+ // This is a ping packet.
+ //
+ case LM_API_UPD_PING:
+ {
+ //
+ // This packet is ignored (other than generating an ACK).
+ //
+ break;
+ }
+
+ //
+ // This is a reset packet.
+ //
+ case LM_API_UPD_RESET:
+ {
+ //
+ // 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)
+ {
+ }
+ }
+
+ //
+ // This is a data packet.
+ //
+ case LM_API_UPD_SEND_DATA:
+ {
+ //
+ // 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 application before 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.
+ //
+ ui8Status = CAN_CMD_FAIL;
+ }
+ }
+
+ //
+ // Check if there are any more bytes to receive.
+ //
+ if(g_ui32TransferSize >= ui32Bytes)
+ {
+ //
+ // Decrypt the data if required.
+ //
+#ifdef BL_DECRYPT_FN_HOOK
+ BL_DECRYPT_FN_HOOK(g_pui8CommandBuffer, ui32Bytes);
+#endif
+
+ //
+ // Clear the flash access interrupt.
+ //
+ BL_FLASH_CL_ERR_FN_HOOK();
+
+ //
+ // Skip the first transfer.
+ //
+ if(g_ui32StartSize == g_ui32TransferSize)
+ {
+ g_ui32StartValues[0] =
+ *((uint32_t *)&g_pui8CommandBuffer[0]);
+ g_ui32StartValues[1] =
+ *((uint32_t *)&g_pui8CommandBuffer[4]);
+ }
+ else
+ {
+ //
+ // Loop over the words to program.
+ //
+ BL_FLASH_PROGRAM_FN_HOOK(g_ui32TransferAddress,
+ g_pui8CommandBuffer,
+ ui32Bytes);
+ }
+
+ //
+ // Return an error if an access violation occurred.
+ //
+ if(BL_FLASH_ERROR_FN_HOOK())
+ {
+ //
+ // Indicate that the flash programming failed.
+ //
+ ui8Status = CAN_CMD_FAIL;
+ }
+ else
+ {
+ //
+ // Now update the address to program.
+ //
+ g_ui32TransferSize -= ui32Bytes;
+ g_ui32TransferAddress += ui32Bytes;
+
+ //
+ // If a progress hook function has been provided, call
+ // it here.
+ //
+#ifdef BL_PROGRESS_FN_HOOK
+ BL_PROGRESS_FN_HOOK(g_ui32StartSize -
+ g_ui32TransferSize,
+ g_ui32StartSize);
+#endif
+ }
+ }
+ else
+ {
+ //
+ // This indicates that too much data is being sent to the
+ // device.
+ //
+ ui8Status = CAN_CMD_FAIL;
+ }
+
+ //
+ // If the last expected bytes were received then write out the
+ // first two words of the image to allow it to boot.
+ //
+ if(g_ui32TransferSize == 0)
+ {
+ //
+ // Loop over the words to program.
+ //
+ BL_FLASH_PROGRAM_FN_HOOK(g_ui32StartAddress,
+ (uint8_t *)&g_ui32StartValues,
+ 8);
+
+ //
+ // If an end signal hook function has been provided, call
+ // it here since we have finished a download.
+ //
+#ifdef BL_END_FN_HOOK
+ BL_END_FN_HOOK();
+#endif
+ }
+ break;
+ }
+
+ //
+ // This is a start download packet.
+ //
+ case LM_API_UPD_DOWNLOAD:
+ {
+ //
+ // Get the application address and size from the packet data.
+ //
+ g_ui32TransferAddress =
+ *((uint32_t *)&g_pui8CommandBuffer[0]);
+ g_ui32TransferSize = *((uint32_t *)&g_pui8CommandBuffer[4]);
+ g_ui32StartSize = g_ui32TransferSize;
+ g_ui32StartAddress = g_ui32TransferAddress;
+
+ //
+ // 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.
+ //
+ ui8Status = CAN_CMD_FAIL;
+
+ //
+ // 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())
+ {
+ ui8Status = CAN_CMD_FAIL;
+ }
+
+ //
+ // See if the command was successful.
+ //
+ if(ui8Status != CAN_CMD_SUCCESS)
+ {
+ //
+ // Setting g_ui32TransferSize to zero makes
+ // COMMAND_SEND_DATA fail to accept any data.
+ //
+ g_ui32TransferSize = 0;
+ }
+#ifdef BL_START_FN_HOOK
+ else
+ {
+ //
+ // If a start signal hook function has been provided, call
+ // it here since we are about to start a new download.
+ //
+ BL_START_FN_HOOK();
+ }
+#endif
+
+ break;
+ }
+
+ //
+ // This is an unknown packet.
+ //
+ default:
+ {
+ //
+ // Set the status to indicate a failure.
+ //
+ ui8Status = CAN_CMD_FAIL;
+ break;
+ }
+ }
+
+ //
+ // Send an ACK packet in response to indicate that the packet was
+ // received. The status in the ACK data indicates if the command was
+ // successfully processed.
+ //
+ PacketWrite(LM_API_UPD_ACK, &ui8Status, 1);
+ }
+}
+
+//*****************************************************************************
+//
+// Configures the UART used for CAN traffic bridging.
+//
+//*****************************************************************************
+#ifdef CAN_UART_BRIDGE
+void
+ConfigureBridge(void)
+{
+ //
+ // Enable the GPIO module if necessary.
+ //
+#if (CAN_RX_PERIPH != SYSCTL_RCGC2_GPIOA) && \
+ (CAN_TX_PERIPH != SYSCTL_RCGC2_GPIOA)
+ HWREG(SYSCTL_RCGC2) |= SYSCTL_RCGC2_GPIOA;
+#endif
+
+ //
+ // Enable the UART module.
+ //
+ HWREG(SYSCTL_RCGC1) |= SYSCTL_RCGC1_UART0;
+
+ //
+ // Enable the GPIO pins used for the UART.
+ //
+ HWREG(GPIO_PORTA_BASE + GPIO_O_AFSEL) |= 0x3;
+ HWREG(GPIO_PORTA_BASE + GPIO_O_DEN) |= 0x03;
+
+ //
+ // Configure the UART.
+ //
+ HWREG(UART0_BASE + UART_O_IBRD) = UART_BAUD_RATIO(115200) >> 6;
+ HWREG(UART0_BASE + UART_O_FBRD) = (UART_BAUD_RATIO(115200) &
+ UART_FBRD_DIVFRAC_M);
+ HWREG(UART0_BASE + UART_O_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN;
+ HWREG(UART0_BASE + UART_O_CTL) = (UART_CTL_UARTEN | UART_CTL_TXE |
+ UART_CTL_RXE);
+}
+#endif
+
+//*****************************************************************************
+//
+//! This is the application entry point to the CAN updater.
+//!
+//! This function should only be entered from a running application and not
+//! when running the boot loader with no application present.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+AppUpdaterCAN(void)
+{
+ //
+ // If the boot loader is being called from the application the UART needs
+ // to be configured.
+ //
+#ifdef CAN_UART_BRIDGE
+ ConfigureBridge();
+#endif
+
+ //
+ // Configure the CAN controller but don't change the bit timing.
+ //
+ ConfigureCANInterface(0);
+
+ //
+ // Call the main update routine.
+ //
+ UpdaterCAN();
+}
+
+//*****************************************************************************
+//
+//! 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.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+ConfigureCAN(void)
+{
+#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 while the main oscillator starts up.
+ //
+ Delay(524288);
+
+ //
+ // Set the crystal frequency and switch to the main oscillator.
+ //
+ HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
+ ~(SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M)) |
+ XTAL_VALUE | SYSCTL_RCC_OSCSRC_MAIN);
+#endif
+
+ //
+ // Enable the CAN controller.
+ //
+ HWREG(SYSCTL_RCGC0) |= SYSCTL_RCGC0_CAN0;
+
+#if CAN_RX_PERIPH == CAN_TX_PERIPH
+ //
+ // Enable the GPIO associated with CAN0
+ //
+ HWREG(SYSCTL_RCGC2) |= CAN_RX_PERIPH;
+
+ //
+ // Wait a while before accessing the peripheral.
+ //
+ Delay(3);
+
+ //
+ // Set the alternate function selects.
+ //
+ HWREG(CAN_RX_PORT + GPIO_O_AFSEL) |= CAN_RX_PIN_M | CAN_TX_PIN_M;
+
+ //
+ // Set the pin type to it's digital function.
+ //
+ HWREG(CAN_RX_PORT + GPIO_O_DEN) |= CAN_RX_PIN_M | CAN_TX_PIN_M;
+
+#else
+ //
+ // Enable the GPIO associated with CAN0
+ //
+ HWREG(SYSCTL_RCGC2) |= CAN_RX_PERIPH | CAN_TX_PERIPH;
+
+ //
+ // Wait a while before accessing the peripheral.
+ //
+ Delay(3);
+
+ //
+ // Set the alternate function selects.
+ //
+ HWREG(CAN_RX_PORT + GPIO_O_AFSEL) |= CAN_RX_PIN_M;
+ HWREG(CAN_TX_PORT + GPIO_O_AFSEL) |= CAN_TX_PIN_M;
+
+ //
+ // Set the pin type to it's digital function.
+ //
+ HWREG(CAN_RX_PORT + GPIO_O_DEN) |= CAN_RX_PIN_M;
+ HWREG(CAN_TX_PORT + GPIO_O_DEN) |= CAN_TX_PIN_M;
+#endif
+
+ //
+ // Configure the UART used for bridging.
+ //
+#ifdef CAN_UART_BRIDGE
+ ConfigureBridge();
+#endif
+
+ //
+ // Configure the CAN interface.
+ //
+ ConfigureCANInterface(1);
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+#endif
diff --git a/boot_loader/bl_can.h b/boot_loader/bl_can.h new file mode 100644 index 0000000..504a410 --- /dev/null +++ b/boot_loader/bl_can.h @@ -0,0 +1,64 @@ +//*****************************************************************************
+//
+// bl_can.h - Definitions for the CAN transport functions.
+//
+// Copyright (c) 2008-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.
+//
+//*****************************************************************************
+
+#ifndef __BL_CAN_H__
+#define __BL_CAN_H__
+
+//*****************************************************************************
+//
+// These defines are used to define the range of values that are used for
+// the CAN update protocol.
+//
+//*****************************************************************************
+#define CAN_MSGID_DTYPE_UPDATE 0x1f000000
+#define CAN_MSGID_MFR_LM 0x00020000
+
+//*****************************************************************************
+//
+// The masks of the fields that are used in the message identifier.
+//
+//*****************************************************************************
+#define CAN_MSGID_DEVNO_M 0x0000003f
+#define CAN_MSGID_API_M 0x0000ffc0
+#define CAN_MSGID_MFR_M 0x00ff0000
+#define CAN_MSGID_DTYPE_M 0x1f000000
+#define CAN_MSGID_DEVNO_S 0
+#define CAN_MSGID_API_S 6
+#define CAN_MSGID_MFR_S 16
+#define CAN_MSGID_DTYPE_S 24
+
+//*****************************************************************************
+//
+// Firmware Update API definitions.
+//
+//*****************************************************************************
+#define LM_API_UPD (CAN_MSGID_MFR_LM | CAN_MSGID_DTYPE_UPDATE)
+#define LM_API_UPD_PING (LM_API_UPD | (0 << CAN_MSGID_API_S))
+#define LM_API_UPD_DOWNLOAD (LM_API_UPD | (1 << CAN_MSGID_API_S))
+#define LM_API_UPD_SEND_DATA (LM_API_UPD | (2 << CAN_MSGID_API_S))
+#define LM_API_UPD_RESET (LM_API_UPD | (3 << CAN_MSGID_API_S))
+#define LM_API_UPD_ACK (LM_API_UPD | (4 << CAN_MSGID_API_S))
+#define LM_API_UPD_REQUEST (LM_API_UPD | (6 << CAN_MSGID_API_S))
+
+#endif // __BL_CAN_H__
diff --git a/boot_loader/bl_can_timing.h b/boot_loader/bl_can_timing.h new file mode 100644 index 0000000..f0aaa0c --- /dev/null +++ b/boot_loader/bl_can_timing.h @@ -0,0 +1,241 @@ +//*****************************************************************************
+//
+// bl_can_timing.h - Timing definitions for the CAN controller.
+//
+// Copyright (c) 2008-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.
+//
+//*****************************************************************************
+
+#ifndef __BL_CAN_TIMING_H__
+#define __BL_CAN_TIMING_H__
+
+#ifdef CAN_ENABLE_UPDATE
+
+//*****************************************************************************
+//
+// This macro is used to generate the proper value for CAN_BIT_TIMING. The
+// values selected for each crystal/bit rate combination assumes a propagation
+// delay of 300ns (which will always be rounded up to the next integer multiple
+// of the CAN time quanta).
+//
+//*****************************************************************************
+#define CAN_BIT_REG(seg1, seg2, sjw, brp) \
+ ((((seg2 - 1) << CAN_BIT_TSEG2_S) & \
+ CAN_BIT_TSEG2_M) | \
+ (((seg1 - 1) << CAN_BIT_TSEG1_S) & \
+ CAN_BIT_TSEG1_M) | \
+ (((sjw - 1) << CAN_BIT_SJW_S) & \
+ CAN_BIT_SJW_M) | \
+ (((brp - 1) << CAN_BIT_BRP_S) & \
+ CAN_BIT_BRP_M))
+
+//*****************************************************************************
+//
+// The settings for a 16MHz crystal frequency.
+//
+//*****************************************************************************
+#if CRYSTAL_FREQ == 16000000
+#if CAN_BIT_RATE == 1000000
+#define CAN_BIT_TIMING CAN_BIT_REG(10, 5, 4, 1) // tProp = 312ns
+#elif CAN_BIT_RATE == 500000
+#define CAN_BIT_TIMING CAN_BIT_REG(9, 6, 4, 2) // tProp = 375ns
+#elif CAN_BIT_RATE == 250000
+#define CAN_BIT_TIMING CAN_BIT_REG(4, 3, 3, 8) // tProp = 500ns
+#elif CAN_BIT_RATE == 125000
+#define CAN_BIT_TIMING CAN_BIT_REG(8, 7, 4, 8) // tProp = 500ns
+#elif CAN_BIT_RATE == 50000
+#define CAN_BIT_TIMING CAN_BIT_REG(8, 7, 4, 20) // tProp = 1250ns
+#elif CAN_BIT_RATE == 20000
+#define CAN_BIT_TIMING CAN_BIT_REG(8, 7, 4, 50) // tProp = 3125ns
+#else
+#error Invalid CAN_BIT_RATE value used with a 16MHz crystal.
+#endif
+
+//*****************************************************************************
+//
+// The settings for a 12MHz crystal frequency.
+//
+//*****************************************************************************
+#elif CRYSTAL_FREQ == 12000000
+#if CAN_BIT_RATE == 1000000
+#define CAN_BIT_TIMING CAN_BIT_REG(8, 3, 3, 1) // tProp = 416ns
+#elif CAN_BIT_RATE == 500000
+#define CAN_BIT_TIMING CAN_BIT_REG(7, 4, 4, 2) // tProp = 500ns
+#elif CAN_BIT_RATE == 250000
+#define CAN_BIT_TIMING CAN_BIT_REG(6, 5, 4, 4) // tProp = 333ns
+#elif CAN_BIT_RATE == 125000
+#define CAN_BIT_TIMING CAN_BIT_REG(8, 7, 4, 6) // tProp = 500ns
+#elif CAN_BIT_RATE == 50000
+#define CAN_BIT_TIMING CAN_BIT_REG(8, 7, 4, 15) // tProp = 1250ns
+#elif CAN_BIT_RATE == 20000
+#define CAN_BIT_TIMING CAN_BIT_REG(6, 5, 4, 50) // tProp = 4166ns
+#else
+#error Invalid CAN_BIT_RATE value used with a 12MHz crystal.
+#endif
+
+//*****************************************************************************
+//
+// The settings for a 10MHz crystal frequency.
+//
+//*****************************************************************************
+#elif CRYSTAL_FREQ == 10000000
+#if CAN_BIT_RATE == 1000000
+#define CAN_BIT_TIMING CAN_BIT_REG(6, 3, 3, 1) // tProp = 300ns
+#elif CAN_BIT_RATE == 500000
+#define CAN_BIT_TIMING CAN_BIT_REG(11, 8, 4, 1) // tProp = 300ns
+#elif CAN_BIT_RATE == 250000
+#define CAN_BIT_TIMING CAN_BIT_REG(5, 4, 4, 4) // tProp = 400ns
+#elif CAN_BIT_RATE == 125000
+#define CAN_BIT_TIMING CAN_BIT_REG(8, 7, 4, 5) // tProp = 500ns
+#elif CAN_BIT_RATE == 50000
+#define CAN_BIT_TIMING CAN_BIT_REG(5, 4, 4, 20) // tProp = 2000ns
+#elif CAN_BIT_RATE == 20000
+#define CAN_BIT_TIMING CAN_BIT_REG(5, 4, 4, 50) // tProp = 5000ns
+#else
+#error Invalid CAN_BIT_RATE value used with a 10MHz crystal.
+#endif
+
+//*****************************************************************************
+//
+// The settings for a 8MHz crystal frequency.
+//
+//*****************************************************************************
+#elif CRYSTAL_FREQ == 8000000
+#if CAN_BIT_RATE == 1000000
+#define CAN_BIT_TIMING CAN_BIT_REG(5, 2, 2, 1) // tProp = 375ns
+#elif CAN_BIT_RATE == 500000
+#define CAN_BIT_TIMING CAN_BIT_REG(9, 6, 4, 1) // tProp = 375ns
+#elif CAN_BIT_RATE == 250000
+#define CAN_BIT_TIMING CAN_BIT_REG(4, 3, 3, 4) // tProp = 500ns
+#elif CAN_BIT_RATE == 125000
+#define CAN_BIT_TIMING CAN_BIT_REG(8, 7, 4, 4) // tProp = 500ns
+#elif CAN_BIT_RATE == 50000
+#define CAN_BIT_TIMING CAN_BIT_REG(8, 7, 4, 10) // tProp = 1250ns
+#elif CAN_BIT_RATE == 20000
+#define CAN_BIT_TIMING CAN_BIT_REG(8, 7, 4, 25) // tProp = 3125ns
+#else
+#error Invalid CAN_BIT_RATE value used with a 8MHz crystal.
+#endif
+
+//*****************************************************************************
+//
+// The settings for a 6MHz crystal frequency.
+//
+//*****************************************************************************
+#elif CRYSTAL_FREQ == 6000000
+#if CAN_BIT_RATE == 500000
+#define CAN_BIT_TIMING CAN_BIT_REG(7, 4, 4, 1) // tProp = 500ns
+#elif CAN_BIT_RATE == 250000
+#define CAN_BIT_TIMING CAN_BIT_REG(6, 5, 4, 2) // tProp = 333ns
+#elif CAN_BIT_RATE == 125000
+#define CAN_BIT_TIMING CAN_BIT_REG(8, 7, 4, 3) // tProp = 500ns
+#elif CAN_BIT_RATE == 50000
+#define CAN_BIT_TIMING CAN_BIT_REG(6, 5, 4, 10) // tProp = 1666ns
+#elif CAN_BIT_RATE == 20000
+#define CAN_BIT_TIMING CAN_BIT_REG(6, 5, 4, 25) // tProp = 4166ns
+#else
+#error Invalid CAN_BIT_RATE value used with a 6MHz crystal.
+#endif
+
+//*****************************************************************************
+//
+// The settings for a 5MHz crystal frequency.
+//
+//*****************************************************************************
+#elif CRYSTAL_FREQ == 5000000
+#if CAN_BIT_RATE == 500000
+#define CAN_BIT_TIMING CAN_BIT_REG(6, 3, 3, 1) // tProp = 600ns
+#elif CAN_BIT_RATE == 250000
+#define CAN_BIT_TIMING CAN_BIT_REG(5, 4, 4, 2) // tProp = 400ns
+#elif CAN_BIT_RATE == 125000
+#define CAN_BIT_TIMING CAN_BIT_REG(5, 4, 4, 4) // tProp = 800ns
+#elif CAN_BIT_RATE == 50000
+#define CAN_BIT_TIMING CAN_BIT_REG(5, 4, 4, 10) // tProp = 2000ns
+#elif CAN_BIT_RATE == 20000
+#define CAN_BIT_TIMING CAN_BIT_REG(5, 4, 4, 25) // tProp = 5000ns
+#else
+#error Invalid CAN_BIT_RATE value used with a 5MHz crystal.
+#endif
+
+//*****************************************************************************
+//
+// The settings for a 4MHz crystal frequency.
+//
+//*****************************************************************************
+#elif CRYSTAL_FREQ == 4000000
+#if CAN_BIT_RATE == 500000
+#define CAN_BIT_TIMING CAN_BIT_REG(5, 2, 2, 1) // tProp = 750ns
+#elif CAN_BIT_RATE == 250000
+#define CAN_BIT_TIMING CAN_BIT_REG(4, 3, 3, 2) // tProp = 500ns
+#elif CAN_BIT_RATE == 125000
+#define CAN_BIT_TIMING CAN_BIT_REG(8, 7, 4, 2) // tProp = 500ns
+#elif CAN_BIT_RATE == 50000
+#define CAN_BIT_TIMING CAN_BIT_REG(8, 7, 4, 5) // tProp = 1250ns
+#elif CAN_BIT_RATE == 20000
+#define CAN_BIT_TIMING CAN_BIT_REG(5, 4, 4, 20) // tProp = 5000ns
+#else
+#error Invalid CAN_BIT_RATE value used with a 4MHz crystal.
+#endif
+
+//*****************************************************************************
+//
+// The settings for a 2MHz crystal frequency.
+//
+//*****************************************************************************
+#elif CRYSTAL_FREQ == 2000000
+#if CAN_BIT_RATE == 250000
+#define CAN_BIT_TIMING CAN_BIT_REG(4, 3, 3, 1) // tProp = 500ns
+#elif CAN_BIT_RATE == 125000
+#define CAN_BIT_TIMING CAN_BIT_REG(8, 7, 4, 1) // tProp = 500ns
+#elif CAN_BIT_RATE == 50000
+#define CAN_BIT_TIMING CAN_BIT_REG(5, 4, 4, 4) // tProp = 2000ns
+#elif CAN_BIT_RATE == 20000
+#define CAN_BIT_TIMING CAN_BIT_REG(5, 4, 4, 10) // tProp = 5000ns
+#else
+#error Invalid CAN_BIT_RATE value used with a 2MHz crystal.
+#endif
+
+//*****************************************************************************
+//
+// The settings for a 1MHz crystal frequency.
+//
+//*****************************************************************************
+#elif CRYSTAL_FREQ == 1000000
+#if CAN_BIT_RATE == 125000
+#define CAN_BIT_TIMING CAN_BIT_REG(4, 3, 3, 1) // tProp = 1000ns
+#elif CAN_BIT_RATE == 50000
+#define CAN_BIT_TIMING CAN_BIT_REG(5, 4, 4, 2) // tProp = 2000ns
+#elif CAN_BIT_RATE == 20000
+#define CAN_BIT_TIMING CAN_BIT_REG(5, 4, 4, 5) // tProp = 5000ns
+#else
+#error Invalid CAN_BIT_RATE value used with a 1MHz crystal.
+#endif
+
+//*****************************************************************************
+//
+// An unsupported crystal frequency was specified.
+//
+//*****************************************************************************
+#else
+#error The CRYSTAL_FREQ value is not supported by the CAN controller.
+#endif
+
+#endif
+
+#endif // __BL_CAN_TIMING_H__
diff --git a/boot_loader/bl_check.c b/boot_loader/bl_check.c new file mode 100644 index 0000000..b481013 --- /dev/null +++ b/boot_loader/bl_check.c @@ -0,0 +1,266 @@ +//*****************************************************************************
+//
+// bl_check.c - Code to check for a forced update.
+//
+// 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_memmap.h"
+#include "inc/hw_sysctl.h"
+#include "inc/hw_types.h"
+#include "bl_config.h"
+#include "boot_loader/bl_check.h"
+#include "boot_loader/bl_hooks.h"
+#ifdef CHECK_CRC
+#include "boot_loader/bl_crc32.h"
+#endif
+
+//*****************************************************************************
+//
+//! \addtogroup bl_check_api
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// This global is used to remember if a forced update occurred.
+//
+//*****************************************************************************
+#ifdef ENABLE_UPDATE_CHECK
+uint32_t g_ui32Forced;
+#endif
+
+//*****************************************************************************
+//
+// A prototype for the function (in the startup code) for a predictable length
+// delay.
+//
+//*****************************************************************************
+extern void Delay(uint32_t ui32Count);
+
+//*****************************************************************************
+//
+//! 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.
+//
+//*****************************************************************************
+#ifdef ENABLE_UPDATE_CHECK
+uint32_t
+CheckGPIOForceUpdate(void)
+{
+ //
+ // Enable the required GPIO module.
+ //
+ HWREG(SYSCTL_RCGC2) |= 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);
+}
+#endif
+
+//*****************************************************************************
+//
+//! 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)
+{
+#ifdef CHECK_CRC
+ uint32_t ui32Retcode;
+#endif
+
+#ifdef BL_CHECK_UPDATE_FN_HOOK
+ //
+ // If the update check function is hooked, call the application to determine
+ // how to proceed.
+ //
+ return(BL_CHECK_UPDATE_FN_HOOK());
+#else
+ uint32_t *pui32App;
+
+#ifdef ENABLE_UPDATE_CHECK
+ g_ui32Forced = 0;
+#endif
+
+ //
+ // 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 required, scan the image for an embedded CRC and ensure that it
+ // matches the current CRC of the image.
+ //
+#ifdef CHECK_CRC
+ InitCRC32Table();
+ ui32Retcode = CheckImageCRC32(pui32App);
+
+ //
+ // If ENFORCE_CRC is defined, we only boot the image if the CRC is
+ // present in the image information header and the value calculated
+ // matches the value in the header. If ENFORCE_CRC is not defined, we
+ // the image if the CRC is good but also if the length field of the header
+ // is zero (which typically indicates that the post-build step of running
+ // binpack to add the length and CRC to the header was not run).
+ //
+#ifdef ENFORCE_CRC
+ if(ui32Retcode != CHECK_CRC_OK)
+#else
+ if((ui32Retcode != CHECK_CRC_OK) && (ui32Retcode != CHECK_CRC_NO_LENGTH))
+#endif
+ {
+ //
+ // The CRC32 image check failed indicating that the image is
+ // corrupt (or doesn't have the CRC embedded correctly). Either way,
+ // fail the update check and force the boot loader to retain control.
+ //
+ return(2);
+ }
+#endif
+
+#ifdef ENABLE_UPDATE_CHECK
+ //
+ // If simple GPIO checking is configured, determine whether or not to force
+ // an update.
+ //
+ return(CheckGPIOForceUpdate());
+#else
+ //
+ // GPIO checking is not required so, if we get here, a valid image exists
+ // and no update is needed.
+ //
+ return(0);
+#endif
+#endif
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/boot_loader/bl_check.h b/boot_loader/bl_check.h new file mode 100644 index 0000000..a3e0519 --- /dev/null +++ b/boot_loader/bl_check.h @@ -0,0 +1,39 @@ +//*****************************************************************************
+//
+// bl_check.h - Definitions for the forced update check function.
+//
+// Copyright (c) 2007-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.
+//
+//*****************************************************************************
+
+#ifndef __BL_CHECK_H__
+#define __BL_CHECK_H__
+
+//*****************************************************************************
+//
+// Prototype for the forced update check function.
+//
+//*****************************************************************************
+extern uint32_t CheckForceUpdate(void);
+#ifdef ENABLE_UPDATE_CHECK
+extern uint32_t CheckGPIOForceUpdate(void);
+extern uint32_t g_ui32Forced;
+#endif
+
+#endif // __BL_CHECK_H__
diff --git a/boot_loader/bl_commands.h b/boot_loader/bl_commands.h new file mode 100644 index 0000000..f666e15 --- /dev/null +++ b/boot_loader/bl_commands.h @@ -0,0 +1,242 @@ +//*****************************************************************************
+//
+// bl_commands.h - The list of commands and return messages supported by 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.
+//
+//*****************************************************************************
+
+#ifndef __BL_COMMANDS_H__
+#define __BL_COMMANDS_H__
+
+//*****************************************************************************
+//
+// This command is used to receive an acknowledge from the the boot loader
+// proving that communication has been established. This command is a single
+// byte.
+//
+// The format of the command is as follows:
+//
+// uint8_t ui8Command[1];
+//
+// ui8Command[0] = COMMAND_PING;
+//
+//*****************************************************************************
+#define COMMAND_PING 0x20
+
+//*****************************************************************************
+//
+// This command is sent to the boot loader to indicate where to store data and
+// how many bytes will be sent by the COMMAND_SEND_DATA commands that follow.
+// The command consists of two 32-bit values that are both transferred MSB
+// first. The first 32-bit value is the address to start programming data
+// into, while the second is the 32-bit size of the data that will be sent.
+// This command also triggers an erasure of the full application area in the
+// flash or possibly the entire flash depending on the address used. This
+// causes the command to take longer to send the ACK/NAK in response to the
+// command. This command should be followed by a COMMAND_GET_STATUS to ensure
+// that the program address and program size were valid for the microcontroller
+// running the boot loader.
+//
+// The format of the command is as follows:
+//
+// uint8_t ui8Command[9];
+//
+// ui8Command[0] = COMMAND_DOWNLOAD;
+// ui8Command[1] = Program Address [31:24];
+// ui8Command[2] = Program Address [23:16];
+// ui8Command[3] = Program Address [15:8];
+// ui8Command[4] = Program Address [7:0];
+// ui8Command[5] = Program Size [31:24];
+// ui8Command[6] = Program Size [23:16];
+// ui8Command[7] = Program Size [15:8];
+// ui8Command[8] = Program Size [7:0];
+//
+//*****************************************************************************
+#define COMMAND_DOWNLOAD 0x21
+
+//*****************************************************************************
+//
+// This command is sent to the boot loader to transfer execution control to the
+// specified address. The command is followed by a 32-bit value, transferred
+// MSB first, that is the address to which execution control is transferred.
+//
+// The format of the command is as follows:
+//
+// uint8_t ui8Command[5];
+//
+// ui8Command[0] = COMMAND_RUN;
+// ui8Command[1] = Run Address [31:24];
+// ui8Command[2] = Run Address [23:16];
+// ui8Command[3] = Run Address [15:8];
+// ui8Command[4] = Run Address [7:0];
+//
+//*****************************************************************************
+#define COMMAND_RUN 0x22
+
+//*****************************************************************************
+//
+// This command returns the status of the last command that was issued.
+// Typically this command should be received after every command is sent to
+// ensure that the previous command was successful or, if unsuccessful, to
+// properly respond to a failure. The command requires one byte in the data of
+// the packet and the boot loader should respond by sending a packet with one
+// byte of data that contains the current status code.
+//
+// The format of the command is as follows:
+//
+// uint8_t ui8Command[1];
+//
+// ui8Command[0] = COMMAND_GET_STATUS;
+//
+// The following are the definitions for the possible status values that can be
+// returned from the boot loader when <tt>COMMAND_GET_STATUS</tt> is sent to
+// the microcontroller.
+//
+// COMMAND_RET_SUCCESS
+// COMMAND_RET_UNKNOWN_CMD
+// COMMAND_RET_INVALID_CMD
+// COMMAND_RET_INVALID_ADD
+// COMMAND_RET_FLASH_FAIL
+// COMMAND_RET_CRC_FAIL
+//
+//*****************************************************************************
+#define COMMAND_GET_STATUS 0x23
+
+//*****************************************************************************
+//
+// This command should only follow a COMMAND_DOWNLOAD command or another
+// COMMAND_SEND_DATA command, if more data is needed. Consecutive send data
+// commands automatically increment the address and continue programming from
+// the previous location. The transfer size is limited by the size of the
+// receive buffer in the boot loader (as configured by the BUFFER_SIZE
+// parameter). The command terminates programming once the number of bytes
+// indicated by the COMMAND_DOWNLOAD command has been received. Each time this
+// function is called, it should be followed by a COMMAND_GET_STATUS command to
+// ensure that the data was successfully programmed into the flash. If the
+// boot loader sends a NAK to this command, the boot loader will not increment
+// the current address to allow retransmission of the previous data.
+//
+// The format of the command is as follows:
+//
+// uint8_t ui8Command[9];
+//
+// ui8Command[0] = COMMAND_SEND_DATA;
+// ui8Command[1] = Data[0];
+// ui8Command[2] = Data[1];
+// ui8Command[3] = Data[2];
+// ui8Command[4] = Data[3];
+// ui8Command[5] = Data[4];
+// ui8Command[6] = Data[5];
+// ui8Command[7] = Data[6];
+// ui8Command[8] = Data[7];
+//
+//*****************************************************************************
+#define COMMAND_SEND_DATA 0x24
+
+//*****************************************************************************
+//
+// This command is used to tell the boot loader to reset. This is used after
+// downloading a new image to the microcontroller to cause the new application
+// or the new boot loader to start from a reset. The normal boot sequence
+// occurs and the image runs as if from a hardware reset. It can also be used
+// to reset the boot loader if a critical error occurs and the host device
+// wants to restart communication with the boot loader.
+//
+// The format of the command is as follows:
+//
+// uint8_t ui8Command[1];
+//
+// ui8Command[0] = COMMAND_RESET;
+//
+// The boot loader responds with an ACK signal to the host device before
+// actually executing the software reset on the microcontroller running the
+// boot loader. This informs the updater application that the command was
+// received successfully and the part will be reset.
+//
+//*****************************************************************************
+#define COMMAND_RESET 0x25
+
+//*****************************************************************************
+//
+// This is returned in response to a COMMAND_GET_STATUS command and indicates
+// that the previous command completed successful.
+//
+//*****************************************************************************
+#define COMMAND_RET_SUCCESS 0x40
+
+//*****************************************************************************
+//
+// This is returned in response to a COMMAND_GET_STATUS command and indicates
+// that the command sent was an unknown command.
+//
+//*****************************************************************************
+#define COMMAND_RET_UNKNOWN_CMD 0x41
+
+//*****************************************************************************
+//
+// This is returned in response to a COMMAND_GET_STATUS command and indicates
+// that the previous command was formatted incorrectly.
+//
+//*****************************************************************************
+#define COMMAND_RET_INVALID_CMD 0x42
+
+//*****************************************************************************
+//
+// This is returned in response to a COMMAND_GET_STATUS command and indicates
+// that the previous download command contained an invalid address value.
+//
+//*****************************************************************************
+#define COMMAND_RET_INVALID_ADR 0x43
+
+//*****************************************************************************
+//
+// This is returned in response to a COMMAND_GET_STATUS command and indicates
+// that an attempt to program or erase the flash has failed.
+//
+//*****************************************************************************
+#define COMMAND_RET_FLASH_FAIL 0x44
+
+//*****************************************************************************
+//
+// This is returned in response to a COMMAND_GET_STATUS command and indicates
+// that the boot loader is configured to check the embedded CRC32 in the
+// downloaded image but the check failed. This status can only be returned
+// after the last COMMAND_SEND_DATA has been received and processed, and only
+// if CHECK_CRC is defined in the boot loader configuration.
+//
+//*****************************************************************************
+#define COMMAND_RET_CRC_FAIL 0x45
+
+//*****************************************************************************
+//
+// This is the value that is sent to acknowledge a packet.
+//
+//*****************************************************************************
+#define COMMAND_ACK 0xcc
+
+//*****************************************************************************
+//
+// This is the value that is sent to not-acknowledge a packet.
+//
+//*****************************************************************************
+#define COMMAND_NAK 0x33
+
+#endif // __BL_COMMANDS_H__
diff --git a/boot_loader/bl_config.c b/boot_loader/bl_config.c new file mode 100644 index 0000000..9c26068 --- /dev/null +++ b/boot_loader/bl_config.c @@ -0,0 +1,164 @@ +//*****************************************************************************
+//
+// bl_config.c - A dummy C file to generate bl_config.in from bl_config.h.
+//
+// Copyright (c) 2007-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 "bl_config.h"
+
+//*****************************************************************************
+//
+// Since the RV-MDK assembler is not able to run assembly code through the C
+// preprocessor, the relevant contents of bl_config.h need to be converted to
+// assembly format for inclusion into the RV-MDK startup code. This file
+// performs this conversion when manually run through the C preprocessor via:
+//
+// armcc --device DLM -o bl_config.inc -E bl_config.c
+//
+// This file does not contain valid C code and will fail to compile (-E tells
+// the compiler to preprocess but not attempt to compile the code).
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Define an assembler symbol for the stack size.
+//
+//*****************************************************************************
+_STACK_SIZE equ STACK_SIZE
+
+//*****************************************************************************
+//
+// Define an assembler symbol for the application starting address.
+//
+//*****************************************************************************
+_APP_START_ADDRESS equ APP_START_ADDRESS
+
+//*****************************************************************************
+//
+// Define an assembler symbol for the application vector table address.
+//
+//*****************************************************************************
+_VTABLE_START_ADDRESS equ VTABLE_START_ADDRESS
+
+//*****************************************************************************
+//
+// Define an assembler symbol if the MOSCFAIL handler is enabled.
+//
+//*****************************************************************************
+#ifdef ENABLE_MOSCFAIL_HANDLER
+_ENABLE_MOSCFAIL_HANDLER equ 1
+#endif
+
+//*****************************************************************************
+//
+// Define an assembler symbol if update via the UART is enabled.
+//
+//*****************************************************************************
+#ifdef UART_ENABLE_UPDATE
+_UART_ENABLE_UPDATE equ 1
+#endif
+
+//*****************************************************************************
+//
+// Define an assember symbol if UART autobauding is enabled.
+//
+//*****************************************************************************
+#ifdef UART_AUTOBAUD
+_UART_AUTOBAUD equ 1
+#endif
+
+//*****************************************************************************
+//
+// Define an assembler symbol if update via Ethernet is enabled.
+//
+//*****************************************************************************
+#ifdef ENET_ENABLE_UPDATE
+_ENET_ENABLE_UPDATE equ 1
+#endif
+
+//*****************************************************************************
+//
+// Define an assembler symbol if update via CAN is enabled.
+//
+//*****************************************************************************
+#ifdef CAN_ENABLE_UPDATE
+_CAN_ENABLE_UPDATE equ 1
+#endif
+
+//*****************************************************************************
+//
+// Define an assembler symbol if update via USB is enabled.
+//
+//*****************************************************************************
+#ifdef USB_ENABLE_UPDATE
+_USB_ENABLE_UPDATE equ 1
+#endif
+
+//*****************************************************************************
+//
+// Define an assembler symbol if a hardware initialization hook is provided.
+//
+//*****************************************************************************
+#ifdef BL_HW_INIT_FN_HOOK
+#define _quote(x) #x
+#define quote(x) _quote(x)
+ gbls _BL_HW_INIT_FN_HOOK
+_BL_HW_INIT_FN_HOOK sets quote(BL_HW_INIT_FN_HOOK)
+#undef _quote
+#undef quote
+#endif
+
+//*****************************************************************************
+//
+// Define an assembler symbol if an initialization hook is provided.
+//
+//*****************************************************************************
+#ifdef BL_INIT_FN_HOOK
+#define _quote(x) #x
+#define quote(x) _quote(x)
+ gbls _BL_INIT_FN_HOOK
+_BL_INIT_FN_HOOK sets quote(BL_INIT_FN_HOOK)
+#undef _quote
+#undef quote
+#endif
+
+//*****************************************************************************
+//
+// Define an assembler symbol if a re-initialization hook is provided.
+//
+//*****************************************************************************
+#ifdef BL_REINIT_FN_HOOK
+#define _quote(x) #x
+#define quote(x) _quote(x)
+ gbls _BL_REINIT_FN_HOOK
+_BL_REINIT_FN_HOOK sets quote(BL_REINIT_FN_HOOK)
+#undef _quote
+#undef quote
+#endif
+
+//*****************************************************************************
+//
+// The assembler will require an end statement at the end of the output
+// bl_config.inc file.
+//
+//*****************************************************************************
+ end
diff --git a/boot_loader/bl_config.h.tmpl b/boot_loader/bl_config.h.tmpl new file mode 100644 index 0000000..99ab978 --- /dev/null +++ b/boot_loader/bl_config.h.tmpl @@ -0,0 +1,950 @@ +//*****************************************************************************
+//
+// bl_config.h - The configurable parameters of the boot loader.
+//
+// Copyright (c) 2010-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.
+//
+//*****************************************************************************
+
+#ifndef __BL_CONFIG_H__
+#define __BL_CONFIG_H__
+
+//*****************************************************************************
+//
+// The following defines are used to configure the operation of the boot
+// loader. For each define, its interactions with other defines are described.
+// First is the dependencies (i.e. the defines that must also be defined if it
+// is defined), next are the exclusives (i.e. the defines that can not be
+// defined if it is defined), and finally are the requirements (i.e. the
+// defines that must be defined if it is defined).
+//
+// The following defines must be defined in order for the boot loader to
+// operate:
+//
+// One of CAN_ENABLE_UPDATE, ENET_ENABLE_UPDATE, I2C_ENABLE_UPDATE,
+// SSI_ENABLE_UPDATE, UART_ENABLE_UPDATE, or USB_ENABLE_UPDATE
+// APP_START_ADDRESS
+// STACK_SIZE
+// BUFFER_SIZE
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// The frequency of the crystal used to clock the microcontroller.
+//
+// This defines the crystal frequency used by the microcontroller running the
+// boot loader. If this is unknown at the time of production, then use the
+// UART_AUTOBAUD feature to properly configure the UART.
+//
+// Depends on: None
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+#define CRYSTAL_FREQ 8000000
+
+//*****************************************************************************
+//
+// This enables the boosting of the LDO voltage to 2.75V. For boot loader
+// configurations that enable the PLL (for example, using the Ethernet port)
+// on a part that has the PLL errata, this should be enabled. This applies to
+// revision A2 of Fury-class devices.
+//
+// Depends on: None
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define BOOST_LDO_VOLTAGE
+
+//*****************************************************************************
+//
+// 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 0x00001000
+
+//*****************************************************************************
+//
+// The address at which the application locates its exception vector table.
+// This must be a multiple of 1KB (making it aligned to a page boundary).
+// Typically, an application will start with its vector table and this value
+// will default 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 0x00001000
+
+//*****************************************************************************
+//
+// The size of a single, erasable page in the flash. This must be a power
+// of 2. The default value of 1KB represents the page size for the internal
+// flash on all Tiva MCUs and this value should only be overridden if
+// configuring a boot loader to access external flash devices with a page size
+// different from this.
+//
+// Depends on: None
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+#define FLASH_PAGE_SIZE 0x00000400
+
+//*****************************************************************************
+//
+// The amount of space at the end of flash to reserved. This must be a
+// multiple of 1024 bytes (making it aligned to a page boundary). This
+// reserved space is not erased when the application is updated, providing
+// non-volatile storage that can be used for parameters.
+//
+// Depends on: None
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define FLASH_RSVD_SPACE 0x00000800
+
+//*****************************************************************************
+//
+// The number of words of stack space to reserve for the boot loader.
+//
+// Depends on: None
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+#define STACK_SIZE 64
+
+//*****************************************************************************
+//
+// The number of words in the data buffer used for receiving packets. This
+// value must be at least 3. If using autobauding on the UART, this must be at
+// least 20. The maximum usable value is 65 (larger values will result in
+// unused space in the buffer).
+//
+// Depends on: None
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+#define BUFFER_SIZE 20
+
+//*****************************************************************************
+//
+// Enables updates to the boot loader. Updating the boot loader is an unsafe
+// operation since it is not fully fault tolerant (losing power to the device
+// part way though could result in the boot loader no longer being present in
+// flash).
+//
+// Depends on: None
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define ENABLE_BL_UPDATE
+
+//*****************************************************************************
+//
+// This definition will cause the the boot loader to erase the entire flash on
+// updates to the boot loader or to erase the entire application area when the
+// application is updated. This erases any unused sections in the flash before
+// the firmware is updated.
+//
+// Depends on: None
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define FLASH_CODE_PROTECTION
+
+//*****************************************************************************
+//
+// Enables the call to decrypt the downloaded data before writing it into
+// flash. The decryption routine is empty in the reference boot loader source,
+// which simply provides a placeholder for adding an actual decrypter.
+//
+// Depends on: None
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define ENABLE_DECRYPTION
+
+//*****************************************************************************
+//
+// Enables support for the MOSCFAIL handler in the NMI interrupt.
+// Note: Sandstorm or Fury devices do not provide the MOSCFAIL reset, so this
+// feature should not be enabled for these devices.
+//
+// Depends on: None
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define ENABLE_MOSCFAIL_HANDLER
+
+//*****************************************************************************
+//
+// Enables the pin-based forced update check. When enabled, the boot loader
+// will go into update mode instead of calling the application if a pin is read
+// at a particular polarity, forcing an update operation. In either case, the
+// application is still able to return control to the boot loader in order to
+// start an update.
+//
+// Depends on: None
+// Exclusive of: None
+// Requires: FORCED_UPDATE_PERIPH, FORCED_UPDATE_PORT, FORCED_UPDATE_PIN,
+// FORCED_UPDATE_POLARITY
+//
+//*****************************************************************************
+//#define ENABLE_UPDATE_CHECK
+
+//*****************************************************************************
+//
+// 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
+
+//*****************************************************************************
+//
+// 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_PORTB_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 4
+
+//*****************************************************************************
+//
+// 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 for the GPIO pin used in a forced update. This
+// value should be 0 if the pin should be have an internal weak pull down and
+// 1 if the pin should have an interal weak pull up.
+// Only FORCED_UPDATE_WPU or FORCED_UPDATE_WPD or neither should be defined.
+//
+// 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
+
+//*****************************************************************************
+//
+// Selects the UART as the port for communicating with the boot loader.
+//
+// Depends on: None
+// Exclusive of: CAN_ENABLE_UPDATE, ENET_ENABLE_UPDATE, I2C_ENABLE_UPDATE,
+// SSI_ENABLE_UPDATE, USB_ENABLE_UPDATE
+// Requires: UART_AUTOBAUD or UART_FIXED_BAUDRATE
+//
+//*****************************************************************************
+//#define UART_ENABLE_UPDATE
+
+//*****************************************************************************
+//
+// Enables automatic baud rate detection. This can be used if the crystal
+// frequency is unknown, or if operation at different baud rates is desired.
+//
+// Depends on: UART_ENABLE_UPDATE
+// Exclusive of: UART_FIXED_BAUDRATE
+// Requires: None
+//
+//*****************************************************************************
+//#define UART_AUTOBAUD
+
+//*****************************************************************************
+//
+// Selects the baud rate to be used for the UART.
+//
+// Depends on: UART_ENABLE_UPDATE, CRYSTAL_FREQ
+// Exclusive of: UART_AUTOBAUD
+// Requires: None
+//
+//*****************************************************************************
+//#define UART_FIXED_BAUDRATE 115200
+
+//*****************************************************************************
+//
+// Selects the SSI port as the port for communicating with the boot loader.
+//
+// Depends on: None
+// Exclusive of: CAN_ENABLE_UPDATE, ENET_ENABLE_UPDATE, I2C_ENABLE_UPDATE,
+// UART_ENABLE_UPDATE, USB_ENABLE_UPDATE
+// Requires: None
+//
+//*****************************************************************************
+//#define SSI_ENABLE_UPDATE
+
+//*****************************************************************************
+//
+// Selects the I2C port as the port for communicating with the boot loader.
+//
+// Depends on: None
+// Exclusive of: CAN_ENABLE_UPDATE, ENET_ENABLE_UPDATE, SSI_ENABLE_UPDATE,
+// UART_ENABLE_UPDATE, USB_ENABLE_UPDATE
+// Requires: I2C_SLAVE_ADDR
+//
+//*****************************************************************************
+//#define I2C_ENABLE_UPDATE
+
+//*****************************************************************************
+//
+// Specifies the I2C address of the boot loader.
+//
+// Depends on: I2C_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define I2C_SLAVE_ADDR 0x42
+
+//*****************************************************************************
+//
+// Selects Ethernet update via the BOOTP/TFTP protocol.
+//
+// Depends on: None
+// Exclusive of: CAN_ENABLE_UPDATE, I2C_ENABLE_UPDATE, SSI_ENABLE_UPDATE,
+// UART_ENABLE_UPDATE, USB_ENABLE_UPDATE
+// Requires: CRYSTAL_FREQ
+//
+//*****************************************************************************
+//#define ENET_ENABLE_UPDATE
+
+//*****************************************************************************
+//
+// Selects if the Ethernet LEDs should be enabled.
+//
+// Depends on: ENET_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define ENET_ENABLE_LEDS
+
+//*****************************************************************************
+//
+// Selects the Ethernet MAC address. If not specified, the MAC address is
+// taken from the user registers.
+//
+// Depends on: ENET_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define ENET_MAC_ADDR0 0x00
+//#define ENET_MAC_ADDR1 0x00
+//#define ENET_MAC_ADDR2 0x00
+//#define ENET_MAC_ADDR3 0x00
+//#define ENET_MAC_ADDR4 0x00
+//#define ENET_MAC_ADDR5 0x00
+
+//*****************************************************************************
+//
+// Sets the name of the BOOTP server to use. This can be used to request that
+// a particular BOOTP server respond to our request; the value will be either
+// the server's name, or a nickname used by that server. If not defined then
+// any BOOTP server is allowed to respond.
+//
+// Depends on: ENET_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define ENET_BOOTP_SERVER "tiva"
+
+//*****************************************************************************
+//
+// Selects USB update via Device Firmware Update class.
+//
+// Depends on: None
+// Exclusive of: CAN_ENABLE_UPDATE, ENET_ENABLE_UPDATE, I2C_ENABLE_UPDATE,
+// SSI_ENABLE_UPDATE, UART_ENABLE_UPDATE,
+// Requires: CRYSTAL_FREQ, USB_VENDOR_ID, USB_PRODUCT_ID
+//
+//*****************************************************************************
+//#define USB_ENABLE_UPDATE
+
+//*****************************************************************************
+//
+// The USB vendor ID published by the DFU device. This value is the TI
+// Tiva vendor ID. Change this to the vendor ID you have been assigned by
+// USB-IF.
+//
+// Depends on: USB_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define USB_VENDOR_ID 0x1cbe
+
+//*****************************************************************************
+//
+// The USB device ID published by the DFU device. If you are using your own
+// vendor ID, chose a device ID that is different from the ID you use in
+// non-update operation. If you have sublicensed TI's vendor ID, you must
+// use an assigned product ID here.
+//
+// Depends on: USB_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define USB_PRODUCT_ID 0x00ff
+
+//*****************************************************************************
+//
+// Selects the BCD USB device release number published in the device
+// descriptor.
+//
+// Depends on: USB_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define USB_DEVICE_ID 0x0001
+
+//*****************************************************************************
+//
+// Sets the maximum power consumption that the DFU device will report to the
+// USB host in the configuration descriptor. Units are milliamps.
+//
+// Depends on: USB_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define USB_MAX_POWER 150
+
+//*****************************************************************************
+//
+// Determines whether the DFU device reports to the host that it is self
+// powered (defined as 0) or bus powered (defined as 1).
+//
+// Depends on: USB_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define USB_BUS_POWERED 1
+
+//*****************************************************************************
+//
+// Specifies the GPIO peripheral associated with the USB host/device mux.
+//
+// Depends on: USB_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: USB_MUX_PERIPH, USB_MUX_PORT, USB_MUX_PIN, USB_MUX_DEVICE
+//
+//*****************************************************************************
+//#define USB_HAS_MUX
+
+//*****************************************************************************
+//
+// Specifies the GPIO peripheral associated with the USB host/device mux.
+//
+// Depends on: USB_ENABLE_UPDATE, USB_HAS_MUX
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define USB_MUX_PERIPH SYSCTL_RCGC2_GPIOH
+
+//*****************************************************************************
+//
+// Specifies the GPIO port associated with the USB host/device mux.
+//
+// Depends on: USB_ENABLE_UPDATE, USB_HAS_MUX
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define USB_MUX_PORT GPIO_PORTH_BASE
+
+//*****************************************************************************
+//
+// Specifies the GPIO pin number used to switch the USB host/device mux. Valid
+// values are 0 through 7.
+//
+// Depends on: USB_ENABLE_UPDATE, USB_HAS_MUX
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define USB_MUX_PIN 2
+
+//*****************************************************************************
+//
+// Specifies the state to set the GPIO pin to to select USB device mode via
+// the USB host/device mux. Valid values are 1 (high) or 0 (low).
+//
+// Depends on: USB_ENABLE_UPDATE, USB_HAS_MUX
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define USB_MUX_DEVICE 1
+
+//*****************************************************************************
+//
+// Selects the CAN port as the port for communicating with the boot loader.
+//
+// Depends on: None
+// Exclusive of: ENET_ENABLE_UPDATE, I2C_ENABLE_UPDATE, SSI_ENABLE_UPDATE,
+// UART_ENABLE_UPDATE, USB_ENABLE_UPDATE
+// Requires: CAN_RX_PERIPH, CAN_RX_PORT, CAN_RX_PIN, CAN_TX_PERIPH,
+// CAN_TX_PORT, CAN_TX_PIN, CAN_BIT_RATE, CRYSTAL_FREQ.
+//
+//*****************************************************************************
+//#define CAN_ENABLE_UPDATE
+
+//*****************************************************************************
+//
+// Enables the UART to CAN bridging for use when the CAN port is selected for
+// communicating with the boot loader.
+//
+// Depends on: CAN_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define CAN_UART_BRIDGE
+
+//*****************************************************************************
+//
+// Specifies the GPIO peripheral associated with CAN0 RX pin used by the boot
+// loader.
+//
+// Depends on: CAN_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define CAN_RX_PERIPH SYSCTL_RCGC2_GPIOA
+
+//*****************************************************************************
+//
+// Specifies the GPIO port associated with CAN0 RX pin used by the boot loader.
+//
+// Depends on: CAN_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define CAN_RX_PORT GPIO_PORTA_BASE
+
+//*****************************************************************************
+//
+// Specifies the GPIO pin number associated with CAN0 RX pin used by the boot
+// loader.
+//
+// Depends on: CAN_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define CAN_RX_PIN 4
+
+//*****************************************************************************
+//
+// Specifies the GPIO peripheral associated with CAN0 TX pin used by the boot
+// loader.
+//
+// Depends on: CAN_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define CAN_TX_PERIPH SYSCTL_RCGC2_GPIOA
+
+//*****************************************************************************
+//
+// Specifies the GPIO port associated with CAN0 TX pin used by the boot loader.
+//
+// Depends on: CAN_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define CAN_TX_PORT GPIO_PORTA_BASE
+
+//*****************************************************************************
+//
+// Specifies the GPIO pin number associated with CAN0 TX pin used by the boot
+// loader.
+//
+// Depends on: CAN_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define CAN_TX_PIN 5
+
+//*****************************************************************************
+//
+// Specifies the bit rate for CAN0 used by the boot loader.
+//
+// Depends on: CAN_ENABLE_UPDATE
+// Exclusive of: None
+// Requires: None
+//
+//*****************************************************************************
+//#define CAN_BIT_RATE 1000000
+
+//*****************************************************************************
+//
+// Boot loader hook functions.
+//
+// The following defines allow you to add application-specific function which
+// are called at various points during boot loader execution.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Performs application-specific low level hardware initialization on system
+// reset.
+//
+// If hooked, this function will be called immediately after the boot loader
+// code relocation completes. An application may perform any required low
+// hardware initialization during this function. Note that the system clock
+// has not been set when this function is called. Initialization that assumes
+// the system clock is set may be performed in the BL_INIT_FN_HOOK function
+// instead.
+//
+// void MyHwInitFunc(void);
+//
+//*****************************************************************************
+//#define BL_HW_INIT_FN_HOOK MyHwInitFunc
+
+//*****************************************************************************
+//
+// Performs application-specific initialization on system reset.
+//
+// If hooked, this function will be called immediately after the boot loader
+// sets the system clock. An application may perform any additional
+// initialization during this function.
+//
+// void MyInitFunc(void);
+//
+//*****************************************************************************
+//#define BL_INIT_FN_HOOK MyInitFunc
+
+//*****************************************************************************
+//
+// Performs application-specific reinitialization on boot loader entry via SVC.
+//
+// If hooked, this function will be called immediately after the boot loader
+// reinitializes the system clock when it is entered from an application
+// via the SVC mechanism rather than as a result of a system reset. An
+// application may perform any additional reinitialization in this function.
+//
+// void MyReinitFunc(void);
+//
+//*****************************************************************************
+//#define BL_REINIT_FN_HOOK MyReinitFunc
+
+//*****************************************************************************
+//
+// Informs an application that a download is starting.
+//
+// If hooked, this function will be called when a new firmware download is
+// about to start. The application may use this signal to initialize any
+// progress display.
+//
+// void MyStartFunc(void);
+//
+//*****************************************************************************
+//#define BL_START_FN_HOOK MyStartFunc
+
+//*****************************************************************************
+//
+// Informs an application of download progress.
+//
+// If hooked, this function will be called periodically during firmware
+// download. The application may use this to update its user interface.
+// When using a protocol which does not inform the client of the final size of
+// the download in advance (e.g. TFTP), the ulTotal parameter will be 0,
+// otherwise it indicates the expected size of the complete download.
+//
+// void MyProgressFunc(unsigned long ulCompleted, unsigned long ulTotal);
+//
+// where:
+//
+// - ulCompleted indicates the number of bytes already downloaded.
+// - ulTotal indicates the number of bytes expected or 0 if this is not known.
+//
+//*****************************************************************************
+//#define BL_PROGRESS_FN_HOOK MyProgressFunc
+
+//*****************************************************************************
+//
+// Informs an application that a download has completed.
+//
+// If hooked, this function will be called when a firmware download ends.
+// The application may use this signal to update its user interface. Typically
+// a system reset will occur shortly after this function returns as the boot
+// loader attempts to boot the new image.
+//
+// void MyEndFunc(void);
+//
+//*****************************************************************************
+//#define BL_END_FN_HOOK MyEndFunc
+
+//*****************************************************************************
+//
+// Allows an application to perform in-place data decryption during download.
+//
+// If hooked, this function will be called on receipt of any new block of
+// downloaded firmware image data. The application must decrypt this data
+// in place then return at which point the boot loader will write the data to
+// flash.
+//
+// void MyDecryptionFunc(unsigned char *pucBuffer, unsigned long ulSize);
+//
+// where:
+//
+// - pucBuffer points to the first byte of data to be decrypted.
+// - ulSize indicates the number of bytes of data at pucBuffer.
+//
+//*****************************************************************************
+//#define BL_DECRYPT_FN_HOOK MyDecryptionFunc
+
+//*****************************************************************************
+//
+// Allows an application to force a new firmware download.
+//
+// If hooked, this function will be called after a system reset (following
+// basic initialization and the initialization hook function) to give the
+// application an opportunity to force a new firmware download. Depending upon
+// the return code, the boot loader will either boot the existing firmware
+// image or wait for a new download to be started.
+//
+// Note that this hook takes precedence over ENABLE_UPDATE_CHECK settings. If
+// the hook function is defined, the basic GPIO check offered by
+// ENABLE_UPDATE_CHECK does not take place.
+//
+// unsigned long MyCheckUpdateFunc(void);
+//
+// where the return code is 0 if the boot loader should boot the existing
+// image (if found) or non-zero to indicate that the boot loader should retain
+// control and wait for a new firmware image to be downloaded.
+//
+//*****************************************************************************
+//#define BL_CHECK_UPDATE_FN_HOOK MyCheckUpdateFunc
+
+//*****************************************************************************
+//
+// Allows an application to replace the flash block erase function.
+//
+// If hooked, this function will be called whenever a block of flash is to
+// be erased. The function must erase the block and block until the operation
+// has completed. The size of the block which will be erased is defined by
+// FLASH_BLOCK_SIZE.
+//
+// void MyFlashEraseFunc(unsigned long ulBlockAddr);
+//
+// where:
+//
+// - ulBlockAddr is the address of the flash block to be erased.
+//
+//*****************************************************************************
+//#define BL_FLASH_ERASE_FN_HOOK MyFlashEraseFunc
+
+//*****************************************************************************
+//
+// Allows an application to replace the flash programming function.
+//
+// If hooked, this function will be called whenever a block of data is to be
+// be written to flash. The function must program the supplied data and block
+// until the operation has has completed.
+//
+// void MyFlashProgramFunc(unsigned long ulDstAddr,
+// unsigned char *pucSrcData,
+// unsigned long ulLength);
+//
+// where:
+//
+// - ulDstAddr is the address in flash at which the data is to be programmed.
+// This must be a multiple of 4.
+// - pucSrcData points to the first byte of the data to program.
+// - ulLength is the number of bytes of data to program. This must be a
+// multiple of 4.
+//
+//*****************************************************************************
+//#define BL_FLASH_PROGRAM_FN_HOOK MyFlashProgramFunc
+
+//*****************************************************************************
+//
+// Allows an application to replace the flash error clear function.
+//
+// If hooked, this function will be called before each flash erase or program
+// operation. The function must clear any flash error indicators and prepare
+// to detect access violations that may occur in a future erase or program
+// operation.
+//
+// void MyFlashClearErrorFunc(void);
+//
+//*****************************************************************************
+//#define BL_FLASH_CL_ERR_FN_HOOK MyFlashClearErrorFunc
+
+//*****************************************************************************
+//
+// Reports whether or not a flash access violation error has occurred.
+//
+// If hooked, this function will be called after flash erase or program
+// operations. The return code indicates to the caller whether or not
+// an access violation error has occurred since the last call to the function
+// defined by BL_FLASH_CL_ERR_FN_HOOK.
+//
+// unsigned long MyFlashErrorFunc(void);
+//
+// where the return code is 0 if no error has occurred or non-zero if an
+// error was detected.
+//
+//*****************************************************************************
+//#define BL_FLASH_ERROR_FN_HOOK MyFlashErrorFunc
+
+//*****************************************************************************
+//
+// Reports the total size of the device flash.
+//
+// If hooked, this function will be called to determine the size of the flash
+// device.
+//
+// unsigned long MyFlashSizeFunc(void);
+//
+// where the return code is the total number of bytes of flash supported by the
+// device. Note that this does not take into account any reserved space
+// defined via the FLASH_RSVD_SPACE value in this header file.
+//
+//*****************************************************************************
+//#define BL_FLASH_SIZE_FN_HOOK MyFlashSizeFunc
+
+//*****************************************************************************
+//
+// Reports the address of the first byte after the end of the device flash.
+//
+// If hooked, this function will be called to determine the address of the end
+// of valid flash.
+//
+// unsigned long MyFlashEndFunc(void);
+//
+// where the return code is the address of the first byte after the end of flash.
+// Note that this does not take into account any reserved space defined via
+// the FLASH_RSVD_SPACE value in this header file.
+//
+//*****************************************************************************
+//#define BL_FLASH_END_FN_HOOK MyFlashEndFunc
+
+//*****************************************************************************
+//
+// Checks whether the start address and size of an image are valid.
+//
+// If hooked, this function will be called whenever a new download is to be
+// started. It determines whether or not an image of a particular size may be
+// flashed at a given address. Valid addresses are:
+//
+// 1. APP_START_ADDRESS in all cases.
+// 2. 0x00000000 if ENABLE_BL_UPDATE is defined.
+// 3. The start of the reserved space if FLASH_RSVD_SPACE is defined.
+//
+// unsigned long MyFlashAddrCheckFunc(unsigned long ulAddr,
+// unsigned long ulSize);
+//
+// where:
+//
+// - ulAddr is the address in flash at which the image is to be programmed.
+// - ulSize is the total size of the image if known or 0 otherwise.
+//
+// The return code will be 0 if the address or size is invalid or a non-zero
+// value if valid.
+//
+//*****************************************************************************
+//#define BL_FLASH_AD_CHECK_FN_HOOK MyFlashAddrCheckFunc
+
+#endif // __BL_CONFIG_H__
diff --git a/boot_loader/bl_crc32.c b/boot_loader/bl_crc32.c new file mode 100644 index 0000000..9413987 --- /dev/null +++ b/boot_loader/bl_crc32.c @@ -0,0 +1,267 @@ +//*****************************************************************************
+//
+// bl_crc32.c - CRC32 calculation functions used in the boot loader.
+//
+// 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 Tiva Firmware Development Package.
+//
+//*****************************************************************************
+#include <stdint.h>
+#include <stdbool.h>
+#include "inc/hw_types.h"
+#include "inc/hw_flash.h"
+#include "inc/hw_sysctl.h"
+#include "bl_config.h"
+#include "boot_loader/bl_crc32.h"
+
+//*****************************************************************************
+//
+// Storage for the CRC32 calculation lookup table.
+//
+//*****************************************************************************
+static uint32_t g_pui32CRC32Table[256];
+
+//*****************************************************************************
+//
+// Initialize the CRC32 calculation table for the polynomial used. We pick
+// the commonly used ANSI X 3.66 polymonial. This code was informed by an
+// example found at http://www.createwindow.com/programming/crc32/index.htm.
+//
+//*****************************************************************************
+static uint32_t
+Reflect(uint32_t ui32Ref, uint8_t ui8Ch)
+{
+ uint_fast32_t ui32Value;
+ int_fast16_t i16Loop;
+
+ //
+ // Clear our accumulator variable.
+ //
+ ui32Value = 0;
+
+ //
+ // Swap bit 0 for bit 7, bit 1 for bit 6, etc.
+ //
+ for(i16Loop = 1; i16Loop < (ui8Ch + 1); i16Loop++)
+ {
+ if(ui32Ref & 1)
+ {
+ ui32Value |= 1 << (ui8Ch - i16Loop);
+ }
+ ui32Ref >>= 1;
+ }
+
+ //
+ // Return the reflected value.
+ //
+ return(ui32Value);
+}
+
+//*****************************************************************************
+//
+// Initialize the lookup table used in calculating the CRC32 value.
+//
+//*****************************************************************************
+void
+InitCRC32Table(void)
+{
+ uint_fast32_t ui32Polynomial;
+ int_fast16_t i16Loop, i16Bit;
+
+ //
+ // This is the ANSI X 3.66 polynomial as required by the DFU
+ // specification.
+ //
+ ui32Polynomial = 0x04c11db7;
+
+ for(i16Loop = 0; i16Loop <= 0xFF; i16Loop++)
+ {
+ g_pui32CRC32Table[i16Loop]=Reflect(i16Loop, 8) << 24;
+ for (i16Bit = 0; i16Bit < 8; i16Bit++)
+ {
+ g_pui32CRC32Table[i16Loop] = ((g_pui32CRC32Table[i16Loop] << 1) ^
+ (g_pui32CRC32Table[i16Loop] &
+ ((uint32_t)1 << 31) ?
+ ui32Polynomial : 0));
+ }
+ g_pui32CRC32Table[i16Loop] = Reflect(g_pui32CRC32Table[i16Loop], 32);
+ }
+}
+
+//*****************************************************************************
+//
+// Calculate the CRC for the supplied block of data.
+//
+//*****************************************************************************
+uint32_t
+CalculateCRC32(uint8_t *pui8Data, uint32_t ui32Length, uint32_t ui32CRC)
+{
+ uint32_t ui32Count;
+ uint8_t *pui8Buffer;
+ uint8_t ui8Char;
+
+ //
+ // Get a pointer to the start of the data and the number of bytes to
+ // process.
+ //
+ pui8Buffer = pui8Data;
+ ui32Count = ui32Length;
+
+ //
+ // Perform the algorithm on each byte in the supplied buffer using the
+ // lookup table values calculated in InitCRC32Table().
+ //
+ while(ui32Count--)
+ {
+ ui8Char = *pui8Buffer++;
+ ui32CRC = (ui32CRC >> 8) ^ g_pui32CRC32Table[(ui32CRC & 0xFF) ^
+ ui8Char];
+ }
+
+ //
+ // Return the result.
+ //
+ return(ui32CRC);
+}
+
+//*****************************************************************************
+//
+//! Checks that the embedded CRC in the image matches the expected value.
+//!
+//! \param pui32Image points to the start of the firmware image in memory.
+//!
+//! This function finds the firmware image information header and verifies that
+//! the embedded CRC32 matches one calculated over the image.
+//!
+//! \return Returns \b CHECK_CRC_OK if the CRC calculated matches the value
+//! embedded in the image, \b CHECK_CRC_NO_HEADER if no image information
+//! header was found at the top of the vector table, \b CHECK_CRC_BAD_CRC if
+//! an embedded CRC was found but did not match the calculated value or \b
+//! CHECK_CRC_ZERO_LENGTH if the length field of the image information header
+//! contains 0 (likely indicating that the image had not been run through the
+//! binpack tool which inserts the length and CRC values into the header).
+//
+//*****************************************************************************
+uint32_t
+CheckImageCRC32(uint32_t *pui32Image)
+{
+ uint32_t ui32Loop, ui32FlashSize, ui32CRC;
+
+ //
+ // Determine the size of flash (giving an upper bound for the image
+ // size).
+ //
+ if(CLASS_IS_TM4C129)
+ {
+ //
+ // Get the flash size from the FLASH_PP register.
+ //
+ ui32FlashSize = ((2048 * ((HWREG(FLASH_PP) & FLASH_PP_SIZE_M) + 1)) -
+ APP_START_ADDRESS);
+ }
+ else
+ {
+ //
+ // Compute the size of the flash.
+ //
+ ui32FlashSize = (((HWREG(SYSCTL_DC0) & SYSCTL_DC0_FLASHSZ_M) << 11) +
+ 0x800 - APP_START_ADDRESS);
+ }
+
+ //
+ // Scan for the image information header marker bytes. Given that the
+ // largest possible vector table includes 16 system exceptions and 240
+ // IC-specific vectors, we only need to search 257 words into memory before
+ // giving up.
+ //
+ for(ui32Loop = 0; ui32Loop < 257; ui32Loop++)
+ {
+ //
+ // Have we found the header marker words?
+ //
+ if((pui32Image[ui32Loop] == 0xFF01FF02) &&
+ (pui32Image[ui32Loop + 1] == 0xFF03FF04))
+ {
+ //
+ // Yes. Check to see if the length field is 0xFFFFFFFF. This
+ // likely indicates that the image has not been processed by the
+ // binpack tool which adds the length and CRC information to the
+ // image header.
+ //
+ if(pui32Image[ui32Loop + 2] == 0xFFFFFFFF)
+ {
+ //
+ // The header reports an image size of 0 so we can't go on and
+ // check the CRC.
+ //
+ return(CHECK_CRC_NO_LENGTH);
+ }
+
+ //
+ // Extract the image length and ensure that it is sensible
+ // given the flash size. We assume the length is invalid if it
+ // is larger than the available flash size or smaller than the
+ // space taken up by the vector table and header we've already
+ // scanned through.
+ //
+ if((pui32Image[ui32Loop + 2] > ui32FlashSize) ||
+ (pui32Image[ui32Loop + 2] <
+ ((ui32Loop + 4) * sizeof(uint32_t))))
+ {
+ //
+ // The header reports an image size that is larger than the
+ // available flash so this is obviously incorrect. Fail the
+ // check.
+ //
+ return(CHECK_CRC_BAD_LENGTH);
+ }
+
+ //
+ // Calculate the CRC32 value for the image. Note that we skip the
+ // 4 bytes that hold the check CRC.
+ //
+ ui32CRC = CalculateCRC32((uint8_t *)pui32Image,
+ (ui32Loop + 3) * sizeof(uint32_t),
+ 0xffffffff);
+ ui32CRC = CalculateCRC32((uint8_t *)&pui32Image[ui32Loop + 4],
+ (pui32Image[ui32Loop + 2] -
+ ((ui32Loop + 4) * sizeof(uint32_t))),
+ ui32CRC);
+ ui32CRC ^= 0xffffffff;
+
+ //
+ // Determine whether the calculated CRC matches the value stored
+ // in the image information header.
+ //
+ if(ui32CRC == pui32Image[ui32Loop + 3])
+ {
+ return(CHECK_CRC_OK);
+ }
+ else
+ {
+ return(CHECK_CRC_BAD_CRC);
+ }
+ }
+ }
+
+ //
+ // If we drop out the loop, there was no image information header so
+ // fail the call.
+ //
+ return(CHECK_CRC_NO_HEADER);
+}
diff --git a/boot_loader/bl_crc32.h b/boot_loader/bl_crc32.h new file mode 100644 index 0000000..ab8848d --- /dev/null +++ b/boot_loader/bl_crc32.h @@ -0,0 +1,49 @@ +//*****************************************************************************
+//
+// bl_crc32.h - Public header for the boot loader CRC32 functions.
+//
+// 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 Tiva Firmware Development Package.
+//
+//*****************************************************************************
+
+#ifndef __BL_CRC32_H__
+#define __BL_CRC32_H__
+
+//*****************************************************************************
+//
+// Return codes generated by CheckImageCRC32().
+//
+//*****************************************************************************
+#define CHECK_CRC_OK 0
+#define CHECK_CRC_NO_HEADER 1
+#define CHECK_CRC_NO_LENGTH 2
+#define CHECK_CRC_BAD_LENGTH 3
+#define CHECK_CRC_BAD_CRC 4
+
+//*****************************************************************************
+//
+// Exported function prototypes.
+//
+//*****************************************************************************
+extern void InitCRC32Table(void);
+extern uint32_t CheckImageCRC32(uint32_t *pui32Image);
+extern uint32_t CalculateCRC32(uint8_t *pui8Data, uint32_t ui32Length,
+ uint32_t ui32CRC);
+
+#endif
diff --git a/boot_loader/bl_crystal.h b/boot_loader/bl_crystal.h new file mode 100644 index 0000000..268d102 --- /dev/null +++ b/boot_loader/bl_crystal.h @@ -0,0 +1,79 @@ +//*****************************************************************************
+//
+// bl_crystal.h - Macros to convert a CRYSTAL_FREQ value into the appropriate
+// RCC XTAL field define.
+//
+// Copyright (c) 2010-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.
+//
+//*****************************************************************************
+
+#ifndef __BL_CRYSTAL_H__
+#define __BL_CRYSTAL_H__
+
+//*****************************************************************************
+//
+// Convert the CRYSTAL_FREQ value into the corresponding SYSCTL_RCC_XTAL_???
+// value.
+//
+//*****************************************************************************
+#if CRYSTAL_FREQ == 3579545
+#define XTAL_VALUE SYSCTL_RCC_XTAL_3_57MHZ
+#elif CRYSTAL_FREQ == 3686400
+#define XTAL_VALUE SYSCTL_RCC_XTAL_3_68MHZ
+#elif CRYSTAL_FREQ == 4000000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_4MHZ
+#elif CRYSTAL_FREQ == 4096000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_4_09MHZ
+#elif CRYSTAL_FREQ == 4915200
+#define XTAL_VALUE SYSCTL_RCC_XTAL_4_91MHZ
+#elif CRYSTAL_FREQ == 5000000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_5MHZ
+#elif CRYSTAL_FREQ == 5120000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_5_12MHZ
+#elif CRYSTAL_FREQ == 6000000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_6MHZ
+#elif CRYSTAL_FREQ == 6144000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_6_14MHZ
+#elif CRYSTAL_FREQ == 7372800
+#define XTAL_VALUE SYSCTL_RCC_XTAL_7_37MHZ
+#elif CRYSTAL_FREQ == 8000000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_8MHZ
+#elif CRYSTAL_FREQ == 8192000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_8_19MHZ
+#elif CRYSTAL_FREQ == 10000000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_10MHZ
+#elif CRYSTAL_FREQ == 12000000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_12MHZ
+#elif CRYSTAL_FREQ == 12288000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_12_2MHZ
+#elif CRYSTAL_FREQ == 13560000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_13_5MHZ
+#elif CRYSTAL_FREQ == 14318180
+#define XTAL_VALUE SYSCTL_RCC_XTAL_14_3MHZ
+#elif CRYSTAL_FREQ == 16000000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_16MHZ
+#elif CRYSTAL_FREQ == 16384000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_16_3MHZ
+#elif CRYSTAL_FREQ == 25000000
+#define XTAL_VALUE SYSCTL_RCC_XTAL_25MHZ
+#else
+#error ERROR: Unknown CRYSTAL_FREQ value specified!
+#endif
+
+#endif // __BL_CRYSTAL_H__
diff --git a/boot_loader/bl_decrypt.c b/boot_loader/bl_decrypt.c new file mode 100644 index 0000000..6db64da --- /dev/null +++ b/boot_loader/bl_decrypt.c @@ -0,0 +1,64 @@ +//*****************************************************************************
+//
+// bl_decrypt.c - Code for performing an in-place decryption of the firmware
+// image as it is downloaded.
+//
+// Copyright (c) 2007-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 "bl_config.h"
+#include "boot_loader/bl_decrypt.h"
+
+//*****************************************************************************
+//
+//! \addtogroup bl_decrypt_api
+//! @{
+//
+//*****************************************************************************
+#if defined(ENABLE_DECRYPTION) || defined(DOXYGEN)
+
+//*****************************************************************************
+//
+//! Performs an in-place decryption of downloaded data.
+//!
+//! \param pui8Buffer is the buffer that holds the data to decrypt.
+//! \param ui32Size is the size, in bytes, of the buffer that was passed in via
+//! the \e pui8Buffer parameter.
+//!
+//! This function is a stub that could provide in-place decryption of the data
+//! that is being downloaded to the device.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+DecryptData(uint8_t *pui8Buffer, uint32_t ui32Size)
+{
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+#endif
+
diff --git a/boot_loader/bl_decrypt.h b/boot_loader/bl_decrypt.h new file mode 100644 index 0000000..c8eed0c --- /dev/null +++ b/boot_loader/bl_decrypt.h @@ -0,0 +1,35 @@ +//*****************************************************************************
+//
+// bl_decrypt.h - Definitions for the decryption function.
+//
+// Copyright (c) 2007-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.
+//
+//*****************************************************************************
+
+#ifndef __BL_DECRYPT_H__
+#define __BL_DECRYPT_H__
+
+//*****************************************************************************
+//
+// Prototype for the decryption function.
+//
+//*****************************************************************************
+extern void DecryptData(uint8_t *pui8Buffer, uint32_t ui32Size);
+
+#endif // __BL_DECRYPT_H__
diff --git a/boot_loader/bl_emac.c b/boot_loader/bl_emac.c new file mode 100644 index 0000000..c098da0 --- /dev/null +++ b/boot_loader/bl_emac.c @@ -0,0 +1,1914 @@ +//*****************************************************************************
+//
+// bl_emac.c - Functions to update via Ethernet.
+//
+// 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 Tiva Firmware Development Package.
+//
+//*****************************************************************************
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include "bl_config.h"
+#include "inc/hw_emac.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/emac.h"
+#include "driverlib/sysctl.h"
+#include "boot_loader/bl_decrypt.h"
+#include "boot_loader/bl_flash.h"
+#include "boot_loader/bl_hooks.h"
+#include "driverlib/rom.h"
+//
+// Define ROM_SysCtlClockFreqSet() for snowflake RA0. Even though this function
+// is deprecated in RA0 ROM, the function operates correctly when
+// SYSCTL_MOSCCTL register is configured correctly prior to calling this
+// function.
+//
+#if defined(TARGET_IS_TM4C129_RA0)
+#define ROM_SysCtlClockFreqSet \
+ ((uint32_t (*)(uint32_t ui32Config, \
+ uint32_t ui32SysClock))ROM_SYSCTLTABLE[48])
+#endif
+
+//
+// Define MAP_GPIOPadConfigSet() for the Boot Loader for Snowflake.
+// This function fails in Snowflake for higher drive strengths, it will work
+// properly for the instances where it is used here in the boot loader.
+//
+#if defined(TARGET_IS_TM4C129_RA0) || \
+ defined(TARGET_IS_TM4C129_RA1)
+#define ROM_GPIOPadConfigSet \
+ ((void (*)(uint32_t ui32Port, \
+ uint8_t ui8Pins, \
+ uint32_t ui32Strength, \
+ uint32_t ui32PadType))ROM_GPIOTABLE[5])
+#endif
+
+#include "driverlib/rom_map.h"
+
+//*****************************************************************************
+//
+//! \addtogroup bl_emac_api
+//! @{
+//
+//*****************************************************************************
+
+#if defined(ENET_ENABLE_UPDATE) || defined(DOXYGEN)
+//*****************************************************************************
+//
+// Make sure that the crystal frequency is defined.
+//
+//*****************************************************************************
+#if !defined(CRYSTAL_FREQ)
+#error ERROR: CRYSTAL_FREQ must be defined for Ethernet update!
+#endif
+
+//*****************************************************************************
+//
+// Make sure that boot loader update is not enabled (it is not supported via
+// BOOTP given that there is no way to distinguish between a normal firmware
+// image and a boot loader update image).
+//
+//*****************************************************************************
+#if defined(ENABLE_BL_UPDATE)
+#error ERROR: Updating the boot loader is not supported over Ethernet!
+#endif
+
+//*****************************************************************************
+//
+// TFTP packets contain 512 bytes of data and a packet shorter than this
+// indicates the end of the transfer.
+//
+//*****************************************************************************
+#define TFTP_BLOCK_SIZE 512
+
+//*****************************************************************************
+//
+// uIP uses memset, so a simple one is provided here. This is not as efficient
+// as the one in the C library (from an execution time perspective), but it is
+// much smaller.
+//
+//*****************************************************************************
+void *
+my_memset(void *pvDest, int iChar, size_t i32Length)
+{
+ int8_t *pi8Buf = (int8_t *)pvDest;
+
+ //
+ // Fill the buffer with the given character.
+ //
+ while(i32Length--)
+ {
+ *pi8Buf++ = iChar;
+ }
+
+ //
+ // Return a pointer to the beginning of the buffer.
+ //
+ return(pvDest);
+}
+
+//*****************************************************************************
+//
+// uIP uses memcpy, so a simple one is provided here. This is not as efficient
+// as the one in the C library (from an execution time perspective), but it is
+// much smaller.
+//
+//*****************************************************************************
+void *
+my_memcpy(void *pvDest, const void *pvSrc, size_t i32Length)
+{
+ const int8_t *pi8Src = (const int8_t *)pvSrc;
+ int8_t *pi8Dest = (int8_t *)pvDest;
+
+ //
+ // Copy bytes from the source buffer to the destination buffer.
+ //
+ while(i32Length--)
+ {
+ *pi8Dest++ = *pi8Src++;
+ }
+
+ //
+ // Return a pointer to the beginning of the destination buffer.
+ //
+ return(pvDest);
+}
+
+//*****************************************************************************
+//
+// Directly include the uIP code if using Ethernet for the update. This allows
+// non-Ethernet boot loader builds to not have to supply the uip-conf.h file
+// that would otherwise be required.
+//
+//*****************************************************************************
+#define memcpy my_memcpy
+#define memset my_memset
+#undef htonl
+#undef ntohl
+#undef htons
+#undef ntohs
+#include "third_party/uip-1.0/uip/pt.h"
+#include "third_party/uip-1.0/uip/uip_arp.c"
+#undef BUF
+#include "third_party/uip-1.0/uip/uip.c"
+
+//*****************************************************************************
+//
+// A prototype for the function (in the startup code) for a predictable length
+// delay.
+//
+//*****************************************************************************
+extern void Delay(uint32_t ui32Count);
+
+//*****************************************************************************
+//
+// Defines for setting up the system clock.
+//
+//*****************************************************************************
+#define SYSTICKHZ 100
+#define SYSTICKMS (1000 / SYSTICKHZ)
+
+//*****************************************************************************
+//
+// UIP Timers (in ms)
+//
+//*****************************************************************************
+#define UIP_PERIODIC_TIMER_MS 50
+#define UIP_ARP_TIMER_MS 10000
+
+//*****************************************************************************
+//
+// This structure defines the fields in a BOOTP request/reply packet.
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ // The operation; 1 is a request, 2 is a reply.
+ //
+ uint8_t ui8Op;
+
+ //
+ // The hardware type; 1 is Ethernet.
+ //
+ uint8_t ui8HType;
+
+ //
+ // The hardware address length; for Ethernet this will be 6, the length of
+ // the MAC address.
+ //
+ uint8_t ui8HLen;
+
+ //
+ // Hop count, used by gateways for cross-gateway booting.
+ //
+ uint8_t ui8Hops;
+
+ //
+ // The transaction ID.
+ //
+ uint32_t ui32XID;
+
+ //
+ // The number of seconds elapsed since the client started trying to boot.
+ //
+ uint16_t ui16Secs;
+
+ //
+ // The BOOTP flags.
+ //
+ uint16_t ui16Flags;
+
+ //
+ // The client's IP address, if it knows it.
+ //
+ uint32_t ui32CIAddr;
+
+ //
+ // The client's IP address, as assigned by the BOOTP server.
+ //
+ uint32_t ui32YIAddr;
+
+ //
+ // The TFTP server's IP address.
+ //
+ uint32_t ui32SIAddr;
+
+ //
+ // The gateway IP address, if booting cross-gateway.
+ //
+ uint32_t ui32GIAddr;
+
+ //
+ // The hardware address; for Ethernet this is the MAC address.
+ //
+ uint8_t pui8CHAddr[16];
+
+ //
+ // The name, or nickname, of the server that should handle this BOOTP
+ // request.
+ //
+ char pcSName[64];
+
+ //
+ // The name of the boot file to be loaded via TFTP.
+ //
+ char pcFile[128];
+
+ //
+ // Optional vendor-specific area; not used for BOOTP.
+ //
+ uint8_t pui8Vend[64];
+}
+tBOOTPPacket;
+
+//*****************************************************************************
+//
+// The BOOTP commands.
+//
+//*****************************************************************************
+#define BOOTP_REQUEST 1
+#define BOOTP_REPLY 2
+
+//*****************************************************************************
+//
+// The TFTP commands.
+//
+//*****************************************************************************
+#define TFTP_RRQ 1
+#define TFTP_WRQ 2
+#define TFTP_DATA 3
+#define TFTP_ACK 4
+#define TFTP_ERROR 5
+
+//*****************************************************************************
+//
+// The UDP ports used by the BOOTP protocol.
+//
+//*****************************************************************************
+#define BOOTP_SERVER_PORT 67
+#define BOOTP_CLIENT_PORT 68
+
+//*****************************************************************************
+//
+// The UDP port for the TFTP server.
+//
+//*****************************************************************************
+#define TFTP_PORT 69
+
+//*****************************************************************************
+//
+// The MAC address of the Ethernet interface.
+//
+//*****************************************************************************
+#ifdef ENET_MAC_ADDR0
+static struct uip_eth_addr g_sMACAddr =
+{
+ {
+ ENET_MAC_ADDR0,
+ ENET_MAC_ADDR1,
+ ENET_MAC_ADDR2,
+ ENET_MAC_ADDR3,
+ ENET_MAC_ADDR4,
+ ENET_MAC_ADDR5
+ }
+};
+#else
+static struct uip_eth_addr g_sMACAddr;
+#endif
+
+//*****************************************************************************
+//
+// The number of SysTick interrupts since the start of the boot loader.
+//
+//*****************************************************************************
+static uint32_t g_ui32Ticks;
+
+//*****************************************************************************
+//
+// The seed for the random number generator.
+//
+//*****************************************************************************
+static uint32_t g_ui32RandomSeed;
+
+//*****************************************************************************
+//
+// The number of milliseconds since the last call to uip_udp_periodic().
+//
+//*****************************************************************************
+static volatile uint32_t g_ui32PeriodicTimer;
+
+//*****************************************************************************
+//
+// The number of milliseconds since the last call to uip_arp_timer().
+//
+//*****************************************************************************
+static volatile uint32_t g_ui32ARPTimer;
+
+//*****************************************************************************
+//
+// The transaction ID of the most recently sent out BOOTP request.
+//
+//*****************************************************************************
+static uint32_t g_ui32XID;
+
+//*****************************************************************************
+//
+// The state for the proto-thread that handles the BOOTP process.
+//
+//*****************************************************************************
+static struct pt g_sThread;
+
+//*****************************************************************************
+//
+// The amount of time to wait for a BOOTP reply before sending out a new BOOTP
+// request.
+//
+//*****************************************************************************
+static uint32_t g_ui32Delay;
+
+//*****************************************************************************
+//
+// The target time (relative to g_ui32Ticks) when the next timeout occurs.
+//
+//*****************************************************************************
+static uint32_t g_ui32Target;
+
+//*****************************************************************************
+//
+// The IP address of the TFTP server.
+//
+//*****************************************************************************
+static uip_ipaddr_t g_sServerAddr;
+
+//*****************************************************************************
+//
+// The name of the file to be read from the TFTP server.
+//
+//*****************************************************************************
+static char g_pcFilename[128];
+
+//*****************************************************************************
+//
+// The end of flash. If there is not a reserved block at the end of flash,
+// this is the real end of flash. If there is a reserved block, this is the
+// start of the reserved block (i.e. the virtual end of flash).
+//
+//*****************************************************************************
+static uint32_t g_ui32FlashEnd;
+
+//*****************************************************************************
+//
+// The current block being read from the TFTP server.
+//
+//*****************************************************************************
+static uint32_t g_ui32TFTPBlock;
+
+//*****************************************************************************
+//
+// The number of TFTP retries.
+//
+//*****************************************************************************
+static uint32_t g_ui32TFTPRetries;
+
+//*****************************************************************************
+//
+// The UDP socket used to communicate with the BOOTP and TFTP servers (in
+// sequence).
+//
+//*****************************************************************************
+struct uip_udp_conn *g_pConn;
+
+//*****************************************************************************
+//
+// The current link status.
+//
+//*****************************************************************************
+static uint32_t g_ui32Link;
+
+//*****************************************************************************
+//
+// Ethernet DMA descriptors.
+//
+// Although uIP uses a single buffer, the MAC hardware needs a minimum of
+// 3 receive descriptors to operate.
+//
+//*****************************************************************************
+#define NUM_TX_DESCRIPTORS 3
+#define NUM_RX_DESCRIPTORS 3
+tEMACDMADescriptor g_psRxDescriptor[NUM_TX_DESCRIPTORS];
+tEMACDMADescriptor g_psTxDescriptor[NUM_RX_DESCRIPTORS];
+uint32_t g_ui32RxDescIndex;
+uint32_t g_ui32TxDescIndex;
+
+//*****************************************************************************
+//
+// Transmit and receive buffers.
+//
+//*****************************************************************************
+#define RX_BUFFER_SIZE 1536
+#define TX_BUFFER_SIZE 1536
+uint8_t g_pui8RxBuffer[RX_BUFFER_SIZE];
+uint8_t g_pui8TxBuffer[TX_BUFFER_SIZE];
+
+//*****************************************************************************
+//
+//! Handles the SysTick interrupt.
+//!
+//! This function is called when the SysTick interrupt occurs. It simply
+//! keeps a running count of interrupts, used as a time basis for the BOOTP and
+//! TFTP protocols.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SysTickIntHandler(void)
+{
+ //
+ // Increment the tick count.
+ //
+ g_ui32Ticks++;
+ g_ui32PeriodicTimer += SYSTICKMS;
+ g_ui32ARPTimer += SYSTICKMS;
+}
+
+//*****************************************************************************
+//
+//! Computes a new random number.
+//!
+//! This function computes a new pseudo-random number, using a linear
+//! congruence random number generator. Note that if the entire 32-bits of the
+//! produced random number are not being used, the upper N bits should be used
+//! instead of the lower N bits as they are much more random (for example, use
+//! ``RandomNumber() >> 28'' instead of ``RandomNumber() & 15'').
+//!
+//! \return Returns a 32-bit pseudo-random number.
+//
+//*****************************************************************************
+static uint32_t
+RandomNumber(void)
+{
+ //
+ // Generate a new pseudo-random number with a linear congruence random
+ // number generator. This new random number becomes the seed for the next
+ // random number.
+ //
+ g_ui32RandomSeed = (g_ui32RandomSeed * 1664525) + 1013904223;
+
+ //
+ // Return the new random number.
+ //
+ return(g_ui32RandomSeed);
+}
+
+//*****************************************************************************
+//
+// Read a packet from the DMA receive buffer into the uIP packet buffer.
+//
+//*****************************************************************************
+static int32_t
+PacketReceive(uint8_t *pui8Buf, int32_t i32BufLen)
+{
+ int_fast32_t i32FrameLen, i32Loop;
+
+ //
+ // By default, we assume we got a bad frame.
+ //
+ i32FrameLen = 0;
+
+ //
+ // See if the receive descriptor contains a valid frame. Look for a
+ // descriptor error, indicating that the incoming packet was truncated or,
+ // if this is the last frame in a packet, the receive error bit.
+ //
+ if(!(g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus &
+ DES0_RX_STAT_ERR))
+ {
+ //
+ // We have a valid frame so copy the content to the supplied buffer.
+ // First check that the "last descriptor" flag is set. We sized the
+ // receive buffer such that it can always hold a valid frame so this
+ // flag should never be clear at this point but...
+ //
+ if(g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus &
+ DES0_RX_STAT_LAST_DESC)
+ {
+ i32FrameLen =
+ ((g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus &
+ DES0_RX_STAT_FRAME_LENGTH_M) >>
+ DES0_RX_STAT_FRAME_LENGTH_S);
+
+ //
+ // Sanity check. This shouldn't be required since we sized the uIP
+ // buffer such that it's the same size as the DMA receive buffer
+ // but, just in case...
+ //
+ if(i32FrameLen > i32BufLen)
+ {
+ i32FrameLen = i32BufLen;
+ }
+
+ //
+ // Copy the data from the DMA receive buffer into the provided
+ // frame buffer.
+ //
+ for(i32Loop = 0; i32Loop < i32FrameLen; i32Loop++)
+ {
+ pui8Buf[i32Loop] = g_pui8RxBuffer[i32Loop];
+ }
+ }
+ }
+
+ //
+ // Move on to the next descriptor in the chain.
+ //
+ g_ui32RxDescIndex++;
+ if(g_ui32RxDescIndex == NUM_RX_DESCRIPTORS)
+ {
+ g_ui32RxDescIndex = 0;
+ }
+
+ //
+ // Mark the next descriptor in the ring as available for the receiver to
+ // write into.
+ //
+ g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus = DES0_RX_CTRL_OWN;
+
+ //
+ // Return the Frame Length
+ //
+ return(i32FrameLen);
+}
+
+//*****************************************************************************
+//
+// Transmit a packet from the supplied buffer.
+//
+//*****************************************************************************
+static int32_t
+PacketTransmit(uint8_t *pui8Buf, int32_t i32BufLen)
+{
+ int_fast32_t i32Loop;
+
+ //
+ // Wait for the previous packet to be transmitted.
+ //
+ while(g_psTxDescriptor[g_ui32TxDescIndex].ui32CtrlStatus &
+ DES0_TX_CTRL_OWN)
+ {
+ }
+
+ //
+ // Check that we're not going to overflow the transmit buffer. This
+ // shouldn't be necessary since the uIP buffer is smaller than our DMA
+ // transmit buffer but, just in case...
+ //
+ if(i32BufLen > TX_BUFFER_SIZE)
+ {
+ i32BufLen = TX_BUFFER_SIZE;
+ }
+
+ //
+ // Copy the packet data into the transmit buffer.
+ //
+ for(i32Loop = 0; i32Loop < i32BufLen; i32Loop++)
+ {
+ g_pui8TxBuffer[i32Loop] = pui8Buf[i32Loop];
+ }
+
+ //
+ // Move to the next descriptor.
+ //
+ g_ui32TxDescIndex++;
+ if(g_ui32TxDescIndex == NUM_TX_DESCRIPTORS)
+ {
+ g_ui32TxDescIndex = 0;
+ }
+
+ //
+ // Fill in the packet size and tell the transmitter to start work.
+ //
+ g_psTxDescriptor[g_ui32TxDescIndex].ui32Count = (uint32_t)i32BufLen;
+ g_psTxDescriptor[g_ui32TxDescIndex].ui32CtrlStatus =
+ (DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG |
+ DES0_TX_CTRL_INTERRUPT | DES0_TX_CTRL_IP_ALL_CKHSUMS |
+ DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_OWN);
+
+ //
+ // Tell the DMA to reacquire the descriptor now that we've filled it in.
+ //
+ ROM_EMACTxDMAPollDemand(EMAC0_BASE);
+
+ //
+ // Return the number of bytes sent.
+ //
+ return(i32BufLen);
+}
+
+//*****************************************************************************
+//
+//! Constructs and sends a BOOTP request packet.
+//!
+//! This function constructs a BOOTP request packet and sends it as a broadcast
+//! message to the network.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+SendBOOTPRequest(void)
+{
+ uint8_t *pui8Packet = (uint8_t *)uip_appdata;
+ tBOOTPPacket *psBOOTP = (tBOOTPPacket *)uip_appdata;
+ uint32_t ui32Idx;
+
+ //
+ // Zero fill the BOOTP request packet.
+ //
+ for(ui32Idx = 0; ui32Idx < sizeof(tBOOTPPacket); ui32Idx++)
+ {
+ pui8Packet[ui32Idx] = 0;
+ }
+
+ //
+ // Construct a BOOTP request.
+ //
+ psBOOTP->ui8Op = BOOTP_REQUEST;
+
+ //
+ // Set the hardware type to Ethernet.
+ //
+ psBOOTP->ui8HType = 0x01;
+
+ //
+ // Set the hardware address length to 6.
+ //
+ psBOOTP->ui8HLen = 0x06;
+
+ //
+ // Choose a random number for the transaction ID.
+ //
+ psBOOTP->ui32XID = g_ui32XID = RandomNumber();
+
+ //
+ // Set the number of seconds since we started.
+ //
+ psBOOTP->ui16Secs = HTONS(g_ui32Ticks / SYSTICKHZ);
+
+ //
+ // Fill in the Ethernet MAC address.
+ //
+ for(ui32Idx = 0; ui32Idx < 6; ui32Idx++)
+ {
+ psBOOTP->pui8CHAddr[ui32Idx] = g_sMACAddr.addr[ui32Idx];
+ }
+
+ //
+ // Set the server name if defined.
+ //
+#ifdef ENET_BOOTP_SERVER
+ for(ui32Idx = 0;
+ (psBOOTP->pcSName[ui32Idx] = ENET_BOOTP_SERVER[ui32Idx]) != 0;
+ ui32Idx++)
+ {
+ }
+#endif
+
+ //
+ // Send the BOOTP request packet.
+ //
+ uip_udp_send(sizeof(tBOOTPPacket));
+}
+
+//*****************************************************************************
+//
+//! Parses a packet checking for a BOOTP reply message.
+//!
+//! This function parses a packet to determine if it is a BOOTP reply to our
+//! currently outstanding BOOTP request. If a valid reply is found, the
+//! appropriate information from the packet is extracted and saved.
+//!
+//! \return Returns 1 if a valid BOOTP reply message was found and 0 otherwise.
+//
+//*****************************************************************************
+static uint32_t
+ParseBOOTPReply(void)
+{
+ tBOOTPPacket *psBOOTP = (tBOOTPPacket *)uip_appdata;
+ uint32_t ui32Idx;
+
+ //
+ // See if this is a reply for our current BOOTP request.
+ //
+ if((psBOOTP->ui8Op != BOOTP_REPLY) ||
+ (psBOOTP->ui32XID != g_ui32XID) ||
+ (*(uint32_t *)psBOOTP->pui8CHAddr != *(uint32_t *)g_sMACAddr.addr) ||
+ (*(uint16_t *)(psBOOTP->pui8CHAddr + 4) !=
+ *(uint16_t *)(g_sMACAddr.addr + 4)))
+ {
+ return(0);
+ }
+
+ //
+ // Extract our IP address from the response.
+ //
+ *((uint32_t *)(void *)(&uip_hostaddr)) = psBOOTP->ui32YIAddr;
+
+ //
+ // Extract the server address from the response.
+ //
+ *((uint32_t *)(void *)(&g_sServerAddr)) = psBOOTP->ui32SIAddr;
+
+ //
+ // Save the boot file name.
+ //
+ for(ui32Idx = 0;
+ ((g_pcFilename[ui32Idx] = psBOOTP->pcFile[ui32Idx]) != 0) &&
+ (ui32Idx < (sizeof(g_pcFilename) - 1));
+ ui32Idx++)
+ {
+ }
+ g_pcFilename[ui32Idx] = 0;
+
+ //
+ // A valid BOOTP reply was found and decoded.
+ //
+ return(1);
+}
+
+
+//*****************************************************************************
+//
+//! Constructs and sends a TFTP error packet.
+//!
+//! This function constructs a TFTP read request packet (RRQ) and sends it to
+//! the server.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+SendTFTPError(uint16_t ui16Error, char *pcString)
+{
+ uint8_t *pui8Packet = (uint8_t *)uip_appdata;
+ int32_t i32Len;
+
+ pui8Packet[0] = (TFTP_ERROR >> 8) & 0xff;
+ pui8Packet[1] = TFTP_ERROR & 0xff;
+ pui8Packet[2] = (ui16Error >> 8) & 0xFF;
+ pui8Packet[3] = ui16Error & 0xFF;
+
+ //
+ // Get ready to copy the error string.
+ //
+ i32Len = 4;
+ pui8Packet += 4;
+
+ //
+ // Copy as much of the string as we can fit.
+ //
+ while((i32Len < (UIP_APPDATA_SIZE - 1)) && *pcString)
+ {
+ *pui8Packet++ = *pcString++;
+ i32Len++;
+ }
+
+ //
+ // Write the terminating 0.
+ //
+ *pui8Packet = (uint8_t)0;
+
+ //
+ // Send the error packet.
+ //
+ uip_udp_send(i32Len + 1);
+}
+
+//*****************************************************************************
+//
+//! Constructs and sends a TFTP read packet.
+//!
+//! This function constructs a TFTP read request packet (RRQ) and sends it to
+//! the server.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+SendTFTPGet(void)
+{
+ uint8_t *pui8Packet = (uint8_t *)uip_appdata;
+ uint32_t ui32Idx;
+ char *pcFilename;
+
+ //
+ // The TFTP RRQ packet should be sent to the TFTP server port.
+ //
+ g_pConn->rport = HTONS(TFTP_PORT);
+
+ //
+ // Set the TFTP packet opcode to RRQ.
+ //
+ pui8Packet[0] = (TFTP_RRQ >> 8) & 0xff;
+ pui8Packet[1] = TFTP_RRQ & 0xff;
+
+ //
+ // Copy the file name into the RRQ packet.
+ //
+ for(ui32Idx = 2, pcFilename = g_pcFilename;
+ (pui8Packet[ui32Idx++] = *pcFilename++) != 0; )
+ {
+ }
+
+ //
+ // Set the transfer mode to binary.
+ //
+ for(pcFilename = "octet"; (pui8Packet[ui32Idx++] = *pcFilename++) != 0; )
+ {
+ }
+
+ //
+ // Send the TFTP read packet.
+ //
+ uip_udp_send(ui32Idx);
+}
+
+//*****************************************************************************
+//
+//! Parses a packet checking for a TFTP data packet.
+//!
+//! This function parses a packet to determine if it is a TFTP data packet for
+//! out current TFTP transfer. If a valid packet is found, the contents of the
+//! packet are programmed into flash.
+//!
+//! \return Returns 1 if this packet was the last packet of the TFTP data
+//! transfer and 0 otherwise.
+//
+//*****************************************************************************
+static uint32_t
+ParseTFTPData(void)
+{
+ uint8_t *pui8Packet = (uint8_t *)uip_appdata;
+ uint32_t ui32FlashAddr;
+ uint32_t ui32Idx;
+
+ //
+ // See if this is a TFTP data packet.
+ //
+ if((pui8Packet[0] != ((TFTP_DATA >> 8) && 0xff)) ||
+ (pui8Packet[1] != (TFTP_DATA & 0xff)))
+ {
+ return(0);
+ }
+
+ //
+ // If the remote port on our connection is still the TFTP server port (i.e.
+ // this is the first data packet), then copy the transaction ID for the
+ // TFTP data connection into our connection. This will ensure that our
+ // response will be sent to the correct port.
+ //
+ if(g_pConn->rport == HTONS(TFTP_PORT))
+ {
+ g_pConn->rport =
+ ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->srcport;
+ }
+
+ //
+ // See if this is the correct data packet.
+ //
+ if((pui8Packet[2] != ((g_ui32TFTPBlock >> 8) & 0xff)) ||
+ (pui8Packet[3] != (g_ui32TFTPBlock & 0xff)))
+ {
+ //
+ // Since the wrong data packet was sent, resend the ACK for it since
+ // we've already processed it.
+ //
+ pui8Packet[0] = (TFTP_ACK >> 8) & 0xff;
+ pui8Packet[1] = TFTP_ACK & 0xff;
+ uip_udp_send(4);
+
+ //
+ // Ignore this packet.
+ //
+ return(0);
+ }
+
+ //
+ // What address are we about to program to?
+ //
+ ui32FlashAddr =
+ ((g_ui32TFTPBlock - 1) * TFTP_BLOCK_SIZE) + APP_START_ADDRESS;
+
+ //
+ // Do not program this data into flash if it is beyond the end of flash.
+ //
+ if(ui32FlashAddr < g_ui32FlashEnd)
+ {
+ //
+ // If this is the first block and we have been provided with a start
+ // hook function, call it here to indicate that we are about to begin
+ // flashing a new image.
+ //
+#ifdef BL_START_FN_HOOK
+ if(g_ui32TFTPBlock == 1)
+ {
+ BL_START_FN_HOOK();
+ }
+#endif
+
+ //
+ // Clear any flash error indicator.
+ //
+ BL_FLASH_CL_ERR_FN_HOOK();
+
+ //
+ // If this is the first data packet and code protection is enabled,
+ // then erase the entire flash.
+ //
+#ifdef FLASH_CODE_PROTECTION
+ if(g_ui32TFTPBlock == 1)
+ {
+ //
+ // Loop through the pages in the flash, excluding the pages that
+ // contain the boot loader and the optional reserved space.
+ //
+ for(ui32Idx = APP_START_ADDRESS; ui32Idx < g_ui32FlashEnd;
+ ui32Idx += FLASH_PAGE_SIZE)
+ {
+ //
+ // Erase this block of the flash.
+ //
+ BL_FLASH_ERASE_FN_HOOK((ui32Idx);
+ }
+ }
+#else
+ //
+ // Flash code protection is not enabled, so see if the data in this
+ // packet will be programmed to the beginning of a flash block. We
+ // assume that the flash block size is always a multiple of 1KB so,
+ // since each TFTP packet is 512 bytes and that the start must always
+ // be on a flash page boundary, we can be sure that we will hit the
+ // start of each page as we receive packets.
+ //
+ if(!(ui32FlashAddr & (FLASH_PAGE_SIZE - 1)))
+ {
+ //
+ // Erase this block of the flash.
+ //
+ BL_FLASH_ERASE_FN_HOOK(ui32FlashAddr);
+ }
+#endif
+
+ //
+ // Decrypt the data if required.
+ //
+#ifdef BL_DECRYPT_FN_HOOK
+ BL_DECRYPT_FN_HOOK(pui8Packet + 4, uip_len - 4);
+#endif
+
+ //
+ // Program this block of data into flash.
+ //
+ BL_FLASH_PROGRAM_FN_HOOK(ui32FlashAddr, (pui8Packet + 4),
+ (uip_len - 4));
+
+ //
+ // If a progress reporting hook function has been provided, call it
+ // here. The TFTP protocol doesn't let us know how large the image is
+ // before it starts the transfer so we pass 0 as the ui32Total
+ // parameter to indicate this.
+ //
+#ifdef BL_PROGRESS_FN_HOOK
+ BL_PROGRESS_FN_HOOK(((ui32FlashAddr - APP_START_ADDRESS) +
+ (uip_len - 4)), 0);
+#endif
+ }
+
+ //
+ // Increment to the next block.
+ //
+ g_ui32TFTPBlock++;
+
+ //
+ // Save the packet length.
+ //
+ ui32Idx = uip_len;
+
+ //
+ // Did we see any error?
+ //
+ if(BL_FLASH_ERROR_FN_HOOK())
+ {
+ //
+ // Yes - send back an error packet.
+ //
+ SendTFTPError(2, "Error programming flash.");
+ }
+ else
+ {
+ //
+ // No errors reported so construct an ACK packet. The block number
+ // field is already correct, so it does not need to be set.
+ //
+ pui8Packet[0] = (TFTP_ACK >> 8) & 0xff;
+ pui8Packet[1] = TFTP_ACK & 0xff;
+
+ //
+ // Send the ACK packet to the TFTP server.
+ //
+ uip_udp_send(4);
+ }
+
+ //
+ // If the packet was shorter than TFTP_BLOCK_SIZE bytes then this was the
+ // last packet in the file.
+ //
+ if(ui32Idx != (TFTP_BLOCK_SIZE + 4))
+ {
+ //
+ // If an end signal hook function has been provided, call it here.
+ //
+#ifdef BL_END_FN_HOOK
+ BL_END_FN_HOOK();
+#endif
+ return(1);
+ }
+ //
+ // There is more data to be read.
+ //
+ return(0);
+}
+
+uint16_t
+LOCAL_EMACPHYRead(uint32_t ui32Base, uint8_t ui8PhyAddr, uint8_t ui8RegAddr)
+{
+
+ //
+ // Make sure the MII is idle.
+ //
+ while(HWREG(ui32Base + EMAC_O_MIIADDR) & EMAC_MIIADDR_MIIB)
+ {
+ }
+
+ //
+ // Tell the MAC to read the given PHY register.
+ //
+ HWREG(ui32Base + EMAC_O_MIIADDR) =
+ ((HWREG(ui32Base + EMAC_O_MIIADDR) & EMAC_MIIADDR_CR_M) |
+ (ui8RegAddr << EMAC_MIIADDR_MII_S) |
+ (ui8PhyAddr << EMAC_MIIADDR_PLA_S) | EMAC_MIIADDR_MIIB);
+
+ //
+ // Wait for the read to complete.
+ //
+ while(HWREG(ui32Base + EMAC_O_MIIADDR) & EMAC_MIIADDR_MIIB)
+ {
+ }
+
+ //
+ // Return the result.
+ //
+ return(HWREG(ui32Base + EMAC_O_MIIDATA) & EMAC_MIIDATA_DATA_M);
+}
+
+//*****************************************************************************
+//
+//! Handles the BOOTP process.
+//!
+//! This function contains the proto-thread for handling the BOOTP process. It
+//! first communicates with the BOOTP server to get its boot parameters (IP
+//! address, server address, and file name), then it communicates with the TFTP
+//! server on the specified server to read the firmware image file.
+//!
+//! \return None.
+//
+//*****************************************************************************
+#ifdef DOXYGEN
+char
+BOOTPThread(void)
+#else
+PT_THREAD(BOOTPThread(void))
+#endif
+{
+ //
+ // Begin the proto-thread.
+ //
+ PT_BEGIN(&g_sThread);
+
+wait_for_link:
+ PT_WAIT_UNTIL(&g_sThread,
+ (LOCAL_EMACPHYRead(EMAC0_BASE, 0, EPHY_BMSR) &
+ EPHY_BMSR_LINKSTAT) != 0);
+
+ //
+ // Reset the host address.
+ //
+ *((uint32_t *)(void *)(&uip_hostaddr)) = 0;
+
+ //
+ // Re-bind the UDP socket for sending requests to the BOOTP server.
+ //
+ uip_udp_remove(g_pConn);
+ *((uint32_t *)(void *)(&g_sServerAddr)) = 0xffffffff;
+ uip_udp_new(&g_sServerAddr, HTONS(BOOTP_SERVER_PORT));
+ uip_udp_bind(g_pConn, HTONS(BOOTP_CLIENT_PORT));
+
+ //
+ // Set the initial delay between BOOTP requests to 1 second.
+ //
+ g_ui32Delay = SYSTICKHZ;
+
+ //
+ // Loop forever. This loop is explicitly exited when a valid BOOTP reply
+ // is received.
+ //
+ while(1)
+ {
+ //
+ // Send a BOOTP request.
+ //
+ SendBOOTPRequest();
+
+ //
+ // Set the amount of time to wait for the BOOTP reply message.
+ //
+ g_ui32Target = g_ui32Ticks + g_ui32Delay;
+
+ //
+ // Wait until a packet is received or the timeout has occurred.
+ //
+wait_for_bootp_reply:
+ PT_WAIT_UNTIL(&g_sThread,
+ ((g_ui32Link = (LOCAL_EMACPHYRead(EMAC0_BASE, 0, EPHY_BMSR) &
+ EPHY_BMSR_LINKSTAT)) == 0) ||
+ uip_newdata() || (g_ui32Ticks > g_ui32Target));
+
+ //
+ // If the link has been lost, go back to waiting for a link.
+ //
+ if(g_ui32Link == 0)
+ {
+ goto wait_for_link;
+ }
+
+ //
+ // See if a packet has been received.
+ //
+ if(uip_newdata())
+ {
+ //
+ // Clear the new data flag so that this packet will only be
+ // examined one time.
+ //
+ uip_flags &= ~(UIP_NEWDATA);
+
+ //
+ // See if this is a BOOTP reply.
+ //
+ if(ParseBOOTPReply() == 1)
+ {
+ break;
+ }
+
+ //
+ // This was not a BOOTP reply packet, so go back to waiting.
+ //
+ goto wait_for_bootp_reply;
+ }
+
+ //
+ // If the delay between BOOTP requests is less than 60 seconds, double
+ // the delay time. This avoids constantly slamming the network with
+ // requests.
+ //
+ if(g_ui32Delay < (60 * SYSTICKHZ))
+ {
+ g_ui32Delay *= 2;
+ }
+ }
+
+ //
+ // Reconfigure the UDP socket to target the TFTP port on the server.
+ //
+ uip_ipaddr_copy(&g_pConn->ripaddr, g_sServerAddr);
+ uip_udp_bind(g_pConn, HTONS(13633));
+
+ //
+ // Send a TFTP read request.
+ //
+ SendTFTPGet();
+
+ //
+ // Since the first TFTP read request will result in an ARP request, delay
+ // for just a bit and then re-issue the TFTP read request.
+ //
+ PT_YIELD(&g_sThread);
+
+ //
+ // Resend the TFTP read request. If the ARP request has already been
+ // answered, this will go out as is and avoid the two second timeout below.
+ //
+ SendTFTPGet();
+
+ //
+ // Start the TFTP transfer from block one.
+ //
+ g_ui32TFTPBlock = 1;
+
+ //
+ // Set the number of TFTP retries to zero.
+ //
+ g_ui32TFTPRetries = 0;
+
+ //
+ // Loop forever. This loop is explicitly exited when the TFTP transfer has
+ // completed.
+ //
+ while(1)
+ {
+ //
+ // Set the amount of time to wait for the TFTP data packet.
+ //
+ g_ui32Target = g_ui32Ticks + (SYSTICKHZ * 4);
+
+ //
+ // Wait until a packet is received or the timeout has occurred.
+ //
+ PT_WAIT_UNTIL(&g_sThread,
+ ((g_ui32Link = (LOCAL_EMACPHYRead(EMAC0_BASE, 0, EPHY_BMSR) &
+ EPHY_BMSR_LINKSTAT)) == 0) ||
+ uip_newdata() || (g_ui32Ticks > g_ui32Target));
+
+ //
+ // If the link has been lost, go back to waiting for a link.
+ //
+ if(g_ui32Link == 0)
+ {
+ goto wait_for_link;
+ }
+
+ //
+ // See if a packet has been received.
+ //
+ if(uip_newdata())
+ {
+ //
+ // Clear the new data flag so that this packet will only be
+ // examined one time.
+ //
+ uip_flags &= ~(UIP_NEWDATA);
+
+ //
+ // See if this is a TFTP data packet.
+ //
+ if(ParseTFTPData() == 1)
+ {
+ break;
+ }
+ }
+ else if(g_ui32TFTPRetries < 3)
+ {
+ //
+ // The transfer timed out, so send a new TFTP read request.
+ //
+ SendTFTPGet();
+
+ //
+ // Start the TFTP transfer from block one.
+ //
+ g_ui32TFTPBlock = 1;
+
+ //
+ // Increment the count of TFTP retries.
+ //
+ g_ui32TFTPRetries++;
+ }
+ else
+ {
+ //
+ // The TFTP transfer failed after three retries, so start over.
+ //
+ goto wait_for_link;
+ }
+ }
+ //
+ // Wait for the last packet to be transmitted.
+ //
+ while(g_psTxDescriptor[g_ui32TxDescIndex].ui32CtrlStatus &
+ DES0_TX_CTRL_OWN)
+ {
+ }
+
+ //
+ // Wait for a bit to make sure that the final ACK packet is transmitted.
+ //
+ g_ui32Target = g_ui32Ticks + (SYSTICKHZ / 4);
+ while(g_ui32Ticks < g_ui32Target)
+ {
+ PT_YIELD(&g_sThread);
+ }
+
+ //
+ // 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)
+ {
+ }
+
+ //
+ // End the proto-thread.
+ //
+ PT_END(&g_sThread);
+}
+
+static void
+LOCAL_EMACPHYConfigSet(uint32_t ui32Base, uint32_t ui32Config)
+{
+ //
+ // Write the Ethernet PHY configuration to the peripheral configuration
+ // register.
+ //
+ HWREG(ui32Base + EMAC_O_PC) = ui32Config;
+
+ //
+ // If using the internal PHY, reset it to ensure that new configuration is
+ // latched there.
+ //
+ if((ui32Config & EMAC_PHY_TYPE_MASK) == EMAC_PHY_TYPE_INTERNAL)
+ {
+ ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);
+ while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_EPHY0))
+ {
+ //
+ // Wait for the PHY reset to complete.
+ //
+ }
+
+ //
+ // Delay a bit longer to ensure that the PHY reset has completed.
+ //
+ ROM_SysCtlDelay(1000);
+ }
+
+ //
+ // If using an external RMII PHY, we must set 2 bits in the Ethernet MAC
+ // Clock Configuration Register.
+ //
+ if((ui32Config & EMAC_PHY_TYPE_MASK) == EMAC_PHY_TYPE_EXTERNAL_RMII)
+ {
+ //
+ // Select and enable the external clock from the RMII PHY.
+ //
+ HWREG(EMAC0_BASE + EMAC_O_CC) |= EMAC_CC_CLKEN;
+ }
+ else
+ {
+ //
+ // Disable the external clock.
+ //
+ HWREG(EMAC0_BASE + EMAC_O_CC) &= ~EMAC_CC_CLKEN;
+ }
+
+ //
+ // Reset the MAC regardless of whether the PHY connection changed or not.
+ //
+ ROM_EMACReset(EMAC0_BASE);
+
+ ROM_SysCtlDelay(1000);
+}
+
+//*****************************************************************************
+//
+//! Reconfigures the Ethernet controller.
+//!
+//! \param ui32Clock is the system clock frequency.
+//!
+//! This function reconfigures the Ethernet controller, preparing it for use by
+//! the boot loader. This performs the steps common between the direct
+//! invocation of the boot loader and the application invocation of the boot
+//! loader.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+EnetReconfig(uint32_t ui32Clock)
+{
+ uip_ipaddr_t sAddr;
+ uint32_t ui32Loop;
+ uint32_t ui32User0, ui32User1;
+
+ //
+ // Configure for use with the internal PHY.
+ //
+ LOCAL_EMACPHYConfigSet(EMAC0_BASE,
+ (EMAC_PHY_TYPE_INTERNAL | EMAC_PHY_INT_MDIX_EN |
+ EMAC_PHY_AN_100B_T_FULL_DUPLEX));
+
+
+ //
+ // Reset the MAC.
+ //
+ ROM_EMACReset(EMAC0_BASE);
+
+ //
+ // Initialize the MAC and set the DMA mode.
+ //
+ ROM_EMACInit(EMAC0_BASE, ui32Clock,
+ EMAC_BCONFIG_MIXED_BURST | EMAC_BCONFIG_PRIORITY_FIXED, 4, 4, 0);
+
+ //
+ // Get the MAC address from the flash user registers. If it has not been
+ // programmed, then use the boot loader default MAC address.
+ //
+ ROM_FlashUserGet(&ui32User0, &ui32User1);
+ if((ui32User0 == 0xffffffff) || (ui32User1 == 0xffffffff))
+ {
+ //
+ // MAC address has not been programmed, use default.
+ //
+ g_sMACAddr.addr[0] = 0x00;
+ g_sMACAddr.addr[1] = 0x1a;
+ g_sMACAddr.addr[2] = 0xb6;
+ g_sMACAddr.addr[3] = 0x00;
+ g_sMACAddr.addr[4] = 0x64;
+ g_sMACAddr.addr[5] = 0x00;
+ }
+ else
+ {
+ g_sMACAddr.addr[0] = ui32User0 & 0xff;
+ g_sMACAddr.addr[1] = (ui32User0 >> 8) & 0xff;
+ g_sMACAddr.addr[2] = (ui32User0 >> 16) & 0xff;
+ g_sMACAddr.addr[3] = ui32User1 & 0xff;
+ g_sMACAddr.addr[4] = (ui32User1 >> 8) & 0xff;
+ g_sMACAddr.addr[5] = (ui32User1 >> 16) & 0xff;
+ }
+
+ //
+ // Set MAC configuration options.
+ //
+ ROM_EMACConfigSet(EMAC0_BASE,
+ (EMAC_CONFIG_FULL_DUPLEX | EMAC_CONFIG_CHECKSUM_OFFLOAD |
+ EMAC_CONFIG_7BYTE_PREAMBLE | EMAC_CONFIG_IF_GAP_96BITS |
+ EMAC_CONFIG_USE_MACADDR0 | EMAC_CONFIG_SA_FROM_DESCRIPTOR |
+ EMAC_CONFIG_BO_LIMIT_1024),
+ (EMAC_MODE_RX_STORE_FORWARD | EMAC_MODE_TX_STORE_FORWARD |
+ EMAC_MODE_TX_THRESHOLD_64_BYTES |
+ EMAC_MODE_RX_THRESHOLD_64_BYTES), 0);
+
+ //
+ // Initialize each of the transmit descriptors. Note that we leave the OWN
+ // bit clear here since we have not set up any transmissions yet.
+ //
+ for(ui32Loop = 0; ui32Loop < NUM_TX_DESCRIPTORS; ui32Loop++)
+ {
+ g_psTxDescriptor[ui32Loop].ui32Count =
+ (DES1_TX_CTRL_SADDR_INSERT |
+ (TX_BUFFER_SIZE << DES1_TX_CTRL_BUFF1_SIZE_S));
+ g_psTxDescriptor[ui32Loop].pvBuffer1 = g_pui8TxBuffer;
+ g_psTxDescriptor[ui32Loop].DES3.pLink =
+ (ui32Loop == (NUM_TX_DESCRIPTORS - 1)) ?
+ g_psTxDescriptor : &g_psTxDescriptor[ui32Loop + 1];
+ g_psTxDescriptor[ui32Loop].ui32CtrlStatus =
+ (DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG |
+ DES0_TX_CTRL_INTERRUPT | DES0_TX_CTRL_CHAINED |
+ DES0_TX_CTRL_IP_ALL_CKHSUMS);
+ }
+
+ //
+ // Initialize each of the receive descriptors. We clear the OWN bit here
+ // to make sure that the receiver doesn't start writing anything
+ // immediately.
+ //
+ for(ui32Loop = 0; ui32Loop < NUM_RX_DESCRIPTORS; ui32Loop++)
+ {
+ g_psRxDescriptor[ui32Loop].ui32CtrlStatus = 0;
+ g_psRxDescriptor[ui32Loop].ui32Count =
+ (DES1_RX_CTRL_CHAINED |
+ (RX_BUFFER_SIZE << DES1_RX_CTRL_BUFF1_SIZE_S));
+ g_psRxDescriptor[ui32Loop].pvBuffer1 = g_pui8RxBuffer;
+ g_psRxDescriptor[ui32Loop].DES3.pLink =
+ (ui32Loop == (NUM_RX_DESCRIPTORS - 1)) ?
+ g_psRxDescriptor : &g_psRxDescriptor[ui32Loop + 1];
+ }
+
+ //
+ // Set the descriptor pointers in the hardware.
+ //
+ ROM_EMACRxDMADescriptorListSet(EMAC0_BASE, g_psRxDescriptor);
+ ROM_EMACTxDMADescriptorListSet(EMAC0_BASE, g_psTxDescriptor);
+
+ //
+ // Start from the beginning of both descriptor chains. We actually set
+ // the transmit descriptor index to the last descriptor in the chain
+ // since it will be incremented before use and this means the first
+ // transmission we perform will use the correct descriptor.
+ //
+ g_ui32RxDescIndex = 0;
+ g_ui32TxDescIndex = NUM_TX_DESCRIPTORS - 1;
+
+ //
+ // Program the MAC address.
+ //
+ ROM_EMACAddrSet(EMAC0_BASE, 0, g_sMACAddr.addr);
+
+ //
+ // Wait for the link to become active.
+ //
+ while((ROM_EMACPHYRead(EMAC0_BASE, 0, EPHY_BMSR) &
+ EPHY_BMSR_LINKSTAT) == 0)
+ {
+ }
+
+ //
+ // Set MAC filtering options. We receive all broadcast and multicast
+ // packets along with those addressed specifically for us.
+ //
+ ROM_EMACFrameFilterSet(EMAC0_BASE, (EMAC_FRMFILTER_SADDR |
+ EMAC_FRMFILTER_PASS_MULTICAST |
+ EMAC_FRMFILTER_PASS_NO_CTRL));
+
+ //
+ // Seed the random number generator from the MAC address.
+ //
+ g_ui32RandomSeed = *(uint32_t *)(g_sMACAddr.addr + 2);
+
+ //
+ // Initialize the uIP stack.
+ //
+ uip_init();
+ uip_arp_init();
+
+ //
+ // Set the MAC address.
+ //
+ uip_setethaddr(g_sMACAddr);
+
+ //
+ // Initialize the proto-thread used by the BOOTP protocol handler.
+ //
+ PT_INIT(&g_sThread);
+
+ //
+ // Create a UDP socket for sending requests to the BOOTP server. After the
+ // BOOTP portion of the protocol has been handled, this socket will be
+ // reused to communicate with the TFTP server.
+ //
+ *((uint32_t *)(void *)(&sAddr)) = 0xffffffff;
+ g_pConn = uip_udp_new(&sAddr, HTONS(BOOTP_SERVER_PORT));
+ uip_udp_bind(g_pConn, HTONS(BOOTP_CLIENT_PORT));
+
+ //
+ // Enable the Ethernet MAC transmitter and receiver.
+ //
+ ROM_EMACTxEnable(EMAC0_BASE);
+ ROM_EMACRxEnable(EMAC0_BASE);
+
+ //
+ // Mark the first receive descriptor as available to the DMA to start
+ // the receive processing.
+ //
+ g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus |= DES0_RX_CTRL_OWN;
+
+ //
+ // Reset the counters that are incremented by SysTick.
+ //
+ g_ui32Ticks = 0;
+ g_ui32PeriodicTimer = 0;
+ g_ui32ARPTimer = 0;
+
+ //
+ // Setup SysTick.
+ //
+ HWREG(NVIC_ST_RELOAD) = (ui32Clock / SYSTICKHZ) - 1;
+ HWREG(NVIC_ST_CTRL) = (NVIC_ST_CTRL_CLK_SRC | NVIC_ST_CTRL_INTEN |
+ NVIC_ST_CTRL_ENABLE);
+}
+//*****************************************************************************
+//
+//! Configures the Ethernet controller.
+//!
+//! This function configures the Ethernet controller, preparing it for use by
+//! the boot loader.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+ConfigureEnet(void)
+{
+ //
+ // Make sure the main oscillator is enabled because this is required by
+ // the PHY. The system must have a 25MHz crystal attached to the OSC
+ // pins. The SYSCTL_MOSC_HIGHFREQ parameter is used when the crystal
+ // frequency is 10MHz or higher.
+ //
+ HWREG(SYSCTL_MOSCCTL) = SYSCTL_MOSC_HIGHFREQ;
+
+ //
+ // Delay while the main oscillator starts up.
+ //
+ Delay(5242880);
+
+ MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
+ SYSCTL_OSC_MAIN |
+ SYSCTL_USE_PLL |
+ SYSCTL_CFG_VCO_480), 120000000);
+
+
+#ifdef ENET_ENABLE_LEDS
+ //
+ // PF1/PK4/PK6 are used for Ethernet LEDs.
+ //
+ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
+ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
+ ROM_GPIOPinConfigure(GPIO_PF1_EN0LED2);
+ ROM_GPIOPinConfigure(GPIO_PK4_EN0LED0);
+ ROM_GPIOPinConfigure(GPIO_PK6_EN0LED1);
+
+ //
+ // Make the pin(s) be peripheral controlled.
+ //
+ ROM_GPIODirModeSet(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_DIR_MODE_HW);
+ ROM_GPIODirModeSet(GPIO_PORTK_BASE, GPIO_PIN_4|GPIO_PIN_6, GPIO_DIR_MODE_HW);
+
+ //
+ // Set the pad(s) for standard push-pull operation.
+ //
+ ROM_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
+ ROM_GPIOPadConfigSet(GPIO_PORTK_BASE, GPIO_PIN_4|GPIO_PIN_6, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
+#endif
+
+ //
+ // Enable and reset the Ethernet modules.
+ //
+ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
+ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
+ ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
+ ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);
+
+ while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0))
+ {
+ }
+
+}
+
+//*****************************************************************************
+//
+//! Starts the update process via BOOTP.
+//!
+//! This function starts the Ethernet firmware update process. The BOOTP
+//! (as defined by RFC951 at http://tools.ietf.org/html/rfc951) and TFTP (as
+//! defined by RFC1350 at http://tools.ietf.org/html/rfc1350) protocols are
+//! used to transfer the firmware image over Ethernet.
+//!
+//! \return Never returns.
+//
+//*****************************************************************************
+void
+UpdateBOOTP(void)
+{
+ //
+ // Get the size of flash.
+ //
+ g_ui32FlashEnd = ROM_SysCtlFlashSizeGet();
+#ifdef FLASH_RSVD_SPACE
+ g_ui32FlashEnd -= FLASH_RSVD_SPACE;
+#endif
+
+ //
+ // Perform the common Ethernet configuration. The frequency should
+ // match whatever the application sets the system clock.
+ //
+ EnetReconfig(120000000);
+
+ //
+ // Main Application Loop.
+ //
+ while(1)
+ {
+ uint32_t ui32Temp;
+
+ //
+ // See if there is a packet waiting to be read.
+ //
+ if(!(g_psRxDescriptor[g_ui32RxDescIndex].ui32CtrlStatus &
+ DES0_RX_CTRL_OWN))
+ {
+ //
+ // Read the packet from the Ethernet controller.
+ //
+ uip_len = PacketReceive(uip_buf, UIP_CONF_BUFFER_SIZE);
+
+ //
+ // See if this is an IP packet.
+ //
+ if((uip_len != 0) &&
+ (((struct uip_eth_hdr *)&uip_buf[0])->type ==
+ HTONS(UIP_ETHTYPE_IP)))
+ {
+ //
+ // Update the ARP tables based on this packet.
+ //
+ uip_arp_ipin();
+
+ //
+ // Process this packet.
+ //
+ uip_input();
+
+ //
+ // See if the processing of this packet resulted in a packet to be
+ // sent.
+ //
+ if(uip_len > 0)
+ {
+ //
+ // Update the ARP tables based on the packet to be sent.
+ //
+ uip_arp_out();
+
+ //
+ // Send the packet.
+ //
+ PacketTransmit(uip_buf, uip_len);
+
+ //
+ // Indicate that the packet has been sent.
+ //
+ uip_len = 0;
+ }
+ }
+
+ //
+ // See if this is an ARP packet.
+ //
+ else if((uip_len != 0) &&
+ (((struct uip_eth_hdr *)&uip_buf[0])->type ==
+ HTONS(UIP_ETHTYPE_ARP)))
+ {
+ //
+ // Process this packet.
+ //
+ uip_arp_arpin();
+
+ //
+ // See if the processing of this packet resulted in a packet to be
+ // sent.
+ //
+ if(uip_len > 0)
+ {
+ //
+ // Send the packet.
+ //
+ PacketTransmit(uip_buf, uip_len);
+
+ //
+ // Indicate that the packet has been sent.
+ //
+ uip_len = 0;
+ }
+ }
+ }
+
+ //
+ // See if the periodic timer has expired.
+ //
+ if(g_ui32PeriodicTimer > UIP_PERIODIC_TIMER_MS)
+ {
+ //
+ // Reset the periodic timer.
+ //
+ g_ui32PeriodicTimer = 0;
+
+ //
+ // Loop through the UDP connections.
+ //
+ for(ui32Temp = 0; ui32Temp < UIP_UDP_CONNS; ui32Temp++)
+ {
+ //
+ // Perform the periodic processing on this UDP connection.
+ //
+ uip_udp_periodic(ui32Temp);
+
+ //
+ // See if the periodic processing of this connection resulted in a
+ // packet to be sent.
+ //
+ if(uip_len > 0)
+ {
+ //
+ // Update the ARP tables based on the packet to be sent.
+ //
+ uip_arp_out();
+
+ //
+ // Send the packet.
+ //
+ PacketTransmit(uip_buf, uip_len);
+
+ //
+ // Indicate that the packet has been sent.
+ //
+ uip_len = 0;
+ }
+ }
+ }
+
+ //
+ // See if the ARP timer has expired.
+ //
+ if(g_ui32ARPTimer > UIP_ARP_TIMER_MS)
+ {
+ //
+ // Reset the ARP timer.
+ //
+ g_ui32ARPTimer = 0;
+
+ //
+ // Perform periodic processing on the ARP table.
+ //
+ uip_arp_timer();
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+#endif
diff --git a/boot_loader/bl_flash.c b/boot_loader/bl_flash.c new file mode 100644 index 0000000..3bbb0ee --- /dev/null +++ b/boot_loader/bl_flash.c @@ -0,0 +1,218 @@ +//*****************************************************************************
+//
+// bl_flash.c - Flash programming functions used by 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 "inc/hw_types.h"
+#include "inc/hw_flash.h"
+#include "inc/hw_sysctl.h"
+#include "inc/hw_memmap.h"
+#include "bl_config.h"
+#include "boot_loader/bl_flash.h"
+
+//*****************************************************************************
+//
+//! Erases a single 1KB block of internal flash.
+//!
+//! \param ui32Address is the address of the block of flash to erase.
+//!
+//! This function erases a single 1KB block of the internal flash, blocking
+//! until the erase has completed.
+//!
+//! \return None
+//
+//*****************************************************************************
+void
+BLInternalFlashErase(uint32_t ui32Address)
+{
+ //
+ // Erase this block of the flash.
+ //
+ HWREG(FLASH_FMA) = ui32Address;
+ HWREG(FLASH_FMC) = FLASH_FMC_WRKEY | FLASH_FMC_ERASE;
+
+ //
+ // Wait until the flash has been erased.
+ //
+ while(HWREG(FLASH_FMC) & FLASH_FMC_ERASE)
+ {
+ }
+}
+
+//*****************************************************************************
+//
+//! Programs a block of data at a given address in the internal flash.
+//!
+//! \param ui32DstAddr is the address of the first word to be programmed in
+//! flash.
+//! \param pui8SrcData is a pointer to the first byte to be programmed.
+//! \param ui32Length is the number of bytes to program. This must be a
+//! multiple of 4.
+//!
+//! This function writes a block of data to the internal flash at a given
+//! address. Since the flash is written a word at a time, the data must be a
+//! multiple of 4 bytes and the destination address, ui32DstAddr, must be on a
+//! word boundary.
+//!
+//! \return None
+//
+//*****************************************************************************
+void
+BLInternalFlashProgram(uint32_t ui32DstAddr, uint8_t *pui8SrcData,
+ uint32_t ui32Length)
+{
+ uint32_t ui32Loop;
+
+ for(ui32Loop = 0; ui32Loop < ui32Length; ui32Loop += 4)
+ {
+ //
+ // Program this word into flash.
+ //
+ HWREG(FLASH_FMA) = ui32DstAddr + ui32Loop;
+ HWREG(FLASH_FMD) = *(uint32_t *)(pui8SrcData + ui32Loop);
+ HWREG(FLASH_FMC) = FLASH_FMC_WRKEY | FLASH_FMC_WRITE;
+
+ //
+ // Wait until the flash has been programmed.
+ //
+ while(HWREG(FLASH_FMC) & FLASH_FMC_WRITE)
+ {
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! Returns the size of the internal flash in bytes.
+//!
+//! This function returns the total number of bytes of internal flash in the
+//! current part. No adjustment is made for any sections reserved via
+//! options defined in bl_config.h.
+//!
+//! \return Returns the total number of bytes of internal flash.
+//
+//*****************************************************************************
+uint32_t
+BLInternalFlashSizeGet(void)
+{
+ return(((HWREG(SYSCTL_DC0) & SYSCTL_DC0_FLASHSZ_M) + 1) << 11);
+}
+
+//*****************************************************************************
+//
+//! Checks whether a given start address is valid for a download.
+//!
+//! This function checks to determine whether the given address is a valid
+//! download image start address given the options defined in bl_config.h.
+//!
+//! \return Returns non-zero if the address is valid or 0 otherwise.
+//
+//*****************************************************************************
+uint32_t
+BLInternalFlashStartAddrCheck(uint32_t ui32Addr, uint32_t ui32ImgSize)
+{
+ uint32_t ui32FlashSize;
+
+ //
+ // Determine the size of the flash available on the part in use.
+ //
+ ui32FlashSize = ((HWREG(SYSCTL_DC0) & SYSCTL_DC0_FLASHSZ_M) + 1) << 11;
+
+ //
+ // If we are reserving space at the top of flash then this space is not
+ // available for application download but it is availble to be updated
+ // directly.
+ //
+#ifdef FLASH_RSVD_SPACE
+ if((ui32FlashSize - FLASH_RSVD_SPACE) != ui32Addr)
+ {
+ ui32FlashSize -= FLASH_RSVD_SPACE;
+ }
+#endif
+
+ //
+ // Is the address we were passed a valid start address? We allow:
+ //
+ // 1. Address 0 if configured to update the boot loader.
+ // 2. The start of the reserved block if parameter space is reserved (to
+ // allow a download of the parameter block contents).
+ // 3. The application start address specified in bl_config.h.
+ //
+ // The function fails if the address is not one of these, if the image
+ // size is larger than the available space or if the address is not word
+ // aligned.
+ //
+ if((
+#ifdef ENABLE_BL_UPDATE
+ (ui32Addr != 0) &&
+#endif
+#ifdef FLASH_RSVD_SPACE
+ (ui32Addr != (ui32FlashSize - FLASH_RSVD_SPACE)) &&
+#endif
+ (ui32Addr != APP_START_ADDRESS)) ||
+ ((ui32Addr + ui32ImgSize) > ui32FlashSize) || ((ui32Addr & 3) != 0))
+ {
+ return(0);
+ }
+ else
+ {
+ return(1);
+ }
+}
+
+//*****************************************************************************
+//
+//! Checks whether a flash access violation occurred.
+//!
+//! This function checks whether an access violation error occurred during
+//! the previous program or erase operation.
+//!
+//! \return Returns 0 if no error occurred or a non-zero value if an error was
+//! reported.
+//
+//*****************************************************************************
+void
+BLInternalFlashErrorClear(void)
+{
+ //
+ // Clear the flash controller access interrupt.
+ //
+ HWREG(FLASH_FCMISC) = FLASH_FCMISC_AMISC;
+}
+
+//*****************************************************************************
+//
+//! Checks whether a flash access violation occurred.
+//!
+//! This function checks whether an access violation error occurred since the
+//! last call to BLInternalFlashErrorClear().
+//!
+//! \return Returns 0 if no error occurred or a non-zero value if an error was
+//! reported.
+//
+//*****************************************************************************
+uint32_t
+BLInternalFlashErrorCheck(void)
+{
+ return(HWREG(FLASH_FCRIS) & FLASH_FCRIS_ARIS);
+}
diff --git a/boot_loader/bl_flash.h b/boot_loader/bl_flash.h new file mode 100644 index 0000000..4a23f00 --- /dev/null +++ b/boot_loader/bl_flash.h @@ -0,0 +1,127 @@ +//*****************************************************************************
+//
+// bl_flash.h - Flash programming functions used by 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.
+//
+//*****************************************************************************
+
+#ifndef __BL_FLASH_H__
+#define __BL_FLASH_H__
+
+#include "driverlib/rom.h"
+
+//*****************************************************************************
+//
+// Basic functions for erasing and programming internal flash.
+//
+//*****************************************************************************
+extern void BLInternalFlashErase(uint32_t ui32Address);
+extern void BLInternalFlashProgram(uint32_t ui32DstAddr, uint8_t *pui8SrcData,
+ uint32_t ui32Length);
+extern uint32_t BLInternalFlashSizeGet(void);
+extern uint32_t BLInternalFlashStartAddrCheck(uint32_t ui32Addr,
+ uint32_t ui32ImgSize);
+extern uint32_t BLInternalFlashErrorCheck(void);
+extern void BLInternalFlashErrorClear(void);
+
+//*****************************************************************************
+//
+// If the user has not specified which flash programming functions to use,
+// default to the basic, internal flash functions on Sandstorm, Fury and
+// DustDevil parts or the ROM-resident function for Tempest-class parts.
+//
+//*****************************************************************************
+#ifndef BL_FLASH_ERASE_FN_HOOK
+#define BL_FLASH_ERASE_FN_HOOK(ui32Address) \
+ { \
+ HWREG(FLASH_FMA) = (ui32Address); \
+ HWREG(FLASH_FMC) = FLASH_FMC_WRKEY | FLASH_FMC_ERASE; \
+ while(HWREG(FLASH_FMC) & FLASH_FMC_ERASE) \
+ { \
+ } \
+ }
+#else
+extern void BL_FLASH_ERASE_FN_HOOK(uint32_t ui32Address);
+#endif
+
+#ifndef BL_FLASH_PROGRAM_FN_HOOK
+#ifdef ROM_FlashProgram
+#define BL_FLASH_PROGRAM_FN_HOOK(ui32DstAddr, pui8SrcData, ui32Length) \
+ ROM_FlashProgram((uint32_t *)pui8SrcData, ui32DstAddr, \
+ (((ui32Length) + 3) & ~3))
+#else
+#define BL_FLASH_PROGRAM_FN_HOOK(ui32DstAddr, pui8SrcData, ui32Length) \
+ { \
+ uint32_t ui32FlashProgLoop; \
+ \
+ for(ui32FlashProgLoop = 0; ui32FlashProgLoop < (ui32Length); \
+ ui32FlashProgLoop += 4) \
+ { \
+ HWREG(FLASH_FMA) = (ui32DstAddr) + ui32FlashProgLoop; \
+ HWREG(FLASH_FMD) = *(uint32_t *)((pui8SrcData) + \
+ ui32FlashProgLoop); \
+ HWREG(FLASH_FMC) = FLASH_FMC_WRKEY | FLASH_FMC_WRITE; \
+ while(HWREG(FLASH_FMC) & FLASH_FMC_WRITE) \
+ { \
+ } \
+ } \
+ }
+#endif
+#else
+extern uint32_t BL_FLASH_PROGRAM_FN_HOOK(uint32_t ui32DstAddr,
+ uint8_t *pui8SrcData,
+ uint32_t ui32Length);
+#endif
+
+#ifndef BL_FLASH_CL_ERR_FN_HOOK
+#define BL_FLASH_CL_ERR_FN_HOOK() HWREG(FLASH_FCMISC) = FLASH_FCMISC_AMISC
+#else
+extern void BL_FLASH_CL_ERR_FN_HOOK(void);
+#endif
+
+#ifndef BL_FLASH_ERROR_FN_HOOK
+#define BL_FLASH_ERROR_FN_HOOK() (HWREG(FLASH_FCRIS) & FLASH_FCRIS_ARIS)
+#else
+extern uint32_t BL_FLASH_ERROR_FN_HOOK(void);
+#endif
+
+#ifndef BL_FLASH_SIZE_FN_HOOK
+#define BL_FLASH_SIZE_FN_HOOK() \
+ (((HWREG(SYSCTL_DC0) & SYSCTL_DC0_FLASHSZ_M) + 1) << 11)
+#else
+extern uint32_t BL_FLASH_SIZE_FN_HOOK(void);
+#endif
+
+#ifndef BL_FLASH_END_FN_HOOK
+#define BL_FLASH_END_FN_HOOK() \
+ (((HWREG(SYSCTL_DC0) & SYSCTL_DC0_FLASHSZ_M) + 1) << 11)
+#else
+extern uint32_t BL_FLASH_END_FN_HOOK(void);
+#endif
+
+#ifndef BL_FLASH_AD_CHECK_FN_HOOK
+#define BL_FLASH_AD_CHECK_FN_HOOK(ui32Addr, ui32Size) \
+ BLInternalFlashStartAddrCheck((ui32Addr), (ui32Size))
+#else
+extern uint32_t BL_FLASH_AD_CHECK_FN_HOOK(uint32_t ui32Address,
+ uint32_t ui32Length);
+#endif
+
+#endif // __BL_FLASH_H__
diff --git a/boot_loader/bl_hooks.h b/boot_loader/bl_hooks.h new file mode 100644 index 0000000..1a174e3 --- /dev/null +++ b/boot_loader/bl_hooks.h @@ -0,0 +1,72 @@ +//*****************************************************************************
+//
+// bl_hooks.h - Definitions for the application-specific hook function.
+//
+// Copyright (c) 2009-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.
+//
+//*****************************************************************************
+
+#ifndef __BL_HOOKS_H__
+#define __BL_HOOKS_H__
+
+//*****************************************************************************
+//
+// Prototypes for any application-specific hook functions that are defined in
+// bl_config.h. Note that the low level flash programming hooks are handled
+// in bl_flash.h to allow us to define macros for internal flash programming
+// in the normal case where no override functions are provided.
+//
+//*****************************************************************************
+#ifdef BL_HW_INIT_FN_HOOK
+extern void BL_HW_INIT_FN_HOOK(void);
+#endif
+#ifdef BL_INIT_FN_HOOK
+extern void BL_INIT_FN_HOOK(void);
+#endif
+#ifdef BL_REINIT_FN_HOOK
+extern void BL_REINIT_FN_HOOK(void);
+#endif
+#ifdef BL_START_FN_HOOK
+extern void BL_START_FN_HOOK(void);
+#endif
+#ifdef BL_PROGRESS_FN_HOOK
+extern void BL_PROGRESS_FN_HOOK(uint32_t ui32Completed, uint32_t ui32Total);
+#endif
+#ifdef BL_END_FN_HOOK
+extern void BL_END_FN_HOOK(void);
+#endif
+#ifdef BL_DECRYPT_FN_HOOK
+extern void BL_DECRYPT_FN_HOOK(uint8_t *pui8Buffer, uint32_t ui32Size);
+#endif
+#ifdef BL_CHECK_UPDATE_FN_HOOK
+extern uint32_t BL_CHECK_UPDATE_FN_HOOK(void);
+#endif
+
+//*****************************************************************************
+//
+// If ENABLE_DECRYPTION is defined but we don't have a hook function set for
+// decryption, default to the previous behavior which calls the stub function
+// DecryptData.
+//
+//*****************************************************************************
+#if (defined ENABLE_DECRYPTION) && !(defined BL_DECRYPT_FN_HOOK)
+#define BL_DECRYPT_FN_HOOK DecryptData
+#endif
+
+#endif // __BL_HOOKS_H__
diff --git a/boot_loader/bl_i2c.c b/boot_loader/bl_i2c.c new file mode 100644 index 0000000..bc2b62c --- /dev/null +++ b/boot_loader/bl_i2c.c @@ -0,0 +1,149 @@ +//*****************************************************************************
+//
+// bl_i2c.c - This file contains the function used to transfer data via the I2C
+// port.
+//
+// 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 "inc/hw_gpio.h"
+#include "inc/hw_i2c.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_sysctl.h"
+#include "inc/hw_types.h"
+#include "bl_config.h"
+#include "boot_loader/bl_i2c.h"
+
+//*****************************************************************************
+//
+//! \addtogroup bl_i2c_api
+//! @{
+//
+//*****************************************************************************
+#if defined(I2C_ENABLE_UPDATE) || defined(DOXYGEN)
+
+//*****************************************************************************
+//
+//! Sends data over the I2C port.
+//!
+//! \param pui8Data is the buffer containing the data to write out to the I2C
+//! port.
+//! \param ui32Size is the number of bytes provided in \e pui8Data buffer that
+//! will be written out to the I2C port.
+//!
+//! This function sends \e ui32Size bytes of data from the buffer pointed to by
+//! \e pui8Data via the I2C port. The function will wait till the I2C Slave
+//! port has been properly addressed by the I2C Master device before sending
+//! the first byte.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+I2CSend(const uint8_t *pui8Data, uint32_t ui32Size)
+{
+ //
+ // Transmit the number of bytes requested on the UART port.
+ //
+ while(ui32Size--)
+ {
+ //
+ // Wait for request to come in at slave.
+ //
+ while(!(HWREG(I2C0_BASE + I2C_O_SCSR) & I2C_SCSR_TREQ))
+ {
+ }
+
+ //
+ // Send out the next byte.
+ //
+ HWREG(I2C0_BASE + I2C_O_SDR) = *pui8Data++;
+ }
+}
+
+//*****************************************************************************
+//
+//! Waits until all data has been transmitted by the I2C port.
+//!
+//! This function waits until all data written to the I2C port has been read by
+//! the master.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+I2CFlush(void)
+{
+ //
+ // Wait until the I2C bus is no longer busy, meaning that the last byte has
+ // been sent.
+ //
+ while(HWREG(I2C0_BASE + I2C_O_MCS) & I2C_MCS_BUSBSY)
+ {
+ }
+}
+
+//*****************************************************************************
+//
+//! Receives data over the I2C port.
+//!
+//! \param pui8Data is the buffer to read data into from the I2C port.
+//! \param ui32Size is the number of bytes provided in the \e pui8Data buffer
+//! that should be written with data from the I2C port.
+//!
+//! This function reads back \e ui32Size bytes of data from the I2C port, into
+//! the buffer that is pointed to by \e pui8Data. This function will not
+//! return until \e ui32Size number of bytes have been received. This function
+//! will wait till the I2C Slave port has been properly addressed by the I2C
+//! Master before reading the first byte of data from the I2C port.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+I2CReceive(uint8_t *pui8Data, uint32_t ui32Size)
+{
+ //
+ // Send out the number of bytes requested.
+ //
+ while(ui32Size--)
+ {
+ //
+ // Wait until the slave has received the character.
+ //
+ while(!(HWREG(I2C0_BASE + I2C_O_SCSR) & I2C_SCSR_RREQ))
+ {
+ }
+
+ //
+ // Receive a byte from the I2C.
+ //
+ *pui8Data++ = HWREG(I2C0_BASE + I2C_O_SDR);
+ }
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+#endif
diff --git a/boot_loader/bl_i2c.h b/boot_loader/bl_i2c.h new file mode 100644 index 0000000..4b7a01a --- /dev/null +++ b/boot_loader/bl_i2c.h @@ -0,0 +1,70 @@ +//*****************************************************************************
+//
+// bl_i2c.h - Definitions for the I2C transport functions.
+//
+// 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.
+//
+//*****************************************************************************
+
+#ifndef __BL_I2C_H__
+#define __BL_I2C_H__
+
+//*****************************************************************************
+//
+// This defines the I2C clock pin that is being used by the boot loader.
+//
+//*****************************************************************************
+#define I2C_CLK (1 << 2)
+
+//*****************************************************************************
+//
+// This defines the I2C data pin that is being used by the boot loader.
+//
+//*****************************************************************************
+#define I2C_DATA (1 << 3)
+
+//*****************************************************************************
+//
+// This defines the combination of pins used to implement the I2C port used by
+// the boot loader.
+//
+//*****************************************************************************
+#define I2C_PINS (I2C_CLK | I2C_DATA)
+
+//*****************************************************************************
+//
+// I2C Transport APIs
+//
+//*****************************************************************************
+extern void I2CSend(const uint8_t *pui8Data, uint32_t ui32Size);
+extern void I2CReceive(uint8_t *pui8Data, uint32_t ui32Size);
+extern void I2CFlush(void);
+
+//*****************************************************************************
+//
+// Define the transport functions if the I2C port is being used.
+//
+//*****************************************************************************
+#ifdef I2C_ENABLE_UPDATE
+#define SendData I2CSend
+#define FlushData I2CFlush
+#define ReceiveData I2CReceive
+#endif
+
+#endif // __BL_I2C_H__
diff --git a/boot_loader/bl_link.icf b/boot_loader/bl_link.icf new file mode 100644 index 0000000..3e7af89 --- /dev/null +++ b/boot_loader/bl_link.icf @@ -0,0 +1,83 @@ +//*****************************************************************************
+//
+// bl_link.icf - Linker script for EW-ARM.
+//
+// Copyright (c) 2007-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.
+//
+//*****************************************************************************
+
+//
+// Define a memory region that covers the entire 4 GB addressible space of the
+// processor.
+//
+define memory mem with size = 4G;
+
+//
+// Define a region for the on-chip flash.
+//
+define region FLASH = mem:[from 0x00000000 to 0x0000ffff];
+
+//
+// Define a region for the on-chip SRAM.
+//
+define region SRAM = mem:[from 0x20000000 to 0x2000ffff];
+
+//
+// Indicate that the sections containing the boot loader code should be
+// initialized by copying.
+//
+initialize manually with packing = none { section INTVEC };
+initialize manually with packing = none { section CODE };
+initialize manually with packing = none { section .text };
+initialize manually with packing = none { section .rodata };
+initialize manually with packing = none { section .data };
+
+keep { section INTVEC };
+keep { section INTVEC_init };
+
+//
+// Indicate that the noinit values should be left alone. This includes the
+// stack, which if initialized will destroy the return address from the
+// initialization code, causing the processor to branch to zero and fault.
+//
+do not initialize { section .noinit };
+
+//
+// Place the interrupt vectors at the start of flash/SRAM.
+//
+place at start of FLASH { readonly section INTVEC_init };
+place at start of SRAM { readwrite section INTVEC };
+
+//
+// Place the remainder of the read-only items into flash/SRAM.
+//
+place in FLASH { readonly section CODE_init };
+place in SRAM { readwrite section CODE };
+place in FLASH { readonly section .text_init };
+place in SRAM { readwrite section .text };
+place in FLASH { readonly section .rodata_init };
+place in SRAM { readwrite section .rodata };
+place in FLASH { readonly section .data_init };
+place in SRAM { readwrite section .data };
+place in FLASH { readonly };
+
+//
+// Place all read/write items into SRAM.
+//
+place in SRAM { readwrite };
diff --git a/boot_loader/bl_link.ld b/boot_loader/bl_link.ld new file mode 100644 index 0000000..aae5f00 --- /dev/null +++ b/boot_loader/bl_link.ld @@ -0,0 +1,51 @@ +/******************************************************************************
+ *
+ * bl_link.ld - Scatter file for Gnu tools
+ *
+ * Copyright (c) 2007-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.
+ *
+ *****************************************************************************/
+
+SECTIONS
+{
+ .text 0x20000000 : AT (0x00000000)
+ {
+ _text = .;
+ KEEP(*(.isr_vector))
+ *(.text*)
+ *(.rodata*)
+ _etext = .;
+ }
+
+ .data 0x20000000 + SIZEOF(.text) : AT (SIZEOF(.text))
+ {
+ _data = .;
+ *(.data*)
+ _edata = .;
+ }
+
+ .bss 0x20000000 + SIZEOF(.text) + SIZEOF(.data) :
+ AT (ADDR(.data) + SIZEOF(.data))
+ {
+ _bss = .;
+ *(.bss*)
+ *(COMMON)
+ _ebss = .;
+ }
+}
diff --git a/boot_loader/bl_link.sct b/boot_loader/bl_link.sct new file mode 100644 index 0000000..fe22bd1 --- /dev/null +++ b/boot_loader/bl_link.sct @@ -0,0 +1,45 @@ +;******************************************************************************
+;
+; bl_link.sct - Scatter file for RV-MDK.
+;
+; 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.
+;
+;******************************************************************************
+
+;
+; The contents of this application reside in flash.
+;
+FLASH 0x00000000 0x00010000
+{
+ ;
+ ; Place the vector table and reset handlers into flash.
+ ;
+ RESET 0x00000000 0x00010000
+ {
+ *.o (RESET, +First)
+ }
+
+ ;
+ ; Place everything else remaining into SRAM (RO, RW, and ZI)
+ ;
+ SRAM +0x20000000 0x00010000
+ {
+ * (+RO, +RW, +ZI)
+ }
+}
diff --git a/boot_loader/bl_link_ccs.cmd b/boot_loader/bl_link_ccs.cmd new file mode 100644 index 0000000..0e09b6e --- /dev/null +++ b/boot_loader/bl_link_ccs.cmd @@ -0,0 +1,63 @@ +/******************************************************************************
+ *
+ * bl_link_ccs.cmd - CCS linker configuration file for boot loader.
+ *
+ * Copyright (c) 2009-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.
+ *
+ *****************************************************************************/
+
+--retain=Vectors
+
+/* The following command line options are set as part of the CCS project. */
+/* If you are building using the command line, or for some reason want to */
+/* define them here, you can uncomment and modify these lines as needed. */
+/* If you are using CCS for building, it is probably better to make any such */
+/* modifications in your CCS project and leave this file alone. */
+/* */
+/* --heap_size=0 */
+/* --stack_size=256 */
+/* --library=rtsv7M3_T_le_eabi.lib */
+
+/* System memory map */
+
+MEMORY
+{
+ FLASH (RX) : origin = 0x00000000, length = 0x00010000
+ SRAM (RWX) : origin = 0x20000000, length = 0x00010000
+}
+
+/* Section allocation in memory */
+
+SECTIONS
+{
+ GROUP
+ {
+ .intvecs
+ .text
+ .const
+ .data
+ } load = FLASH, run = 0x20000000, LOAD_START(init_load), RUN_START(init_run), SIZE(init_size)
+
+ GROUP
+ {
+ .bss
+ .stack
+ } run = SRAM, RUN_START(bss_run), RUN_END(bss_end), SIZE(bss_size), RUN_END(__STACK_TOP)
+
+}
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
diff --git a/boot_loader/bl_packet.c b/boot_loader/bl_packet.c new file mode 100644 index 0000000..f54495c --- /dev/null +++ b/boot_loader/bl_packet.c @@ -0,0 +1,295 @@ +//*****************************************************************************
+//
+// bl_packet.c - Packet handler functions used by 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 "bl_config.h"
+#include "boot_loader/bl_commands.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"
+
+//*****************************************************************************
+//
+//! \addtogroup bl_packet_api
+//! @{
+//
+//*****************************************************************************
+#if defined(I2C_ENABLE_UPDATE) || defined(SSI_ENABLE_UPDATE) || \
+ defined(UART_ENABLE_UPDATE) || defined(DOXYGEN)
+
+//*****************************************************************************
+//
+// The packet that is sent to acknowledge a received packet.
+//
+//*****************************************************************************
+static const uint8_t g_pui8ACK[2] = { 0, COMMAND_ACK };
+
+//*****************************************************************************
+//
+// The packet that is sent to not-acknowledge a received packet.
+//
+//*****************************************************************************
+static const uint8_t g_pui8NAK[2] = { 0, COMMAND_NAK };
+
+//*****************************************************************************
+//
+//! Calculates an 8-bit checksum
+//!
+//! \param pui8Data is a pointer to an array of 8-bit data of size ui32Size.
+//! \param ui32Size is the size of the array that will run through the checksum
+//! algorithm.
+//!
+//! This function simply calculates an 8-bit checksum on the data passed in.
+//!
+//! \return Returns the calculated checksum.
+//
+//*****************************************************************************
+uint32_t
+CheckSum(const uint8_t *pui8Data, uint32_t ui32Size)
+{
+ uint32_t ui32CheckSum;
+
+ //
+ // Initialize the checksum to zero.
+ //
+ ui32CheckSum = 0;
+
+ //
+ // Add up all the bytes, do not do anything for an overflow.
+ //
+ while(ui32Size--)
+ {
+ ui32CheckSum += *pui8Data++;
+ }
+
+ //
+ // Return the caculated check sum.
+ //
+ return(ui32CheckSum & 0xff);
+}
+
+//*****************************************************************************
+//
+//! Sends an Acknowledge packet.
+//!
+//! This function is called to acknowledge that a packet has been received by
+//! the microcontroller.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+AckPacket(void)
+{
+ //
+ // ACK/NAK packets are the only ones with no size.
+ //
+ SendData(g_pui8ACK, 2);
+}
+
+//*****************************************************************************
+//
+//! Sends a no-acknowledge packet.
+//!
+//! This function is called when an invalid packet has been received by the
+//! microcontroller, indicating that it should be retransmitted.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+NakPacket(void)
+{
+ //
+ // ACK/NAK packets are the only ones with no size.
+ //
+ SendData(g_pui8NAK, 2);
+}
+
+//*****************************************************************************
+//
+//! Receives a data packet.
+//!
+//! \param pui8Data is the location to store the data that is sent to the boot
+//! loader.
+//! \param pui32Size is the number of bytes returned in the pui8Data buffer
+//! that was provided.
+//!
+//! This function receives a packet of data from specified transfer function.
+//!
+//! \return Returns zero to indicate success while any non-zero value indicates
+//! a failure.
+//
+//*****************************************************************************
+int
+ReceivePacket(uint8_t *pui8Data, uint32_t *pui32Size)
+{
+ uint32_t ui32Size, ui32CheckSum;
+
+ //
+ // Wait for non-zero data before getting the first byte that holds the
+ // size of the packet we are receiving.
+ //
+ ui32Size = 0;
+ while(ui32Size == 0)
+ {
+ ReceiveData((uint8_t *)&ui32Size, 1);
+ }
+
+ //
+ // Subtract off the size and checksum bytes.
+ //
+ ui32Size -= 2;
+
+ //
+ // Receive the checksum followed by the actual data.
+ //
+ ReceiveData((uint8_t *)&ui32CheckSum, 1);
+
+ //
+ // If there is room in the buffer then receive the requested data.
+ //
+ if(*pui32Size >= ui32Size)
+ {
+ //
+ // Receive the actual data in the packet.
+ //
+ ReceiveData(pui8Data, ui32Size);
+
+ //
+ // Send a no acknowledge if the checksum does not match, otherwise send
+ // an acknowledge to the packet later.
+ //
+ if(CheckSum(pui8Data, ui32Size) != (ui32CheckSum & 0xff))
+ {
+ //
+ // Indicate tha the packet was not received correctly.
+ //
+ NakPacket();
+
+ //
+ // Packet was not received, there is no valid data in the buffer.
+ //
+ return(-1);
+ }
+ }
+ else
+ {
+ //
+ // If the caller allocated a buffer that was too small for the received
+ // data packet, receive it but don't fill the buffer.
+ // Then inform the caller that the packet was not received correctly.
+ //
+ while(ui32Size--)
+ {
+ ReceiveData(pui8Data, 1);
+ }
+
+ //
+ // Packet was not received, there is no valid data in the buffer.
+ //
+ return(-1);
+ }
+
+ //
+ // Make sure to return the number of bytes received.
+ //
+ *pui32Size = ui32Size;
+
+ //
+ // Packet was received successfully.
+ //
+ return(0);
+}
+
+//*****************************************************************************
+//
+//! Sends a data packet.
+//!
+//! \param pui8Data is the location of the data to be sent.
+//! \param ui32Size is the number of bytes to send.
+//!
+//! This function sends the data provided in the \e pui8Data parameter in the
+//! packet format used by the boot loader. The caller only needs to specify
+//! the buffer with the data that needs to be transferred. This function
+//! addresses all other packet formatting issues.
+//!
+//! \return Returns zero to indicate success while any non-zero value indicates
+//! a failure.
+//
+//*****************************************************************************
+int
+SendPacket(uint8_t *pui8Data, uint32_t ui32Size)
+{
+ uint32_t ui32Temp;
+
+ //
+ // Caculate the checksum to be sent out with the data.
+ //
+ ui32Temp = CheckSum(pui8Data, ui32Size);
+
+ //
+ // Need to include the size and checksum bytes in the packet.
+ //
+ ui32Size += 2;
+
+ //
+ // Send out the size followed by the data.
+ //
+ SendData((uint8_t *)&ui32Size, 1);
+ SendData((uint8_t *)&ui32Temp, 1);
+ SendData(pui8Data, ui32Size - 2);
+
+ //
+ // Wait for a non zero byte.
+ //
+ ui32Temp = 0;
+ while(ui32Temp == 0)
+ {
+ ReceiveData((uint8_t *)&ui32Temp, 1);
+ }
+
+ //
+ // Check if the byte was a valid ACK and return a negative value if it was
+ // not and aknowledge.
+ //
+ if(ui32Temp != COMMAND_ACK)
+ {
+ return(-1);
+ }
+
+ //
+ // This packet was sent and received successfully.
+ //
+ return(0);
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+#endif
diff --git a/boot_loader/bl_packet.h b/boot_loader/bl_packet.h new file mode 100644 index 0000000..3c4f78d --- /dev/null +++ b/boot_loader/bl_packet.h @@ -0,0 +1,37 @@ +//*****************************************************************************
+//
+// bl_packet.h - The global variables and definitions 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.
+//
+//*****************************************************************************
+
+#ifndef __BL_PACKET_H__
+#define __BL_PACKET_H__
+
+//*****************************************************************************
+//
+// Packet Handling APIs
+//
+//*****************************************************************************
+extern int ReceivePacket(uint8_t *pui8Data, uint32_t *pui32Size);
+extern int SendPacket(uint8_t *pui8Data, uint32_t ui32Size);
+extern void AckPacket(void);
+
+#endif // __BL_PACKET_H__
diff --git a/boot_loader/bl_ssi.c b/boot_loader/bl_ssi.c new file mode 100644 index 0000000..ca10517 --- /dev/null +++ b/boot_loader/bl_ssi.c @@ -0,0 +1,161 @@ +//*****************************************************************************
+//
+// bl_ssi.c - Functions used to transfer data via the SSI port.
+//
+// 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 "inc/hw_gpio.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_ssi.h"
+#include "inc/hw_sysctl.h"
+#include "inc/hw_types.h"
+#include "bl_config.h"
+#include "boot_loader/bl_ssi.h"
+
+//*****************************************************************************
+//
+//! \addtogroup bl_ssi_api
+//! @{
+//
+//*****************************************************************************
+#if defined(SSI_ENABLE_UPDATE) || defined(DOXYGEN)
+
+//*****************************************************************************
+//
+//! Sends data via the SSI port in slave mode.
+//!
+//! \param pui8Data is the location of the data to send through the SSI port.
+//! \param ui32Size is the number of bytes of data to send.
+//!
+//! This function sends data through the SSI port in slave mode. This function
+//! will not return until all bytes are sent.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SSISend(const uint8_t *pui8Data, uint32_t ui32Size)
+{
+ //
+ // Send the requested number of bytes over the SSI port.
+ //
+ while(ui32Size--)
+ {
+ //
+ // Wait until there is space in the SSI FIFO.
+ //
+ while(!(HWREG(SSI0_BASE + SSI_O_SR) & SSI_SR_TNF))
+ {
+ }
+
+ //
+ // Write the next byte to the SSI port.
+ //
+ HWREG(SSI0_BASE + SSI_O_DR) = *pui8Data++;
+ }
+
+ //
+ // Empty the receive FIFO.
+ //
+ while(HWREG(SSI0_BASE + SSI_O_SR) & SSI_SR_RNE)
+ {
+ HWREG(SSI0_BASE + SSI_O_DR);
+ }
+}
+
+//*****************************************************************************
+//
+//! Waits until all data has been transmitted by the SSI port.
+//!
+//! This function waits until all data written to the SSI port has been read by
+//! the master.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SSIFlush(void)
+{
+ //
+ // Wait until the transmit FIFO is empty.
+ //
+ while(!(HWREG(SSI0_BASE + SSI_O_SR) & SSI_SR_TFE))
+ {
+ }
+
+ //
+ // Wait until the interface is not busy.
+ //
+ while(HWREG(SSI0_BASE + SSI_O_SR) & SSI_SR_BSY)
+ {
+ }
+}
+
+//*****************************************************************************
+//
+//! Receives data from the SSI port in slave mode.
+//!
+//! \param pui8Data is the location to store the data received from the SSI
+//! port.
+//! \param ui32Size is the number of bytes of data to receive.
+//!
+//! This function receives data from the SSI port in slave mode. The function
+//! will not return until \e ui32Size number of bytes have been received.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+SSIReceive(uint8_t *pui8Data, uint32_t ui32Size)
+{
+ //
+ // Ensure that we are sending out zeros so that we don't confuse the host.
+ //
+ HWREG(SSI0_BASE + SSI_O_DR) = 0;
+
+ //
+ // Wait for the requested number of bytes.
+ //
+ while(ui32Size--)
+ {
+ //
+ // Wait until there is data in the FIFO.
+ //
+ while(!(HWREG(SSI0_BASE + SSI_O_SR) & SSI_SR_RNE))
+ {
+ }
+
+ //
+ // Read the next byte from the FIFO.
+ //
+ *pui8Data++ = HWREG(SSI0_BASE + SSI_O_DR);
+ HWREG(SSI0_BASE + SSI_O_DR) = 0;
+ }
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+#endif
diff --git a/boot_loader/bl_ssi.h b/boot_loader/bl_ssi.h new file mode 100644 index 0000000..05ec3bb --- /dev/null +++ b/boot_loader/bl_ssi.h @@ -0,0 +1,92 @@ +//*****************************************************************************
+//
+// bl_ssi.h - Definitions for the SSI transport functions.
+//
+// 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.
+//
+//*****************************************************************************
+
+#ifndef __BL_SSI_H__
+#define __BL_SSI_H__
+
+//*****************************************************************************
+//
+// This is the number of bits per transfer for SSI. This is a constant and
+// cannot be changed without corresponding code changes.
+//
+//*****************************************************************************
+#define DATA_BITS_SSI 8
+
+//*****************************************************************************
+//
+// This defines the SSI chip select pin that is being used by the boot loader.
+//
+//*****************************************************************************
+#define SSI_CS (1 << 3)
+
+//*****************************************************************************
+//
+// This defines the SSI clock pin that is being used by the boot loader.
+//
+//*****************************************************************************
+#define SSI_CLK (1 << 2)
+
+//*****************************************************************************
+//
+// This defines the SSI transmit pin that is being used by the boot loader.
+//
+//*****************************************************************************
+#define SSI_TX (1 << 5)
+
+//*****************************************************************************
+//
+// This defines the SSI receive pin that is being used by the boot loader.
+//
+//*****************************************************************************
+#define SSI_RX (1 << 4)
+
+//*****************************************************************************
+//
+// This defines the combination of pins used to implement the SSI port used by
+// the boot loader.
+//
+//*****************************************************************************
+#define SSI_PINS (SSI_CLK | SSI_TX | SSI_RX | SSI_CS)
+
+//*****************************************************************************
+//
+// SSI Transport APIs
+//
+//*****************************************************************************
+extern void SSISend(const uint8_t *pui8Data, uint32_t ui32Size);
+extern void SSIReceive(uint8_t *pui8Data, uint32_t ui32Size);
+extern void SSIFlush(void);
+
+//*****************************************************************************
+//
+// Define the transport functions if the SSI port is being used.
+//
+//*****************************************************************************
+#ifdef SSI_ENABLE_UPDATE
+#define SendData SSISend
+#define FlushData SSIFlush
+#define ReceiveData SSIReceive
+#endif
+
+#endif // __BL_SSI_H__
diff --git a/boot_loader/bl_startup_ccs.s b/boot_loader/bl_startup_ccs.s new file mode 100644 index 0000000..8bfa96b --- /dev/null +++ b/boot_loader/bl_startup_ccs.s @@ -0,0 +1,645 @@ +;;*****************************************************************************
+;;
+;; bl_startup_ccs.s - Boot loader startup code for Code Composer Studio
+;;
+;; Copyright (c) 2009-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 the boot loader configuration options.
+;;
+;;*****************************************************************************
+ .cdecls C, NOLIST, WARN
+ %{
+ #include "inc/hw_nvic.h"
+ #include "inc/hw_sysctl.h"
+ #include "bl_config.h"
+ %}
+
+;;*****************************************************************************
+;;
+;; Export symbols from this file that are used elsewhere
+;;
+;;*****************************************************************************
+ .global ResetISR, Delay, Vectors
+
+;;*****************************************************************************
+;;
+;; Create the stack and put it in a section
+;;
+;;*****************************************************************************
+ .global __stack
+__stack:.usect ".stack", STACK_SIZE * 4, 8
+
+;;*****************************************************************************
+;;
+;; Put the assembler into the correct configuration.
+;;
+;;*****************************************************************************
+ .thumb
+
+;;*****************************************************************************
+;;
+;; This portion of the file goes into interrupt vectors section
+;;
+;;*****************************************************************************
+ .sect ".intvecs"
+
+;;*****************************************************************************
+;;
+;; The minimal vector table for a Cortex-M3 processor.
+;;
+;;*****************************************************************************
+Vectors:
+ .ref __STACK_TOP
+ .word __STACK_TOP ;; Offset 00: Initial stack pointer
+ .word ResetISR - 0x20000000 ;; Offset 04: Reset handler
+ .word NmiSR - 0x20000000 ;; Offset 08: NMI handler
+ .word FaultISR - 0x20000000 ;; Offset 0C: Hard fault handler
+ .word IntDefaultHandler ;; Offset 10: MPU fault handler
+ .word IntDefaultHandler ;; Offset 14: Bus fault handler
+ .word IntDefaultHandler ;; Offset 18: Usage fault handler
+ .word 0 ;; Offset 1C: Reserved
+ .word 0 ;; Offset 20: Reserved
+ .word 0 ;; Offset 24: Reserved
+ .word 0 ;; Offset 28: Reserved
+ .word UpdateHandler - 0x20000000 ;; Offset 2C: SVCall handler
+ .word IntDefaultHandler ;; Offset 30: Debug monitor handler
+ .word 0 ;; Offset 34: Reserved
+ .word IntDefaultHandler ;; Offset 38: PendSV handler
+ .if $$defined(ENET_ENABLE_UPDATE)
+ .ref SysTickIntHandler
+ .word SysTickIntHandler ;; Offset 3C: SysTick handler
+ .else
+ .word IntDefaultHandler ;; Offset 3C: SysTick handler
+ .endif
+ .if $$defined(UART_ENABLE_UPDATE) & $$defined(UART_AUTOBAUD)
+ .ref GPIOIntHandler
+ .word GPIOIntHandler ;; Offset 40: GPIO port A handler
+ .else
+ .word IntDefaultHandler ;; Offset 40: GPIO port A handler
+ .endif
+ .if ($$defined(USB_ENABLE_UPDATE) | (APP_START_ADDRESS != VTABLE_START_ADDRESS))
+ .word IntDefaultHandler ;; Offset 44: GPIO Port B
+ .word IntDefaultHandler ;; Offset 48: GPIO Port C
+ .word IntDefaultHandler ;; Offset 4C: GPIO Port D
+ .word IntDefaultHandler ;; Offset 50: GPIO Port E
+ .word IntDefaultHandler ;; Offset 54: UART0 Rx and Tx
+ .word IntDefaultHandler ;; Offset 58: UART1 Rx and Tx
+ .word IntDefaultHandler ;; Offset 5C: SSI0 Rx and Tx
+ .word IntDefaultHandler ;; Offset 60: I2C0 Master and Slave
+ .word IntDefaultHandler ;; Offset 64: PWM Fault
+ .word IntDefaultHandler ;; Offset 68: PWM Generator 0
+ .word IntDefaultHandler ;; Offset 6C: PWM Generator 1
+ .word IntDefaultHandler ;; Offset 70: PWM Generator 2
+ .word IntDefaultHandler ;; Offset 74: Quadrature Encoder 0
+ .word IntDefaultHandler ;; Offset 78: ADC Sequence 0
+ .word IntDefaultHandler ;; Offset 7C: ADC Sequence 1
+ .word IntDefaultHandler ;; Offset 80: ADC Sequence 2
+ .word IntDefaultHandler ;; Offset 84: ADC Sequence 3
+ .word IntDefaultHandler ;; Offset 88: Watchdog timer
+ .word IntDefaultHandler ;; Offset 8C: Timer 0 subtimer A
+ .word IntDefaultHandler ;; Offset 90: Timer 0 subtimer B
+ .word IntDefaultHandler ;; Offset 94: Timer 1 subtimer A
+ .word IntDefaultHandler ;; Offset 98: Timer 1 subtimer B
+ .word IntDefaultHandler ;; Offset 9C: Timer 2 subtimer A
+ .word IntDefaultHandler ;; Offset A0: Timer 2 subtimer B
+ .word IntDefaultHandler ;; Offset A4: Analog Comparator 0
+ .word IntDefaultHandler ;; Offset A8: Analog Comparator 1
+ .word IntDefaultHandler ;; Offset AC: Analog Comparator 2
+ .word IntDefaultHandler ;; Offset B0: System Control
+ .word IntDefaultHandler ;; Offset B4: FLASH Control
+ .endif
+ .if ($$defined(USB_ENABLE_UPDATE) | (APP_START_ADDRESS != VTABLE_START_ADDRESS))
+ .word IntDefaultHandler ;; Offset B8: GPIO Port F
+ .word IntDefaultHandler ;; Offset BC: GPIO Port G
+ .word IntDefaultHandler ;; Offset C0: GPIO Port H
+ .word IntDefaultHandler ;; Offset C4: UART2 Rx and Tx
+ .word IntDefaultHandler ;; Offset C8: SSI1 Rx and Tx
+ .word IntDefaultHandler ;; Offset CC: Timer 3 subtimer A
+ .word IntDefaultHandler ;; Offset D0: Timer 3 subtimer B
+ .word IntDefaultHandler ;; Offset D4: I2C1 Master and Slave
+ .word IntDefaultHandler ;; Offset D8: Quadrature Encoder 1
+ .word IntDefaultHandler ;; Offset DC: CAN0
+ .word IntDefaultHandler ;; Offset E0: CAN1
+ .word IntDefaultHandler ;; Offset E4: CAN2
+ .word IntDefaultHandler ;; Offset E8: Ethernet
+ .word IntDefaultHandler ;; Offset EC: Hibernation module
+ .if $$defined(USB_ENABLE_UPDATE)
+ .ref USB0DeviceIntHandler
+ .word USB0DeviceIntHandler ;; Offset F0: USB 0 Controller
+ .else
+ .word IntDefaultHandler ;; Offset F0: USB 0 Controller
+ .endif
+ .endif
+
+;;*****************************************************************************
+;;
+;; This portion of the file goes into the text section.
+;;
+;;*****************************************************************************
+ .text
+
+;;*****************************************************************************
+;;
+;; 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.
+;;
+;;*****************************************************************************
+ .ref bss_run
+bss_start .word bss_run
+ .ref __STACK_TOP
+bss_end .word __STACK_TOP
+
+ .thumbfunc ProcessorInit
+ProcessorInit: .asmfunc
+ ;;
+ ;; Copy the code image from flash to SRAM.
+ ;;
+ movs r0, #0x0000
+ movs r1, #0x0000
+ movt r1, #0x2000
+ ldr r2, bss_start
+copy_loop:
+ ldr r3, [r0], #4
+ str r3, [r1], #4
+ cmp r1, r2
+ blt copy_loop
+
+ ;;
+ ;; Zero fill the .bss section.
+ ;;
+ movs r0, #0x0000
+ ldr r2, bss_end
+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]
+
+ ;;
+ ;; Set the return address to the code just copied into SRAM.
+ ;;
+ orr lr, lr, #0x20000000
+
+ ;;
+ ;; Return to the caller.
+ ;;
+ bx lr
+ .endasmfunc
+
+;;*****************************************************************************
+;;
+;; The reset handler, which gets called when the processor starts.
+;;
+;;*****************************************************************************
+ .thumbfunc ResetISR
+ResetISR: .asmfunc
+ ;;
+ ;; 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, r1, #0x00F00000
+ str r1, [r0]
+
+ ;;
+ ;; Initialize the processor.
+ ;;
+ bl ProcessorInit
+
+ ;;
+ ;; Call the user-supplied low level hardware initialization function
+ ;; if provided.
+ ;;
+ .if $$defined(BL_HW_INIT_FN_HOOK)
+ .ref BL_HW_INIT_FN_HOOK
+ bl BL_HW_INIT_FN_HOOK
+ .endif
+
+ ;;
+ ;; See if an update should be performed.
+ ;;
+ .ref CheckForceUpdate
+ bl CheckForceUpdate
+ cbz r0, CallApplication
+
+ ;;
+ ;; Configure the microcontroller.
+ ;;
+ .thumbfunc EnterBootLoader
+EnterBootLoader:
+ .if $$defined(ENET_ENABLE_UPDATE)
+ .ref ConfigureEnet
+ bl ConfigureEnet
+ .elseif $$defined(CAN_ENABLE_UPDATE)
+ .ref ConfigureCAN
+ bl ConfigureCAN
+ .elseif $$defined(USB_ENABLE_UPDATE)
+ .ref ConfigureUSB
+ bl ConfigureUSB
+ .else
+ .ref ConfigureDevice
+ bl ConfigureDevice
+ .endif
+
+ ;;
+ ;; Call the user-supplied initialization function if provided.
+ ;;
+ .if $$defined(BL_INIT_FN_HOOK)
+ .ref BL_INIT_FN_HOOK
+ bl BL_INIT_FN_HOOK
+ .endif
+
+ ;;
+ ;; Branch to the update handler.
+ ;;
+ .if $$defined(ENET_ENABLE_UPDATE)
+ .ref UpdateBOOTP
+ b UpdateBOOTP
+ .elseif $$defined(CAN_ENABLE_UPDATE)
+ .ref UpdaterCAN
+ b UpdaterCAN
+ .elseif $$defined(USB_ENABLE_UPDATE)
+ .ref UpdaterUSB
+ b UpdaterUSB
+ .else
+ .ref Updater
+ b Updater
+ .endif
+ .endasmfunc
+
+ ;;
+ ;; This is a second symbol to allow starting the application from the boot
+ ;; loader the linker may not like the perceived jump.
+ ;;
+ .global StartApplication
+ .thumbfunc StartApplication
+StartApplication:
+ ;;
+ ;; Call the application via the reset handler in its vector table. Load
+ ;; the address of the application vector table.
+ ;;
+ .thumbfunc CallApplication
+CallApplication: .asmfunc
+ ;;
+ ;; 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 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]
+
+ ;;
+ ;; 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
+ .endasmfunc
+
+;;*****************************************************************************
+;;
+;; The update handler, which gets called when the application would like to
+;; start an update.
+;;
+;;*****************************************************************************
+ .thumbfunc UpdateHandler
+UpdateHandler: .asmfunc
+ ;;
+ ;; Initialize the processor.
+ ;;
+ bl ProcessorInit
+
+ ;;
+ ;; Load the stack pointer from the vector table.
+ ;;
+ movs r0, #0x0000
+ ldr sp, [r0]
+
+ ;;
+ ;; Call the user-supplied low level hardware initialization function
+ ;; if provided.
+ ;;
+ .if $$defined(BL_HW_INIT_FN_HOOK)
+ bl BL_HW_INIT_FN_HOOK
+ .endif
+
+ ;;
+ ;; Call the user-supplied re-initialization function if provided.
+ ;;
+ .if $$defined(BL_REINIT_FN_HOOK)
+ .ref BL_REINIT_FN_HOOK
+ bl BL_REINIT_FN_HOOK
+ .endif
+
+ ;;
+ ;; Branch to the update handler.
+ ;;
+ .if $$defined(ENET_ENABLE_UPDATE)
+ b UpdateBOOTP
+ .elseif $$defined(CAN_ENABLE_UPDATE)
+ .ref AppUpdaterCAN
+ b AppUpdaterCAN
+ .elseif $$defined(USB_ENABLE_UPDATE)
+ .ref AppUpdaterUSB
+ b AppUpdaterUSB
+ .else
+ b Updater
+ .endif
+ .endasmfunc
+
+;;*****************************************************************************
+;;
+;; The NMI handler.
+;;
+;;*****************************************************************************
+ .thumbfunc NmiSR
+NmiSR: .asmfunc
+ .if $$defined(ENABLE_MOSCFAIL_HANDLER)
+ ;;
+ ;; Grab the fault frame from the stack (the stack will be cleared by the
+ ;; processor initialization that follows).
+ ;;
+ ldm sp, {r4-r11}
+ mov r12, lr
+
+ ;;
+ ;; Initialize the processor.
+ ;;
+ bl ProcessorInit
+
+ ;;
+ ;; 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 $$defined(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
+ .else
+ ;;
+ ;; Loop forever since there is nothing that we can do about a NMI.
+ ;;
+ b NmiSR
+ .endif
+ .endasmfunc
+
+;;*****************************************************************************
+;;
+;; The hard fault handler.
+;;
+;;*****************************************************************************
+ .thumbfunc FaultISR
+FaultISR: .asmfunc
+ ;;
+ ;; Loop forever since there is nothing that we can do about a hard fault.
+ ;;
+ b FaultISR
+ .endasmfunc
+
+;;*****************************************************************************
+;;
+;; The default interrupt handler.
+;;
+;;*****************************************************************************
+ .thumbfunc IntDefaultHandler
+IntDefaultHandler: .asmfunc
+ ;;
+ ;; Loop forever since there is nothing that we can do about an unexpected
+ ;; interrupt.
+ ;;
+ b IntDefaultHandler
+ .endasmfunc
+
+;;*****************************************************************************
+;;
+;; Provides a small delay. The loop below takes 3 cycles/loop.
+;;
+;;*****************************************************************************
+; .globl Delay
+ .thumbfunc Delay
+Delay: .asmfunc
+ subs r0, #1
+ bne Delay
+ bx lr
+ .endasmfunc
+
+ .thumbfunc _c_int00
+ .global _c_int00
+_c_int00: .asmfunc
+ b ResetISR
+
+;;*****************************************************************************
+;;
+;; This is the end of the file.
+;;
+;;*****************************************************************************
+ .end
diff --git a/boot_loader/bl_startup_ewarm.S b/boot_loader/bl_startup_ewarm.S new file mode 100644 index 0000000..2100b96 --- /dev/null +++ b/boot_loader/bl_startup_ewarm.S @@ -0,0 +1,612 @@ +//*****************************************************************************
+//
+// bl_startup_ewarm.S - Startup code for EWARM.
+//
+// Copyright (c) 2007-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 the assember definitions used to make this code compiler
+// independent.
+//
+//*****************************************************************************
+#include "inc/hw_nvic.h"
+#include "inc/hw_sysctl.h"
+#include "bl_config.h"
+
+//*****************************************************************************
+//
+// The stack gets placed into the zero-init section.
+//
+//*****************************************************************************
+ rseg .bss:DATA(2)
+
+//*****************************************************************************
+//
+// Allocate storage for the stack.
+//
+//*****************************************************************************
+ export g_pulStack
+g_pulStack ds8 STACK_SIZE * 4
+
+//*****************************************************************************
+//
+// This portion of the file goes into the vector section.
+//
+//*****************************************************************************
+ rseg INTVEC:CONST(2)
+
+//*****************************************************************************
+//
+// The minimal vector table for a Cortex-M3 processor.
+//
+//*****************************************************************************
+ export __vector_table
+__vector_table
+ dcd g_pulStack + (STACK_SIZE * 4) // Offset 00: Initial stack pointer
+ dcd ResetISR - 0x20000000 // Offset 04: Reset handler
+ dcd NmiSR - 0x20000000 // Offset 08: NMI handler
+ dcd FaultISR - 0x20000000 // Offset 0C: Hard fault handler
+ dcd IntDefaultHandler // Offset 10: MPU fault handler
+ dcd IntDefaultHandler // Offset 14: Bus fault handler
+ dcd IntDefaultHandler // Offset 18: Usage fault handler
+ dcd 0 // Offset 1C: Reserved
+ dcd 0 // Offset 20: Reserved
+ dcd 0 // Offset 24: Reserved
+ dcd 0 // Offset 28: Reserved
+ dcd UpdateHandler - 0x20000000 // Offset 2C: SVCall handler
+ dcd IntDefaultHandler // Offset 30: Debug monitor handler
+ dcd 0 // Offset 34: Reserved
+ dcd IntDefaultHandler // Offset 38: PendSV handler
+#if defined(ENET_ENABLE_UPDATE)
+ import SysTickIntHandler
+ dcd SysTickIntHandler // Offset 3C: SysTick handler
+#else
+ dcd IntDefaultHandler // Offset 3C: SysTick handler
+#endif
+#if defined(UART_ENABLE_UPDATE) && defined(UART_AUTOBAUD)
+ import GPIOIntHandler
+ dcd GPIOIntHandler // Offset 40: GPIO port A handler
+#else
+ dcd IntDefaultHandler // Offset 40: GPIO port A handler
+#endif
+#if (defined(USB_ENABLE_UPDATE) || \
+ (APP_START_ADDRESS != VTABLE_START_ADDRESS))
+ dcd IntDefaultHandler // Offset 44: GPIO Port B
+ dcd IntDefaultHandler // Offset 48: GPIO Port C
+ dcd IntDefaultHandler // Offset 4C: GPIO Port D
+ dcd IntDefaultHandler // Offset 50: GPIO Port E
+ dcd IntDefaultHandler // Offset 54: UART0 Rx and Tx
+ dcd IntDefaultHandler // Offset 58: UART1 Rx and Tx
+ dcd IntDefaultHandler // Offset 5C: SSI0 Rx and Tx
+ dcd IntDefaultHandler // Offset 60: I2C0 Master and Slave
+ dcd IntDefaultHandler // Offset 64: PWM Fault
+ dcd IntDefaultHandler // Offset 68: PWM Generator 0
+ dcd IntDefaultHandler // Offset 6C: PWM Generator 1
+ dcd IntDefaultHandler // Offset 70: PWM Generator 2
+ dcd IntDefaultHandler // Offset 74: Quadrature Encoder 0
+ dcd IntDefaultHandler // Offset 78: ADC Sequence 0
+ dcd IntDefaultHandler // Offset 7C: ADC Sequence 1
+ dcd IntDefaultHandler // Offset 80: ADC Sequence 2
+ dcd IntDefaultHandler // Offset 84: ADC Sequence 3
+ dcd IntDefaultHandler // Offset 88: Watchdog timer
+ dcd IntDefaultHandler // Offset 8C: Timer 0 subtimer A
+ dcd IntDefaultHandler // Offset 90: Timer 0 subtimer B
+ dcd IntDefaultHandler // Offset 94: Timer 1 subtimer A
+ dcd IntDefaultHandler // Offset 98: Timer 1 subtimer B
+ dcd IntDefaultHandler // Offset 9C: Timer 2 subtimer A
+ dcd IntDefaultHandler // Offset A0: Timer 2 subtimer B
+ dcd IntDefaultHandler // Offset A4: Analog Comparator 0
+ dcd IntDefaultHandler // Offset A8: Analog Comparator 1
+ dcd IntDefaultHandler // Offset AC: Analog Comparator 2
+ dcd IntDefaultHandler // Offset B0: System Control
+ dcd IntDefaultHandler // Offset B4: FLASH Control
+#endif
+#if (defined(USB_ENABLE_UPDATE) || (APP_START_ADDRESS != VTABLE_START_ADDRESS))
+ dcd IntDefaultHandler // Offset B8: GPIO Port F
+ dcd IntDefaultHandler // Offset BC: GPIO Port G
+ dcd IntDefaultHandler // Offset C0: GPIO Port H
+ dcd IntDefaultHandler // Offset C4: UART2 Rx and Tx
+ dcd IntDefaultHandler // Offset C8: SSI1 Rx and Tx
+ dcd IntDefaultHandler // Offset CC: Timer 3 subtimer A
+ dcd IntDefaultHandler // Offset D0: Timer 3 subtimer B
+ dcd IntDefaultHandler // Offset D4: I2C1 Master and Slave
+ dcd IntDefaultHandler // Offset D8: Quadrature Encoder 1
+ dcd IntDefaultHandler // Offset DC: CAN0
+ dcd IntDefaultHandler // Offset E0: CAN1
+ dcd IntDefaultHandler // Offset E4: CAN2
+ dcd IntDefaultHandler // Offset E8: Ethernet
+ dcd IntDefaultHandler // Offset EC: Hibernation module
+#if defined(USB_ENABLE_UPDATE)
+ import USB0DeviceIntHandler
+ dcd USB0DeviceIntHandler // Offset F0: USB 0 Controller
+#else
+ dcd IntDefaultHandler // Offset F0: USB 0 Controller
+#endif
+#endif
+
+//*****************************************************************************
+//
+// This portion of the file goes into the text section.
+//
+//*****************************************************************************
+ rseg CODE:CODE(2)
+ thumb
+
+//*****************************************************************************
+//
+// 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.
+//
+//*****************************************************************************
+ProcessorInit
+ //
+ // Copy the code image from flash to SRAM.
+ //
+ movs r0, #0x0000
+ movs r1, #0x0000
+ movt r1, #0x2000
+ ldr r2, =SFB(.bss)
+copy_loop
+ ldr r3, [r0], #4
+ str r3, [r1], #4
+ cmp r1, r2
+ blt copy_loop
+
+ //
+ // Zero fill the .bss section.
+ //
+ movs r0, #0x0000
+ ldr r2, =SFE(.bss)
+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]
+
+ //
+ // Set the return address to the code just copied into SRAM.
+ //
+ orr lr, lr, #0x20000000
+
+ //
+ // Return to the caller.
+ //
+ bx lr
+
+//*****************************************************************************
+//
+// The reset handler, which gets called when the processor starts.
+//
+//*****************************************************************************
+ export ResetISR
+ResetISR
+ //
+ // 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, r1, #0x00F00000
+ str r1, [r0]
+
+ //
+ // Initialize the processor.
+ //
+ bl ProcessorInit
+
+ //
+ // Call the user-supplied low level hardware initialization function
+ // if provided.
+ //
+#ifdef BL_HW_INIT_FN_HOOK
+ import BL_HW_INIT_FN_HOOK
+ bl BL_HW_INIT_FN_HOOK
+#endif
+
+ //
+ // See if an update should be performed.
+ //
+ import CheckForceUpdate
+ bl CheckForceUpdate
+ cbz r0, CallApplication
+
+ //
+ // Configure the microcontroller.
+ //
+EnterBootLoader
+#ifdef ENET_ENABLE_UPDATE
+ import ConfigureEnet
+ bl ConfigureEnet
+#elif defined(CAN_ENABLE_UPDATE)
+ import ConfigureCAN
+ bl ConfigureCAN
+#elif defined(USB_ENABLE_UPDATE)
+ import ConfigureUSB
+ bl ConfigureUSB
+#else
+ import ConfigureDevice
+ bl ConfigureDevice
+#endif
+
+ //
+ // Call the user-supplied initialization function if provided.
+ //
+#ifdef BL_INIT_FN_HOOK
+ import BL_INIT_FN_HOOK
+ bl BL_INIT_FN_HOOK
+#endif
+
+ //
+ // Branch to the update handler.
+ //
+#ifdef ENET_ENABLE_UPDATE
+ import UpdateBOOTP
+ b UpdateBOOTP
+#elif defined(CAN_ENABLE_UPDATE)
+ import UpdaterCAN
+ b UpdaterCAN
+#elif defined(USB_ENABLE_UPDATE)
+ import UpdaterUSB
+ b UpdaterUSB
+#else
+ import Updater
+ b Updater
+#endif
+
+ //
+ // 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's vector table first.
+ //
+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 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]
+
+ //
+ // Load the stack pointer from the application's vector table at the
+ // beginning of the image.
+ //
+#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
+ //
+ // Initialize the processor.
+ //
+ bl ProcessorInit
+
+ //
+ // Load the stack pointer from the vector table.
+ //
+ movs r0, #0x0000
+ ldr sp, [r0]
+
+ //
+ // Call the user-supplied low level hardware initialization function
+ // if provided.
+ //
+#ifdef BL_HW_INIT_FN_HOOK
+ bl BL_HW_INIT_FN_HOOK
+#endif
+
+ //
+ // Call the user-supplied re-initialization function if provided.
+ //
+#ifdef BL_REINIT_FN_HOOK
+ import BL_REINIT_FN_HOOK
+ bl BL_REINIT_FN_HOOK
+#endif
+
+ //
+ // Branch to the update handler.
+ //
+#ifdef ENET_ENABLE_UPDATE
+ b UpdateBOOTP
+#elif defined(CAN_ENABLE_UPDATE)
+ import AppUpdaterCAN
+ b AppUpdaterCAN
+#elif defined(USB_ENABLE_UPDATE)
+ import AppUpdaterUSB
+ b AppUpdaterUSB
+#else
+ b Updater
+#endif
+
+//*****************************************************************************
+//
+// The NMI handler.
+//
+//*****************************************************************************
+NmiSR
+#ifdef ENABLE_MOSCFAIL_HANDLER
+ //
+ // Grab the fault frame from the stack (the stack will be cleared by the
+ // processor initialization that follows).
+ //
+ ldm sp, {r4-r11}
+ mov r12, lr
+
+ //
+ // Initialize the processor.
+ //
+ bl ProcessorInit
+
+ //
+ // 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.
+ //
+#ifdef 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
+#else
+ //
+ // Loop forever since there is nothing that we can do about a NMI.
+ //
+ b .
+#endif
+
+//*****************************************************************************
+//
+// The hard fault handler.
+//
+//*****************************************************************************
+FaultISR
+ //
+ // Loop forever since there is nothing that we can do about a hard fault.
+ //
+ b .
+
+//*****************************************************************************
+//
+// The default interrupt handler.
+//
+//*****************************************************************************
+IntDefaultHandler
+ //
+ // Loop forever since there is nothing that we can do about an unexpected
+ // interrupt.
+ //
+ b .
+
+//*****************************************************************************
+//
+// Provides a small delay. The loop below takes 3 cycles/loop.
+//
+//*****************************************************************************
+ export Delay
+Delay
+ subs r0, #1
+ bne Delay
+ bx lr
+
+//*****************************************************************************
+//
+// This is the end of the file.
+//
+//*****************************************************************************
+ end
diff --git a/boot_loader/bl_startup_gcc.S b/boot_loader/bl_startup_gcc.S new file mode 100644 index 0000000..53f28d1 --- /dev/null +++ b/boot_loader/bl_startup_gcc.S @@ -0,0 +1,630 @@ +//*****************************************************************************
+//
+// bl_startup_gcc.S - Startup code for GNU.
+//
+// Copyright (c) 2007-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 the assember definitions used to make this code compiler
+// independent.
+//
+//*****************************************************************************
+#include "inc/hw_nvic.h"
+#include "inc/hw_sysctl.h"
+#include "bl_config.h"
+
+//*****************************************************************************
+//
+// Put the assembler into the correct configuration.
+//
+//*****************************************************************************
+ .syntax unified
+ .thumb
+
+//*****************************************************************************
+//
+// The stack gets placed into the zero-init section.
+//
+//*****************************************************************************
+ .bss
+
+//*****************************************************************************
+//
+// Allocate storage for the stack.
+//
+//*****************************************************************************
+g_pulStack:
+ .space STACK_SIZE * 4
+
+//*****************************************************************************
+//
+// This portion of the file goes into the text section.
+//
+//*****************************************************************************
+ .section .isr_vector
+
+//*****************************************************************************
+//
+// The minimal vector table for a Cortex-M3 processor.
+//
+//*****************************************************************************
+Vectors:
+ .word g_pulStack + (STACK_SIZE * 4) // Offset 00: Initial stack pointer
+ .word ResetISR - 0x20000000 // Offset 04: Reset handler
+ .word NmiSR - 0x20000000 // Offset 08: NMI handler
+ .word FaultISR - 0x20000000 // Offset 0C: Hard fault handler
+ .word IntDefaultHandler // Offset 10: MPU fault handler
+ .word IntDefaultHandler // Offset 14: Bus fault handler
+ .word IntDefaultHandler // Offset 18: Usage fault handler
+ .word 0 // Offset 1C: Reserved
+ .word 0 // Offset 20: Reserved
+ .word 0 // Offset 24: Reserved
+ .word 0 // Offset 28: Reserved
+ .word UpdateHandler - 0x20000000 // Offset 2C: SVCall handler
+ .word IntDefaultHandler // Offset 30: Debug monitor handler
+ .word 0 // Offset 34: Reserved
+ .word IntDefaultHandler // Offset 38: PendSV handler
+#if defined(ENET_ENABLE_UPDATE)
+ .extern SysTickIntHandler
+ .word SysTickIntHandler // Offset 3C: SysTick handler
+#else
+ .word IntDefaultHandler // Offset 3C: SysTick handler
+#endif
+#if defined(UART_ENABLE_UPDATE) && defined(UART_AUTOBAUD)
+ .extern GPIOIntHandler
+ .word GPIOIntHandler // Offset 40: GPIO port A handler
+#else
+ .word IntDefaultHandler // Offset 40: GPIO port A handler
+#endif
+#if (defined(USB_ENABLE_UPDATE) || \
+ (APP_START_ADDRESS != VTABLE_START_ADDRESS))
+ .word IntDefaultHandler // Offset 44: GPIO Port B
+ .word IntDefaultHandler // Offset 48: GPIO Port C
+ .word IntDefaultHandler // Offset 4C: GPIO Port D
+ .word IntDefaultHandler // Offset 50: GPIO Port E
+ .word IntDefaultHandler // Offset 54: UART0 Rx and Tx
+ .word IntDefaultHandler // Offset 58: UART1 Rx and Tx
+ .word IntDefaultHandler // Offset 5C: SSI0 Rx and Tx
+ .word IntDefaultHandler // Offset 60: I2C0 Master and Slave
+ .word IntDefaultHandler // Offset 64: PWM Fault
+ .word IntDefaultHandler // Offset 68: PWM Generator 0
+ .word IntDefaultHandler // Offset 6C: PWM Generator 1
+ .word IntDefaultHandler // Offset 70: PWM Generator 2
+ .word IntDefaultHandler // Offset 74: Quadrature Encoder 0
+ .word IntDefaultHandler // Offset 78: ADC Sequence 0
+ .word IntDefaultHandler // Offset 7C: ADC Sequence 1
+ .word IntDefaultHandler // Offset 80: ADC Sequence 2
+ .word IntDefaultHandler // Offset 84: ADC Sequence 3
+ .word IntDefaultHandler // Offset 88: Watchdog timer
+ .word IntDefaultHandler // Offset 8C: Timer 0 subtimer A
+ .word IntDefaultHandler // Offset 90: Timer 0 subtimer B
+ .word IntDefaultHandler // Offset 94: Timer 1 subtimer A
+ .word IntDefaultHandler // Offset 98: Timer 1 subtimer B
+ .word IntDefaultHandler // Offset 9C: Timer 2 subtimer A
+ .word IntDefaultHandler // Offset A0: Timer 2 subtimer B
+ .word IntDefaultHandler // Offset A4: Analog Comparator 0
+ .word IntDefaultHandler // Offset A8: Analog Comparator 1
+ .word IntDefaultHandler // Offset AC: Analog Comparator 2
+ .word IntDefaultHandler // Offset B0: System Control
+ .word IntDefaultHandler // Offset B4: FLASH Control
+#endif
+#if (defined(USB_ENABLE_UPDATE) || (APP_START_ADDRESS != VTABLE_START_ADDRESS))
+ .word IntDefaultHandler // Offset B8: GPIO Port F
+ .word IntDefaultHandler // Offset BC: GPIO Port G
+ .word IntDefaultHandler // Offset C0: GPIO Port H
+ .word IntDefaultHandler // Offset C4: UART2 Rx and Tx
+ .word IntDefaultHandler // Offset C8: SSI1 Rx and Tx
+ .word IntDefaultHandler // Offset CC: Timer 3 subtimer A
+ .word IntDefaultHandler // Offset D0: Timer 3 subtimer B
+ .word IntDefaultHandler // Offset D4: I2C1 Master and Slave
+ .word IntDefaultHandler // Offset D8: Quadrature Encoder 1
+ .word IntDefaultHandler // Offset DC: CAN0
+ .word IntDefaultHandler // Offset E0: CAN1
+ .word IntDefaultHandler // Offset E4: CAN2
+ .word IntDefaultHandler // Offset E8: Ethernet
+ .word IntDefaultHandler // Offset EC: Hibernation module
+#if defined(USB_ENABLE_UPDATE)
+ .extern USB0DeviceIntHandler
+ .word USB0DeviceIntHandler // Offset F0: USB 0 Controller
+#else
+ .word IntDefaultHandler // Offset F0: USB 0 Controller
+#endif
+#endif
+
+//*****************************************************************************
+//
+// This portion of the file goes into the text section.
+//
+//*****************************************************************************
+ .text
+
+//*****************************************************************************
+//
+// 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.
+//
+//*****************************************************************************
+ .thumb_func
+ProcessorInit:
+ //
+ // Copy the code image from flash to SRAM.
+ //
+ movs r0, #0x0000
+ movs r1, #0x0000
+ movt r1, #0x2000
+ .extern _bss
+ ldr r2, =_bss
+copy_loop:
+ ldr r3, [r0], #4
+ str r3, [r1], #4
+ cmp r1, r2
+ blt copy_loop
+
+ //
+ // Zero fill the .bss section.
+ //
+ movs r0, #0x0000
+ .extern _ebss
+ ldr r2, =_ebss
+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]
+
+ //
+ // Set the return address to the code just copied into SRAM.
+ //
+ orr lr, lr, #0x20000000
+
+ //
+ // Return to the caller.
+ //
+ bx lr
+
+//*****************************************************************************
+//
+// The reset handler, which gets called when the processor starts.
+//
+//*****************************************************************************
+ .globl ResetISR
+ .thumb_func
+ResetISR:
+ //
+ // 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, r1, #0x00F00000
+ str r1, [r0]
+
+ //
+ // Initialize the processor.
+ //
+ bl ProcessorInit
+
+ //
+ // Call the user-supplied low level hardware initialization function
+ // if provided.
+ //
+#ifdef BL_HW_INIT_FN_HOOK
+ .extern BL_HW_INIT_FN_HOOK
+ bl BL_HW_INIT_FN_HOOK
+#endif
+
+ //
+ // See if an update should be performed.
+ //
+ .extern CheckForceUpdate
+ bl CheckForceUpdate
+ cbz r0, CallApplication
+
+ //
+ // Configure the microcontroller.
+ //
+ .thumb_func
+EnterBootLoader:
+#ifdef ENET_ENABLE_UPDATE
+ .extern ConfigureEnet
+ bl ConfigureEnet
+#elif defined(CAN_ENABLE_UPDATE)
+ .extern ConfigureCAN
+ bl ConfigureCAN
+#elif defined(USB_ENABLE_UPDATE)
+ .extern ConfigureUSB
+ bl ConfigureUSB
+#else
+ .extern ConfigureDevice
+ bl ConfigureDevice
+#endif
+
+ //
+ // Call the user-supplied initialization function if provided.
+ //
+#ifdef BL_INIT_FN_HOOK
+ .extern BL_INIT_FN_HOOK
+ bl BL_INIT_FN_HOOK
+#endif
+
+ //
+ // Branch to the update handler.
+ //
+#ifdef ENET_ENABLE_UPDATE
+ .extern UpdateBOOTP
+ b UpdateBOOTP
+#elif defined(CAN_ENABLE_UPDATE)
+ .extern UpdaterCAN
+ b UpdaterCAN
+#elif defined(USB_ENABLE_UPDATE)
+ .extern UpdaterUSB
+ b UpdaterUSB
+#else
+ .extern Updater
+ b Updater
+#endif
+
+ //
+ // This is a second symbol to allow starting the application from the boot
+ // loader the linker may not like the perceived jump.
+ //
+ .globl StartApplication
+ .thumb_func
+StartApplication:
+ //
+ // Call the application via the reset handler in its vector table. Load
+ // the address of the application vector table.
+ //
+ .thumb_func
+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 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]
+
+ //
+ // 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.
+//
+//*****************************************************************************
+ .thumb_func
+UpdateHandler:
+ //
+ // Initialize the processor.
+ //
+ bl ProcessorInit
+
+ //
+ // Load the stack pointer from the vector table.
+ //
+ movs r0, #0x0000
+ ldr sp, [r0]
+
+ //
+ // Call the user-supplied low level hardware initialization function
+ // if provided.
+ //
+#ifdef BL_HW_INIT_FN_HOOK
+ bl BL_HW_INIT_FN_HOOK
+#endif
+
+ //
+ // Call the user-supplied re-initialization function if provided.
+ //
+#ifdef BL_REINIT_FN_HOOK
+ .extern BL_REINIT_FN_HOOK
+ bl BL_REINIT_FN_HOOK
+#endif
+
+ //
+ // Branch to the update handler.
+ //
+#ifdef ENET_ENABLE_UPDATE
+ b UpdateBOOTP
+#elif defined(CAN_ENABLE_UPDATE)
+ .extern AppUpdaterCAN
+ b AppUpdaterCAN
+#elif defined(USB_ENABLE_UPDATE)
+ .extern AppUpdaterUSB
+ b AppUpdaterUSB
+#else
+ b Updater
+#endif
+
+//*****************************************************************************
+//
+// The NMI handler.
+//
+//*****************************************************************************
+ .thumb_func
+NmiSR:
+#ifdef ENABLE_MOSCFAIL_HANDLER
+ //
+ // Grab the fault frame from the stack (the stack will be cleared by the
+ // processor initialization that follows).
+ //
+ ldm sp, {r4-r11}
+ mov r12, lr
+
+ //
+ // Initialize the processor.
+ //
+ bl ProcessorInit
+
+ //
+ // 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.
+ //
+#ifdef 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.
+ //
+ .thumb_func
+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
+#else
+ //
+ // Loop forever since there is nothing that we can do about a NMI.
+ //
+ b .
+#endif
+
+//*****************************************************************************
+//
+// The hard fault handler.
+//
+//*****************************************************************************
+ .thumb_func
+FaultISR:
+ //
+ // Loop forever since there is nothing that we can do about a hard fault.
+ //
+ b .
+
+//*****************************************************************************
+//
+// The default interrupt handler.
+//
+//*****************************************************************************
+ .thumb_func
+IntDefaultHandler:
+ //
+ // Loop forever since there is nothing that we can do about an unexpected
+ // interrupt.
+ //
+ b .
+
+//*****************************************************************************
+//
+// Provides a small delay. The loop below takes 3 cycles/loop.
+//
+//*****************************************************************************
+ .globl Delay
+ .thumb_func
+Delay:
+ subs r0, #1
+ bne Delay
+ bx lr
+
+//*****************************************************************************
+//
+// This is the end of the file.
+//
+//*****************************************************************************
+ .end
diff --git a/boot_loader/bl_startup_rvmdk.S b/boot_loader/bl_startup_rvmdk.S new file mode 100644 index 0000000..435c325 --- /dev/null +++ b/boot_loader/bl_startup_rvmdk.S @@ -0,0 +1,653 @@ +;******************************************************************************
+;
+; bl_startup_rvmdk.S - Startup code for RV-MDK.
+;
+; Copyright (c) 2007-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 bl_config.inc
+
+;******************************************************************************
+;
+; 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
+
+;******************************************************************************
+;
+; Put the assembler into the correct configuration.
+;
+;******************************************************************************
+ thumb
+ require8
+ preserve8
+
+;******************************************************************************
+;
+; The stack gets placed into the zero-init section.
+;
+;******************************************************************************
+ area ||.bss||, noinit, align=2
+
+;******************************************************************************
+;
+; Allocate storage for the stack.
+;
+;******************************************************************************
+g_pulStack
+ space _STACK_SIZE * 4
+
+;******************************************************************************
+;
+; This portion of the file goes into the reset section.
+;
+;******************************************************************************
+ area RESET, code, readonly, align=3
+
+;******************************************************************************
+;
+; The minimal vector table for a Cortex-M3 processor.
+;
+;******************************************************************************
+ export __Vectors
+__Vectors
+ dcd g_pulStack + (_STACK_SIZE * 4) ; Offset 00: Initial stack pointer
+ dcd Reset_Handler ; Offset 04: Reset handler
+ dcd NmiSR ; Offset 08: NMI handler
+ dcd FaultISR ; Offset 0C: Hard fault handler
+ dcd IntDefaultHandler ; Offset 10: MPU fault handler
+ dcd IntDefaultHandler ; Offset 14: Bus fault handler
+ dcd IntDefaultHandler ; Offset 18: Usage fault handler
+ dcd 0 ; Offset 1C: Reserved
+ dcd 0 ; Offset 20: Reserved
+ dcd 0 ; Offset 24: Reserved
+ dcd 0 ; Offset 28: Reserved
+ dcd UpdateHandler ; Offset 2C: SVCall handler
+ dcd IntDefaultHandler ; Offset 30: Debug monitor handler
+ dcd 0 ; Offset 34: Reserved
+ dcd IntDefaultHandler ; Offset 38: PendSV handler
+ if :def:_ENET_ENABLE_UPDATE
+ import SysTickIntHandler
+ dcd SysTickIntHandler ; Offset 3C: SysTick handler
+ else
+ dcd IntDefaultHandler ; Offset 3C: SysTick handler
+ endif
+ if :def:_UART_ENABLE_UPDATE :land: :def:_UART_AUTOBAUD
+ import GPIOIntHandler
+ dcd GPIOIntHandler ; Offset 40: GPIO port A handler
+ else
+ dcd IntDefaultHandler ; Offset 40: GPIO port A handler
+ endif
+ if :def:_USB_ENABLE_UPDATE :lor: \
+ (_APP_START_ADDRESS != _VTABLE_START_ADDRESS)
+ dcd IntDefaultHandler ; Offset 44: GPIO Port B
+ dcd IntDefaultHandler ; Offset 48: GPIO Port C
+ dcd IntDefaultHandler ; Offset 4C: GPIO Port D
+ dcd IntDefaultHandler ; Offset 50: GPIO Port E
+ dcd IntDefaultHandler ; Offset 54: UART0 Rx and Tx
+ dcd IntDefaultHandler ; Offset 58: UART1 Rx and Tx
+ dcd IntDefaultHandler ; Offset 5C: SSI0 Rx and Tx
+ dcd IntDefaultHandler ; Offset 60: I2C0 Master and Slave
+ dcd IntDefaultHandler ; Offset 64: PWM Fault
+ dcd IntDefaultHandler ; Offset 68: PWM Generator 0
+ dcd IntDefaultHandler ; Offset 6C: PWM Generator 1
+ dcd IntDefaultHandler ; Offset 70: PWM Generator 2
+ dcd IntDefaultHandler ; Offset 74: Quadrature Encoder 0
+ dcd IntDefaultHandler ; Offset 78: ADC Sequence 0
+ dcd IntDefaultHandler ; Offset 7C: ADC Sequence 1
+ dcd IntDefaultHandler ; Offset 80: ADC Sequence 2
+ dcd IntDefaultHandler ; Offset 84: ADC Sequence 3
+ dcd IntDefaultHandler ; Offset 88: Watchdog timer
+ dcd IntDefaultHandler ; Offset 8C: Timer 0 subtimer A
+ dcd IntDefaultHandler ; Offset 90: Timer 0 subtimer B
+ dcd IntDefaultHandler ; Offset 94: Timer 1 subtimer A
+ dcd IntDefaultHandler ; Offset 98: Timer 1 subtimer B
+ dcd IntDefaultHandler ; Offset 9C: Timer 2 subtimer A
+ dcd IntDefaultHandler ; Offset A0: Timer 2 subtimer B
+ dcd IntDefaultHandler ; Offset A4: Analog Comparator 0
+ dcd IntDefaultHandler ; Offset A8: Analog Comparator 1
+ dcd IntDefaultHandler ; Offset AC: Analog Comparator 2
+ dcd IntDefaultHandler ; Offset B0: System Control
+ dcd IntDefaultHandler ; Offset B4: FLASH Control
+ endif
+ if :def:_USB_ENABLE_UPDATE :lor: \
+ (_APP_START_ADDRESS != _VTABLE_START_ADDRESS)
+ dcd IntDefaultHandler ; Offset B8: GPIO Port F
+ dcd IntDefaultHandler ; Offset BC: GPIO Port G
+ dcd IntDefaultHandler ; Offset C0: GPIO Port H
+ dcd IntDefaultHandler ; Offset C4: UART2 Rx and Tx
+ dcd IntDefaultHandler ; Offset C8: SSI1 Rx and Tx
+ dcd IntDefaultHandler ; Offset CC: Timer 3 subtimer A
+ dcd IntDefaultHandler ; Offset D0: Timer 3 subtimer B
+ dcd IntDefaultHandler ; Offset D4: I2C1 Master and Slave
+ dcd IntDefaultHandler ; Offset D8: Quadrature Encoder 1
+ dcd IntDefaultHandler ; Offset DC: CAN0
+ dcd IntDefaultHandler ; Offset E0: CAN1
+ dcd IntDefaultHandler ; Offset E4: CAN2
+ dcd IntDefaultHandler ; Offset E8: Ethernet
+ dcd IntDefaultHandler ; Offset EC: Hibernation module
+ if :def: _USB_ENABLE_UPDATE
+ import USB0DeviceIntHandler
+ dcd USB0DeviceIntHandler ; Offset F0: USB 0 Controller
+ else
+ dcd IntDefaultHandler ; Offset F0: USB 0 Controller
+ endif
+ endif
+
+;******************************************************************************
+;
+; 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 NMI handler.
+;
+;******************************************************************************
+NmiSR
+ if :def:_ENABLE_MOSCFAIL_HANDLER
+ ;
+ ; Grab the fault frame from the stack (the stack will be cleared by the
+ ; processor initialization that follows).
+ ;
+ ldm sp, {r4-r11}
+ mov r12, lr
+
+ ;
+ ; Initialize the processor.
+ ;
+ bl ProcessorInit
+
+ ;
+ ; Branch to the SRAM copy of the NMI handler.
+ ;
+ ldr pc, =NmiSR_In_SRAM
+ else
+ ;
+ ; Loop forever since there is nothing that we can do about a NMI.
+ ;
+ b .
+ endif
+
+;******************************************************************************
+;
+; The hard fault handler.
+;
+;******************************************************************************
+FaultISR
+ ;
+ ; Loop forever since there is nothing that we can do about a hard fault.
+ ;
+ b .
+
+;******************************************************************************
+;
+; 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
+
+;******************************************************************************
+;
+; This portion of the file goes into the text section.
+;
+;******************************************************************************
+ align 4
+ area ||.text||, code, readonly, align=2
+
+Reset_Handler_In_SRAM
+ ;
+ ; Call the user-supplied low level hardware initialization function
+ ; if provided.
+ ;
+ if :def:_BL_HW_INIT_FN_HOOK
+ import $_BL_HW_INIT_FN_HOOK
+ bl $_BL_HW_INIT_FN_HOOK
+ endif
+
+ ;
+ ; See if an update should be performed.
+ ;
+ import CheckForceUpdate
+ bl CheckForceUpdate
+ cbz r0, CallApplication
+
+ ;
+ ; Configure the microcontroller.
+ ;
+EnterBootLoader
+ if :def:_ENET_ENABLE_UPDATE
+ import ConfigureEnet
+ bl ConfigureEnet
+ elif :def:_CAN_ENABLE_UPDATE
+ import ConfigureCAN
+ bl ConfigureCAN
+ elif :def:_USB_ENABLE_UPDATE
+ import ConfigureUSB
+ bl ConfigureUSB
+ else
+ import ConfigureDevice
+ bl ConfigureDevice
+ endif
+
+ ;
+ ; Call the user-supplied initialization function if provided.
+ ;
+ if :def:_BL_INIT_FN_HOOK
+ import $_BL_INIT_FN_HOOK
+ bl $_BL_INIT_FN_HOOK
+ endif
+
+ ;
+ ; Branch to the update handler.
+ ;
+ if :def:_ENET_ENABLE_UPDATE
+ import UpdateBOOTP
+ b UpdateBOOTP
+ elif :def:_CAN_ENABLE_UPDATE
+ import UpdaterCAN
+ b UpdaterCAN
+ elif :def:_USB_ENABLE_UPDATE
+ import UpdaterUSB
+ b UpdaterUSB
+ else
+ import Updater
+ b Updater
+ endif
+
+ ;
+ ; 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]
+
+ ;
+ ; 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
+
+ ;
+ ; Call the user-supplied re-initialization function if provided.
+ ;
+ if :def:_BL_REINIT_FN_HOOK
+ import $_BL_REINIT_FN_HOOK
+ bl $_BL_REINIT_FN_HOOK
+ endif
+
+ ;
+ ; Branch to the update handler.
+ ;
+ if :def:_ENET_ENABLE_UPDATE
+ b UpdateBOOTP
+ elif :def:_CAN_ENABLE_UPDATE
+ import AppUpdaterCAN
+ b AppUpdaterCAN
+ elif :def:_USB_ENABLE_UPDATE
+ import AppUpdaterUSB
+ b AppUpdaterUSB
+ else
+ b Updater
+ endif
+
+;******************************************************************************
+;
+; 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 default interrupt handler.
+;
+;******************************************************************************
+IntDefaultHandler
+ ;
+ ; Loop forever since there is nothing that we can do about an unexpected
+ ; interrupt.
+ ;
+ b .
+
+;******************************************************************************
+;
+; Provides a small delay. The loop below takes 3 cycles/loop.
+;
+;******************************************************************************
+ export Delay
+Delay
+ subs r0, #1
+ bne Delay
+ bx lr
+
+;******************************************************************************
+;
+; This is the end of the file.
+;
+;******************************************************************************
+ align 4
+ end
diff --git a/boot_loader/bl_startup_sourcerygxx.S b/boot_loader/bl_startup_sourcerygxx.S new file mode 100644 index 0000000..ded9231 --- /dev/null +++ b/boot_loader/bl_startup_sourcerygxx.S @@ -0,0 +1,630 @@ +//*****************************************************************************
+//
+// bl_startup_sourcerygxx.S - Startup code for Sourcery G++.
+//
+// Copyright (c) 2007-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 the assember definitions used to make this code compiler
+// independent.
+//
+//*****************************************************************************
+#include "inc/hw_nvic.h"
+#include "inc/hw_sysctl.h"
+#include "bl_config.h"
+
+//*****************************************************************************
+//
+// Put the assembler into the correct configuration.
+//
+//*****************************************************************************
+ .syntax unified
+ .thumb
+
+//*****************************************************************************
+//
+// The stack gets placed into the zero-init section.
+//
+//*****************************************************************************
+ .bss
+
+//*****************************************************************************
+//
+// Allocate storage for the stack.
+//
+//*****************************************************************************
+g_pulStack:
+ .space STACK_SIZE * 4
+
+//*****************************************************************************
+//
+// This portion of the file goes into the text section.
+//
+//*****************************************************************************
+ .section .isr_vector
+
+//*****************************************************************************
+//
+// The minimal vector table for a Cortex-M3 processor.
+//
+//*****************************************************************************
+Vectors:
+ .word g_pulStack + (STACK_SIZE * 4) // Offset 00: Initial stack pointer
+ .word ResetISR - 0x20000000 // Offset 04: Reset handler
+ .word NmiSR - 0x20000000 // Offset 08: NMI handler
+ .word FaultISR - 0x20000000 // Offset 0C: Hard fault handler
+ .word IntDefaultHandler // Offset 10: MPU fault handler
+ .word IntDefaultHandler // Offset 14: Bus fault handler
+ .word IntDefaultHandler // Offset 18: Usage fault handler
+ .word 0 // Offset 1C: Reserved
+ .word 0 // Offset 20: Reserved
+ .word 0 // Offset 24: Reserved
+ .word 0 // Offset 28: Reserved
+ .word UpdateHandler - 0x20000000 // Offset 2C: SVCall handler
+ .word IntDefaultHandler // Offset 30: Debug monitor handler
+ .word 0 // Offset 34: Reserved
+ .word IntDefaultHandler // Offset 38: PendSV handler
+#if defined(ENET_ENABLE_UPDATE)
+ .extern SysTickIntHandler
+ .word SysTickIntHandler // Offset 3C: SysTick handler
+#else
+ .word IntDefaultHandler // Offset 3C: SysTick handler
+#endif
+#if defined(UART_ENABLE_UPDATE) && defined(UART_AUTOBAUD)
+ .extern GPIOIntHandler
+ .word GPIOIntHandler // Offset 40: GPIO port A handler
+#else
+ .word IntDefaultHandler // Offset 40: GPIO port A handler
+#endif
+#if (defined(USB_ENABLE_UPDATE) || \
+ (APP_START_ADDRESS != VTABLE_START_ADDRESS))
+ .word IntDefaultHandler // Offset 44: GPIO Port B
+ .word IntDefaultHandler // Offset 48: GPIO Port C
+ .word IntDefaultHandler // Offset 4C: GPIO Port D
+ .word IntDefaultHandler // Offset 50: GPIO Port E
+ .word IntDefaultHandler // Offset 54: UART0 Rx and Tx
+ .word IntDefaultHandler // Offset 58: UART1 Rx and Tx
+ .word IntDefaultHandler // Offset 5C: SSI0 Rx and Tx
+ .word IntDefaultHandler // Offset 60: I2C0 Master and Slave
+ .word IntDefaultHandler // Offset 64: PWM Fault
+ .word IntDefaultHandler // Offset 68: PWM Generator 0
+ .word IntDefaultHandler // Offset 6C: PWM Generator 1
+ .word IntDefaultHandler // Offset 70: PWM Generator 2
+ .word IntDefaultHandler // Offset 74: Quadrature Encoder 0
+ .word IntDefaultHandler // Offset 78: ADC Sequence 0
+ .word IntDefaultHandler // Offset 7C: ADC Sequence 1
+ .word IntDefaultHandler // Offset 80: ADC Sequence 2
+ .word IntDefaultHandler // Offset 84: ADC Sequence 3
+ .word IntDefaultHandler // Offset 88: Watchdog timer
+ .word IntDefaultHandler // Offset 8C: Timer 0 subtimer A
+ .word IntDefaultHandler // Offset 90: Timer 0 subtimer B
+ .word IntDefaultHandler // Offset 94: Timer 1 subtimer A
+ .word IntDefaultHandler // Offset 98: Timer 1 subtimer B
+ .word IntDefaultHandler // Offset 9C: Timer 2 subtimer A
+ .word IntDefaultHandler // Offset A0: Timer 2 subtimer B
+ .word IntDefaultHandler // Offset A4: Analog Comparator 0
+ .word IntDefaultHandler // Offset A8: Analog Comparator 1
+ .word IntDefaultHandler // Offset AC: Analog Comparator 2
+ .word IntDefaultHandler // Offset B0: System Control
+ .word IntDefaultHandler // Offset B4: FLASH Control
+#endif
+#if (defined(USB_ENABLE_UPDATE) || (APP_START_ADDRESS != VTABLE_START_ADDRESS))
+ .word IntDefaultHandler // Offset B8: GPIO Port F
+ .word IntDefaultHandler // Offset BC: GPIO Port G
+ .word IntDefaultHandler // Offset C0: GPIO Port H
+ .word IntDefaultHandler // Offset C4: UART2 Rx and Tx
+ .word IntDefaultHandler // Offset C8: SSI1 Rx and Tx
+ .word IntDefaultHandler // Offset CC: Timer 3 subtimer A
+ .word IntDefaultHandler // Offset D0: Timer 3 subtimer B
+ .word IntDefaultHandler // Offset D4: I2C1 Master and Slave
+ .word IntDefaultHandler // Offset D8: Quadrature Encoder 1
+ .word IntDefaultHandler // Offset DC: CAN0
+ .word IntDefaultHandler // Offset E0: CAN1
+ .word IntDefaultHandler // Offset E4: CAN2
+ .word IntDefaultHandler // Offset E8: Ethernet
+ .word IntDefaultHandler // Offset EC: Hibernation module
+#if defined(USB_ENABLE_UPDATE)
+ .extern USB0DeviceIntHandler
+ .word USB0DeviceIntHandler // Offset F0: USB 0 Controller
+#else
+ .word IntDefaultHandler // Offset F0: USB 0 Controller
+#endif
+#endif
+
+//*****************************************************************************
+//
+// This portion of the file goes into the text section.
+//
+//*****************************************************************************
+ .text
+
+//*****************************************************************************
+//
+// 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.
+//
+//*****************************************************************************
+ .thumb_func
+ProcessorInit:
+ //
+ // Copy the code image from flash to SRAM.
+ //
+ movs r0, #0x0000
+ movs r1, #0x0000
+ movt r1, #0x2000
+ .extern _bss
+ ldr r2, =_bss
+copy_loop:
+ ldr r3, [r0], #4
+ str r3, [r1], #4
+ cmp r1, r2
+ blt copy_loop
+
+ //
+ // Zero fill the .bss section.
+ //
+ movs r0, #0x0000
+ .extern _ebss
+ ldr r2, =_ebss
+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]
+
+ //
+ // Set the return address to the code just copied into SRAM.
+ //
+ orr lr, lr, #0x20000000
+
+ //
+ // Return to the caller.
+ //
+ bx lr
+
+//*****************************************************************************
+//
+// The reset handler, which gets called when the processor starts.
+//
+//*****************************************************************************
+ .globl ResetISR
+ .thumb_func
+ResetISR:
+ //
+ // 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, r1, #0x00F00000
+ str r1, [r0]
+
+ //
+ // Initialize the processor.
+ //
+ bl ProcessorInit
+
+ //
+ // Call the user-supplied low level hardware initialization function
+ // if provided.
+ //
+#ifdef BL_HW_INIT_FN_HOOK
+ .extern BL_HW_INIT_FN_HOOK
+ bl BL_HW_INIT_FN_HOOK
+#endif
+
+ //
+ // See if an update should be performed.
+ //
+ .extern CheckForceUpdate
+ bl CheckForceUpdate
+ cbz r0, CallApplication
+
+ //
+ // Configure the microcontroller.
+ //
+ .thumb_func
+EnterBootLoader:
+#ifdef ENET_ENABLE_UPDATE
+ .extern ConfigureEnet
+ bl ConfigureEnet
+#elif defined(CAN_ENABLE_UPDATE)
+ .extern ConfigureCAN
+ bl ConfigureCAN
+#elif defined(USB_ENABLE_UPDATE)
+ .extern ConfigureUSB
+ bl ConfigureUSB
+#else
+ .extern ConfigureDevice
+ bl ConfigureDevice
+#endif
+
+ //
+ // Call the user-supplied initialization function if provided.
+ //
+#ifdef BL_INIT_FN_HOOK
+ .extern BL_INIT_FN_HOOK
+ bl BL_INIT_FN_HOOK
+#endif
+
+ //
+ // Branch to the update handler.
+ //
+#ifdef ENET_ENABLE_UPDATE
+ .extern UpdateBOOTP
+ b UpdateBOOTP
+#elif defined(CAN_ENABLE_UPDATE)
+ .extern UpdaterCAN
+ b UpdaterCAN
+#elif defined(USB_ENABLE_UPDATE)
+ .extern UpdaterUSB
+ b UpdaterUSB
+#else
+ .extern Updater
+ b Updater
+#endif
+
+ //
+ // This is a second symbol to allow starting the application from the boot
+ // loader the linker may not like the perceived jump.
+ //
+ .globl StartApplication
+ .thumb_func
+StartApplication:
+ //
+ // Call the application via the reset handler in its vector table. Load
+ // the address of the application vector table.
+ //
+ .thumb_func
+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 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]
+
+ //
+ // 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.
+//
+//*****************************************************************************
+ .thumb_func
+UpdateHandler:
+ //
+ // Initialize the processor.
+ //
+ bl ProcessorInit
+
+ //
+ // Load the stack pointer from the vector table.
+ //
+ movs r0, #0x0000
+ ldr sp, [r0]
+
+ //
+ // Call the user-supplied low level hardware initialization function
+ // if provided.
+ //
+#ifdef BL_HW_INIT_FN_HOOK
+ bl BL_HW_INIT_FN_HOOK
+#endif
+
+ //
+ // Call the user-supplied re-initialization function if provided.
+ //
+#ifdef BL_REINIT_FN_HOOK
+ .extern BL_REINIT_FN_HOOK
+ bl BL_REINIT_FN_HOOK
+#endif
+
+ //
+ // Branch to the update handler.
+ //
+#ifdef ENET_ENABLE_UPDATE
+ b UpdateBOOTP
+#elif defined(CAN_ENABLE_UPDATE)
+ .extern AppUpdaterCAN
+ b AppUpdaterCAN
+#elif defined(USB_ENABLE_UPDATE)
+ .extern AppUpdaterUSB
+ b AppUpdaterUSB
+#else
+ b Updater
+#endif
+
+//*****************************************************************************
+//
+// The NMI handler.
+//
+//*****************************************************************************
+ .thumb_func
+NmiSR:
+#ifdef ENABLE_MOSCFAIL_HANDLER
+ //
+ // Grab the fault frame from the stack (the stack will be cleared by the
+ // processor initialization that follows).
+ //
+ ldm sp, {r4-r11}
+ mov r12, lr
+
+ //
+ // Initialize the processor.
+ //
+ bl ProcessorInit
+
+ //
+ // 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.
+ //
+#ifdef 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.
+ //
+ .thumb_func
+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
+#else
+ //
+ // Loop forever since there is nothing that we can do about a NMI.
+ //
+ b .
+#endif
+
+//*****************************************************************************
+//
+// The hard fault handler.
+//
+//*****************************************************************************
+ .thumb_func
+FaultISR:
+ //
+ // Loop forever since there is nothing that we can do about a hard fault.
+ //
+ b .
+
+//*****************************************************************************
+//
+// The default interrupt handler.
+//
+//*****************************************************************************
+ .thumb_func
+IntDefaultHandler:
+ //
+ // Loop forever since there is nothing that we can do about an unexpected
+ // interrupt.
+ //
+ b .
+
+//*****************************************************************************
+//
+// Provides a small delay. The loop below takes 3 cycles/loop.
+//
+//*****************************************************************************
+ .globl Delay
+ .thumb_func
+Delay:
+ subs r0, #1
+ bne Delay
+ bx lr
+
+//*****************************************************************************
+//
+// This is the end of the file.
+//
+//*****************************************************************************
+ .end
diff --git a/boot_loader/bl_uart.c b/boot_loader/bl_uart.c new file mode 100644 index 0000000..71df5c3 --- /dev/null +++ b/boot_loader/bl_uart.c @@ -0,0 +1,156 @@ +//*****************************************************************************
+//
+// bl_uart.c - Functions to transfer data via the UART port.
+//
+// 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 "inc/hw_gpio.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_sysctl.h"
+#include "inc/hw_types.h"
+#include "inc/hw_uart.h"
+#include "bl_config.h"
+#include "boot_loader/bl_uart.h"
+
+//*****************************************************************************
+//
+//! \addtogroup bl_uart_api
+//! @{
+//
+//*****************************************************************************
+#if defined(UART_ENABLE_UPDATE) || defined(DOXYGEN)
+
+//*****************************************************************************
+//
+//! Sends data over the UART port.
+//!
+//! \param pui8Data is the buffer containing the data to write out to the UART
+//! port.
+//! \param ui32Size is the number of bytes provided in \e pui8Data buffer that
+//! will be written out to the UART port.
+//!
+//! This function sends \e ui32Size bytes of data from the buffer pointed to by
+//! \e pui8Data via the UART port.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+UARTSend(const uint8_t *pui8Data, uint32_t ui32Size)
+{
+ //
+ // Transmit the number of bytes requested on the UART port.
+ //
+ while(ui32Size--)
+ {
+ //
+ // Make sure that the transmit FIFO is not full.
+ //
+ while((HWREG(UART0_BASE + UART_O_FR) & UART_FR_TXFF))
+ {
+ }
+
+ //
+ // Send out the next byte.
+ //
+ HWREG(UART0_BASE + UART_O_DR) = *pui8Data++;
+ }
+
+ //
+ // Wait until the UART is done transmitting.
+ //
+ UARTFlush();
+}
+
+//*****************************************************************************
+//
+//! Waits until all data has been transmitted by the UART port.
+//!
+//! This function waits until all data written to the UART port has been
+//! transmitted.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+UARTFlush(void)
+{
+ //
+ // Wait for the UART FIFO to empty and then wait for the shifter to get the
+ // bytes out the port.
+ //
+ while(!(HWREG(UART0_BASE + UART_O_FR) & UART_FR_TXFE))
+ {
+ }
+
+ //
+ // Wait for the FIFO to not be busy so that the shifter completes.
+ //
+ while((HWREG(UART0_BASE + UART_O_FR) & UART_FR_BUSY))
+ {
+ }
+}
+
+//*****************************************************************************
+//
+//! Receives data over the UART port.
+//!
+//! \param pui8Data is the buffer to read data into from the UART port.
+//! \param ui32Size is the number of bytes provided in the \e pui8Data buffer
+//! that should be written with data from the UART port.
+//!
+//! This function reads back \e ui32Size bytes of data from the UART port, into
+//! the buffer that is pointed to by \e pui8Data. This function will not
+//! return until \e ui32Size number of bytes have been received.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+UARTReceive(uint8_t *pui8Data, uint32_t ui32Size)
+{
+ //
+ // Send out the number of bytes requested.
+ //
+ while(ui32Size--)
+ {
+ //
+ // Wait for the FIFO to not be empty.
+ //
+ while((HWREG(UART0_BASE + UART_O_FR) & UART_FR_RXFE))
+ {
+ }
+
+ //
+ // Receive a byte from the UART.
+ //
+ *pui8Data++ = HWREG(UART0_BASE + UART_O_DR);
+ }
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+#endif
diff --git a/boot_loader/bl_uart.h b/boot_loader/bl_uart.h new file mode 100644 index 0000000..8148995 --- /dev/null +++ b/boot_loader/bl_uart.h @@ -0,0 +1,81 @@ +//*****************************************************************************
+//
+// bl_uart.h - Definitions for the UART transport functions.
+//
+// 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.
+//
+//*****************************************************************************
+
+#ifndef __BL_UART_H__
+#define __BL_UART_H__
+
+//*****************************************************************************
+//
+// This macro is used to generate a constant to represent the UART baud rate to
+// processor clock rate ratio. This prevents the need for run-time calculation
+// of the ratio of baud rate to processor clock rate ratio.
+//
+//*****************************************************************************
+#define UART_BAUD_RATIO(ui32Baud) \
+ ((((CRYSTAL_FREQ * 8) / ui32Baud) + 1) / 2)
+
+//*****************************************************************************
+//
+// This defines the UART receive pin that is being used by the boot loader.
+//
+//*****************************************************************************
+#define UART_RX (1 << 0)
+
+//*****************************************************************************
+//
+// This defines the UART transmit pin that is being used by the boot loader.
+//
+//*****************************************************************************
+#define UART_TX (1 << 1)
+
+//*****************************************************************************
+//
+// This defines the combination of pins used to implement the UART port used by
+// the boot loader.
+//
+//*****************************************************************************
+#define UART_PINS (UART_RX | UART_TX)
+
+//*****************************************************************************
+//
+// UART Transport APIs
+//
+//*****************************************************************************
+extern void UARTSend(const uint8_t *pui8Data, uint32_t ui32Size);
+extern void UARTReceive(uint8_t *pui8Data, uint32_t ui32Size);
+extern void UARTFlush(void);
+extern int UARTAutoBaud(uint32_t *pui32Ratio);
+
+//*****************************************************************************
+//
+// Define the transport functions if the UART is being used.
+//
+//*****************************************************************************
+#ifdef UART_ENABLE_UPDATE
+#define SendData UARTSend
+#define FlushData UARTFlush
+#define ReceiveData UARTReceive
+#endif
+
+#endif // __BL_UART_H__
diff --git a/boot_loader/bl_usb.c b/boot_loader/bl_usb.c new file mode 100644 index 0000000..00ccd7a --- /dev/null +++ b/boot_loader/bl_usb.c @@ -0,0 +1,2166 @@ +//*****************************************************************************
+//
+// bl_usb.c - Functions to transfer data via the USB port.
+//
+// Copyright (c) 2009-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 <stdbool.h>
+#include <stdint.h>
+#include "inc/hw_gpio.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_flash.h"
+#include "inc/hw_sysctl.h"
+#include "inc/hw_types.h"
+#include "inc/hw_nvic.h"
+#include "inc/hw_usb.h"
+#include "bl_config.h"
+#include "boot_loader/bl_crystal.h"
+#include "boot_loader/bl_flash.h"
+#include "boot_loader/bl_hooks.h"
+#include "boot_loader/bl_usbfuncs.h"
+#include "boot_loader/usbdfu.h"
+
+//*****************************************************************************
+//
+// DFU Notes:
+//
+// 1. This implementation is manifestation-tolerant and doesn't time out
+// waiting for a reset after a download completes. As a result, the detach
+// timeout in the DFU functional descriptor is set to the maximum possible
+// value representing a timeout of 65.536 seconds.
+//
+// 2. This implementation does not support the BUSY state. By skipping this
+// and remaining in DNLOAD_SYNC when we are waiting for a programming or
+// erase operation to complete, we save the overhead of having to support a
+// timeout mechanism. Host-side implementations don't seem to rely upon
+// the busy state so this does not appear to be a problem.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! \addtogroup bl_usb_api
+//! @{
+//
+//*****************************************************************************
+#if defined(USB_ENABLE_UPDATE) || defined(DOXYGEN)
+
+//*****************************************************************************
+//
+// Make sure that the crystal frequency is defined.
+//
+//*****************************************************************************
+#if !defined(CRYSTAL_FREQ)
+#error ERROR: CRYSTAL_FREQ must be defined for USB update!
+#endif
+
+//*****************************************************************************
+//
+// Make sure that the crystal frequency is one of the ones that support USB
+// operation.
+//
+//*****************************************************************************
+#if CRYSTAL_FREQ != 4000000 && \
+ CRYSTAL_FREQ != 5000000 && \
+ CRYSTAL_FREQ != 6000000 && \
+ CRYSTAL_FREQ != 8000000 && \
+ CRYSTAL_FREQ != 10000000 && \
+ CRYSTAL_FREQ != 12000000 && \
+ CRYSTAL_FREQ != 16000000
+#error ERROR: Invalid CRYSTAL_FREQ specified for USB update!
+#endif
+
+//*****************************************************************************
+//
+// The DFU device information structure was developed assuming flash block
+// sizes in the 1KB to 32KB range but large external flash devices may have
+// 64KB or larger blocks. If the configuration options indicate a target
+// device with large pages, we fake the size at 32KB to keep the client happy.
+// The other option would be to redefine this field as an uint32_t but that
+// would break existing applications using the interface.
+//
+// For normal operation, this is unlikely to cause a problem since we will not
+// allow a flash operation to start anywhere other than at APP_START_ADDRESS
+// (which must fall on a real flash page boundary) or the start of the
+// reserved
+//
+//*****************************************************************************
+#if (FLASH_PAGE_SIZE > 0x10000)
+#define DFU_REPORTED_PAGE_SIZE 0x8000
+#else
+#define DFU_REPORTED_PAGE_SIZE FLASH_PAGE_SIZE
+#endif
+
+//*****************************************************************************
+//
+// This holds the total size of the firmware image being downloaded (which is
+// needed if we have a progress reporting hook function provided).
+//
+//*****************************************************************************
+#ifdef BL_PROGRESS_FN_HOOK
+uint32_t g_ui32ImageSize;
+#endif
+
+//*****************************************************************************
+//
+// The structure used to define a block of memory.
+//
+//*****************************************************************************
+typedef struct
+{
+ uint8_t *pui8Start;
+ uint32_t ui32Length;
+}
+tMemoryBlock;
+
+//*****************************************************************************
+//
+// The block of memory that is to be sent back in response to the next upload
+// request.
+//
+//*****************************************************************************
+tMemoryBlock g_sNextUpload;
+
+//*****************************************************************************
+//
+// The block of memory into which the next programming operation will write.
+//
+//*****************************************************************************
+volatile tMemoryBlock g_sNextDownload;
+
+//*****************************************************************************
+//
+// The block of flash to be erased.
+//
+//*****************************************************************************
+volatile tMemoryBlock g_sErase;
+
+//*****************************************************************************
+//
+// Information on the device we are running on. This will be returned to the
+// host after a download request containing command DFU_CMD_INFO.
+//
+//*****************************************************************************
+tDFUDeviceInfo g_sDFUDeviceInfo;
+
+//*****************************************************************************
+//
+// This variable keeps track of the last software-specific command received
+// from the host via a download request.
+//
+//*****************************************************************************
+uint8_t g_ui8LastCommand;
+
+//*****************************************************************************
+//
+// The current status of the DFU device as reported to the host in response to
+// USBD_DFU_REQUEST_GETSTATUS.
+//
+//*****************************************************************************
+tDFUGetStatusResponse g_sDFUStatus =
+{
+ 0, { 5, 0, 0 }, (uint8_t)STATE_IDLE, 0
+};
+
+//*****************************************************************************
+//
+// The structure sent in response to a valid USBD_DFU_REQUEST_TIVA.
+//
+//*****************************************************************************
+tDFUQueryTIVAProtocol g_sDFUProtocol =
+{
+ DFU_PROTOCOL_USBLIB_MARKER,
+ DFU_PROTOCOL_USBLIB_VERSION_1
+};
+
+//*****************************************************************************
+//
+// The current state of the device.
+//
+//*****************************************************************************
+volatile tDFUState g_eDFUState = STATE_IDLE;
+
+//*****************************************************************************
+//
+// The current status of the device.
+//
+//*****************************************************************************
+volatile tDFUStatus g_eDFUStatus = STATUS_OK;
+
+//*****************************************************************************
+//
+// The buffer used to hold download data from the host prior to writing it to
+// flash or image data in the process of being uploaded to the host.
+//
+//*****************************************************************************
+uint8_t g_pui8DFUBuffer[DFU_TRANSFER_SIZE];
+
+//*****************************************************************************
+//
+// The start of the image data within g_pui8DFUBuffer.
+//
+//*****************************************************************************
+uint8_t *g_pui8DFUWrite;
+
+//*****************************************************************************
+//
+// The number of bytes of valid data in the DFU buffer.
+//
+//*****************************************************************************
+volatile uint16_t g_ui16DFUBufferUsed;
+
+//*****************************************************************************
+//
+// Flags used to indicate that the main thread is being asked to do something.
+//
+//*****************************************************************************
+volatile uint32_t g_ui32CommandFlags;
+#define CMD_FLAG_ERASE 0
+#define CMD_FLAG_WRITE 1
+#define CMD_FLAG_RESET 2
+
+//*****************************************************************************
+//
+// This global determines whether or not we add a DFU header to any uploaded
+// image data. If true, the binary image is sent without the header. If false
+// the header is included. This is a DFU requirement since uploaded images
+// must be able to be downloaded again and hence must have the header in place
+// so that the destination address is available.
+//
+//*****************************************************************************
+bool g_bUploadBinary = false;
+
+//*****************************************************************************
+//
+// If the upload format includes the header, we need to be able to suppress
+// this when replying to TIVA-specific commands such as CMD_DFU_INFO. This
+// global determines whether we need to suppress the header that would
+// otherwise be send in response to the first USBD_DFU_REQUEST_UPLOAD received
+// while in STATE_IDLE.
+//
+//*****************************************************************************
+bool g_bSuppressUploadHeader = false;
+
+//*****************************************************************************
+//
+// A flag we use to indicate when the device has been enumerated.
+//
+//*****************************************************************************
+bool g_bAddressSet = false;
+
+//*****************************************************************************
+//
+// The languages supported by this device.
+//
+//*****************************************************************************
+const uint8_t g_pui8LangDescriptor[] =
+{
+ 4,
+ USB_DTYPE_STRING,
+ USBShort(USB_LANG_EN_US)
+};
+
+//*****************************************************************************
+//
+// The jump table used to implement request handling in the DFU state machine.
+//
+//*****************************************************************************
+typedef void (* tHandleRequests)(tUSBRequest *psUSBRequest);
+
+extern void HandleRequestIdle(tUSBRequest *psUSBRequest);
+extern void HandleRequestDnloadSync(tUSBRequest *psUSBRequest);
+extern void HandleRequestDnloadIdle(tUSBRequest *psUSBRequest);
+extern void HandleRequestManifestSync(tUSBRequest *psUSBRequest);
+extern void HandleRequestUploadIdle(tUSBRequest *psUSBRequest);
+extern void HandleRequestError(tUSBRequest *psUSBRequest);
+
+tHandleRequests g_pfnRequestHandlers[] =
+{
+ 0, // STATE_APP_IDLE
+ 0, // STATE_APP_DETACH
+ HandleRequestIdle, // STATE_IDLE
+ HandleRequestDnloadSync, // STATE_DNLOAD_SYNC
+ HandleRequestDnloadSync, // STATE_DNBUSY
+ HandleRequestDnloadIdle, // STATE_DNLOAD_IDLE
+ HandleRequestManifestSync, // STATE_MANIFEST_SYNC
+ 0, // STATE_MANIFEST
+ 0, // STATE_MANIFEST_WAIT_RESET
+ HandleRequestUploadIdle, // STATE_UPLOAD_IDLE
+ HandleRequestError // STATE_ERROR
+};
+
+//*****************************************************************************
+//
+// The manufacturer string.
+//
+//*****************************************************************************
+const uint8_t g_pui8ManufacturerString[] =
+{
+ (17 + 1) * 2,
+ USB_DTYPE_STRING,
+ 'T', 0, 'e', 0, 'x', 0, 'a', 0, 's', 0, ' ', 0, 'I', 0, 'n', 0,
+ 's', 0, 't', 0, 'r', 0, 'u', 0, 'm', 0, 'e', 0, 'n', 0, 't', 0,
+ 's', 0
+};
+
+//*****************************************************************************
+//
+// The product string.
+//
+//*****************************************************************************
+const uint8_t g_pui8ProductString[] =
+{
+ (23 + 1) * 2,
+ USB_DTYPE_STRING,
+ 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, ' ', 0, 'F', 0, 'i', 0,
+ 'r', 0, 'm', 0, 'w', 0, 'a', 0, 'r', 0, 'e', 0, ' ', 0, 'U', 0, 'p', 0,
+ 'g', 0, 'r', 0, 'a', 0, 'd', 0, 'e', 0
+};
+
+//*****************************************************************************
+//
+// The serial number string.
+//
+//*****************************************************************************
+const uint8_t g_pui8SerialNumberString[] =
+{
+ (3 + 1) * 2,
+ USB_DTYPE_STRING,
+ '0', 0, '.', 0, '1', 0
+};
+
+//*****************************************************************************
+//
+// The descriptor string table.
+//
+//*****************************************************************************
+const uint8_t *const g_ppui8StringDescriptors[] =
+{
+ g_pui8LangDescriptor,
+ g_pui8ManufacturerString,
+ g_pui8ProductString,
+ g_pui8SerialNumberString
+};
+
+//*****************************************************************************
+//
+// DFU Device Descriptor.
+//
+//*****************************************************************************
+const uint8_t g_pui8DFUDeviceDescriptor[] =
+{
+ 18, // Size of this structure.
+ USB_DTYPE_DEVICE, // Type of this structure.
+ USBShort(0x110), // USB version 1.1 (if we say 2.0, hosts assume
+ // high-speed - see USB 2.0 spec 9.2.6.6)
+ USB_CLASS_VEND_SPECIFIC, // USB Device Class
+ 0, // USB Device Sub-class
+ 0, // USB Device protocol
+ 64, // Maximum packet size for default pipe.
+ USBShort(USB_VENDOR_ID), // Vendor ID (VID).
+ USBShort(USB_PRODUCT_ID), // Product ID (PID).
+ USBShort(USB_DEVICE_ID), // Device Release Number BCD.
+ 1, // Manufacturer string identifier.
+ 2, // Product string identifier.
+ 3, // Product serial number.
+ 1 // Number of configurations.
+};
+
+//*****************************************************************************
+//
+// DFU device configuration descriptor.
+//
+//*****************************************************************************
+const uint8_t g_pui8DFUConfigDescriptor[] =
+{
+ //
+ // Configuration descriptor header.
+ //
+ 9, // Size of the configuration descriptor.
+ USB_DTYPE_CONFIGURATION, // Type of this descriptor.
+ USBShort(27), // The total size of this full structure.
+ 1, // The number of interfaces in this
+ // configuration.
+ 1, // The unique value for this configuration.
+ 0, // The string identifier that describes this
+ // configuration.
+#if USB_BUS_POWERED
+ USB_CONF_ATTR_BUS_PWR, // Bus Powered
+#else
+ USB_CONF_ATTR_SELF_PWR, // Self Powered
+#endif
+ (USB_MAX_POWER / 2), // The maximum power in 2mA increments.
+
+ //
+ // Interface descriptor.
+ //
+ 9, // Length of this descriptor.
+ USB_DTYPE_INTERFACE, // This is an interface descriptor.
+ 0, // Interface number .
+ 0, // Alternate setting number.
+ 0, // Number of endpoints (only endpoint 0 used)
+ USB_CLASS_APP_SPECIFIC, // Application specific interface class
+ USB_DFU_SUBCLASS, // Device Firmware Upgrade subclass
+ USB_DFU_PROTOCOL, // DFU protocol
+ 0, // No interface description string present.
+
+ //
+ // Device Firmware Upgrade functional descriptor.
+ //
+ 9, // Length of this descriptor.
+ 0x21, // DFU Functional descriptor type
+ (DFU_ATTR_CAN_DOWNLOAD | // DFU attributes.
+ DFU_ATTR_CAN_UPLOAD |
+ DFU_ATTR_MANIFEST_TOLERANT),
+ USBShort(0xFFFF), // Detach timeout (set to maximum).
+ USBShort(DFU_TRANSFER_SIZE),// Transfer size 1KB.
+ USBShort(0x0110) // DFU Version 1.1
+};
+
+//*****************************************************************************
+//
+// The USB device interrupt handler.
+//
+// This function is called to process USB interrupts when in device mode.
+// This handler will branch the interrupt off to the appropriate application or
+// stack handlers depending on the current status of the USB controller.
+//
+// \return None.
+//
+//*****************************************************************************
+void
+USB0DeviceIntHandler(void)
+{
+ uint32_t ui32TxStatus, ui32GenStatus;
+
+ //
+ // Get the current full USB interrupt status.
+ //
+ ui32TxStatus = HWREGH(USB0_BASE + USB_O_TXIS);
+ ui32GenStatus = HWREGB(USB0_BASE + USB_O_IS);
+
+ //
+ // Received a reset from the host.
+ //
+ if(ui32GenStatus & USB_IS_RESET)
+ {
+ USBDeviceEnumResetHandler();
+ }
+
+ //
+ // USB device was disconnected.
+ //
+ if(ui32GenStatus & USB_IS_DISCON)
+ {
+ HandleDisconnect();
+ }
+
+ //
+ // Handle end point 0 interrupts.
+ //
+ if(ui32TxStatus & USB_TXIE_EP0)
+ {
+ USBDeviceEnumHandler();
+ }
+}
+
+//*****************************************************************************
+//
+// A prototype for the function (in the startup code) for a predictable length
+// delay.
+//
+//*****************************************************************************
+extern void Delay(uint32_t ui32Count);
+
+//*****************************************************************************
+//
+// Send the current state or status structure back to the host. This function
+// also acknowledges the request which causes us to send back this data.
+//
+//*****************************************************************************
+void
+SendDFUStatus(void)
+{
+ //
+ // Acknowledge the original request.
+ //
+ USBDevEndpoint0DataAck(false);
+
+ //
+ // Copy the current state into the status structure we will return.
+ //
+ g_sDFUStatus.bState = (uint8_t)g_eDFUState;
+ g_sDFUStatus.bStatus = (uint8_t)g_eDFUStatus;
+
+ //
+ // Send the status structure back to the host.
+ //
+ USBBLSendDataEP0((uint8_t *)&g_sDFUStatus, sizeof(tDFUGetStatusResponse));
+}
+
+//*****************************************************************************
+//
+// Send the next block of upload data back to the host assuming data remains
+// to be sent.
+//
+// \param ui16Length is the requested amount of data.
+// \param bAppendHeader is \b true to append a tDFUDownloadProgHeader at the
+// start of the uploaded data or \b false if no header is required.
+//
+// Returns \b true if a full packet containing DFU_TRANSFER_SIZE bytes
+// was sent and data remains to be sent following this transaction, or \b
+// false if no more data remains to be sent following this transaction.
+//
+//*****************************************************************************
+bool
+SendUploadData(uint16_t ui16Length, bool bAppendHeader)
+{
+ uint16_t ui16ToSend;
+ uint32_t ui32Available;
+
+ //
+ // Acknowledge the original request.
+ //
+ USBDevEndpoint0DataAck(false);
+
+ //
+ // How much data is available to be sent?
+ //
+ ui32Available = (g_sNextUpload.ui32Length +
+ (bAppendHeader ? sizeof(tDFUDownloadProgHeader) : 0));
+
+ //
+ // How much data can we send? This is the smallest of the maximum transfer
+ // size, the requested length or the available data.
+ //
+ ui16ToSend =
+ (ui16Length > DFU_TRANSFER_SIZE) ? DFU_TRANSFER_SIZE : ui16Length;
+ ui16ToSend =
+ ((uint32_t)ui16ToSend > ui32Available) ? ui32Available : ui16ToSend;
+
+ //
+ // If we have been asked to send a header, we need to copy some of the data
+ // into a buffer and send from there. If we don't do this, we run the risk
+ // of sending a long packet prematurely and ending the upload before it is
+ // complete.
+ //
+ if(bAppendHeader)
+ {
+ tDFUDownloadProgHeader *psHdr;
+ uint8_t *pui8From;
+ uint8_t *pui8To;
+ uint32_t ui32Loop;
+
+ //
+ // We are appending a header so write the header information into a
+ // buffer then copy the first chunk of data from its original position
+ // into the same buffer.
+ //
+ psHdr = (tDFUDownloadProgHeader *)g_pui8DFUBuffer;
+
+ //
+ // Build the header.
+ //
+ psHdr->ui8Command = DFU_CMD_PROG;
+ psHdr->ui8Reserved = 0;
+ psHdr->ui16StartAddr = ((uint32_t)(g_sNextUpload.pui8Start) / 1024);
+ psHdr->ui32Length = g_sNextUpload.ui32Length;
+
+ //
+ // Copy the remainder of the first transfer's data from its original
+ // position.
+ //
+ pui8From = g_sNextUpload.pui8Start;
+ pui8To = (uint8_t *)(psHdr + 1);
+ for(ui32Loop = (ui16ToSend - sizeof(tDFUDownloadProgHeader)); ui32Loop;
+ ui32Loop--)
+ {
+ *pui8To++ = *pui8From++;
+ }
+
+ //
+ // Send the data.
+ //
+ USBBLSendDataEP0((uint8_t *)psHdr, ui16ToSend);
+
+ //
+ // Update our upload pointer and length.
+ //
+ g_sNextUpload.pui8Start += ui16ToSend - sizeof(tDFUDownloadProgHeader);
+ g_sNextUpload.ui32Length -=
+ ui16ToSend - sizeof(tDFUDownloadProgHeader);
+ }
+ else
+ {
+ //
+ // We are not sending a header so send the requested upload data back
+ // to the host directly from its original position.
+ //
+ USBBLSendDataEP0(g_sNextUpload.pui8Start, ui16ToSend);
+
+ //
+ // Update our upload pointer and length.
+ //
+ g_sNextUpload.pui8Start += ui16ToSend;
+ g_sNextUpload.ui32Length -= ui16ToSend;
+ }
+
+ //
+ // We return true if we sent a full packet (containing the maximum transfer
+ // size bytes) or false to indicate that a long packet was sent or no more
+ // data remains.
+ //
+ return(((ui16ToSend == DFU_TRANSFER_SIZE) && g_sNextUpload.ui32Length) ?
+ true : false);
+}
+
+//*****************************************************************************
+//
+// Send the current state back to the host.
+//
+//*****************************************************************************
+void
+SendDFUState(void)
+{
+ //
+ // Acknowledge the original request.
+ //
+ USBDevEndpoint0DataAck(false);
+
+ //
+ // Update the status structure with the current state.
+ //
+ g_sDFUStatus.bState = (uint8_t)g_eDFUState;
+
+ //
+ // Send the state from the status structure back to the host.
+ //
+ USBBLSendDataEP0((uint8_t *)&g_sDFUStatus.bState, 1);
+}
+
+//*****************************************************************************
+//
+//! Handle USB requests sent to the DFU device.
+//!
+//! \param psUSBRequest is a pointer to the USB request that the device has
+//! been sent.
+//!
+//! This function is called to handle all non-standard requests received
+//! by the device. This will include all the DFU endpoint 0 commands along
+//! with the TIVA-specific request we use to query whether the device
+//! supports our flavor of the DFU binary format. Incoming DFU requests are
+//! processed by request handlers specific to the particular state of the DFU
+//! connection. This state machine implementation is chosen to keep the
+//! software as close as possible to the USB DFU class documentation.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+HandleRequests(tUSBRequest *psUSBRequest)
+{
+ //
+ // This request is used by the host to determine whether the connected
+ // device supports the TIVA protocol extensions to DFU (our
+ // DFU_CMD_xxxx command headers passed alongside DNLOAD requests). We
+ // check the parameters and, if they are as expected, we respond with
+ // a 4 byte structure providing a marker and the protocol version
+ // number.
+ //
+ if(psUSBRequest->bRequest == USBD_DFU_REQUEST_TIVA)
+ {
+ //
+ // Check that the request parameters are all as expected. We are
+ // using the wValue value merely as a way of making it less likely
+ // that we respond to another vendor's device-specific request.
+ //
+ if((psUSBRequest->wLength == sizeof(tDFUQueryTIVAProtocol)) &&
+ (psUSBRequest->wValue == REQUEST_TIVA_VALUE))
+ {
+ //
+ // Acknowledge the original request.
+ //
+ USBDevEndpoint0DataAck(false);
+
+ //
+ // Send the status structure back to the host.
+ //
+ USBBLSendDataEP0((uint8_t *)&g_sDFUProtocol,
+ sizeof(tDFUQueryTIVAProtocol));
+ }
+ else
+ {
+ //
+ // The request parameters were not as expected so we assume
+ // that this is not our request and stall the endpoint to
+ // indicate an error.
+ //
+ USBBLStallEP0();
+ }
+
+ return;
+ }
+
+ //
+ // Pass the request to the relevant handler depending upon our current
+ // state. If no handler is configured, we stall the endpoint since this
+ // implies that requests can't be handled in this state.
+ //
+ if(g_pfnRequestHandlers[g_eDFUState])
+ {
+ //
+ // Dispatch the request to the relevant handler depending upon the
+ // current state.
+ //
+ (g_pfnRequestHandlers[g_eDFUState])(psUSBRequest);
+ }
+ else
+ {
+ USBBLStallEP0();
+ }
+}
+
+//*****************************************************************************
+//
+// Handle all incoming DFU requests while in state STATE_IDLE.
+//
+//*****************************************************************************
+void
+HandleRequestIdle(tUSBRequest *psUSBRequest)
+{
+ switch(psUSBRequest->bRequest)
+ {
+ //
+ // This is a download request. We need to request the transaction
+ // payload unless this is a zero length request in which case we mark
+ // the error by stalling the endpoint.
+ //
+ case USBD_DFU_REQUEST_DNLOAD:
+ {
+ if(psUSBRequest->wLength)
+ {
+ USBBLRequestDataEP0(g_pui8DFUBuffer, psUSBRequest->wLength);
+ }
+ else
+ {
+ USBBLStallEP0();
+ return;
+ }
+ break;
+ }
+
+ //
+ // This is an upload request. We send back a block of data
+ // corresponding to the current upload pointer as held in
+ // g_sNextUpload.
+ //
+ case USBD_DFU_REQUEST_UPLOAD:
+ {
+ //
+ // If we have any upload data to send, send it. Make sure we append
+ // a header if required.
+ //
+ if(SendUploadData(psUSBRequest->wLength,
+ g_bSuppressUploadHeader ? false :
+ !g_bUploadBinary))
+ {
+ //
+ // We sent a full (max packet size) frame to the host so
+ // transition to UPLOAD_IDLE state since we expect another
+ // upload request to continue the process.
+ //
+ g_eDFUState = STATE_UPLOAD_IDLE;
+ }
+
+ //
+ // Clear the flag we use to suppress sending the DFU header.
+ //
+ g_bSuppressUploadHeader = false;
+
+ return;
+ }
+
+ //
+ // Return the current device status structure.
+ //
+ case USBD_DFU_REQUEST_GETSTATUS:
+ {
+ SendDFUStatus();
+ return;
+ }
+
+ //
+ // Return the current device state.
+ //
+ case USBD_DFU_REQUEST_GETSTATE:
+ {
+ SendDFUState();
+ return;
+ }
+
+ //
+ // Ignore the ABORT request. This returns us to IDLE state but we're
+ // there already.
+ //
+ case USBD_DFU_REQUEST_ABORT:
+ {
+ break;
+ }
+
+ //
+ // All other requests are illegal in this state so signal the error
+ // by stalling the endpoint.
+ //
+ case USBD_DFU_REQUEST_CLRSTATUS:
+ case USBD_DFU_REQUEST_DETACH:
+ default:
+ {
+ USBBLStallEP0();
+ return;
+ }
+ }
+
+ //
+ // If we drop out of the switch, we need to ACK the received request.
+ //
+ USBDevEndpoint0DataAck(false);
+}
+
+//*****************************************************************************
+//
+// Handle all incoming DFU requests while in state STATE_DNLOAD_SYNC or
+// STATE_DNBUSY.
+//
+//*****************************************************************************
+void
+HandleRequestDnloadSync(tUSBRequest *psUSBRequest)
+{
+ //
+ // In this state, we have received a block of the download and are waiting
+ // for a USBD_DFU_REQUEST_GETSTATUS which will trigger a return
+ // to STATE_DNLOAD_IDLE assuming we have finished programming the block.
+ // If the last command we received was not DFU_CMD_PROG, we transition
+ // directly from this state back to STATE_IDLE once the last operation has
+ // completed since we need to be able to accept a new command.
+ //
+ switch(psUSBRequest->bRequest)
+ {
+ //
+ // The host is requesting the current device status. Return this and
+ // revert to STATE_IDLE.
+ //
+ case USBD_DFU_REQUEST_GETSTATUS:
+ {
+ //
+ // Are we finished processing whatever the last flash-operation
+ // was? Note that we don't support DNLOAD_BUSY state in this
+ // implementation, we merely continue to report DNLOAD_SYNC state
+ // until we are finished with the command.
+ //
+ if(!g_ui32CommandFlags)
+ {
+ //
+ // If we are in the middle of a programming operation,
+ // transition back to DNLOAD_IDLE state to wait for the
+ // next block. If not, go back to idle since we expect a
+ // new command.
+ //
+ g_eDFUState = ((g_ui8LastCommand == DFU_CMD_PROG) ?
+ STATE_DNLOAD_IDLE : STATE_IDLE);
+ }
+
+ //
+ // Send the latest status back to the host.
+ //
+ SendDFUStatus();
+
+ //
+ // Return here since we've already ACKed the request.
+ //
+ return;
+ }
+
+ //
+ // The host is requesting the current device state.
+ //
+ case USBD_DFU_REQUEST_GETSTATE:
+ {
+ //
+ // Are we currently in DNLOAD_SYNC state?
+ //
+ if(g_eDFUState == STATE_DNLOAD_SYNC)
+ {
+ //
+ // Yes - send back the state.
+ //
+ SendDFUState();
+ }
+ else
+ {
+ //
+ // In STATE_BUSY, we can't respond to any requests so stall
+ // the endpoint.
+ //
+ USBBLStallEP0();
+ }
+
+ //
+ // Return here since the incoming request has already been either
+ // ACKed or stalled by the processing above.
+ //
+ return;
+ }
+
+ //
+ // Any other request is ignored and causes us to stall the control
+ // endpoint and remain in STATE_ERROR.
+ //
+ default:
+ {
+ USBBLStallEP0();
+ return;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// Handle all incoming DFU requests while in state STATE_DNLOAD_IDLE.
+//
+//*****************************************************************************
+void
+HandleRequestDnloadIdle(tUSBRequest *psUSBRequest)
+{
+ switch(psUSBRequest->bRequest)
+ {
+ //
+ // This is a download request. We need to request the transaction
+ // payload unless this is a zero length request in which case we mark
+ // the error by stalling the endpoint.
+ //
+ case USBD_DFU_REQUEST_DNLOAD:
+ {
+ //
+ // Are we being passed data to program?
+ //
+ if(psUSBRequest->wLength)
+ {
+ //
+ // Yes - request the data.
+ //
+ USBBLRequestDataEP0(g_pui8DFUBuffer, psUSBRequest->wLength);
+ }
+ else
+ {
+ //
+ // No - this is the signal that a download operation is
+ // complete. Do we agree?
+ //
+ if(g_sNextDownload.ui32Length)
+ {
+ //
+ // We think there should still be some data to be received
+ // so mark this as an error.
+ //
+ g_eDFUState = STATE_ERROR;
+ g_eDFUStatus = STATUS_ERR_NOTDONE;
+ }
+ else
+ {
+ //
+ // We agree that the download has completed. Enter state
+ // STATE_MANIFEST_SYNC.
+ //
+ g_eDFUState = STATE_MANIFEST_SYNC;
+ }
+ }
+ break;
+ }
+
+ //
+ // Return the current device status structure.
+ //
+ case USBD_DFU_REQUEST_GETSTATUS:
+ {
+ SendDFUStatus();
+ return;
+ }
+
+ //
+ // Return the current device state.
+ //
+ case USBD_DFU_REQUEST_GETSTATE:
+ {
+ SendDFUState();
+ return;
+ }
+
+ //
+ // An ABORT request causes us to abort the current transfer and
+ // return the the idle state regardless of the state of the previous
+ // programming operation.
+ //
+ case USBD_DFU_REQUEST_ABORT:
+ {
+ //
+ // Default to downloading the main code image.
+ //
+ g_sNextDownload.pui8Start =
+ (uint8_t *)g_sDFUDeviceInfo.ui32AppStartAddr;
+ g_sNextDownload.ui32Length = (g_sDFUDeviceInfo.ui32FlashTop -
+ g_sDFUDeviceInfo.ui32AppStartAddr);
+ g_eDFUState = STATE_IDLE;
+ break;
+ }
+
+ //
+ // All other requests are illegal in this state so signal the error
+ // by stalling the endpoint.
+ //
+ case USBD_DFU_REQUEST_CLRSTATUS:
+ case USBD_DFU_REQUEST_DETACH:
+ case USBD_DFU_REQUEST_UPLOAD:
+ default:
+ {
+ USBBLStallEP0();
+ return;
+ }
+ }
+
+ //
+ // If we drop out of the switch, we need to ACK the received request.
+ //
+ USBDevEndpoint0DataAck(false);
+}
+
+//*****************************************************************************
+//
+// Handle all incoming DFU requests while in state STATE_MANIFEST_SYNC.
+//
+//*****************************************************************************
+void
+HandleRequestManifestSync(tUSBRequest *psUSBRequest)
+{
+ //
+ // In this state, we have received the last block of a download and are
+ // waiting for a USBD_DFU_REQUEST_GETSTATUS which will trigger a return
+ // to STATE_IDLE.
+ //
+ switch(psUSBRequest->bRequest)
+ {
+ //
+ // The host is requesting the current device status. Return this and
+ // revert to STATE_IDLE.
+ //
+ case USBD_DFU_REQUEST_GETSTATUS:
+ {
+ g_eDFUState = STATE_IDLE;
+ SendDFUStatus();
+ break;
+ }
+
+ //
+ // The host is requesting the current device state.
+ //
+ case USBD_DFU_REQUEST_GETSTATE:
+ {
+ SendDFUState();
+ break;
+ }
+
+ //
+ // Any other request is ignored and causes us to stall the control
+ // endpoint and remain in STATE_MANIFEST_SYNC.
+ //
+ default:
+ {
+ USBBLStallEP0();
+ break;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// Handle all incoming DFU requests while in state STATE_UPLOAD_IDLE.
+//
+//*****************************************************************************
+void
+HandleRequestUploadIdle(tUSBRequest *psUSBRequest)
+{
+ //
+ // In this state, we have already received the first upload request. What
+ // are we being asked to do now?
+ //
+ switch(psUSBRequest->bRequest)
+ {
+ //
+ // The host is requesting more upload data.
+ //
+ case USBD_DFU_REQUEST_UPLOAD:
+ {
+ //
+ // See if there is any more data to transfer and, if there is,
+ // send it back to the host.
+ //
+ if(!SendUploadData(psUSBRequest->wLength, false))
+ {
+ //
+ // We sent less than a full packet of data so the transfer is
+ // complete. Revert to idle state and ensure that we reset
+ // our upload pointer and size to the default flash region.
+ //
+ g_eDFUState = STATE_IDLE;
+ g_sNextUpload.pui8Start =
+ (uint8_t *)g_sDFUDeviceInfo.ui32AppStartAddr;
+ g_sNextUpload.ui32Length = (g_sDFUDeviceInfo.ui32FlashTop -
+ g_sDFUDeviceInfo.ui32AppStartAddr);
+ }
+ break;
+ }
+
+ //
+ // The host is requesting the current device status.
+ //
+ case USBD_DFU_REQUEST_GETSTATUS:
+ {
+ SendDFUStatus();
+ break;
+ }
+
+ //
+ // The host is requesting the current device state.
+ //
+ case USBD_DFU_REQUEST_GETSTATE:
+ {
+ SendDFUState();
+ break;
+ }
+
+ //
+ // The host is requesting that we abort the current upload.
+ //
+ case USBD_DFU_REQUEST_ABORT:
+ {
+ //
+ // Default to sending the main application image for the next
+ // upload.
+ //
+ g_sNextUpload.pui8Start =
+ (uint8_t *)g_sDFUDeviceInfo.ui32AppStartAddr;
+ g_sNextUpload.ui32Length = (g_sDFUDeviceInfo.ui32FlashTop -
+ g_sDFUDeviceInfo.ui32AppStartAddr);
+ g_eDFUState = STATE_IDLE;
+ break;
+ }
+
+ //
+ // Any other request is ignored and causes us to stall the control
+ // endpoint and remain in STATE_ERROR.
+ //
+ default:
+ {
+ USBBLStallEP0();
+ break;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// Handle all incoming DFU requests while in state STATE_ERROR.
+//
+//*****************************************************************************
+void
+HandleRequestError(tUSBRequest *psUSBRequest)
+{
+ //
+ // In this state, we respond to state and status requests and also to
+ // USBD_DFU_REQUEST_CLRSTATUS which clears the previous error condition.
+ //
+ switch(psUSBRequest->bRequest)
+ {
+ //
+ // The host is requesting the current device status.
+ //
+ case USBD_DFU_REQUEST_GETSTATUS:
+ {
+ SendDFUStatus();
+ break;
+ }
+
+ //
+ // The host is requesting the current device state.
+ //
+ case USBD_DFU_REQUEST_GETSTATE:
+ {
+ SendDFUState();
+ break;
+ }
+
+ //
+ // The host is asking us to clear our previous error condition and
+ // revert to idle state in preparation to receive new commands.
+ //
+ case USBD_DFU_REQUEST_CLRSTATUS:
+ {
+ g_eDFUState = STATE_IDLE;
+ g_eDFUStatus = STATUS_OK;
+ USBDevEndpoint0DataAck(false);
+ break;
+ }
+
+ //
+ // Any other request is ignored and causes us to stall the control
+ // endpoint and remain in STATE_ERROR.
+ //
+ default:
+ {
+ USBBLStallEP0();
+ break;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// Handle cases where the host sets a new USB configuration.
+//
+//*****************************************************************************
+void
+HandleConfigChange(uint32_t ui32Info)
+{
+ //
+ // Revert to idle state.
+ //
+ g_eDFUState = STATE_IDLE;
+ g_eDFUStatus = STATUS_OK;
+}
+
+//*****************************************************************************
+//
+// Setting the device address indicates that we are now connected to the host
+// and can expect some DFU communication so we use this opportunity to clean
+// out our state just in case we were not idle last time the host disconnected.
+//
+//*****************************************************************************
+void
+HandleSetAddress(void)
+{
+ g_eDFUState = STATE_IDLE;
+ g_eDFUStatus = STATUS_OK;
+ g_bAddressSet = true;
+
+ //
+ // Default the download address to the app start address and valid length
+ // to the whole of the programmable flash area.
+ //
+ g_sNextDownload.pui8Start =
+ (uint8_t *)g_sDFUDeviceInfo.ui32AppStartAddr;
+ g_sNextDownload.ui32Length = (g_sDFUDeviceInfo.ui32FlashTop -
+ g_sDFUDeviceInfo.ui32AppStartAddr);
+
+ //
+ // Default the upload address to the app start address and valid length
+ // to the whole of the programmable flash area.
+ //
+ g_sNextUpload.pui8Start =
+ (uint8_t *)g_sDFUDeviceInfo.ui32AppStartAddr;
+ g_sNextUpload.ui32Length = (g_sDFUDeviceInfo.ui32FlashTop -
+ g_sDFUDeviceInfo.ui32AppStartAddr);
+}
+
+//*****************************************************************************
+//
+// Check that a range of addresses passed is within the region of flash that
+// the boot loader is allowed to access.
+//
+// Returns true if the address range is accessible or false otherwise.
+//
+//*****************************************************************************
+bool
+FlashRangeCheck(uint32_t ui32Start, uint32_t ui32Length)
+{
+#ifdef ENABLE_BL_UPDATE
+ if((ui32Length <=
+ (g_sDFUDeviceInfo.ui32FlashTop - g_sDFUDeviceInfo.ui32AppStartAddr)) &&
+ ((ui32Start + ui32Length) <= g_sDFUDeviceInfo.ui32FlashTop))
+#else
+ if((ui32Start >= g_sDFUDeviceInfo.ui32AppStartAddr) &&
+ (ui32Length <=
+ (g_sDFUDeviceInfo.ui32FlashTop - g_sDFUDeviceInfo.ui32AppStartAddr)) &&
+ ((ui32Start + ui32Length) <= g_sDFUDeviceInfo.ui32FlashTop))
+#endif
+ {
+ //
+ // The block passed lies wholly within the flash address range of
+ // this device.
+ //
+ return(true);
+ }
+ else
+ {
+ //
+ // We were passed an address that is out of range so set the
+ // appropriate status code.
+ //
+ g_eDFUStatus = STATUS_ERR_ADDRESS;
+ return(false);
+ }
+}
+
+//*****************************************************************************
+//
+//! Process TIVA-specific commands passed via DFU download requests.
+//!
+//! \param psCmd is a pointer to the first byte of the \b DFU_DNLOAD payload
+//! that is expected to hold a command.
+//! \param ui32Size is the number of bytes of data pointed to by \e psCmd.
+//! This function is called when a DFU download command is received while in
+//! \b STATE_IDLE. New downloads are assumed to contain a prefix structure
+//! containing one of several TIVA-specific commands and this function
+//! is responsible for parsing the download data and processing whichever
+//! command is contained within it.
+//!
+//! \return Returns \b true on success or \b false on failure.
+//
+//*****************************************************************************
+bool
+ProcessDFUDnloadCommand(tDFUDownloadHeader *psCmd, uint32_t ui32Size)
+{
+ //
+ // Make sure we got enough data to contain a valid command header.
+ //
+ if(ui32Size < sizeof(tDFUDownloadHeader))
+ {
+ return(false);
+ }
+
+ //
+ // Remember the command that we have been passed since we will need thi
+ // to determine which state to transition to on exit from STATE_DNLOAD_SYNC.
+ //
+ g_ui8LastCommand = psCmd->ui8Command;
+
+ //
+ // Which command have we been passed?
+ //
+ switch(psCmd->ui8Command)
+ {
+ //
+ // We are being asked to start a programming operation.
+ //
+ case DFU_CMD_PROG:
+ {
+ tDFUDownloadProgHeader *psHdr;
+
+ //
+ // Extract the address and size from the command header.
+ //
+ psHdr = (tDFUDownloadProgHeader *)psCmd;
+
+ //
+ // Is the passed address range valid?
+ //
+ if(BL_FLASH_AD_CHECK_FN_HOOK(psHdr->ui16StartAddr * 1024,
+ psHdr->ui32Length))
+ {
+ //
+ // Yes - remember the range passed so that we will write the
+ // passed data to the correct place.
+ //
+ g_sNextDownload.pui8Start =
+ (uint8_t *)(psHdr->ui16StartAddr * 1024);
+ g_sNextDownload.ui32Length = psHdr->ui32Length;
+
+ //
+ // If we have been provided with a progress reporting hook
+ // function, remember the total length of the image so that
+ // we can report this later.
+ //
+#ifdef BL_PROGRESS_FN_HOOK
+ g_ui32ImageSize = psHdr->ui32Length;
+#endif
+
+ //
+ // Also set the upload address and size to match this download
+ // so that, by default, the host will get back what it just
+ // wrote if it performs an upload without an intermediate
+ // DFU_CMD_READ to set the address and size.
+ //
+ g_sNextUpload.pui8Start =
+ (uint8_t *)(psHdr->ui16StartAddr * 1024);
+ g_sNextUpload.ui32Length = psHdr->ui32Length;
+
+ //
+ // Also remember that we have data in this packet to write.
+ //
+ g_pui8DFUWrite = (uint8_t *)(psHdr + 1);
+ g_ui16DFUBufferUsed = ui32Size - sizeof(tDFUDownloadHeader);
+
+ //
+ // If a start signal hook function has been provided, call it
+ // here since we are about to start a new download.
+ //
+#ifdef BL_START_FN_HOOK
+ BL_START_FN_HOOK();
+#endif
+
+ //
+ // If FLASH_CODE_PROTECTION is defined in bl_config.h we
+ // erase the whole application area at this point before we
+ // start to flash the new image.
+ //
+#ifdef FLASH_CODE_PROTECTION
+ g_sErase.pui8Start =
+ (uint8_t *)g_sDFUDeviceInfo.ui32AppStartAddr;
+
+ g_sErase.ui32Length = (g_sDFUDeviceInfo.ui32FlashTop -
+ g_sDFUDeviceInfo.ui32AppStartAddr);
+ HWREGBITW(&g_ui32CommandFlags, CMD_FLAG_ERASE) = 1;
+#endif
+
+ //
+ // Tell the main thread to write the data we just received it.
+ //
+ HWREGBITW(&g_ui32CommandFlags, CMD_FLAG_WRITE) = 1;
+ }
+ else
+ {
+ //
+ // The flash range was invalid so switch to error state.
+ //
+ return(false);
+ }
+ break;
+ }
+
+ //
+ // We are being passed the position and size of a block of flash to
+ // return in a following upload operation.
+ //
+ case DFU_CMD_READ:
+ {
+ tDFUDownloadReadCheckHeader *psHdr;
+
+ //
+ // Extract the address and size from the command header.
+ //
+ psHdr = (tDFUDownloadReadCheckHeader *)psCmd;
+
+ //
+ // Is the passed address range valid?
+ //
+ if(FlashRangeCheck(psHdr->ui16StartAddr * 1024, psHdr->ui32Length))
+ {
+ //
+ // Yes - remember the range passed so that we will return
+ // this block of flash on the next upload request.
+ //
+ g_sNextUpload.pui8Start =
+ (uint8_t *)(psHdr->ui16StartAddr * 1024);
+ g_sNextUpload.ui32Length = psHdr->ui32Length;
+ }
+ else
+ {
+ //
+ // The flash range was invalid so switch to error state.
+ //
+ return(false);
+ }
+ break;
+ }
+
+ //
+ // We are being passed the position and size of a block of flash which
+ // we will check to ensure that it is erased.
+ //
+ case DFU_CMD_CHECK:
+ {
+ tDFUDownloadReadCheckHeader *psHdr;
+ uint32_t *pui32Check;
+ uint32_t ui32Loop;
+
+ //
+ // Extract the address and size from the command header.
+ //
+ psHdr = (tDFUDownloadReadCheckHeader *)psCmd;
+
+ //
+ // Make sure the range we have been passed is within the area of
+ // flash that we are allowed to look at.
+ //
+ if(FlashRangeCheck(psHdr->ui16StartAddr * 1024, psHdr->ui32Length))
+ {
+ //
+ // The range is valid so perform the check here.
+ //
+ pui32Check = (uint32_t *)(psHdr->ui16StartAddr * 1024);
+
+ //
+ // Check each word in the range to ensure that it is erased. If
+ // not, set the error status and return.
+ //
+ for(ui32Loop = 0; ui32Loop < (psHdr->ui32Length / 4);
+ ui32Loop++)
+ {
+ if(*pui32Check != 0xFFFFFFFF)
+ {
+ g_eDFUStatus = STATUS_ERR_CHECK_ERASED;
+ return(false);
+ }
+ pui32Check++;
+ }
+
+ //
+ // If we get here, the check passed so set the status to
+ // indicate this.
+ //
+ g_eDFUStatus = STATUS_OK;
+ }
+ else
+ {
+ //
+ // The flash range was invalid so switch to error state.
+ //
+ return(false);
+ }
+ break;
+ }
+
+ //
+ // We are being asked to erase a block of flash.
+ //
+ case DFU_CMD_ERASE:
+ {
+ tDFUDownloadEraseHeader *psHdr;
+
+ //
+ // Extract the address and size from the command header.
+ //
+ psHdr = (tDFUDownloadEraseHeader *)psCmd;
+
+ //
+ // Make sure the range we have been passed is within the area of
+ // flash that we are allowed to look at.
+ //
+ if(FlashRangeCheck((uint32_t)psHdr->ui16StartAddr * 1024,
+ ((uint32_t)psHdr->ui16NumBlocks *
+ DFU_REPORTED_PAGE_SIZE )))
+ {
+ //
+ // The range is valid so tell the main loop to erase the
+ // block.
+ //
+ g_sErase.pui8Start = (uint8_t *)
+ ((uint32_t)psHdr->ui16StartAddr * 1024);
+ g_sErase.ui32Length = ((uint32_t)psHdr->ui16NumBlocks *
+ DFU_REPORTED_PAGE_SIZE);
+ HWREGBITW(&g_ui32CommandFlags, CMD_FLAG_ERASE) = 1;
+ }
+ else
+ {
+ //
+ // The flash range was invalid so switch to error state.
+ //
+ return(false);
+ }
+ break;
+ }
+
+ //
+ // We are being asked to send back device information on the next
+ // upload request.
+ //
+ case DFU_CMD_INFO:
+ {
+ //
+ // Register that we need to send the device info structure on the
+ // next upload request.
+ //
+ g_sNextUpload.pui8Start = (uint8_t *)&g_sDFUDeviceInfo;
+ g_sNextUpload.ui32Length = sizeof(tDFUDeviceInfo);
+
+ //
+ // Make sure we don't append the DFU_CMD_PROG header when we send
+ // back the data.
+ //
+ g_bSuppressUploadHeader = true;
+ break;
+ }
+
+ //
+ // We are being asked to set the format of uploaded images.
+ //
+ case DFU_CMD_BIN:
+ {
+ tDFUDownloadBinHeader *psHdr;
+
+ //
+ // Extract the required format the command header.
+ //
+ psHdr = (tDFUDownloadBinHeader *)psCmd;
+
+ //
+ // Set the global format appropriately.
+ //
+ g_bUploadBinary = psHdr->bBinary ? true : false;
+ break;
+ }
+
+ //
+ // We are being asked to prepare to reset the board and, as a result,
+ // run the main application image.
+ //
+ case DFU_CMD_RESET:
+ {
+ //
+ // Tell the main thread that it's time to go bye-bye...
+ //
+ HWREGBITW(&g_ui32CommandFlags, CMD_FLAG_RESET) = 1;
+
+ break;
+ }
+
+ //
+ // We have been passed an unrecognized command identifier so report an
+ // error.
+ //
+ default:
+ {
+ g_eDFUStatus = STATUS_ERR_VENDOR;
+ return(false);
+ }
+ }
+
+ return(true);
+}
+
+//*****************************************************************************
+//
+// This callback function is called when data is received for the DATA phase
+// of an EP0 OUT transaction. This data will either be a block of download
+// data (if we are in STATE_DNLOAD_IDLE) or a new command (if we are in
+// STATE_IDLE).
+//
+//*****************************************************************************
+void
+HandleEP0Data(uint32_t ui32Size)
+{
+ bool bRetcode;
+
+ if(g_eDFUState == STATE_IDLE)
+ {
+ //
+ // This must be a new DFU download command header so parse it and
+ // determine what to do next.
+ //
+ bRetcode =
+ ProcessDFUDnloadCommand((tDFUDownloadHeader *)g_pui8DFUBuffer,
+ ui32Size);
+
+ //
+ // Did we receive a recognized and valid command?
+ //
+ if(!bRetcode)
+ {
+ //
+ // No - set the error state. The status is set within the
+ // ProcessDFUDnloadCommand() function.
+ //
+ g_eDFUState = STATE_ERROR;
+ return;
+ }
+ }
+ else
+ {
+ //
+ // If we are not in STATE_IDLE, this must be a block of data for an
+ // ongoing download so signal the main thread to write it to flash.
+ //
+ g_ui16DFUBufferUsed = (uint16_t)ui32Size;
+ g_pui8DFUWrite = g_pui8DFUBuffer;
+
+ //
+ // Tell the main thread to write the new data.
+ //
+ HWREGBITW(&g_ui32CommandFlags, CMD_FLAG_WRITE) = 1;
+ }
+
+ //
+ // Move to STATE_DNLOAD_SYNC since we now expect USBD_DFU_REQUEST_GETSTATUS
+ // before the next USBD_DFU_REQUEST_DNLOAD.
+ //
+ g_eDFUState = STATE_DNLOAD_SYNC;
+}
+
+//*****************************************************************************
+//
+// Handle bus resets
+//
+// This function is called if the USB controller detects a reset condition on
+// the bus. If we are not in the process of downloading a new image, we use
+// this as a signal to reboot and run the main application image.
+//
+//*****************************************************************************
+void
+HandleReset(void)
+{
+ //
+ // Are we currently in the middle of a download operation?
+ //
+ if((g_eDFUState != STATE_DNLOAD_IDLE) &&
+ (g_eDFUState != STATE_DNLOAD_SYNC) && (g_eDFUState != STATE_IDLE))
+ {
+ //
+ // No - tell the main thread that it should reboot the system assuming
+ // that we are already configured. If we don't check that we are
+ // already configured, this will cause a reset during initial
+ // enumeration and that wouldn't be very helpful.
+ //
+ if(g_bAddressSet)
+ {
+ HWREGBITW(&g_ui32CommandFlags, CMD_FLAG_RESET) = 1;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// Handle cases where the USB host disconnects.
+//
+//*****************************************************************************
+void
+HandleDisconnect(void)
+{
+ //
+ // For error resilience, it may be desireable to note if the host
+ // disconnects and, if partway through a main image download, clear the
+ // first block of the flash to ensure that the image is not considered
+ // valid on the next boot. For now, however, we merely wait for the host
+ // to connect again, remaining in DFU mode.
+ //
+
+ //
+ // Remember that we are waiting for enumeration.
+ //
+ g_bAddressSet = false;
+}
+
+//*****************************************************************************
+//
+// Erase a single block of flash
+//
+// This function erases a single, 1KB block of flash, returning once the
+// operation has completed.
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+EraseFlashBlock(uint32_t ui32Addr)
+{
+ BL_FLASH_ERASE_FN_HOOK(ui32Addr);
+}
+
+//*****************************************************************************
+//
+//! This is the main routine for handling updating over USB.
+//!
+//! This function forms the main loop of the USB DFU updater. It polls for
+//! commands sent from the USB request handlers and is responsible for
+//! erasing flash blocks, programming data into erased blocks and resetting
+//! the device.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+UpdaterUSB(void)
+{
+ uint32_t ui32Idx, ui32Start, ui32Temp;
+ uint16_t ui16Used;
+#ifndef FLASH_CODE_PROTECTION
+ uint32_t ui32End;
+#endif
+
+ //
+ // Loop forever waiting for the USB interrupt handlers to tell us to do
+ // something.
+ //
+ while(1)
+ {
+ while(g_ui32CommandFlags == 0)
+ {
+ //
+ // Wait for something to do.
+ //
+ }
+
+ //
+ // Are we being asked to perform a system reset?
+ //
+ if(HWREGBITW(&g_ui32CommandFlags, CMD_FLAG_RESET))
+ {
+ //
+ // Time to go bye-bye... 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)
+ {
+ }
+ }
+
+ //
+ // Are we being asked to erase a range of blocks in flash?
+ //
+ if(HWREGBITW(&g_ui32CommandFlags, CMD_FLAG_ERASE))
+ {
+ //
+ // Loop through the pages in the block of flash we have been asked
+ // to erase and clear each one.
+ //
+ ui32Temp = g_sErase.ui32Length;
+ for(ui32Idx = (uint32_t)g_sErase.pui8Start;
+ ui32Idx < (uint32_t)(g_sErase.pui8Start + ui32Temp);
+ ui32Idx += FLASH_PAGE_SIZE)
+ {
+ EraseFlashBlock(ui32Idx);
+ }
+
+ //
+ // Clear the command flag to indicate that we are done.
+ //
+ HWREGBITW(&g_ui32CommandFlags, CMD_FLAG_ERASE) = 0;
+ }
+
+ //
+ // Are we being asked to program a block of flash?
+ //
+ if(HWREGBITW(&g_ui32CommandFlags, CMD_FLAG_WRITE))
+ {
+ //
+ // Decrypt the data if required.
+ //
+#ifdef BL_DECRYPT_FN_HOOK
+ BL_DECRYPT_FN_HOOK(g_pui8DFUWrite, g_ui16DFUBufferUsed);
+#endif
+
+ //
+ // Where will the new block be written?
+ //
+ ui32Start = (uint32_t)(g_sNextDownload.pui8Start);
+
+#ifndef FLASH_CODE_PROTECTION
+ //
+ // What is the address of the last byte we will write in this
+ // block of data? We copy g_ui16DFUBufferUsed to prevent warnings
+ // about "undefined order of volatile accesses" from some
+ // compilers.
+ //
+ ui16Used = g_ui16DFUBufferUsed;
+
+ ui32End = (uint32_t)g_sNextDownload.pui8Start + ui16Used - 1;
+
+ //
+ // Are we writing data at the start of a new flash block? If so,
+ // we need to erase the content of the block first.
+ //
+ if((ui32Start & (FLASH_PAGE_SIZE - 1)) == 0)
+ {
+ //
+ // We are writing to the start of a block so erase it.
+ //
+ EraseFlashBlock(ui32Start & ~(FLASH_PAGE_SIZE - 1));
+ }
+ else
+ {
+ //
+ // Will this block of data straddle two flash blocks? If so,
+ // we need to erase the following block.
+ //
+ if((ui32Start & ~(FLASH_PAGE_SIZE - 1)) !=
+ (ui32End & ~(FLASH_PAGE_SIZE - 1)))
+ {
+ EraseFlashBlock(ui32End & ~(FLASH_PAGE_SIZE - 1));
+ }
+ }
+#endif
+
+ //
+ // Write the new block of data to the flash
+ //
+ BL_FLASH_PROGRAM_FN_HOOK(ui32Start, g_pui8DFUWrite, ui16Used);
+
+ //
+ // Update our position and remaining size.
+ //
+ g_sNextDownload.pui8Start += ui16Used;
+ g_sNextDownload.ui32Length -= ui16Used;
+
+ //
+ // Clear the command flag to indicate that we are done.
+ //
+ HWREGBITW(&g_ui32CommandFlags, CMD_FLAG_WRITE) = 0;
+
+ //
+ // If a progress hook function has been provided, call
+ // it here.
+ //
+#ifdef BL_PROGRESS_FN_HOOK
+ BL_PROGRESS_FN_HOOK(g_ui32ImageSize - g_sNextDownload.ui32Length,
+ g_ui32ImageSize);
+#endif
+
+ //
+ // If we just finished the download and an end signal hook function
+ // has been provided, call it too.
+ //
+#ifdef BL_END_FN_HOOK
+ if(g_sNextDownload.ui32Length == 0)
+ {
+ BL_END_FN_HOOK();
+ }
+#endif
+ }
+ }
+}
+
+//*****************************************************************************
+//
+//! Configure the USB controller and place the DFU device on the bus.
+//!
+//! This function configures the USB controller for DFU device operation,
+//! initializes the state machines required to control the firmware update and
+//! places the device on the bus in preparation for requests from the host. It
+//! is assumed that the main system clock has been configured at this point.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+ConfigureUSBInterface(void)
+{
+ uint32_t ui32FlashSize;
+
+ //
+ // Initialize our device information structure.
+ //
+ ui32FlashSize = BL_FLASH_SIZE_FN_HOOK();
+
+ g_sDFUDeviceInfo.ui16FlashBlockSize = DFU_REPORTED_PAGE_SIZE;
+ g_sDFUDeviceInfo.ui16NumFlashBlocks =
+ ui32FlashSize / DFU_REPORTED_PAGE_SIZE;
+ g_sDFUDeviceInfo.ui32ClassInfo = HWREG(SYSCTL_DID0);
+ g_sDFUDeviceInfo.ui32PartInfo = HWREG(SYSCTL_DID1);
+ g_sDFUDeviceInfo.ui32AppStartAddr = APP_START_ADDRESS;
+#ifdef FLASH_RSVD_SPACE
+ g_sDFUDeviceInfo.ui32FlashTop = ui32FlashSize - FLASH_RSVD_SPACE;
+#else
+ g_sDFUDeviceInfo.ui32FlashTop = ui32FlashSize;
+#endif
+
+ //
+ // Publish our DFU device descriptors and place the device on the bus.
+ //
+ USBBLInit();
+}
+
+#if (defined USB_HAS_MUX) || (defined DOXYGEN)
+//*****************************************************************************
+//
+//! Configures and set the mux selecting USB device-mode operation.
+//!
+//! On target boards which use a multiplexer to switch between USB host and
+//! device operation, this function is used to configure the relevant GPIO
+//! pin and drive it such that the mux selects USB device-mode operation.
+//! If \b USB_HAS_MUX is not defined in bl_config.h, this function is compiled
+//! out.
+//!
+//! \return None.
+//
+//*****************************************************************************
+static void
+SetUSBMux(void)
+{
+ //
+ // Enable the GPIO peripheral that contains the mux control pin.
+ //
+ HWREG(SYSCTL_RCGC2) |= USB_MUX_PERIPH;
+
+ //
+ // Delay a very short period before we access the newly-enabled peripheral.
+ //
+ Delay(1);
+
+ //
+ // Make the pin be an output.
+ //
+ HWREG(USB_MUX_PORT + GPIO_O_DIR) |= (1 << USB_MUX_PIN);
+ HWREG(USB_MUX_PORT + GPIO_O_AFSEL) &= ~(1 << USB_MUX_PIN);
+
+ //
+ // Set the output drive strength to 2mA.
+ //
+ HWREG(USB_MUX_PORT + GPIO_O_DR2R) |= (1 << USB_MUX_PIN);
+ HWREG(USB_MUX_PORT + GPIO_O_DR4R) &= ~(1 << USB_MUX_PIN);
+ HWREG(USB_MUX_PORT + GPIO_O_DR8R) &= ~(1 << USB_MUX_PIN);
+ HWREG(USB_MUX_PORT + GPIO_O_SLR) &= ~(1 << USB_MUX_PIN);
+
+ //
+ // Set the pin type to a normal, GPIO output.
+ //
+ HWREG(USB_MUX_PORT + GPIO_O_ODR) &= ~(1 << USB_MUX_PIN);
+ HWREG(USB_MUX_PORT + GPIO_O_PUR) &= ~(1 << USB_MUX_PIN);
+ HWREG(USB_MUX_PORT + GPIO_O_PDR) &= ~(1 << USB_MUX_PIN);
+ HWREG(USB_MUX_PORT + GPIO_O_DEN) |= (1 << USB_MUX_PIN);
+
+ //
+ // Clear this pin's bit in the analog mode select register.
+ //
+ HWREG(USB_MUX_PORT + GPIO_O_AMSEL) &= ~(1 << USB_MUX_PIN);
+
+ //
+ // Write the pin to the appropriate level to select USB device mode.
+ //
+ HWREG(USB_MUX_PORT + (GPIO_O_DATA + ((1 << USB_MUX_PIN) << 2))) =
+ (USB_MUX_DEVICE ? (1 << USB_MUX_PIN) : 0);
+}
+#endif
+
+//*****************************************************************************
+//
+//! 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 and place the DFU device on the bus.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+ConfigureUSB(void)
+{
+ //
+ // Enable the main oscillator.
+ //
+ HWREG(SYSCTL_RCC) &= ~(SYSCTL_RCC_MOSCDIS);
+
+ //
+ // Delay while the main oscillator starts up.
+ //
+ Delay(524288);
+
+ //
+ // Set the crystal frequency, switch to the main oscillator, and enable the
+ // PLL.
+ //
+ HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
+ ~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_XTAL_M |
+ SYSCTL_RCC_OSCSRC_M)) |
+ XTAL_VALUE | SYSCTL_RCC_OSCSRC_MAIN);
+
+ //
+ // Delay while the PLL locks.
+ //
+ Delay(524288);
+
+ //
+ // Disable the PLL bypass so that the part is clocked from the PLL, and set
+ // sysdiv to 8. This yields a system clock of 25MHz.
+ //
+ HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) & ~(SYSCTL_RCC_BYPASS |
+ SYSCTL_RCC_SYSDIV_M)) |
+ ((8 - 1) << SYSCTL_RCC_SYSDIV_S) |
+ SYSCTL_RCC_USESYSDIV);
+
+ //
+ // If the target device has a mux to allow selection of USB host or
+ // device mode, make sure this is set to device mode.
+ //
+#ifdef USB_HAS_MUX
+ SetUSBMux();
+#endif
+
+ //
+ // Configure the USB interface and put the device on the bus.
+ //
+ ConfigureUSBInterface();
+}
+
+//*****************************************************************************
+//
+//! This is the application entry point to the USB updater.
+//!
+//! This function should only be entered from a running application and not
+//! when running the boot loader with no application present. If the
+//! calling application supports any USB device function, it must remove
+//! itself from the USB bus prior to calling this function. This function
+//! assumes that the calling application has already configured the system
+//! clock to run from the PLL.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+AppUpdaterUSB(void)
+{
+ //
+ // Set sysdiv to 8. This yields a system clock of 25MHz.
+ //
+ HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) & ~(SYSCTL_RCC_SYSDIV_M)) |
+ ((8 - 1) << SYSCTL_RCC_SYSDIV_S));
+
+ //
+ // If the target device has a mux to allow selection of USB host or
+ // device mode, make sure this is set to device mode.
+ //
+#ifdef USB_HAS_MUX
+ SetUSBMux();
+#endif
+
+ //
+ // Configure the USB interface and put the device on the bus.
+ //
+ ConfigureUSBInterface();
+
+ //
+ // Call the main update routine.
+ //
+ UpdaterUSB();
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+#endif
diff --git a/boot_loader/bl_usbfuncs.c b/boot_loader/bl_usbfuncs.c new file mode 100644 index 0000000..552fabc --- /dev/null +++ b/boot_loader/bl_usbfuncs.c @@ -0,0 +1,1915 @@ +//*****************************************************************************
+//
+// bl_usbfuncs.c - The subset of USB library functions required by the USB DFU
+// boot loader.
+//
+// Copyright (c) 2008-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 <stdbool.h>
+#include <stdint.h>
+#include "inc/hw_types.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_usb.h"
+#include "inc/hw_sysctl.h"
+#include "inc/hw_nvic.h"
+#include "inc/hw_ints.h"
+#include "inc/hw_gpio.h"
+#include "bl_config.h"
+#include "boot_loader/bl_usbfuncs.h"
+
+//*****************************************************************************
+//
+//! \addtogroup bl_usb_api
+//! @{
+//
+//*****************************************************************************
+#if defined(USB_ENABLE_UPDATE) || defined(DOXYGEN)
+
+//*****************************************************************************
+//
+// Local functions prototypes.
+//
+//*****************************************************************************
+static void USBDGetStatus(tUSBRequest *pUSBRequest);
+static void USBDClearFeature(tUSBRequest *pUSBRequest);
+static void USBDSetFeature(tUSBRequest *pUSBRequest);
+static void USBDSetAddress(tUSBRequest *pUSBRequest);
+static void USBDGetDescriptor(tUSBRequest *pUSBRequest);
+static void USBDSetDescriptor(tUSBRequest *pUSBRequest);
+static void USBDGetConfiguration(tUSBRequest *pUSBRequest);
+static void USBDSetConfiguration(tUSBRequest *pUSBRequest);
+static void USBDGetInterface(tUSBRequest *pUSBRequest);
+static void USBDSetInterface(tUSBRequest *pUSBRequest);
+static void USBDEP0StateTx(void);
+static int32_t USBDStringIndexFromRequest(uint16_t ui16Lang,
+ uint16_t ui16Index);
+
+//*****************************************************************************
+//
+// This structure holds the full state for the device enumeration.
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ // The devices current address, this also has a change pending bit in the
+ // MSB of this value specified by DEV_ADDR_PENDING.
+ //
+ volatile uint32_t ui32DevAddress;
+
+ //
+ // This holds the current active configuration for this device.
+ //
+ uint32_t ui32Configuration;
+
+ //
+ // This holds the current alternate interface for this device. We only have
+ // 1 interface so only need to hold 1 setting.
+ //
+ uint8_t ui8AltSetting;
+
+ //
+ // This is the pointer to the current data being sent out or received
+ // on endpoint zero.
+ //
+ uint8_t *pui8EP0Data;
+
+ //
+ // This is the number of bytes that remain to be sent from or received
+ // into the g_sUSBDeviceState.pui8EP0Data data buffer.
+ //
+ volatile uint32_t ui32EP0DataRemain;
+
+ //
+ // The amount of data being sent/received due to a custom request.
+ //
+ uint32_t ui32OUTDataSize;
+
+ //
+ // Holds the current device status.
+ //
+ uint8_t ui8Status;
+
+ //
+ // This flag indicates whether or not remote wakeup signalling is in
+ // progress.
+ //
+ bool bRemoteWakeup;
+
+ //
+ // During remote wakeup signalling, this counter is used to track the
+ // number of milliseconds since the signalling was initiated.
+ //
+ uint8_t ui8RemoteWakeupCount;
+}
+tDeviceState;
+
+//*****************************************************************************
+//
+// The states for endpoint zero during enumeration.
+//
+//*****************************************************************************
+typedef enum
+{
+ //
+ // The USB device is waiting on a request from the host controller on
+ // endpoint zero.
+ //
+ USB_STATE_IDLE,
+
+ //
+ // The USB device is sending data back to the host due to an IN request.
+ //
+ USB_STATE_TX,
+
+ //
+ // The USB device is receiving data from the host due to an OUT
+ // request from the host.
+ //
+ USB_STATE_RX,
+
+ //
+ // The USB device has completed the IN or OUT request and is now waiting
+ // for the host to acknowledge the end of the IN/OUT transaction. This
+ // is the status phase for a USB control transaction.
+ //
+ USB_STATE_STATUS,
+
+ //
+ // This endpoint has signaled a stall condition and is waiting for the
+ // stall to be acknowledged by the host controller.
+ //
+ USB_STATE_STALL
+}
+tEP0State;
+
+//*****************************************************************************
+//
+// Define the max packet size for endpoint zero.
+//
+//*****************************************************************************
+#define EP0_MAX_PACKET_SIZE 64
+
+//*****************************************************************************
+//
+// This is a flag used with g_sUSBDeviceState.ui32DevAddress to indicate that a
+// device address change is pending.
+//
+//*****************************************************************************
+#define DEV_ADDR_PENDING 0x80000000
+
+//*****************************************************************************
+//
+// This label defines the default configuration number to use after a bus
+// reset.
+//
+//*****************************************************************************
+#define DEFAULT_CONFIG_ID 1
+
+//*****************************************************************************
+//
+// This label defines the number of milliseconds that the remote wakeup signal
+// must remain asserted before removing it. Section 7.1.7.7 of the USB 2.0 spec
+// states that "the remote wakeup device must hold the resume signaling for at
+// least 1ms but for no more than 15ms" so 10mS seems a reasonable choice.
+//
+//*****************************************************************************
+#define REMOTE_WAKEUP_PULSE_MS 10
+
+//*****************************************************************************
+//
+// This label defines the number of milliseconds between the point where we
+// assert the remote wakeup signal and calling the client back to tell it that
+// bus operation has been resumed. This value is based on the timings provided
+// in section 7.1.7.7 of the USB 2.0 specification which indicates that the host
+// (which takes over resume signalling when the device's initial signal is
+// detected) must hold the resume signalling for at least 20mS.
+//
+//*****************************************************************************
+#define REMOTE_WAKEUP_READY_MS 20
+
+//*****************************************************************************
+//
+// The buffer for reading data coming into EP0
+//
+//*****************************************************************************
+static uint8_t g_pui8DataBufferIn[EP0_MAX_PACKET_SIZE];
+
+//*****************************************************************************
+//
+// This global holds the current state information for the USB device.
+//
+//*****************************************************************************
+static volatile tDeviceState g_sUSBDeviceState;
+
+//*****************************************************************************
+//
+// This global holds the current state of endpoint zero.
+//
+//*****************************************************************************
+static volatile tEP0State g_eUSBDEP0State = USB_STATE_IDLE;
+
+//*****************************************************************************
+//
+// Function table to handle standard requests.
+//
+//*****************************************************************************
+static const tStdRequest g_ppfnUSBDStdRequests[] =
+{
+ USBDGetStatus,
+ USBDClearFeature,
+ 0,
+ USBDSetFeature,
+ 0,
+ USBDSetAddress,
+ USBDGetDescriptor,
+ USBDSetDescriptor,
+ USBDGetConfiguration,
+ USBDSetConfiguration,
+ USBDGetInterface,
+ USBDSetInterface,
+};
+
+//*****************************************************************************
+//
+// Amount to shift the RX interrupt sources by in the flags used in the
+// interrupt calls.
+//
+//*****************************************************************************
+#define USB_INT_RX_SHIFT 8
+
+//*****************************************************************************
+//
+// Amount to shift the status interrupt sources by in the flags used in the
+// interrupt calls.
+//
+//*****************************************************************************
+#define USB_INT_STATUS_SHIFT 24
+
+//*****************************************************************************
+//
+// Amount to shift the RX endpoint status sources by in the flags used in the
+// calls.
+//
+//*****************************************************************************
+#define USB_RX_EPSTATUS_SHIFT 16
+
+//*****************************************************************************
+//
+// Converts from an endpoint specifier to the offset of the endpoint's
+// control/status registers.
+//
+//*****************************************************************************
+#define EP_OFFSET(Endpoint) (Endpoint - 0x10)
+
+//*****************************************************************************
+//
+// Retrieves data from endpoint 0's FIFO.
+//
+// \param pui8Data is a pointer to the data area used to return the data from
+// the FIFO.
+// \param pui32Size is initially the size of the buffer passed into this call
+// via the \e pui8Data parameter. It will be set to the amount of data
+// returned in the buffer.
+//
+// This function will return the data from the FIFO for endpoint 0.
+// The \e pui32Size parameter should indicate the size of the buffer passed in
+// the \e pui32Data parameter. The data in the \e pui32Size parameter will be
+// changed to match the amount of data returned in the \e pui8Data parameter.
+// If a zero byte packet was received this call will not return a error but
+// will instead just return a zero in the \e pui32Size parameter. The only
+// error case occurs when there is no data packet available.
+//
+// \return This call will return 0, or -1 if no packet was received.
+//
+//*****************************************************************************
+int32_t
+USBEndpoint0DataGet(uint8_t *pui8Data, uint32_t *pui32Size)
+{
+ uint32_t ui32ByteCount;
+
+ //
+ // Don't allow reading of data if the RxPktRdy bit is not set.
+ //
+ if((HWREGH(USB0_BASE + USB_O_CSRL0) & USB_CSRL0_RXRDY) == 0)
+ {
+ //
+ // Can't read the data because none is available.
+ //
+ *pui32Size = 0;
+
+ //
+ // Return a failure since there is no data to read.
+ //
+ return(-1);
+ }
+
+ //
+ // Get the byte count in the FIFO.
+ //
+ ui32ByteCount = HWREGH(USB0_BASE + USB_O_COUNT0 + USB_EP_0);
+
+ //
+ // Determine how many bytes we will actually copy.
+ //
+ ui32ByteCount = (ui32ByteCount < *pui32Size) ? ui32ByteCount : *pui32Size;
+
+ //
+ // Return the number of bytes we are going to read.
+ //
+ *pui32Size = ui32ByteCount;
+
+ //
+ // Read the data out of the FIFO.
+ //
+ for(; ui32ByteCount > 0; ui32ByteCount--)
+ {
+ //
+ // Read a byte at a time from the FIFO.
+ //
+ *pui8Data++ = HWREGB(USB0_BASE + USB_O_FIFO0 + (USB_EP_0 >> 2));
+ }
+
+ //
+ // Success.
+ //
+ return(0);
+}
+
+//*****************************************************************************
+//
+// Acknowledge that data was read from endpoint 0's FIFO.
+//
+// \param bIsLastPacket indicates if this is the last packet.
+//
+// This function acknowledges that the data was read from the endpoint 0's
+// FIFO. The \e bIsLastPacket parameter is set to a \b true value if this is
+// the last in a series of data packets. This call can be used if processing
+// is required between reading the data and acknowledging that the data has
+// been read.
+//
+// \return None.
+//
+//*****************************************************************************
+void
+USBDevEndpoint0DataAck(bool bIsLastPacket)
+{
+ //
+ // Clear RxPktRdy, and optionally DataEnd, on endpoint zero.
+ //
+ HWREGB(USB0_BASE + USB_O_CSRL0) =
+ USB_CSRL0_RXRDYC | (bIsLastPacket ? USB_CSRL0_DATAEND : 0);
+
+}
+
+//*****************************************************************************
+//
+// Puts data into endpoint 0's FIFO.
+//
+// \param pui8Data is a pointer to the data area used as the source for the
+// data to put into the FIFO.
+// \param ui32Size is the amount of data to put into the FIFO.
+//
+// This function will put the data from the \e pui8Data parameter into the FIFO
+// for endpoint 0. If a packet is already pending for transmission then
+// this call will not put any of the data into the FIFO and will return -1.
+//
+// \return This call will return 0 on success, or -1 to indicate that the FIFO
+// is in use and cannot be written.
+//
+//*****************************************************************************
+int32_t
+USBEndpoint0DataPut(uint8_t *pui8Data, uint32_t ui32Size)
+{
+ //
+ // Don't allow transmit of data if the TxPktRdy bit is already set.
+ //
+ if(HWREGB(USB0_BASE + USB_O_CSRL0 + USB_EP_0) & USB_CSRL0_TXRDY)
+ {
+ return(-1);
+ }
+
+ //
+ // Write the data to the FIFO.
+ //
+ for(; ui32Size > 0; ui32Size--)
+ {
+ HWREGB(USB0_BASE + USB_O_FIFO0 + (USB_EP_0 >> 2)) = *pui8Data++;
+ }
+
+ //
+ // Success.
+ //
+ return(0);
+}
+
+//*****************************************************************************
+//
+// Starts the transfer of data from endpoint 0's FIFO.
+//
+// \param ui32TransType is set to indicate what type of data is being sent.
+//
+// This function will start the transfer of data from the FIFO for
+// endpoint 0. This is necessary if the \b USB_EP_AUTO_SET bit was not enabled
+// for the endpoint. Setting the \e ui32TransType parameter will allow the
+// appropriate signaling on the USB bus for the type of transaction being
+// requested. The \e ui32TransType parameter should be one of the following:
+//
+// - USB_TRANS_OUT for OUT transaction on any endpoint in host mode.
+// - USB_TRANS_IN for IN transaction on any endpoint in device mode.
+// - USB_TRANS_IN_LAST for the last IN transactions on endpoint zero in a
+// sequence of IN transactions.
+// - USB_TRANS_SETUP for setup transactions on endpoint zero.
+// - USB_TRANS_STATUS for status results on endpoint zero.
+//
+// \return This call will return 0 on success, or -1 if a transmission is
+// already in progress.
+//
+//*****************************************************************************
+int32_t
+USBEndpoint0DataSend(uint32_t ui32TransType)
+{
+ //
+ // Don't allow transmit of data if the TxPktRdy bit is already set.
+ //
+ if(HWREGB(USB0_BASE + USB_O_CSRL0 + USB_EP_0) & USB_CSRL0_TXRDY)
+ {
+ return(-1);
+ }
+
+ //
+ // Set TxPktRdy in order to send the data.
+ //
+ HWREGB(USB0_BASE + USB_O_CSRL0 + USB_EP_0) = ui32TransType & 0xff;
+
+ //
+ // Success.
+ //
+ return(0);
+}
+
+#if defined(USB_VBUS_CONFIG) || defined(USB_ID_CONFIG) || \
+ defined(USB_DP_CONFIG) || defined(USB_DM_CONFIG) || defined(DOXYGEN)
+//*****************************************************************************
+//
+//! Initialize the pins used by USB functions.
+//!
+//! This function configures the pins for USB functions depending on defines
+//! from the bl_config.h file.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USBConfigurePins(void)
+{
+ //
+ // Enable the clocks to the GPIOs.
+ //
+ HWREG(SYSCTL_RCGCGPIO) |= (0x0
+#if defined(USB_VBUS_CONFIG)
+ | USB_VBUS_PERIPH
+#endif
+#if defined(USB_ID_CONFIG)
+ | USB_ID_PERIPH
+#endif
+#if defined(USB_DP_CONFIG)
+ | USB_DP_PERIPH
+#endif
+#if defined(USB_DM_CONFIG)
+ | USB_DM_PERIPH
+#endif
+ );
+
+ //
+ // Setup the pins based on bl_config.h
+ //
+#if defined(USB_VBUS_CONFIG)
+ //
+ // Set the VBUS pin to be an analog input.
+ //
+ HWREG(USB_VBUS_PORT + GPIO_O_DIR) &= ~(1 << USB_VBUS_PIN);
+ HWREG(USB_VBUS_PORT + GPIO_O_AMSEL) |= (1 << USB_VBUS_PIN);
+#endif
+
+#if defined(USB_ID_CONFIG)
+ //
+ // Set the ID pin to be an analog input.
+ //
+ HWREG(USB_ID_PORT + GPIO_O_DIR) &= ~(1 << USB_ID_PIN);
+ HWREG(USB_ID_PORT + GPIO_O_AMSEL) |= (1 << USB_ID_PIN);
+#endif
+
+#if defined(USB_DP_CONFIG)
+ //
+ // Set the DP pin to be an analog input.
+ //
+ HWREG(USB_DP_PORT + GPIO_O_DIR) &= ~(1 << USB_DP_PIN);
+ HWREG(USB_DP_PORT + GPIO_O_AMSEL) |= (1 << USB_DP_PIN);
+#endif
+
+#if defined(USB_DM_CONFIG)
+ //
+ // Set the DM pin to be an analog input.
+ //
+ HWREG(USB_DM_PORT + GPIO_O_DIR) &= ~(1 << USB_DM_PIN);
+ HWREG(USB_DM_PORT + GPIO_O_AMSEL) |= (1 << USB_DM_PIN);
+#endif
+
+}
+#endif
+
+//*****************************************************************************
+//
+//! Initialize the boot loader USB functions.
+//!
+//! This function initializes the boot loader USB functions and places the DFU
+//! device onto the USB bus.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USBBLInit(void)
+{
+ //
+ // Configure the USB Pins based on the bl_config.h settings.
+ //
+#if defined(USB_VBUS_CONFIG) || defined(USB_ID_CONFIG) || \
+ defined(USB_DP_CONFIG) || defined(USB_DM_CONFIG)
+ USBConfigurePins();
+#endif
+
+ //
+ // Initialize a couple of fields in the device state structure.
+ //
+ g_sUSBDeviceState.ui32Configuration = DEFAULT_CONFIG_ID;
+
+ //
+ // Enable the USB controller.
+ //
+ HWREG(SYSCTL_RCGC2) |= 0x10000;
+
+ //
+ // Turn on USB Phy clock.
+ //
+ HWREG(SYSCTL_RCC2) &= ~SYSCTL_RCC2_USBPWRDN;
+
+ //
+ // Clear any pending interrupts.
+ //
+ HWREGH(USB0_BASE + USB_O_TXIS);
+ HWREGB(USB0_BASE + USB_O_IS);
+
+ //
+ // Enable USB Interrupts.
+ //
+ HWREGH(USB0_BASE + USB_O_TXIE) = USB_TXIS_EP0;
+ HWREGB(USB0_BASE + USB_O_IE) = (USB_IS_DISCON | USB_IS_RESET);
+
+ //
+ // Default to the state where remote wakeup is disabled.
+ //
+ g_sUSBDeviceState.ui8Status = 0;
+ g_sUSBDeviceState.bRemoteWakeup = false;
+
+ //
+ // Determine the self- or bus-powered state based on bl_config.h setting.
+ //
+#if USB_BUS_POWERED
+ g_sUSBDeviceState.ui8Status &= ~USB_STATUS_SELF_PWR;
+#else
+ g_sUSBDeviceState.ui8Status |= USB_STATUS_SELF_PWR;
+#endif
+
+ //
+ // Attach the device using the soft connect.
+ //
+ HWREGB(USB0_BASE + USB_O_POWER) |= USB_POWER_SOFTCONN;
+
+ //
+ // Enable the USB interrupt.
+ //
+ HWREG(NVIC_EN1) = 1 << (INT_USB0 - 48);
+}
+
+//*****************************************************************************
+//
+// This function starts the request for data from the host on endpoint zero.
+//
+// \param pui8Data is a pointer to the buffer to fill with data from the USB
+// host.
+// \param ui32Size is the size of the buffer or data to return from the USB
+// host.
+//
+// This function handles retrieving data from the host when a custom command
+// has been issued on endpoint zero. When the requested data is received,
+// the function HandleEP0Data() will be called.
+//
+// \return None.
+//
+//*****************************************************************************
+void
+USBBLRequestDataEP0(uint8_t *pui8Data, uint32_t ui32Size)
+{
+ //
+ // Enter the RX state on end point 0.
+ //
+ g_eUSBDEP0State = USB_STATE_RX;
+
+ //
+ // Save the pointer to the data.
+ //
+ g_sUSBDeviceState.pui8EP0Data = pui8Data;
+
+ //
+ // Location to save the current number of bytes received.
+ //
+ g_sUSBDeviceState.ui32OUTDataSize = ui32Size;
+
+ //
+ // Bytes remaining to be received.
+ //
+ g_sUSBDeviceState.ui32EP0DataRemain = ui32Size;
+}
+
+//*****************************************************************************
+//
+//! This function requests transfer of data to the host on endpoint zero.
+//!
+//! \param pui8Data is a pointer to the buffer to send via endpoint zero.
+//! \param ui32Size is the amount of data to send in bytes.
+//!
+//! This function handles sending data to the host when a custom command is
+//! issued or non-standard descriptor has been requested on endpoint zero.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USBBLSendDataEP0(uint8_t *pui8Data, uint32_t ui32Size)
+{
+ //
+ // Return the externally provided device descriptor.
+ //
+ g_sUSBDeviceState.pui8EP0Data = pui8Data;
+
+ //
+ // The size of the device descriptor is in the first byte.
+ //
+ g_sUSBDeviceState.ui32EP0DataRemain = ui32Size;
+
+ //
+ // Save the total size of the data sent.
+ //
+ g_sUSBDeviceState.ui32OUTDataSize = ui32Size;
+
+ //
+ // Now in the transmit data state.
+ //
+ USBDEP0StateTx();
+}
+
+//*****************************************************************************
+//
+//! This function generates a stall condition on endpoint zero.
+//!
+//! This function is typically called to signal an error condition to the host
+//! when an unsupported request is received by the device. It should be
+//! called from within the callback itself (in interrupt context) and not
+//! deferred until later since it affects the operation of the endpoint zero
+//! state machine.
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USBBLStallEP0(void)
+{
+ //
+ // Perform a stall on endpoint zero.
+ //
+ HWREGB(USB0_BASE + USB_O_CSRL0) |= (USB_CSRL0_STALL | USB_CSRL0_RXRDYC);
+
+ //
+ // Enter the stalled state.
+ //
+ g_eUSBDEP0State = USB_STATE_STALL;
+}
+
+//*****************************************************************************
+//
+// This internal function reads a request data packet and dispatches it to
+// either a standard request handler or the registered device request
+// callback depending upon the request type.
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBDReadAndDispatchRequest(void)
+{
+ uint32_t ui32Size;
+ tUSBRequest *pRequest;
+
+ //
+ // Cast the buffer to a request structure.
+ //
+ pRequest = (tUSBRequest *)g_pui8DataBufferIn;
+
+ //
+ // Set the buffer size.
+ //
+ ui32Size = EP0_MAX_PACKET_SIZE;
+
+ //
+ // Get the data from the USB controller end point 0.
+ //
+ USBEndpoint0DataGet(g_pui8DataBufferIn, &ui32Size);
+
+ if(!ui32Size)
+ {
+ return;
+ }
+
+ //
+ // See if this is a standard request or not.
+ //
+ if((pRequest->bmRequestType & USB_RTYPE_TYPE_M) != USB_RTYPE_STANDARD)
+ {
+ //
+ // Pass this non-standard request on to the DFU handler
+ //
+ HandleRequests(pRequest);
+ }
+ else
+ {
+ //
+ // Assure that the jump table is not out of bounds.
+ //
+ if((pRequest->bRequest <
+ (sizeof(g_ppfnUSBDStdRequests) / sizeof(tStdRequest))) &&
+ (g_ppfnUSBDStdRequests[pRequest->bRequest] != 0))
+ {
+ //
+ // Jump table to the appropriate handler.
+ //
+ g_ppfnUSBDStdRequests[pRequest->bRequest](pRequest);
+ }
+ else
+ {
+ //
+ // If there is no handler then stall this request.
+ //
+ USBBLStallEP0();
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// This is the low level interrupt handler for endpoint zero.
+//
+// This function handles all interrupts on endpoint zero in order to maintain
+// the state needed for the control endpoint on endpoint zero. In order to
+// successfully enumerate and handle all USB standard requests, all requests
+// on endpoint zero must pass through this function. The endpoint has the
+// following states: \b USB_STATE_IDLE, \b USB_STATE_TX, \b USB_STATE_RX,
+// \b USB_STATE_STALL, and \b USB_STATE_STATUS. In the \b USB_STATE_IDLE
+// state the USB controller has not received the start of a request, and once
+// it does receive the data for the request it will either enter the
+// \b USB_STATE_TX, \b USB_STATE_RX, or \b USB_STATE_STALL depending on the
+// command. If the controller enters the \b USB_STATE_TX or \b USB_STATE_RX
+// then once all data has been sent or received, it must pass through the
+// \b USB_STATE_STATUS state to allow the host to acknowledge completion of
+// the request. The \b USB_STATE_STALL is entered from \b USB_STATE_IDLE in
+// the event that the USB request was not valid. Both the \b USB_STATE_STALL
+// and \b USB_STATE_STATUS are transitional states that return to the
+// \b USB_STATE_IDLE state.
+//
+// \return None.
+//
+// USB_STATE_IDLE -*--> USB_STATE_TX -*-> USB_STATE_STATUS -*->USB_STATE_IDLE
+// | | |
+// |--> USB_STATE_RX - |
+// | |
+// |--> USB_STATE_STALL ---------->---------
+//
+// ----------------------------------------------------------------
+// | Current State | State 0 | State 1 |
+// | --------------------|-------------------|----------------------
+// | USB_STATE_IDLE | USB_STATE_TX/RX | USB_STATE_STALL |
+// | USB_STATE_TX | USB_STATE_STATUS | |
+// | USB_STATE_RX | USB_STATE_STATUS | |
+// | USB_STATE_STATUS | USB_STATE_IDLE | |
+// | USB_STATE_STALL | USB_STATE_IDLE | |
+// ----------------------------------------------------------------
+//
+//*****************************************************************************
+void
+USBDeviceEnumHandler(void)
+{
+ uint32_t ui32EPStatus;
+
+ //
+ // Get the TX portion of the endpoint status.
+ //
+ ui32EPStatus = HWREGH(USB0_BASE + EP_OFFSET(USB_EP_0) + USB_O_TXCSRL1);
+
+ //
+ // Get the RX portion of the endpoint status.
+ //
+ ui32EPStatus |=
+ ((HWREGH(USB0_BASE + EP_OFFSET(USB_EP_0) + USB_O_RXCSRL1)) <<
+ USB_RX_EPSTATUS_SHIFT);
+
+ //
+ // What state are we currently in?
+ //
+ switch(g_eUSBDEP0State)
+ {
+ //
+ // Handle the status state, this is a transitory state from
+ // USB_STATE_TX or USB_STATE_RX back to USB_STATE_IDLE.
+ //
+ case USB_STATE_STATUS:
+ {
+ //
+ // Just go back to the idle state.
+ //
+ g_eUSBDEP0State = USB_STATE_IDLE;
+
+ //
+ // If there is a pending address change then set the address.
+ //
+ if(g_sUSBDeviceState.ui32DevAddress & DEV_ADDR_PENDING)
+ {
+ //
+ // Clear the pending address change and set the address.
+ //
+ g_sUSBDeviceState.ui32DevAddress &= ~DEV_ADDR_PENDING;
+ HWREGB(USB0_BASE + USB_O_FADDR) =
+ (uint8_t)g_sUSBDeviceState.ui32DevAddress;
+ }
+
+ //
+ // If a new packet is already pending, we need to read it
+ // and handle whatever request it contains.
+ //
+ if(ui32EPStatus & USB_DEV_EP0_OUT_PKTRDY)
+ {
+ //
+ // Process the newly arrived packet.
+ //
+ USBDReadAndDispatchRequest();
+ }
+ break;
+ }
+
+ //
+ // In the IDLE state the code is waiting to receive data from the host.
+ //
+ case USB_STATE_IDLE:
+ {
+ //
+ // Is there a packet waiting for us?
+ //
+ if(ui32EPStatus & USB_DEV_EP0_OUT_PKTRDY)
+ {
+ //
+ // Yes - process it.
+ //
+ USBDReadAndDispatchRequest();
+ }
+ break;
+ }
+
+ //
+ // Data is still being sent to the host so handle this in the
+ // EP0StateTx() function.
+ //
+ case USB_STATE_TX:
+ {
+ USBDEP0StateTx();
+ break;
+ }
+
+ //
+ // Handle the receive state for commands that are receiving data on
+ // endpoint zero.
+ //
+ case USB_STATE_RX:
+ {
+ uint32_t ui32DataSize;
+
+ //
+ // Set the number of bytes to get out of this next packet.
+ //
+ if(g_sUSBDeviceState.ui32EP0DataRemain > EP0_MAX_PACKET_SIZE)
+ {
+ //
+ // Don't send more than EP0_MAX_PACKET_SIZE bytes.
+ //
+ ui32DataSize = EP0_MAX_PACKET_SIZE;
+ }
+ else
+ {
+ //
+ // There was space so send the remaining bytes.
+ //
+ ui32DataSize = g_sUSBDeviceState.ui32EP0DataRemain;
+ }
+
+ //
+ // Get the data from the USB controller end point 0.
+ //
+ USBEndpoint0DataGet(g_sUSBDeviceState.pui8EP0Data, &ui32DataSize);
+
+ //
+ // If there we not more that EP0_MAX_PACKET_SIZE or more bytes
+ // remaining then this transfer is complete. If there were exactly
+ // EP0_MAX_PACKET_SIZE remaining then there still needs to be
+ // null packet sent before this is complete.
+ //
+ if(g_sUSBDeviceState.ui32EP0DataRemain < EP0_MAX_PACKET_SIZE)
+ {
+ //
+ // Need to ack the data on end point 0 in this case
+ // without setting data end.
+ //
+ USBDevEndpoint0DataAck(true);
+
+ //
+ // Return to the idle state.
+ //
+ g_eUSBDEP0State = USB_STATE_IDLE;
+
+ //
+ // If there is a receive callback then call it.
+ //
+ if(g_sUSBDeviceState.ui32OUTDataSize != 0)
+ {
+ //
+ // Call the receive handler to handle the data
+ // that was received.
+ //
+ HandleEP0Data(g_sUSBDeviceState.ui32OUTDataSize);
+
+ //
+ // Indicate that there is no longer any data being waited
+ // on.
+ //
+ g_sUSBDeviceState.ui32OUTDataSize = 0;
+ }
+ }
+ else
+ {
+ //
+ // Need to ack the data on end point 0 in this case
+ // without setting data end.
+ //
+ USBDevEndpoint0DataAck(false);
+ }
+
+ //
+ // Advance the pointer.
+ //
+ g_sUSBDeviceState.pui8EP0Data += ui32DataSize;
+
+ //
+ // Decrement the number of bytes that are being waited on.
+ //
+ g_sUSBDeviceState.ui32EP0DataRemain -= ui32DataSize;
+
+ break;
+ }
+ //
+ // The device stalled endpoint zero so check if the stall needs to be
+ // cleared once it has been successfully sent.
+ //
+ case USB_STATE_STALL:
+ {
+ //
+ // If we sent a stall then acknowledge this interrupt.
+ //
+ if(ui32EPStatus & USB_DEV_EP0_SENT_STALL)
+ {
+ //
+ // Clear the stall condition.
+ //
+ HWREGB(USB0_BASE + USB_O_CSRL0) &= ~(USB_DEV_EP0_SENT_STALL);
+
+ //
+ // Reset the global end point 0 state to IDLE.
+ //
+ g_eUSBDEP0State = USB_STATE_IDLE;
+
+ }
+ break;
+ }
+ //
+ // Halt on an unknown state, but only in DEBUG mode builds.
+ //
+ default:
+ {
+#ifdef DEBUG
+ while(1);
+#endif
+ break;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// This function handles bus reset notifications.
+//
+// This function is called from the low level USB interrupt handler whenever
+// a bus reset is detected. It performs tidy-up as required and resets the
+// configuration back to defaults in preparation for descriptor queries from
+// the host.
+//
+// \return None.
+//
+//*****************************************************************************
+void
+USBDeviceEnumResetHandler(void)
+{
+ //
+ // Disable remote wakeup signalling (as per USB 2.0 spec 9.1.1.6).
+ //
+ g_sUSBDeviceState.ui8Status &= ~USB_STATUS_REMOTE_WAKE;
+ g_sUSBDeviceState.bRemoteWakeup = false;
+
+ //
+ // Call the device dependent code to indicate a bus reset has occurred.
+ //
+ HandleReset();
+
+ //
+ // Reset the default configuration identifier and alternate function
+ // selections.
+ //
+ g_sUSBDeviceState.ui32Configuration = DEFAULT_CONFIG_ID;
+ g_sUSBDeviceState.ui8AltSetting = 0;
+}
+
+//*****************************************************************************
+//
+// This function handles the GET_STATUS standard USB request.
+//
+// \param pUSBRequest holds the request type and endpoint number if endpoint
+// status is requested.
+//
+// This function handles responses to a Get Status request from the host
+// controller. A status request can be for the device, an interface or an
+// endpoint. If any other type of request is made this function will cause
+// a stall condition to indicate that the command is not supported. The
+// \e pUSBRequest structure holds the type of the request in the
+// bmRequestType field. If the type indicates that this is a request for an
+// endpoint's status, then the wIndex field holds the endpoint number.
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBDGetStatus(tUSBRequest *pUSBRequest)
+{
+ uint16_t ui16Data;
+
+ //
+ // Determine what type of status was requested.
+ //
+ switch(pUSBRequest->bmRequestType & USB_RTYPE_RECIPIENT_M)
+ {
+ //
+ // This was a Device Status request.
+ //
+ case USB_RTYPE_DEVICE:
+ {
+ //
+ // Return the current status for the device.
+ //
+ ui16Data = g_sUSBDeviceState.ui8Status;
+
+ break;
+ }
+
+ //
+ // This was a Interface status request.
+ //
+ case USB_RTYPE_INTERFACE:
+ {
+ //
+ // Interface status always returns 0.
+ //
+ ui16Data = 0;
+
+ break;
+ }
+
+ //
+ // This was an unknown request or a request for an endpoint (of which
+ // we have none) so set a stall.
+ //
+ case USB_RTYPE_ENDPOINT:
+ default:
+ {
+ //
+ // Anything else causes a stall condition to indicate that the
+ // command was not supported.
+ //
+ USBBLStallEP0();
+ return;
+ }
+ }
+
+ //
+ // Send the two byte status response.
+ //
+ g_sUSBDeviceState.ui32EP0DataRemain = 2;
+ g_sUSBDeviceState.pui8EP0Data = (uint8_t *)&ui16Data;
+
+ //
+ // Send the response.
+ //
+ USBDEP0StateTx();
+}
+
+//*****************************************************************************
+//
+// This function handles the CLEAR_FEATURE standard USB request.
+//
+// \param pUSBRequest holds the options for the Clear Feature USB request.
+//
+// This function handles device or endpoint clear feature requests. The
+// \e pUSBRequest structure holds the type of the request in the bmRequestType
+// field and the feature is held in the wValue field. For device, the only
+// clearable feature is the Remote Wake feature. This device request
+// should only be made if the descriptor indicates that Remote Wake is
+// implemented by the device. For endpoint requests the only clearable
+// feature is the ability to clear a halt on a given endpoint. If any other
+// requests are made, then the device will stall the request to indicate to
+// the host that the command was not supported.
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBDClearFeature(tUSBRequest *pUSBRequest)
+{
+ //
+ // Determine what type of status was requested.
+ //
+ switch(pUSBRequest->bmRequestType & USB_RTYPE_RECIPIENT_M)
+ {
+ //
+ // This is a clear feature request at the device level.
+ //
+ case USB_RTYPE_DEVICE:
+ {
+ //
+ // Only remote wake is clearable by this function.
+ //
+ if(USB_FEATURE_REMOTE_WAKE & pUSBRequest->wValue)
+ {
+ //
+ // Clear the remote wake up state.
+ //
+ g_sUSBDeviceState.ui8Status &= ~USB_STATUS_REMOTE_WAKE;
+
+ //
+ // Need to ack the data on end point 0.
+ //
+ USBDevEndpoint0DataAck(true);
+ }
+ else
+ {
+ USBBLStallEP0();
+ }
+ break;
+ }
+
+ //
+ // This is an unknown request or one destined for an invalid endpoint.
+ //
+ case USB_RTYPE_ENDPOINT:
+ default:
+ {
+ USBBLStallEP0();
+ return;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// This function handles the SET_FEATURE standard USB request.
+//
+// \param pUSBRequest holds the feature in the wValue field of the USB
+// request.
+//
+// This function handles device or endpoint set feature requests. The
+// \e pUSBRequest structure holds the type of the request in the bmRequestType
+// field and the feature is held in the wValue field. For device, the only
+// settable feature is the Remote Wake feature. This device request
+// should only be made if the descriptor indicates that Remote Wake is
+// implemented by the device. For endpoint requests the only settable feature
+// is the ability to issue a halt on a given endpoint. If any other requests
+// are made, then the device will stall the request to indicate to the host
+// that the command was not supported.
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBDSetFeature(tUSBRequest *pUSBRequest)
+{
+ //
+ // Determine what type of status was requested.
+ //
+ switch(pUSBRequest->bmRequestType & USB_RTYPE_RECIPIENT_M)
+ {
+ //
+ // This is a set feature request at the device level.
+ //
+ case USB_RTYPE_DEVICE:
+ {
+ //
+ // Only remote wake is setable by this function.
+ //
+ if(USB_FEATURE_REMOTE_WAKE & pUSBRequest->wValue)
+ {
+ //
+ // Set the remote wakeup state.
+ //
+ g_sUSBDeviceState.ui8Status |= USB_STATUS_REMOTE_WAKE;
+
+ //
+ // Need to ack the data on end point 0.
+ //
+ USBDevEndpoint0DataAck(true);
+ }
+ else
+ {
+ USBBLStallEP0();
+ }
+ break;
+ }
+
+ //
+ // This is an unknown request or one destined for an invalid endpoint.
+ //
+ case USB_RTYPE_ENDPOINT:
+ default:
+ {
+ USBBLStallEP0();
+ return;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// This function handles the SET_ADDRESS standard USB request.
+//
+// \param pUSBRequest holds the new address to use in the wValue field of the
+// USB request.
+//
+// This function is called to handle the change of address request from the
+// host controller. This can only start the sequence as the host must
+// acknowledge that the device has changed address. Thus this function sets
+// the address change as pending until the status phase of the request has
+// been completed successfully. This prevents the devices address from
+// changing and not properly responding to the status phase.
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBDSetAddress(tUSBRequest *pUSBRequest)
+{
+ //
+ // The data needs to be acknowledged on end point 0 without setting data
+ // end because there is no data coming.
+ //
+ USBDevEndpoint0DataAck(true);
+
+ //
+ // Save the device address as we cannot change address until the status
+ // phase is complete.
+ //
+ g_sUSBDeviceState.ui32DevAddress = pUSBRequest->wValue | DEV_ADDR_PENDING;
+
+ //
+ // Transition directly to the status state since there is no data phase
+ // for this request.
+ //
+ g_eUSBDEP0State = USB_STATE_STATUS;
+
+ //
+ // Clear the DFU status just in case we were in an error state last time
+ // the device was accessed and we were unplugged and replugged (for a self-
+ // powered implementation, of course).
+ //
+ HandleSetAddress();
+}
+
+//*****************************************************************************
+//
+// This function handles the GET_DESCRIPTOR standard USB request.
+//
+// \param pUSBRequest holds the data for this request.
+//
+// This function will return all configured standard USB descriptors to the
+// host - device, config and string descriptors. Any request for a descriptor
+// which is not available will result in endpoint 0 being stalled.
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBDGetDescriptor(tUSBRequest *pUSBRequest)
+{
+ uint32_t ui32Stall;
+
+ //
+ // Default to no stall.
+ //
+ ui32Stall = 0;
+
+ //
+ // Which descriptor are we being asked for?
+ //
+ switch(pUSBRequest->wValue >> 8)
+ {
+ //
+ // This request was for a device descriptor.
+ //
+ case USB_DTYPE_DEVICE:
+ {
+ //
+ // Return the externally provided device descriptor.
+ //
+ g_sUSBDeviceState.pui8EP0Data =
+ (uint8_t *)g_pui8DFUDeviceDescriptor;
+
+ //
+ // The size of the device descriptor is in the first byte.
+ //
+ g_sUSBDeviceState.ui32EP0DataRemain =
+ g_pui8DFUDeviceDescriptor[0];
+ break;
+ }
+
+ //
+ // This request was for a configuration descriptor.
+ //
+ case USB_DTYPE_CONFIGURATION:
+ {
+ uint8_t ui8Index;
+
+ //
+ // Which configuration are we being asked for?
+ //
+ ui8Index = (uint8_t)(pUSBRequest->wValue & 0xFF);
+
+ //
+ // Is this valid?
+ //
+ if(ui8Index != 0)
+ {
+ //
+ // This is an invalid configuration index. Stall EP0 to
+ // indicate a request error.
+ //
+ USBBLStallEP0();
+ g_sUSBDeviceState.pui8EP0Data = 0;
+ g_sUSBDeviceState.ui32EP0DataRemain = 0;
+ }
+ else
+ {
+ //
+ // Start by sending data from the beginning of the first
+ // descriptor.
+ //
+
+ g_sUSBDeviceState.pui8EP0Data =
+ (uint8_t *)g_pui8DFUConfigDescriptor;
+
+ //
+ // Get the size of the config descriptor (remembering that in
+ // this case, we only have a single section)
+ //
+ g_sUSBDeviceState.ui32EP0DataRemain =
+ *(uint16_t *)&(g_pui8DFUConfigDescriptor[2]);
+ }
+ break;
+ }
+
+ //
+ // This request was for a string descriptor.
+ //
+ case USB_DTYPE_STRING:
+ {
+ int32_t i32Index;
+
+ //
+ // Determine the correct descriptor index based on the requested
+ // language ID and index.
+ //
+ i32Index = USBDStringIndexFromRequest(pUSBRequest->wIndex,
+ pUSBRequest->wValue & 0xFF);
+
+ //
+ // If the mapping function returned -1 then stall the request to
+ // indicate that the request was not valid.
+ //
+ if(i32Index == -1)
+ {
+ USBBLStallEP0();
+ break;
+ }
+
+ //
+ // Return the externally specified configuration descriptor.
+ //
+ g_sUSBDeviceState.pui8EP0Data =
+ (uint8_t *)g_ppui8StringDescriptors[i32Index];
+
+ //
+ // The total size of a string descriptor is in byte 0.
+ //
+ g_sUSBDeviceState.ui32EP0DataRemain =
+ g_ppui8StringDescriptors[i32Index][0];
+
+ break;
+ }
+
+ //
+ // Any other request is not handled by the default enumeration handler
+ // so see if it needs to be passed on to another handler.
+ //
+ default:
+ {
+ //
+ // All other requests are not handled.
+ //
+ USBBLStallEP0();
+ ui32Stall = 1;
+ break;
+ }
+ }
+
+ //
+ // If there was no stall, ACK the data and see if data needs to be sent.
+ //
+ if(ui32Stall == 0)
+ {
+ //
+ // Need to ack the data on end point 0 in this case without
+ // setting data end.
+ //
+ USBDevEndpoint0DataAck(false);
+
+ //
+ // If this request has data to send, then send it.
+ //
+ if(g_sUSBDeviceState.pui8EP0Data)
+ {
+ //
+ // If there is more data to send than is requested then just
+ // send the requested amount of data.
+ //
+ if(g_sUSBDeviceState.ui32EP0DataRemain > pUSBRequest->wLength)
+ {
+ g_sUSBDeviceState.ui32EP0DataRemain = pUSBRequest->wLength;
+ }
+
+ //
+ // Now in the transmit data state. Be careful to call the correct
+ // function since we need to handle the config descriptor
+ // differently from the others.
+ //
+ USBDEP0StateTx();
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// This function determines which string descriptor to send to satisfy a
+// request for a given index and language.
+//
+// \param ui16Lang is the requested string language ID.
+// \param ui16Index is the requested string descriptor index.
+//
+// When a string descriptor is requested, the host provides a language ID and
+// index to identify the string ("give me string number 5 in French"). This
+// function maps these two parameters to an index within our device's string
+// descriptor array which is arranged as multiple groups of strings with
+// one group for each language advertised via string descriptor 0.
+//
+// We assume that there are an equal number of strings per language and
+// that the first descriptor is the language descriptor and use this fact to
+// perform the mapping.
+//
+// \return The index of the string descriptor to return or -1 if the string
+// could not be found.
+//
+//*****************************************************************************
+static int32_t
+USBDStringIndexFromRequest(uint16_t ui16Lang, uint16_t ui16Index)
+{
+ tString0Descriptor *pLang;
+ uint32_t ui32NumLangs;
+ uint32_t ui32NumStringsPerLang;
+ uint32_t ui32Loop;
+
+ //
+ // First look for the trivial case where descriptor 0 is being
+ // requested. This is the special case since descriptor 0 contains the
+ // language codes supported by the device.
+ //
+ if(ui16Index == 0)
+ {
+ return(0);
+ }
+
+ //
+ // How many languages does this device support? This is determined by
+ // looking at the length of the first descriptor in the string table,
+ // subtracting 2 for the header and dividing by two (the size of each
+ // language code).
+ //
+ ui32NumLangs = (g_ppui8StringDescriptors[0][0] - 2) / 2;
+
+ //
+ // We assume that the table includes the same number of strings for each
+ // supported language. We know the number of entries in the string table,
+ // so how many are there for each language? This may seem an odd way to
+ // do this (why not just have the application tell us in the device info
+ // structure?) but it's needed since we didn't want to change the API
+ // after the first release which did not support multiple languages.
+ //
+ ui32NumStringsPerLang = ((NUM_STRING_DESCRIPTORS - 1) / ui32NumLangs);
+
+ //
+ // Just to be sure, make sure that the calculation indicates an equal
+ // number of strings per language. We expect the string table to contain
+ // (1 + (strings_per_language * languages)) entries.
+ //
+ if((1 + (ui32NumStringsPerLang * ui32NumLangs)) != NUM_STRING_DESCRIPTORS)
+ {
+ return(-1);
+ }
+
+ //
+ // Now determine which language we are looking for. It is assumed that
+ // the order of the groups of strings per language in the table is the
+ // same as the order of the language IDs listed in the first descriptor.
+ //
+ pLang = (tString0Descriptor *)(g_ppui8StringDescriptors[0]);
+
+ //
+ // Look through the supported languages looking for the one we were asked
+ // for.
+ //
+ for(ui32Loop = 0; ui32Loop < ui32NumLangs; ui32Loop++)
+ {
+ //
+ // Have we found the requested language?
+ //
+ if(pLang->wLANGID[ui32Loop] == ui16Lang)
+ {
+ //
+ // Yes - calculate the index of the descriptor to send.
+ //
+ return((ui32NumStringsPerLang * ui32Loop) + ui16Index);
+ }
+ }
+
+ //
+ // If we drop out of the loop, the requested language was not found so
+ // return -1 to indicate the error.
+ //
+ return(-1);
+}
+
+//*****************************************************************************
+//
+// This function handles the SET_DESCRIPTOR standard USB request.
+//
+// \param pUSBRequest holds the data for this request.
+//
+// This function currently is not supported and will respond with a Stall
+// to indicate that this command is not supported by the device.
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBDSetDescriptor(tUSBRequest *pUSBRequest)
+{
+ //
+ // This function is not handled by default.
+ //
+ USBBLStallEP0();
+}
+
+//*****************************************************************************
+//
+// This function handles the GET_CONFIGURATION standard USB request.
+//
+// \param pUSBRequest holds the data for this request.
+//
+// This function responds to a host request to return the current
+// configuration of the USB device. The function will send the configuration
+// response to the host and return. This value will either be 0 or the last
+// value received from a call to SetConfiguration().
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBDGetConfiguration(tUSBRequest *pUSBRequest)
+{
+ uint8_t ui8Value;
+
+ //
+ // If we still have an address pending then the device is still not
+ // configured.
+ //
+ if(g_sUSBDeviceState.ui32DevAddress & DEV_ADDR_PENDING)
+ {
+ ui8Value = 0;
+ }
+ else
+ {
+ ui8Value = (uint8_t)g_sUSBDeviceState.ui32Configuration;
+ }
+
+ g_sUSBDeviceState.ui32EP0DataRemain = 1;
+ g_sUSBDeviceState.pui8EP0Data = &ui8Value;
+
+ //
+ // Send the single byte response.
+ //
+ USBDEP0StateTx();
+}
+
+//*****************************************************************************
+//
+// This function handles the SET_CONFIGURATION standard USB request.
+//
+// \param pUSBRequest holds the data for this request.
+//
+// This function responds to a host request to change the current
+// configuration of the USB device. The actual configuration number is taken
+// from the structure passed in via \e pUSBRequest.
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBDSetConfiguration(tUSBRequest *pUSBRequest)
+{
+ //
+ // Cannot set the configuration to one that does not exist so check the
+ // enumeration structure to see how many valid configurations are present.
+ //
+ if(pUSBRequest->wValue > 1)
+ {
+ //
+ // The passed configuration number is not valid. Stall the endpoint to
+ // signal the error to the host.
+ //
+ USBBLStallEP0();
+ }
+ else
+ {
+ //
+ // Need to ack the data on end point 0.
+ //
+ USBDevEndpoint0DataAck(true);
+
+ //
+ // Save the configuration.
+ //
+ g_sUSBDeviceState.ui32Configuration = pUSBRequest->wValue;
+
+ //
+ // If passed a configuration other than 0 (which tells us that we are
+ // not currently configured), configure the endpoints (other than EP0)
+ // appropriately.
+ //
+ if(g_sUSBDeviceState.ui32Configuration)
+ {
+ //
+ // Set the power state
+ //
+#if USB_BUS_POWERED
+ g_sUSBDeviceState.ui8Status &= ~USB_STATUS_SELF_PWR;
+#else
+ g_sUSBDeviceState.ui8Status |= USB_STATUS_SELF_PWR;
+#endif
+ }
+
+ //
+ // Do whatever needs to be done as a result of the config change.
+ //
+ HandleConfigChange(g_sUSBDeviceState.ui32Configuration);
+ }
+}
+
+//*****************************************************************************
+//
+// This function handles the GET_INTERFACE standard USB request.
+//
+// \param pUSBRequest holds the data for this request.
+//
+// This function is called when the host controller request the current
+// interface that is in use by the device. This simply returns the value set
+// by the last call to SetInterface().
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBDGetInterface(tUSBRequest *pUSBRequest)
+{
+ uint8_t ui8Value;
+
+ //
+ // If we still have an address pending then the device is still not
+ // configured.
+ //
+ if(g_sUSBDeviceState.ui32DevAddress & DEV_ADDR_PENDING)
+ {
+ ui8Value = 0;
+ }
+ else
+ {
+ //
+ // Is the interface number valid?
+ //
+ if(pUSBRequest->wIndex == 0)
+ {
+ //
+ // Read the current alternate setting for the required interface.
+ //
+ ui8Value = g_sUSBDeviceState.ui8AltSetting;
+ }
+ else
+ {
+ //
+ // An invalid interface number was specified.
+ //
+ USBBLStallEP0();
+ return;
+ }
+ }
+
+ //
+ // Send the single byte response.
+ //
+ g_sUSBDeviceState.ui32EP0DataRemain = 1;
+ g_sUSBDeviceState.pui8EP0Data = &ui8Value;
+
+ //
+ // Send the single byte response.
+ //
+ USBDEP0StateTx();
+}
+
+//*****************************************************************************
+//
+// This function handles the SET_INTERFACE standard USB request.
+//
+// \param pUSBRequest holds the data for this request.
+//
+// The DFU device supports a single interface with no alternate settings so
+// this handler is hardcoded assuming this configuration.
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBDSetInterface(tUSBRequest *pUSBRequest)
+{
+ if((pUSBRequest->wIndex == 0) && (pUSBRequest->wValue == 0))
+ {
+ //
+ // We were passed a valid interface number so acknowledge the request.
+ //
+ USBDevEndpoint0DataAck(true);
+ }
+ else
+ {
+ //
+ // The values passed were not valid so stall endpoint 0.
+ //
+ USBBLStallEP0();
+ }
+}
+
+//*****************************************************************************
+//
+// This internal function handles sending data on endpoint zero.
+//
+// \return None.
+//
+//*****************************************************************************
+static void
+USBDEP0StateTx(void)
+{
+ uint32_t ui32NumBytes;
+ uint8_t *pui8Data;
+
+ //
+ // In the TX state on endpoint zero.
+ //
+ g_eUSBDEP0State = USB_STATE_TX;
+
+ //
+ // Set the number of bytes to send this iteration.
+ //
+ ui32NumBytes = g_sUSBDeviceState.ui32EP0DataRemain;
+
+ //
+ // Limit individual transfers to 64 bytes.
+ //
+ if(ui32NumBytes > EP0_MAX_PACKET_SIZE)
+ {
+ ui32NumBytes = EP0_MAX_PACKET_SIZE;
+ }
+
+ //
+ // Save the pointer so that it can be passed to the USBEndpointDataPut()
+ // function.
+ //
+ pui8Data = g_sUSBDeviceState.pui8EP0Data;
+
+ //
+ // Advance the data pointer and counter to the next data to be sent.
+ //
+ g_sUSBDeviceState.ui32EP0DataRemain -= ui32NumBytes;
+ g_sUSBDeviceState.pui8EP0Data += ui32NumBytes;
+
+ //
+ // Put the data in the correct FIFO.
+ //
+ USBEndpoint0DataPut(pui8Data, ui32NumBytes);
+
+ //
+ // If this is exactly 64 then don't set the last packet yet.
+ //
+ if(ui32NumBytes == EP0_MAX_PACKET_SIZE)
+ {
+ //
+ // There is more data to send or exactly 64 bytes were sent, this
+ // means that there is either more data coming or a null packet needs
+ // to be sent to complete the transaction.
+ //
+ USBEndpoint0DataSend(USB_TRANS_IN);
+ }
+ else
+ {
+ //
+ // Now go to the status state and wait for the transmit to complete.
+ //
+ g_eUSBDEP0State = USB_STATE_STATUS;
+
+ //
+ // Send the last bit of data.
+ //
+ USBEndpoint0DataSend(USB_TRANS_IN_LAST);
+ g_sUSBDeviceState.ui32OUTDataSize = 0;
+ }
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+#endif // USB_ENABLE_UPDATE
diff --git a/boot_loader/bl_usbfuncs.h b/boot_loader/bl_usbfuncs.h new file mode 100644 index 0000000..7c3868c --- /dev/null +++ b/boot_loader/bl_usbfuncs.h @@ -0,0 +1,505 @@ +//*****************************************************************************
+//
+// bl_usbfuncs.h - Prototypes for the subset of USB library functions used in
+// the USB DFU boot loader.
+//
+// Copyright (c) 2008-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.
+//
+//*****************************************************************************
+
+#ifndef __BL_USBFUNCS_H__
+#define __BL_USBFUNCS_H__
+
+//*****************************************************************************
+//
+//! \addtogroup bl_usb_api
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// If building with a C++ compiler, make all of the definitions in this header
+// have a C binding.
+//
+//*****************************************************************************
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+//*****************************************************************************
+//
+// The following macro allows compiler-independent syntax to be used to
+// define packed structures. A typical structure definition using these
+// macros will look similar to the following example:
+//
+// #ifdef ewarm
+// #pragma pack(1)
+// #endif
+//
+// typedef struct _PackedStructName
+// {
+// uint32_t ui32FirstField;
+// int8_t i8CharMember;
+// uint16_t ui16Short;
+// }
+// PACKED tPackedStructName;
+//
+// #ifdef ewarm
+// #pragma pack()
+// #endif
+//
+// The conditional blocks related to ewarm include the #pragma pack() lines
+// only if the IAR Embedded Workbench compiler is being used. Unfortunately,
+// it is not possible to emit a #pragma from within a macro definition so this
+// must be done explicitly.
+//
+//*****************************************************************************
+#if defined(ccs) || \
+ defined(codered) || \
+ defined(gcc) || \
+ defined(rvmdk) || \
+ defined(__ARMCC_VERSION) || \
+ defined(sourcerygxx)
+#define PACKED __attribute__ ((packed))
+#elif defined(ewarm)
+#define PACKED
+#else
+#error Unrecognized COMPILER!
+#endif
+
+//*****************************************************************************
+//
+// Standard USB descriptor types. These values are passed in the upper bytes
+// of tUSBRequest.wValue on USBREQ_GET_DESCRIPTOR and also appear in the
+// bDescriptorType field of standard USB descriptors.
+//
+//*****************************************************************************
+#define USB_DTYPE_DEVICE 1
+#define USB_DTYPE_CONFIGURATION 2
+#define USB_DTYPE_STRING 3
+#define USB_DTYPE_INTERFACE 4
+#define USB_DTYPE_ENDPOINT 5
+#define USB_DTYPE_DEVICE_QUAL 6
+#define USB_DTYPE_OSPEED_CONF 7
+#define USB_DTYPE_INTERFACE_PWR 8
+
+#define USBShort(ui16Value) (ui16Value & 0xff), (ui16Value >> 8)
+
+#define USB_LANG_EN_US 0x0409 // English (United States)
+
+#define USB_EP_DEV_IN 0x00002000 // Device IN endpoint
+#define USB_EP_DEV_OUT 0x00001000 // Device OUT endpoint
+
+//*****************************************************************************
+//
+// All structures defined in this section of the header require byte packing of
+// fields. This is usually accomplished using the PACKED macro but, for IAR
+// Embedded Workbench, this requires a pragma.
+//
+//*****************************************************************************
+#ifdef ewarm
+#pragma pack(1)
+#endif
+
+//*****************************************************************************
+//
+// Definitions related to standard USB device requests (sections 9.3 & 9.4)
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! The standard USB request header as defined in section 9.3 of the USB 2.0
+//! specification.
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! Determines the type and direction of the request.
+ //
+ uint8_t bmRequestType;
+
+ //
+ //! Identifies the specific request being made.
+ //
+ uint8_t bRequest;
+
+ //
+ //! Word-sized field that varies according to the request.
+ //
+ uint16_t wValue;
+
+ //
+ //! Word-sized field that varies according to the request; typically used
+ //! to pass an index or offset.
+ //
+ uint16_t wIndex;
+
+ //
+ //! The number of bytes to transfer if there is a data stage to the
+ //! request.
+ //
+ uint16_t wLength;
+}
+PACKED tUSBRequest;
+
+//*****************************************************************************
+//
+// The following defines are used with the bmRequestType member of tUSBRequest.
+//
+// Request types have 3 bit fields:
+// 4:0 - Is the recipient type.
+// 6:5 - Is the request type.
+// 7 - Is the direction of the request.
+//
+//*****************************************************************************
+#define USB_RTYPE_DIR_IN 0x80
+#define USB_RTYPE_DIR_OUT 0x00
+
+#define USB_RTYPE_TYPE_M 0x60
+#define USB_RTYPE_VENDOR 0x40
+#define USB_RTYPE_CLASS 0x20
+#define USB_RTYPE_STANDARD 0x00
+
+#define USB_RTYPE_RECIPIENT_M 0x1f
+#define USB_RTYPE_OTHER 0x03
+#define USB_RTYPE_ENDPOINT 0x02
+#define USB_RTYPE_INTERFACE 0x01
+#define USB_RTYPE_DEVICE 0x00
+
+//*****************************************************************************
+//
+// Standard USB requests IDs used in the bRequest field of tUSBRequest.
+//
+//*****************************************************************************
+#define USBREQ_GET_STATUS 0x00
+#define USBREQ_CLEAR_FEATURE 0x01
+#define USBREQ_SET_FEATURE 0x03
+#define USBREQ_SET_ADDRESS 0x05
+#define USBREQ_GET_DESCRIPTOR 0x06
+#define USBREQ_SET_DESCRIPTOR 0x07
+#define USBREQ_GET_CONFIG 0x08
+#define USBREQ_SET_CONFIG 0x09
+#define USBREQ_GET_INTERFACE 0x0a
+#define USBREQ_SET_INTERFACE 0x0b
+#define USBREQ_SYNC_FRAME 0x0c
+
+//*****************************************************************************
+//
+// Data returned from a USBREQ_GET_STATUS request to a device.
+//
+//*****************************************************************************
+#define USB_STATUS_SELF_PWR 0x0001 // Currently self powered.
+#define USB_STATUS_BUS_PWR 0x0000 // Currently bus-powered.
+#define USB_STATUS_PWR_M 0x0001 // Mask for power mode.
+#define USB_STATUS_REMOTE_WAKE 0x0002 // Remote wake-up is currently enabled.
+
+
+//*****************************************************************************
+//
+//! This structure describes the USB configuration descriptor as defined in
+//! USB 2.0 specification section 9.6.3. This structure also applies to the
+//! USB other speed configuration descriptor defined in section 9.6.4.
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! The length of this descriptor in bytes. All configuration descriptors
+ //! are 9 bytes long.
+ //
+ uint8_t bLength;
+
+ //
+ //! The type of the descriptor. For a configuration descriptor, this will
+ //! be USB_DTYPE_CONFIGURATION (2).
+ //
+ uint8_t bDescriptorType;
+
+ //
+ //! The total length of data returned for this configuration. This
+ //! includes the combined length of all descriptors (configuration,
+ //! interface, endpoint and class- or vendor-specific) returned for this
+ //! configuration.
+ //
+ uint16_t wTotalLength;
+
+ //
+ //! The number of interface supported by this configuration.
+ //
+ uint8_t bNumInterfaces;
+
+ //
+ //! The value used as an argument to the SetConfiguration standard request
+ //! to select this configuration.
+ //
+ uint8_t bConfigurationValue;
+
+ //
+ //! The index of a string descriptor describing this configuration.
+ //
+ uint8_t iConfiguration;
+
+ //
+ //! Attributes of this configuration.
+ //
+ uint8_t bmAttributes;
+
+ //
+ //! The maximum power consumption of the USB device from the bus in this
+ //! configuration when the device is fully operational. This is expressed
+ //! in units of 2mA so, for example, 100 represents 200mA.
+ //
+ uint8_t bMaxPower;
+}
+PACKED tConfigDescriptor;
+
+//*****************************************************************************
+//
+// Flags used in constructing the value assigned to the field
+// tConfigDescriptor.bmAttributes. Note that bit 7 is reserved and must be set
+// to 1.
+//
+//*****************************************************************************
+#define USB_CONF_ATTR_PWR_M 0xC0
+
+#define USB_CONF_ATTR_SELF_PWR 0xC0
+#define USB_CONF_ATTR_BUS_PWR 0x80
+#define USB_CONF_ATTR_RWAKE 0xA0
+
+//*****************************************************************************
+//
+// Feature Selectors (tUSBRequest.wValue) passed on USBREQ_CLEAR_FEATURE and
+// USBREQ_SET_FEATURE.
+//
+//*****************************************************************************
+#define USB_FEATURE_EP_HALT 0x0000 // Endpoint halt feature.
+#define USB_FEATURE_REMOTE_WAKE 0x0001 // Remote wake feature, device only.
+#define USB_FEATURE_TEST_MODE 0x0002 // Test mode
+
+//*****************************************************************************
+//
+//! This structure describes the USB string descriptor for index 0 as defined
+//! in USB 2.0 specification section 9.6.7. Note that the number of language
+//! IDs is variable and can be determined by examining bLength. The number of
+//! language IDs present in the descriptor is given by ((bLength - 2) / 2).
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! The length of this descriptor in bytes. This value will vary
+ //! depending upon the number of language codes provided in the descriptor.
+ //
+ uint8_t bLength;
+
+ //
+ //! The type of the descriptor. For a string descriptor, this will be
+ //! USB_DTYPE_STRING (3).
+ //
+ uint8_t bDescriptorType;
+
+ //
+ //! The language code (LANGID) for the first supported language. Note that
+ //! this descriptor may support multiple languages, in which case, the
+ //! number of elements in the wLANGID array will increase and bLength will
+ //! be updated accordingly.
+ //
+ uint16_t wLANGID[1];
+}
+PACKED tString0Descriptor;
+
+//*****************************************************************************
+//
+//! This structure describes the USB string descriptor for all string indexes
+//! other than 0 as defined in USB 2.0 specification section 9.6.7.
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! The length of this descriptor in bytes. This value will be 2 greater
+ //! than the number of bytes comprising the UNICODE string that the
+ //! descriptor contains.
+ //
+ uint8_t bLength;
+
+ //
+ //! The type of the descriptor. For a string descriptor, this will be
+ //! USB_DTYPE_STRING (3).
+ //
+ uint8_t bDescriptorType;
+
+ //
+ //! The first byte of the UNICODE string. This string is not NULL
+ //! terminated. Its length (in bytes) can be computed by subtracting 2
+ //! from the value in the bLength field.
+ //
+ uint8_t bString;
+}
+PACKED tStringDescriptor;
+
+//*****************************************************************************
+//
+// Return to default packing when using the IAR Embedded Workbench compiler.
+//
+//*****************************************************************************
+#ifdef ewarm
+#pragma pack()
+#endif
+
+//*****************************************************************************
+//
+// Some standard USB class definitions.
+//
+//*****************************************************************************
+#define USB_CLASS_APP_SPECIFIC 0xfe
+#define USB_CLASS_VEND_SPECIFIC 0xff
+
+//*****************************************************************************
+//
+// The following are values that are returned from USBEndpointStatus(). The
+// USB_HOST_* values are used when the USB controller is in host mode and the
+// USB_DEV_* values are used when the USB controller is in device mode.
+//
+//*****************************************************************************
+#define USB_DEV_RX_SENT_STALL 0x00400000 // Stall was sent on this endpoint
+#define USB_DEV_RX_DATA_ERROR 0x00080000 // CRC error on the data
+#define USB_DEV_RX_OVERRUN 0x00040000 // OUT packet was not loaded due to
+ // a full FIFO
+#define USB_DEV_RX_FIFO_FULL 0x00020000 // RX FIFO full
+#define USB_DEV_RX_PKT_RDY 0x00010000 // Data packet ready
+#define USB_DEV_TX_NOT_COMP 0x00000080 // Large packet split up, more data
+ // to come
+#define USB_DEV_TX_SENT_STALL 0x00000020 // Stall was sent on this endpoint
+#define USB_DEV_TX_UNDERRUN 0x00000004 // IN received with no data ready
+#define USB_DEV_TX_FIFO_NE 0x00000002 // The TX FIFO is not empty
+#define USB_DEV_TX_TXPKTRDY 0x00000001 // Transmit still being transmitted
+#define USB_DEV_EP0_SETUP_END 0x00000010 // Control transaction ended before
+ // Data End seen
+#define USB_DEV_EP0_SENT_STALL 0x00000004 // Stall was sent on this endpoint
+#define USB_DEV_EP0_IN_PKTPEND 0x00000002 // Transmit data packet pending
+#define USB_DEV_EP0_OUT_PKTRDY 0x00000001 // Receive data packet ready
+
+//*****************************************************************************
+//
+// This value specifies the maximum size of transfers on endpoint 0 as 64
+// bytes. This value is fixed in hardware as the FIFO size for endpoint 0.
+//
+//*****************************************************************************
+#define MAX_PACKET_SIZE_EP0 64
+
+//*****************************************************************************
+//
+// These values are used to indicate which endpoint to access.
+//
+//*****************************************************************************
+#define USB_EP_0 0x00000000 // Endpoint 0
+#define NUM_USB_EP 4 // Number of supported endpoints
+
+//*****************************************************************************
+//
+// These macros allow conversion between 0-based endpoint indices and the
+// USB_EP_x values required when calling various USB APIs.
+//
+//*****************************************************************************
+#define INDEX_TO_USB_EP(x) ((x) << 4)
+#define USB_EP_TO_INDEX(x) ((x) >> 4)
+
+//*****************************************************************************
+//
+// The following are values that can be passed to USBEndpointDataSend() as the
+// ui32TransType parameter.
+//
+//*****************************************************************************
+#define USB_TRANS_OUT 0x00000102 // Normal OUT transaction
+#define USB_TRANS_IN 0x00000102 // Normal IN transaction
+#define USB_TRANS_IN_LAST 0x0000010a // Final IN transaction (for
+ // endpoint 0 in device mode)
+#define USB_TRANS_SETUP 0x0000110a // Setup transaction (for endpoint
+ // 0)
+#define USB_TRANS_STATUS 0x00000142 // Status transaction (for endpoint
+ // 0)
+
+//*****************************************************************************
+//
+// Function prototype for any standard USB request.
+//
+//*****************************************************************************
+typedef void (* tStdRequest)(tUSBRequest *psUSBRequest);
+
+//*****************************************************************************
+//
+// Data structures defined in bl_usb.c but referenced elsewhere.
+//
+//*****************************************************************************
+extern const uint8_t g_pui8DFUConfigDescriptor[];
+extern const uint8_t g_pui8DFUDeviceDescriptor[];
+extern const uint8_t * const g_ppui8StringDescriptors[];
+
+#define NUM_STRING_DESCRIPTORS 4
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Prototypes of the various USB handler functions.
+//
+//*****************************************************************************
+extern void HandleRequests(tUSBRequest *psUSBRequest);
+extern void HandleConfigChange(uint32_t ui32Info);
+extern void HandleEP0Data(uint32_t ui32Info);
+extern void HandleReset(void);
+extern void HandleDisconnect(void);
+extern void HandleSetAddress(void);
+
+//*****************************************************************************
+//
+// Prototypes for the APIs.
+//
+//*****************************************************************************
+extern void USBDevEndpoint0DataAck(bool bIsLastPacket);
+extern int32_t USBEndpoint0DataGet(uint8_t *pui8Data, uint32_t *pui32Size);
+extern int32_t USBEndpoint0DataPut(uint8_t *pui8Data, uint32_t ui32Size);
+extern int32_t USBEndpoint0DataSend(uint32_t ui32TransType);
+extern void USBBLInit(void);
+extern void USBBLStallEP0(void);
+extern void USBBLRequestDataEP0(uint8_t *pui8Data, uint32_t ui32Size);
+extern void USBBLSendDataEP0(uint8_t *pui8Data, uint32_t ui32Size);
+extern void USBDeviceEnumHandler(void);
+extern void USBDeviceEnumResetHandler(void);
+
+//*****************************************************************************
+//
+// Mark the end of the C bindings section for C++ compilers.
+//
+//*****************************************************************************
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __BL_USBFUNCS_H__
diff --git a/boot_loader/readme.txt b/boot_loader/readme.txt new file mode 100644 index 0000000..6c37d28 --- /dev/null +++ b/boot_loader/readme.txt @@ -0,0 +1,28 @@ +Boot Loader
+
+The boot loader is a small piece of code that can be programmed at the
+beginning of flash to act as an application loader as well as an update
+mechanism for an application running on a Tiva microcontroller, utilizing
+either UART0, I2C0, SSI0, Ethernet or USB. The capabilities of the boot loader
+are configured via the bl_config.h include file (which is located in the
+application directory, not in the boot loader source directory).
+
+-------------------------------------------------------------------------------
+
+Copyright (c) 2007-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.
diff --git a/boot_loader/uip-conf.h b/boot_loader/uip-conf.h new file mode 100644 index 0000000..5c1d770 --- /dev/null +++ b/boot_loader/uip-conf.h @@ -0,0 +1,108 @@ +//*****************************************************************************
+//
+// uip-conf.h - uIP configuration for the boot loader.
+//
+// Copyright (c) 2007-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.
+//
+//*****************************************************************************
+
+#ifndef __UIP_CONF_H__
+#define __UIP_CONF_H__
+
+//*****************************************************************************
+//
+// This typedef defines the 8-bit type used throughout uIP.
+//
+//*****************************************************************************
+typedef uint8_t u8_t;
+
+//*****************************************************************************
+//
+// This typedef defines the 16-bit type used throughout uIP.
+//
+//*****************************************************************************
+typedef uint16_t u16_t;
+
+//*****************************************************************************
+//
+// This typedef defines the dataype used for keeping statistics in uIP.
+//
+//*****************************************************************************
+typedef uint16_t uip_stats_t;
+
+//*****************************************************************************
+//
+// Turn off TCP support.
+//
+//*****************************************************************************
+#define UIP_CONF_TCP 0
+
+//*****************************************************************************
+//
+// Turn on UDP support.
+//
+//*****************************************************************************
+#define UIP_CONF_UDP 1
+
+//*****************************************************************************
+//
+// Only support a single UDP connection.
+//
+//*****************************************************************************
+#define UIP_CONF_UDP_CONNS 1
+
+//*****************************************************************************
+//
+// Only support a single entry in the ARP table.
+//
+//*****************************************************************************
+#define UIP_CONF_ARPTAB_SIZE 1
+
+//*****************************************************************************
+//
+// Set the size of the uIP packet data buffer.
+//
+//*****************************************************************************
+#define UIP_CONF_BUFFER_SIZE 1600//700
+
+//*****************************************************************************
+//
+// Enable UDP broadcast support.
+//
+//*****************************************************************************
+#define UIP_CONF_BROADCAST 1
+
+//*****************************************************************************
+//
+// Define a data type for the UDP application state. This is not used, but
+// must be defined for uIP.
+//
+//*****************************************************************************
+typedef uint32_t uip_udp_appstate_t;
+
+//*****************************************************************************
+//
+// The name of the function to be called when UDP packets arrive, or when the
+// UDP periodic timer expires.
+//
+//*****************************************************************************
+extern char BOOTPThread(void);
+#define UIP_UDP_APPCALL BOOTPThread
+
+#endif // __UIP_CONF_H__
diff --git a/boot_loader/usbdfu.h b/boot_loader/usbdfu.h new file mode 100644 index 0000000..3ae00e1 --- /dev/null +++ b/boot_loader/usbdfu.h @@ -0,0 +1,420 @@ +//*****************************************************************************
+//
+// usbdfu.h - Definitions related to the USB Device Firmware Upgrade class.
+//
+// Copyright (c) 2008-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.
+//
+//*****************************************************************************
+
+#ifndef __USBDFU_H__
+#define __USBDFU_H__
+
+//*****************************************************************************
+//
+// DFU attributes as published in the functional descriptor.
+//
+//*****************************************************************************
+#define DFU_ATTR_WILL_DETACH 0x08
+#define DFU_ATTR_MANIFEST_TOLERANT \
+ 0x04
+#define DFU_ATTR_CAN_UPLOAD 0x02
+#define DFU_ATTR_CAN_DOWNLOAD 0x01
+
+//*****************************************************************************
+//
+// The states that the DFU device can be in. These values are reported to
+// the host in response to a USBD_DFU_REQUEST_GETSTATE request.
+//
+//*****************************************************************************
+typedef enum
+{
+ STATE_APP_IDLE = 0,
+ STATE_APP_DETACH,
+ STATE_IDLE,
+ STATE_DNLOAD_SYNC,
+ STATE_DNBUSY,
+ STATE_DNLOAD_IDLE,
+ STATE_MANIFEST_SYNC,
+ STATE_MANIFEST,
+ STATE_MANIFEST_WAIT_RESET,
+ STATE_UPLOAD_IDLE,
+ STATE_ERROR
+}
+tDFUState;
+
+//*****************************************************************************
+//
+// The current error status of the DFU device. These values are reported to
+// the host in response to a USBD_DFU_REQUEST_GETSTATUS request.
+//
+//*****************************************************************************
+typedef enum
+{
+ STATUS_OK = 0,
+ STATUS_ERR_TARGET,
+ STATUS_ERR_FILE,
+ STATUS_ERR_WRITE,
+ STATUS_ERR_ERASE,
+ STATUS_ERR_CHECK_ERASED,
+ STATUS_ERR_PROG,
+ STATUS_ERR_VERIFY,
+ STATUS_ERR_ADDRESS,
+ STATUS_ERR_NOTDONE,
+ STATUS_ERR_FIRMWARE,
+ STATUS_ERR_VENDOR,
+ STATUS_ERR_USBR,
+ STATUS_ERR_POR,
+ STATUS_ERR_UNKNOWN,
+ STATUS_ERR_STALLEDPKT
+}
+tDFUStatus;
+
+//*****************************************************************************
+//
+// The descriptor type for the DFU functional descriptor.
+//
+//*****************************************************************************
+#define USB_DFU_FUNC_DESCRIPTOR_TYPE 0x21
+
+//*****************************************************************************
+//
+// The subclass identifier for DFU as reported to the host in the
+// bInterfaceSubClass field of the DFU interface descriptor.
+//
+//*****************************************************************************
+#define USB_DFU_SUBCLASS 0x01
+
+//*****************************************************************************
+//
+// The protocol identifier for DFU as reported to the host in the
+// bInterfaceProtocol field of the DFU interface descriptor.
+//
+//*****************************************************************************
+#define USB_DFU_PROTOCOL 0x02
+#define USB_DFU_RUNTIME_PROTOCOL 0x01
+
+//*****************************************************************************
+//
+// DFU class-specific request identifiers.
+//
+//*****************************************************************************
+#define USBD_DFU_REQUEST_DETACH 0
+#define USBD_DFU_REQUEST_DNLOAD 1
+#define USBD_DFU_REQUEST_UPLOAD 2
+#define USBD_DFU_REQUEST_GETSTATUS 3
+#define USBD_DFU_REQUEST_CLRSTATUS 4
+#define USBD_DFU_REQUEST_GETSTATE 5
+#define USBD_DFU_REQUEST_ABORT 6
+
+//*****************************************************************************
+//
+// Request 1KB blocks from the host. This value is published in the USB
+// functional descriptor.
+//
+//*****************************************************************************
+#define DFU_TRANSFER_SIZE 1024
+
+//*****************************************************************************
+//
+// TIVA-specific request identifier. This is used to determine whether
+// the target device supports our DFU command protocol. It is expected that
+// a device not supporting our extensions will stall this request. This
+// request is only supported while the DFU device is in STATE_IDLE.
+//
+// An IN request containing the following parameters will result in the device
+// sending back a tDFUQueryTIVAProtocol structure indicating that
+// TIVA extensions are supported. The actual values in wValue and wIndex
+// have no meaning other than to act as markers in the unlikely event that
+// another DFU device also chooses to use request ID 0x42 for some other
+// purpose.
+//
+// wValue - 0x23(REQUEST_TIVA_VALUE)
+// wIndex - Interface number
+// wLength - sizeof(tDFUQueryTIVAProtocol)
+//
+//*****************************************************************************
+#define USBD_DFU_REQUEST_TIVA 0x42
+#define REQUEST_TIVA_VALUE 0x23
+
+#define DFU_PROTOCOL_USBLIB_MARKER \
+ 0x4C4D
+#define DFU_PROTOCOL_USBLIB_VERSION_1 \
+ 0x0001
+
+#ifdef ewarm
+#pragma pack(1)
+#endif
+
+//*****************************************************************************
+//
+// The structure sent to the host when a valid USBD_DFU_REQUEST_TIVA is
+// received while the DFU device is in idle state.
+//
+//*****************************************************************************
+typedef struct
+{
+ uint16_t ui16Marker; // DFU_PROTOCOL_USBLIB_MARKER
+ uint16_t ui16Version; // DFU_PROTOCOL_USBLIB_VERSION_1
+}
+PACKED tDFUQueryTIVAProtocol;
+
+//*****************************************************************************
+//
+// Structure sent to the host in response to USBD_DFU_REQUEST_GETSTATUS.
+//
+//*****************************************************************************
+typedef struct
+{
+ uint8_t bStatus;
+ uint8_t bwPollTimeout[3];
+ uint8_t bState;
+ uint8_t iString;
+}
+PACKED tDFUGetStatusResponse;
+
+//*****************************************************************************
+//
+// Firmware Download Commands
+//
+// The data passed on a USBD_DFU_REQUEST_DNLOAD request is comprised of a
+// header which instructs the boot loader how to interpret the block and
+// block-specific data. The following definitions relate to the download
+// block headers.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Supported command identifiers
+//
+//*****************************************************************************
+#define DFU_CMD_PROG 0x01
+#define DFU_CMD_READ 0x02
+#define DFU_CMD_CHECK 0x03
+#define DFU_CMD_ERASE 0x04
+#define DFU_CMD_INFO 0x05
+#define DFU_CMD_BIN 0x06
+#define DFU_CMD_RESET 0x07
+
+//*****************************************************************************
+//
+// Generic download command header.
+//
+//*****************************************************************************
+typedef struct
+{
+ uint8_t ui8Command; // Command identifier.
+ uint8_t pui8Data[7]; // Command-specific data elements.
+}
+PACKED tDFUDownloadHeader;
+
+//*****************************************************************************
+//
+// Header for the DFU_CMD_PROG command.
+//
+// This command is used to program a section of the flash with the binary data
+// which immediately follows the header. The start address of the data is
+// expressed as a 1KB block number so 0 would represent the bottom of flash
+// (which, incidentally, the USB boot loader will not let you program) and 0x10
+// would represent address 16KB or 16384 (0x4000). The ui32Length field
+// contains the total number of bytes of data in the following programming
+// operation. The DFU device will not look for any command header on following
+// USBD_DFU_REQUEST_DNLOAD requests until the operation is completed or
+// aborted.
+//
+// By using this protocol, the DFU_CMD_PROG command header may be used as a
+// simple header on the binary files to be sent to the DFU device for
+// programming. If we enforce the requirement that the DFU_CMD_PROG header is
+// applied to each USBD_DFU_REQUEST_DNLOAD (one per block), this means that the
+// host-side DFU application must be aware of the underlying protocol and
+// insert these headers dynamically during programming operations. This could
+// be handled by post processing the binary to insert the headers at the
+// appropriate points but this would then tie the binary structure to the
+// chosen transfer size and break the operation if the transfer size were to
+// change in the future.
+//
+//*****************************************************************************
+typedef struct
+{
+ uint8_t ui8Command; // DFU_CMD_PROG
+ uint8_t ui8Reserved; // Reserved - set to 0x00.
+ uint16_t ui16StartAddr; // Block start address / 1024
+ uint32_t ui32Length; // Total length, in bytes, of following data
+ // for the complete download operation.
+}
+PACKED tDFUDownloadProgHeader;
+
+//*****************************************************************************
+//
+// Header for the DFU_CMD_READ and DFU_CMD_CHECK commands.
+//
+// This command may be used to set the address range whose content will be
+// returned on subsequent USBD_DFU_REQUEST_UPLOAD requests from the host.
+//
+// To read back a the contents of a region of flash, the host should send
+// USBD_DFU_REQUEST_DNLOAD with ui8Command DFU_CMD_READ, ui16StartAddr set to
+// the 1KB block start address and ui32Length set to the number of bytes to
+// read. The host should then send one or more USBD_DFU_REQUEST_UPLOAD
+// requests to receive the current flash contents from the configured
+// addresses. Data returned will include an 8 byte DFU_CMD_PROG prefix
+// structure unless the prefix has been disabled by sending a DFU_CMD_BIN
+// command with the bBinary parameter set to 1.
+//
+// To check that a region of flash is erased, the DFU_CMD_CHECK command should
+// be sent with ui16StartAddr and ui32Length set to describe the region to
+// check. The host should then send a USBD_DFU_REQUEST_GETSTATUS. If the
+// erase check was successful, the returned bStatus value will be STATUS_OK,
+// otherwise it will be STATUS_ERR_CHECK_ERASED. Note that ui32Length passed
+// must be a multiple of 4. If this is not the case, the value will be
+// truncated before the check is performed.
+//
+//*****************************************************************************
+typedef struct
+{
+ uint8_t ui8Command; // DFU_CMD_READ or DFU_CMD_CHECK
+ uint8_t ui8Reserved; // Reserved - write to 0
+ uint16_t ui16StartAddr; // Block start address / 1024
+ uint32_t ui32Length; // The number of bytes of data to read back or
+ // check.
+}
+PACKED tDFUDownloadReadCheckHeader;
+
+//*****************************************************************************
+//
+// Header for the DFU_CMD_ERASE command.
+//
+// This command may be used to erase a number of flash blocks. The address of
+// the first block to be erased is passed in ui16StartAddr with ui16NumBlocks
+// containing the number of blocks to be erased from this address. The block
+// size of the device may be determined using the DFU_CMD_INFO command.
+//
+//*****************************************************************************
+typedef struct
+{
+ uint8_t ui8Command; // DFU_CMD_ERASE
+ uint8_t ui8Reserved; // Reserved - set to 0
+ uint16_t ui16StartAddr; // Block start address / 1024
+ uint16_t ui16NumBlocks; // The number of blocks to erase
+ uint8_t pui8Reserved2[2]; // Reserved - set to 0
+}
+PACKED tDFUDownloadEraseHeader;
+
+//*****************************************************************************
+//
+// Header for the DFU_CMD_INFO command.
+//
+// This command may be used to query information about the connected device.
+// After sending the command, the information is returned on the next
+// USBD_DFU_REQUEST_UPLOAD request.
+//
+//*****************************************************************************
+typedef struct
+{
+ uint8_t ui8Command; // DFU_CMD_INFO
+ uint8_t pui8Reserved[7]; // Reserved - set to 0
+}
+PACKED tDFUDownloadInfoHeader;
+
+//*****************************************************************************
+//
+// Header for the DFU_CMD_BIN command.
+//
+// This command may be used to set the format of uploaded data. By default,
+// images read using USBD_DFU_REQUEST_UPLOAD are formatted with the appropriate
+// header to allow the same image to be flashed back to the device and have it
+// located at the address from which it originated. This is a requirement of
+// the DFU class specification (section 6.2 "the uploaded image must be
+// usable in a subsequent download") but may not be helpful in some cases where
+// the application wishes to receive only the binary image from flash. To
+// instruct the DFU device to omit the position and size header, send this
+// command with the bBinary field set to \b true prior to issuing a
+// USBD_DFU_REQUEST_UPLOAD for image data. The format choice remains in effect
+// until the command is sent once again with bBinary set to \b false.
+//
+// Note that the format choice affects only image data sent and not responses
+// read via USBD_DFU_REQUEST_UPLOAD following software-specific commands such
+// as DFU_CMD_INFO.
+//
+//*****************************************************************************
+typedef struct
+{
+ uint8_t ui8Command; // DFU_CMD_BIN
+ uint8_t bBinary; // Set to true to omit image header or false
+ // to include it (the default)
+ uint8_t pui8Reserved[6]; // Reserved - set to 0
+}
+PACKED tDFUDownloadBinHeader;
+
+//*****************************************************************************
+//
+// The DFU_CMD_RESET command uses a tDFUDownloadHeader structure since
+// only the ui8Command field is important. This command causes an immediate
+// reset of the the target board.
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+//! Payload returned in response to the DFU_CMD_INFO command.
+//!
+//! This is structure is returned in response to the first
+//! USBD_DFU_REQUEST_UPLOAD request following a DFU_CMD_INFO command.
+//
+//*****************************************************************************
+typedef struct
+{
+ //
+ //! The size of a flash block in bytes.
+ //
+ uint16_t ui16FlashBlockSize;
+
+ //
+ //! The number of blocks of flash in the device. Total flash size is
+ //! ui16NumFlashBlocks * ui16FlashBlockSize.
+ //
+ uint16_t ui16NumFlashBlocks;
+
+ //
+ //! Information on the part number, family, version and package as read
+ //! from SYSCTL register DID1.
+ //
+ uint32_t ui32PartInfo;
+
+ //
+ //! Information on the part class and revision as read from SYSCTL DID0.
+ //
+ uint32_t ui32ClassInfo;
+
+ //
+ //! Address 1 byte above the highest location the boot loader can access.
+ //
+ uint32_t ui32FlashTop;
+
+ //
+ //! Lowest address the boot loader can write or erase.
+ //
+ uint32_t ui32AppStartAddr;
+}
+PACKED tDFUDeviceInfo;
+
+#ifdef ewarm
+#pragma pack()
+#endif
+
+#endif // __USBDFU_H__
|
