2014-07-27

Originally posted on: http://geekswithblogs.net/WindowsEmbeddedCookbook/archive/2014/07/27/windows-for-iot-first-impressions.aspx



(the Galileo board with an Arduino UNO and a VF50 module from Toradex)

Last week, as many other MVPs and developers around the world, I received an Intel Galileo board preloaded with WindowsIoT version.

This is a preview (so don't take for granted that what I'm describing matches official releases) but we were encouraged to blog about it, so here's my first impressions.

This version has been announced (as an unexpected surprise I should say) during Build 2014 conference in spring and you can find more information about it on the WindowsOnDevices website here: http://dev.windows.com/en-us/featured/Windows-Developer-Program-for-IoT

The board firmware has been modified to run the Windows kernel, I tried to run it on another unmodified Galileo board I had at home and I was able to boot.

To do that you need to access a serial console using a serial port disguised as an audio jack... how brilliant!

Here you can find an adapter: http://www.exp-tech.de/Shields/Interface/USB-to-RS232-TTL-Converter-Module-for-Intel-Galileo.html

But even after accessing the EFI boot menu and selecting SD card as boot media the board doesn't not seem to fully load the OS.

Having a working board I did not spent too much time on this and I inserted the SD image and powered the board up.

But first I checked how big the OS image is.

It's 1GB, quite big compared to other embedded operating system (mostly considering that we have no graphics here since the Galileo is an headless board), but definitely smaller than a standard Windows 8 setup. More or less what you can archieve using the Windows Embedded Standard toolset.

I mentioned that the board is headless, so how are we supposed to access it?

The SDK that you can download from the official website includes a small application named "Galileo Watcher" that shows the board it detects inside your local network.

Here's a screenshot of the tool:



From the main window you can see the board name (I suspect it's the same for all the boards), it's MAC address (useful to distinguish a specific board since it's printed on the network connector) and its status. By right-clicking the board name in the list you can open a telnet prompt (using to perform command-line maintenance), open a very simple web interface (so there is a minimal webserver running on the device, even if I found no documentation about it) and browse its folders (something you can do by just reading the SD card from an SD reader connected to your PC).

If you think that this does not sound exactly exciting, you are right. The most interesting part starts when you launch Visual Studio 2013 and create a new project for the board. You will see that a "Windows for IoT" subcategory appears in the list of templates and, selecting it, you'll be able to create your first IoT application running on top of Windows 8 kernel.



As you can see from the screenshot, the project is referenced as "Galileo Wiring App". Wiring is the programming environment made very popular by the Arduino (http://www.arduino.cc). On the Galileo we can use the same functions made popular by this famous (and Italian!) microcontoller board to access features on an x86-based device. This makes sense since the Galileo also has an Arduino compatible pinout.

Be careful to run the wizard when you are connected to the internet! A failure to do this leads to build issues afterward as my friend Paolo Patierno discovered and documented here http://www.embedded101.com/Blogs/PaoloPatierno/tabid/106/entryid/484/Windows-for-IoT-cannot-open-include-file-arduino-h-Check-your-Internet-connection-you-need-Galileo-C-SDK-Nuget-package.aspx.

The wizard generate sample code that is quite similar to the "blink" sample sketch provided with the Arduino IDE (Arduino programs are called "sketches").

Here's the code:

// Main.cpp : Defines the entry point for the console application.

//

#include "stdafx.h"

#include "arduino.h"

// Pin 13 has an LED connected on most Arduino boards.

// give it a name:

int led = 13;

// Helper function for logging to debug output and the console

void CustomLogging(char* str)

{

OutputDebugStringA(str); // for VS Output

printf(str); // for commandline output

}

int _tmain(int argc, _TCHAR* argv[])

{

return RunArduinoSketch();

}

void setup()

{

// TODO: Add your code here

CustomLogging("Hello Blinky!\n");

// initialize the digital pin as an output.

pinMode(led, OUTPUT);

}

void loop()

{

// TODO: Add your code here

CustomLogging("LED ON\n");

digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)

delay(1000); // wait for a second

CustomLogging("LED OFF\n");

digitalWrite(led, LOW); // turn the LED off by making the voltage LOW

delay(1000); // wait for a second

}

This is actually a plain Windows 32 console application (you can recognize it from the _tmain entry point). The "RunArduinoSketch()" call just initializes the "Arduino-compatible" behaviour and let to call to setup (once) and loop (continuously) callbacks like it happens in the Arduino. Also the pinMode, delay and digitalWrite functions are part of the Arduino standard library. The Serial class, used for serial communication and usually debug messages has been replaced by the "CustomLogging" function that invokes standard Win32 tracing and console output APIs (no variable arguments, so no fancy formatting of your output with variable dumps etc...), so it's redirected to Visual Studio output window or to the console if you launch your app using telnet.

Our application can be remotely debugged just by selecting "Run", this is an improvement compared to Arduino IDE that, at least on 8-bit versions with no jtag connection, does not provide any kind of remote-debugging capability.

To download and execute our app we need to authenticate ourselves:

User is "Administrator" and the password (for the happyness of sysadmins) is "admin".

Once the app is deployed we can start it, put breakpoints, inspect variables etc. as we are used to do with any regular Windows (or Window CE) application.

If you connect a led between pins 13 and GND you'll see it blinking at one second intervals.

Since I'm a low-level driver BSP and other boring stuff embedded developer I tried to understand the real capabilities of such an implementation. Usually hardware access on Windows is complicated, requiring drivers etc. here we can toggle GPIOs from our main function, looks cool.

I tried to decrease the time of delay to 1ms and to remove debug messages (to prevent any kind of slow-downs) and checked the timing of the resulting square-wave using an oscilloscope.

The results aren't exactly what you may expect and here's a graphical view of the wave (with time for each pulse):

As you see we have positive pulses lasting for around 6.75ms and negative ones around 12ms. This means that the delay function is not reliable? Is not as reliable as it is on a regular Arduino UNO,as you can see from this other graph:

On the arduino pulse times are quite close to 1ms.

This means that the Arduino is more performant than the Quark CPU used on the Galileo? Not at all, the Arduino UNO uses an 8-bit microcontroller, while the Galileo is powered by a 500MHz 32bit CPU.

So why we don't have better times on the Galileo? Because Windows is not a real-time operating system. On the Arduino we write code that runs directly on the processor and, unless we enable interrupts and waste a lot of time inside interrupt handlers, the processor will respect our timing quite strictly. On Windows the operating system schedules multiple threads and does not grant 1ms reliability in delays. As we can see by looking at the arduino.h include file, that contains most of the wiring implemetation, the delay function is implemented using the Sleep API. Sleep grants that a thread sleeps at least for the number of milliseconds passed as parameter. No grant is made about the maximum lenght of the delay. I suspect that we will see a similar behaviour also when we run the wiring implementation on top of Linux that comes with the "standard" Galileo boards, but I didn't had the time to do this test at the moment.

This behaviour may impact some protocols and hardwares that expects exact timings in the signals used to drive them. The wiring implementation on the Galileo also provides SPI and I2C access and those buses, if used through an hardware controller should respect their timings (will check this as soon as possible) but other protocols that on a regular Arduino could be "bit banged" by directly accessing GPIO pins may not work if their timing requirements are under 10ms.

Talking about hardware compatibility, the Galileo can be used with many of the shields designed to be used with the Arduino. The pinout of the original Arduino has become a de-facto standard for maker-hobbyst targeted boards and the Galileo, on the hardware side, allow us to use 5V or 3.3V signals to interface the shield (you have to select the voltage using a jumper). On the other side some shield may require strict timings for their signals or may provide libraries that access directly some hardware features of the AT-Mega microcontroller used on Arduino (for performance reasons or to access hardware capabilities not supported by the wiring API). Those libraries are not compatible with the Galileo and Windows for IoT SDK that, as we have seen, rebuild code to native Win32 code, not providing any kind of emulation of the original microcontroller used on Arduino.

Arduino.h is the hearth of the Wiring implementation and, digging a bit more deeply into it, we can discover that it provides implementation for a good share of the Arduino base library (reference is here: http://arduino.cc/en/Reference/HomePage), including GPIO control and configuration, timing (with the limitations described above), analog inputs, PWM outputs, I2C and SPI. We currently have no support for serial port, interrupts and other advanced HW features.

Looking at the code (the SDK full source is available on github: https://github.com/ms-iot) we can see that the Arduino HW access APIs are implemented calling functions defined in embprpusr.h. Those functions define a low-level API that may offer direct access to hardware features without requiring Arduino compatibility and reducing the overhead (for example GPIO access functions in Wiring always test validity of the pin index and translate it from the Arduino pin numbers to Quark's internal indexes, adding some overhead each time you toggle a pin) and allowing you to use them in regular windows console applications, for example to toggle a pin when you receive data on a socket or read characters from a console. A phylosophy not much different from the HW access libraries provided by Toradex: http://developer.toradex.com/software-resources/arm-family/windows-ce/windows-ce-libraries-and-code-samples. Using this API will broke Arduino compatibility but may give better control of the hardware and better integration with standard Windows features. Those APIs are undocumented at the moment, so they may change in future updates, be careful if you decide to use them!

On the API side is not very clear what's the amount of Win32 APIs supported on this platform. Having an headless device excludes any graphic related feature. On the other side basic networking features like sockets seem to be supported (still haven't tested them in detail) while other more advanced features like HTTP/HTTPS, SSL etc. may have some dependencies on Internet Explorer (like it happened with the wininet library in the past) that may prevent them from running on this low-footprint version. On the other side (and this is a bit disappointing since we are talking about an IoT version), there are no libraries (at least no documented ones) to access cloud-services like the Azure Service Bus, to make HTTP request, to use messaging systems or to manage security certificates. I hope to see those functions in future releases because they can simplify and standardize sharng information with cloud-based services. And this should be the main point of an IoT device compared to traditional embedded devices.

It seems that currently there is no support for .NET/managed code and no support for the new WinRT programming model. This is not such a bad thing for me because I'm used to write native applications (mostly on Windows CE) using the "old" Win32 model but for sure it may be a big limitation for high-level developers used to C#/VB or Javascript that at this moment are not supported on the platform.

What are my tought about Windows for IoT? I think it's interesting to see Windows "shrinking down" to fit small devices. On the other side 1GB of OS quite don't fit the definition of "small" in the embedded space, even if storage/memory size and processing power on devices is increasing quickly. Being limited to headless devices is also quite a strong limitation, preventing the creation of interactive devices, unless they are limited to small LCD/text displays (or use voice, sound or other ways to interact). Currently the system targets makers and technology enthusiasts and for sure can't be used in a product (at least because you can't buy Galileo boards configured to run it...). On the other side having Windows compatibile features on an embedded device clearly has a lot of potential (even if I would love to see more on the "I" side of IoT in-the-box). Currently no announcements have been made about supported hardware etc., the only statement released at build was about licence cost, that will be zero (good news since other MS operating systems for embedded still carry a price tag). In my opinion supporting other kinds of hardware (including those with a graphic controller) and in particular ARM chips will be crucial for the success of this platform. We know that the Windows 8 kernel already runs on ARMs (even if application development is artificially limited to WinRT only) and being able to run it on different kind of processors (including of course those used on Toradex's COMs) would provide a flexible soution in many different scenarios. Being tied to x86 or Quark would limit the applications that can be provided considering the limit of the chip (no graphics, no CAN, power consumption etc.) that may be good for some devices but not for many others.

Show more