This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

how to use serial flash loader practically on 0x800

Other Parts Discussed in Thread: MAX3232, LM3S600, LM3S811, EK-LM3S811

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.....!!!!!!!!!!!!!!!!!!

  • embed con,

    A couple questions to start:

    What revision of LM3S600 are you developing with?

    When you say is the bootloader overwritten are you talking about flashing the device with the serial bootloader at 0x0800 and then flashing your application code at address 0x0000?

    Best regards,

    Austin Miller

  • MY QUESTION IS HOW TO BURN MY CODE ON CHIP PRACTICALLY.

    i allready explain that my application will start at 0x800,boot code is a 0 TO  0X800

    my simple question is how to use the serial boot loader practically..simple question.

    for that i explained my above post breifly with point to point with even solution .. then wats the problem from your side just explain me the above code with simple example

    my volume will be 3000-5000/a. but suffered this problem since 6months.

    each time support answer "refer the datasheet, and just they gave me thertically idea " BUT HOW TO USE THIS PRACTICALLY?

    last option replace the ti chip....

     

  • embed con,

    embed con said:

    1. *How is the serial flashloader invoked?*practically 

     

     

    I misunderstood your original posting, below is information concerning the Stellaris Bootloader.

    I will address the Serial Flash Loader in my next post.

    Please reference the page 9 of the following document Stellaris Bootloader User's Guide (Rev J.)

    In this document and on the pages 9-10, it will be explained how the bootloader is invoked, discuss the API function calls, vector table and the default fault handler.

     

    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?

    [/quote]

    You also need to configure the settings for the linker to flash the application at address 0x800.

    In Keil µVision V4.03, Navigate to 'Flash'->'Configure Flash Tools...'->'Linker' tab

    Where you see the 'Scatter File' field click on the 'Edit' button.

    This will open the scatter file in the text editor in the background of the menu.

    Close the menu and change the following to have your application flash the device starting at 0x800.

    See the below illustration for the changes needed to the scatter file:

    Save the changes to this file and you should be all set.

    Best regards,

    Austin Miller

    [quote user="embed con"]

  • Hii Miller,

    Thanx  for ur reply .

    i will change the IROM1 starting address from 0 to 0x800,its not a big issue thanx for it.

    the Controller revision is : IQN50C2DD.

    my next question is which changes i will do in bootloder section APPLICATION _START_ADDRESS is already set ie at 800.

    and also my application have stepper, sensor, i2c ,serial ,main,applicaion_code these are .c files so how to merge this with bootloder code.

    so that it is ready for burn on chip.   

     how to prepare and start to burn chip :

    1a) bootloder & serial flash loader both to be used( i think it is neccessry?) 

    1b)   how to changes in bootloader and serial flash loder? and what code to be change or to be add in bootloder or in my applicaton.

    2c) which are the 1steps to be impliment(to change the update .c as per my applicaion ,if it is then how? )

        so i am requesting  u to give me some ready example which demonstrate the implimentaion & use od bootloder and serial flash loder. for that i am allready posting u UPDATE .C which in serial flash loder.

    ok read the  Stellaris Bootloader User's Guide (Rev J.) pages9-10 and studying the same ........

     

     

     

     

     

     

     

     



  • embed con,

    Some of the information that I have posted here you may already be aware of, however to make sure we are on the same page I will discuss all of the details that concern the serial bootloader and serial flash loader.

    Since you do not have a JTAG or a SSI interface, you will need the Serial Flash Loader to write the serial bootloader and your application code binaries to the LM3S600 over a simple two wire UART connection.

    It is important to keep in mind that the serial flash loader is factory programmed into flash and to allow flashing of application code the serial flash loader copies itself into RAM before downloading the application source code.

    The serial bootloader is not pre-programmed into flash and is used for downloading firmware upgrades to the device.

    We have examples for the serial bootloader and how to use this bootloader with application code.

    You can find these examples here: DK-LM3S811 Firmware Development Package.

    Or you can download the full package of StellarisWare that supports all of our evaluation kits and development kits here: StellarisWare

    The reason I point you to the LM3S811 is because it is from the same class of devices, Sandstorm, as the LM3S600 and the examples for the LM3S811 will work for the LM3S600.

    If you install StellarisWare in the default location you will find the examples that I am talking about located here: C:\StellarisWare\boards\ek-lm3s811

    The examples names specifically are:

    •  Serial Bootloader: boot_serial
    • Application code example 1: boot_demo1
    • Application code example 2: boot_demo2

    You will also find documentation in the default directory here: C:\StellarisWare\docs

    I also recommend ordering a EK-LM3S811 board for development testing, which can be found here: EK-LM3S811.

    The link that I have provided for this evaluation board is also packaged with Keil tools.

    This will allow you to do some testing before flashing your board with the serial flash loader through a serial port.

    Now, you need the serial flash loader but if your application does not have a use for firmware upgrades then you do not need the serial bootloader or to preserve the serial flash loader.

    The options for using the serial flash loader are discussed on page 10 of the document 'Using the Stellaris Serial Flash Loader'.

    The changes needed to the bootloader are mentioned within the bootloader source code files.

    You cannot change the serial flash loader as we only provide the serial flash loader pre-loaded into flash or as a downloadable .bin file.

    Let me know what you think,

    Best regards,

    Austin Miller