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.

Addressing beyond 16-bit addresses

Other Parts Discussed in Thread: MSP430F5418A, MSP430F5418, MSP430F5659

Hi, I am having problems addressing when the data addresses are 17-bit+.

The warnings that I am getting are like this one:
relocation from function "UI_handleObjects" to symbol "testObj" overflowed; the 17-bit relocated address 0x19000 is too large to encode in the 16-bit field (type = 'R_MSP_REL16' (161), file = "./UserInterface.obj"

void

 

UI_handleObjects( void )
{
char teststring[20] ;
testObj[0].captionObjNo = 1 ;
strcpy( testObj[1].data.string ,
"Test str" ) ;
}

 

I am using large data and large code model with CCS 4 Core Version: 4.1.3.00038,

 

Is this warning something to worry about? I assume it is. 
How do I address data in 17-bit+ address ranges? Any examples how this is done?

Hope someone out there has an answer. :)

Thanks,
Bo

As a bonus question, how do I verify that CCS4 is running with the right license?

 

 

  • Hi Bo,

    You're right about it being a serious error.

    Your linker appears to be angry with your compiler for not giving it enough space to insert an offset.  Do you have the correct MSP430 target selected in CCS?

    Can you post your declaration of testObj (including all pragmas, modifiers, and other decorating), and can you also post the assembly output of the compiler for this block of code.  The compiler seems to have picked the wrong addressing mode (by virtue of using a non-X instruction), which is why I ask about the target processor.

    Could just be a bug in CCS, too.

    Jeff

     

  • Hello Jeff, thank you for your swift reply.

    The objects I use are a little complex, so I have made a little modification, doing a smimilar action but to an ordinary unsigned char in the same memory range as the object was located. Doesn't get much simpler than this.

    From UserInterface.c:

     

    #pragma DATA_SECTION(testByte, ".testObjSeg") ;
    unsigned

     

    char testByte ;

     

     

     

    void UI_handleObjects( void )
    {

    testByte ++ ;
    }


    From lnk_msp430f5418a.cmd:
    ...
    TEST_OBJ_SEG : origin = 0x19000, length = 0x08000
    ...
    .testObjSeg : {} > TEST_OBJ_SEG
    ...

    I am still getting the same warning:

    "UI_handleObjects" to symbol "testByte" overflowed; the 17-bit relocated address 0x19000 is too large to encode in the 16-bit field (type = 'R_MSP_REL16' (161), file = "./UserInterface.obj", offset = 0x00000002, section = ".productCaption:UI_handleObjects")  ......

    The resulting dissasembly of the function is:

    UI_handleObjects:
    0x095AE:   53D2 9000           INC.B   &0x9000
    0x095B2:   0110                RETA

    Which clearly shows that the address 0x19000 is truncated to 0x09000.
    Am I configuring the compiler, the linker, og something else wrong?

    Compiler arguments:
    -vmspx --large_memory_model -g --include_path="C:/Programmer/Texas Instruments/ccsv4/msp430/include" --include_path="C:/Programmer/Texas Instruments/ccsv4/tools/compiler/msp430/include" --diag_warning=225 --code_model=large --data_model=large --printf_support=minimal

    Using: Code Composer Studio Core Edition Version: 4.1.3.00038

    Thanks in advance.

    Best regards, Bo

  • Hi Bo,

    I did a 'quick and dirty' test with some code if tested for answering another post. If edited the linker command file and was able to compile without errors.

    #include "msp430f5418.h"

    int test[7680] = { 1 };


    #pragma DATA_SECTION(testByte, ".testObjSeg") ;
    unsigned char testByte [50];

    void main( void )
    {
      // disable watchdog timer
      //------------------------
      WDTCTL = WDTPW + WDTHOLD;               // Stop WDT
     
      test[3] = test[4];
      test[7678] = 0xaa;
      test[7679] = 0xa0;
      test[0] = test[7679] - test[7678];
    }

    I've placed your user-defined-segment at the end of flash memory (after FLASH2) like:

    MEMORY
    {
        ...
        FLASH                   : origin = 0x5C00, length = 0xA380
        FLASH2                  : origin = 0x10000,length = 0x0DC00 /* keep in mind to reduce the size of FLASH2 !*/
        TEST_OBJ_SEG    : origin = 0x1DC00,length = 0x08000   
        INT00                   : origin = 0xFF80, length = 0x0002
        ...

    My .map file then shows correct allocation:

    Pls have a look at your .cmd file and keep us posted if this was your problem. In addition, be shure to have LARGE-DATA MEMORY MODEL enabled!

    Kind regards
    aBUGSworstnightmare

     

  • Hello aBUGSworstnightmare,

    I have made a completely new project and copy-pasted your code. And no compilation errors. However, you never access the testByte[50] array, only the test array located in ram. Therefore no operations is performed in the high end of flash. As soon as I modified your code, the warning returned.

    void main( void )
    // disable watchdog timer
    //------------------------
    WDTCTL = WDTPW + WDTHOLD;
    // Stop WDT
    test[3] = testByte[4];
    test[7678] = 0xaa;
    test[7679] = 0xa0;
    test[0] = test[7679] - test[7678];
    }

    If you modify the main routine as I did, do you still not see the warning?

    I realize that in the original code I posted this morning, I was actually trying to modify the values in flash directly, which may have resulted in usage of operations not meant to operate in 17-bit+. However, seeing that the code in this post also has the problem, it must be something else causing it.

    Best regards,
    Bo

  • Hi Bo,

    have you tested the result when using a pointer to testByte?

    #include "msp430f5418.h"

    int test[7680] = { 1 };


    #pragma DATA_SECTION(testByte, ".testObjSeg") ;
    unsigned char testByte [50];
    unsigned char *pointer;

    void main( void )
    {
      // disable watchdog timer
      //------------------------
      WDTCTL = WDTPW + WDTHOLD;               // Stop WDT
     
      pointer = &testByte[4];
      test[3] = *pointer;
      test[7678] = 0xaa;
      test[7679] = 0xa0;
      test[0] = test[7679] - test[7678];
    }

    Rgds
    aBUGSworstnightmare

    P.S. I'm sry! as mentioned above I do not have any HW at hands at the moment, so I can not debug it myself to see what happens. 

  • Thank you very much for the suggestion. By addressing a pointer to the right object in the object array (which virtually already is a pointer plus an offset), the warning disappeared.

    void UI_loadObject( uint objNo )
    {
      object* objPointer = &objectArray[objNo] ;
      uint type = (*objPointer).type & 0xFF00 ;
      switch( type )
      {
      ....
      }
    }

    I do not understand why my original method isn't possible, as I assume that this µC should be able to directly access these addresses. However I will use the pointer method instead to work around the problem.
    Thanks again :-)

    Best regards,
    Bo Simmons

     

  • Hi Bo,

    well, I think that is not an issue with the micro! This is related how the compiler deals with pointers (although a pointer should be 20-bit when using large memory model).

    Because I don't have an real answer to this I will post a question in the CCS forum.

    aBUGSworstnightmare


  • Hi Bo,

    The CCS compiler could be looking at the section type of the target variable.  Because you used "DATA_SECTION", the compiler assumes the variable is in RAM, which is always addressable with absolute addressing "&", 0x0000 through 0xFFFF, no matter the memory model or target processor.

    If you're still interested, try a section type like CONST_SECTION.  (I don't use CCS so I don't know the proper type name.)  Your code can still write to that flash area even if you tell the linker the section type is CONST.

    Jeff

     

  • Jeff Tenney said:
    The CCS compiler could be looking at the section type of the target variable.

    The compiler has no idea where a section is located. Only the linker knows. So the compiler just makes a simple assumption:

    If it is a variable, it is in RAM (or it couldn't be a variable) and therefore in the lower 64k and requires a 16 bit pointer for accessing it. All accesses are done using the smaller and faster 16 bit code.
    If it is a constant, it is located in Flash and its address may be 20 bit (large data model).
    Pointers in large data model are 32 bit (the upper 12 bits being don't care and may change/clear without notice), as the compiler does not know whether it will later point to a constant or a variable.

    Just declare the data you put above 64k as const and the compiler should generate the proper code (actually, the upper 4 bit of a 20 bit pointer are part of the instruction itself rather than an instruction parameter, so different instructions are needed for 20 bit pointers) and the linker can insert the address (which might still be 16 bit, depending on the linker file). Of course the data then is read-only. But it is in flash and you shouldn't write to flash anyway except in separate writing functions.

  • Yet another "Ahaa-experience", now everything makes sense.

    Thank you very much Jens-Michael.

  • Jens-Michael Gross said:
    Just declare the data you put above 64k as const and the compiler should generate the proper code (actually, the upper 4 bit of a 20 bit pointer are part of the instruction itself rather than an instruction parameter, so different instructions are needed for 20 bit pointers) and the linker can insert the address (which might still be 16 bit, depending on the linker file). Of course the data then is read-only. But it is in flash and you shouldn't write to flash anyway except in separate writing functions.

    Jens-Michael,

    I am having a similar issue in my program, which has become very large due to a huge amount of data buffering. Changing the offending variable in my case to include the 'const' keyword works as you suggested; however, I cannot help but think there must be a better way to do this. I have changed the code and data model to large. CCS appears to not understand the 'far' keyword also.

    Eventually, I would like to bootstrap the code to program and update devices in the field. With the bootstrapped release, won't this issue become a larger problem? Or should I just declare all data items that go into RAM as 'const'?

    Thank you for the input,

    Blaine

  • Brandon Gardner said:
    there must be a better way to do this

    I don't think there is a better way to put data in flash only than to declare it const. If data is in flash, it is read-only and therefore constant. If it should be read/write, it needs to be in ram.

    Brandon Gardner said:
    I have changed the code and data model to large

    This is required to allow 20 bit data pointers and accessing (constant) data above 64k. However, it makes the code bigger and slower, requiring two 16 bit writes on each register save (and restore).

    There are a few MSPs with RAM above 64k. In this case, of course variables can be placed in RAM too and are read/write then. Using this ram area also requires large data model.

    Brandon Gardner said:
    CCS appears to not understand the 'far' keyword also.

    No. The structure requires either all of the code to use the same code and/or data model. So either all pointers are far or none is. Else you'd lose significant address bits when pointers are stored on stack.
    On PC, the 'far' and 'near' means that a pointer has a separate segment address or uses the current data segment. But the MSP does not have segment registers at all. The pointer is the absolute address, and the model defines whether 16 or 20 bit instructions are used to handle the pointer address in a register.

    Brandon Gardner said:
    Or should I just declare all data items that go into RAM as 'const'?

    This would make them read only and move them from ram to flash.
    Which is of probably not what you want.
    However, I don't have enough information about your project and the exact issue. So I can't say anything definitive.
    I'd need code excepts, memory maps or such, and a more detailed information about what exact problem you have where.
    The statement 'I have the same problem' usually doesn't mean 'exactly the same problem', but rather 'a similar problem' or 'a problem that seems to me as if it were loosely related'. In many cases, the reasons adn the solutions turn out to be quite different.

    What I can say... in case of a field update, you replace the current firmware by a new one. completely. Including its data structures and memory positions. Each versions is consistent by itself and doesn't care nor have to care for what the previous version placed where.
    Except if you store data in an INFO segment and pass it to the next version. Then of course both versions need to access the INFO segment in the same way.

  • I have constructed a simple example to re-create the specific issue I am having with my MSP430F5659, which has 64k of RAM available. 16k is available as RAM starting at 0x2400, and 48k is available as RAM2 starting at 0xf0000.

    I am receiving an error as follows: 

    #17003-D</a> relocation from function "main" to symbol "huge_buffer" overflowed; the 20-bit
    relocated address 0xf0000 is too large to encode in the 16-bit field (type = 'R_MSP430_ABS16_MSPX' (15), file = "./main.obj", offset = 0x00000026, section = ".text:main")

    Below is the code from my main.c file. It is the only file in a brand new project I created. I have made sure to compile using the large data model, but the issue remains.

    I have done a lot of Google searches related to the issue, and I can find no solution to my problem. Has anyone used the upper RAM section of the 5659 or 5658 successfully? I can find no example code accessing this region either.

  • Very curious.  Unless you've done something strange in your project settings relating to the large data model, you have found an issue with your compiler.  It didn't use the right instruction(s) to leave enough room for the linker to do its job.


    You're using CCS?  Have you checked for any updates?


    Jeff

  • My CCS and compiler were updated within the month. I will check for updates when I get back to work tomorrow; however, I am not hopeful of its efficacy.

    As for the project settings, I created a brand new project and simply changed the data model to large. I modified no other settings.

  • Here are some details about my current set-up:

    Microcontroller: MSP430F5659  (REV A)

    CCS Version: 5.4.0.00091 

    Compiler Version: Ti v4.1.8

    Additionally, I made sure to check for and update all parts of CCS this morning. If it truly is a compiler error, how do I go about getting help from TI personnel?

  • What processor did you pick in the project configuration?  I quickly scanned the change log for CCS and didn't see support for F5659 or F5359.  I did see F6659 which I'm guessing is the same plus LCD.  In that case, there's no excuse for CCS to have this bug if F6659 is supported.

    I know it's lame but try those other variants of processor selection just as a test case.

    And I don't know how to get help with CCS.  (I use IAR.)

    Jeff

  • I think this is already discussed earlier. Create a 20-bit pointer:

    int main(void) {
    	WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    	
    	unsigned char i, *p;
    	unsigned short j;
    
    	for (i=0; i<50; i++)
    	{
    		for (j=0; j<512; j++)
    		{
    	//		huge_buffer[i][j] = 1 + (unsigned char) j;
    			p = huge_buffer[i];
    			p[j] = 1 + (unsigned char) j;
    		}
    	}
    
    	return 0;
    }

  • Jeff,

    As per your suggestion, I changed my processor type to the 6659 as well as 6458 to test the compilation. Unfortunately, the compilation failed in the same manner. Using the 6769, however, the compilation succeeds, but it does not have split RAM like the others do. Thank you for the suggestion.

    Leo,

    I also appreciate your suggestion and noticed that the 20-bit pointer trick worked previously; however, I cannot help but feel that I should have to rely on awkward coding tricks to get the compiler to generate appropriate code.

    Blaine

  • As I see it; Array’s are a simple and fast way to access small data stacks, the pointer is mostly relative and therefore they have a small range. It’s legal to define the array but you get a warning if you want to access it on the relative way.

    But I guess JMG can tell you a lot more about this.

  • Additionally, a probably better way is:

    unsigned char huge_buffer[50][512];
    
    int main(void) {
    	WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    	
    	unsigned char i, **p;
    	unsigned short j;
    
    	p = (unsigned char**)huge_buffer;
    	for (i=0; i<50; i++)
    	{
    		for (j=0; j<512; j++)
    		{
    			p[i][j] = 1 + (unsigned char) j;
    		}
    	}
    
    	return 0;
    }
    

  • I agree with Blaine (Brandon). It's a strange work-around (hack) to use a separate pointer.  There isn't any functional reason to prefer a pointer over a direct array reference.  In fact, in MSP430 there's good reason to use the array directly.

    It's really just a matter of the compiler using the wrong instruction.  For example, in MCUs with all RAM below 0x10000, you can use this:

    MOV.B   R15, huge_buffer(R14)

    However, this won't work if huge_buffer gets located above 0x10000.  There's only one 16-bit word in the instruction dedicated to the address of huge_buffer.  The linker can't fit the final address into 16-bits.  The compiler needs to use this instead:

    MOVX.B  R15, huge_buffer(R14)

    The 'X' instruction leaves two 16-bit words for the address of huge_buffer.  That would work.

    The pointer approach works because the compiler calculates the final address and uses a zero for the index, like this:

    ADDA    R13, R14    ; R13 is the work-around pointer (points to huge_buffer)
    MOV.B   R15, 0(R14)

    Slower but it works.  Actually, because this ADDA is only one cycle, this is the same speed as the MOVX.B.

    Blaine please let us know what the CCS people tell you.  It's a pretty clear bug from what I see.  Thanks.

  • Leo Bosch said:
    But I guess JMG can tell you a lot more about this.

    Thank you for your faith in me :)

    I don't know the code actually generated by the compiler. But it is possible that that compiler generates an access of the array using the Address instructions (MOVA) to access the array.

    MOVA supports 20bit register and immediate values, but only 16 bit signed offset in indirect addressing mode.

    Now indirect addressing mode means the base address is in a register and the offset is hard-coded as immediate value. However, usually, you need the base address hard-coded and the index is variable (in a register) and this is howthe compiler uses it. In 16 bi taddress range, it doesn't matter. But in case of an array in upper memory, the base address is 20 bit and the index is 16 bit (or 20 bit too for arrays >64k).

    Now the compiler simply generates the MOVA instruction and the linker can't put the 20 bit array base address into the 16 bit immediate value of the MOVA instruction. Unfortunately, the compiler doesn't know that the array will end up in upper memory. Probably a bug, as the MOVX.A instruction could be used, whcih supports 20 bit offset constants. It is just a tick slower and 2 bytes larger.

    A similar bug appeared some time ago with a jumptable located in lower memory but above 32k. The compiler used CALLA x(Ry) to access the function pointer and call the funciton. Now x is a signed 16 bit offset to Ry (and therefore negative) and not otherwise. So the instruction was loading the function pointer from 0xF8xxx instead of 0x08xxx. Here not even a linker error was reported. Just broken code. Verified by viewing the compiler generated assembly code.

  • I can reproduce that linker diagnostic.  This smells like a problem in the compiler to me.  So I filed SDSCM00049596 in the SDOWP system to have this investigated.  Feel free to follow it with the SDOWP link below in my signature.

    Thanks and regards,

    -George

  • The default data memory model is small.  The small data model only allows data to be located in the low 64k of memory.   To get the desired behavior, change the data memory model (i.e. --data_model=[restricted, large]) and use --near_data=none (global variables by default are near).

    -Mack 

  • I have tried changing the memory model to default, to large, to small, and leaving it blank; however, none of these options fix the issue. How do I change the model to restricted large via the settings?

  • You would use --data_model=restricted and --near_model=none.

    -Mack

  • In Project Properties select CCS Build\MSP430 Compiler\Processor Options and select;

    Silicon version [mspx] (which I guess you already have)

    Code memory model [blank] (not relevant for this case)

    Data memory model [large] (the important one)

    Near [blank] (in my opinion not relevant for this case)

    This setup must work without errors/warnings, if not maybe you have to update your CCS.

  • Mack,

    Thank you for the clarification. My problem was not specifying the near_model as none. I read the optimizing compiler document and now have a better understanding of what the near_model options do; however, it was not apparent that this should be changed to none for a program with data above 64k. This may be something that should be clarified in the document.

    Blaine

**Attention** This is a public forum