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.

MSP430Fxxx Memory Maps

Other Parts Discussed in Thread: MSP430F5438A, MSP430F5438, MSP430F2619, MSP430FR5739

This question is basically,

"Why does my code not fit, even though it is significantly smaller than the total available memory?"


TI Memory Architechure

Purely from an architectural standpoint, why would TI place a 128 byte region of interrupt vectors and a reset vector right in the middle of FLASH?

I'm having trouble understanding the methodology behind TI's memory organization and structure. If I am using a part in a product family which has 128KB of flash, and I write 80KB of code, use 1 KB of RAM, how is it possible that the default linker file supplied by TI's compiler tools complain that "code cannot fit"?


Re-mapping Memory

Attached is a memory map I created via a combination of the default linker file, datasheet and map file generated by CCS.

On the top diagram (Default), the compiler was complaining about not having enough memory. You can see that .text was mapped completely to FLASH2, because

.text :{}>> FLASH1 | FLASH2 would attempt to place the code in FLASH1, then give up because it wouldn't fit, and then try to place it all in FLASH2, and it wouldn't fit there either.

So there's a bunch of unused memory in "FLASH1".

To mitigate this issue, I remapped FLASH1 to be a smaller 1280 byte region to store all other data except code. Some data, like .const and .cinit want to be in FLASH1, and if you try to move them to FLASH2, they don't want to be in FLASH2, and you get yet another linker error. So now, in the bottom diagram (Modified), I split .text up into FLASH2 and FLASH3. It seems now that .text can partially fill FLASH2 and then fill up the rest in FLASH3.

After programming the device, I observe strange behavior with interrupts on the F5328. Furthermore, using a similar remapping technique on the F5438A, the program will build with no warnings or errors, but will fail when trying to download. (Trouble reading memory block at 0x6100 on page 0 of length 0x7fff0).

Any ideas?

Best regards

Russell

MSP430F5328_Memory_Map.pdf
  •  

    Russell Lemburg said:
    Purely from an architectural standpoint, why would TI place a 128 byte region of interrupt vectors and a reset vector right in the middle of FLASH?
    I think it is for backwards compatability. The original CPU module had a 16-bit address bus and the interrupt vectors and reset vector were at the top of the 64Kbyte address space. The CPUX module added a 20-bit address bus for a 1Mbyte address space the the interrupt vectors and reset vectors were left at the same address as for the CPU module.

    Russell Lemburg said:
    I'm having trouble understanding the methodology behind TI's memory organization and structure. If I am using a part in a product family which has 128KB of flash, and I write 80KB of code, use 1 KB of RAM, how is it possible that the default linker file supplied by TI's compiler tools complain that "code cannot fit"?

    I suspect a bug / limitation in the linker in how it decides to allocate sections which may be placed in either FLASH (below the interrupt vectors) or in FLASH2 (above the interrupt vectors). When I get the linker error changing from:

    .text : {}>> FLASH | FLASH2 /* CODE */

    To:

      .text : {}>> FLASH2 | FLASH /* CODE */

    makes the linker error "go away". I will try and create a repeatible test case to report to TI.

  • I have reported the issue about the linker error #10099-D in the TI C/C++ compiler forum - see MSP430 linker reports "error #10099-D: program will not fit into available memory" even when there is space

    Russell Lemburg said:
    After programming the device, I observe strange behavior with interrupts on the F5328. Furthermore, using a similar remapping technique on the F5438A, the program will build with no warnings or errors, but will fail when trying to download.

    Is this using the same hardware / project as in the MSP430F5438A Linker file (can not fit code into memory) thread?

    Russell Lemburg said:
    (Trouble reading memory block at 0x6100 on page 0 of length 0x7fff0).

    In that the actual contents of the error message, or is it a typo? The MSP430F5438A has 256Kbytes of flash, but 0x7fff0 is just under 512Kbytes.

  • Chester Gillon said:
    (Trouble reading memory block at 0x6100 on page 0 of length 0x7fff0).

    In that the actual contents of the error message, or is it a typo? The MSP430F5438A has 256Kbytes of flash, but 0x7fff0 is just under 512Kbytes.[/quote]It rather looks like there is a valiue of -16 bytes due to a value range rollover in teh placing algorithm

    However, you're right, the vector table is there for compatibility reasons. The MSP430X core with its 20 bit address range and register set still supports the 16 bit instructions, which are smaller and faster. Unless the address range above 64k is required, the MSP is 100% backwarsd compatible.

    When using the range above 64k for data storage with specialized access funcitons, the fast and small 16 bit code can be used for the whole project except when reading from ar writing to this addiitonal flash.

    Hwoever, when using this additonal address range for code, things get complicated. And the classical compiler/linker strategy isn't suited for that. The compiler needs to know this (large code model) and has to generate 20 bit pointers and 20 bit calls for functions (and the proper return code).This makes the code by up to 10% larger and slower.

    Also, all code in a single .c file (and included -.c files) forms a monolithic code block which the linker cannot split into different flash sections. Additionally, all ISRs need to be still in lower 64k, since the interrupt vectors are 16 bit only. (at least there must be an entry point below 64k, but this is advanced ASM/C mixup)

    When putting constants into upper flash, also large code model needs to be used since pointers to data then need to be 20 bit. This makes the code even longer and slower.

    Is there a solution to this? well, upgrading to the latest compiler version might help, as 20bit support is constantly improved.
    Also, splitting th eproject in different modules that are compiled independently does also help. Especially a separation of interrupt funcitons and normal code into different and separately compiled .c files may help the linker to distribute the code.
    And of course carefully reading the compiler manual (and re-readign it with the next version) is important. In the microcontrolelr world (not what Microsoft calls a "microcontroller" for their .Net embedded library), there a re no abstraction levels as these cost speed and space. So the compiler and its runtime libraries cannot provide the ease-of-use as it is common when writing Windows programs (at the expense of huge and slow code that you pay for with more ram and faster processors - and more power consumption for the same task)

  • Jens-Michael Gross said:
    Also, all code in a single .c file (and included -.c files) forms a monolithic code block which the linker cannot split into different flash sections. Additionally, all ISRs need to be still in lower 64k, since the interrupt vectors are 16 bit only. (at least there must be an entry point below 64k, but this is advanced ASM/C mixup)

    Looking at an example compiled using CCS 5.2 / MSP430 compiler v4.1.2 the linker does split a single object file into different sections, in that some functions in the same .c file were placed below the interrupt vectors (.text.1 / FLASH) and some above the interrupt vectors (.text.2 / FLASH2)

    Also, ISRs are placed in the .text:_isr section which the linker command file only allows to be placed in the lower 64K.

  • Chester Gillon said:
    the linker does split a single object file into different sections

    THen the linker has been improved significantly. I guess along with the large code model implementation. Well, this ability to split is important for using two non-contiguous flash segmetns for code. However, this does not fit the observations stated in the very first post of this thread. If the linker can split, there is no reason why all code ended up in one segment where it didn't fit. Either this functionality has been added in a newer compiler version than the one used in the first post, or it needs to be enabled explicitely.

    It is possible (just a guess) that the original post used a project that was created with an older compiler/IDE version and didn't have this feature enabled, so it was still disabled when the code grew past the capacity of the lower flash.
    I believe you when you say that your version of the linker can do it, but in the original post, the linker obviously didn't.

    However, compiling each function so that it can be linked separately requires the compiler to not generate any direct dependency between funcitons in the same code block. This limits the possibilities of global optimization to reduce code size. It also liekly makes it impossible to tie implicit constants (such as printf format strings) to the code they are used in, as the constat and the code may end up at different locations and therefore cannot use PC-relative addressing. Well, I don't know whether CCS has ever used this optimization at all.

  • Jens-Michael Gross said:
    I believe you when you say that your version of the linker can do it, but in the original post, the linker obviously didn't.

    The issue is that under some conditions the linker automatic section allocation fails. I created a test case with the latest MSP430 linker v4.1.2 -see MSP430 linker reports "error #10099-D: program will not fit into available memory" even when there is space

    Jens-Michael Gross said:
    However, compiling each function so that it can be linked separately requires the compiler to not generate any direct dependency between funcitons in the same code block. This limits the possibilities of global optimization to reduce code size. It also liekly makes it impossible to tie implicit constants (such as printf format strings) to the code they are used in, as the constat and the code may end up at different locations and therefore cannot use PC-relative addressing. Well, I don't know whether CCS has ever used this optimization at all.

    When compiling my test case for a MSP430F5438 initially I used the (default) small memory model. The linker produced numerous warnings of the form:

    _printfi.c", line 515 (approximate): warning #17003-D: relocation from
    function "_setfield" to symbol "$C$SL2" overflowed; the 17-bit relocated
    address 0x1f648 is too large to encode in the 16-bit field (type =
    'R_MSP430_ABS16_MSPX' (15), file =
      "C:\ti\ccsv5\tools\compiler\msp430_4.1.2\lib\rts430x_lc_sd_eabi.lib<_printfi_min.obj>", offset = 0x0000005c, section = ".text:_setfield")

    Followed by a final warning of:

    warning #10015-D: output file "esparanoia_test.out" cannot be loaded and run on a target system

    Changing the Data Memory Model to Restricted removed these "relocated address to large warnings" and the program ran OK in the MSP430F5438.

    On a MSP430F2619, the same program doesn't produce the "relocated address to large warnings" with a small data model and produced the same answer as on the MSP430F5438 with the restricted data model. The program uses ~99kbyte of flash so needs to be partitioned into FLASH and FLASH2.

    Don't understand why the need to change the Data Memory Model varies according to big the FLASH2 section of flash is. Maybe there is some condition under which the linker doesn't warn that the relocation is too large, and the code then fails at runtime. 

  • I'm going to include the project I'm discussing.  This project builds with no warnings or errors using my modified linker file (lnk2_msp430f5438a.cmd), will compile and download to the MSP-EXP430F5438 (with the 5438A chip), but it seems like the code is not really executing, or the processor is continuously resetting itself. In reference to the article Chester indicated (MSP430 linker reports "error #10099-D: program will not fit into available memory" even when there is space), I'm concerned we may have no other option but to reduce memory use significantly.

    In Project Properties

    Compiler Version: TI v. 4.1.0

    Output Format: eabi

    Linker command file: lnk2_msp430f5438a.cmd

    Runtime support library: rts430x_lc_sd_eabi.lib

    In Processor Options

    Code Memory Model: large

    Data Memory Model: small

    In Compiler Optimization Options

    Optimization Level: 4

    Control speed vs. size trade-offs (0=size): 0

    Chester and Jens-Michael, thank you for your responses. This is a considerably more advanced solution than I imagined it to be.

    LEDGoggles.zip
  • Chester Gillon said:
    I used the (default) small memory model

    There are two completely different typers of memory mode. One is code memory model. small uses 16 bit funciton pointers, all code must be in the lower 64k. 16 bit calls and returns are used.
    Large code model uses 20 bit funciton calls and return values and code (except ISRs) may reside anywhere in 20 bit range. This has only minimal impact on size and speed (each function call saves 32 bit instead of 16 bit return address, so calling a function takes two more MCLK cycles and 2 bytes more stack space).
    There are some issues with funciton pointers, which not only have to be 20(32) bit but there is also a compiler bug with indirect indexed funciton calls, when the target address is stored aove 0x8000. This is because the fixed address part is actuall the index part of the call isntruciton and a signed 16 bit value while the variable part of the instruction is th ebase address, but of course is used for the offset part of an indirect address. This was never an issue when there was only 16 bit address space and therefore even a negative offset wrapped to the correct destination.

    The other memory model is data memory model. It is independent of cod ememory model. However, if large data memory model is used, constants (as there is no ram above 64k) may be placed above 64k and poitners to data therefore need to be 20/32 bit. As this requires using the processor register in 20 bit mode, all code in a large dat amodel project needs to save registers as 20/32 bit to the stack, inlcudung ISRs or libraries. Else e.g. a register that is temporarily used by an ISR would lose its upper 4 bit on ISR retuen.

    Teh 17 bit warning indicates that here constants have been placed above 64k btu the instruction generated by the compiler were 16 bit, so the linker couldn't place the final 17 bit address of hte constants into the 16 bit offset provided by the code.

    If it is ensured that constants are placed below 64k, then small code model should be sufficient.

    IIRC, on the new compilers, large code model is the default for targets with >64k flash.

  • I haven't read this entire thread.  But you should probably see this similar thread in the compiler forum.  It ended with a request for an enhancement in the linker.  This request is recorded under id SDSCM00045294 in the SDOWP system.  Feel free to follow it with the SDOWP link below in my signature.

    Thanks and regards,

    -George 

  • Russell Lemburg said:
    I'm going to include the project I'm discussing.  This project builds with no warnings or errors using my modified linker file (lnk2_msp430f5438a.cmd), will compile and download to the MSP-EXP430F5438 (with the 5438A chip), but it seems like the code is not really executing, or the processor is continuously resetting itself.

    I haven't got a MSP430F5438A to try, but did run the project on a MSP430F5438. When the program was run, instead of the timer interrupts occurring regularly the program would "crash" in different ways. e.g. saw:

    a) A corrupt PC of zero

    b) A corrupt PC of 0xfd392 which lead to CCS reporting:

    MSP430: Trouble Reading Memory Block at 0xfd392 on Page 0 of Length 0x11: Invalid parameter(s)
    MSP430: Trouble Reading Memory Block at 0xfd392 on Page 0 of Length 0x7d: Invalid parameter(s)

    c) The PC was in the run-time library initialisation code, which suggests the device was being reset.

    The initClocks function contains the following:

    void initClocks(void)
    {
      //Output SMCLK (Pin 86), MCLK (Pin 85), ACLK (Pin 84) to pins
      UCSCTL0 = 0x1F00;   //DCO and MODulation registers (see p. 50 of chip datasheet)   DCO=31, MOD=0
      UCSCTL1 = 0x0060;   //DCO table for selecting clock ranges on p. 50 of Chip Datashseet DCORSEL = 6
      UCSCTL2 = 0x02DC; //DCO multiplier   Divide by 1, multiply by 732
      UCSCTL4 = 0x0333;   //Clock source is DCO for ACLK, SMCLK, MCLK
      UCSCTL5 = 0x0550; //Clock divide source (set MCLK to /1, set SMCLK and ACLK to /32)
      UCSCTL6 = 0x01DC;   //Set up maximum capacitance for XT1, LF mode, turn off XT2
      MCLK_PORT_DIR |= 0x07;
      MCLK_PORT_SEL |= 0x07;
    }

    This initialises the DCORSEL to 6 and DCO tap selection to 31. According to the MSP430F5438A datasheet DCO Frequency section this initialises the DCO frequency, and in this case the MCLK frequency, to a range of 39 MHz to 88 MHz. The FLL then reduces the DCO tap selection to bring the DCO and MCLK frequency into the desired range around ~24 MHz. However, the initial MCLK frequency is outside of the maximum spec and can cause the CPU to operate incorrectly.

    Rather than initialise the DCO tap selection to the maximum, I changed to initialise it to the minimum with:

     UCSCTL0 = 0x0000;   //DCO and MODulation registers (see p. 50 of chip datasheet)   DCO=0, MOD=0

    This stopped the crashes. (This still leaves the MCLK frequency outside of the spec range for a MSP430F5438 but illustrates that a MCLK which is initially too high can cause crashes)

    The other problem with the code is that it doesn't raise the PMMCOREV to 3, which is required for the MSP430F5438A to operate with a MCLK above 20 MHz. There is the following commented out in initPowerSupply:

      //PMMCTL0 = 0xA503; //Set to Vcore Level 3

    To raise the Vcore level you have to follow the steps in section 2.2.4 Increasing VCORE to Support Higher MCLK Frequencies of the MSP430x5xx/MSP430x6xx Family User's Guide and raise VCORE one level at a time.

    Can you confirm the minimum supply voltage to the MSP430F5438A, and therefore the supported VCORE level and maximum MCLK frequency which can be supported.

  • Turns out a few things, including a complete re-write of the how I set up the clocks fixed the problem:

    • Added runtime support library rts430x_lc_sd_eabi.lib
    • Rewrote initClocks to step VCore from 1 to 2 to 3, (p. 51 of datasheet) and 2.2.4 and also wait for DCO to stabilize using equation in UCS chapter on settling time. This certainly what was causing random resets and strange behavior
    • Increased stack and heap size to 1024 bytes
    • Moved large files into smaller files (maybe this helped the linker, since it seemed to have trouble placing large, contiguous code)
    • Changed  .text : {}>> FLASH | FLASH2 to .text : {}>> FLASH2 | FLASH
  • Jens-Michael Gross said:
    I used the (default) small memory model

    There are two completely different typers of memory mode. One is code memory model. small uses 16 bit funciton pointers, all code must be in the lower 64k. 16 bit calls and returns are used.
    [/quote]Thank you for the clarification. I didn't state exactly what I changed. I was changing the memory data model between small and restricted.

    The code memory model was left at the default.

    Jens-Michael Gross said:
    IIRC, on the new compilers, large code model is the default for targets with >64k flash.

    Looking at CCS 5.2 / MSP430 compiler v4.1.2 the default is a large code model for any target with a CPUX, rather than for a target with >64K flash. e.g. for a MSP430FR5739 with 16 KB of FRAM when the code memory model isn't specified in the CCS project properties the large code model was used by default by the compiler. On an example project using eabi output format the size reported when loaded in the debugger was:

    MSP430: Program loaded. Code Size - Text: 2458 bytes Data: 518 bytes.

    When re-compiled wirh the small code model specified in the CCS project properties the size was reduced to:

    MSP430: Program loaded. Code Size - Text: 2182 bytes Data: 500 bytes.

    If would be more efficient if the large code model was only selected by default when the flash of the target extends above 64K.

**Attention** This is a public forum