Native code NETMF on Cerberus

I thought I would share a little of my excitement for the weekend.

I started playing around with the STM32F0 processor, specifically looking at how multitasking is supported. I got some simple code up and running fairly quickly which could multitask native functions aka threads. Then it dawned on me that we could implement the .NETMF libraries as native code using C++11. So I started building a little multitasking kernel and implemented some of the IO classes.

To ensure that I keep within tight resources, I am developing this on a Cortex-M0 (STM32F051) chip, but ideally I want to implement the Gadgeteer framework and have it run on the FEZ Cerberus.

Here is sample code for two thread functions, the code should look very similar to what you would have in C#.


void threadA (void *param)
{
	OutputPort ledGreen((Cpu::Pin)41, false, false, Port::ResistorMode::Disabled);
	while(true)
	{
		ledGreen.Write(!ledGreen.Read());
		Threading::Thread::Sleep(500);
	}
}

void threadB (void *param)
{
	OutputPort blueGreen((Cpu::Pin)40, false, false, Port::ResistorMode::Disabled);
	while(true)
	{
		blueGreen.Write(!blueGreen.Read());
		Threading::Thread::Sleep(250);
	}
}

Here is a video of the code running on my Discovery board.


I have not implemented the full wrapper for the threading, which is why I have not shown that code. But now that I have confirmed that it can be done, I will try to get through implementing a good amount of the .NETMF SPOT libraries.

I am using GCC 4.8 which has some of the latest C++11 features, which I have started using here. The ease of NETMF with native performance…?

6 Likes

Very interesting!

Do you want to stick to the basic drivers (timers, GPIO, PWM, analog in, serial, I2C, SPI) and rewrite them, or adapt existing HAL drivers, or put a layer on top of the existing HAL drivers?

For the M0 devices, the first approach would probably make sense, for M3/M4 devices with Ethernet etc. the latter approach may be more attractive, unless you have a lot of spare time :wink:

@ Cuno - Too be honest, I have not put too much thought into it yet. At the moment, I am using CMSIS to implement the basic drivers, that way I have maximal portability without me needing to think too hard.

I will also probably start with an existing RTOS as the foundation, I have proven that I can implement the multitasking on the chip, but having done this years ago on x86 processors (yes, many years ago) I know the challenges of getting the synchronization objects right.

Btw.
I just completed the basic threading interface, here is what the code looks like now.


using namespace Threading;
using namespace Hardware;

void threadB();

void threadA ()
{
	Thread t2(threadB);
	t2.Start();

	OutputPort ledGreen((Cpu::Pin)41, false, false, Port::ResistorMode::Disabled);
	while(true)
	{
		ledGreen.Write(!ledGreen.Read());
		Threading::Thread::Sleep(500);
	}
}

void threadB ()
{
	OutputPort blueGreen((Cpu::Pin)40, false, false, Port::ResistorMode::Disabled);
	while(true)
	{
		blueGreen.Write(!blueGreen.Read());
		Threading::Thread::Sleep(250);
	}
}

int main()
{
    Thread t1(threadA);
    t1.Start();

    while(true);
}

main kicks off threadA and threadA kicks off threadB before doing it’s own work.

Will be very interesting to see how far the CMSIS peripheral abstractions work for your project! In the past, portable abstractions were either too limiting or too large to be interesting, but maybe this has changed by now. If your CMSIS experience remains positive, we might modify our [em]NETMF for STM32[/em] drivers accordingly.

From my perspective, for some applications your code could be an attractive alternative to the NETMF PAL (and everything on top of it), on top of the HAL. So that we could reuse our existing HAL drivers.

@ Cuno - Thanks for your interest in my little project. I like your idea of using the NETMF HAL, I will take a look at what it would take to get it building independently and have it underlie the higher level abstractions.

In the meantime, I have integrated CoOS, which looks like a really simple lightweight RTOS from CooCox specifically targeting the Cortex-M family. I looked at FreeRTOS but since I use CoIDE CoOS was an easy choice. Using CoOS I have implemented the System.Threading.Monitor class and with also be implementing Auto/Manual Reset Event.

Currently I am implementing the InterruptPort, then I will have the basics of all the Port I/O classes except TristatePort.

One unfortunate discovery I made is that the FEZ Cerberus does not expose the processor Reset pin, so I need to solder an additional lead from the Reset button on the board to bring it out to the SWD Reset pin on the ST-Link programmer. I am just using the ST-Link from my Discovery board, nice and cheap STM programmer.

However, if I understand correctly the Mountaineer board does expose the Reset pin on the socket, so I might rather go for the Mountaineer board for my first pass at providing a native Gadgeteer wrapper.

Who supplies the Mountainer boards in the US? I see they are still available on Mouser as a GHI device, is that the official source or just while stock lasts?

The first version definitely did, it’s the second version really not pin compatible?

@ godefroi - I am going by the schematic for the Cerberus, and from that the TRST (Test Reset) pin, PB4 IIRC, is brought out, but for the STM32 SWD you need the chip Rest pin to be connected, which from the schematic is not exposed on any of the sockets.

Now to be honest, I did not try connecting SWD reset to the TRST pin, I will try it, who knows maybe it does the trick. Though it would be counter intuitive, to me anyway.

Are you using JTag or SWD? I ask because I also have a JLink so I could try JTag instead of SWD, but I would need to check if all the JTag pins are surfaced on the sockets, I never really paid attention.

The Mountaineer boards expose the Reset pin on pin 3 of socket 8 and pin 7 of socket 7. See also http://www.mountaineer.org/app/download/7038536775/Mainboard+Mainboard+Sockets+V20130108.png?t=1357643442.

In the US, Mouser and Element 14 have the boards stocked:
http://www.newark.com/stmicroelectronics/stm3240g-eth-nmf/16-32-bits-micros/dp/48W6915?ost=STM3240G-ETH%2FNMF&CMP=AFC-STMICRO

We have our own stock here, so we can resupply them when necessary.

Ah, you very clearly said Cerberus, but for some reason, I read Cerb40. Sorry for the confusion.

@ Cuno - Thanks, I will take a look at the Mountaineer board.

@ godferoi, it is good that you mentioned the Cerb40, I don’t own one and did not think of using it. Maybe, I should get one for the initial development of the “NETMF” layer, it will save me having to solder a lead to my Cerberus and then when I get to the Gadgeteer level I can use the Mountainer board.

What I think this library would be nice for is to use it on the DL40, it would give developers a similar programming experience on the DL40 as what they have on the mainboard with C#. Might make using the DL40 as co-processor more attractive if you don’t need to use low level C.

2 Likes

[quote=“taylorza”]What I think this library would be nice for is to use it on the DL40, it would give developers a similar programming experience on the DL40 as what they have on the mainboard with C#. Might make using the DL40 as co-processor more attractive if you don’t need to use low level C.
[/quote]

Agreed - I’m not a C/C++ developer by trade - doing largely C# , however I can do basic work in that environment. A while ago I bought a DL40 figuring that I would use it learn about the lower level aspects in C/C++ in an embedded board.

As you see I used the past tense in that last sentence :wink:

It just wasn’t important enough for me - a library like this would remove a lot of the low level GPIO and other work that seemed to have too large of an learning curve for the time I allotted to it.

That said, I’m more interested in MS’s statements about improving NETMF performance (.NET Native?).