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.

C6452 Serial Bootloader / Application updates via UART

Hi,

I would like to perform application software updates via the UART on the C6452, I already have the UART up and running (by using the DSP/BIOS UART driver). My C6452 is connected and configured to boot from external flash (0xA000000). As soon as the DSP boots up it should wait a few seconds for the new image data via the UART, if new image data arrives it should transfer it to flash as a fallback image. The bootloader should then copy the fallback image to the primary image and start executing from the primary image. If no new data image data arrives via the UART it should start executing the existing primary image in flash.

What are the steps I should follow? Can anyone pls. point me in the right direction?

Thank you.

 

  • It seems like you've already listed the steps!  Can you please clarify your question?

    I'd like to point out one thing that I think you may already understand, but I want to be sure.  The UART boot mode will not automatically fall back to a different boot method (e.g. flash).  So in your setup you need to always boot from flash and then implement your own bootloader in flash.  Your bootloader would be waiting for communication on the serial port and if it timed out then it could continue booting from flash.  You should just make sure the area of flash containing the bootloader cannot possibly erase itself so that you never brick one of your boards!

     

  • I think Brad might have slightly missed what you are trying to do (or maybe I am). It sounds like you want to boot from parallel flash only when there is not a new image to load via UART. If there is a new image, load to flash then boot from flash. If this is the case, I am afraid we may not have an example of this already available.

    Basically what you need to do is a secondary bootloader. This is a custom boot routine (which runs after the on-chip bootloader) which waits on the UART until timeout, then if it does not see anything on the UART finishes loading the current image loaded in flash. You can read a little about it in the DM648 bootloader document - I know you are using C6452, but they use the same bootloader so this app covers it as well.

  • Thanks for the help so far (I had a look at the DM648 bootloader doc as well as 'Creating a 2nd level bootloader for Flash, SPRA999'). I'll give some more details of what I try to accomplish:

    I have 32MB external flash which i plan to map out in the following way:

    myBootLoader: origin = 0xA0000000, length = 0x001FFFFF  (2048KB)

    primaryImage: origin = 0xA0100000,  0x003FFFFF (4096KB)

    secondaryImage: origin = 0xA0300000,  0x003FFFFF (4096KB)

     

    The bootloader must wait for a few seconds, if no new image is received via the UART it should jump to the primary Image at location 0xA0100000, and start executing the application, if a new image is received via the uart it should copy it to the secondary location in flash (0xA0300000) and verify the image, the bootloader should then reset the DSP. Upon start-up the bootloader must now copy the image from the secondary location to the primary location and branch to the the primary image location to execute the new image.

    I have the following questions:

    1.) Can my custom bootloader size be bigger then 64KB (I allocated 2048KB) I read that only 64KB is copied from CE2 (0xA0000000) to address 0x0000 0000 at start-up? 

    2.) Can my bootloader be a DSP/BIOS application since i want to use the DSP/BIOS UART driver?

    3.) Am I on the right track?

    Thank you.

  • RdN said:
    1.) Can my custom bootloader size be bigger then 64KB (I allocated 2048KB) I read that only 64KB is copied from CE2 (0xA0000000) to address 0x0000 0000 at start-up? 

    Not everything in spra999a is applicable to the DM648 bootloader. That document was written for the 'legacy' DSP parts (e.g. 6416, 6713, etc.) whereas the DM648 bootloader is more advanced. As such, you have two options for EMIFA booting: Direct boot or Fast boot (with AIS). If you boot with Direct boot then the bootloader jumps directly to CS2 address space (0xA0000000). This means you aren't limited to a 64k copy and the bootloader can grow bigger. See sections 1.6 and 1.7 of the DM648 bootloader doc.

    RdN said:
    2.) Can my bootloader be a DSP/BIOS application since i want to use the DSP/BIOS UART driver?
    I think the answer to this question is yes, but I haven't done so. I do not know how the system will work as it will load the C and BIOS environments for the bootloader, then again for the run-time application. Maybe someone else with more experience can chime in.

  • RdN said:

    1.) Can my custom bootloader size be bigger then 64KB (I allocated 2048KB) I read that only 64KB is copied from CE2 (0xA0000000) to address 0x0000 0000 at start-up? 

    In older devices like the 6416 you would end up with 1KB of code copied from 0xA0000000 to address 0x00000000 at startup.  On the DM648 you would instead use the "direct boot" option where code would execute directly from address 0xA0000000.  This has the advantage of removing any size limits on the bootloader.  The only disadvantage is that all your code would be executing from a slower interface, the EMIF.  This disadvantage is offset by the fact that L1 cache is enabled by default in this bootmode so once the boot code was cached it could execute very rapidly.

    RdN said:

    2.) Can my bootloader be a DSP/BIOS application since i want to use the DSP/BIOS UART driver?

    The very first piece of your bootloader will need to be in assembly.  The app note Tim referenced (spra999) should be very helpful in constructing that assembly code.  It would need to program the PLL and the DDR interface and then branch to _c_int00.  From that point on your application would be "normal" C code, or a DSP/BIOS application.

    RdN said:

    3.) Am I on the right track?

    Absolutely!  You'll likely run into some issues along the way, but we'll still be here to help!

  • Hi,

    Thanks a lot for the advice so far. OK, I have written a DSP/BIOS 'boot application' which is located at address 0xA0000000 (CE2 - EMIFA on the C6452, external flash, 16-bits wide). Using direct boot option I'm able to boot into and execute the boot application. The boot application gives me the option to transmit a file via the UART using XModem file transfer protocol. The file is then copied to external flash address 0xA0100000, this works and i can almost copy any file there [:)]

    Now I have the following questions?

    1.) From what I've learnt I can't just copy an *.out application to flash, I need to convert it to *.bin using hex6x.exe...is this correct? Do I need to enable the -boot option?

    2.) How do i perform the 'jump' from the boot application to my new application located at 0xA0100000?

    3.) Since my boot application which is written in DSP/BIOS uses 2 tasks (to manage the UART and the FLASH), I assume I will need to 'disable' these tasks before I jump to my new application located at 0xA0100000, or i need some way to 'unload' the DSP/BIOS kernel in case my new uploaded application does not make use of DSP/BIOS?

    Thank you.

  • RdN said:

    1.) From what I've learnt I can't just copy an *.out application to flash, I need to convert it to *.bin using hex6x.exe...is this correct? Do I need to enable the -boot option?

    Enabling the -boot option will tell the hex tool to create a boot table.  That is, it will format your application into a table format such that your bootloader can then copy it to the appropriate locations in RAM.  So assuming you want to execute your application from RAM as you would during development, then yes you should enable that option.  If you execute directly from flash the access times will be much slower, though of course the cache will compensate to some extent.  I recommend copying to RAM though...

    RdN said:

    2.) How do i perform the 'jump' from the boot application to my new application located at 0xA0100000?

    Related to last question, you probably don't want your application to be linked to address 0xA0100000 and executed from there.  More likely you want it to execute from RAM.  As part of the table generated by the hex utility when using the -boot option, it includes the entry point, i.e. the address where your linked code begins, generally the _c_int00 function.  So the last thing your bootloader will do is to branch to that instruction.

    RdN said:

    3.) Since my boot application which is written in DSP/BIOS uses 2 tasks (to manage the UART and the FLASH), I assume I will need to 'disable' these tasks before I jump to my new application located at 0xA0100000, or i need some way to 'unload' the DSP/BIOS kernel in case my new uploaded application does not make use of DSP/BIOS?

    When you start running the "real" application the stack pointers and everything will be re-initialized so effectively your bootloader application will be lost/forgotten.  The one area that you need to be very careful about is cache.  I recommend turning the cache completely off in your bootloader and then enabling cache in your application.  Otherwise you might end up with some nasty cache coherence issues to debug.  Note that L1P/L1D default to "on" so you will need to actively disable them in your code.

    Brad

  • Hi,

    Brad Griffis said:
    I recommend turning the cache completely off in your bootloader and then enabling cache in your application.  Otherwise you might end up with some nasty cache coherence issues to debug.  Note that L1P/L1D default to "on" so you will need to actively disable them in your code.

    I have the following question related to disabling cache in my DSP/BIOS boot application.

    1.) I have disabled L1P and L1D cache in DSP/BIOS by setting their size to 0k under Global settings->64PLUS tab. However, when i try to disable L2 cache (by changing it from 256k to 0k), my application 'hangs' as soon as i start to send the file via the uart (using xmodem protocol)...  I make use of QUE objects (Object memory - DDR2). MAR 224-255 bitmask is set to 0x0000ffff. I also get this behavior where my application 'hangs' when i set MAR 224-255 bitmask is set to 0x00000000... Do I need to disable L2 cache as well to prevent cache coherence issues?

    Thank you.

     

  • Can you tell what is happening when the application hangs?  You might try opening a DSP/BIOS Message Log and looking at the Execution Graph Details.  It might have some clue as to what happened, e.g. exception, etc.

  • Thanks Brad, the L2 cache disable problem seem to have 'dissapeared' after i restared CCS, i think it had something to do with my GEL file. Ok, I now have a DSP/BIOS boot application with L1 and L2 cache disabled. My boot application has a command line interface via the UART with the following options:

    1.) Upload DSP application to FLASH (16-bit) address 0xA0100000

    2.) Branch to DSP application 0xA0100000

    Now, I have another DSP/BIOS application called flashLED.out which i want to upload to flash and when i branch to it, it should execute in RAM. I think i might be missing something somewhere but what i understand is that i now should do the following:

    1.) Add a userlinker.cmd file to flashLED project which looks like this:

    -l flashLEDcfg.cmd

    SECTIONS {

    .boot_load > BOOT_RAM

    }

    Build the project and use hex6x.exe to convert *.out to *.hex.

    hex6x procHex.cmd

    where procHex.cmd looks like:

    flashLED.out
    -a
    -memwidth  16
    -map flashLEDhex.map
    -boot
    -bootorg 0x64010400 I think this is wrong, but I'm not sure what is should be...
    -bootsection .boot_load 0x64010000 I think this is wrong, but I'm not sure what is should be...
    ROMS
    {
        FLASH:  origin = 0xA0100000, length = 0x00200000, romwidth = 16, files = {flashLED.hex}
    }

    I then upload my hex file to location 0xA0100000 in flash, branch to 0xA0100000, the DSP will then take care to copy the application to RAM and execute the application from _c_int00. Am I correct or am I missing something somewhere?

     

    Thanks a lot for the valuable assistance so far.

     

  • RdN said:

    Thanks Brad, the L2 cache disable problem seem to have 'dissapeared' after i restared CCS, i think it had something to do with my GEL file.

    That's great news!  So is your bootloader already burned into flash?  If so, you might want to refer to this wiki article:

    http://wiki.davincidsp.com/index.php?title=Debugging_from_Flash

    RdN said:

    Now, I have another DSP/BIOS application called flashLED.out which i want to upload to flash and when i branch to it, it should execute in RAM. I think i might be missing something somewhere but what i understand is that i now should do the following:

    1.) Add a userlinker.cmd file to flashLED project which looks like this:

    -l flashLEDcfg.cmd

    SECTIONS {

    .boot_load > BOOT_RAM

    }

    I don't think you should have to generate your own linker command file as you show above.  In spra999a the .boot_load section corresponds to the assembly bootloader.  In that scenario the assembly bootloader was being encapsulated into the flash image being created.  In your scenario you've separated the bootloader from the application so you wouldn't need that section.

    RdN said:

    Build the project and use hex6x.exe to convert *.out to *.hex.

    hex6x procHex.cmd

    where procHex.cmd looks like:

    flashLED.out
    -a
    -memwidth  16
    -map flashLEDhex.map
    -boot
    -bootorg 0x64010400 I think this is wrong, but I'm not sure what is should be...
    -bootsection .boot_load 0x64010000 I think this is wrong, but I'm not sure what is should be...
    ROMS
    {
        FLASH:  origin = 0xA0100000, length = 0x00200000, romwidth = 16, files = {flashLED.hex}
    }

    The -bootorg statement is the address where you want the copy table placed.  In your case that would be 0xA0100000.

    The -bootsection should be left out altogether in your case.  In the app note the example is construction "one big hex image" that contains both the bootloader and the app.  In your case you have separated these such that you can update your application in the field.

    RdN said:

    I then upload my hex file to location 0xA0100000 in flash, branch to 0xA0100000, the DSP will then take care to copy the application to RAM and execute the application from _c_int00. Am I correct or am I missing something somewhere?

    Yes, that's right.  To be clear, your bootloader at 0xA0000000 is responsible for copying your application into RAM and then branching to the entry point, _c_int00.  Just make sure that none of the initialized sections of the application overlap with any of the sections (initialized or uninitialized) of the bootloader.  For example, if your bootloader copies code from the application into memory and overwrites its own stack then you will crash the bootloader!

     

  • Brad Griffis said:
    That's great news!  So is your bootloader already burned into flash?

    Yes, I have the C6452EVM from Lyrtech and they supply a utility called EVMUpdater to write an application to FLASH, since i've set the boot mode to direct mode my boot application at 0xA0000000 is executed at start-up. It is this boot application that gives one the option to upload an image to 0xA0100000 and then execute it.

    Brad Griffis said:
    In your case you have separated these such that you can update your application in the field.

    Correct, I want to be able to update the application in the field via the UART.

    Brad Griffis said:
    To be clear, your bootloader at 0xA0000000 is responsible for copying your application into RAM and then branching to the entry point, _c_int00.

    I think this is the part that i don't understand and where I'm missing something... currently my bootloader does not copy the application to RAM... it only branches to 0xA0100000. Or is the copying to RAM and execution from _c_int00 'transparent' in the sense that there is a boot table at 0xA0100000 which will automatically handle the copying to RAM and execution of the updated application once I've branched there?

    Thanks for the help.

  • RdN said:

    To be clear, your bootloader at 0xA0000000 is responsible for copying your application into RAM and then branching to the entry point, _c_int00.

    I think this is the part that i don't understand and where I'm missing something... currently my bootloader does not copy the application to RAM... it only branches to 0xA0100000. Or is the copying to RAM and execution from _c_int00 'transparent' in the sense that there is a boot table at 0xA0100000 which will automatically handle the copying to RAM and execution of the updated application once I've branched there?

    Thanks for the help.

    [/quote]

    No, you can't just branch to 0xA0100000.  For one, your _c_int00 function will not reside at 0xA0100000.  You should have your application built/linked such that it will run from RAM.  Then when you run the hex conversion step it will create a copy table for you showing where all the pieces of code should reside in the memory map.

    The format of the copy table as generated by the hex conversion utility will be:

    [entry point address, generally _c_int00 (32-bit field)]

    [Section 1 Size in Bytes (32-bit field)]

    [Section 1 Dest (32-bit field)]

    [Section 1 Data (size as specified in above tag)]

    [Section 2 Size in Bytes (32-bit field)]

    [Section 2 Dest (32-bit field)]

    [Section 2 Data (size as specified in above tag)]

    :

    [Section N Size in Bytes (32-bit field)]

    [Section N Dest (32-bit field)]

    [Section N Data (size as specified in above tag)]

    [0x00000000]

    The above table will be located at the address specified by your -bootorg (0xA0100000).  So you would need to write code to parse that table and copy the data to the appropriate location.

    Off the top of my head (untested!!!) it would look something like this:

    unsigned int *pCopyTable = 0xA0100000;
    unsigned int i = 0; // index into Copy Table
    void (*entry_point)(void) = NULL;

    unsigned int size;

    unsigned int *dst;


    // get location for start of application (_c_int00)
    entry_point = (void(*)void)*pCopyTable++;


    while( pCopyTable[i] != 0 )
    {
      size = pCopyTable[i++];
      size = (size+3) >> 2; // convert size from bytes to words (rounding up)
      dst = pCopyTable[i++];
      while (size != 0)
      {
        *dst++ = pCopyTable[i++];
        size--;
      }
    }

    // branch to entry point
    entry_point();


     

     

     

     

     

     

     

  • Thanks a lot!! Things are making much more sense now [:)]

    I can see the uploaded image in the flash with entry_point, section size, destination and data as you explained (using char mode instead of hex32 bit - c style in the memory view)

    .    .    .    $    A    a    0    1
    0    0    0    0    0    ,    .    .
    6    0    .    A    0    .    A    0
    .    0    0
        .    1    8    .    0
    0    .    0    0    .    0    0    .
    B    4    .    B    B    .    A    0
    .    0    0    .    0    0    .    0
    0    .    0    0    .    0    0    .

    The entry is shown in bold, from the map file:

    Entry Point  : 0xa0a060....and the .log section

    .log : btad=a0100000  dest=00a0bbb4 size=00000018

     

    It does't seem as if the hex6x utility support *.bin as output. Do you know of any utility to convert the *.hex file to a *.bin file so that it's in raw format instead of ascii format?

    Thank you for all the help.

  • RdN said:

    It does't seem as if the hex6x utility support *.bin as output. Do you know of any utility to convert the *.hex file to a *.bin file so that it's in raw format instead of ascii format?

    Correct, the hex6x does not support a bin output.  Try Googling "hex2bin".  You will likely find what you need.

  • After I converted the *.hex file to *.bin and copying it to flash, it is working !! I can now perform application updates in the field via the UART! [:)]

    Thanks a lot for all the help and especially Brad for pointing me in the right direction with the copy algorithm.

  • Great news!  I'm glad everything is working now.  FYI, there is an undocumented option (not sure why) "-b" that will cause hex6x to directly output a binary file.  Also, just as a suggestion, you can invoke the hex conversion utility as a "post build step" in CCS such that it automatically runs every time you rebuild your code.

  • can you share me with your bootloading code? Thanks

  • Hi,

    Unfortunately due to intellectual property and company copyright rules I'm not allowed to share source code. However, I will gladly provide assistance to you. The core code of the bootloader is the section of code the Brad shared earlier in the post... it copies the application from flash to memory and executes it. The important thing is to ensure that the application in flash is in the correct format, eg. entry point, section 1 size, section 1 dest, section 1 data...etc.

     

  • refer to this, i have been succesful on DM6437!! thank you very much.