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.

Loading math modules in RAM prevents the use of --symdebug:none option

Expert 1635 points
Other Parts Discussed in Thread: MSP430F5659

Hi,

This is an issue that I have been observing for some time now and just found the cause: the program would crash if I use --symdebug:none, no matter the level of optimization, etc.  It turned out that if I refrain from moving to RAM any of the multiplication and division modules the problem does not manifest at all.  I can still move to RAM other modules like lib_rtti or lib_newhandler without any problem.

The issue then manifests when I add, for example, the following line to the project's .cmd linker file (having of course defined those sections already, where I load most of my my application too) and try --symdebug:none:

   .text:rts430x.lib_mul16  : { rts*.lib<mult16_f5hw.obj>(.text) } load = FLASH_CODE_RAM, run = HIGH_RAM

This happens also with mul32, div16s, div16u, div32s, and div32u.

The important thing here is that if I leave --symdebug:dwarf everything is peachy.  Below are a few related lines of the .map files obtained for different cases:

1) Loaded into RAM, --symdebug:dwarf (works):
.text:rts430x.lib_mul16
*          0    0001a202    00000016     RUN ADDR = 000f4202
                  0001a202    00000016     rts430x_lc_rd_eabi_eh.lib : mult16_f5hw.obj (.text)


2) Loaded into RAM, --symdebug:none (does not work)
.text:rts430x.lib_mul16
*          0    0001a158    00000016     RUN ADDR = 000f420c
                  0001a158    00000016     rts430x_lc_rd_eabi_eh.lib : mult16_f5hw.obj (.text)


3) Kept in Flash (works with and without symbols):
                  00011d9e    00000016     rts430x_lc_rd_eabi_eh.lib : div16u.obj (.text)
                  00011db4    00000016                               : mult16_f5hw.obj (.text)

I would like to know the reason why this happens and if there is a way to have the math modules loaded into RAM while having the debug symbols removed.

Thanks,

Pibe

PS: C++ project on MSP430F5659, exception handling enabled, RTOS.

  • For the case where those functions are loaded into FLASH, but execute out of RAM ... How is the code copied from FLASH to RAM?

    Thanks and regards,

    -George

  • With a memcpy() early during main():

    memcpy( (void*) (0xF0000), (const void*) 0x16000, 0x0C000 );

  • My guess is that there is some underlying problem with the system that is present all the time.  Using --symdebug:none causes some placement of things in memory such that the problem is exposed.  Using --symdebug:dwarf causes a different placement that somehow avoids the problem.

    So, I think we need a more detailed understanding of why things don't work when you build with --symdebug:none.

    One other thought ... Make sure you didn't overflow the stack or run out of heap memory.

    Thanks and regards,

    -George

  • How do you know the program crashes?  Are you able to observe a bogus PC value?  At what point is the PC first bogus?

  • Hi George,

    If the problem happened when symbols were enabled I would agree, but this happening when the symbols are removed?  Hmm.  This is why I decided to report this:

    1. The program is been tested regularly under high rate stimuli that triggers continuous conflicts between concurrent threads and can go on for a couple of days without problem.
    2. The problem manifests at startup (although I could not pinpoint so far when because of lacking symbols, stepping with the disassembler has been inconclusive so far)
    3. The stacks have been measured (system and threads) after long testing runs and they are fine.
    4. The heap assigned is 6KB and testing indicates that after all the objects have being created and a few exceptions has been thrown, the system works fine with as little as 2KB.
    5. Point 4 would indicate that there is 4KB available of heap for any of the math modules (more than enough).
    6. Any of the other modules that run from RAM (lib_rtti, lib_newhandle, etc) do not show any problem.

    Of course, there is always room for mistakes, but I would like to confirm with you (TI) guys that you have ruled out any possibility for those math modules to misbehave on the reported circumstances.


    Regards,

    Pibe

  • Hi Archaeologist,

    It gets trapped into 0x0004: jmp 0x0004.  It happens after initial startup, already in 20-bit address space, in main memory bank 0 (0x1xxxx), mostly RTOS.  I can see also, inter-spaced, my code running from RAM sector 1 (0xf0xxx).  I can see objects been created properly, but without the symbols it is difficult at certain point, after the task switching starts happening, to know what I am looking at.

    I had set a breakpoint at @mul16 hoping I was going to find the smoking gun, but execution never passes by.

    Regards,

    Pibe

  • Sorry, it is 7PM already and I started at 8:30 this morning.  I mistakingly entered in the memory browser the FLASH address, not the RAM!

    It turned out that it does run it, and *it is the smoking gun*.  This is what my .map file says:

    .text:rts430x.lib_mul16
    *          0    0001a176    00000016     RUN ADDR = 000f422a
                      0001a176    00000016     rts430x_lc_rd_eabi_eh.lib : mult16_f5hw.obj (.text)

    This is what I can see at 0x1a176 (FLASH):

    01a176:   1202                PUSH    SR
    01a178:   C232                DINT    
    01a17a:   4303                NOP     
    01a17c:   4C82 04C0           MOV.W   R12,&MPY_16__Multiplier__16_Bit_Mode_MPY
    01a180:   4D82 04C8           MOV.W   R13,&MPY_16__Multiplier__16_Bit_Mode_OP2
    01a184:   421C 04CA           MOV.W   &MPY_16__Multiplier__16_Bit_Mode_RESLO,R12
    01a188:   4132                POP.W   SR
    01a18a:   0110                RETA    

    This is what I got in RAM:

            __mspabi_mpyi_f5hw():
    0f422a:   FFFF FFFF           AND.B   @R15+,0xffff(R15)
    67          NOP                ; Account for latency
    0f422e:   FFFF FFFF           AND.B   @R15+,0xffff(R15)
    68          MOV.W    OP1,&MPY_OP1        ; Load operand 1 into multiplier
    0f4232:   FFFF FFFF           AND.B   @R15+,0xffff(R15)
    69          MOV.W    OP2,&MPY_OP2        ; Load operand 2 which triggers MPY
    0f4236:   FFFF FFFF           AND.B   @R15+,0xffff(R15)
    70          MOV.W    &RESULT, R12        ; Move result into return register
    0f423a:   FFFF FFFF           AND.B   @R15+,0xffff(R15)
    73              RETA
    0f423e:   FFFF FFFF           AND.B   @R15+,0xffff(R15)
    0f4242:   FFFF FFFF           AND.B   @R15+,0xffff(R15)

    What!?

    Yet, the copier's range seems to be OK:

        memcpy( (void*) (0xF0000), (const void*) 0x16000, 0x0C000 );

    It does not seem related to the transition from RAM sector 1 to 2 as I can see proper code been copied at 0xf41xx.  Although I can see the 0xFFFF happenning after address 0xf418c.  I am going to check if this is the same immediately after the copy to RAM is made.

    Thanks,

    Pibe

  • Well, it turned out to be a conflict with the .clean section.

    Some time ago I asked here where to locate it and I was told anywhere.  So it ended up as:

        .clean        : {} > HIGH_RAM

    Now I have just changed it to:

        .clean        : {} > LOW_RAM

    and the damned thing works.  I have tried leaving it in high RAM, but just moving it AFTER (it is currently right before the math modules, in the .cmd file) to no avail.


    Where can I get more information about the .clean section recommended location and its dynamic behavior?

    Thanks,

    Claudio

  • The .clean section is program code, just like .text.  It is special code to destruct C++ objects when a C++ exception is handled.  It is a separate section because it's expected to be rarely executed, and thus can reside in "slow" memory.  It is a different section than .text so that .text may be placed in "fast" memory and .clean in "slow" memory.

  • Thank you, Archaeologist.  That's all good, but it does not explain the problem.  I mean, the fact that removing .clean allows mul16 to be copied properly into RAM, when you consider the enormous amount of RAM left and that .clean uses only 180 bytes indicates that probably this is just circumstantial.

    One thing I am going to try today is to make more room in RAM sector 1 and keep .clean in HIGH_RAM.  This will provide the evidence needed.

    I wondered if I am missing something about accessing the RAM sectors.  We'll see.

    Regards,

    Pibe

  • I doubt moving the .clean section is the actual solution to this problem.  I think the root cause of this problem is still present, and moving the .clean section causes things to somehow be placed such that the problem is avoided.

    If I understand correctly, this copy from FLASH to RAM ...

    Pibe said:
        memcpy( (void*) (0xF0000), (const void*) 0x16000, 0x0C000 );

    fails to copy over some of the math routines, including __mspabi_mpyi_f5hw.  The circumstances which cause this failure are still unknown.  I am convinced that whatever causes this is still present, and might return when it is least expected.

    I don't know how to go about investigating such a problem.  I'll ask a few others to take a look.

    Thanks and regards,

    -George

  • The first thing that popped into my head about the memcpy is that both the source and destination addresses are over 16 bit, and if this were compiled in small data model, the memcpy wouldn't handle them correctly; however, because the library that got linked in is restricted data model, that shouldn't be a problem.  In any case, I'd say try to observe the memcpy in action; if it's failing, the manner in which it fails could be enlightening.   Finally, you might consider looking at linker-generated copy tables and the copy_in function in the RTS.

  • All the testing I was doing this morning is still inconclusive and, yes, memcpy() is in my list of suspects.

  • Another round of tests, and things look a little bit clearer.

    1) memcpy()/memmove() produce the same results when .clean is moved into HIGH_RAM: at some point the copy process is botched and the memory starts looking as a desolate sea of 0xFFs.

    2) If I keep .clean in LOW_RAM, then all of the 13 libraries I want in HIGH_RAM will be copied without problem and the program will run normally.

    This is not size related, as some of the libraries are much bigger than .clean.  So, what is it with .clean that moving it to HIGH_RAM creates this problem?

    Regards,

    Pibe

  • Could you post your linker map file for the bad case?

  • Here they are:

    1) With:    .clean        : {} > HIGH_RAM
    2502.Bad.txt

    2) With:    .clean        : {} > LOW_RAM
    0878.Good.txt

    Regards,

    Pibe

  • Your memcpy copies the entirety of FLASH_CODE_RAM and FLASH_CODE_ISR into HIGH_RAM, completely clobbering the contents of HIGH_RAM, including the .clean section.  There two possible solutions:

    • Arrange for .clean to be allocated somewhere other than HIGH_RAM, probably the same place as the rest of the .text for the library's C++ exception-handling code, or
    • be more selective about copying .text; use copy tables instead of bulk memcpy.

    Are you using a linker command file packaged with CCS, or a custom one?

  • That explains it.  I am using a customized .cmd file.

    Thank you,

    Pibe