I am using a Mountaineer board to simulate input going into a pulse counter and need moderately accurate timing on the generation of the pulse train. More importantly, I need to accurately control the total number of pulses sent to the device.
The specific requirements are to generate a fixed number of pulses, between 1 and 125, during a 250 ms time window.
At any given time, I have at least one other thread running - performing a NetworkStream.Read call - which may be blocking.
Since the Gadgeteer.Timer class is not intended for this level of timing accuracy, what are my other options?
Should I use a blocking function call that toggles the pin state with for loops? If I am only generating 3 - 4 concurrent threads, can I assume a specific thread will be active a certain amount of time?
SignalGenerator is what you need, but it exists on Premium boards only (from GHI). @ taylorza has implemented it for Hydra. You can take a look at his implementation and try to add it to Mountaineerâs open source code and compile custom firmware that way.
Is there any simple hardware that would fit the solution?
Would a 555 be helpful? I know very little about them, and what I know seems that they are setup via hardware, so not sure if they can be changed on the fly?
Well there are a number of hardware options for variable rate pulse generation, but I am not aware of any which would be easy to implement and have the capability of stopping the pulses at a specific count.
In all seriousness, though, you could implement this as a native interop in about 30 seconds once you got the porting kit set up. And NETMF 4.3 has good support for ARM-GCC 4.6, so you wouldnât need to buy a compiler.
Once you get the porting kit set up and your interop created, the code to do your task is quite simple:
int pinNumber = 0; // Pin A0
CPU_GPIO_EnableOutputPin(pinNumber, 0);
for(int i = 0; i<125; i++)
{
CPU_GPIO_SetPinState(pinNumber, 1); // set A0 high
HAL_Time_Sleep_MicroSeconds(500); // wait half a millisecond.
CPU_GPIO_SetPinState(pinNumber, 0); // set it low
HAL_Time_Sleep_MicroSeconds(500); // wait another half a millisecond.
}
If you want help setting up the porting kit, weâll be glad to assist you â but try to take a stab at it yourself first, and post any questions you may have (the Native section of this forum is the most relevant place to post questions about the porting kit). Youâll need to grab a copy of NETMF4.3 porting kit, and then copy the Mountaineer source tree on top of it. Try to start by just building the Mountaineer firmware first. Once you get it built, follow the above directions (which, even though theyâre for a Hydra, will apply to your board as well) to create an interop library.
Once you get it working, youâll feel awesome! Guaranteed!
@ jay, thanks for the great info. I will give it a go and let you know if I have any questions.
About NETMF version numbers: you specifically mention the 4.3 porting kit, but all of our development to date is using the 4.2 SDK. Do the porting kit and SDK version numbers have to match?
@ jay, well I made it pretty far on my own, ran through the tutorial and was able to compile the Hydra firmware from source. However, when I attempt to do the same procedure for the Mountaineer hardware I am getting a build error:
arm-none-eabi-gcc.exe : error : missing argument to â-mcpu=â
which occurs 205 times. I can trace this back to the file C:\MicroFrameworkPK_v4_2\tools\Targets\Microsoft.Spot.system.gcc.targets where it is looking for a variable DEVICE_TYPE, which is apparently undefined.
Any idea what file / command line option is missing to supply this. Note that the Mountaineer uses the same MCU as the Hydra: STM32F4.
Architect is right; the Hydra uses the AT91SAM7, which is an older CPU. The STM32F4 is a Cortex-M4 CPU. I would search the forums on compiling FEZ Cerberus using 4.2 and GCC.
Again, let me reiterate â NETMF 4.3 is much easier to get working with GCC.
Is the build procedure the same for using NETMF 4.3 PK? i.e., copy the specific project files on top of the PK folder, set the gcc environment variables, and build?
I will start over, and try to get a Cerberus firmware build to work, and then have another go at the Mountaineer.
We had been hesitant to upgrade the SDK up to this point since Mountaineer only provides full compatibility with 4.2 QFE1. When Gadgeteer upgraded to QFE2, we were forced to update the Mountaineer to a âplain vanillaâ firmware since the core Gadgeteer libraries include dependencies on types that do not exist in the QFE1 assemblies. This has completely locked us out of using important features such as OSHW.Hardware.LowLevel.
All that said, if we are building our own firmware, I guess none of this is an issue. Thanks for the support, guys, and I will let you know as soon as I am successful.
Shameless self-promotion: I maintain a GitHub repository that contains a full NETMF 4.3 build tree with community contributions located here:
This is, as far as I know, the only place which contains an entire build tree that will compile out-of-the-box with GCC 4.6 or MDK4.54+. Otherwise, youâll need to grab the NETMF PK, then copy GHIâs codebase on top of it, and then apply fixes to get it to work with GCC.
Since we use STM32F4 microcontrollers in my lab, the build tree should never âbreakâ compatibility with that microcontroller. I believe your Mountaineer board is binary-compatible with TinyBooter/TinyCLR from the FEZ Cerberus solution, so you should be able to get things working.
Just remember to grab GCC 4.6 â thatâs the only supported GCC compiler.
Request: If you get your PulseOut code working, and you donât mind sharing, Iâd appreciate a pull request! The idea is to provide a lot of built-in code that community members can add to their port by selecting it in the Solution Wizard.
I am taking the netmf-community-ports project and giving it a try. I also note that there is a similar project by NicolasG on the codeshare.
You mentioned âapplying fixesâ to get it to work with GCC. Exactly how intensive is that? I am imagining that in order to get the MountaineerEth solution to compile, I will have to make many of the same changes required to port the Cerberus.
All PulseGeneration code aside, if I do successfully get the Mountaineer to build using GCC, I think it would be useful to share it somewhere (such as in the community-ports).
As for a development environment, I have the 4.3 SDK and PK installed; however, my managed code development will have to stay in 4.2 since my company manages which version of Visual Studio we use. Sadly, when 4.3 added 2012 support that also means it dropped 2010 support.
@ jay, I am to the point where I think I need help. I have gotten the compilation errors to 0, however, in the final build stage I encounter the error âregion `RAMâ overflowed by 26280 bytesâ
Presumably this is because I just copied the GCC scatterfiles from the Cerberus folder. Looking at the MDK version of the Mountaineer scatterfiles, I note the memory address mapping is quite different, and most notably, there is more RAM on the Mountaineer.
I tried changing the file myself, however, the naming conventions between the MDK and GCC versions are significantly different.
Any tips on creating an appropriate GCC scatterfile for the Mountaineer?
Are you building release or debug versions? The scatterfile is really tight-fitting to provide as much deployment space as possible. Itâs built for release mode; GCCâs debug build is too big. Try compiling in release mode.
If you donât need Ethernet, you can also take that out of the solution file using either Solution Wizard or just editing the .proj file. That will trim down the size, too.
EDIT: I just re-read your post and realized you said RAM, not flash. What command line are you using to build it? You should use:
msbuild /t:build /p:flavor=release;memory=flash
To build it in release mode and put it in flash. NETMF also gives you the option of putting it in RAM which is great for debugging (since it can load really fast), but you donât have enough RAM for that.
@ jay if I recall correctly, BSS is un-initialized static data and/or static scoped (Unix & C world) data initialized to zero (NULL). It is READ/WRITE.