hii i am using a LM3S600 microcontroller for one of the project. It does not have embedded Stellarisware library, and has the bootloader preloaded.We are using Keil uVision v4.03 to develop the firmware. Now we need to write the firmware into the LM3S600 device. We have downloaded the GUI version of flash loader and will be using serial mode.My question is that, do we need to make our code start from address 0x800? If yes, we could modify the Target settings for the controller by changing IROM1 starting address from 0 to 0x800. Is that all that is needed?
Steps Needed to Recreate Problem:
If the starting address of the user code is 0, is the bootloader overwritten? In case this does happen, the microcontroller will not be able to download any fresh code. What is the solution in this case?
I haven't actually programmed any device yet, but we have the prototype ready and are about to write our application into it. The reason I asked this query is because we do not have a JTAG interface or even SSI interface brought out on connectors. We have a serial port with a MAX3232 level-shifter, so any using other configuration to program the device is out of question. Thus, if we lose the bootloader it
would be very difficult to reprogram the device.
I have two queries in this regard:
1. *How is the serial flashloader invoked?*practically
2. Is it enough to change the IROM1 starting address from 0 to 0x800
in Target settings in Keil? Do I need to add any other directives or
configuration code to the source files?
solution:
There is an application note that explains the operation and use of the serial flash loader. Using the Stellaris Serial Flash Loader (AN01242)
i read all this AN01242 ..theoretical OK but t how to use programatically and practically..
i am posting the update.c code from serial flash loader code give the some practically idea like led bink or just consider my application address and simlpfy it.......
//*****************************************************************************
//
//! This variable will point to the filename parameter that is passed in as a
//! parameter to this program.
//
//*****************************************************************************
static char * g_pFilename;....................????????????
//*****************************************************************************
//
//! This variable will point to the filename parameter that is passed in as a
//! boot loader file name.
//
//*****************************************************************************
static char * g_pBootLoadName;...........................?????
//*****************************************************************************
//
//! This variable will be set to the starting address of the binary will be
//! programmed into to device.
//
//*****************************************************************************
static unsigned int g_uiDownloadAddress;
//*****************************************************************************
//
//! This variable will be set to the start execution address for the binary
//! that is downloaded.
//
//*****************************************************************************
static unsigned int g_uiStartAddress;??????????
//*****************************************************************************
//
//! This variable is modified by a command line parameter to match the COM
//! port that has been requested.
//
//*****************************************************************************
static char g_szCOMName[32] =
{
#ifdef __WIN32
"\\\\.\\COM1"
#else
"/dev/ttyS0"
#endif
};
//****************************************************************************
//
//! AutoBaud() performs Automatic baud rate detection.
//!
//! This function will send the sync pattern to the board and establish basic
//! communication with the device. The call to OpenUART() in the routine
//! main() set the baud rate that will be used.
//!
//! \return If any part of the function fails, the function will return a
//! negative error code. The function will return 0 to indicate success.
//
//****************************************************************************
int
AutoBaud(void)
{
static unsigned char const ucSyncPattern[]={0x55, 0x55};
unsigned char ucCommand;
unsigned char ucAck;
//
// Send out the sync pattern and wait for an ack from the board.
//
if(UARTSendData(ucSyncPattern, 2))
{
return(-1);
}
//
// Wait for the ACK to be received, if something besides an ACK or a zero
// is received then something went wrong.
//
do
{
UARTReceiveData(&ucAck, 1);
} while(ucAck == 0);
if (ucAck != COMMAND_ACK)
{
return(-1);
}
//
// Make sure we can at least communicate with the board.
//
ucCommand = COMMAND_PING;
if(SendCommand(&ucCommand, 1) < 0)
{
return(-1);
}
return(0);
}
//****************************************************************************
//
//! SendCommand() sends a command to the serial boot loader.
//!
//! \param pucCommand is the properly formatted serial flash loader command to
//! send to the device.
//! \param ucSize is the size, in bytes, of the command to be sent.
//!
//! This function will send a command to the device and read back the status
//! code from the device to see if the command completed successfully.
//!
//! \return If any part of the function fails, the function will return a
//! negative error code. The function will return 0 to indicate success.
//
//****************************************************************************
int
SendCommand(unsigned char *pucCommand, unsigned char ucSize)
{
unsigned char ucStatus;
//
// Send the command itself.
//
if(SendPacket(pucCommand, ucSize, 1) < 0)
{
return(-1);
}
//
// Send the get status command to tell the device to return status to
// the host.
//
ucStatus = COMMAND_GET_STATUS;
if(SendPacket(&ucStatus, 1, 1) < 0)
{
printf("Failed to Get Status\n");
return(-1);
}
//
// Read back the status provided from the device.
//
ucSize = sizeof(ucStatus);
if(GetPacket(&ucStatus, &ucSize) < 0)
{
printf("Failed to Get Packet\n");
return(-1);
}
if(ucStatus != COMMAND_RET_SUCCESS)
{
printf("Failed to get download command Return Code: %04x\n",
ucStatus);
return(-1);
}
return(0);
}
//*****************************************************************************
//
//! parseArgs() handles command line processing.
//!
//! \param argc is the argc parameter passed into main().
//! \param argv is the argv parameter passed into main().
//!
//! This function parses the known arguments and generates an error if any
//! parameter was specified incorrectly.
//!
//! \return A return value of zero indicates success while any other value
//! indicates a problem with the parameters that were passed in.
//
//*****************************************************************************
int
parseArgs(int argc, char **argv)
{
int i;
char cArg;
cArg = 0;
for(i = 1; i < argc; i++)
{
if(argv[i][0] != '-')
{
if(cArg)
{
switch(cArg)
{
case 'p':
{
g_uiDownloadAddress = strtoul(argv[i], 0, 0);
break;
}
case 'r':
{
g_uiStartAddress = strtoul(argv[i], 0, 0);
break;
}
case 'c':
{
#ifdef __WIN32
sprintf(g_szCOMName, "\\\\.\\COM%s", argv[i]);
#else
strncpy(g_szCOMName, argv[i], sizeof(g_szCOMName));
#endif
break;
}
case 'l':
{
g_pBootLoadName = argv[i];
break;
}
case 'b':
{
g_uiBaudRate = strtoul(argv[i], 0, 0);
break;
}
case 's':
{
g_uiDataSize = strtoul(argv[i], 0, 0);
if((g_uiDataSize < 4) || (g_uiDataSize > 252))
{
g_uiDataSize = 8;
}
g_uiDataSize &= ~3;
break;
}
default:
{
printf("ERROR: Invalid argument\n");
return(-1);
}
}
cArg = 0;
}
else
{
//
// If we already have a filename then error out as everything
// else should have an option before it.
//
if(g_pFilename)
{
return(-1);
}
g_pFilename = argv[i];
}
}
else
{
//
// Single flag parameters go here.
//
switch(argv[i][1])
{
case '-':
case '?':
case 'h':
{
return(-2);
break;
}
case 'd':
{
g_iDisableAutoBaud = 1;
break;
}
default:
{
cArg = argv[i][1];
break;
}
}
}
}
return(0);
}
//*****************************************************************************
//
//! main() is the programs main routine.
//!
//! \param argc is the number of parameters that were passed in via the command
//! line.
//! \param argv is the list of strings that holds each parameter that was were
//! passed in via the command line.
//!
//! This is the main routine for downloading an image to the device via the
//! UART.
//!
//! \return This function either returns a negative value indicating a failure
//! or zero if the download was successful.
//
//*****************************************************************************
int
main(int argc, char **argv)
{
FILE *hFile;
FILE *hFileBoot;
g_uiDownloadAddress = 0;
g_uiStartAddress = 0x800;.......................my application start address 800
g_pFilename = 0;
g_pBootLoadName = 0;
g_uiBaudRate = 115200;
g_uiDataSize = 8;
g_iDisableAutoBaud = 0;
setbuf(stdout, 0);
//
// Get any arguments that were passed in.
//
if(parseArgs(argc, argv))
{
printf("%s", UsageString);
return(-1);
}
if(CheckArgs())
{
return(-1);
}
//
// If a boot loader was specified then open it.
//
if(g_pBootLoadName)
{
//
// Open the boot loader file to download.
//
hFileBoot = fopen(g_pBootLoadName, "rb");
if(hFileBoot == 0)
{
printf("Failed to open file: %s\n", g_pBootLoadName);
return(-1);
}
}
//
// Open the file to download.
//
hFile = fopen(g_pFilename, "rb");
if(hFile == 0)
{
printf("Failed to open file: %s\n", g_pFilename);
return(-1);
}
if(OpenUART(g_szCOMName, g_uiBaudRate))
{
printf("Failed to configure Host UART\n");
return(-1);
}
//
// Now try to auto baud with the board by sending the Sync and waiting
// for an ack from the board.
//
if(g_iDisableAutoBaud == 0)
{
if(AutoBaud())
{
printf("Failed to synchronize with board.\n");
return(-1);
}
}
printf("\n");
if(g_pBootLoadName)
{
printf("Boot Loader : %s\n", g_pBootLoadName);
}
printf("Application : %s\n", g_pFilename);
printf("Program Address: 0x%x\n", g_uiDownloadAddress);
printf(" COM Port: %s\n", g_szCOMName);
printf(" Baud Rate: %d\n", g_uiBaudRate);
printf("Erasing Flash:\n");
//
// If both a boot loader and an application were specified then update both
// the boot loader and the application.
//
if(g_pBootLoadName != 0)
{
if(UpdateFlash(hFile, hFileBoot, g_uiDownloadAddress) < 0)
{
return(-1);
}
}
//
// Otherwise just update the application.
//
else if(UpdateFlash(hFile, 0, g_uiDownloadAddress) < 0)
{
return(-1);
}
//
// If a start address was specified then send the run command to the
// boot loader.
//
if(g_uiStartAddress != 0xffffffff)
{
//
// Send the run command but just send the packet, there will likely
// be no boot loader to answer after this command completes.
//
g_ucBuffer[0] = COMMAND_RUN;
g_ucBuffer[1] = (unsigned char)(g_uiStartAddress>>24);
g_ucBuffer[2] = (unsigned char)(g_uiStartAddress>>16);
g_ucBuffer[3] = (unsigned char)(g_uiStartAddress>>8);
g_ucBuffer[4] = (unsigned char)g_uiStartAddress;
if(SendPacket(g_ucBuffer, 5, 0) < 0)
{
printf("Failed to Send Run command\n");
}
else
{
printf("Running from address %08x\n",g_uiStartAddress);
}
}
else
{
//
// Send the reset command but just send the packet, there will likely
// be no boot loader to answer after this command completes.
//
g_ucBuffer[0] = COMMAND_RESET;
SendPacket(g_ucBuffer, 1, 0);
}
if(hFile != 0)
{
fclose(hFile);
}
printf("Successfully downloaded to device.\n");
return(0);
}
//*****************************************************************************
//
//! UpdateFlash() programs data to the flash.
//!
//! \param hFile is an open file pointer to the binary data to program into the
//! flash as the application.
//! \param hBootFile is an open file pointer to the binary data for the
//! boot loader binary. This will be programmed at offset zero.
//! \param ulAddress is address to start programming data to the falsh.
//!
//! This routine handles the commands necessary to program data to the flash.
//! If hFile should always have a value if hBootFile also has a valid value.
//! This function will concatenate the two files in memory to reduce the number
//! of flash erases that occur when both the boot loader and the application
//! are being updated.
//!
//! \return This function either returns a negative value indicating a failure
//! or zero if the update was successful.
//
//*****************************************************************************
int
UpdateFlash(FILE *hFile, FILE *hBootFile, unsigned long ulAddress)
{
unsigned long ulFileLength;
unsigned long ulBootFileLength;
unsigned long ulTransferStart;
unsigned long ulTransferLength;
unsigned char *pFileBuffer;
unsigned long ulOffset;
//
// At least one file must be specified.
//
if(hFile == 0)
{
return(-1);
}
//
// Get the file sizes.
//
fseek(hFile, 0, SEEK_END);
ulFileLength = ftell(hFile);
fseek(hFile, 0, SEEK_SET);
//
// Default the transfer length to be the size of the application.
//
ulTransferLength = ulFileLength;
ulTransferStart = ulAddress;
if(hBootFile)
{
fseek(hBootFile, 0, SEEK_END);
ulBootFileLength = ftell(hBootFile);
fseek(hBootFile, 0, SEEK_SET);
ulTransferLength = ulAddress + ulFileLength;
ulTransferStart = 0;
}
pFileBuffer = malloc(ulTransferLength);
if(pFileBuffer == 0)
{
return(-1);
}
if(hBootFile)
{
if(fread(pFileBuffer, 1, ulBootFileLength, hBootFile) !=
ulBootFileLength)
{
return(-1);
}
if(ulAddress < ulBootFileLength)
{
return(-1);
}
//
// Pad the unused code space with 0xff to have all of the flash in
// a known state.
//
memset(&pFileBuffer[ulBootFileLength], 0xff,
ulAddress - ulBootFileLength);
//
// Append the application to the boot loader image.
//
if(fread(&pFileBuffer[ulAddress], 1, ulFileLength, hFile) !=
ulFileLength)
{
return(-1);
}
}
else
{
//
// Just read in the full application since there is not boot loader.
//
if(fread(pFileBuffer, 1, ulTransferLength, hFile) != ulTransferLength)
{
return(-1);
}
}
//
// Build up the download command and send it to the board.
//
g_ucBuffer[0] = COMMAND_DOWNLOAD;
g_ucBuffer[1] = (unsigned char)(ulTransferStart >> 24);
g_ucBuffer[2] = (unsigned char)(ulTransferStart >> 16);
g_ucBuffer[3] = (unsigned char)(ulTransferStart >> 8);
g_ucBuffer[4] = (unsigned char)ulTransferStart;
g_ucBuffer[5] = (unsigned char)(ulTransferLength>>24);
g_ucBuffer[6] = (unsigned char)(ulTransferLength>>16);
g_ucBuffer[7] = (unsigned char)(ulTransferLength>>8);
g_ucBuffer[8] = (unsigned char)ulTransferLength;
if(SendCommand(g_ucBuffer, 9) < 0)
{
printf("Failed to Send Download Command\n");
return(-1);
}
ulOffset = 0;
printf("Remaining Bytes: ");
do
{
unsigned char ucBytesSent;
g_ucBuffer[0] = COMMAND_SEND_DATA;
printf("%08ld", ulTransferLength);
//
// Send out 8 bytes at a time to throttle download rate and avoid
// overruning the device since it is programming flash on the fly.
//
if(ulTransferLength >= g_uiDataSize)
{
memcpy(&g_ucBuffer[1], &pFileBuffer[ulOffset], g_uiDataSize);
ulOffset += g_uiDataSize;
ulTransferLength -= g_uiDataSize;
ucBytesSent = g_uiDataSize + 1;
}
else
{
memcpy(&g_ucBuffer[1], &pFileBuffer[ulOffset], ulTransferLength);
ulOffset += ulTransferLength;
ucBytesSent = ulTransferLength + 1;
ulTransferLength = 0;
}
//
// Send the Send Data command to the device.
//
if(SendCommand(g_ucBuffer, ucBytesSent) < 0)
{
printf("Failed to Send Packet data\n");
break;
}
printf("\b\b\b\b\b\b\b\b");
} while (ulTransferLength);
printf("00000000\n");
if(pFileBuffer)
{
free(pFileBuffer);
}
return(0);
}
//*****************************************************************************
//
//! CheckArgs() ensures that the arguments passed in are correct.
//!
//! This routine makes sure that the combination of command line parameters
//! that were passed into the program are valid. If only a Boot Loader binary
//! was specified then the parameters will be modified to be application update
//! update at address zero. This step is done to simplfy logic later in the
//! update program.
//!
//! \return This function either returns a negative value indicating a failure
//! or zero if the update was successful.
//
//*****************************************************************************
int CheckArgs(void)
{
//
// No file names specified.
//
if((g_pFilename == 0) && (g_pBootLoadName == 0))
{
printf("ERROR: no file names specified.\n");
return(-1);
}
//
// Both filenames are specified but the address is zero.
//
if((g_pFilename != 0) && (g_pBootLoadName != 0) &&
(g_uiDownloadAddress == 0))
{
printf(
"ERROR: Download address cannot be zero and specify a boot loader \n"
"binary as well as an application binary\n");
return(-1);
}
//
// If only a boot loader was specified then set the address to 0 and
// specify only one file to download.
//
if((g_pBootLoadName != 0) && (g_pFilename == 0))
{
g_pFilename = g_pBootLoadName;
g_pBootLoadName = 0;
g_uiDownloadAddress = 0;
}
return(0);
}
//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
PLEASE SOLVE MY PROBLEM AND PLEASE GIVE ME SOME PRACTICALLY IDEA ... on the same update.c
thnx
i faced this problem since last decembr.....!!!!!!!!!!!!!!!!!!