Cerberus Firmware for NetMF 4.3 compiled with GCC

I just posted the code on codeshare.
I started from existing work found on this forum and from NetduinoGo. I have to say that previous attempts to compile with Yagarto failed because of bad compilation of the first bytes that must be recognized by the booter: the jump opcode B is interpreted as B.W by Yagarto instead of the expected B.N. The CLR is simply not recognize as an executable.
Yagarto can produce runable code (explicitly coding B.N) but there are other issues with callbacks and probably some more.
I do not recommend Yagarto to compile NetMF.
The GCC toochain supported by ARM is here: GNU Arm Embedded Toolchain in Launchpad

The result is not as large and slow that the rumor said.
In fact, the result is smaller and to some extend faster than the official firmware. It is entirely the result of using the FPU instruction set.
For a simple managed loop, calculation with float is almost two times faster, calculation with double is surprisingly the same.

To be honest, GCC really produce larger code. It is visible with TinyBooter.
GHI should really set the compilator options to enable FPU…

The porting from 4.2 to 4.3 is straighforward. I basically removed all the absolute references to “C:\MicroFrameworkPK_v4_2”, changed the LWIP directory in some proj and implemented some simple new functions.

I added a new feature for quadrature encoder (that was the origin of this work). It is a good sample for real world advanced interop feature with callbacks.

Enjoy!

3 Likes

Excellent contribution. Thanks for the feedback and valuable notes as well.

Besides the WinUSB BSOD fix, this is the greatest thing that has happened all year!

-Valkyrie-MT

Thanks to all.
I hope that this will allow further contributions by developers who do not own expensive ARM compilers.
All the toolchain is now open source and free.

Any numbers to share?
KB size difference and any benchmarks.

You can easily benchmark yourself the features you’re interested in. Just flash you Cerberus with the binaries available in codeshare.
Size comparison is not relevant because of the FPU instruction set use.

Anyone manged to build the Ethernet version?

When I try is is too big for the FLASH region and the RAM.
I can change the scatterfile to get enough FLASH for TinyCLR but I can’t seem to get enough RAM.

@ Stephen61 - Checkout this post which might help
http://www.tinyclr.com/forum/topic?id=10282&page=1#msg102323

@ Taylorza thanks. I had seen the post.
My build is for Cerberus, with less memory.
I am surprised as I increased the RAM allocation by 16k, by reducing stack to 16k.
The message said I was short 16k. I find it hard to believe ethernet support needs an additional 32k Ram for its variables and buffers.

What its the best way to see the code and bss size of a LIb?

The TinyCLR.proj file is configured to include Ethernet feature.
The build can be too large if the flavor is not set to release.
Be sure to use

msbuild /p:flavor=release

to get a correct build.
Other flavors do not use the size optimization option and are not suitable for the default memory map.

NIcolas,
TinyCLR.proj includes the following:

  <ItemGroup>
    <DriverLibs Include="sockets_pal_stubs.$(LIB_EXT)" />
    <RequiredProjects Include="$(SPOCLIENT)\DeviceCode\PAL\COM\Sockets\stubs\dotNetMF.proj" />
  </ItemGroup>
  <!--<ItemGroup>
    <DriverLibs Include="sockets_pal_lwip.$(LIB_EXT)" />
    <RequiredProjects Include="$(SPOCLIENT)\DeviceCode\PAL\COM\Sockets_lwip\dotNetMF.proj" />
  </ItemGroup>-->

  <!-- Ethernet ******************************************************************************************* -->

The forum for building the Hyrda firmware says that to build including Ethernet support that has to be changed to:

  <!--<ItemGroup>
    <DriverLibs Include="sockets_pal_stubs.$(LIB_EXT)" />
    <RequiredProjects Include="$(SPOCLIENT)\DeviceCode\PAL\COM\Sockets\stubs\dotNetMF.proj" />
  </ItemGroup>-->
  <ItemGroup>
    <DriverLibs Include="sockets_pal_lwip.$(LIB_EXT)" />
    <RequiredProjects Include="$(SPOCLIENT)\DeviceCode\PAL\COM\Sockets_lwip\dotNetMF.proj" />
  </ItemGroup>

  <!-- Ethernet ******************************************************************************************* -->

Does this not apply to Cerberus?
When I test the firmware I can get the enc28 to work using a test program using the mip stack; but the firmware throws an exception when I try to list the network interfaces. I assumed that was because the Ethernet wasn’t present.
Thanks

You’re right. There are many features related to ethernet but obviously not all.
You can replace some other features by stubs to save some flash as it is done in TinyBooter but I don’t know how to save ram.

Looking at the .map file and the .bss section I have a line

.bss           0x1000bb0c     0x6a4c sockets_hal_sockets_lwIP.lib(memp.obj)

If I understand this correctly memp.cpp is requiring 26K to be reserved.

I thought that the [quote]lwip_selector.h[/quote] file in the SOLUTION directory difined the LWIP model and services. The version I have is unchanged:

#define NETWORK_MEMORY_PROFILE_LWIP__small         1
 #define TCPIP_LWIP                                  1

Is there somewhere else where memory allocation/reservation is handled?

Perhaps someone from GHI can comment on the RAM usage in the Etherenet version of the firmware.
Naively I would have thought that even using a commercial compiler such as RVDS .bss would be similar in size to the GCC link?

OK, now I understand the problem. It was that the GHI complied firmware uses a different memory allocation.
See: http://www.tinyclr.com/forum/topic?id=10452&page=1#msg104325

With that memory allocation of the whole 65K CCM to .bss and the stack being on the non CCM memory it fits.

Good job.
I understand now why the whole 64k CCM is not used in the GHI memory map.

Why? With the RVDS map the full CCM is allocated to Firmware Ram. And with the MDK map the full CCM ram is split between the Firmware Ram and the Stack.

So the full CCM is used…

Maybe I’m wrong but I think the whole firmware usable memory is the Heap.
CCM is mapped to ER_RAM_RO that is intended to be the execution code memory copied from flash when the microcontroler can not execute code from flash.
STM32 can execute code from flash so it is not used.

The 64k CCM and the 128k SRAM are not contiguous and AFAIK the heap can not handle non contiguous memory and is therefore limited to 128k.

For my non ethernet custom firmware, I located the stack in CCM to save space for heap. That is obviouly not a good idea for ethernet firmware.