Archive for the ‘.NET Micro Framework’ Category

Using VB.NET with the .NET Micro Framework

Tuesday, April 1st, 2008

This blog entry explores if it is possible to run VB.NET code on a .NET Micro Framework device. The current Visual Studio integration for the .NET Micro Framework only supports C# development, but since the framework is based upon the CLR runtime it theoretically supports development in any language that can be compiled down to Microsoft Intermediate Language (MSIL) code. So can we compile a VB.NET application for a .NET Micro Framework device and if so what kind of limitations or issues are we likely to come across? Read on to find out the results of some early experiments…

A sample application

The first thing we need is some VB.NET code to attempt to compile. For this I have written the following WPF application.

Imports System
Imports Microsoft.Spot
Imports Microsoft.SPOT.Presentation
Imports Microsoft.SPOT.Presentation.Media
Imports Microsoft.SPOT.Presentation.Shapes
 
NameSpace HelloWorldVB
  Public Class Program
    Public Shared Sub Main()
      Dim app as Application = New Application()
 
      ' Create a window object and set the size to
      ' the size of the display
      Dim mainWindow as Window= New Window()
      mainWindow.Height = SystemMetrics.ScreenHeight
      mainWindow.Width = SystemMetrics.ScreenWidth
 
      ' Add a green rectangle as the sole child
      ' control of the window
      Dim rect As Rectangle = new Rectangle()
      rect.Fill = new SolidColorBrush(CType(&HFF00, Color))
      mainWindow.Child = rect
 
      ' Make the window visible
      mainWindow.Visibility = Visibility.Visible
      app.Run(mainWindow)
   End Sub
  End Class
End Namespace

This application simply displays a full screen window that is coloured Green. This is a reasonably simple application that doesn’t make use of too many VB.NET language or .NET Micro Framework features so is an ideal starting point.

Compiling the application

The first step is to use the standard VB.NET command line compiler (vbc.exe) to compile the source code into a standard executable. We can do this by using the following commands at a command prompt:

SET NET_BIN=C:\Windows\Microsoft.NET\Framework\v2.0.50727
SET MF_BIN=C:\Program Files\Microsoft .NET Micro Framework\v2.0.3036\Tools
SET MF_LIB=C:\Program Files\Microsoft .NET Micro Framework\v2.0.3036\Assemblies
 
"%NET_BIN%\vbc.exe"
  /netcf
  /define:_MYTYPE=\"EMPTY\"
  /reference:"%MF_LIB%\Microsoft.SPOT.Graphics.dll"
  /reference:"%MF_LIB%\Microsoft.SPOT.TinyCore.dll"
  /out:HelloWorldVB.exe
  /target:exe Program.vb

This is all fairly standard stuff for command line VB.NET compilation, however there are two things to note. First we have used the /netcf argument which causes the compiler to target the .NET Compact Framework. This removes language functionality (such as late binding) that depend upon aspects of the full .NET framework.

The second thing to note is the define which sets _MYTYPE to EMPTY. As discussed by the “Customizing Which Objects are Available in My” article on MSDN setting this define to EMPTY will cause the VB.NET compiler to not generate a My namespace. The My namespace is typically used by VB.NET developers to get quick access to convenience functions for things such as File IO and networking functionality, but the code emitted by the VB.NET compiler is not suitable for the .NET Micro Framework base class libraries.

Transforming the executable

Now that we have compiled the VB.NET code into MSIL we need to run the executable through an application called the Meta Data Processor. This pre-processes the MSIL based executable into a more efficient and smaller format that is suitable for use by the interpreter that forms the core part of the .NET Micro Framework runtime.

The following command line will convert the HelloWorldVB.exe executable into a HelloWorldVB.pe file that is suitable for execution by the .NET Micro Framework.

"%MF_BIN%\MetaDataProcessor.exe"
  -loadHints mscorlib "%MF_LIB%\mscorlib.dll"
  -parse HelloWorldVB.exe
  -minimize
  -compile HelloWorldVB.pe

You should notice that HelloWorldVB.pe is significantly smaller than HelloWorldVB.exe and even while viewing it using Notepad it clearly shows that there is less unnecessary “baggage”. For instance there is no string stating “This program cannot be run in DOS mode”.

Running the application

Now that we finally have what appears to be a compiled VB.NET application in a form that is usable by the .NET Micro Framework we need to figure out a way to load it into our .NET Micro Framework emulator or device.

The following command line launches HelloWorldVB.pe within the sample emulator that comes with the .NET Micro Framework SDK.

"%MF_BIN%/Microsoft.SPOT.Emulator.Sample.SampleEmulator.exe"
  /load:HelloWorldVB.pe
  /load:"%MF_LIB%\mscorlib.pe"
  /load:"%MF_LIB%\Microsoft.SPOT.Native.pe"
  /load:"%MF_LIB%\Microsoft.SPOT.TinyCore.pe"
  /load:"%MF_LIB%\Microsoft.SPOT.Graphics.pe"

At this point in time I have not investigated how to deploy *.pe files to actual devices.

Conclusion

This experiment demonstrates that at a technical level it should be possible for the .NET Micro Framework to eventually support the execution of applications written in VB.NET. It does however demonstrate that at present there are a couple of hurdles to overcome, mainly in the code generated by the VB.NET compiler having dependencies on framework functionality not present by the .NET Micro Framework. Not being a VB.NET expert I wonder how far you can go before finding other problems? My next step is to figure out how to deploy *.pe files to an actual device so that I can verify that HelloWorldVB.pe actually does run on a physical device.

I am also interested in investigating the MetaDataProcessor.exe application in further depth. Is anyone aware of additional documentation for this tool? By running it from the command line it is apparent that it has a wide range of command line arguments, but I have presently been unable to find information about it usage.

WPF “Hello World” for the .NET Micro Framework

Tuesday, November 27th, 2007

Screenshot of WPF Hello World application running within an emulator

The first time I heard that the .NET Micro Framework’s GUI framework was Windows Presentation Foundation (WPF) I was excited but wanted to know more. How could such a “big” framework be compressed for use on such a small device, with little to no OS for support?

This blog entry discusses the structure of simple WPF applications written for the .NET Micro Framework and outlines some of the differences when compared against the WPF framework found on the desktop.

The WPF implementation found within the .NET Micro Framework shares many of the same underlying structures and concepts as the desktop version of WPF, but the implementation and capabilities are completely different. For example there is no declarative markup language (XAML), no data binding, no visual form designer and the namespaces are slightly different.

Getting Started
To get started create a new .NET Micro Framework Console application from within Visual Studio 2005 and delete the contents of Program.cs. We would typically use the “Windows Application” template, but since we want to learn the purpose of the code generated by that template we will code it all from scratch.

We also need to add a couple of additional references to our Project in order for the compiler to find the WPF related classes:

  • Microsoft.SPOT.TinyCore
  • Microsoft.SPOT.Graphics

Creating a window
A window is represented by the Microsoft.SPOT.Presentation.Window class. Typically a subclass of this class will be produced to encapsulate as much window specific logic as possible for each type of window within our application. Since we don’t have a Visual Form designer or XAML we must hand code this in C# directly.

Our main window could be represented as follows:

using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Media;
 
public class MainWindow : Window
{
  public MainWindow() 
  { 
    // Make the window the same size as the LCD screen
    this.Width = SystemMetrics.ScreenWidth;
    this.Height = SystemMetrics.ScreenHeight;
 
    // Make the window have a red background
    this.Background = new SolidColorBrush((Color)0x0000FF);
  }
}

The constructor provides an ideal place to configure the look and feel of our window. In this example we configure the initial width and height of our window to be the same size as the LCD screen found on our device. We also give it a solid red background fill.

Creating an Application
A WPF application is represented by the Microsoft.SPOT.Application class. This class manages the display of windows and routes events from the hardware to the active window’s controls etc.

To display our main window on the screen we must create an instance of our application and call it’s Run method, passing in the main window. Like standard desktop .NET applications, the main entry point of an application is its static Main method and this provides an ideal place to perform this initialisation step as shown below:

using System; 
using Microsoft.SPOT; 
 
public class Program : Application 
{
  // This is the method the .NET Micro Framework
  // will call when our application starts running 
  public static void Main() 
  { 
    // Create an instance of the Application
    // and our main Window class
    Application myApplication = new Program(); 
    Window myWindow = new MainWindow(); 
 
    // Ask the application to display the
    // initial window, and don't return until
    // it is closed.
    myApplication.Run(myWindow);
  }
}

When you run this application you should see a solid red window covering the entire screen. It’s pretty boring! Since there is no way (presently) to close this window the call to myApplication.Run will never return.

Adding content
A window can hold a single control, this is because it derives from ContentControl. This class provides a Child property to specify the control which should be displayed within the client area of the window.

Most of the standard controls can be found within the Microsoft.SPOT.Presentation.Controls namespace. The two we will cover in this blog posting are the Text and Image controls.

Displaying Text
To place a string of text on a window we can use the following code snippet at the end of our Window’s constructor:

Font font = Resources.GetFont(Resources.FontResources.small);
this.Child = new Text(font, "Hello World!");

This code refers to a font called “small”. The .NET Micro Framework by default has no fonts, so we must include this font resource as an embedded resource within our application. We do this by following these steps:

  1. Open Resources.resx within the designer
  2. Open the Files section and select to add an existing file
  3. Navigate to the C:\Program Files\Microsoft .Net Micro Framework\v2.0.2036\Fonts\ directory and select “small.tinyfnt”.

By default there are only a couple of fonts to choose from. With Service Pack 1 of the .NET Micro Framework there is also a conversion utility which allows you to convert any TrueType font you may have into the required format.

Displaying an Image
To place an image on a window we make use of the Image control. The easiest way is to simply pass the bitmap we want to display in as a constructor parameter as shown in the below code snippet:

Bitmap bmp = Resources.GetBitmap(Resources.BitmapResources.sample);
Image img = new Image(bmp);
this.Child = img;

We could use the bitmap drawing techniques discussed last time to dynamically create a bitmap to display, or we could embedded an image into our executable. To embedded an image such as the “sample” image in the above example, we follow a similar process to adding a font to our resources.resx file, only this time we select the “Image” section instead of the “Files” section.

By default the image or text will be rendered in the top left corner of the area provided by the window. By changing the HorizontalAlignment and VerticalAlignment properties we can modify this to move the image into the center of the area given to the control. For example to center the image in the previous example we could add the following two lines of code to the Window’s constructor:

img.VerticalAlignment = VerticalAlignment.Center; 
img.HorizontalAlignment = HorizontalAlignment.Center;

Sample Application

[Download wpf-hello-world.zip - 6.7 KB]

A small sample application is available for download. This application demonstrates the techniques outlined within this blog entry and displays the classic “Hello World” message to the user.

The next post on the .NET Micro Framework will discuss how to add more than one control to a window and how to control the size and location of these controls. After that posting we will finally be at the stage where we are ready to discuss how to generate and respond to keyboard or button press events. This will also enable us to discuss how to create multiple windows and close them etc.

Drawing shapes with the .NET Micro Framework

Monday, November 19th, 2007

This blog entry is a lead in to a new series of articles about developing GUIs with the .NET Micro Framework.

A good place to start when learning a new GUI framework is to learn how to draw simple graphics. This blog entry discusses how to draw simple graphics with the .NET Micro Framework.

Creating a Bitmap
The Microsoft.SPOT namespace contains a Bitmap class which represents a bitmap image. To create a bitmap the same size as your physical screen you could use a code snippet such as the following:

using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
 
Bitmap bmp = new Bitmap(SystemMetrics.ScreenWidth,
     SystemMetrics.ScreenHeight);

Once you have a bitmap you can draw on it by using the various instance methods of the Bitmap class. When your drawing is completed, you need to copy the bitmap to the LCD screen in order for it to become visible. The framework provides a Flush() method to perform this task. Calling Flush() on your bitmap will copy the bitmap data to the LCD screen.

Bitmap bmp = new Bitmap(SystemMetrics.ScreenWidth,
     SystemMetrics.ScreenHeight);
// ... do drawing stuff here ...
bmp.Flush(); // copy bitmap to LCD

It is important to note that to use the Flush() method your bitmap must be exactly the same size as the LCD display. Otherwise the flush will simply not work, even though no exception or debug diagnostic will indicate a problem while debugging. This is a common trend with many of the .NET Micro Framework Base Class Library methods.

Representing Colours
A colour is represented by the Color enumeration found within the Microsoft.SPOT.Presentation.Media namespace.

This enumeration only has the values Black and White pre-defined. For example to specify the colour White you could use a code snippet such as the following:

using Microsoft.SPOT.Presentation.Media;
Color white = Color.White;

It is possible to specify other colours by specifying the red, green and blue intensity values that make up the desired colour. To do this you use a static method within the ColorUtility class called ColorFromRGB as shown below:

using Microsoft.SPOT.Presentation.Media;
// Specify full intensity red
Color red = ColorUtility.ColorFromRGB(255, 0, 0);

The parameters passed to ColorFromRGB are the Red, Green and Blue components of the desired colour. These values are all bytes which range from 0 to 255 (full brightness).

ColorFromRGB basically encapsulates some simple bit shifts and a typecast. Internally the .NET Micro Framework represents colours as 3 8bit fields packed into a single 32bit unsigned integer. Instead of using the ColorFromRGB method we can perform a manual typecast between a suitable number and the Color enumeration as follows:

using Microsoft.SPOT.Presentation.Media;
//                 0xBBGGRR
Color red = (Color)0x0000FF;

The format when the value is expressed in hexadecimal is 0xBBGGRR, i.e. 8 bits red (R), 8 bits green (G), followed by 8 bits blue (B). So the above example creates a red colour with full intensity.

Drawing Shapes
The bitmap class has numerous methods available for drawing the outlines of basic shapes such as lines, rectangles and ellipses.

Drawing lines:
draw_line.png

// Draw a red line 10 pixels thick
// between (x=20, y=30) and (x=40, y=50).
bmp.DrawLine(red, // colour
     10,  // thickness
     20,  // x0
     30,  // y0
     40,  // x1
     50) // y1;

A line is specified by providing the colour, thickness and start and end co-ordinates of the line. The current implementation of the .NET Micro Framework base class library appears to ignore the thickness parameter, all lines are drawn 1 pixel wide.

Drawing rectangles:
draw_rectangle.png

// Draw a rectangle which is 40 pixels
// wide and 50 pixels high. The top left
// corner is at (x=20, y=30). The outline is
// 10 pixels wide in red. 
bmp.DrawRectangle(red, // outline colour
     10, // outline thickness
     20, // x
     30, // y
     40, // width
     50, // height
     0,  // xCornerRadius,
     0,  // yCornerRadius,
     0, 0, 0, 0, 0, 0, 0);

Drawing a rectangle involves using the DrawRectangle method which potentially requires setting a number of parameters. We will initially ignore the last 7 parameters and set them to zero (we will discuss them later when we cover gradient fills.).

If the outline thickness is greater than 1 then the co-ordinates specified indicate the center of the outline, i.e. half the outline is drawn on each side.

Rectangles with rounded corners can be specified by setting the xCornerRadius and yCornerRadius parameters to the desired radius. If the radius is larger than zero the outline thickness is ignored by the current version of the BCL and the framework reverts to drawing a 1 pixel thick outline.

Drawing Ellipses:
draw_ellipse.png

// Draw an ellipse centred at (x=30, y=60)
// with a radius of 10 on the x axis and
// 20 on the y axis.
bmp.DrawEllipse(red, // colour
     30,  // x
     60,  // y
     10,  // x radius
     20); // y radius

The simplest way to draw an ellipse is to specify the colour, center co-ordinates, and then the radiuses for the x and y axis respectively. This allows drawing not only ellipses, but also circles (which simply have the x and y radiuses the same).

There is a more complex overload of the DrawEllipse method which enables you to specify the thickness of the outline and/or fill the inside of the shape. However both features are not implemented by the current version of the base class library.

Filling Shapes
linear-gradient-fill.png

DrawEllipse and DrawRectangle both have overloads that support specifying a gradient fill to colour in the internal area of the shape (the 7 parameters set to 0 in the above examples).

The specification of a gradient fill consists of a start and end co-ordinate and associated colours at those two points. The framework will then apply a linear gradient between those two points. Any point “before” the start co-ordinate will be the starting colour, while any point “after” the end point will be the end colour. If both the start and end colours are the same a solid fill will be obtained.

The co-ordinates for the gradient start and end points are measured in screen co-ordinates. I.e. they are relative to the top left corner of the LCD and could refer to locations outside the area of the shape being drawn. This fact can be used to produce some interesting rendering and animation effects.

The opacity parameter allows the fill to be semitransparent and show previous content drawn to the same region of the bitmap. The opacity is a byte value with 0 indicating fully transparent, and 255 indicating full opaque (solid fill).

The fill effect shown in the image above was achieved via the following code sample. Notice the direction of the linear fill (as dictated by it’s start and end co-ordinates), and the fact that the bottom right half of the rectangle is a solid white fill due to this region being “after” the gradient’s end point.

bmp.DrawRectangle(Color.White, // outline colour
     0,    // outline thickness (no outline)
     50,    // x
     50,    // y
     100,   // width
     100,   // height
     0,     // x corner radius
     0,     // y corner radius
     red,   // start gradient colour
     50,    // start gradient x
     50,    // start gradient y
     Color.White, // end gradient colour
     100,   // end gradient x
     100,   // end gradient y
     0xFF); // opacity of fill

Sample Applications

[Download drawingexample.zip - 8.6 KB]

alpha-blended-rectangles.pngThe sample application available for download demonstrates a number of basic drawing operations as discussed above. The application cycles through a number of demonstrations. The sample application also demonstrates the use of System.Reflection functionality within the .NET Micro Framework to find the examples. If you would like to experiment with the drawing APIs, this sample application would be an ideal test harness, just add another “Example_XYZ” method that contains your drawing code and your example will be automatically picked up.

[Download randomshapes.zip - 35 KB]

random-shapes-demo.pngAnother sample application is available for download (without explanation as to how it is implemented). This example helps demonstrates the rendering capabilities of the .NET Micro Framework by creating and animating up to 50 random rectangles of different size, colour and alpha transparency over top of the .NET Micro Framework snowflake logo. It also demonstrates the fact that the .NET Micro Framework emulator is really a simulator. You will notice that running this example under the emulator produces very impressive rendering speeds which are not matched when running on actual hardware.

My next blog entry about the .NET Micro Framework will discuss how to create a basic WPF style application. Eventually I will outline an alternative approach for drawing basic shapes that enables the WPF framework to take care of compositing the individual shapes onto the screen, enabling basic shapes to be animated and moved around in a more object orientated manor.

Visual Introduction to .NET Micro Framework

Monday, July 30th, 2007

Confused about the .NET Micro Framework and what scenarios it enables? Or wondering how it compares to the .NET Compact Framework? Finding the documentation heavy going?

The following videos may help explain the differences, and give you some neat ideas for possible applications of the technology.

.NET Micro Framework resources

Sunday, July 29th, 2007

Over the weekend I have found some more .NET Micro Framework developer resources available on the Internet.

  • Kudzu World – “Programming is an art form that fights back”. This is the personal website of Chad Z. Hower, which has a .NET Micro Framework related section. It is essentially an index to blogs, development boards and other resources Chad has discovered.
  • .NET Micro Framework for Dummies – This is a promising new blog by an unknown developer (I could not find any contact details on the blog) who is in a similar situation to me. He has brought a Tahoe development board, and is blogging about his experiences learning to develop for the new platform.
  • Jens Kühner – “Geek stuff about the .NET, Compact and Micro Framework”, a reasonably new blog by Jens Kühner who is currently writing a book about the .NET Micro Framework. He promises to provide further tips and tricks as his book writing continues.

It will be interesting to see how these resources develop over time, many are at an earlier stage of their development (similiar to my own blog).

Another link of interest is a presentation titled “.NET Micro Framework – Brining .NET to smaller embedded devices” which appears to be developed by Microsoft. This is a worthwhile read, for those wanting to get a good overview of the platform. Sorry about the link (it points to a random PDF on someones website), but I discovered it via a Google search results page, and have not managed to find a better page to link to.

When is C# 2.0 not equal to C# 2.0?

Friday, July 27th, 2007

As I have mentioned previously I have only recently started learning about the .NET Micro Framework, as such I am constantly learning new things about this constrained development environment and today was no exception, here is what I learnt…

The lack of generics
I was investigating the use of the ExtendedWeakReference class, and as part of a test application I was putting together I thought it would be nice to make use of some generics. Generics were a new feature in C# v2.0 which enable you to produce efficient, reusable type safe code.

As the following example program demonstrates, you can make use of certain C# 2.0 features such as anonymous delegates when targeting the .NET Micro Framework. However any attempt to use generics will cause a build time error to occur.

using System.Threading;
using Microsoft.SPOT;
 
public class Program
{
  public static void Main()
  {
    // Configure a timer to print out a message to the debug window once
    // every 5 seconds. Notice that we use an anonymous delegate for the
    // TimerCallback delegate parameter. This is a C# 2.0 language feature.
    Timer t = new Timer(delegate(object o){ Debug.Print("Hello World!"); },
                                  null, 0, 5000);
 
    // Place the main thread into an infinite sleep. The
    // timer callbacks will occur on a separate thread.
    while (true)
      Thread.Sleep(Timeout.Infinite);
  }
}

If you do attempt to use generics within your code the C# compiler will execute successfully (i.e. csc.exe indicates no errors in the build log) but the Meta Data Processor (MetaDataProcessor.exe) which runs automatically after the C# compiler will produce the following error:

METADATAPROCESSOR: Error MMP0000: CLR_E_PARSER_UNSUPPORTED_GENERICS

The Meta Data Processor is the utility which converts assemblies from the standard PE Executable file format (as used on the desktop), into a smaller more efficient representation utilised by .NET Micro Framework devices.

My assumption here is that any C# v2.0 feature which ends up being a chunk of “compiler magic” which essentially converts your code behind the scenes into a form that would have been compatible with the V1.0 compiler is supported on the .NET Micro Framework. While features such as Generics, which required CLR changes in addition to compiler changes, are currently not supported by the .NET Micro Framework.

No support within the BCL to parse numbers
A typical programming task is to parse strings and convert them into numbers. Typically a .NET developer would use a static method within the Base Class Library such as Int32.Parse() to perform this operation.

However the numeric classes within the .NET Micro Framework BCL are pretty empty, and don’t include methods such as Parse. Likewise the System.Convert class does not exist. This means if you need to parse a number, you need to write the number parsing code yourself.

This issue has been discussed on numerous blogs and online forums. Some interesting coverage on this subject is as follows:

  • In a thread titled “Best way to convert string to float/double/decimal?” James Webster a Test Manager within the Microsoft .Net Micro Framework team mentions this is an issue which may be resolved in a later release of the framework. He also provides a quick suggestion as to a work around. This sample has a number of performance issues, which are then worked upon in the rest of the thread.
  • A post by Jens Kühner titled Number parsing with the .NET Micro Framework sounds very promising, however at present the download link to the source code appears to be broken.

While I was on Jens Kühner’s blog I noticed that he is currently writing a .NET Micro Framework book. He promises to release more details, and samples as time goes on. So his blog could be an interesting one to watch. It would be interesting to know how his book compares to Microsoft Press’s Embedded Programming with the Microsoft .NET Micro Framework.

The System.Math class
In a similar manor the System.Math class which provides various math functions is rather limited on the .NET Micro Framework’s version of the BCL. There are no SIN or COS functions for instance.

EmbeddedFusion recently released the source code for their “Ball-In-Maze” tutorial designed for their Tahoe Development Board. This lab was originally presented at MEDC 2007. Reading through the source code you come across a number of useful tips and tricks. Including an integer square root implementation, which I assume was done for speed.

Perhaps it is time to dust off my copy of Jack Crenshaw’s MATH Toolkit for REAL-TIME Programming book and develop a small support library of additional math functions.

Handling GPIO Interrupts within the .NET Micro Framework

Wednesday, July 25th, 2007

My previous .NET Micro Framework example demonstrated how to determine the state of a GPIO input signal. This blog entry outlines how to implement an improved application which instead makes use of an interrupt event handler, for improved performance and power efficiency.

The problem with the InputPort based example was that it utilised a polling mechanism to constantly determine the current state of the GPIO port, this mode of operation is not ideal for a number of reasons, including:

  • Power Management – The polling implementation may become a busy loop, spinning around as quickly as possible, burning CPU cycles to check the state of the input which only occasionally changes state.
  • Responsiveness – A common resolution to the power management issue is to only periodically probe the hardware. The example application from the last blog entry sampled the GPIO state once per second. This has the side effect of introducing latency, since we will only detect a change in state once the current delay has completed. We may also miss a change completely if it happens too quickly.

To resolve some of these issues we can utilise the InterruptPort class. This class derives from the InputPort class mentioned in the previous blog entry, and hence by default inherits all of the InputPort’s properties and functionality.

The main difference is an additional constructor parameter which specifies when an ‘OnInterrupt’ event associated with the port should fire.

Determining when the interrupt should trigger
The additional constructor parameter specifies the conditions under which the interrupt should trigger. You can use one of the following Port.InterruptMode enumeration values:

  • InterruptEdgeBoth – The interrupt is triggered on both rising and falling edges.
  • InterruptEdgeHigh – The interrupt is triggered on the rising edge.
  • InterruptEdgeLow – The interrupt is triggered on the falling edge.
  • InterruptEdgeLevelHigh – The interrupt is triggered whenever the input signal is high.
  • InterruptEdgeLevelLow – The interrupt is triggered whenever the input signal is low.

Clearing Interrupt flags
Edge interrupts trigger when the specified signal transition occurs and automatically re-enable themself, ready to trigger on the next state transition. Level based interrupts however behave slightly differently.

Whenever a level interrupt (InterruptEdgeLevelHigh or InterruptEdgeLevelLow) is triggered it sets a flag which disables the interrupt from re-triggering until the flag is explicitly cleared by means of the ClearInterrupt method.

The main purpose for this is to stop a constant stream of interrupts occurring when the specified level is reached on the GPIO signal. By disabling the interrupt once it has triggered, the software can decide when it wants to be interrupted again. When the ClearInterupt method is invoked, it is possible that the interrupt event handler will fire immediately, if the specified level is still held on the signal.

Example Application
The following is a simple example of how the InterruptPort class can be utilised to produce asynchronous behavior.

The main loop of the program, simply prints the message “House Keeping Ping…” to the debug console every 60 seconds. This is to provide an indication of when the main thread is running. In a typical embedded device this main loop may do menial house keeping tasks, such as timer management, and status LED flashing etc.

While the main loop is sleeping (or printing debug messages), the hardware is constantly monitoring the state of the GPIO_Pin_3 input (attached to the Select button within the Sample Emulator). Whenever the signal goes low, an interrupt is triggered, which causes our button_OnInterrupt event handler to execute on a second thread.

You will notice that button presses are detected immediately even while the main thread is sleeping, unlike the polling example which only detected the button press when the main thread woke up.

using System; 
using System.Threading; 
using Microsoft.SPOT; 
 
using Microsoft.SPOT.Hardware;namespace InterruptPortApplication 
{ 
  public class Program 
  { 
    public static void Main() 
    { 
      // Specify the GPIO pin we want to use as an interrupt 
      // source, specify the edges the interrupt should trigger on 
      InterruptPort button = new InterruptPort(Cpu.Pin.GPIO_Pin3, true, 
        Port.ResistorMode.PullDown, Port.InterruptMode.InterruptEdgeLow); 
 
      // Hook up an event handler (delegate) to the OnInterrupt event 
      button.OnInterrupt += new GPIOInterruptEventHandler(button_OnInterrupt); 
 
      while (true) 
      { 
        // The main thread can now essentially sleep 
        // forever. 
        Thread.Sleep(60 * 1000); 
        Debug.Print("House Keeping Ping..."); 
      } 
    } 
 
    static void button_OnInterrupt(Cpu.Pin port, bool state, TimeSpan time) 
    { 
      // This method is called whenever an interrupt occurrs
      Debug.Print("The button is pressed"); 
    } 
  } 
}

The three parameters in the GPIOInterruptEventHandler delegate type are as follows:

  • pin – a reference to the pin that caused the interrupt to occur. This is useful because you can hook up the same event handler to more than one InterruptPort instance.
  • state – the logic level of the GPIO signal when the interrupt occurred.
  • timestamp – a relative time-stamp which allows you to accurately determine when the interrupt occurred.

Performance
The InterruptPort class is not designed for use in hard real time applications. In my mind it is more a Deferred Procedure Call (DPC) implementation triggered by hardware events than a true Interrupt Service Routine (ISR).

Since I have no physical .NET Micro Framework hardware yet, it is a bit difficult for me to tell exactly how the performance characteristics of interrupt handlers within the .NET Micro Framework stack up. This is defiantly an area I would like to characterise further once my hardware arrives.

In the mean time here are some links to low level performance related material that I have managed to find. Both articles are written by Chris Tacke and give an excellent insight into the performance characteristics of the .NET Micro Framework (and managed code in general) for embedded development.

Detecting button presses

Tuesday, July 17th, 2007

My post introducing the .NET Micro Framework covered how to use the OutputPort class to interface to a single GPIO output pin as part of an example to blink a LED.

The matching class to interface to a GPIO input pin, is not too surprisingly called the InputPort class. The InputPort class functions very similar to the OutputPort class discussed last time, in fact they share a common base class.

The constructor for the InputPort class has a couple of additional parameters, in addition to the one which specifies which GPIO pin it should be connected to.

The first is a boolean parameter which enables a glitch filter. Mechanical switches can be “noisy”, meaning that a single press by the user could translate into multiple open and close events, which digitial hardware can potentially detect. This problem is commonly refered to as Contact Bounce or Switch Debouncing. At this stage I have not current managed to find out what technique the .NET Micro Framework utilises for glitch filtering, or even if this is device specific (I suspect it is).

The second parameter is of much more interest, since it deals with setting the type of internal pull up resistor present on the GPIO pin. It can have one of following values from the ResistorMode enumeration:

  • ResistorMode.PullUp – A resistor internal to the CPU is connected between the GPIO pin and VCC, i.e. the pin is pulled up to the positive supply rail.
  • ResistorMode.PullDown – A resistor internal to the CPU is connected between the GPIO pin and GND, i.e. the pin is pulled down to ground.
  • ResistorMode.None – no internal resistor is enabled. In this mode if a pin is left unconnected, it could produce spurious readings due to noise induced into the pin.

The pull up and pull down resistor modes can be handy when interfacing to external hardware, in particular push buttons. By relying upon the internal pull up or pull down resistors, you can get by without requiring additional components, as shown in the following schematics.

Schematic showing pull up and pull down resistor configurations for push button interfacing

It is important to note that if a push button is connected with a pull up resistor, it’s logic levels will be inverted. I.e. the GPIO pin will read a logic high (true) logic level when the push button is not pressed, and will read a logic low (false) logic level when the push button is pressed.

Code Sample
Here is a sample program which will write a message to the debug window each time a push button connected to the GPIO_Pin3 pin is pressed.

To reduce the amount of log messages written to the Visual Studio output window, we only sample the push button once every second. This means we do not need to enable the glitch filter because we are sampling it at a slow enough rate that it should not be a significant issue.

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Threading;
 
namespace InputTestApplication
{
  public class Program
  {
    public static void Main()
    {
      // Monitor the "select" push button
      InputPort button = new InputPort(Cpu.Pin.GPIO_Pin3,
         false, Port.ResistorMode.PullDown);
 
      while (true)
      {
        // Test the state of the button
        if (button.Read())
             Debug.Print("The button is pressed");
 
        // Wait 1 second before sampling the button again
        Thread.Sleep(1000);
      }
    }
  }
}

NOTE: The GPIO pin used for this sample program has been selected for use with the .NET Micro Framework Sample Emulator. If you attempt to run this application on your own .NET Micro Framework module, you may need to adjust the GPIO signal utilised to suit your hardware.

Push Buttons within the Emulator
The “Sample Emulator” released with the .NET Micro Framework SDK has 5 push buttons “wired up” into a D-PAD configuration.

An interesting aspect to the emulated hardware is that the push buttons can be made to act as if there were wired up with pull up or pull down resistors (as outlined above) depending upon the state of the ResistorMode parameter passed into the constructor of the InputPort instance which accesses them. Typical hardware wouldn’t have this flexibility, with the incorrect ResistorMode choice potentially rendering a push button unreadable.

The mapping of emulator buttons to GPIO pins for the Sample Emulator is as follows:

  • Select – GPIO_Pin3
  • Up – GPIO_Pin2
  • Down – GPIO_Pin4
  • Left – GPIO_Pin0
  • Right – GPIO_Pin1

The code sample provided in this blog posting constantly polls the state of the push button. This is not power efficient. It is better to request that the hardware notifies you whenever the GPIO pin changes state. Next time I will discuss how you can use the InterruptPort class to achieve this.

Introduction to the .NET Micro Framework

Sunday, July 15th, 2007

As I mentioned in an earlier posting I have started to become interested in Microsoft’s latest EMCA Common Language Infrastructure (CIL) implementation, aka the .NET Micro Framework.

The .NET Micro Framework is designed for devices where even the .NET Compact Framework requires too many system resources to be feasible. It’s original design specification was to run on a custom ARM7 ASIC running at 27Mhz with 512KB ROM, 384 KB RAM and 8KB EEPROM, without an form of Operating System.

Operating Environment
One feature that makes the .NET Micro Framework unique is it’s ability to optionally run on hardware directly without the need for a traditional operating system. This is achieved by providing two levels of integration within the porting kit utilised to port the .NET Micro Framework to a new device. An OEM may decide to provide support for the .NET Micro Framework, by hooking in at one of two levels, depending upon the capabilities of their device:

  • Platform Adoption Layer (PAL) – This layer is a high level interface which provides a set of high level primitives such as timers, memory management and data structures. These are typically features provided by a host operating system, leading to a reasonably transparent PAL being developed by the OEM.
  • Hardware Abstraction Layer (HAL) – If no host operating system is in use on the target device, the OEM can utilise a standardised PAL, which hooks into the functionality provided by a hardware abstraction layer. The HAL provides a standardised interface to low level hardware features such as GPIO signals, interrupt handlers and power management etc, which the PAL uses to implement it’s own OS like functionality.

Implementing a Hardware Abstraction Layer can lead to the situation where the .NET Micro Framework is running directly on the CPU as the only “process”.

Compilation Process
Another unique feature of the .NET MIcro Framework, is that it has no Just In Timer (JIT) compiler. The framework instead interperts the MSIL bytecode, in a similiar manor to Mono’s mint interpreter.

Similar to the Java Micro Edition platform, the standard bytecode format utilised on the desktop is not understood by a .NET Micro Framework device. Instead, as part of the compilation process, the bytecode is passed through a pre-verification and optomisation stage, which produces an optimised representation of the bytecode understood by the .NET Micro Framework device.

Hello World – Software Developer style
The traditional first program for a software developer learning a new language or development environment is to write an application which simply prints “Hello World” and then exits. This tradition has it’s roots in an example provided in a book called “The C Programming Language” and was apparently sourced from a 1974 Bell Laboratories internal memorandum written by Brian Kernighan (one of the book’s authors).

Within the Visual Studio 2005 environment for the .NET Micro Framework, a Hello World application may be written as follows:

using Microsoft.SPOT;
 
namespace HelloWorldApplication
{
  public class Program
  {
    public static void Main()
    {
      Debug.Print("Hello World!");
    }
  }
}

The Microsoft.Spot.Debug class is somewhat similiar to the System.Diagnostics.Debug class present in the full framework in its intent.

The Debug.Print method can be utilised to emit a string to the standard output stream, which by default is routed to the Visual Studio IDE from the development board while debugging an application.

This code sample is fairly similiar to that produced by the Micro Framework Console Application project wizard within Visual Studio 2005. The main difference being that the project wizard emits code which utilises a string resource to store the string, this aids in internationalisation of the application.

Hello World – Hardware Engineer style
The equvialent to a “Hello World” application for a hardware engineer bringing up a new microprocessor based board is to flash a LED connected to a GPIO pin.

using System.Threading;
using Microsoft.SPOT.Hardware;
 
namespace HelloWorldApplication
{
  public class Program
  {
    public static void Main()
    {
      // The LED is hooked up to GPIO Pin 1. The second parameter
      // within the constructor indicates to set the pin to logic high
      // initially
      OutputPort led = new OutputPort(Cpu.Pin.GPIO_Pin1, true);
 
      while (true)
      {
        // Sleep for 5 seconds (5000 ms)
        Thread.Sleep(5000);
 
        // Toggle the state of the LED
        led.Write(!led.Read());
      }
    }
  }
}

NOTICE: If you attempt to run this sample application on actual hardware, you may need to alter the GPIO Pin assignment to suit your hardware, and add a reference to a device specific assembly.

The Microsoft.Spot.Hardware.OutputPort class accesses a specified pin on the physical hardware and can toggle the pin between the high and low logic levels.

The Read() method queries the pin for it’s current state, while the Write(bool) method allows the user to explicitly set the pin’s current state. For those familiar with traditional Micro-controller firmware development, you will notice that the hardware is accessed in an abstracted sense, where all the bit twiddling typically required to set or reset a single GPIO pin is hidden behind the scenes. This makes for a nice portable application, but is not suitable in applications which need precise real time functionality etc.

Trivia
I initially wondered why the .NET Micro Framework related classes were in namespaces starting with Microsoft.SPOT. SPOT which is an acronym for “Smart Personal Object Technology”, was the Microsoft Research project which initially produced the technology that became the .NET Micro Framework. The Microsoft SPOT group developed a range of devices, with the most well known probably being the smart watch.

One of the proof of concepts the research team produced was a tiny CLR to allow a managed software development environment for their projects. They named the initial namespaces after their group, since this was a technology for internal use only. When it was decided to commercialise the .NET Micro Framework as a seperate product, they decided to keep the namespaces, since a number of internal and external projects were already using them and it helped with backwards compatibility.

I also assume this is why what appears to be the first publically available version of the .NET Micro Framework is versioned as version 2.