The Netduino forums have been replaced by new forums at community.wildernesslabs.co.
This site has been preserved for archival purposes only
and the ability to make new accounts or posts has been turned off.
I have a new, more user-friendly version of SimpleNGen which pulls opcodes directly out of your assembly. This means that the system is actually kind of pleasant to use. Once you have your project set up properly, you just need to build it (typically twice) and then deploy to the Netduino.
Big thanks to Dan Morphis for the recommendation to use Cecil. It works great!
If anyone wants to try it, I'd be very interested in your feedback. I should warn you that this is still alpha software, so lots of things don't work, and even the things that do work are pretty hacky.
Load SimpleNGen.sln into your IDE and build it ALERT: use the updated SimpleNGen on the second post to this topic
Decide where you want to keep the SimpleNGen executables. You can either leave them just where they are (wherever you built them), or you can copy the two executable files (SimpleNGen.exe and Mono.Cecil.dll) and put them somewhere convenient. Personally I just leave them where they are
Load the NgenSandbox solution
Right-click NgenSandbox, select Properties, go to Build Events
The first part of the line invokes SimpleNGen.exe. Fix this path so it points to where SimpleNGen.exe lives on your computer
Notice there are two invocations of SimpleNGen.exe. This is because this sandbox is set up to compile both BitBanger and SetLed
The compiler takes four arguments (-input, -class, -output, and -log) but in this project they have been configured to be project-relative and shouldn't need to change
Set a breakpoint on line 10 of Program.cs
Deploy to your netduino and watch the onboard LED turn on and off as you single-step the program
For reference, here is the code to SetLed.cs. What could be better?
namespace NgenSandbox {
public static class SetLed {
public unsafe static int Doit(int pin, int value) {
var bankOffset=(pin&0x20)<<4;
var bitmask=1<<(pin&0x1f);
var pio=(int*)(Pio.BankBase+bankOffset);
pio[Pio.PER]=bitmask; //enable pin
pio[Pio.OER]=bitmask; //enable output
if(value!=0) {
pio[Pio.SODR]=bitmask; //set data
} else {
pio[Pio.CODR]=bitmask; //set data
}
return 0;
}
}
}
the firmware is still the 4.1.0.6-based? I also suppose that it is for Netduino standard, not the Plus-one?
4.1.1.0 beta 1, as I understand it. Chris Walker graciously built a special version of the firmware for Felix and me. I don't know if he built a Plus version. By the way, my firmware change is very small; it is straightforward to add to the firmware if one has the proper source code and compiler.
Correct me if I wrong, but in the past you were supposing to let the user have only some basic type: Cecil have changed this limitation dramatically?
Same limitations as before. Cecil does not help here. Cecil's job is to help me parse the assembly and find the IL instructions inside it; it doesn't do anything to help me analyze those instructions.
I hope people have a good intuition for what this code does (and doesn't do). If not, maybe I have to do a better job of communicating its limitations. There is a simple subset of operations that have straightforward support in the CPU's instruction set: add, subtract and multiply; and, or, and shift; compare and branch; load and store, array access. Additionally there is a simple set of data types that is relatively easy to represent: signed and unsigned ints, shorts, and bytes.
This project aims only to support the above subset. The micro framework is far more complicated than this, and I don't have the desire or the ability to support more of its features. Just to name a few, I don't want to write a garbage collector, or do virtual dispatch, deal with objects that have dynamic types, or even deal with objects that are larger than one register in size.
How about handling timer events where I need no delay on invocation?
In an earlier post I had asked the community if someone could show me sample firmware code for setting a hardware timer and/or posting events back to C#. I don't think anyone was able to respond. In the absence of that I'll have to figure it out for myself (might take longer). I do know how to use the HAL_COMPLETION scheduler thing.
The Fluent project was able to support the compilation of multiple methods, and also able to schedule HAL_COMPLETION-style callbacks. Although this projeect doesn't do that yet, it should be straightforward to implement. But if someone could show me how to set up hardware timers and/or post back to C# events that will help a lot.
In an earlier post I had asked the community if someone could show me sample firmware code for setting a hardware timer and/or posting events back to C#. I don't think anyone was able to respond.
This seems to me as a paradox: a full open-source project where none is able to put the hands!
No: either some problem MUST be solved, or this MF will be time-limited (IMHO).
Cheers
Biggest fault of Netduino? It runs by electricity.
In an earlier post I had asked the community if someone could show me sample firmware code for setting a hardware timer and/or posting events back to C#.
Please have a look at AT91_TIME_Driver::Initialize() in DeviceCode\Targets\Native\AT91\DeviceCode\AT91_TIME\AT91_TIME.cpp - there is a call to AT91_TIMER_Driver::Initialize() (note the extra 'R') to setup 'slow clock' timer that uses hardware timer TC0 and its ISR calls back HAL completion.
Question...
By following the super-useful tip of CW2 (thanks!), I have found that every slow-clock event the function is called. I think without any delay also.
(Look in: .\DeviceCode\pal\AsyncProcCall\Completions.cpp)
The question is: may I add here a call to a custom service routine?
My aim is to write a kind of register accepting subscriptions for hi-precision timer callbacks.
So, suppose I have my own routine which has to be called *without delay* every slow-clock cycle. The owner class will subscribe the routine as callback to this "register", then the Execute() above will invoke the notification to all the subscribers.
NOTE: all that using NATIVE code! That is synchronous, but very fast service.
Thanks
Biggest fault of Netduino? It runs by electricity.
There are three hardware Timer Counter (TC) modules, so you can easily duplicate the code and setup TC1 and/or TC2 by just using the appropriate index (0 = TC0, 1 = TC1 etc.). I have also found a reference to TC1, which seems to be used as a sampling timer during profiling, but probably not on SAM7 platforms (search for c_PerformanceCounter_Timer); and it is conditionally compiled (#define FIQ_SAMPLING_PROFILER).
Note: It may be possible to use Real-time Timer (RTT) or Periodic Interval Timer (PIT) for CLR scheduling and time functions instead of TC0, and leave TC0 free for other usage (waveform generation, capture mode). I guess .NET MF team used it as lowest common denominator, as the other timers (RTT, PIT) may not be present on the other microcontroller variants.
BTW, I haven't worked on this in a couple of weeks, but I might work on it this weekend. I have a couple of questions:
If I work on the interrupt-driven/sampling stuff, it would be nice if I had some hardware device to sample. Can anyone suggest some simple/sane thing I could buy and hook up that would be suitable for testing my code? Some signal that I could sample that would make it obvious that my code was working consistently and with low latency, like, I dunno, a sine-wave generator or something.
What do you guys use for browsing around the firmware C++ source? I've been using emacs and a windows grep tool, and it's getting tiresome
Is there some (Atmel?) documentation for what the various I/O registers are and where they are mapped to in memory?
If I work on the interrupt-driven/sampling stuff, it would be nice if I had some hardware device to sample. Can anyone suggest some simple/sane thing I could buy and hook up that would be suitable for testing my code? Some signal that I could sample that would make it obvious that my code was working consistently and with low latency, like, I dunno, a sine-wave generator or something.
That would be awesome.
I would hook up a second Netduino, and raise/lower a GPIO every ## ms. That way you can control the speed--or even stop/start it using the pushbutton.
What do you guys use for browsing around the firmware C++ source? I've been using emacs and a windows grep tool, and it's getting tiresome
I personally use Visual Studio and Windows Explorer (or ARM Workbench/RealView Debugger on machines where we have that installed). Then I use "Agent Ransack" for searching within the overall source--it's fast and works well.
Is there some (Atmel?) documentation for what the various I/O registers are and where they are mapped to in memory?
If I work on the interrupt-driven/sampling stuff, it would be nice if I had some hardware device to sample. Can anyone suggest some simple/sane thing I could buy and hook up that would be suitable for testing my code? Some signal that I could sample that would make it obvious that my code was working consistently and with low latency, like, I dunno, a sine-wave generator or something.
Sine wave - if you are not afraid, use a wall wart (AC/DC adapter) secondary winding or bridge rectifier output, voltage low enough (3 V) can be connected directly, although some kind of load is recommended (especially in case of cheap unregulated adapter). Or perhaps amplified speaker output, you can easily play various waveforms on the computer. For digital signal I would sample Netduino's PWM output (wired to another pin).
What do you guys use for browsing around the firmware C++ source? I've been using emacs and a windows grep tool, and it's getting tiresome
I use Visual Studio 2010 too, "Find In Files" is fast and supports wildcards and regular expressions. In case of more complex projects (i.e. if it is worth it), I create a dummy Visual C++ project and add needed .NET MF source and header files to it, so IntelliSense can resolve symbol definitions.
Hi Corey,
Super cool what you have created here. Very very useful.
I get a compile error when trying to use '==' and '='. So comparing with '==' and assignments with '='.
The exception I get is this: "Unexpected opCode pop at offset 16".
I think it happens in your optimize stage - but not sure.
Have you seen this error or experienced this problem?
Maybe I'm using it totally wrong.
Hi Corey,
That sounds awesome - thank you very much.
Have you thought about implementing the option to have more than one method in the class?
I have just now PM'ed you my code I'm trying to run.
Hey--
I just looked at your code. I'm not getting the same 'pop' error you are getting, and I'm not sure why.... did you send me exactly the code you were using? In any case, I am getting a couple of other errors that touch on areas I didn't implement (namely, unsigned types, and types smaller than int). I took a bunch of shortcuts there, just to get things working.
I was hoping to do a quick hack tonight but I'm getting pretty tired. I think I'd like to take another look this weekend if that's OK with you. It would be quite exciting if I could get this prototype to produce correct code for the routine you wrote.
By the way, I'm a little worried about whether this is going to be effective. I'm pretty confident that I can (eventually) produce code for the routine you sent me, but I'm very worried that the interop overhead (going from managed to native) is going to dwarf any savings you get by doing these several math operations in native code. Now on the other hand, if you had a whole array of CrossScale[] Value1[] and Value2[]s to work on (so that you only made one managed-to-native transition but then worked on a whole array of parameters), I'm pretty confident that there would be substantial performance improvement.
Regarding more than one method in the class, yeah, I was thinking about that. It helps a lot that you're interested in this project--after doing the initial prototype I kind of moved on to other things because, although people seem to like this idea in principle, I wasn't sure anyone was actually going to use my particular prototype in practice.
I'm interested in SimpleNGen in principle, but don't have a current need.
On top of that I'm still a little lost on the principles behind SimpleNGen being new to the Netduino and Embedded .NET.
Maybe if some of the information relating to its operation and coding examples could be put on the Wiki for more people to study.