Creating .elf file from DS-5 IDE .axf file

Hello all,

I try to run a program on the M4 core.
On the dual core A7 runs WEC2013 Image 1.1.
I cloned the FreeRTOS repository and opened the hello_world example project.
I can build and debug the project (more precisely I can debug the .axf file).

After that I created a .elf file from the .axf file with the fromelf tool.
Now if I want to start the .elf file from the A7 core, it doesn’t work.

In march @luka.tx has send me a .elf file which is working.
I compared the two .elf files and there is a difference.
I uploaded a .zip archive where you can find the .elf files (see rpmsg_pingpong_freertos.elf and hello_world_imx7_colibri_m4.elf).

The .elf file was created with the following command:

fromelf --elf --nodebug --output=hello_world_imx7_colibri_m4.elf hello_world_imx7_colibri_m4.axf

respectively with debug informations:

fromelf --elf --output=hello_world_imx7_colibri_m4_debug.elf hello_world_imx7_colibri_m4.axf

Both files do not work.
I think that in the “good” file rpmsg_pingpong_freertos.elf the program starts at adress 0x2000.

Is there anything wrong in the fromelf command? Do I have to specify other options?
Or is it the wrong scatter file?

In the archive file you can also find some screenshots from my DS-5 preferences.
But I changed nothing in there so these are the defaults from toradex.

Hope you can help me solving this problem.

Kind regards

kuzco

Hi @Kuzco
We’re working on this issue and will get back to you as soon as we have new information.
Regards, Andy

Hi @andy.tx ,

thanks for your answer. Can you approximately say how long this will take?

Regards Kuzco

Dear @Kuzco

The following modified FreeRtos code worked for me to build/run the HelloWorld application:

I modified the following files:

  • examples/imx7_colibri_m4/demo_apps/hello_world_ocram/ds5/.cproject
  • platform/devices/MCIMX7D/linker/arm/MCIMX7D_M4_ocram.scf
  • platform/devices/MCIMX7D/startup/arm/startup_MCIMX7D_M4.s

and opened the following project in DS-5 v5.29:

  • examples\imx7_colibri_m4\demo_apps\hello_world_ocram\ds5

However, there still seems to be a pending issue: if I insert a malloc() into the code, the M4 freezes somewhere in the malloc() implementation. We will look into this.

Regards, Andy

Dear @andy.tx ,

I downloaded the colibri-imx7-m4-freertos-v8_Modified.zip file, but I can’t see differences between the three files

  • examples/imx7_colibri_m4/demo_apps/hello_world_ocram/ds5/.cproject
  • platform/devices/MCIMX7D/linker/arm/MCIMX7D_M4_ocram.scf
  • platform/devices/MCIMX7D/startup/arm/startup_MCIMX7D_M4.s

with my original FreeRTOS from Toradex.
Only newline differences were found.
1135-newline-diff.jpg

I also opened the hello_world_ocram project with DS-5 v29.1 and build it. But the behavior was still the same.
My fromelf command is right?

Dear @Kuzco

Sorry, I packed and uploaded the wrong folder in my initial answer. Here is the correct link with the modified files:

Regards, Andy

Dear @andy.tx,

thanks for the new code.

Referring to this thread, how do you load the simple hello world m4 application?

I tried the following code:

hRpmsg = Rpmsg_Init(NULL);
returnValue = Rpmsg_SetConfigString(hRpmsg, L"Firmware", L"\\USB HD\\hello_world_ocram_imx7_colibri_m4.elf", StoreVolatile);
returnValue = Rpmsg_SetConfigInt(hRpmsg, L"RxRingAddr", 0x8FFF0000, StoreVolatile);
returnValue = Rpmsg_SetConfigInt(hRpmsg, L"TxRingAddr", 0x8FFF8000, StoreVolatile);
returnValue = Rpmsg_Open(hRpmsg);

But the Rpmsg_Open() function never returns and the iMX7 freezes. But only with the simple hello world application.

If I build the rpmsg_freertos_ping_pong with the new project settings and start it with the above code, the Rpmsg_Open() function returns and the application works.

Is there another way to start an m4 application using WEC2013?

Regards, kuzco

Dear @Kuzco

I use the same code as you do, but I modified the RpmsgLib to solve the problems you described. These modifications will be part of the next library release V2.3.

Reason:
The RpMsg protocol uses the iMX7’s hardware messaging unit MU-A. There’s two library problems around this peripheral:

  1. The clock of this MU-A is only enabled from the M4 side.
  2. The MU-A unit is not reset upon starting the M4 code

The Hello World example does not use messaging, and therefore does not initialize the MU-A unit, nor does it read any pending messages from this unit.

  1. The Rpmsg_Open() V2.2 tries to read the status of the MU-A unit and hence freezes, as its clock is disabled.
  2. Even if the clock is enabled, Rpmsg_Open() tries to send a message to the M4 and in this process it waits until the A7-to-M4 buffer is empty. This works for the first start, but waits forever in the 2nd run.

If you need an urgent fix, I can send you a preliminary version of the libraries.

Best Regards, Andy

Dear @andy.tx,

thanks a lot for your answer. It helped me.

At the moment I do not need the preliminary release of win ce libs v2.3.

But I use malloc in my application and determined the issue also.
Therefore the fix of the malloc issue has a higher priority for me.

I would be glad if you inform me as soon as you solved the issue.

Best regards, kuzco

Hi @Kuzco

I cannot reproduce the malloc() crash anymore.

Before I investicate more on this: Is the Hello World application running in OCRAM the starting point you will choose?
I can imagine that the failure depends on the chosen memory mapping, so I would like to debug this as close as possible to your real configuration.

Regards, Andy

Dear @andy.tx ,

OCRAM would be ok for me.
However the TCM scatter file (TCML region for code and TCMU region for data) would also be ok.

If I can debug and run the application in release using new ce libs v2.3 I do not care about the memory type.

Regards, kuzco

UPDATE!!

Dear @andy.tx ,

I made some tests with both scatterfiles (ocram and tcm).

Debugging in tcm region is much better. I can see variables and tasks in my debug view which i didn’t see while debugging in ocram.
Also malloc and memcpy seems to be working.

However there is a problem while calling xQueueReceive (in tcm and ocram region).
I can create the message queue but receiving frames with the function leads to a hard fault.

Maybe it is better to do the adaptions in tcm region scatter file so that I can create release of the application and run it from A7 core.

Regards, kuzco

Dear @Kuzco

I dis some additional investigations, and basically found 3 issues around the malloc problem:

  1. M4 reset sequence
  2. M4 cache
  3. Scatter file

M4 Reset Sequence

The reset sequence used in the RpmsgLib V2.2 does only reset the M4 core, but not the whole M4 platform. This leaves the LMEM memory controller and M4 caches in an undefined state.
For a restart, the A7 updated code and data, but this does not update the M4 cache content. Therefore, after an M4 reset, I suspect that the M4 is reading instructions and data partially from the outdated cache, not from the actual RAM which was modified by the A7 before.

The next release V2.3 of the RpMsgLib will do a proper M4 platform reset.

M4 cache

Not all debug solutions take cache memory into account. Therefore it can happen that variables or memory dumps shown in the debugger don’t reflect the actual values.
To make sure to get consistent information, you might want to disable the M4 instruction / data caches by clearing the ENCACHEbit in the LMEM_PCCCR and LMEM_PSCCR registers.
Unfortunately this has an impact on the software performance.

Scatter file

There were 2 issues in the scatter files:

  • The reset vector and stack pointer is placed at 0x1fff8000 instead of 0x00000000. This requires the loader on the A7 core to copy the vectors into the correct location, before starting the M4 core. As far as I could see, this is properly handled by the RpMsgLib, so not really an issue.
  • Too much space is allocated for global variables. if >30kB of variables are declared, they overlap with the heap and the stack

The correct scatterfile for using the TCM memories looks as follows (initial comments stripped):

#define m_interrupts_start             0x00000000
#define m_interrupts_size              0x00000240

#define m_text_start                   0x1FFF8240
#define m_text_size                    0x00007DC0

/* m_data_size includes stack and heap */
#define m_data_start                   0x20000000
#define m_data_size                    0x8000

/* Sizes */
#if (defined(__stack_size__))
  #define Stack_Size                   __stack_size__
#else
  #define Stack_Size                   0x0400
#endif

#if (defined(__heap_size__))
  #define Heap_Size                    __heap_size__
#else
  #define Heap_Size                    0x0400
#endif

LR_m_text m_text_start m_text_size {   ; load region size_region
  ER_m_text     m_text_start                                               m_text_size { ; load address = execution address
    * (InRoot$$Sections)
    .ANY (+RO)
  }
  RW_m_data     m_data_start m_data_size - Stack_Size - Heap_Size  { ; RW data
    .ANY (+RW +ZI)
  }
  ARM_LIB_HEAP  m_data_start + m_data_size - Stack_Size - Heap_Size EMPTY  Heap_Size   { ; Heap region growing up
  }
  ARM_LIB_STACK m_data_start + m_data_size                          EMPTY -Stack_Size  { ; Stack region growing down
  }
}

LR_m_interrupts m_interrupts_start m_interrupts_size {
  VECTOR_ROM m_interrupts_start m_interrupts_size { ; load address = execution address
    * (RESET,+FIRST)
  }
}

Best Regards,
Andy

Dear @andy.tx ,

thanks for the time you spent on this.
Up to now my application is running. I can debug and there are no malloc faults.

The xQueueReceive was a mistake in my code.

I hope with Ce Libs v2.3 everything will work together.
Thanks

Best regards
kuzco