RSS

Intel Galileo – First Impressions

August 21st, 2014 • Electronics, Netduino, Software Development2 Comments »

Yesterday I received my Intel Galileo rev 1 board. I know the rev 2 board is available but recently the Windows on Devices program have release the necessary firmware etc to upgrade a Galileo rev 1 board to enable it to run Windows.

See the end of this article for an update added on 6th Sept 2014.

Upgrading the Firmware

The first step was to check athe firmware and upgrade it if necessary. In my case it was necessary. Intel provide a comprehensive set of instructions on how to do this. The upgrade process took about 10 minutes.

Creating a Windows SD Card

The next step is to write Windows to a micro SD card. This step of the process took the longest to complete, about 25-30 minutes.

Booting to Windows

The next step is to verify that Windows has loaded correctly. Insert the card, power on and then waiting for 2 minutes for Windows to boot. If successful you should be able to telnet to the device. I used PTTYPortable to do this and was presented with the login request.

Testing the Board

One of the first tests I normally perform is to deploy a Blinky application to the board. Once I am happy that I can deploy applications to the board I speed up Blinky by removing any code which would cause a pause. The result should be an indicator of the performance of the board and the software. So let’s give it a go.

The Galileo board offers two methods for deploying Blinky to the board:

  1. Arduino UI
  2. Visual Studio Windows application

The first method uses the board without the Windows SD card image, the second deploys a Windows application to the SD card and runs as a Windows application.

Our starting point for the tests will be the standard Blink application:

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
 
  This example code is in the public domain.
*/
 
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

// the setup routine runs once when you press reset:
void setup()
{                
    // initialize the digital pin as an output.
    pinMode(led, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop()
{
    digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);               // wait for a second
    digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);               // wait for a second
}

Arduino UI

Using this application in the Arduino UI for the Galileo is simple. In fact the application is one of the samples (File -> Examples -> 01.Basics -> Blink). Loading this sketch and deploying to the Galileo starts the on board LED blinking at a steadily at 1 Hz.

Visual Studio Windows Application

Microsoft have provided a Wiring API for use in Visual Studio. This allows access to the “Arduino” hardware from a Windows application. An equivalent Windows version of the same application is:

#include "stdafx.h"
#include "arduino.h"

int _tmain(int argc, _TCHAR* argv[])
{
    return RunArduinoSketch();
}

int led = 13;  // This is the pin the LED is attached to.

void setup()
{
    pinMode(led, OUTPUT); // Configure the pin for OUTPUT so you can turn on the LED.
}

// the loop routine runs over and over again forever:
void loop()
{
    digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
    Log(L"LED OFF\n");
    delay(1000);               // wait for a second
    digitalWrite(led, HIGH);    // turn the LED on by making the voltage HIGH
    Log(L"LED ON\n");
    delay(1000);               // wait for a second
}

Much of the application looks the same as the Arduino application. The main differences are the addition of the _tmain method and the Log statement. The _tmain method acts as the entry point for the application and provides a method for running an Arduino sketch (as above) or some other program logic.

The Log statements generate debug information which is displayed in Visual Studio’s Output window.

Deploying this application to the board results in… NOTHING!

Digging a little deeper into the examples section of the web site reveals the On Board LED example:

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

#include "stdafx.h"
#include "arduino.h"

int _tmain(int argc, _TCHAR* argv[])
{
    return RunArduinoSketch();
}

//This application flashes the on board LED of the Galileo board by calling GPIO functions directly in the embprpusr.dll instead of using the Arduino layer.

ULONG state = LOW; // keeps track of the state of the on-board LED

void setup()
{
    GpioSetDir(LED_BUILTIN, OUTPUT); // Sets the pin to output
}

void loop()
{
    if (HIGH == state)
    {
	    state = LOW;
	} 
    else
    {
	    state = HIGH;
	}
    GpioWrite(LED_BUILTIN, state); // Writes to the pin, setting its value either HIGH (on) or LOW (off)
    Log(L"LED %s\n", (HIGH == state ? L"ON" : L"OFF"));
    Sleep(1000);
}

Compiling and deploying this application to the board results in the steady flashing of the on board LED.

Reverting to the previous sample and hooking up an oscilloscope reveals that pin 13 is indeed being toggled at 1 Hz it is just not connected directly to the on board LED.

How Fast Can We Go?

Now to find out how fast the board will actually run. Starting with the Arduino example, remove the delay statements, recompile and deploy to the board. Doing this resulted in a square wave with a 50% duty cycle and a frequency of 221Hz. That’s right Hz, not KHz!

Removing the delay and logging statements and deploying the Windows application results in a square wave. This time a 60Hz square wave with a 30% duty cycle is displayed on the oscilloscope.

There must be something wrong. Surely this board with a 400MHz processor should run faster than this.

What About the Netduino?

The Netduino has always had one issue when compared with Arduino and other similar board. Namely it is running interpreted code which is not real time due to the nature of the .NET Microframework and the way the framework runs. I have performed similar tests and I was convinced that it was faster. Only one way to find out, deploy some code to the Netduino Plus 2. This board runs the .NET Microframework on the STM32 family of microcontrollers at 168 MHz. The equivalent code to the two examples above is:

using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace NetduinoPlus2
{
    public class Program
    {
        public static void Main()
        {
            OutputPort dp = new OutputPort(Pins.GPIO_PIN_D13, false);
            while (true)
            {
                dp.Write(!dp.Read());
            }
        }
    }
}

Deploying this to the Netduino PLus 2 and hooking up the oscilloscope results in a square wave with a 50% duty cycle at 17.8 KHz.

Much faster than the Galileo board.

Update 6th Sept 2014

I have been looking through the schematic for the Galileo Rev 1 board and found that not all of the GPIO pins are connected through the CY8C9540A chip but are in fact connected directly top the Quark processor. These GPIOs should be capable of higher speeds. A quick test shows that these pins (Digital 2, 3 & 10) can all generate a 1.16 KHz square wave for an application compiled in debug mode. Compiling the same applications in release more and running the application on the Galileo increases the frequency from 1.16 KHz to 1.27 KHz.

Conclusion

I’ve only had this board for a few hours but I have deployed a few of the examples. The raw GPIO speed appears lower than the interpreted .NET Microframework equivalent. The Galileo has access to a network port with easy access to the Arduino Wiring API but then so does the .NET Microframework.

Some further investigation is required I believe.

Strictly Yorkshire Photography Exhibition

August 18th, 2014 • PhotographyComments Off on Strictly Yorkshire Photography Exhibition

A few weeks ago I had the opportunity to add some of my photos in a local exhibition of photographs taken in Yorkshire. I don’t know what came over me but I said yes. Never done this sort of thing before but nothing ventured, nothing gained. And so on Saturday 9th and Sunday 10th August I found myself exhibiting seven photographs along with about 30 other members of the Strictly Yorkshire Photography group at the Corn Exchange in Leeds.

The group rules are simple, all photographs must be taken in Yorkshire and the photographs should not contain any offensive or illegal material.

The Exhibition

The group membership is diverse and as with all groups, some members are more active than others. The range of skills and interests are varied. My own particular fields of interest are wildlife and technology as you can see by the photographs I exhibited:

Mark Stevens Display at Yorkshire Photography Exhibition

Mark Stevens Display at Yorkshire Photography Exhibition

Spirit of Yorkshire

This image was taken at a vintage Rolls Royce and Bently gathering at Castle Howard on 1st June 2014. The weather was brilliant and I could not resist taking this image of the Spirit of Ecstasy against and almost clear blue sky.

Spirit of Yorkshire

Spirit of Yorkshire

Three Months

This photograph was taken in April of 2014 in the gardens around the York Museum.

Three Months

Three Months

This is one of the few images I have actually modified to any degree. I wanted to bring out the contrast in the wall at the back of the image whilst highlighting the right-hand headstone. This was achived by using a black and white conversion in Paintshop Pro along with HDR.

Doe at Studley Royal Park

This doe was captured early in the morning on 9th April at Studley Royal Park.

Doe at Studley Royal Park

Doe at Studley Royal Park

Sonny and Charlie

Sonny and Charlie are both resue dogs owned by a friend. I took a series of over 200 images of the two dogs when out walking in mid-April this year.

Sonny in Bluebells

Sonny in Bluebells

Sonny in Bluebells

Where’s the Ball?? WHERE’s THE BALL!!!

Where's the Ball?? WHERE'S THE BALL!!

Where’s the Ball?? WHERE’S THE BALL!!

Tornado Leaving York

Tornado is the last locomotive to be built in the UK as of the time of writing. This locomotive first steamed in 2008.

Tornado Leaving York

Tornado Leaving York

This is also an example of of an image which I manipulated. For this image I converted the image to black and white and then used this to mask off all of the original image except for Tornado itself.

Just Grabbing a Takeout For the Kids

This last image shows a Robin feeding in our garden. This was taken early in the year when the young robins had just hatched.

RobinFeeding

What Did I Learn?

I have always enjoyed photography being an enthusiastic amateur. Looking at the images that were on display gave me some ideas about perspective and angles to improve the quality of the photographs I take.

Looking back I think I over prepared and I could have made my display just as effective but with a simple change such as not using frames and just using mounts.

I felt that the day was an overall success. Would I do it again? Yes, without a doubt.

Finally, I’d just like to thank everyone who took part, a great bunch of people.

Window Watchdog

July 5th, 2014 • Electronics, Software Development, STM8Comments Off on Window Watchdog

Window watchdogs provide a mechanism for detecting software failures in two ways, firstly an early reset of the watchdog and secondly a failure to reset the watchdog in time. In this post we investigate how the window watchdog can be use and illustrate with some examples.

Hardware

Window Watchdog Control Register – WWDG_CR

This register has two components, the timer counter and the enable bit (WWDG_CR_WDGA – see below). The microcontroller will be reset when one of two possible conditions:

  • The counter switches from 0x40 to 0x3f (i.e. bit 6 in the counter changes from 1 to 0)
  • The counter is reset when the counter value is greater than the watchdog window register

Writing 0 to bit 6 will cause the microcontroller to be reset immediately.

Assuming that WWDG_WR contains the default reset value then the time out period (in milliseconds) is defined as follows:

tWWDG = tCPU * 12288 * (WWDG_CR & 0x3f)

where tCPU = 1 / fmaster

On the STM8S running at 16MHz a value of 0x40 represents one count which is equal to 0.768ms. So at 16MHz the time out period is:

tWWDG = 0.768 * (WWDG_CR & 0x3f)

Window Watchdog Enable Register – WWDG_CR_WDGA

Switch the Window Watchdog on (set to 1) or off (set to 0).

Window Watchdog Window Register – WWDG_WR

This register defines a time period where the watchdog counter should not be reset. If the counter (WWDG_CR) is reset when the counter value is greater than the value in this register the microcontroller will be reset. This can be illustrated as follows:

Watchdog Sequence

Watchdog Sequence

We can calculate the value of tWindowStart and ttimeout as follows (assuming a 16MHz clock):

tWindowStart = 0.768 * ((WWDG_CRinitial & 0x3f) – WWDG_WR)

and

ttimeout = 0.768 * (WWDG_CR & 0x3f)

where WWDG_CRinitial is the initial value in the WWDG_CR register.

The default reset value for this register is 0x7f which means that the counter can be reset at any time. In this case, a reset will only be generated if the counter drops below 0x40.

One important point to note is that when the window register is used the value written to the counter (WWDG_CR) must be between 0xc0 and 0x7f. This causes the counter to be reset and the counter value to be reset simultaneously.

Software

The function of the Window Watchdog will be illustrated using the following three examples:

  • WWDG_CR not reset
  • WWDG_CR reset outside the reset window
  • WWDG_CR reset inside the reset window

The first thing we need to do is add some code which will be used in all of the examples.

Common Code

Firstly, lets add the code which will be common to all of the examples:

//
//  This program demonstrates how to use the Window Watchdog on the STM8S
//  microcontroller.
//
//  This software is provided under the CC BY-SA 3.0 licence.  A
//  copy of this licence can be found at:
//
//  http://creativecommons.org/licenses/by-sa/3.0/legalcode
//
#include <iostm8S105c6.h>
#include <intrinsics.h>

//--------------------------------------------------------------------------------
//
//  Setup the system clock to run at 16MHz using the internal oscillator.
//
void InitialiseSystemClock()
{
    CLK_ICKR = 0;                       //  Reset the Internal Clock Register.
    CLK_ICKR_HSIEN = 1;                 //  Enable the HSI.
    CLK_ECKR = 0;                       //  Disable the external clock.
    while (CLK_ICKR_HSIRDY == 0);       //  Wait for the HSI to be ready for use.
    CLK_CKDIVR = 0;                     //  Ensure the clocks are running at full speed.
    CLK_PCKENR1 = 0xff;                 //  Enable all peripheral clocks.
    CLK_PCKENR2 = 0xff;                 //  Ditto.
    CLK_CCOR = 0;                       //  Turn off CCO.
    CLK_HSITRIMR = 0;                   //  Turn off any HSIU trimming.
    CLK_SWIMCCR = 0;                    //  Set SWIM to run at clock / 2.
    CLK_SWR = 0xe1;                     //  Use HSI as the clock source.
    CLK_SWCR = 0;                       //  Reset the clock switch control register.
    CLK_SWCR_SWEN = 1;                  //  Enable switching.
    while (CLK_SWCR_SWBSY != 0);        //  Pause while the clock switch is busy.
}

//--------------------------------------------------------------------------------
//
//  Initialise the ports.
//
//  Configure all of Port D for output.
//
void InitialisePorts()
{
    PD_ODR = 0;             //  All pins are turned off.
    PD_DDR = 0xff;          //  All pins are outputs.
    PD_CR1 = 0xff;          //  Push-Pull outputs.
    PD_CR2 = 0xff;          //  Output speeds up to 10 MHz.
}

This code has been used many times in The Way of the Register series of posts. It simply sets the system clock to the high speed internal clock and configures Port D for output.

Example 1 – Continuous Reset

This example sets the Windows Watchdog running and then waits for the watchdog to trigger the system reset. We indicate that the application is running by generating a pulse on Port D, pin 2.

//--------------------------------------------------------------------------------
//
//  Initialise the Windows Watchdog.
//
void InitialiseWWDG()
{
    PD_ODR_ODR2 = 1;
    __no_operation();
    __no_operation();
    __no_operation();
    __no_operation();
    PD_ODR_ODR2 = 0;
    WWDG_CR = 0xc0;
}

The __no_operation() instruction in the above code allow the pulse to stabilise on the pin.

The WWDG_CR is set to 0xc0 to both set the value in the counter and enable the watchdog at the same time. This sets bit 6 in the counter to 11 and the remaining bits to 0 (i.e. the counter is set to 0x40). The effect of this is that the first down count event will cause bit 6 to be cleared and the counter to be set to 0x3f. This will trigger the reset event.

The main program simply sets everything up and then “pauses” by simply waiting for an interrupt:

//--------------------------------------------------------------------------------
//
//  Main program loop.
//
int main()
{
    //
    //  Initialise the system.
    //
    __disable_interrupt();
    InitialiseSystemClock();
    InitialisePorts();
    InitialiseWWDG();
    __enable_interrupt();
    //
    //  Main program loop.
    //
    while (1)
    {
        __wait_for_interrupt();
    }
}

If we run this application and connect PD2 and NRST to the oscilloscope we see the following trace:

Initial continuous reset

Initial continuous reset

The yellow trace shows the reset line being pulled low and gradually returning to high. The drop shows where the watchdog has caused the reset pin to be pulled low and the microcontroller to be reset. The blue trace shows the pulse on PD2. If we measure the time difference between the pulse on PD2 and the time that the reset pin is pulled low we find that this is 770uS. This is very close to the time for one count, 768uS.

To verify this we can change the value in the counter to say 0x48. In this case we should see the watchdog running for 9 counts and the system running for 6.912mS. Changing WWDG_CR = 0xc0 to WWDG_CR = 0xc8 gives the following output on the oscilloscope:

Continuous reset

Continuous reset

Measuring the time difference we get a value of 6.9mS.

Example 2 – Reset Outside Watchdog Window

Using the above code as a starting point we will look at the effects of the watch dog window register (WWDG_WR). This defines when the application is allowed to change the value in the counter. The first task is to change the initial value in the control register to 0xc1 and verify that we get a rest every 1.54ms (2 x timer period). So change the InitialiseWWDG method to the following:

void InitialiseWWDG()
{
    PD_ODR_ODR2 = 1;
    __no_operation();
    __no_operation();
    __no_operation();
    __no_operation();
    PD_ODR_ODR2 = 0;
    WWDG_CR = 0xc1;
}

Running this application on the STM8S Discovery board results in the following traces:

Reset Outside window

Reset Outside window

Now we have two counts (1.54mS) in order to change the value in the control register. First task is to modify the InitialiseWWDG method to define the window. We will define this to be 0x40:

void InitialiseWWDG()
{
    PD_ODR_ODR2 = 1;
    __no_operation();
    __no_operation();
    __no_operation();
    __no_operation();
    PD_ODR_ODR2 = 0;
    WWDG_CR = 0xc1;
    WWDG_WR = 0x40;
}

This means that for the first 768uS the control register should not be changed. If the register is changed during this period a reset will be triggered. To demonstrate this we will change the value in the control register immediately after the microcontroller has been initialised:

int main()
{
    //
    //  Initialise the system.
    //
    __disable_interrupt();
    InitialiseSystemClock();
    InitialisePorts();
    InitialiseWWDG();
    __enable_interrupt();
    //
    //  Main program loop.
    //
    while (1)
    {
        WWDG_CR = 0xc1;             //  Trigger a reset.
        __wait_for_interrupt();
    }
}

Deploying this application to the microcontroller results in the following trace on the oscilloscope:

Watchdog immediate reset

Watchdog immediate reset

As you can see, the system is reset almost immediately (there is virtually no time between the pulse on PD2 and the reset line being pulled low).

Example 3 – Reset Within the Watchdog Window

Starting with the common code we initialise the Window Watchdog with the following method:

//--------------------------------------------------------------------------------
//
//  Initialise the Windows Watchdog.
//
void InitialiseWWDG()
{
    WWDG_CR = 0x5b;         //  Approx 70ms total window.
    WWDG_WR = 0x4c;         //  Approx 11.52ms window where cannot reset
    WWDG_CR_WDGA = 1;       //  Enable the watchdog.
}

This code defines a period of 11.52ms where we cannot reset the window watchdog counter followed by a period of 9.216ms during which the watchdog counter must be reset in order to prevent the microcontroller from being reset.

A simple main application loop would look something like this:

//--------------------------------------------------------------------------------
//
//  Main program loop.
//
int main()
{
    //
    //  Initialise the system.
    //
    __disable_interrupt();
    InitialiseSystemClock();
    InitialisePorts();
    PD_ODR_ODR4 = 1;
    __no_operation();
    PD_ODR_ODR4 = 0;
    InitialiseWWDG();
    __enable_interrupt();
    //
    //  Main program loop.
    //
    while (1)
    {
        unsigned char counter = (unsigned char) WWDG_CR;
        if ((counter & 0x7f) < WWDG_WR)
        {
            WWDG_CR = 0xdb;     //  Reset the Window Watchdog counter.
            PD_ODR_ODR2 = !PD_ODR_ODR2;
        }
        //
        //  Do something here.
        //
    }
}

The initial pulse on PD4 indicates that the application has started. We can use this to detect the reset of the microcontroller. In this trivial application the main program loop simply checks to see if the current value of the counter is less than the value in WWDG_WR. If the counter is less than WWDG_WR then the system write a new value into the counter. The value written is 0x5b anded with 0x80, this brings the reset value into the value range (0xc0 – 0xff).

This application also pulses PD2 to indicate that the watchdog counter has been reset.

Deploying this application and hooking up the Saleae logic analyser gives the following trace:

Window watchdog initial trace

Window watchdog initial trace

As you can see, there is an initial pulse showing that the board is reset (top trace) and then a series of pulses showing that the counter is being reset (lower trace). Each up/down transition represents a watchdog counter reset.

This is a relatively trivial example so let’s spice this up and add in a timer.

To the code above add the following code:

//--------------------------------------------------------------------------------
//
//  Setup Timer 2 to generate a 12.5ms interrupt.
//
void SetupTimer2()
{
    TIM2_PSCR = 0x02;       //  Prescaler = 4.
    TIM2_ARRH = 0xc3;       //  High byte of 50,000.
    TIM2_ARRL = 0x50;       //  Low byte of 50,000.
    TIM2_IER_UIE = 1;       //  Enable the update interrupts.
    TIM2_CR1_CEN = 1;       //  Finally enable the timer.
}

This method will set up timer 2 to generate an interrupt every 12.5ms.

Adding the following will catch the interrupt:

//--------------------------------------------------------------------------------
//
//  Timer 2 Overflow handler.
//
#pragma vector = TIM2_OVR_UIF_vector
__interrupt void TIM2_UPD_OVF_IRQHandler(void)
{
    if (_firstTime)
    {
        InitialiseWWDG();
        _firstTime = 0;
    }
    else
    {
        unsigned char counter = (unsigned char) WWDG_CR;
        unsigned char window = WWDG_WR;
        BitBangByte(counter & 0x7f);
        BitBangByte(window);
        WWDG_CR = 0xdb;     //  Reset the Window Watchdog counter.
        counter = (unsigned char) WWDG_CR;
        BitBangByte(counter);
    }
    PD_ODR_ODR2 = !PD_ODR_ODR2;
    TIM2_SR1_UIF = 0;       //  Reset the interrupt otherwise it will fire again straight away.
}

The interrupt will, on first invocation, initialise the window watchdog. Subsequent invocations will output the values of the registers and reset the window watchdog.

We need some code to bit bang the register values:

#define SR_CLOCK            PD_ODR_ODR5
#define SR_DATA             PD_ODR_ODR3

//
//  BitBang the data through the GPIO ports.
//
void BitBangByte(unsigned char b)
{
    //
    //  Initialise the clock and data lines into known states.
    //
    SR_DATA = 0;                    //  Set the data line low.
    SR_CLOCK = 0;                   //  Set the clock low.
    //
    //  Output the data.
    //
    for (int index = 7; index >= 0; index--)
    {
        SR_DATA = ((b >> index) & 0x01);
        SR_CLOCK = 1;               //  Send a clock pulse.
        __no_operation();
        SR_CLOCK = 0;
    }
    //
    //  Set the clock and data lines into a known state.
    //
    SR_CLOCK = 0;                   //  Set the clock low.
    SR_DATA = 0;
}

The main program loop needs to be modified to set up the timer and registers etc. So replace the main program loop with the following:

//--------------------------------------------------------------------------------
//
//  Main program loop.
//
int main()
{
    //
    //  Initialise the system.
    //
    __disable_interrupt();
    InitialiseSystemClock();
    InitialisePorts();
    PD_ODR_ODR4 = 1;
    __no_operation();
    PD_ODR_ODR4 = 0;
    SetupTimer2();
    InitialiseWWDG();
    __enable_interrupt();
    //
    //  Main program loop.
    //
    while (1)
    {
        __wait_for_interrupt();
    }
}

Deploying and running this application gives the following output on the Saleae logic analyser:

Window watchdog full trace

Window watchdog full trace

Zooming in produces the following

Window watchdog zoomed in

Window watchdog zoomed in

Starting with the top trace and descending we can see the following values:

  • Reset pulse
  • Timer 2 interrupt triggers (up/down transitions)
  • Data (register values)
  • Clock signal

The decoded register values can be seen above the data trace. The first value is the current value of the counter. The second value is the value in the window watchdog register and the final value is the new value in the counter register.

Conclusion

The Window Watchdog provides a mechanism for the developer to detect software faults similar to the Independent Watchdog but further constrains the developer by defining a window where a counter reset by the application is not allowed.

Interesting Book Offer

July 1st, 2014 • GeneralComments Off on Interesting Book Offer

Packt Publishing are celebrating their 10 year anniversary by offering any e-Book for $10 until 5th July.

I’ve read a few of their books recently as I’ve been experimenting with mobile development. Had a look at iOS and currently checking out Xamarin. Interestingly, the special offers also seem to apply. I noticed this afternoon that a couple of books (Raspberry Pi networking plus C Programming for Arduino) when purchased together would only cost £11.80.

I’m currently working my way through the iOS Xamarin Cookbook and that’s looking to be a really useful book. Next step is looking at the Android and Windows Phone equivalents.

STM8S Beep Function

July 1st, 2014 • Electronics, Software Development, STM8Comments Off on STM8S Beep Function

The beep function uses the 128 KHz LSI to generate a beep signal on the beep pin of the STM8S. This post demonstrates how to use this function.

Hardware

The signal is output on the beep pin. On the STM8S discovery board this is an alternative function on PD4 (port D, pin 4).

Setting the Alternative Function

The alternative functions are assigned to a pin by reprogramming the option bytes. This can be performed using the ST Visual Programmer. Start this application and read the option bytes from the STM8S:

Reading the options bytes using ST Visual Developer

Reading the options bytes using ST Visual Developer

  1. Select the STM8S model. On the STM8S Discovery board this is STM8S105C6
  2. Select the OPTION BYTE tab
  3. Read the option bytes from the microcontroller
  4. Check the value of the AFR7 bit

AFR7 needs to be set to Port D4 Alternative Function = BEEP on the STM8S Discovery board. This may be different on your STM8S so check the documentation for your microcontroller. To set the alternative function to beep:

Writing new options bytes using ST Visual Developer

Writing new options bytes using ST Visual Developer

  1. Select Port D4 Alternative Function = BEEP from the list of values in the alternative functions
  2. Write the option bytes back to the microcontroller

The beep function should now be assigned to PD4.

Registers

The beep function is controlled by three registers:

  • BEEP_CSR_BEEPSEL
  • BEEP_CSR_BEEPDIV
  • BEEP_CSR_BEEPEN

Beep Selection – BEEP_CSR_BEEPSEL

These bits set the multiplier for the Beep Divider.

BEEP_CSR_BEEPSELFrequency (KHz)
0fLSI / (8 * BEEPDIV)
1fLSI / (4 * BEEPDIV)
2 or 3fLSI / (2 * BEEPDIV)

Beep Divider – BEEP_CSR_BEEPDIV

Value for the prescalar divider.

BEEPDIV = 2 + BEEP_CSR_BEEPDIV

The documentation states that this should not be left set to the reset value (0x1f) and the value should be in the range 0 – 0x1e.

Beep Enable – BEEP_CSR_BEEPEN

Enable the beep function by setting this to 1, disable by setting this to 0.

Software

We start by providing a method for resetting the system clock to use the HSI:

//
//  This program demonstrates how to use the beep function on the STM8S 
//  microcontroller.
//
//  This software is provided under the CC BY-SA 3.0 licence.  A
//  copy of this licence can be found at:
//
//  http://creativecommons.org/licenses/by-sa/3.0/legalcode
//
#include <iostm8S105c6.h>
#include <intrinsics.h>

//--------------------------------------------------------------------------------
//
//  Setup the system clock to run at 16MHz using the internal oscillator.
//
void InitialiseSystemClock()
{
    CLK_ICKR = 0;                       //  Reset the Internal Clock Register.
    CLK_ICKR_HSIEN = 1;                 //  Enable the HSI.
    CLK_ECKR = 0;                       //  Disable the external clock.
    while (CLK_ICKR_HSIRDY == 0);       //  Wait for the HSI to be ready for use.
    CLK_CKDIVR = 0;                     //  Ensure the clocks are running at full speed.
    CLK_PCKENR1 = 0xff;                 //  Enable all peripheral clocks.
    CLK_PCKENR2 = 0xff;                 //  Ditto.
    CLK_CCOR = 0;                       //  Turn off CCO.
    CLK_HSITRIMR = 0;                   //  Turn off any HSIU trimming.
    CLK_SWIMCCR = 0;                    //  Set SWIM to run at clock / 2.
    CLK_SWR = 0xe1;                     //  Use HSI as the clock source.
    CLK_SWCR = 0;                       //  Reset the clock switch control register.
    CLK_SWCR_SWEN = 1;                  //  Enable switching.
    while (CLK_SWCR_SWBSY != 0);        //  Pause while the clock switch is busy.
}

The next task is to configure the beep function:

//--------------------------------------------------------------------------------
//
//  Initialise the Beep function.
//
void InitialiseBeep()
{
    BEEP_CSR_BEEPEN = 0;    //  Turn off the beep.
    BEEP_CSR_BEEPSEL = 0;   //  Set beep to fls / (8 * BEEPDIV) KHz.
    BEEP_CSR_BEEPDIV = 0;   //  Set beep divider to 2.
    BEEP_CSR_BEEPEN = 1;    //  Re-enable the beep.
}

The final piece of code is the main program loop. This sets up the clock and the beep function:

//--------------------------------------------------------------------------------
//
//  Main program loop.
//
void main()
{
    //
    //  Initialise the system.
    //
    __disable_interrupt();
    InitialiseSystemClock();
    InitialiseBeep();
    __enable_interrupt();
    //
    //  Main program loop.
    //
    while (1)
    {
        __halt();
    }
}

Compiling this code and deploying to the STM8S results in the following trace on the oscilloscope:

Beep Oscilloscope Output

Beep Oscilloscope Output

As you can see, the output is not exactly 8KHz.

Conclusion

The documentation states that the beep function can generate 1KHz, 2KHz and 4KHz. By changing the values of the prescalar and the selection register it appears that you can also go as low as 500Hz and as high as 32KHz.

STM8S Independent Watchdog

June 21st, 2014 • Electronics, Software Development, STM8Comments Off on STM8S Independent Watchdog

The Independent Watchdog (IWDG) allows the developer to detect software failures and reset the STM8S microcontroller restarting the application. This post demonstrates how this feature works and how the developer can change the time window for the watchdog.

Watchdogs offer the application developer a simple to use method of determining if an application has entered a state which means that it is locked or taking too long to perform an operation.

The first task is to define what we mean by too long. This will vary from one application to another but the key point is that this should be longer than the longest operation the application will perform plus a margin. Once we have this time period defined we know that the application must reset the IWDG before the time period has elapsed.

Hardware

Independent Watchdog Key Register – IWDG_KR

The Key Register controls the operation of the IWDG. The allowed values are as follows:

ValueDescription
0x55Enable writing to the IWDG_PR and IWDG_RLR registers. These registers are write protected by default.
0xAAReset the IWDG counter to the reload value. This value must be written to the key register periodically in order to prevent the watchdog from resetting the microcontroller.
0xCCEnable and start the IWDG.
0x00Disable writing to the IWDG_PR and IWDG_RLR registers.

The final value in the table is not present in revision 9 of RM0016 – Reference Manual but does appear in the header files for the STD Peripheral Library.

In researching this post a key point in the documentation was missed, namely IWDG_PR and IWDG_RLR can only be written when the IWDG has actually been enabled. This means that the IWDG needs to be running before the prescaler and reload registers can be loaded with the values required by the application. If the IWDG is not running then the system will resort to the default reset values for these registers. This gives a watchdog window of 16ms. It also means that the application has 16ms to set the desired time window through the IWDG_PR and IWDG_RLR registers before the microcontroller is reset.

Independent Watchdog Prescaler – IWDG_PR and Independent Watchdog Reload Register – IWDG_RLR

These two registers define the watchdog window and can. The default values are IWDG_PR = 0 and IWDG_RLR = 0xff. This gives a watchdog window of approximately 16ms. To change the size of the watchdog window use the table below to determine the values which are appropriate for your application:

Prescaler DividerPrescaler Value (IWDG_PR)Period when RL = 0Period when RL = 0xff
4062.5 us15.90 ms
81125 us31.90 ms
162250 us63.70 ms
323500 us127 ms
6441.00 ms255 ms
12852.00 ms510 ms
25664.00 ms1.02 s

The programming reference for the STM8S gives the following formula for determining the exact reset period:

T = 2 x TLSI x P x R

where:

TTimeout period
TLSI1 / fLSI
P2(IWDG_PR + 2)
RIWDG_RLR + 1

Additionally, the time between the last reset of the key register (i.e. writing 0xAA to IWDG_KR) is T + 6 x TLSI.

Software

So lets look at how we can implement this:

//
//  This program demonstrates how to use the Independent Watchdog timer
//  on the STM8S microcontroller in order to detect software failures and
//  reset the microcontroller.
//
//  This software is provided under the CC BY-SA 3.0 licence.  A
//  copy of this licence can be found at:
//
//  http://creativecommons.org/licenses/by-sa/3.0/legalcode
//
#include <iostm8S105c6.h>
#include <intrinsics.h>

//--------------------------------------------------------------------------------
//
//  Setup the system clock to run at 16MHz using the internal oscillator.
//
void InitialiseSystemClock()
{
    CLK_ICKR = 0;                       //  Reset the Internal Clock Register.
    CLK_ICKR_HSIEN = 1;                 //  Enable the HSI.
    CLK_ECKR = 0;                       //  Disable the external clock.
    while (CLK_ICKR_HSIRDY == 0);       //  Wait for the HSI to be ready for use.
    CLK_CKDIVR = 0;                     //  Ensure the clocks are running at full speed.
    CLK_PCKENR1 = 0xff;                 //  Enable all peripheral clocks.
    CLK_PCKENR2 = 0xff;                 //  Ditto.
    CLK_CCOR = 0;                       //  Turn off CCO.
    CLK_HSITRIMR = 0;                   //  Turn off any HSIU trimming.
    CLK_SWIMCCR = 0;                    //  Set SWIM to run at clock / 2.
    CLK_SWR = 0xe1;                     //  Use HSI as the clock source.
    CLK_SWCR = 0;                       //  Reset the clock switch control register.
    CLK_SWCR_SWEN = 1;                  //  Enable switching.
    while (CLK_SWCR_SWBSY != 0);        //  Pause while the clock switch is busy.
}

//--------------------------------------------------------------------------------
//
//  Initialise the ports.
//
//  Configure all of Port D for output.
//
void InitialisePorts()
{
    PD_ODR = 0;             //  All pins are turned off.
    PD_DDR = 0xff;          //  All pins are outputs.
    PD_CR1 = 0xff;          //  Push-Pull outputs.
    PD_CR2 = 0xff;          //  Output speeds up to 10 MHz.
}

The code above should be pretty familiar to anyone who has been following The Way of the Register series of posts. This sets up the system clock to run at 16MHz and sets port D as an output port.

//--------------------------------------------------------------------------------
//
//  Initialise the Independent Watchdog (IWDG)
//
void InitialiseIWDG()
{
    IWDG_KR = 0xcc;         //  Start the independent watchdog.
    IWDG_KR = 0x55;         //  Allow the IWDG registers to be programmed.
    IWDG_PR = 0x02;         //  Prescaler is 2 => each count is 250uS
    IWDG_RLR = 0x04;        //  Reload counter.
    IWDG_KR = 0xaa;         //  Reset the counter.
}

We follow this up by setting up the IWDG. The prescaler and counter values should give a 1ms window.

//--------------------------------------------------------------------------------
//
//  Main program loop.
//
int main()
{
    //
    //  Initialise the system.
    //
    __disable_interrupt();
    InitialiseSystemClock();
    InitialisePorts();
    InitialiseIWDG();
    __enable_interrupt();
    __halt();
}

The main program configures the system and then halts the microcontroller. Without the watchdog this would the end of the application. With the watchdog we should see the microcontroller continuously resetting. This can be verified by connecting an oscilloscope to Port D. If we do this we see the output on the port rise as the microcontroller is reset and the InitialisePorts method is called.

Now replace the __halt(); statement with the following code:

while (1)
{
    IWDG_KR = 0xaa;
}

This code continuously writes the I am alive message to the IWDG key register. Doing this forces the IWDG to reset the counters with the reload values and start again. Running this application we see a flat line following the initial reset of the microcontroller. The flat line indicates that the microcontroller is not being reset.

Conclusion

The Independent Watchdog provides a simple method for detecting software failures merely writing a reset value into the key register.

Earlier the point was made that it appears that the IWDG must be enabled (and hence running) before the prescaler and reload registers can be modified. This point is critical as the microcontroller will resort to the reset values otherwise.

Although not demonstrated here it is possible for the application to determine if the application has been started through the application of power to the microcontroller or because of a reset by the IWDG. This can be determined by checking the value in RST_SR_IWDGF. This will be set to 1 if the IWDG has caused the microcontroller to be reset or 0 otherwise. This is left as an exercise for the reader.

Download

The source code for this post is available for download.

Auto-Wakeup on the STM8S

June 20th, 2014 • Electronics, Software Development, STM8Comments Off on Auto-Wakeup on the STM8S

A few days ago I was asked for advice about pausing the STM8S for a long time period (in this case 30 seconds). I had to admit that I was not sure how to achieve this without using a timer and counting interrupts until the 30 time period had expired. A quick examination of the STM8S Programming Reference reveals that there is a simpler way of doing this. This post examines the Auto-Wakeup (AWU) feature of the STM8S and shows how this feature can be used to pause for a time period which can range from 15.625uS to 30.720s, assuming the clock source is accurate.

Auto-Wakeup (AWU) Feature

The AWU feature wakes the STM8S after a predefined time period following the microcontroller going into the active halt state. This feature can only be used when the microcontroller is halted and the accuracy is dependent upon the clock source.

The clock source is fed into a prescalar. The output from the prescalar is then used as a clock for a counter. The counter will cause an interrupt to be generated when the preset counter value has been reached.

It is also possible to determine the accuracy of the clock source by using the capture compare feature of TIM1 or TIM3 to measure the clock frequency.

Auto-Wakeup Registers

The function of the AWU is determined by the values in the AWU control registers.

Auto-Wakeup Enable – AWU_CSR1_AWUEN

Setting this bit to 1 enables the AWU function. Setting this to 0 disables the function.

Auto-Wakeup Asynchronous Prescalar Divider – AWU_APR_APR and Auto-Wakeup Timebase Selection Register – AWU_TBR_AWUTB

These two registers together control the duration of the AWU. The exact duration of the wakeup period is determined by the AWU_APR_APR and AWU_TBR_AWUTB values from the following table.

fLS = ffLS = 128 kHzAWU_TBR_AWUTBAPRDIV FormulaAWU_APR_APR Range
2/f – 64/f0.015625 ms – 0.5 ms0001APRDIV/fLS2 to 64
2×32/f – 2x2x32/f0.5 ms – 1.0 ms00102 x APRDIV/fLS32 to 64
2×64/f – 2x2x64/f1 ms – 2 ms001122 x APRDIV/fLS32 to 64
22×64/f – 22×128/f2 ms – 4ms010023 x APRDIV/fLS32 to 64
23×64/f – 23×128/f4 ms – 8 ms010124 x APRDIV/fLS32 to 64
24×64/f – 24×128/f8 ms – 16 ms011025 x APRDIV/fLS32 to 64
25×64/f – 25×128/f16 ms – 32 ms011126 x APRDIV/fLS32 to 64
26×64/f – 26×128/f32 ms – 64 ms100027 x APRDIV/fLS32 to 64
27×64/f – 27×128/f64 ms – 128 ms100128 x APRDIV/fLS32 to 64
28×64/f – 28×128/f128 ms – 256 ms101029 x APRDIV/fLS32 to 64
29×64/f – 29×128/f256 ms – 512 ms1011210 x APRDIV/fLS32 to 64
210×64/f – 210×128/f512 ms – 1.024 s1100211 x APRDIV/fLS32 to 64
211×64/f – 211×128/f1.024 s – 2.048 s1101212 x APRDIV/fLS32 to 64
211×130/f – 211×320/f2.080 s – 5.120 s11105 x 211 x APRDIV/fLS26 to 64
211×330/f – 212×960/f5.280 s – 30.720s111130 x 211 x APRDIV/fLS11 to 64

Where fLS = f is the formula which should be used when the inbuilt LSI is not being used.

It may not be possible to obtain an exact time period and the application may have to use the values which give the closest period.

When not in use, AWU_TBR_AWUB should be set to 0 in order to reduce power consumption.

Auto-Wakeup Flag – AWU_CSR1_AWUF

This flag is set when the AWU interrupt has been generated. The flag is cleared by reading the AWU control/status register (AWU_CSR1).

Auto-Wakeup Measurement Enable – AWU_CSR1_MSR

Setting this flag to 1 connects the output from the prescalar to one of the internal timers. This allows the application to accurately determine the clock frequency connected to the AWU prescalar. By measuring the clock frequency the application can adjust the values used for the prescalar divider and the timebase.

Software

Now we have the theory it is time to break out the STM8S Discovery board and the IAR compiler. The application starts pretty much the same as previous examples in this series, by setting the system clock and configuring a port for output:

//
//  This program demonstrates how to use the Auto-Wakeup feature of the STM8S
//  microcontroller.
//
//  This software is provided under the CC BY-SA 3.0 licence.  A
//  copy of this licence can be found at:
//
//  http://creativecommons.org/licenses/by-sa/3.0/legalcode
//
#include <iostm8S105c6.h>
#include <intrinsics.h>

//--------------------------------------------------------------------------------
//
//  Setup the system clock to run at 16MHz using the internal oscillator.
//
void InitialiseSystemClock()
{
    CLK_ICKR = 0;                       //  Reset the Internal Clock Register.
    CLK_ICKR_HSIEN = 1;                 //  Enable the HSI.
    CLK_ECKR = 0;                       //  Disable the external clock.
    while (CLK_ICKR_HSIRDY == 0);       //  Wait for the HSI to be ready for use.
    CLK_CKDIVR = 0;                     //  Ensure the clocks are running at full speed.
    CLK_PCKENR1 = 0xff;                 //  Enable all peripheral clocks.
    CLK_PCKENR2 = 0xff;                 //  Ditto.
    CLK_CCOR = 0;                       //  Turn off CCO.
    CLK_HSITRIMR = 0;                   //  Turn off any HSIU trimming.
    CLK_SWIMCCR = 0;                    //  Set SWIM to run at clock / 2.
    CLK_SWR = 0xe1;                     //  Use HSI as the clock source.
    CLK_SWCR = 0;                       //  Reset the clock switch control register.
    CLK_SWCR_SWEN = 1;                  //  Enable switching.
    while (CLK_SWCR_SWBSY != 0);        //  Pause while the clock switch is busy.
}

//--------------------------------------------------------------------------------
//
//  Initialise the ports.
//
//  Configure all of Port D for output.
//
void InitialisePorts()
{
    PD_ODR = 0;             //  All pins are turned off.
    PD_DDR = 0xff;          //  All pins are outputs.
    PD_CR1 = 0xff;          //  Push-Pull outputs.
    PD_CR2 = 0xff;          //  Output speeds up to 10 MHz.
}

The next step is to provide a method to initialise the AWU function:

//--------------------------------------------------------------------------------
//
//  Initialise the Auto Wake-up feature.
//
//
//
void InitialiseAWU()
{
    AWU_CSR1_AWUEN = 0;     // Disable the Auto-wakeup feature.
    AWU_APR_APR = 38;
    AWU_TBR_AWUTB = 1;
    AWU_CSR1_AWUEN = 1;     // Enable the Auto-wakeup feature.
}

Firstly, the AWU function is disabled. The prescalar is set followed by the timebase. The final step is to re-enable the AWU.

//--------------------------------------------------------------------------------
//
//  Auto Wakeup Interrupt Service Routine (ISR).
//
//  Pulse PD0 for a short time.  The NOP instructions generate a more stable
//  pulse on the oscilloscope.
//
#pragma vector = AWU_vector
__interrupt void AWU_IRQHandler(void)
{
    volatile unsigned char reg;

    PD_ODR = 1;
    asm("nop;");
    asm("nop;");
    PD_ODR = 0;
    reg = AWU_CSR1;     // Reading AWU_CSR1 register clears the interrupt flag.
}

This interrupt handler is triggered at the end of the AWU period. This handler simply pulses pin 0 on port D.

//--------------------------------------------------------------------------------
//
//  Main program loop.
//
int main(void)
{
    //
    //  Initialise the system.
    //
    __disable_interrupt();
    InitialiseSystemClock();
    InitialisePorts();
    InitialiseAWU();
    __enable_interrupt();
    //
    //  Main program loop.
    //
    while (1)
    {
        __halt();
    }
}

The AWU function is turned on when the microcontroller enters the active halt state. A halt instruction is generated by the __halt() method.

Running the above code on the STM8S Discovery board results in the following trace on the oscilloscope:

AWU 3208Hz Signal

AWU 3208Hz Signal

and:

AWU Expanded Pulse

AWU Expanded Pulse

Examining the table above and the values used for the precalar and timebase we should be seeing a pulse with a frequency of approximately 3,368Hz. The actual value measured on the oscilloscope is 3,208Hz. The measurement on the oscilloscope will alway be slightly out due to the time it takes for the ISR to be setup and called. An ISR on the STM8S takes 9 clock cycles to be established, this equates to about 560nS on a system running at 16MHz. The actual difference is 6.25mS. The remainder of the difference comes from the fact that the LSI has an accuracy of +/-12.5%. A quick calculation shows the the LSI was running at about 121KHz at the time this post was written.

Conclusion

AWU offers a simple way of triggering processing at predetermined time periods. The active halt state puts the microcontroller into a low power mode whilst the microcontroller is waiting for the time period to elapse.

It should also be noted that using the LSI results in a slightly variable time period.

Bare Metal GPIO on the Raspberry Pi

June 16th, 2014 • Electronics, Raspberry Pi, Software Development2 Comments »

The Raspberry Pi is classically used as a single board computer running Linux but it also offers the possibility of using the board without Linux (known as bare metal development). Add to this the availability of free ARM development tools and we have the opportunity to develop on a high speed ARM processor at a reasonable cost.

This post explores the steps necessary to toggle a GPIO pin on the Raspberry Pi by directly accessing the registers without the presence of an operating system.

Project Description

For this simple project the software will need to perform three operations:

  • Configure the GPIO port
  • Set the GPIO pins for the selected port
  • Reset the GPIO pins for the selected port

The application here will toggle two GPIO pins, one connected to one of the LEDs on the board (GPIO16 connected to the OK/ACT LED) and the second connected to a pin on the header (GPIO18 connected to Pin 12 on header P1).

Resources

There are already a number of resources out on the internet which cover this topic including a large number references in the Bare Metal forum on the Raspberry Pi web site.

As well as the Raspberry Pi web site there are a number of other sites discussing OS development for the Raspberry Pi. This post was going to be a comprehensive write up of the tools and various scripts required to put together a bare metal example but I have since discovered an excellent tutorial on this subject on the OSDev web site. I would heartily recommend that you visit this web site and review the material on the Raspberry Pi C Tutorial page.

Hardware

Before we look at the registers we need to take a look at the first chapter of the Broadcom BCM2835 ARM Peripheral document. Particularly the following two paragraphs:

Physical addresses range from 0x20000000 to 0x20FFFFFF for peripherals. The bus addresses for peripherals are set up to map onto the peripheral bus address range starting at 0x7E000000. Thus a peripheral advertised here at bus address 0x7Ennnnnn is available at physical address 0x20nnnnnn.

and

The peripheral addresses specified in this document are bus addresses. Software directly accessing peripherals must translate these addresses into physical or virtual addresses, as described above. Software accessing peripherals using the DMA engines must use bus addresses.

The remainder of the document discusses the registers and uses addresses in the 0x7Ennnnnn-0x7EFFFFFF memory range. This means that any software written should translate the 0x7Ennnnnn range down to the 0x20nnnnnn range.

GPIO Configuration Register

The software will need to set the function for GPIO pins 16 and 18 using the function select registers. The description of these registers and the GPIO pins which they relate to can be found on page 92 of the Broadcom BCM2835 ARM Peripheral manual. The port is configured using three bits in the register. The three bits have the following meaning:

Bit FieldDescription
000GPIO Pin is an input
001GPIO Pin is an output
100GPIO Pin configured for alternate function 0
101GPIO Pin configured for alternate function 1
110GPIO Pin configured for alternate function 2
111GPIO Pin configured for alternate function 3
011GPIO Pin configured for alternate function 4
010GPIO Pin configured for alternate function 5

The two pins the software will be accessing are pins 16 and 18. These pins are configured using bits 24-26 for GPIO 18 and 18-20 for GPIO 16 of the GPFSEL1 register at 0x7E200004. This maps to the address 0x20200004.

Set GPIO Pin High

The GPIO pins are set by setting a bit in the GPSETn registers. Both GPIO16 and GPIO18 are set through the GPSET0 register (see page 95 of the Broadcom BCM2835 ARM Peripheral manual). The address of this register is 0x7E20001C (0x2020001C).

Set GPIO Pin Low (Clear the GPIO Pin)

The GPIO pins are reset by setting a bit in the GPCLRn registers. Both GPIO16 and GPIO18 are set through the GPCLR0 register (see page 95 of the Broadcom BCM2835 ARM Peripheral manual). The address of this register is 0x7E200028 (0x20200028).

Software

The application is a relatively simple one, toggling a GPIO pin continuously. The following should suffice:

//
//  Flags used to configure the GPIO port.
//
#define FLAG_GPIO_RESET     ((7 << 18) | (7 << 24))
#define FLAG_GPIO_CONFIG    ((1 << 18) | (1 << 24))
//
//  Bits which will allow control of GPIO0 pins for the status
//  LED and the header on the Pi.
//
#define GPIO_PINS           ((1 << 16) | (1 << 18))
//
//  The following register definitions are used to access the GPIO
//  pins on the BCM2835.  The register definitions are taken from
//  section 6 of the BCM manual and the mapping is described in
//  section 1 of the same.
//
//  Address of the register which will configure the GPIO pins.
//
volatile unsigned int *gpsel1 = (unsigned int *) 0x20200004;
//
//  Address of the register which will set the GPIO pins.
//
volatile unsigned int *gpset0 = (unsigned int *) 0x2020001C;
//
//  Address of the register which will clear the GPIO pins.
//
volatile unsigned int *gpclr0 = (unsigned int *) 0x20200028;
//
//  Contents of the GPIO configuration register.
//
unsigned int gpioConfig;
//
//  Main program loop.
//
int main()
{
    //
    //  Reconfigure GPIO 16 and 18 to be outputs.  Clear any
    //  previous GPIO configuration for these pins.
    //
    gpioConfig = *gpsel1;
    //
    //  Firstly, remove any configuration for GPIO 16 & 18.
    //
    gpioConfig &= ~FLAG_GPIO_RESET;
    //
    //  Now configure GPIO 16 & 18 to be plain GPIO outputs.
    //
    gpioConfig |= FLAG_GPIO_CONFIG;
    *gpsel1 = gpioConfig;
    //
    //  Toggle GPIO 16 and 18 forever.
    //
    while (1)
    {
        *gpclr0 = GPIO_PINS;
        *gpset0 = GPIO_PINS;
    }
    return(0);
}

The makefile I used to build the application looks as follows:

#
#   Root directory/name of the ARM tools used to build the application.
#
ARMTOOLSROOT = e:\utils\gcc-arm\bin\arm-none-eabi

#
#   C Compiler options.
#
OPTIONS = -nostdlib -ffreestanding -O3

#
#   What do we need to make to build everything?
#
all: kernel.img
    copy /y /d kernel.img j:\

HelloWorldBlinky.o : HelloWorldBlinky.c
	$(ARMTOOLSROOT)-gcc $(OPTIONS) -c HelloWorldBlinky.c -o HelloWorldBlinky.o

HelloWorldBlinky.elf : memmap HelloWorldBlinky.o 
	$(ARMTOOLSROOT)-ld HelloWorldBlinky.o -T memmap -o HelloWorldBlinky.elf
	$(ARMTOOLSROOT)-objdump -D HelloWorldBlinky.elf > HelloWorldBlinky.list

kernel.img : HelloWorldBlinky.elf
	$(ARMTOOLSROOT)-objcopy HelloWorldBlinky.elf -O binary kernel.img

#
#   Delete any previously built files.
#
clean :
	del -f HelloWorldBlinky.o
	del -f HelloWorldBlinky.elf
	del -f HelloWorldBlinky.list
	del -f kernel.img

Tools

The software present here was compiled using the version 4.8.3 of the ARM eabi tools.

Conclusion

Compiling the above code and executing the application results in the following output when the oscilloscope is connection to GPIO18:

Raspberry Pi GPIO Output

Raspberry Pi GPIO Output

It is necessary to review the documents in the resources section of this post in order to fully understand the theory behind this application.

And now it is time to take on some more complex topics.

Learning Objective-C by Developing iPhone Games

June 4th, 2014 • iOSComments Off on Learning Objective-C by Developing iPhone Games

In the last few weeks I have been reading Learning Objective-C by Developing iPhone Games in order to improve my iPhone development skills. A topical subject given this week is the start of Apple’s WWDC.

Learning Objective-C by Developing iPhone Games offers an insight into the iPhone development platform from a games programmers perspective. The book covers the fundamentals of the Objective-C programming language and the development environment.

The early chapters cover the installation of the tools (XCode) and the process of applying for a development certificates along with an insight into the basic language constructs.

The book moves on from the basic environment and gets started with the development of a basic Space Invaders game. The text covers the basic theory of games development including state machines and frame rates putting this into perspective discussing the resource constrained environment of the iPhone.

Later chapters cover the topics of sound and sprite animation and uses three other games (Simon Says, Mini Golf and Galaxy) to cover these topics.

The final chapters gives advice on publishing your game through the Apple store with detailed instructions on the process. I will be reaching for this book when I finally get around to publishing an app through the store.

Conclusion

The title of the book suggests this is suitable for a beginner and I believe that it is suitable for an experienced developer who wants to use this book as an introduction to the iPhone platform. I also think that a new/novice programmer should also invest in a book dedicated to Objective-C and programming theory as the book is a little light in these areas. There are also some inconsistencies which will annoy an experienced developer and risk confusing a novice. Having said this it is still a good introduction to this topic.

Form more information on this title follow this link: Learning Objective-C by Developing iPhone Games

Image Renamer

May 2nd, 2014 • Photography, Software DevelopmentComments Off on Image Renamer

Tornado Leaving York

This year has been busy and after the heavy workload at the start of the year April was a time for some much needed R&R. Time to break out the camera and explore a little of Yorkshire. During the month I took about 1,300 photographs storing both the raw sensor data and a high quality JPG image. This leaves me with a whole series of files with names like DSC_0001.nef and a corresponding JPG file DSC_0001.jpg. These names are not really descriptive of the contents of the image. Renaming the files is easy but I also need to guarantee that the link between the raw file and the JPG file is retained.

This project is trivial but I have decided to present this as I could not find any software which would do what I needed. Being a Software Engineer I decided to turn to Visual Studio and solve the problem myself.

The project files and binary are available for download (see the conclusion at the end of this article).

Image File Renamer

So the project brief is:

  • Rename all of the files in a directory with a specific root file name
  • Add a sequence number to the file name
  • If there is a raw file and a JPG file with the same source root file name then make sure that the two files have the same destination root file name

Should be simple enough to achieve with a small command line program.

Parsing the Command Line

First this we need to do is to find out what the user wants the application to do. In order to achieve this we need to parse the command line.

Parsing the command line is a simple task and I have written classes to do this many times in the past but recently I have come across the CommandLineParser library on CodePlex. This library is powerful and performs many of the common command line parsing tasks for you. All you need to do is provide a class with properties decorated by appropriate attributes (more on that later).

Installation is easy. Start Visual Studio and create a new C# Windows console line project. Next Open the Package Manager console (Tools -> NuGet Package Manager -> Package Manager Console) and enter the command Install-Package CommandLineParser. A few seconds later the package will have bee downloaded and added to the project. All we need to do now is use it.

The two obvious options which are needed for this application to work are the new name to be used as the root of the file name and the directory which contains the source files. These two options are represented by two properties in the options class. The code for this is as follows:

using CommandLine;
using CommandLine.Text;

namespace PhotoRenamer
{
    /// <summary>
    /// Class to parse and hold the command line options.
    /// </summary>
    class Options
    {
        /// <summary>
        /// Location of the source files.
        /// </summary>
        [Option('d', "directory", DefaultValue = ".", HelpText = "Directory containing files to be renamed (default = .)")]
        public string SourceDirectory { get; set; }

        /// <summary>
        /// New source name for the files.
        /// </summary>
        [Option('n', "name", Required = true, HelpText = "Root of the new file name.")]
        public string Name { get; set; }

        [ParserState]
        public IParserState LastParserState { get; set; }

        /// <summary>
        /// Build up the usage text.
        /// </summary>
        /// <returns>Options string</returns>
        [HelpOption]
        public string GetUsage()
        {
            return HelpText.AutoBuild(this, (HelpText current) => HelpText.DefaultParsingErrorsHandler(this, current));
        }
    }
}

As you can see, the properties within the class which represent the two command line options are decorated by an Option attribute. The attribute informs the CommandLineParser how it should deal with the property and the name and type of option it should expect.

The class is set up by creating a new instance of the Options class and executing the following code:

var options = new Options();
try
{
    if (CommandLine.Parser.Default.ParseArguments(args, options))
    {
        // Your application logic goes here.
    }
}
catch (Exception ex)
{
    Console.WriteLine(options.GetUsage());
}

This will parse the command line and set the properties accordingly. An exception will be thrown if there is a problem parsing the command line or if any of the mandatory options are not present.

The main application logic will create a list of all of the JPG files in a directory, rename the file and then look for an associated raw image file. If the raw image file exists then it is also renamed using the same root file name and sequence number. The source code is present here for completeness:

using System;
using System.IO;

namespace PhotoRenamer
{
    class Program
    {
        static void Main(string[] args)
        {
            var options = new Options();
            try
            {
                if (CommandLine.Parser.Default.ParseArguments(args, options))
                {
                    if (options.Verbose)
                    {
                        Console.WriteLine("Directory: {0}", options.SourceDirectory);
                        Console.WriteLine("Root name: {0}", options.Name);
                    }

                    if (Directory.Exists(options.SourceDirectory))
                    {
                        try
                        {
                            string[] files = Directory.GetFiles(options.SourceDirectory);
                            int sequenceNumber = 1;
                            int filesProcessed = 0;
                            string jpgExtension = string.Format(".{0}", options.JPGExtension.ToLower());
                            string rawExtension = string.Format(".{0}", options.RawExtension.ToLower());
                            foreach (string file in files)
                            {
                                if (Path.GetExtension(file).ToLower().Equals(jpgExtension))
                                {
                                    string newRootFileName = string.Format("{0}\\{1} {2:0000}", options.SourceDirectory, options.Name, sequenceNumber++);
                                    string jpgFileName = string.Format("{0}{1}", newRootFileName, jpgExtension);

                                    if (options.Verbose)
                                    {
                                        Console.WriteLine("Renaming file {0} to {1}", file, jpgFileName);
                                    }
                                    File.Move(file, jpgFileName);
                                    filesProcessed++;
                                    string sourceNEFFileName = string.Format("{0}\\{1}{2}", Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file), rawExtension);
                                    if (File.Exists(sourceNEFFileName))
                                    {
                                        string newNEFFileName = string.Format("{0}{1}", newRootFileName, rawExtension);
                                        if (options.Verbose)
                                        {
                                            Console.WriteLine("Renaming file {0} to {1}", sourceNEFFileName, newNEFFileName);
                                        }
                                        File.Move(sourceNEFFileName, newNEFFileName);
                                        filesProcessed++;
                                    }
                                }
                            }
                            Console.WriteLine("{0} Files processed.", filesProcessed);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.Message);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Directory '{0}' does not exist.", options.SourceDirectory);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(options.GetUsage());
            }
        }
    }
}

Three additional properties have been added to the Options class, two to support different raw and JPG file name extensions and a final option to put the application into verbose mode.

Conclusion

This application provides a simple methods of renaming image files keeping the link between the original raw and JPG files. The source code and compiled binary can be downloaded and used on a royalty free basis.

The source code and application are provided as is and no warranty is provided.