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.

TMS320F28388D: Getting Started writing a bootloader and no idea how to acquire the necessary knowledge, several questions

Part Number: TMS320F28388D
Other Parts Discussed in Thread: C2000WARE, CCSTUDIO

Hello, I am a working student who received the task to write a bootloader for this microcontroller without any prior knowledge about this kind of stuff. My C knowledge is also rather shaky.

I have read/skimmed several manuals, e.g. the FLASH API manual, the 6k pages general manual of the controller and others. When reading these manuals I obviously approached them with the wrong mindset, I expected them to be like the documentation I am familiar with: A list of functions with their parameters and what they do. So I went searching for e.g. a 'reboot' function among others, but didn't find anything like that.

I have also looked into the examples in the C2000Ware directory and tried to understand them. I learned about the existence of .cmd files and what they do, but I still don't understand them fully.

My Goals are:

1. Read an update file from an SD card and overwrite the flash memory with the contents of that update file if present.

2. If the file isn't present or after the update is performed, jump to the main program.

My Problems:

1. I do not know how to jump to the address of the main program. I expected some already existing function to do that for me and to just hand it over one of the addresses in my .cmd file, but I couldn't find anything like that. I do have the main program and my bootloader as separate projects in CCStudio and fiddled with the 2838x_FLASH_Ink_ecat_cpu1.cmd files of both projects. I moved the beginning of the main program to FLASH4 and want to reserve FLASH0-FLASH3 for the bootloader.

cmd for main program:

MEMORY
{
   /* BEGIN is used for the "boot to Flash" bootloader mode   */
   BEGIN            : origin = 0x088000, length = 0x000002
   BOOT_RSVD        : origin = 0x000002, length = 0x0001AF     /* Part of M0, BOOT rom will use this for stack */
   RAMM0            : origin = 0x0001B1, length = 0x00024F
   RAMM1            : origin = 0x000400, length = 0x0003F8     /* on-chip RAM block M1 */
//   RAMM1_RSVD       : origin = 0x0007F8, length = 0x000008     /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */
   RAMD0            : origin = 0x00C000, length = 0x000800
   RAMD1            : origin = 0x00C800, length = 0x000800
   RAMLS0           : origin = 0x008000, length = 0x000800
   RAMLS1           : origin = 0x008800, length = 0x000800
   RAMLS2           : origin = 0x009000, length = 0x000800
   RAMLS3           : origin = 0x009800, length = 0x000800
   RAMLS4           : origin = 0x00A000, length = 0x000800
   RAMLS5           : origin = 0x00A800, length = 0x000800
   RAMLS6           : origin = 0x00B000, length = 0x000800
   RAMLS7           : origin = 0x00B800, length = 0x000800

   RAMGS0           : origin = 0x00D000, length = 0x001000
   RAMGS1           : origin = 0x00E000, length = 0x001000
   RAMGS2           : origin = 0x00F000, length = 0x001000

   RAMGS3_to_10      : origin = 0x010000, length = 0x008000
/*
   RAMGS3           : origin = 0x010000, length = 0x001000
   RAMGS4           : origin = 0x011000, length = 0x001000
   RAMGS5           : origin = 0x012000, length = 0x001000
   RAMGS6           : origin = 0x013000, length = 0x001000
   RAMGS7           : origin = 0x014000, length = 0x001000
   RAMGS8           : origin = 0x015000, length = 0x001000
   RAMGS9           : origin = 0x016000, length = 0x001000
   RAMGS10          : origin = 0x017000, length = 0x001000*/

   RAMGS11          : origin = 0x018000, length = 0x001000
   RAMGS12          : origin = 0x019000, length = 0x001000
   RAMGS13          : origin = 0x01A000, length = 0x001000
   RAMGS14          : origin = 0x01B000, length = 0x001000
   RAMGS15          : origin = 0x01C000, length = 0x000FF8
//   RAMGS15_RSVD     : origin = 0x01CFF8, length = 0x000008     /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */

   /* Flash sectors */
//   FLASH0           : origin = 0x080002, length = 0x001FFE  /* on-chip Flash */
//   FLASH1           : origin = 0x082000, length = 0x002000  /* on-chip Flash */
//   FLASH2           : origin = 0x084000, length = 0x002000  /* on-chip Flash */
//   FLASH3           : origin = 0x086000, length = 0x002000  /* on-chip Flash */
   FLASH4           : origin = 0x088002, length = 0x007FFE  /* on-chip Flash */
   FLASH5           : origin = 0x090000, length = 0x008000  /* on-chip Flash */
   FLASH6           : origin = 0x098000, length = 0x008000  /* on-chip Flash */
   FLASH7           : origin = 0x0A0000, length = 0x008000  /* on-chip Flash */
   FLASH8           : origin = 0x0A8000, length = 0x008000  /* on-chip Flash */
   FLASH9           : origin = 0x0B0000, length = 0x008000  /* on-chip Flash */
   FLASH10          : origin = 0x0B8000, length = 0x002000  /* on-chip Flash */
   FLASH11          : origin = 0x0BA000, length = 0x002000  /* on-chip Flash */
   FLASH12          : origin = 0x0BC000, length = 0x002000  /* on-chip Flash */
   FLASH13          : origin = 0x0BE000, length = 0x001FF0  /* on-chip Flash */
//   FLASH13_RSVD     : origin = 0x0BFFF0, length = 0x000010  /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */

   CPU1TOCPU2RAM   : origin = 0x03A000, length = 0x000800
   CPU2TOCPU1RAM   : origin = 0x03B000, length = 0x000800
   CPUTOCMRAM      : origin = 0x039000, length = 0x000800
   CMTOCPURAM      : origin = 0x038000, length = 0x000800

   CANA_MSG_RAM     : origin = 0x049000, length = 0x000800
   CANB_MSG_RAM     : origin = 0x04B000, length = 0x000800

   RESET            : origin = 0x3FFFC0, length = 0x000002
}

SECTIONS
{
   codestart           : > BEGIN, ALIGN(8)
   .text               : >> FLASH5 | FLASH6 | FLASH7 | FLASH8, ALIGN(8)
   .cinit              : > FLASH8 | FLASH9 | FLASH10, ALIGN(8)
   .switch             : > FLASH5, ALIGN(8)
   .reset              : > RESET, TYPE = DSECT /* not used, */
   .stack              : > RAMM1

#if defined(__TI_EABI__)
   .init_array      : > FLASH5, ALIGN(8)
   .bss             : >> RAMLS4 | RAMLS5 | RAMLS6 | RAMLS7 | RAMGS2
   .bss:output      : > RAMLS3
   .bss:cio         : > RAMLS5
   .data            : > RAMLS5
   .sysmem          : > RAMLS5
   /* Initalized sections go in Flash */
   .const           : > FLASH10, ALIGN(8)
#else
   .pinit           : > FLASH5, ALIGN(8)
   .ebss            : > RAMLS5
   .esysmem         : > RAMLS5
   .cio             : > RAMLS5
   /* Initalized sections go in Flash */
   .econst          : >> FLASH8 | FLASH9, ALIGN(8)
#endif

   ramgs0 : > RAMGS0, type=NOINIT
   ramgs1 : > RAMGS1, type=NOINIT
   
   PIXDATA_RAM > RAMGS3_to_10, type=NOINIT

   MSGRAM_CPU1_TO_CPU2 : > CPU1TOCPU2RAM, type=NOINIT
   MSGRAM_CPU2_TO_CPU1 : > CPU2TOCPU1RAM, type=NOINIT
   MSGRAM_CPU_TO_CM    : > CPUTOCMRAM, type=NOINIT
   MSGRAM_CM_TO_CPU    : > CMTOCPURAM, type=NOINIT

   /* The following section definition are for SDFM examples */
/*   Filter_RegsFile  : > RAMGS0
   Filter1_RegsFile : > RAMGS1, fill=0x1111
   Filter2_RegsFile : > RAMGS2, fill=0x2222
   Filter3_RegsFile : > RAMGS3, fill=0x3333
   Filter4_RegsFile : > RAMGS4, fill=0x4444
   Difference_RegsFile : >RAMGS5, fill=0x3333 */

   #if defined(__TI_EABI__)
       .TI.ramfunc : {} LOAD = FLASH7,
                        RUN = RAMLS0 | RAMLS1 | RAMLS2 |RAMLS3,
                        LOAD_START(RamfuncsLoadStart),
                        LOAD_SIZE(RamfuncsLoadSize),
                        LOAD_END(RamfuncsLoadEnd),
                        RUN_START(RamfuncsRunStart),
                        RUN_SIZE(RamfuncsRunSize),
                        RUN_END(RamfuncsRunEnd),
                        ALIGN(8)
   #else
       .TI.ramfunc : {} LOAD = FLASH7,
                        RUN = RAMLS0 | RAMLS1 | RAMLS2 |RAMLS3,
                        LOAD_START(_RamfuncsLoadStart),
                        LOAD_SIZE(_RamfuncsLoadSize),
                        LOAD_END(_RamfuncsLoadEnd),
                        RUN_START(_RamfuncsRunStart),
                        RUN_SIZE(_RamfuncsRunSize),
                        RUN_END(_RamfuncsRunEnd),
                        ALIGN(8)
   #endif

}

/*
//===========================================================================
// End of file.
//===========================================================================
*/

cmd for bootloader (currently erroneous)

MEMORY
{
   /* BEGIN is used for the "boot to Flash" bootloader mode   */
   BEGIN            : origin = 0x080000, length = 0x000002
   BOOT_RSVD        : origin = 0x000002, length = 0x0001AF     /* Part of M0, BOOT rom will use this for stack */
   RAMM0            : origin = 0x0001B1, length = 0x00024F
   RAMM1            : origin = 0x000400, length = 0x0003F8     /* on-chip RAM block M1 */
//   RAMM1_RSVD       : origin = 0x0007F8, length = 0x000008     /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */
   RAMD0            : origin = 0x00C000, length = 0x000800
   RAMD1            : origin = 0x00C800, length = 0x000800
   RAMLS0           : origin = 0x008000, length = 0x000800
   RAMLS1           : origin = 0x008800, length = 0x000800
   RAMLS2           : origin = 0x009000, length = 0x000800
   RAMLS3           : origin = 0x009800, length = 0x000800
   RAMLS4           : origin = 0x00A000, length = 0x000800
   RAMLS5           : origin = 0x00A800, length = 0x000800
   RAMLS6           : origin = 0x00B000, length = 0x000800
   RAMLS7           : origin = 0x00B800, length = 0x000800

   RAMGS0           : origin = 0x00D000, length = 0x001000
   RAMGS1           : origin = 0x00E000, length = 0x001000
   RAMGS2           : origin = 0x00F000, length = 0x001000

   RAMGS3_to_10      : origin = 0x010000, length = 0x008000
/*
   RAMGS3           : origin = 0x010000, length = 0x001000
   RAMGS4           : origin = 0x011000, length = 0x001000
   RAMGS5           : origin = 0x012000, length = 0x001000
   RAMGS6           : origin = 0x013000, length = 0x001000
   RAMGS7           : origin = 0x014000, length = 0x001000
   RAMGS8           : origin = 0x015000, length = 0x001000
   RAMGS9           : origin = 0x016000, length = 0x001000
   RAMGS10          : origin = 0x017000, length = 0x001000*/

   RAMGS11          : origin = 0x018000, length = 0x001000
   RAMGS12          : origin = 0x019000, length = 0x001000
   RAMGS13          : origin = 0x01A000, length = 0x001000
   RAMGS14          : origin = 0x01B000, length = 0x001000
   RAMGS15          : origin = 0x01C000, length = 0x000FF8
//   RAMGS15_RSVD     : origin = 0x01CFF8, length = 0x000008     /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */

   /* Flash sectors */
   FLASH0           : origin = 0x080002, length = 0x001FFE  /* on-chip Flash */
   FLASH1           : origin = 0x082000, length = 0x002000  /* on-chip Flash */
   FLASH2           : origin = 0x084000, length = 0x002000  /* on-chip Flash */
   FLASH3           : origin = 0x086000, length = 0x002000  /* on-chip Flash */
//   FLASH4           : origin = 0x088000, length = 0x008000  /* on-chip Flash */
//   FLASH5           : origin = 0x090000, length = 0x008000  /* on-chip Flash */
//   FLASH6           : origin = 0x098000, length = 0x008000  /* on-chip Flash */
//   FLASH7           : origin = 0x0A0000, length = 0x008000  /* on-chip Flash */
//   FLASH8           : origin = 0x0A8000, length = 0x008000  /* on-chip Flash */
//   FLASH9           : origin = 0x0B0000, length = 0x008000  /* on-chip Flash */
//   FLASH10          : origin = 0x0B8000, length = 0x002000  /* on-chip Flash */
//   FLASH11          : origin = 0x0BA000, length = 0x002000  /* on-chip Flash */
//   FLASH12          : origin = 0x0BC000, length = 0x002000  /* on-chip Flash */
//   FLASH13          : origin = 0x0BE000, length = 0x001FF0  /* on-chip Flash */
//   FLASH13_RSVD     : origin = 0x0BFFF0, length = 0x000010  /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */

   CPU1TOCPU2RAM   : origin = 0x03A000, length = 0x000800
   CPU2TOCPU1RAM   : origin = 0x03B000, length = 0x000800
   CPUTOCMRAM      : origin = 0x039000, length = 0x000800
   CMTOCPURAM      : origin = 0x038000, length = 0x000800

   CANA_MSG_RAM     : origin = 0x049000, length = 0x000800
   CANB_MSG_RAM     : origin = 0x04B000, length = 0x000800

   RESET            : origin = 0x3FFFC0, length = 0x000002
}

SECTIONS
{
   codestart           : > BEGIN, ALIGN(8)
   .text               : >> FLASH1 | FLASH2 | FLASH3,   ALIGN(8)
   .cinit              : > FLASH2 | FLASH3, ALIGN(8)
   .switch             : > FLASH1, ALIGN(8)
   .reset              : > RESET, TYPE = DSECT /* not used, */
   .stack              : > RAMM1

#if defined(__TI_EABI__)
   .init_array      : > FLASH1, ALIGN(8)
   .bss             : >> RAMLS4 | RAMLS5 | RAMLS6 | RAMLS7 | RAMGS2
   .bss:output      : > RAMLS3
   .bss:cio         : > RAMLS5
   .data            : > RAMLS5
   .sysmem          : > RAMLS5
   /* Initalized sections go in Flash */
   .const           : > FLASH3, ALIGN(8)
#else
   .pinit           : > FLASH1, ALIGN(8)
   .ebss            : > RAMLS5
   .esysmem         : > RAMLS5
   .cio             : > RAMLS5
   /* Initalized sections go in Flash */
   .econst          : >> FLASH2 | FLASH3, ALIGN(8)
#endif

   ramgs0 : > RAMGS0, type=NOINIT
   ramgs1 : > RAMGS1, type=NOINIT
   
   PIXDATA_RAM > RAMGS3_to_10, type=NOINIT

   MSGRAM_CPU1_TO_CPU2 : > CPU1TOCPU2RAM, type=NOINIT
   MSGRAM_CPU2_TO_CPU1 : > CPU2TOCPU1RAM, type=NOINIT
   MSGRAM_CPU_TO_CM    : > CPUTOCMRAM, type=NOINIT
   MSGRAM_CM_TO_CPU    : > CMTOCPURAM, type=NOINIT

   /* The following section definition are for SDFM examples */
/*   Filter_RegsFile  : > RAMGS0
   Filter1_RegsFile : > RAMGS1, fill=0x1111
   Filter2_RegsFile : > RAMGS2, fill=0x2222
   Filter3_RegsFile : > RAMGS3, fill=0x3333
   Filter4_RegsFile : > RAMGS4, fill=0x4444
   Difference_RegsFile : >RAMGS5, fill=0x3333 */

   #if defined(__TI_EABI__)
       .TI.ramfunc : {} LOAD = FLASH3,
                        RUN = RAMLS0 | RAMLS1 | RAMLS2 |RAMLS3,
                        LOAD_START(RamfuncsLoadStart),
                        LOAD_SIZE(RamfuncsLoadSize),
                        LOAD_END(RamfuncsLoadEnd),
                        RUN_START(RamfuncsRunStart),
                        RUN_SIZE(RamfuncsRunSize),
                        RUN_END(RamfuncsRunEnd),
                        ALIGN(8)
   #else
       .TI.ramfunc : {} LOAD = FLASH3,
                        RUN = RAMLS0 | RAMLS1 | RAMLS2 |RAMLS3,
                        LOAD_START(_RamfuncsLoadStart),
                        LOAD_SIZE(_RamfuncsLoadSize),
                        LOAD_END(_RamfuncsLoadEnd),
                        RUN_START(_RamfuncsRunStart),
                        RUN_SIZE(_RamfuncsRunSize),
                        RUN_END(_RamfuncsRunEnd),
                        ALIGN(8)
   #endif

}

/*
//===========================================================================
// End of file.
//===========================================================================
*/

you probably get what I was trying to do. but assuming the addresses where correct and the approach is correct, how do I jump to the starting address of the main program from the bootloader?

From the documentation, it seemed to me that something like this should be enough, but I never got it to work: int jump_to_main_program() { return 0x088002; }

2. I do not know how to access/read from the SD card. I have some mmc_F2828x.c file in my project that gives me access to the drive and a ff.h file that deals with files/FRESULTs. I tried opening a file that just contains the string 'hello' with this snippet:

FRESULT fresult = f_open(&update_file, "/hello", FA_READ);

but it doesn't work (sorry for unformatted code snippets, but this website doesn't let me use C code snippets.) Must be that I also need to use disk_read() somehow. I am quite confident that I figure out the SD card stuff on my own in the end, but I have no confidence in my ability to figure out how to jump to a specific address and how to overwrite specific parts of the flash and how to order bootloader and main program. I feel very lost with this task.

I would already greatly appreciate if someone could just point me in the direction of where to learn how this stuff works. I also checked out the C2000 Academy, but it didn't help me at all. I feel like I am just brute forcing things and have no idea what I am doing, contrary to my usual development tasks with python or rust.

  • Hi Vincenzo, 

    Apologies for the delay in reply.  First, note that the task of developing a bootloader is not a simple one and if you do not have a reasonably good understanding of C, this is going to be a challenge.  It looks like you already aware of the knowledge gap please allocate enough bandwidth to go through the learning curve to implement your solution. 

    The F2838x is one of our more complex devices.  It contains three CPUs.  So the first thing we would recommend is that you determine what your requirements are? Which boot mode will you be using?

    We have several resources that can help.  A good place to start is the F2838x Technical Reference Manual. https://www.ti.com/lit/pdf/spruii0c

    You can review chapter 5.  

    At this point, do not worry about how to jump to and run the application.  Please focus on the design and implementation of communicating with a host and getting the F2838x application into the target.

    Do you have C2000Ware and have you run some of the examples to get more familiar with the F2838x device?

    You can also study this application note:  https://www.ti.com/lit/an/sprabv4e/sprabv4e.pdf

    Please let us know with specific questions based on your understanding of the details available in the above documentation.

    Regards,

    Krishna