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.

Problem when placing constant data into INFOB Info Flash segment using CCE V3.1

Other Parts Discussed in Thread: MSP430F2012

Hi, I try to place 64bytes of constant data (altered by the application during runtime) to Info Flash Segment INFOB but I always get an error message like "../lnk_msp430f2012.cmd", line xxx: error: run placement fails for object ".infoB" I'm converting a well working project from IAR to CCE V3.1 when I encountered the problem. I have made a short demo program to aid in verifying the problem and - hopefully - sending me an answer how to fix it. The source code in the demo below is taken from various TI App Notes and I only made minor changes to it (main is from 'msp430x20x3_1.c Software Toggle P1.0' (see App Notes slac080e.zip) and the flash routines are from the 'MSP-EXP430F5438_User_Experience_CCE' (see App Notes slac227.zip) Demo Application. Thank you in advance for your answer(s), regards Gookbuster /* DEMO APPLICATION STARTS HERE */ /* quick and dirty INFOB error demo * unable to place more than 9bytes (variable1 to variable7) of const data into INFOB segment * using CCE V3.1 * to verify the problem try to rebuild the project with variable8 and * variable9 included --> this is resulting in an error message: "../lnk_msp430f2012.cmd", line 355: error: run placement fails for object ".infoB" */ #include /*------------------------------------------------------------- * Macros * ------------------------------------------------------------*/ #define FLASH_UNLOCK FCTL3 = FWKEY; FCTL1 = FWKEY + WRT; #define FLASH_LOCK FCTL1 = FWKEY; FCTL3 = FWKEY + LOCK; #define FLASH_WRITE_INFOB(destination, source) st( FLASH_UNLOCK_INFOB; destination = source; while (FCTL3 & BUSY ); FLASH_LOCK_INFOB; ) //--Calibration constants and user configuration values stored in INFOB Flash-- #pragma DATA_SECTION(variable1, ".infoB"); #pragma DATA_SECTION(variable2, ".infoB"); #pragma DATA_SECTION(variable3, ".infoB"); #pragma DATA_SECTION(variable4, ".infoB"); #pragma DATA_SECTION(variable5, ".infoB"); #pragma DATA_SECTION(variable6, ".infoB"); #pragma DATA_SECTION(variable7, ".infoB"); //#pragma DATA_SECTION(variable8, ".infoB"); //#pragma DATA_SECTION(variable9, ".infoB"); #pragma DATA_ALIGN(variable1, 8); #pragma DATA_ALIGN(variable2, 8); #pragma DATA_ALIGN(variable3, 16); #pragma DATA_ALIGN(variable4, 8); #pragma DATA_ALIGN(variable5, 8); #pragma DATA_ALIGN(variable6, 16); #pragma DATA_ALIGN(variable7, 8); //#pragma DATA_ALIGN(variable8, 8); //#pragma DATA_ALIGN(variable9, 16); unsigned char variable1; unsigned char variable2; int variable3; unsigned char variable4; unsigned char variable5; int variable6; unsigned char variable7; //unsigned char variable8; //int variable9; // -- local variable set -- unsigned char variable1LOCAL = 0; unsigned char variable2LOCAL = 0; int variable3LOCAL = 0; unsigned char variable4LOCAL = 0; unsigned char variable5LOCAL = 0; int variable6LOCAL = 0; unsigned char variable7LOCAL = 0; //unsigned char variable8LOCAL = 0; //int variable9LOCAL = 0; /**********************************************************************//** * @brief Erases a bank in flash memory. * * @param FarPtr The pointer to the location in memory within the bank to * be erased. * * @return none **************************************************************************/ void flashEraseBank( unsigned long FarPtr) { unsigned long *Flash_ptr; // Flash pointer Flash_ptr = (unsigned long *) FarPtr; // Initialize Flash pointer FCTL3 = FWKEY; while (FCTL3 & BUSY ); FCTL1 = FWKEY + MERAS; *Flash_ptr = 0; // Dummy write to start erase while (FCTL3 & BUSY ); FCTL1 = FWKEY; FCTL3 = FWKEY + LOCK; } /**********************************************************************//** * @brief Erases a single segment of memory containing the address FarPtr. * * @param FarPtr The address location within the segment of memory to be * erased. * * @return none **************************************************************************/ void flashEraseSegment(unsigned long FarPtr) { unsigned long *Flash_ptr; // Flash pointer Flash_ptr = (unsigned long *) FarPtr; // Initialize Flash pointer FCTL3 = FWKEY; FCTL1 = FWKEY + ERASE; *Flash_ptr = 0; // Dummy write to start erase while (FCTL3 & BUSY ); FCTL1 = FWKEY; FCTL3 = FWKEY + LOCK; } /**********************************************************************//** * @brief Stores calibration and user-config data into INFOB flash * * @param none * * @return none *************************************************************************/ void saveSettings(void) { flashEraseSegment((unsigned long)&variable1); FLASH_UNLOCK; variable1 = variable1LOCAL ; variable2 = variable2LOCAL ; variable3 = variable3LOCAL ; variable4 = variable4LOCAL ; variable5 = variable5LOCAL; variable6 = variable6LOCAL ; variable7 = variable7LOCAL; //variable8 = variable8LOCAL; //variable9 = variable9LOCAL; FLASH_LOCK; } /**********************************************************************//** * @brief Loads calibration and user-config data from INFOB flash. * * @param none * * @return none *************************************************************************/ void loadSettings(void) { variable1LOCAL = variable1; variable2LOCAL = variable2; variable3LOCAL = variable3; variable4LOCAL = variable4; variable5LOCAL = variable5; variable6LOCAL = variable6; variable7LOCAL = variable7; //variable8LOCAL = variable8; //variable9LOCAL = variable9; } void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer P1DIR |= 0x01; // Set P1.0 to output direction for (;;) { volatile unsigned int i; P1OUT ^= 0x01; // Toggle P1.0 using exclusive-OR loadSettings(); // load data from INFOB i = 50000; // Delay do (i--); while (i != 0); variable1LOCAL++; // increment variable1LOCAL variable2LOCAL = 101; // change value for variable2LOCAL saveSettings(); // write data back to nfo Flash INFOB } } /* END OF DEMO APPLICATION */
  • When posting the example code all formatting were lost, so here's an new attempt.

     

    /* quick and dirty INFOB error demo
     * unable to place more than 9bytes of const data into INFOB segment
     * using CCE V3.1
     * to verify the problem try to rebuild the project with variable8  and
     * variable9 included
    */

    #include  <msp430x20x2.h>

    /*-------------------------------------------------------------
     *                       Macros
     * ------------------------------------------------------------*/
    #define FLASH_UNLOCK    FCTL3 = FWKEY; FCTL1 = FWKEY + WRT;
    #define FLASH_LOCK      FCTL1 = FWKEY; FCTL3 = FWKEY +  LOCK;
    #define FLASH_WRITE_INFOB(destination, source) st( FLASH_UNLOCK_INFOB;  destination = source; while (FCTL3 & BUSY ); FLASH_LOCK_INFOB; ) 

    //--Calibration constants and user configuration values stored in INFOB Flash--
    #pragma DATA_SECTION(variable1, ".infoB");
    #pragma DATA_SECTION(variable2, ".infoB");
    #pragma DATA_SECTION(variable3, ".infoB");
    #pragma DATA_SECTION(variable4, ".infoB");
    #pragma DATA_SECTION(variable5, ".infoB");
    #pragma DATA_SECTION(variable6, ".infoB");
    #pragma DATA_SECTION(variable7, ".infoB");
    //#pragma DATA_SECTION(variable8, ".infoB");
    //#pragma DATA_SECTION(variable9, ".infoB");


    #pragma DATA_ALIGN(variable1, 8);
    #pragma DATA_ALIGN(variable2, 8);
    #pragma DATA_ALIGN(variable3, 16);
    #pragma DATA_ALIGN(variable4, 8);
    #pragma DATA_ALIGN(variable5, 8);
    #pragma DATA_ALIGN(variable6, 16);
    #pragma DATA_ALIGN(variable7, 8);
    //#pragma DATA_ALIGN(variable8, 8);
    //#pragma DATA_ALIGN(variable9, 16);

    unsigned char variable1;
    unsigned char variable2;
    int variable3;
    unsigned char variable4;
    unsigned char variable5;
    int variable6;
    unsigned char variable7;
    //unsigned char variable8;
    //int  variable9;

    // -- local variable set --
    unsigned char variable1LOCAL;
    unsigned char variable2LOCAL;
    int variable3LOCAL;
    unsigned char variable4LOCAL;
    unsigned char variable5LOCAL;
    int variable6LOCAL;
    unsigned char variable7LOCAL;
    //unsigned char variable8LOCAL;
    //int  variable9;

    /**********************************************************************//**
     *  from file flashUtils.c
     *
     * taken from MSP-EXP430F5438_User_Experience_CCE (slac227.zip)
     **************************************************************************/
    /**********************************************************************//**
     * @brief  Erases a bank in flash memory.
     *
     * @param  FarPtr The pointer to the location in memory within the bank to
     *                be erased.
     *
     * @return none
     **************************************************************************/
    void flashEraseBank( unsigned long FarPtr)
    {
      FCTL3 = FWKEY;
      while (FCTL3 & BUSY );
      FCTL1 = FWKEY + MERAS;
     
      __data20_write_char(FarPtr, 0x00);        // Dummy write to start erase

      while (FCTL3 & BUSY );
      FCTL1 = FWKEY;               
      FCTL3 = FWKEY +  LOCK;
    }

    /**********************************************************************//**
     * @brief  Erases a single segment of memory containing the address FarPtr.
     *
     * @param  FarPtr The address location within the segment of memory to be
     *                erased.
     *
     * @return none
     **************************************************************************/
    void flashEraseSegment(unsigned long FarPtr)
    {
      FCTL3 = FWKEY;
      FCTL1 = FWKEY + ERASE;
     
      __data20_write_char(FarPtr, 0x00);        // Dummy write to start erase
     
      while (FCTL3 & BUSY );
      FCTL1 = FWKEY;               
      FCTL3 = FWKEY +  LOCK;
    }

    /**********************************************************************//**
     * @brief  Erases the (multiple) segment(s) of memory including address
     *         locations Memstart through Memend.
     *
     * @param  Memstart The starting address location identifying a segment of
     *                  memory to be erased
     *
     * @param  Memend   The ending address location identifying a segment of
     *                  memory to be erased
     *
     * @return none
     **************************************************************************/
    void flashErase(unsigned long Memstart, unsigned long Memend)
    {
      unsigned long FarPtr = Memstart;          // Start of record memory array
     
      FCTL3 = FWKEY;                            // Unlock Flash memory for write
      do
      {
        if ( (FarPtr & 0xFFFF) == 0x0000)       // Use bit 12 to toggle LED
          P1OUT ^= 0x01;

        FCTL1 = FWKEY + ERASE;
       
        __data20_write_char(FarPtr, 0x00);      // Dummy write to activate
       
        while (FCTL3 & BUSY );                  // Segment erase
        FarPtr += 0x0200;                       // Point to next segment
      } while (FarPtr < Memend);
     
      FCTL1 = FWKEY;               
      FCTL3 = FWKEY +  LOCK;
    }


    /*-------------------------------------------------------------------------*/
    /**********************************************************************//**
     * @brief  Stores calibration and user-config data into INFOB flash
     *
     * @param  none
     *
     * @return none
     *************************************************************************/
    void saveSettings(void)

      flashEraseSegment((unsigned long)&variable1);
      FLASH_UNLOCK;
      variable1 = variable1LOCAL ;
      variable2 = variable2LOCAL ;
      variable3 = variable3LOCAL ;
      variable4 = variable4LOCAL ;
      variable5 = variable5LOCAL; 
      variable6 = variable6LOCAL ;
      variable7 = variable7LOCAL;
      //variable8 = variable8LOCAL; 
      //variable9 = variable9LOCAL; 
      FLASH_LOCK; 
    }

    /**********************************************************************//**
     * @brief  Loads calibration and user-config data from INFOB flash.
     *
     * @param  none
     *
     * @return none
     *************************************************************************/
    void loadSettings(void)

      variable1LOCAL = variable1;
      variable2LOCAL = variable2;
      variable3LOCAL = variable3;
      variable4LOCAL = variable4;
      variable5LOCAL = variable5;
      variable6LOCAL = variable6;
      variable7LOCAL = variable7;
      //variable8LOCAL = variable8;
      //variable9LOCAL = variable9;
    }

    void main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
      P1DIR |= 0x01;                            // Set P1.0 to output direction

      for (;;)
      {
        volatile unsigned int i;

        P1OUT ^= 0x01;                          // Toggle P1.0 using exclusive-OR
       
        loadSettings();

        i = 50000;                              // Delay
        do (i--);
        while (i != 0);
       
        variable1LOCAL++;
        variable2LOCAL = 0xAA;
       
        saveSettings();
      }
    }

  • The linker error "placement fails for object" means that it was unable to allocate that section to the memory region, typically because the section is larger than the available memory. In your case you need to ensure that all your variables allocated to infoB are within the available 0x40 for INFOB memory

    PLease refer to
    http://tiexpressdsp.com/index.php?title=CCE_FAQ#What_does_the_CCE_linker_error:_.27placement_fails_for_object_.22xxx.22.27_mean_and_how_to_fix_it.3F

  • Hi Aarti, thanks for the answer. Here is the memory map for the demo project:

    MEMORY CONFIGURATION

             name            origin    length      used     unused   attr    fill
    ----------------------  --------  ---------  --------  --------  ----  --------
      SFR                   00000000   00000010  00000000  00000010  RWIX
      PERIPHERALS_8BIT      00000010   000000f0  00000000  000000f0  RWIX
      PERIPHERALS_16BIT     00000100   00000100  00000000  00000100  RWIX
      RAM                   00000200   00000080  00000044  0000003c  RWIX
      INFOD                 00001000   00000040  00000000  00000040  RWIX
      INFOC                 00001040   00000040  00000000  00000040  RWIX
      INFOB                 00001080   00000040  00000039  00000007  RWIX
      INFOA                 000010c0   00000040  00000000  00000040  RWIX
      FLASH                 0000f800   000007e0  000001e0  00000600  RWIX
      ..
      RESET                 0000fffe   00000002  00000002  00000000  RWIX

     

     This says, that 0x39 = 57bytes of INFOB memory is used by my application. I'm a little confused on that since I only placed 5 variables of type 'unsigned char' (--> 5bytes) and 2 variables of type 'int' (--> 4 bytes in total) in INFOB. That means 9bytes of variables placed in a segment which is 64bytes long should result in an available space of  55bytes. So, why is the linker allocating 57bytes for 9bytes of data?

    Is it possible that there's an error in the C compiler's user guide (SLAU132C, Nov 2008, see section 5.8.3; #pragma DATA_ALIGN (symbol, constant) with constant a power of 2 (?)? Because, when I change my variable defininition to

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    #pragma DATA_ALIGN(variable1, 1);
    #pragma DATA_ALIGN(variable2, 1);
    #pragma DATA_ALIGN(variable3, 2);
    #pragma DATA_ALIGN(variable4, 1);
    #pragma DATA_ALIGN(variable5, 1);
    #pragma DATA_ALIGN(variable6, 2);
    #pragma DATA_ALIGN(variable7, 1);
    //#pragma DATA_ALIGN(variable8, 1);
    //#pragma DATA_ALIGN(variable9, 2);

    with constant representing the number of bytes used by the variable the map file looks like

    MEMORY CONFIGURATION

             name            origin    length      used     unused   attr    fill
    ----------------------  --------  ---------  --------  --------  ----  --------
      ..
      INFOD                 00001000   00000040  00000000  00000040  RWIX
      INFOC                 00001040   00000040  00000000  00000040  RWIX
      INFOB                 00001080   00000040  00000009  00000037  RWIX
      INFOA                 000010c0   00000040  00000000  00000040  RWIX

    and that's what I would expect (9bytes used by 9bytes of data). It would be nice if someone could clarify this issue. Rgds Gookbuster

     

  • Gookbuster said:

    This says, that 0x39 = 57bytes of INFOB memory is used by my application. I'm a little confused on that since I only placed 5 variables of type 'unsigned char' (--> 5bytes) and 2 variables of type 'int' (--> 4 bytes in total) in INFOB. That means 9bytes of variables placed in a segment which is 64bytes long should result in an available space of  55bytes. So, why is the linker allocating 57bytes for 9bytes of data?

    Is it possible that there's an error in the C compiler's user guide (SLAU132C, Nov 2008, see section 5.8.3; #pragma DATA_ALIGN (symbol, constant) with constant a power of 2 (?)? Because, when I change my variable defininition to

    #pragma DATA_ALIGN(variable1, 1);
    #pragma DATA_ALIGN(variable2, 1);
    #pragma DATA_ALIGN(variable3, 2);
    #pragma DATA_ALIGN(variable4, 1);
    #pragma DATA_ALIGN(variable5, 1);
    #pragma DATA_ALIGN(variable6, 2);
    #pragma DATA_ALIGN(variable7, 1);
    //#pragma DATA_ALIGN(variable8, 1);
    //#pragma DATA_ALIGN(variable9, 2);

    with constant representing the number of bytes used by the variable the map file looks like

    MEMORY CONFIGURATION

             name            origin    length      used     unused   attr    fill
    ----------------------  --------  ---------  --------  --------  ----  --------
      ..
      INFOD                 00001000   00000040  00000000  00000040  RWIX
      INFOC                 00001040   00000040  00000000  00000040  RWIX
      INFOB                 00001080   00000040  00000009  00000037  RWIX
      INFOA                 000010c0   00000040  00000000  00000040  RWIX

    and that's what I would expect (9bytes used by 9bytes of data). It would be nice if someone could clarify this issue.

    The DATA_ALIGN pragma tells the compiler/linker to place the variable at an address location that is aligned on a boundary specified by the "constant" input.

    Using your example below:

    #pragma DATA_ALIGN(variable1, 8);
    #pragma DATA_ALIGN(variable2, 8);
    #pragma DATA_ALIGN(variable3, 16);
    #pragma DATA_ALIGN(variable4, 8);
    #pragma DATA_ALIGN(variable5, 8);
    #pragma DATA_ALIGN(variable6, 16);
    #pragma DATA_ALIGN(variable7, 8);

    variable1 and variable2 need to be aligned on an 8-byte boundary, which means variable2 would not be nested right next to variable1 in the memory map.  I suspect the address of variable1 and variable2 are :
    0x00001080 : variable1
    0x00001088 : variable2

    Similarly, variable3 would need to be aligned on an 16-byte boundary, which actually would be 0x00001090.

    Therefore, my expectation of the DATA_ALIGN() is aligned with the observations you have.  Does this make sense?

  • Hi Brandon,

    that's correct! My (expected) memory map look's like:

    0x00001080  :  variable1
    0x00001081  :  variable2
    0x00001082  :  variable3 (integer --> 2 bytes long --> uses address 0x00001082 and 0x00001083)
    0x00001084  :  variable4
    ...

     Unfortuneately, the compiler's user manual is not precise on this point (although 1 is a power of two (2^0 = 1), Maybe an example would help [:)]

    Thank's again for your support, rgds Gookbuster

**Attention** This is a public forum