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.

Concerto: Boot to flash (ARM) does not work in standalone mode when global data is declared

Other Parts Discussed in Thread: CONTROLSUITE

 

I am leading the SW team for project using Concerto dual core processor (F28M35H52C1). We been plaugued with an issue that taken over a week of my time to investigate and I've only been able to narrow it down.

Symptom: We can load and run both cores from the CCSv5 debugger without issue, but when we disconnect the debugger and then recycle power, the ARM (Master) will not run. I'm using an LED to tell right now (our own designed board). I am using the _STANDALONE switch to comment out the command to boot the C2000 so it does not hold up the Master. In fact, most of the time I don't even load the C2000 because it is not entering the equation.

Investigation: We were able to compile the "flash" example from ControlSuite v150. It's Master runs in both debug and standalone. So we started with that project, imported our linker command files on both core processors, same target config file, and them matched the project settings. Still the example worked and our project did not. Then I began porting our code into the example project while keeping the main startup file from the example, so none of our code was actually being called. I was able to narrow it down to two source files which if both were taken out, the problem goes away, but if either is included, the problem returns. The common factor was that these were the only two source files that declear global data structures. The code is in C++ so these are class object instantiations with constructors. I was able to include back those files but just comment out the global data and found that ANY inclusion of a global variable caused the problem, so it was not a size issue in the .bss section where these object seem to be placed.

This is where we're at and any further suggestions you could offer would be helpful. I've already check all the other threads talking about trouble booting from flash in standalone mode and all the suggested rememdies are in place.

Thank you

  • Raymond,

    inspect your linker command file properly, it is mostly because of some initialized global data that your main() needs. When loading through CCS the loader is probably initializing it while loading itself and when running in stand alone there is no one initializing it. So the progarm is going to weeds.

    have a look at this application note http://processors.wiki.ti.com/index.php/ROMing_Software_Components:_An_RTS_Use_Case_(SPRAAN5) , it talks about how to take care of certain sections when ROMing the SW but can be applied to any SW thats there is non-volatile memory.

    please let us know if you have any more questions.

    Best Regards

    santosh

     

  •  

    Santosh,

    Thank you for the response. I have not yet looked at your wiki link, but have some further information based on my own investigation.

    I have confirmed that any C-style globals are not causing the problem. This includes primitive types, arrays, and structures of POD. I also found that a C++ class is safe if it contains POD data and no constructor. The minute I add a constructor to the class or struct, the standalone boot fails. So this must have something to do with the C++ global initialization routine. Do you know of anywhere I can find information on what section the compiler puts the global init code into for C++?

    Thank you

  • Raymond,

    thats interesting. check your compiler tools manual on how it handles C++ constructors and desctructors. Which compiler are you using and what is your development environment? Normally they are supposed to be put in CTORS and DTORS relocatable sections and the real time library initialization for C++ should take care of loading these to run time memory before calling main. You probably have these linked to initialized data sections or have both load and run from RAM. Inspecting your map file and careful look at any default actions taken by linker in your linker output while building could give you some clues. Also check what is your real entry point - it shouldn't be main(), it should be some function that calls RTS initialization function for C++ environment set up and then it branches to main().

    see if you can attach the map file, I can probably point the sections but it depends on how complex the application is.

    Also try posting the specific question on to handle constructiors and destructors for stand-alone execution,  in the compiler tools forum. You might get quick help from there too.

     

    Best Regards

    santosh

     

     

  • Yes, I believe it must be the ctor code is getting assigned to a RAM section. I don't see a specific ctor or dtor section in the linker file which I copied originally from the flash example project in controlsuite, which is in C. There does not seem to be any C++ examples in control suite. I tried moving all code from the class definition (which may be inline) to the source module and it did not help.

    I tried uploading the map file but I don't think it worked, and it message up the post. If you got it, the offending object is called g_theDataExchanger, which is assigned .bss. The class type is CDataExchange whose functions are assigned to .text, but I can't break out the constructor signature.

    The entry point is _c_int00, which I believe applies to both C and C++ initialization.

    I will try to find the compiler tools forum.

  •  

    Latest report: I placed a breakpoint in the class constructor in the debugger and verified that it is getting called and that it's address is in flash around 205000. Looks like the class code is correctly being assigned to flash section. I am still trying to identify the problem - why does calling a constructor prior to reaching main() cause the ARM to fail to run?

  •  

    Success!!

    I discovered the problem, and it looks like it is a bug in your flash example project.

    I read through the compiler User Guide and found this excerpt:

    All global C++ variables that have constructors must have their constructor called before main. The compiler builds a table of global constructor addresses that must be called, in order, before main in a section called .init_array. The linker combines the .init_array section form each input file to form a single table in the .init_array section. The boot routine uses this table to execute the constructors. The linker defines two symbols to identify the combined .init_array table as shown below. This table is not null terminated by the linker.

    I checked the linkder command file and the .init_array section was assigned to C2 RAM. That means when loaded to flash, this section is not present, so as soon as the init routine tries find the address of a global constructor, it finds a zero and jumps to the wrong address. For a program that executes from flash, .init_array must be allocated to a flash section. I re-assigned it to FLASH and everything works.

    Please take note and update your example files.

  • Raymond,

    thanks - I'll mark it up for improvement/correction in examples, I also agree it would be nice to have some C++ examples.

    Feel free to throw in your suggestions as you use Concerto. Good luck.

     

    Best Regards

    santosh

  • Hi Raymond,

    I encountered a similar problem,but I just debug the program in ccs. Any suggestions,thanks.

    http://e2e.ti.com/support/development_tools/compiler/f/343/p/339136/1184614.aspx#1184614