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.

Compiler/TMS320F28075: "ramfuncs" linker behavior

Part Number: TMS320F28075


Tool/software: TI C/C++ Compiler

I have implemented a CRC32 to perform a ROM check on power-up which computes the CRC for flash sectors A through G. These flash sectors include the following sections of my .cmd file: .cinit, .pinit, .text, .econst, and .switch. The CRC works as expected; I also make sure to skip the flash addresses where the expected CRC value is stored so that updating the expected CRC definition does not affect the CRC calculation. The CRC does not run through flash sector H, where I store "ramfuncs" functions. However, it appears that modifications to "ramfuncs" functions affect the calculated CRC value. When analyzing the .map file, references to modules that exclusively contain "ramfuncs" are only in sector H and various RAM addresses. Since the CRC doesn't check these sections, why does the calculated CRC change after modifying "ramfuncs" functions? It seems that some part of these functions exist in the flash sectors that I am checking, though this is not apparent in the .map file.

I've attached the .cmd and .map file where the module "test" only contains a single function "test_1" which is part of "ramfuncs". If you search on this in the .map file you will see that it does not appear in any addresses in flash sectors A through G, yet when I modify an operation in that file (e.g. change a multiply to an add), the CRC changes.

4540.map.txt

MEMORY
{
// program memory
PAGE 0 :
   // BEGIN is used for the "boot to Flash" bootloader mode
   BEGIN           	: origin = 0x080000, length = 0x000002
   // RAM sections
   //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
   RAMLS            : origin = 0x008000, length = 0x002800
   RESET           	: origin = 0x3FFFC0, length = 0x000002
   
   // flash sectors
   FLASHA           : origin = 0x080002, length = 0x001FFE
   FLASHB           : origin = 0x082000, length = 0x002000
   FLASHC           : origin = 0x084000, length = 0x002000
   FLASHD           : origin = 0x086000, length = 0x002000
   FLASHE           : origin = 0x088000, length = 0x008000
   FLASHF           : origin = 0x090000, length = 0x008000
   FLASHG           : origin = 0x098000, length = 0x008000
   FLASHH           : origin = 0x0A0000, length = 0x008000

// data memory
PAGE 1 :
  // Memory (RAM/FLASH) blocks can be moved to PAGE0 for program allocation
  // part of M0, BOOT rom will use this for stack
  BOOT_RSVD       : origin = 0x000002, length = 0x000120
  // RAM sections
  RAMM0           : origin = 0x000122, length = 0x0002DE
  RAMM1           : origin = 0x000400, length = 0x000400
  RAMD0           : origin = 0x00B000, length = 0x000800
  RAMD1           : origin = 0x00B800, length = 0x000800

  RAMLS5      : origin = 0x00A800, length = 0x000800

  RAMGS0      : origin = 0x00C000, length = 0x001000
  RAMGS1      : origin = 0x00D000, length = 0x001000
  RAMGS2      : origin = 0x00E000, length = 0x001000
  RAMGS3      : origin = 0x00F000, length = 0x001000
  RAMGS4      : origin = 0x010000, length = 0x001000
  RAMGS5      : origin = 0x011000, length = 0x001000
  RAMGS6      : origin = 0x012000, length = 0x001000
  RAMGS7      : origin = 0x013000, length = 0x001000

  // flash sectors
  FLASHI           : origin = 0x0A8000, length = 0x008000
  FLASHJ           : origin = 0x0B0000, length = 0x008000
  FLASHK           : origin = 0x0B8000, length = 0x002000
  FLASHL           : origin = 0x0BA000, length = 0x002000
  FLASHM           : origin = 0x0BC000, length = 0x002000
  FLASHN           : origin = 0x0BE000, length = 0x002000
}


SECTIONS
{
  // allocate program areas:
  .cinit              : >  FLASHA | FLASHB            PAGE = 0, ALIGN(4)
  .pinit              : >  FLASHA | FLASHB,           PAGE = 0, ALIGN(4)
  .text               : >> FLASHC | FLASHD | FLASHE   PAGE = 0, ALIGN(4)
  codestart           : > BEGIN                       PAGE = 0, ALIGN(4)

  GROUP
    {
      ramfuncs
      { -l F021_API_F2837xD_FPU32.lib}
    } LOAD = FLASHH,
      RUN = RAMLS,
      LOAD_START(_RamfuncsLoadStart),
      LOAD_SIZE(_RamfuncsLoadSize),
      LOAD_END(_RamfuncsLoadEnd),
      RUN_START(_RamfuncsRunStart),
      RUN_SIZE(_RamfuncsRunSize),
      RUN_END(_RamfuncsRunEnd),
      PAGE = 0, ALIGN(4)
						 
  // allocate uninitalized data sections:
  .stack              : >  RAMD0                          PAGE = 1
  .ebss               : >> RAMGS6 | RAMGS7                PAGE = 1
  .esysmem            : >> RAMGS6 | RAMGS7                PAGE = 1

  // initalized sections go in Flash
  .econst             : >> FLASHF        PAGE = 0, ALIGN(4)
  .switch             : >  FLASHG        PAGE = 0, ALIGN(4)

  .reset              : > RESET,     PAGE = 0, TYPE = DSECT /* not used, */

  ramgs0           : > RAMGS0,    PAGE = 1
  ramgs1           : > RAMGS1,    PAGE = 1
}

  • Thinking out loud, when you change a ramfuncs function, the memory map may shift and change the address of the various ramfuncs functions.  You call these functions from your regular .text code.  Hence, the calling address changes in the .text flash.

    Also, you copy the ramfuncs from flash to ram.  The start, end, and length parameters embedded with the copy function in the .text section change, right?

    Just two thoughts...

    - David

  • Good answer. I verified this by changing the end address of the ROM check to just before and after memcpy; the CRC is not affected prior to memcpy and is affected subsequent to it (also the length of the modified "ramfuncs" function changes when I modify an operator). I do have a followup question:

    When I adjust the end address of the ROM check to include flash sector H (where "ramfuncs" are stored), the calculated CRC changes as I modify the expected CRC value, thus preventing me from being able to define the expected CRC. Presumably this is because my modified expected checksum (i.e. ROM_CHECKSUM) exists in the program data to initialize the value, so the modified expected CRC affects the subsequent CRC calculation. I suppose this is more of a C question than a TI question, but is there an easy way to have this function skip over the memory location where "ROM_CHECKSUM" exists without resorting to function pointers and using specific addresses in the .map file?



    #pragma CODE_SECTION(rom_check, "ramfuncs");

    void rom_check(FRAMEWORK *framework)
    {
    static const Uint32 expected_checksum = ROM_CHECKSUM;
    Uint32 *rom_address = ((Uint32 *)(Bzero_SectorA_start));
    // initialize the ROM checksum
    framework->rom_checksum = 0;
    // loop through ROM addresses to the endpoint
    while(rom_address < ((Uint32 *)(Bzero_SectorH_End))) {
    // make sure we skip the stored checksum address
    if(rom_address != &expected_checksum) {
    // update the current checksum
    framework->rom_checksum = crc32_single(framework->rom_checksum, (*rom_address) );
    }
    // increment the ROM address
    rom_address++;
    }
    // set the checksum mismatch flag
    framework->status.bit.rom_fault = (framework->rom_checksum != expected_checksum);
    }