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 placed in named segment is corrupted after erasing other memory segments



Hello, and thank you for reading.

I am loading program code into a customized memory segment map on an MSP403F4152:

SEGMENT              SPACE    START ADDRESS   END ADDRESS     SIZE  TYPE  ALIGN
=======              =====    =============   ===========     ====  ====  =====
DATA16_AN                              0001 - 0003               3   rel    0
                                       0019 - 001B               3
                                       001D - 0026               A
 ...
                                       0192 - 0193               2
                                       01B0 - 01B5               6
DATA16_I                                  0200                       dse    0
DATA16_Z                               0200 - 021D              1E   rel    1
CSTACK                                 03B0 - 03FF              50   rel    1
MONITOR                                C000 - C285             286   rel    1
DATA16_C                               C400 - C4AB              AC   rel    1
CSTART                                 C4AC - C4C3              18   rel    1
<CODE> 1                               C4C4 - E069            1BA6   rel    1
INTVEC                                 FFE0 - FFF9              1A   com    1
RESET                                  FFFE - FFFF               2   rel    1

My main() function and related code is being placed into 0xC400-0xFFFF.  A separate function called firmware() is being placed into a segment named MONITOR at location 0xC00-0xC3FF.  The firmware() function is used to erase 0xC400-0xFFFF and then reprogram it with updated code through a UART.  This has worked well for us for years, but recently we tried to simplify our manufacturing process by combining all the code into a single project and programming the chip in 1 pass instead of 2 passes.  After this combination, everything still works as expected up until the firmware() function erases 0xC400-0xFFFF.  At that point, the local variables in the firmware() function appear to become corrupted.  For example, a left shift operation on a local unsigned char results in an erroneous value.

Does anyone recognize this problem, or have any suggestions?  I have tried all sorts of hacks such as placing the firmware() local variables in a separate named segment.  Just to be clear, everything works correctly after the following:  we load firmware() as a main() function within project #1 into 0xC000-0xC3FF, then load our appilcation code as a main() function within project #2 into 0xC400-0xFFFF while retaining unchanged memory.  Everything still works if we combine the code into a single project and place firmware() using a customized memory segment map, until we use firmware() to erase the other parts of memory.

  • Are those local variables on the stack, or in SRAM?
  • I thought the stack was located in SRAM?  The variables are declared locally within the function, for example

    unsigned char which_bits,i;

    unsigned int two_byte_value;

    I have noticed that a left shift operation always induces the corruption, but adds and multiplies do not.

  • Global/static variables are allocated to fixed addresses in SRAM; local variables are allocated automatically.

    What does a shift operation have to do with flash erasing?
  • I have tried allocating the variables locally, globally, and placing each at a fixed address using a named segment. From the segment map in the original post, I assume when global they reside within DATA16_Z (0x0200-0x021D), when local they reside within CSTACK (0x03B0-0x03FF), both of which are in the 512 bytes of RAM and should not be affected by flash erasure of code memory 0xC400-0xFFFF. I also tried placing each at a fixed address in the range 0xC300-0xC3FF using individually named segments. I always get the same corruption during calculations.

    I only mention the shift operation in case it provides a clue. The behavior is not something I have seen before.
  • Placing variables in flash (C300) will not work unless they are read only.

    If I had to guess, I'd say that some code or variable ends up in the wrong segment.

  • I have further info on the problem.  I had to look at the assembly code to find it.  The C code "temp_byte=temp_byte << which_bits;" is being compiled into assembly as "call #?ShiftLeft16".  This works fine until after having erased memory 0xC400-0xFFFF, at which point this call statement resets the processor.  I assume the compiler is forming this subroutine as I did not explicitly write it, and that it is placing it in the memory range I am erasing.  Reading over the instruction set for the MSP430x4xx, I did not find an instruction that shifts an arbitrary number of bits, so I assume the compiler wrote a subroutine callled ShiftLeft16 that loops through single bit shifts.


    Why would the compiler write an assembly subroutine call and place the subroutine into memory outside the memory segment #pragma defined for the C function?  I am using IAR Embedded Workbench.

    I have verified this is the problem by replacing all shift operations with loops of multiplying by 2.  Everything works perfectly with this substitution.

    In summary, the problem appears to be that IAR Embedded Workbench is writing a subroutine called ShiftLeft16 to shift a varying number of bits, and that I cannot control where the subroutine is placed in memory.

  • That ?ShiftLeft16 function probably comes from some IAR library. You'd have to get its source code, and recompile it for a different segment. (And this becomes interesting if both your programs need this function.)

**Attention** This is a public forum