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.

Code stop working with large-memory model

Other Parts Discussed in Thread: MSP430F149, MSP430F2418

Hi

 

I have a code that I have been using for a long time in MSP430F149. Now I want to use the same code in MSP430F2418. I have renamed the registers and the code is working fine when I don’t use the large memory model function in CCE (Version 3.1). My question is why don’t the code work when I use the large memory model? Does anyone know or have been able to use the large memory model with 2418?

 

  • On large memory mode, the number of bytes pushed on Stack for function call and return is higher, as a 20 bit address is required for return address. This breaks some code that is directly accessing data on the stack. (such as printf), if not adjusted for large memory. Also, interrupt functions still need to sit in lower 64K, as the interrupt vectors are 16 bit only and therefore always point into the lower 64k area. And of course all linked libraries need to be compiled for large memory too, so they will use the required return statements for a 20 bit return address.

    There are some other restrictions and considerations, includign the usage of pointers (which are 16 bit but now need to be 32 bit for holding the 20 bit memory address). If you put your constant data into lower 64KB only, it makes things easier.

     

  • Kristofer Klein said:
    Hi
     
    I have a code that I have been using for a long time in MSP430F149. Now I want to use the same code in MSP430F2418. I have renamed the registers and the code is working fine when I don’t use the large memory model function in CCE (Version 3.1). My question is why don’t the code work when I use the large memory model? Does anyone know or have been able to use the large memory model with 2418?

     

     

    When you say that your code doesn't work with the large memory model do you receive a compiler error? if so what is it?

  • No. The compiler compiles the code with no error. When debugging it seems that my pointers doesn’t work correctly.

    Example: if(GPSpnt = (strstr(&recGpsBuf[0], "$GPRMC"))), gives GPSpnt 0x00000 in debugg mode

     

    All my interrupt code is in the lower flash, and main code is in the upper flash.

     

    I have tried to read about the use of large memory model, but I don’t understand if I have to rewrite the hole code and only use _data20_read() _data20_write() for pinters?

  • In CCE V3 there was a bug involving large data model & pointers. I am not sure if this bug is fixed in the more recent CCS V4. Hopefully someone can clarify the status of this bug.

  • I am having issues as well with the large memory models using the MSP430F2418. I cannot get the debugger to run in either CCE or CCS when I switch over to large memory models. It does not run to main() when the debugger is launched in either case, and it sits there with the run button grayed out and the stop button active. I can click the stop button and see that it does stop in what I believe is cinit().  It appears as though the cinit() process never finishes, although I have not verified that just yet. Before I dig too deeply into this, has anyone been able to run the debugger with large memory models?

    It all works fine using the small model. I'm using CCS Version: 4.0.1.01001, and CCE Version: 3.2.2.1.8 with MSP-FET430UIF, both with the same results. To switch to the large memory model I select C/C++ Build/Tool Settings/MSP430 Compiler/Runtime Model Options and select the "Use large-data memory model (--large_memory_model)" checkbox, and I use the rts430xl.lib library (I tried all of them). It all compiles and loads just fine, but it never makes it to main(). I will dig a little deeper, but if someone knows of anything I'm doing wrong, please let me know.

    Thanks!

    Dave

  • I am having the exact same issue.

    My hardware and FET run properly with programs built without the large-data memory model.  One important note is that I am running with a slightly modified linker script. In the past, while using the default linker script, I was able to successful run and debug a large-data memory model builds.  I am thinking the issue may be related to my linker script modifications, but I they are minor and should not have an effect.

     

    Thanks,

    Josh

  • Well...  After a series of rebuilds, resets and reboots it just started to work.

    Not too sure what changed but the debugger now starts at main() and the program executes properly.

    Hate it when those things happen.

  • I wish I knew what you did. I have NEVER seen large memory models work. The debugger always sits there and never makes it to main(). I'm running CCS 4.2.4.00033. Am I really the only one having this problem? EVERYBODY else's  debugger runs to main()?

  • Just a guess:

    Maybe main() needs to be in lower 64k memory too.
    Because the C startup code is precompiled and linked-in. And if it does not jump to main as a 20 bit address at its end, it jumps to the wrong location.

    The reset vector, which points to the C startup code, is a 16 bit vector too. so to the startup code and maybe main, the same rules apply as for ISRs.

  • Why would the linker put main() anywhere but in lower 64? That's not something the user typically specifies. Am I missing something here? Looking at the debugger window I see it's never making it to the call to main(); it's getting stuck in cinit at a memcpy call between C$L2 and C$L3 (your results may vary) in lower 64K. I've looked all over but I cannot find any C or assembly source code for cinit. Is that available somewhere? It's painful trying to debug this using only the disassembly window.

     

    I also must be the only one on the planet that does not have a cursor in this post window. I'm just lucky, I guess.    :o)

     

    Thanks -

  • Dave 1024 said:
    Why would the linker put main() anywhere but in lower 64?

    because it is  code just as any other function?
    From the linkers view, there's nothing special on main() except that this name is coincidentally referenced by the startup code.

    If you want, you can declare main() as interurpt function, or let it return a pointer, or 'pass' it a long parameter list or whatever (okay, there might be strange effects later when the code executes). It's just a plain vanilla function. Well, it may be that the compiler has some special check that will trigger a warning then, but after main has been compiled, it differes in no way from any other funciton.

    And why does one use large memory model if plain vanilla funcitons may not be placed above 64k?

    Dave 1024 said:
    I cannot find any C or assembly source code for cinit. Is that available somewhere?


    I don't think so. It is precompiled and a rather integral part of the compiler (not part of the standard lib). It may even change between different compiler versions. And of course it isn't written in C. IF there is source ocde somewhere, it will be assembly code anyway - and wouldn't differ much from the disassembly window.

    However, you say "It's getting stuck at a memcpy call". That's interesting. The MSPGC init code doesn't call anything, but here is a nother possible pitfall:

    memcpy might end up in upper memory too. And the INIT code needs to call it using a CALLA instruction then. Also, the large memory model version of memcpy needs to be linked-in, which end with a RETA instruction rather than a RET instruction. (well, since the init code is definitely in lower memory, the wrong memcpy version would result in an excess byte on the stack that just wastes the first stack byte - assuming that the stack was initialized already, which it should when a funciton is called)

  • Have you access to the registers using the register view? If so, you may want to try to disable the watchdog manually (write a 0x5A80) and then let your program run.

    I had this once, that my program never started to run because in the cinit() a memcpy was performed which took more cycles than allowed by the watchdog - and as it never reached the main() in the first place the watchdog got never disabled (or reset). So it was stuck being restarted during cinit all the time.

    I don't think on the 2xx devices the SYSRSTIV register is available - so you cannot simply check if it was indeed a watchdog reset.

    Of course this would only happen if you try to copy something large into memory (a lookup table for example (which would be declared in a wrong way then), or any other preinitialized array).

  • Bernhard Weller said:
    I had this once, that my program never started to run because in the cinit() a memcpy was performed which took more cycles than allowed by the watchdog

    You're right. It happened to me once on the 1611 with its large ram. This is why on MSPGCC, the watchdog was disbaled by the statup code (bad idea, especially if it happens undocumented). So I wrote my own version to have the WDT on all the time. However, the MSPGCC startup code, not using memcpy at all, was so fast that this only happened on the 1611. On 149 with its 2k ram, this never happened, even if all ram was filled with init values.

    Also, on CCS, uninitialized data space is not filled with 0. So I doubt the init code is soo slow copying less than 2k data that the watchdog will trigger. If so, then memcpy is awfully slow.
    However, it might be a reason that it hangs in memcpy.
    Maybe it is because in large memory mode, the large memory version of memcpy has to deal with 20 bit addresses (e.g. to copy the init data from upper memory to ram) and is much slower than the standard 16 bit version.

**Attention** This is a public forum