RSS

Archive for the ‘Software Development’ Category

Making a Netduino GO! Module – Conclusion

Tuesday, May 7th, 2013

Making the OutputExpander module has been an interesting journey. The original drawings started in August 2012 and then sat on the hard drive for about eight months. Much of the time following the original drawings were spent working out how the STM8S worked. You can find out more in The Way of the Register series (something I will pick up again soon, to my mind there are a few missing topics).

For those who do not know, I’m a software engineer and electronics is a hobby. The prospect of designing a board and using SMD components would have been unthinkable to me two years ago. Today I sit here with my first prototype PCB connected to a commercial board and the output looks reasonably professional – well I’ll let you decide.

Completed Board

Completed Board

Not looking too bad if I say so myself.

So let’s look at what I have learned and also how long the project took.

Lessons Learned

With all projects we should look back and learn from the experience, both good and bad. So here are a few things I have learned over the past few months.

Designing the Board

The original design started life in August 2012. I probably should have taken the plunge and developed the board a little quicker than I did although in truth, I did not get the major requirement of the board, namely GoBus 1.0 really sorted out until late November 2012.

Prototyping

This was probably the simplest bit of the project. I have all of the standard components in my toolbox already and I also have the tools required. This was really a case of getting the system working. The hardest part was getting to grips with the STM8S, a story I have documented in The Way of The Register series of posts.

Schematic

During this part of the design phase I tried several different packages. All of them had strengths and weaknesses. I finally settled on DesignSpark. For me this package had three major strengths:

  • It’s free
  • You can use it for commercial projects
  • It feels like a Windows application
  • In fairness it does have a few weaknesses. The most obvious for me was the lack of the ability to add images of any kind to the design. Come on, at version 5 you should have this one!

    Nets – I discovered these when producing the final draft of the schematic. These allowed the separation of the nets into logical groups/functions/areas. It made the schematic a lot cleaner.

    Schematic to Manufacture

    For me this was the where I learned the most. The first thing I learned was that auto-routers are dreadful. They are slow and produce some interesting board layouts. This board is a simple board and yet the auto-router still took a long time to make a half-hearted attempt at routing the board. In the end I did this manually. This was not too much of a problem as the board was simple.

    Next, you have to learn to think in three dimensions. You have two layers so use them.

    The Netduino modules produced by Secret Labs have nice rounded corners – these are a devil to produce in DesignSpark. I think that the module I produced has one corner which is slightly different from the others.

    The cost of prototyping is a lot lower than I thought. Ten boards including shipping costs about £18 and only took 10 days.

    I now know what 0403 means. The ‘0’ stands for Ohhh my goodness that’s small. Seriously, the four digits should be split into two and thy give the dimensions of the component. So for a metric component an 0403 part is 0.4 x 0.3 mm – that’s small.

    The STM8S part selected has a 0.65mm pitch for the pins. I originally found this a little worrying. Don’t be afraid – they are not that bad.

    Get a USB microscope when soldering SMD components. This tools is cheap and allows the examination of joints for shorts. The quality will never be great, mine only runs at 640×480, but a 400x zoom means you can be sure that you have no problems.

    Add test points. There came a point when I was making the board and I needed to see the data going through to the 74HC595’s. I did not have a suitable connection and so I had to solder a piece of wire to the board:

    Improvised Test Point

    Improvised Test Point

    A good test point would have made this easier.

    How Long Did it Take

    The original drawing started in August 2012 and the final board was put together and tested only yesterday. So in elapsed time that’s about nine months. In real working time this broke down as follows:

    Activity Duration (Hours)
    Building Prototype circuit 2
    Prototype software 3
    Schematic 6
    PCB layout 20
    Assembly and testing 5
    Enhanced software 4
    Total 40

    Something to bear in mind is that no production evaluation or component selection has been conducted as part of this project. It was supposed to be the final item on the list. I am still not sure if this should be taken through to manufacture – time will tell.

    Another item to be considered is to achieve the Netduino GO! logo approval. At the time of writing this required the approval of the board by Secret Labs – this activity has not been completed.

    Conclusion

    Well, that was a hectic few weeks.

    Did I enjoy it – YES!

    Would I recommend that you try it – YES!

    As for me, I’ll be taking a few days off of hardware development and blogging. Love doing it but it can take it’s toll.

    I suppose you may be interested in some downloads…

    If you use any of the code or techniques discussed in this series of posts then please let me know as I’m interested in what other people are doing with this work.

    Making a Netduino GO! Module – Stage 5 – Enhancing the Drivers

    Saturday, April 27th, 2013

    This series of posts follows the steps required in order to make your own Netduino GO! module. To do this we are using a simple idea, an Output Expander (yes, it seems to have a name now) for the Netduino GO!. Using only a hand full of simple components, the Output Expander will add 32 digital outputs to the Netduino Go!.

    The Story So Far…

    The module has so far completed the following steps:

    • Concept and prototype on breadboard
    • Basic drivers
    • PCB design and layout
    • Generation of PCB manufacturing files

    The first batch of 10 boards were ordered on 20th April 2013 using iTeads prototyping service. I am expecting the manufacturing process to take about one week with a further two weeks for shipping as I used the cheap, slow courier service.

    In the meantime we still have the breadboard prototype to work with. This may only have two shift registers attached to it but by carefully parametrising the code we should be able to develop a driver which only needs to be recompiled when the final hardware becomes available.

    Features

    The driver for this module should be relatively simple as we are merely setting outputs from the shift registers to be either on or off. We shall start with the following list of desired features:

    • Default initialisation to set up for one board
    • Set the bytes for the digital outputs
    • Array like access for the bits
    • Configurable latching mode (automatic or manual)
    • Clear the output
    • Turn outputs from the registers on or off

    The only remaining task is to decide where the features are to be implemented. We have two options:

    • On the Netduino GO! in C#
    • On the STM8S in C

    Some of the code is better left on the Netduino GO! with the base features (setting all of the register values etc) being implemented on the STM8S.

    Initialisation

    Initialisation should allow for the use of cascaded boards. If you look back at the schematic you will notice a connector called CascadeConn. This connector allows the addition of a simpler board as an expansion module. This board only need to supply additional shift registers leaving the first, main board supplying the logic to communicate with the Netduino GO!. The concept is that if you want 64 outputs then you would have a single Output Expander module with a single, cheaper daughter board.

    In order to support the addition of the daughter board the initialisation will need to support the specification of the number of shift registers in the cascade.

    In supporting the cascading of these boards we will also need to provide some sensible default values. The basic case is a single board which contains four shift registers.

    We should also consider a maximum value for the number of shift registers. In this case I am going to set this to 12 for two reasons:

    • Power considerations – all of the power for the shift registers is being provided by the Netduino GO!
    • Data packet size – the data packets used in the GoBus are fixed size. Keeping the number of shift registers to a value where only one data packet is required simplifies the communication between the Netduino GO! and the module as a single packet can be used for all messages.

    In order to facilitate this we will need code on both the Netduino GO! and the module.

    Module Code

    The code on the module should allow for the number of shift registers to be set up (assuming a default value of four registers) and then clear the registers. The default code should be called when the module is re-initialised.

    //--------------------------------------------------------------------------------
    //
    //  GO! function 3 - Set up the module.
    //
    void SetUp()
    {
        U8 n = _rxBuffer[2];
        if ((n < 0) && (n < MAX_REGISTERS))
        {
            _numberOfShiftRegisters = n;
            free(_registers);
            _registers = (U8 *) malloc(n);
            ClearRegisters();
            OutputData();
            NotifyGOBoard();
        }
    }
    

    Netduino GO! Code

    The initialisation code on the Netduino GO! will assume that the startup code on the module will initialise itself to four shift registers. This will reduce the communications overhead between the Netduino GO! and the module. The following when added to the Initialise method should set up the module driver on the Netduino GO! for a variable number of shift registers in the sequence:

    //
    //  Next, set up the space to store the data.
    //
    _shiftRegisterData = new byte[numberOfShiftRegisters];
    for (int index = 0; index < numberOfShiftRegisters; index++)
    {
        _shiftRegisterData[index] = 0;
    }
    LatchMode = LatchingMode.Automatic;
    if (numberOfShiftRegisters != 4)
    {
        _writeFrameBuffer[0] = GO_BUS10_COMMAND_RESPONSE;
        _writeFrameBuffer[1] = CMD_SETUP;
        _writeFrameBuffer[2] = (byte) (numberOfShiftRegisters & 0xff);
        WriteDataToModule("Initialise: cannot setup the OutputExpander module");
    }
    

    Set Outputs

    Setting the outputs is simply a case of sending a number of bytes, one for each shift register to the module.

    /// <summary>
    /// Set the shift registers using the values in the byte array.
    /// "/summary>
    /// "param name="registers">Bytes containing the shift register values.</param>
    public void Set(byte[] registers)
    {
        if (registers.Length != _shiftRegisterData.Length)
        {
            throw new ArgumentException("registers: length mismatch");
        }
        for (int index = 0; index < registers.Length; index++)
        {
            _shiftRegisterData[index] = registers[index];
        }
        Latch();
    }
    

    The module code needs a slight adjustment to transfer the correct number of incoming bytes to the register store:

    //--------------------------------------------------------------------------------
    //
    //  GO! function 2 - Output the specified bytes to the shift registers.
    //  Tx buffer.
    //
    void SetShiftRegisters()
    {
        for (int index = 0; index < _numberOfShiftRegisters; index++)
        {
            _registers[index] = _rxBuffer[2 + index];
        }
        OutputData();
        NotifyGOBoard();
    }
    

    Array of Bits

    From a software point of view, a shift register is nothing more than an array of boolean values. Internally it makes sense for the driver to allow this abstraction and use the indexing operator to set a single bit at a time. The code for this operator looks something like this:

    /// <summary>
    /// Overload the index operator to allow the user to get/set a particular 
    /// bit in the shift register.
    /// </summary>
    /// <param name="bit">Bit number to get/set.</param>
    /// <returns>Value in the specified bit.</returns>
    public bool this[int bit]
    {
        get
        {
            if ((bit >= 0) && (bit < (_shiftRegisterData.Length * 8)))
            {
                int register = bit >> 3;
                byte mask = (byte) (bit & 0x07);
                return ((_shiftRegisterData[register] & mask) == 1);
            }
            throw new IndexOutOfRangeException("OutputExpander: Bit index out of range.");
        }
        set
        {
            if ((bit >= 0) && (bit < (_shiftRegisterData.Length * 8)))
            {
                int register = bit >> 3;
                byte mask = (byte) ((1 << (bit & 0x07)) & 0xff);
                if (value)
                {
                    _shiftRegisterData[register] |= mask;
                }
                else
                {
                    mask = (byte) ~mask;
                    _shiftRegisterData[register] &= mask;
                }
                if (LatchMode == LatchingMode.Automatic)
                {
                    Latch();
                }
            }
            else
            {
                throw new IndexOutOfRangeException("OutputExpander: Bit index out of range.");
            }
        }
    }
    

    Adding the above code allows the programmer to use constructs such as:

    OutputExpander outputs = new OutputExpander();
    outputs[2] = true;
    

    instead of the more obscure:

    OutputExpander outputs = new OutputExpander();
    byte[] data = new byte[4];
    data[0] = 0x04;
    SetOutputs(data);
    

    Not only is the former example more elegant but it is also more concise.

    Clear All Registers

    This method will simply clear the shift registers and set the outputs to 0;

    /// <summary>
    /// This method calls the ClearRegister method on the GO! module and then waits for the
    /// module to indicate that it has received and executed the command.
    /// </summary>
    public void Clear()
    {
        _writeFrameBuffer[0] = GO_BUS10_COMMAND_RESPONSE;
        _writeFrameBuffer[1] = CMD_CLEAR_REGISTERS;
        for (int index = 0; index < _shiftRegisterData.Length; index++)
        {
            _shiftRegisterData[index] = 0;
        }
        WriteDataToModule("Clear cannot communicate with the Output Expander module");
    }
    

    This method could have been rewritten to set the values to 0 and then send the values to the module. However, the prototype already had an implementation of a clear command and so this was left in as is.

    Latch Mode

    The introduction of the array indexing operators does introduce on complication, namely that we cannot set all of the outputs to a specified value at the same time without delaying the latching of the registers. Consider the following case:

    OutputExpander outputs = new OutputExpander();
    outputs[2] = true;
    outputs[3] = true;
    

    In this case we would set bit 2 of the lower shift register followed by bit 3 of the same shift register. Because of the speed of .NETMF there would be a slight delay between the two outputs of the shift register being set high. In order to allow for this we introduce the ability to delay the latching of the data from the internal shift register into the output register.

    /// <summary>
    /// Determine when the data should be sent to the module.
    /// </summary>
    public enum LatchingMode
    {
        /// <summary>
        /// Automtically send the data to the module as soon as there are any changes.
        /// </summary>
        Automatic,
        /// <summary>
        /// Manually latch the data.
        /// </summary>
        Manual
    }
    
    /// <summary>
    /// Backing variable for the LatchMode property.
    /// </summary>
    private LatchingMode _latchMode;
    
    /// <summary>
    /// Determine how the data will be send to the module.  The default is to 
    /// automatically send data as soon as there are any changes.
    /// </summary>
    public LatchingMode LatchMode
    {
        get { return (_latchMode); }
        set { _latchMode = value; }
    }
    

    The initialisation of the class would also need to be modified in order to set the mode to automatic:

    LatchMode = LatchingMode.Automatic;
    

    The most lightweight method of using the LatchMode is to simply not send the data to the shift registers until the mode is either reset or until the controlling program explicitly latches the data. The Set method will therefore need some adjustment to take into account the two modes:

    /// <summary>
    /// Set the shift registers using the values in the byte array.
    /// </summary>
    /// <param name="registers">Bytes containing the shift register values.</param>
    public void Set(byte[] registers)
    {
        if (registers.Length != _shiftRegisterData.Length)
        {
            throw new ArgumentException("registers: length mismatch");
        }
        for (int index = 0; index < registers.Length; index++)
        {
            _shiftRegisterData[index] = registers[index];
        }
        if (LatchMode == LatchingMode.Automatic)
        {
            Latch();
        }
    }
    

    Latch Operation

    The introduction of the LatchMode means that we also need to allow for the data to be latched into the shift registers.

    /// <summary>
    /// Call the Set command on the module to set the outputs of the shift registers.
    /// </summary>
    private void Set()
    {
        _writeFrameBuffer[0] = GO_BUS10_COMMAND_RESPONSE;
        _writeFrameBuffer[1] = CMD_SET_REGISTERS;
        for (int index = 0; index < _shiftRegisterData.Length; index++)
        {
            _writeFrameBuffer[2 + index] = _shiftRegisterData[index];
        }
        WriteDataToModule("Latch cannot communicate with the Output Expander module");
    }
    

    The above method simply sends the data to the module.

    Testing

    We can perform some simple testing of the software while the prototype boards are being made by using the breadboard test environment build in the first post. This board only has two shift registers but it should be possible to test the majority of functionality using this board.

    In the previous posts we have cycled through the bits one at a time either from 0 to 15 or down from 15 to 0. In this example we will perform some counting and use the LEDs to display the number in binary. Our test code becomes:

    output = new OutputExpander(2);
    short cycleCount = 0;
    byte[] registers = new byte[2];
    output.LatchMode = OutputExpander.LatchingMode.Manual;
    while (true)
    {
        Debug.Print("Cycle: " + ++cycleCount);
        short mask = 1;
        output.Clear();
        for (int index = 0; index <= 15; index++)
        {
            if ((cycleCount & mask) != 0)
            {
                output[index] = true;
            }
            mask <<= 1;
        }
        output.Latch();
        Thread.Sleep(200);
    }
    

    Deploying this application should result in the Netduino GO! counting up from 0 and the binary representation of cycleCount being output on the shift registers. The following video shows this in action:

    Conclusion

    The above minor modifications to the STM8S module code and the Netduino GO! driver has added the following functionality:

    • Default initialisation to set up for one board
    • Set the bytes for the digital outputs
    • Array like access for the bits
    • Configurable latching mode (automatic or manual)
    • Clear the output
    • Turn outputs from the registers on or off

    The code has been carefully written so that we should only need to change two parameters when the final PCBs arrive in order to change the drivers from two shift registers to four shift registers.

    A quick test has shown that the main functionality appears to be working on the breadboard prototype as demonstrated by the above video. The prototype PCBs have completed manufacture and are currently with the Hong Kong postal service (as of 27th April 2013). Delivery should take another 7-10 days so there is plenty of time to complete the test suite.

    Making a Netduino GO! Module – Stage 2 – Connect the GO! to the Breadboard

    Friday, April 12th, 2013

    In the previous post a prototype for the multiple digital outputs was developed and implemented on breadboard. The STM8S code was independent and demonstrated that two chained 74HC595 shift registers could be controlled by bit-banging data through GPIO pins on the STM8S.

    In this post we will continue the development of the module by merging the code from the previous post with the STM8S module code from the post STM8S SPI Slave (Part 3) – Making a Go Module. We will develop both the STM8S code and the NETMF driver to implement the following functionality:

    • Clear the shift registers
    • Set the outputs of the two shift registers

    These two functions are already in the standalone version of the STM8S code and it should be a relatively simple exercise to merge this functionality with the Netduino Go Bus communication protocol.

    STM8S Application

    The first task to be completed for the STM8S code is to create a new project and add the code from the post STM8S SPI Slave (Part 3) – Making a Go Module. The two functions should then be removed and the two new ones we are implementing should be added.

    Start a New Project

    Start a new STM8S project and save the project into a new directory. Now take the source code in main.c from the project STM8S SPI Slave (Part 3) – Making a Go Module and paste over the code in you new project. Ensure that the project is targeting the correct microcontroller and save the project.

    Alternatively, copy the project code from STM8S SPI Slave (Part 3) – Making a Go Module into a new directory.

    Remove Dummy Functionality

    The project code in the STM8S module post contained a couple of dummy functions illustrating the concept of module functionality and communications. This code should be removed and the application stripped down to the basics required for SPI communication with the Netduino Go!.

    Add New Functionality

    The final task is to add the code which implements the new functionality as defined for the basic module (i.e. clear the shift registers and set the outputs of the shift registers).

    The first thing which is required is to add the #define statements to support the bit-banging:

    //--------------------------------------------------------------------------------
    //
    //  Pins which we will be using for output the data to the shift registers.
    //
    #define SR_CLOCK            PD_ODR_ODR3
    #define SR_DATA             PD_ODR_ODR2
    #define SR_CLEAR            PC_ODR_ODR3
    #define SR_OUTPUT_ENABLE    PC_ODR_ODR4
    #define SR_LATCH            PD_ODR_ODR4
    

    The InitialisePorts method will also need to be modified in order to ensure that the ports above are all setup correctly. We need these to be output ports capable of running at up to 10MHz. The code becomes:

    //--------------------------------------------------------------------------------
    //
    //  Initialise the ports.
    //
    void InitialisePorts()
    {
        //
        //  Initialise Port D.
        //
        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.
        //
        //  Initialise Port C.
        //
        PC_ODR = 0;             //  Turn port C outputs off.
        PC_DDR = 0x18;          //  PC3 &amp; PC4 initialised for output.
        PC_CR1 = 0x18;          //  PC3 &amp; PC4 Push-Pull outputs
        PC_CR2 = 0x18;          //  PC3 &amp; PC4 can run up to 10MHz.
        //
        //  Initialise the CS port for input and set up the interrupt behaviour.
        //
    #if defined(DISCOVERY)
        PB_ODR = 0;             //  Turn the outputs off.
        PB_DDR = 0;             //  All pins are inputs.
        PB_CR1 = 0xff;          //  All inputs have pull-ups enabled.
        PB_CR2 = 0xff;          //  Interrupts enabled on all pins.
        EXTI_CR1_PBIS = 2;      //  Port B interrupt on falling edge (initially).
    #else
        PA_ODR = 0;             //  Turn the outputs off.
        PA_DDR = 0;             //  All pins are inputs.
        PA_CR1 = 0xff;          //  All inputs have pull-ups enabled.
        PA_CR2 = 0xff;          //  Interrupts enabled on all pins.
        EXTI_CR1_PAIS = 2;      //  Port A interrupt on falling edge (initially).
    #endif
    }
    

    The application will also need some storage space for the data in the shift registers:

    //--------------------------------------------------------------------------------
    //
    //  Number of registers in the chain.
    //
    #define NUMBER_OF_REGISTERS     2
    //
    //  Data area holding the values in the register.
    //
    U8 _registers[NUMBER_OF_REGISTERS];             //  Data in the shift registers.
    

    Note that the variable used to store the data in the registers has been converted into a static array instead of a variable sized array using malloc.

    The function table needs to be modified to hold the references to the methods which will implement the module functionality:

    //
    //  Forward function declarations for the function table.
    //
    void SetShiftRegisters();
    void ClearShiftRegisters();
    //
    //  Table of pointers to functions which implement the specified commands.
    //
    FunctionTableEntry _functionTable[] = { { 0x01, ClearShiftRegisters }, { 0x02, SetShiftRegisters } };
    

    The next step is to add the methods which will implement the functionality:

    //--------------------------------------------------------------------------------
    //
    //  Clear the shift registers.
    //
    void ClearRegisters()
    {
        for (U8 index = 0; index < NUMBER_OF_REGISTERS; index++)
        {
            _registers[index] = 0;
        }
    }
    
    //--------------------------------------------------------------------------------
    //
    //  GO! Function 1 - Clear the shift registers.
    //
    void ClearShiftRegisters()
    {
        ClearRegisters();
        OutputData();
        NotifyGOBoard();
    }
    

    Note that the functionality has been implemented using two methods, the first ClearRegisters is the internal implementation. This is independent of the Netduino Go! communications and allows the functionality to be called in say the initialisation code of the module. The second method, ClearShiftRegisters is the method which is called by the code as determined by the Netduino Go! driver code. This has the additional output and notification methods which actually sets the data in the shift registers and sends a signal back to the Netduino Go! to let the board know that the request has been received and processed. Note that this split is not necessary but is a design decision taken for this particular module.

    The code should be ready to compile and deploy to the STM8S.

    Netduino Go! Driver

    At this point we should have one half of the communications channel ready to test. The second stage is to implement the driver on the Netduino Go!. As our starting point, we will copy the code from the BasicGoModule class in the post STM8S SPI Slave (Part 3) – Making a Go Module into a new class OutputExpander. We will modify this to add create new functionality to clear and set the shift registers.

    Command Constants

    The first this we need to do is to remove the old command constants and add two new ones:

    /// <summary>
    /// Command number for the ClearShiftRegister command.
    /// </summary>
    private const byte CMD_CLEAR_REGISTERS = 1;
    
    /// <summary
    /// Command number for the SetRegister command.
    /// </summary>
    private const byte CMD_SET_REGISTERS = 2;
    

    Modify the Supporting Methods

    The existing code in the module can be optimised for this module. To do this rename the WriteDataToModule method to WriteDataToSPIBus. Now add the following code:

    /// <summary>
    /// Write the data in the _writeFrameBuffer to the module.  Make several
    /// attempts to write the data before throwing an exception.
    /// </summary>
    /// <param name="exceptionMessage">Exception message to the used in the constructor if the write attempt fails.</param>
    private void WriteDataToModule(string exceptionMessage)
    {
        int retriesLeft = 10;
        bool responseReceived = false;
    
        WriteDataToSPIBus();
        while (!responseReceived && (retriesLeft > 0))
        {
            //
            //  We have written the data to the module so wait for a maximum 
            //  of 5 milliseconds to see if the module responds with some 
            //  data for us.
            //
            responseReceived = _irqPortInterruptEvent.WaitOne(5, false);
            if ((responseReceived) && (_readFrameBuffer[1] == GO_BUS10_COMMAND_RESPONSE))
            {
                //
                //  Assume good result, it is up to the calling method to determine if
                //  the command has been executed correctly.
                //
                return;
            }
            else
            {
                //
                //  No response within the 5ms so lets make another attempt.
                //
                retriesLeft--;
                if (retriesLeft > 0)
                {
                    WriteDataToSPIBus();
                }
            }
        }
        throw new Exception(exceptionMessage);
    }
    

    By making this change we are also making the assumption that the signal back from the module (via the interrupt) is always indicating success. This is a decision which is appropriate for this module but may not be appropriate for other applications/modules.

    Add New Functionality

    Before adding new functionality it is necessary to remove the existing AddFive functionality from the BasicGoModule.

    Out OutputExpander module will provide the application with two basic functions:

    • Clear – clear the shift registers setting the output to 0
    • Set – Set the values in the shift registers to those specified by the parameters

    This functionality is provided by the following code:

    /// <summary>
    /// This method calls the ClearRegister method on the GO! module and then waits for the
    /// module to indicate that it has received and executed the command.
    /// </summary>
    public void Clear()
    {
        _writeFrameBuffer[0] = GO_BUS10_COMMAND_RESPONSE;
        _writeFrameBuffer[1] = CMD_CLEAR_REGISTERS;
        WriteDataToModule("Clear cannot communicate with the Output Expander module");
    }
    
    /// <summary>
    /// Set the shift registers using the values in the byte array.
    /// </summary>
    /// <param name="registers">Bytes containing the shift register values.</param>
    public void Set(byte[] registers)
    {
        if (registers.Length != 2)
        {
            throw new ArgumentException("registers: length should be 2 bytes");
        }
        _writeFrameBuffer[0] = GO_BUS10_COMMAND_RESPONSE;
        _writeFrameBuffer[1] = CMD_SET_REGISTERS;
        for (int index = 0; index < registers.Length; index++)
        {
            _writeFrameBuffer[2 + index] = registers[index];
        }
        WriteDataToModule("Clear cannot communicate with the Output Expander module");
    }
    

    Testing

    At this point we should be able to add some code the Main method of the application to test the module. We will perform something similar to the code in the previous post, we will move a single LED but this time we will illuminate the LED starting a position 15 and working down to 0. This should ensure that we have deployed new code to both the module and the Netduino Go! board.

    public static void Main()
    {
        OutputExpander output = new OutputExpander();
        int cycleCount = 0;
        byte[] registers = new byte[2];
        while (true)
        {
            Debug.Print("Cycle: " + ++cycleCount);
            for (int index = 15; index >= 0; index--)
            {
                output.Clear();
                if (index < 8)
                {
                    registers[0] = (byte) (1 << index);
                    registers[1] = 0;
                }
                else
                {
                    registers[0] = 0;
                    registers[1] = (byte) (1 << (index - 8));
                }
                output.Set(registers);
                Thread.Sleep(200);
            }
        }
    }
    

    The test breadboard and Netduino Go! were connected through the Komodex GoBus Breakout Module. This allows the Netduino Go! and the ST-Link/2 programmer to be connected to the breadboard:

    Output Expander Connected to Netdunio GO!

    Output Expander Connected to Netdunio GO!

    And here is a video of this working:

    You can just see the Netduino Go! in the bottom left corner of the video.

    Conclusion

    At this point the basic concept has be proven and the application can perform the following:

    1. STM8S code can control one or more LEDs
    2. STM8S can be controlled using SPI
    3. Netduino Go! can pass instructions to the STM8S

    One thing that did become apparent during this part of the process was that both the STM8S code and the Netduino code can be improved by improved grouping the functionality. For instance, in order to add the methods to the function table in the STM8S code I had to jump around the source code a little.

    The next step in the process is to look at the hardware and start to prepare for prototype PCB manufacture.

    Making a Netduino GO! Module

    Saturday, April 6th, 2013

    This series of posts will examine the activities required to take the concept of a module for the Netduino GO! through to production.

    Project Definition

    A simple project will allow the series of posts to concentrate on the principles required for the production of a Netduino GO! module without being too distracted by the functional aspects of the module. The following project definition should meet this brief:

    • Provide 16 or more digital outputs
    • Work with the Netduino GO!
    • Low cost manufacture
    • Use simple tried and tested components/techniques

    Meeting the Objectives

    As you can no doubt see, this is a reasonably simple project and with the exception of cost, we should have no major problems reaching the objectives. The most obvious solution to this problem is to look at using 74HC595 serial to parallel chips. These are cheap components and the techniques needed to solve this type of problem are tried and tested. The project definition looks like the counting example which is discussed in the Counting Using 74HC595 Shift Registers post with the addition of the Netduino Go! functionality.

    Project Plan

    Initial assessment of the project indicates that the following steps are required in order to take the project from concept to manufacture:

    1. Build a hardware prototype using the STM8S103F3 to control two shift registers. This will have some form of visual output to prove that we can control the digital lines (probably some LEDs)
    2. Write the software for the STM8S which will control the output of the 74HC595 chips
    3. Generate the schematic for the board
    4. Layout a prototype board and send to manufacture
    5. Write the software for the Netduino GO! while waiting for the manufactured boards to turn up
    6. Assemble a prototype on one of the prototype boards
    7. Conclusion

    The first post in the series will build the breadboard prototype and start to control the LEDs using the STM8S.

    STM32F4 Clocks

    Thursday, March 28th, 2013

    The STM32 contains several clocks each of which can be turned on or off when not used. In this post we will examine the clocks available and how they can be configured. To do this we will modify the simple GPIO example to change the clock parameters. Any changes to the system clock speed will increase or decrease the period of the delay. The results can be seen using an oscilloscope. We will look at the following topics:

    At the end of this post you should be able to configure the system clock and introduce a known delay subject to the tolerances of the system clocks.

    Clock Sources

    The STM32 Reference Manual (RM0090) states that there are five clocks available:

    • High Speed Internal (HSI) oscillator
    • High Speed External (HSE) oscillator
    • Phase Locked Loop (PLL)
    • Low Speed Internal (LSI) clock
    • Low Speed External (LSE) clock

    As already noted, each clock can be turned on/off as required. Turning an unused clock off reduces the power consumption of the microcontroller.

    The first three clocks are used to drive the system clock for the microcontroller. The final two are low speed clocks and are primarily used to drive the watchdogs.

    HSI

    After reset, the STM32 enables the HSI oscillator. This has a relatively low accuracy, only 1%, but is suitable for most applications. Using the HSI oscillator eliminates the need for an external clock in the final circuit design. On the STM32F4, the HSI oscillator has a clock speed of 16 MHz.

    HSE

    The STM32 can operate using an external clock circuit. It is possible to design an external clock to run with a greater accuracy than the internal HSI clock enabling finer control of the operating parameters of the final circuit. The exact specification of the external clock frequency varies but is typically 4-16 MHz.

    The STM32F4 Discovery Board has a built in external oscillator circuit fitted with a 8 MHz crystal.

    PLL

    The PLL is used to multiply it’s input clock source by a factor varying between 2 to 16. The input of the PLL is one of HSI, HSE or HSE/2.

    It is important to note that the configuration of the PLL cannot be changed once it has been enabled.

    LSI

    The LSI is a low power clock used for the watchdog timers.

    LSE

    The LSE is powered by an external 32.768 KHz clock. This provides a method of providing a low speed accurate clock for the real time clock.

    System and Peripheral Clocks

    Once the clock source has been selected it is necessary to configure the internal system and peripheral clocks. The internal clocks are:

    • System Clock
    • Advanced High Performance Bus (AHB)
    • Low speed Advanced Peripheral Bus (APB1)
    • High speed Advanced Peripheral Bus (APB2)

    Each of these clocks can be scaled using prescalers. A fuller picture of the types of clocks and their relationships can be found in the STM32 Reference Manual (RM0090).

    System Clock

    The system clock is used to determine the speed at which instructions are executed and has a maximum speed of 168MHz.

    Advanced High Performance Bus (AHB)

    Derived from the system clock, this bus has a maximum speed of 168MHz.

    Low speed Advanced Peripheral Bus (APB1)

    Derived from AHB, this bus has a maximum speed of 42MHz.

    High speed Advanced Peripheral Bus (APB2)

    Derived from AHB, this clock has a maximum frequency of 84MHz.

    Non-System Clock Peripherals

    A number of the peripheral clocks are not derived from the system clock but have their own independent source.

    USB OTG FS, Random Number Generator and SDIO Clock

    These clocks are all driven by an independent output of the PLL. The maximum speed for these peripherals is 48MHz.

    I2S

    The I2S peripherals have their own internal clock (PLLI2S). Alternatively, this can be derived by an independent external clock source.

    USB OTG HS and Ethernet Clock

    These clocks are derived from an external source.

    Microcontroller Clock Output

    The STM32 provides the ability to output up to two clocks to the external circuit using the Microcontroller Clock Output (MCO) pins. Both of the outputs can have a prescaler applied. This can be in the range 1 to 5 inclusive.

    Microcontroller Clock Output 1 (MCO1) is output on pin PA8. MCO1 output can be one of HSI, LSE, HSE or PLL scaled appropriately.

    Microcontroller Clock Output 2 (MCO2) is output on pin PC9. MCO2 output can be one of HSE, PLL, System Clock or PLLI2S scaled appropriately.

    The clock output is configured by selecting the appropriate alternative function for the GPIO port and is restricted to 100MHz.

    Configuring the Clock

    The number of features on the STM32F4 analysis and discussion of the registers and their function large. Luckily ST have come to the rescue and provided a configuration tool to help.

    ST Clock Configuration Tool in Wizard Mode

    ST Clock Configuration Tool in Wizard Mode

    This Excel spreadsheet can be run in both Expert and Wizard mode making it suitable for a wide range of users.

    ST Clock Configuration Tool in Expert Mode

    ST Clock Configuration Tool in Expert Mode

    The grey number in the above illustration have been calculated whilst the numbers in black can be changed by the users.

    The output from this spreadsheet is a source file (system_stm32f4xx.c) which can be added to your project. This file, system_stm32f4xx.c, contains three methods which can be called to setup the clocks on the microcontroller:

    • SystemInit – Setup the system including the clocks
    • SystemCoreClockUpdate – Setup the SystemCoreClock variable (clock frequency)
    • SetSysClock – Setup the system clock (called from SystemInit)

    We can see the effect of calling SystemInit by using the code from the simple GPIO example to the following:

    #include "stm32f4xx_rcc.h"
    #include "stm32f4xx_gpio.h"
    #include "system_stm32f4xx.h"
    
    int main()
    {
        //
        //  Uncomment this line to see the effect of
        //  the clock change.
        //
    	//SystemInit();
        //
        //  Initialise the peripheral clock.
        //
        RCC->AHB1ENR |= RCC_AHB1Periph_GPIOD;
        //
        //  Initialise the GPIO port.
        //
        GPIOD->MODER |= GPIO_Mode_OUT;
        GPIOD->OSPEEDR |= GPIO_Speed_100MHz;
        GPIOD->OTYPER |= GPIO_OType_PP;
        GPIOD->PUPDR |= GPIO_PuPd_NOPULL;
        //
        //  Toggle Port D, pin 0 indefinitely.
        //
        while (1)
        {
            GPIOD->BSRRL = GPIO_Pin_0;
            GPIOD->BSRRH = GPIO_Pin_0;
        }
    }
    

    If we run the code above with the SystemInit line commented out and hook an oscilloscope up to pin 0 of port D we get a square wave output with a frequency of about 1.5MHz.

    STM32F4 Output (1.46MHz)

    STM32F4 Output (1.46MHz)

    Now uncomment the SystemInit line of code and re-run the example. This time we see that the output signal has a frequency of nearly 4.9MHz.

    STM32F4 Output (5.75MHz)

    STM32F4 Output (5.75MHz)

    Turning the configuration tool into expert mode and tweaking a few of the parameters allows the frequency of the output signal to go to 8.77MHz.

    STM32F4 Output (8.77MHz)

    STM32F4 Output (8.77MHz)

    Timings are based upon the optimisation level being set to no optimisation. Turning the optimisation on to the maximum speed allows an output signal of nearly 20MHz to be generated.

    Conclusion

    The STM32 contains a variety of clock sources and configuration using the registers within the microcontroller would be a complex task. The Clock Configuration tool eases the configuration of the internal and peripheral clocks generating the source code for system_stm32f4xx.c automatically.

    The Clock Configuration tool and the associated guide can be downloaded from ST’s web site. The tool and document are in the following files:

    • stsm-stm32091 Clock Configuration Tool
    • AN3988 Clock Configuration Tool User Guide

    CooCox – ARM Development Environment For the Beginner

    Saturday, March 23rd, 2013

    A few weeks ago I published two articles on development environments for the STM32F4 Doscovery Board. Since then I have become aware of CooCox IDE. This is a small development environment for a number of Microcontrollers including some of the STM32 range of processors.

    The IDE promises to be free, unrestricted and simple offering the ability to develop high-quality software solutions in a timely and cost effective manner.

    Too good to be true?

    Let’s find out.

    Web Site

    I must admit, it took me a long time to take this tool seriously. I found the web site in the very early days in my search for a reasonable cost development environment for the STM32F4 Discovery board. The look and feel of the site left me a little cold. The design looks like it was put together in the early 1990s.

    My only hope was that the tools were better.

    Clicking through to the CoIDE page promised to show a video instead I found myself presented with a large amount of white space where the video should be. Maybe this works with IE or Firefox but not with Chrome. If you do see the white spave please take the time to scroll to the bottom of the page. There you will find tables detailing the supported chips/boards along with some download links.

    On the whole this web site left me feeling nervous and I must admit that the first time I came across this tool I dismissed it purely based upon the look and feel of the web site.

    So what made me come back, a comment made by a colleague, i.e. it worked and was simple to use.

    Software

    In order to use this IDE to develop applications for your board you also need to download the ARM GCC 4.7 toolchain. This is the same toolchain I used when setting us Eclipse to work with the STM32F4 Discovery board (see Setting up GCC for the STM32F4 Discovery Board). I was lucky enough to have this toolchain already installed making one less task to perform.

    Downloading the IDE is simple although you do need to register on the site.

    Installation was painless and the initial setup was also simple.

    I’m starting to get over the feeling of unease I experienced when I first visited the web site.

    Starting the IDE present you with a very familiar look and feel:

    New Project

    New Project

    It feels like Eclipse.

    Creating a Project

    Let’s see how good the environment is by taking the code from STM32 – Simple GPIO and Some Flashing LEDs post.

    Creating a new project is simple, just head over to the Project->New Project menu item. Doing this will present you with a wizard which will take you through the steps required to select your board and create an empty project.

    Some hints:

    • When creating a new project you need to untick the Use default path option if you want your code to be put anywhere other than under the installation directory.
    • The select board or chip does not have an option for the STM32F4 Discovery Board (or any for the Discovery boards for that matter). To use this board select Chip and then locate the STM32F407VG chip.

    Upon completion of the wizard you will be presented with the component selection tab in the IDE:

    Component Selection

    Component Selection

    This tab is really powerful and makes it easy for the new comer to this board to get off the ground. In the previous example I used two sets of definitions; Reset and clock control and GPIO. Ticking the RCC option in the component tab automatically adds the headers and source files needed to use the RCC library to the project. It also adds any dependencies, in this case the CMSIS core system startup files. After selecting the RCC and GPIO components the IDE looks as follows:

    Initial Component Selection

    Initial Component Selection

    Opening file explorer on the PC showed that the directory structure had been modified and the files put in place. So what happens if you untick and option? Removing components removes the files from the project and it also removes them from file store as well.

    Now this feature may seem simple but for the beginner it is really powerful. It ensures that all of the source and header files required are added to the project. This is something which whilst not difficult can trip up the beginner. It is also a little tedious to do with IAR and Eclipse.

    One downside of the component selection tab is that it does not easily allow you to remove the source code for the components you have added without also removing the header files as well. I am following the principle of The Way of the Register and not using the Standard Peripheral Library. This requires the header files but not the source code for the library itself. We can only hope the linker is smart enough to remove unused code from the final object executable.

    Building the project is as simple as clicking on the Build icon (or using the Project->Build menu item). A few seconds later I have the default applicaiton and the library files compiled.

    Debugging

    An IDE is really nothing without a reasonable debugger. I remember from the work I did setting up Eclipse (see Setting up GCC for the STM32F4 Discovery Board) that Eclipse needed the OpenOCD library in order to be able to debug an application using ST-Link. There is no mention of OpenOCD when using CooCox. The only additional software required for debugging appears to be the ST-Link USB driver. Again, I already have this installed but you may need to visit ST’s web site for the latest version.

    In order to debug we need some code so let’s borrow the code from the Simple GPIO example:

    #include "stm32f4xx_rcc.h"
    #include "stm32f4xx_gpio.h"
    
    int main()
    {
        //
        //  Initialise the peripheral clock.
        //
        RCC->AHB1ENR |= RCC_AHB1Periph_GPIOD;
        //
        //  Initialise the GPIO port.
        //
        GPIOD->MODER |= GPIO_Mode_OUT;
        GPIOD->OSPEEDR |= GPIO_Speed_25MHz;
        GPIOD->OTYPER |= GPIO_OType_PP;
        GPIOD->PUPDR |= GPIO_PuPd_NOPULL;
        //
        //  Toggle Port D, pin 0 indefinitely.
        //
        while (1)
        {
            GPIOD->BSRRL = GPIO_Pin_0;
            GPIOD->BSRRH = GPIO_Pin_0;
        }
    }
    

    Starting the debugger (Ctrl-F5) changes the IDE context and presents the debugging interface with the application stopped at the first line of code:

    CooCox debugging aspect

    CooCox debugging aspect

    Warning – the above image is large

    Pressing F5 runs the application to the next breakpoint. As I have not set any breakpoints this should run the application indefinitely and indeed it does. Hooking up the scope to pin 0 of port D shows the following output:

    Scope output

    Scope output

    Single stepping is achieved using F10 and F11. So re-running the application and pressing F10 should single step over the current line of code and indeed it does. The registers window also highlights the ARM registers that were changed by executing the last instruction:

    Register View

    Register View

    One thing that I have found missing which I really appreciate with IAR is the ability to view the state of the peripheral registers (as opposed to the microcontroller registers). This is a really useful feature as it means you do not have to locate the registers in memory and decode them yourself.

    Conclusion

    CooCox IDE is a simple way to get into working with the STM32F4 Discovery board. The power and simplicity of the tool is only let down by the dated look of the web site.

    A cracking tool; well worth looking at.

    STM32 – Simple GPIO and Some Flashing LEDs

    Saturday, March 23rd, 2013

    When starting with a new development board I always revisit the fundamentals like GPIO. Doing this helps establish that the development tools are working and gives a basic library for future development. So with this post we will be looking at GPIO on the STM32 Discovery board. When Rediscovering the STM32 Discovery Board I mentioned that I would need to look at using either the standard peripheral library provided by ST or to use a lower level method of controlling the board. After due consideration I have decided to continue with the lower level access. Whilst this may be more effort it does lead to a better understanding of what is actually happening at the low level.

    Our objective today will be to toggle a GPIO pin (Port D, pin 0) generating a square wave. The result will be something similar to the Simple GPIO post for the STM8S.

    STM32F4 Discovery Board

    The STM32F4 Discovery board is a low cost development board for hobbyists, beginners and experienced users. The board uses the STM32F407VGT6 and hosts a number of sensors including digital accelerometer, push buttons, microphone and DAC. It also contains four built in LEDs which can be used to give feedback to the developer and breakout pins for the GPIO ports.

    STM32F4 Discovery Board

    STM32F4 Discovery Board

    Each of the GPIO pins can be used for simple input/output of digital signals. The majority of the pins are also mapped to one or more alternative functions. For instance, Port C, pin 3 is also mapped to the following alternative functions:

    • SPI2 MOSI
    • I2S2 SD
    • OTG HS ULPI NXT
    • ETH MI TX Clk
    • EVENTOUT

    For the remainder of this post we will restrict ourselves to the GPIO functionality of the chip and demonstrate the following:

    • Output a digital signal on a single GPIO pin
    • Flash one of the LEDs on the board

    The alternative functionality will be considered in future posts.

    The functionality of the 16 pins on each of the GPIO ports is controlled by a number of registers. The description of each of the registers can be found in RM0090 Reference Manual for the STM32 chip. This manual can be downloaded from STs web site.

    GPIO Registers

    Each STM32 chip has a number of ports each of which has 16 pins. As already noted, each of these pins has a number of functions, the most basic of which is digital input/output. The functionality and state of each port is controlled by a number of GPIO registers:

    • Four configuration registers
    • Two data registers
    • One set/reset register
    • One locking register
    • Two alternative function registers

    An overview of the registers follows; a fuller description of the registers can be found in section 7 of RM0090 Reference Manual (Revision 4).

    When referring to the registers, the reference manual uses the following notation:

    GPIOx_Function

    Where x is replaced by the port to be used. For instance, GPIOx_MODER refers to the generic mode register for a GPIO port. A specific instance of this would be GPIOD_MODER. This refers to the mode register for port D. Normally, x is in the range A to I and is defined by the specific version of the STM32 being used in the project.

    Configuration Registers

    The STM32 has four configuration registers for each of the ports.

    • Port mode register – GPIOx_MODER
    • Output type register – GPIOx_OTYPER
    • Speed register – GPIOx_OSPEEDR
    • Pull-up/Pull-down register – GPIOx_PUPDR

    Each of these registers is 32-bits wide although not all of the bits are used in all of the registers.

    Port Mode Register – GPIOx_MODER

    This 32 bit register holds 2 bit values which defines the operation mode. The modes allowed are:

    Bit ValuesDescription
    00Input
    01General purpose output
    10Alternate function
    11Analog

    In general, the default reset value for this register is 0. Some of the ports are reset to non-zero values as the pins in the port have special meanings (debugging pins etc). The rest values are:

    PortReset Value
    A0xA800 0000
    B0x0000 0280
    All others0x0000 0000

    The bits in the register are read/write and are in consecutive pairs. So bits 0 & 1 define the mode for pin 0, bits 2 & 3 define the mode for pin 1 etc.

    Output Type Register – GPIOx_OTYPER

    This is a 32-bit register but only the lower 16 bits are used. The top 16 bits are reserved and should not be used. This register uses a single bit for each pin to define the output type of the pins in the port. So, bit 0 defines the output type for pin 0, bit 1 for pin 1 etc.

    Bit ValueDescription
    0Push/pull output
    1Open drain output

    The default reset value for all of the GPIOx_TYPER registers is 0x0000 0000 meaning that all ports are configured for push/pull output.

    Speed Register – GPIOx_OSPEEDR

    This 32-bit register uses all of the bits in the register in pairs (similar to the port mode register). The bits define the output speed of the port. The bit pairs have the following meaning:

    Bit ValuesDescription
    002 MHz Low speed
    0125 MHz Medium speed
    1050 MHz Fast speed
    11100 MHz High speed on 30pF
    80 MHz High speed on 15 pF

    The reset value for these registers is 0x0000 00C0 for port B and 0x0000 0000 for all other registers.

    Pull-up/Pull-down register – GPIOx_PUPDR

    This 32-bit register uses all of the bits in the register in pairs (similar to the port mode register). The bits define pull-up / pull-down resistor mode for the pins on a port. The bit pairs have the following meaning:

    Bit ValuesDescription
    00No pull-up or pull-down resistor
    01Pull-up resistor
    10Pull-down resistor
    11Reserved

    The reset values for the registers are:

    PortReset Value
    A0x6400 0000
    B0x0000 0100
    All others0x0000 0000

    Data Registers

    The two data registers for each port indicate the input/output state of the port. Each of the registers are 32-bit registers but only the lower 16 bits are used. The top 16 bits are reserved and should not be used.

    • Input data register – GPIOx_IDR
    • Output data register – GPIOx_ODR

    Input data register – GPIOx_IDR

    The input data register indicates if a high or low signal has been applied to the pin within a port. The register is read-only and the whole word should be read.

    Bit ValueDescription
    0High logic value
    1Low logic value

    As with the output type register – GPIOx_OTYPER, the bits in the register map onto the pins in the port (bit 0 maps to pin 0, bit 1 to pin 1 etc.).

    The reset value for all of these registers is 0x0000 XXXX where X indicates that the bits are unknown as they will be defined by the input signals applied to the pins are reset.

    Output data register – GPIOx_ODR

    The output data register allows the program to change the output state of a pin within the port. This is a 32-bit register and only the lower 16 bits are used. The top 16 bits are reserved and should not be used. The output states are defined as:

    Bit ValueDescription
    0High logic value
    1Low logic value

    As with the output type register – GPIOx_OTYPER, the bits in the register map onto the pins in the port (bit 0 maps to pin 0, bit 1 to pin 1 etc.). The bits in the lower 16 bits of the register are all read/write bits.

    The reset value for all of these registers is 0x0000 0000.

    A more effective way of setting/resetting a bit in the output register is to use the bit set/reset register.

    Set/reset register

    The set/reset register sets or resets a single bit in the output data register.

    Bit Set/Reset Register – GPIOx_BSSR

    This is a 32-bit register and it is split into two halves, the lower 16 bits are used for setting a bit and the upper 16 bits are used for resetting a bit. This is a write only register; reading this register will return 0x0000.

    Setting a bit in the lower 16-bits of this register will cause the corresponding bit in the output data register to be set to 1.

    Similarly, setting a bit in the upper 16-bits of this register will cause the corresponding bit in the output data register to be set to 0.

    For the lower 16-bits the mapping is simple, bit 0 in GPIOx_BSRR maps to bit 0 in GPIOx_ODR etc. For the upper 16-bits, bit 16 of the GPIOx_BSRR maps to bit 0 of the GPIOx_ODR; bit 17 of GPIOx_BSRR maps to bit 1 of GPIOx_ODR etc.

    So why provide the set/reset functionality when you have the output data registers? The set/reset register provide an atomic method of setting or resetting an output pin on a port. When using the output data registers, the compiler will have to generate a number of statements in order to set or reset a pin. This can allow an interrupt to be processed when part way through the set/reset operation. By using this register it is possible to set or reset a pin using a single instruction. This means that the operation will complete before the interrupt can be processed.

    Configuration Lock Register

    This register is used to lock the configuration of the port until the next reset of the chip.

    Configuration Lock Register – GPIOx_LCKR

    The register is a 32-bit register but only 17 bits are actually used. The lower 16 bits indicate which bit of the port configuration is locked. So setting bit 0 of the register will lock the configuration of pin 0 etc.

    The final bit used is bit 16 in the register (known as the Lock Key – LCKK); this bit determines the lock status of the port; a zero indicates that no lock is applied whilst a 1 indicates that the port configuration is locked.

    In order to lock the configuration of a port the configuration lock write sequence must be followed. This will prevent accidental locking of the port configuration. The algorithm for locking the configuration is as follows:

    • Set bits 0 through 15 of the register indicating which pins should have their configuration locked
    • Set LCKK to 1 and write the value into the register
    • Set LCKK to 0 and write the value into the register
    • Set LCKK to 1 and write the value into the register
    • Read the lock bit of the port

    It is important to note that the values in bits 0 through 15 should not change whilst following the above sequence. Should they change or any error occur then the lock will be aborted.

    The final step, reading the lock bit, confirms the success or failure of the operation.

    Alternative function registers

    The alternative function registers allow the configuration of the port to change from simple GPIO to an alternative function such as SPI MOSI. These registers are noted here but will not be discussed further as they will be covered in subsequent posts.

    C Definitions and Some Typedefs

    The register in the STM32 microcontroller have been mapped onto specific memory locations within the valid address space of the STM32. These memory locations are defined in the various header files for the microcontroller. For instance, the following type definition has been taken from the header file stm32f4xx.h:

    typedef struct
    {
      __IO uint32_t MODER;    /*!> GPIO port mode register,               Address offset: 0x00      */
      __IO uint32_t OTYPER;   /*!> GPIO port output type register,        Address offset: 0x04      */
      __IO uint32_t OSPEEDR;  /*!> GPIO port output speed register,       Address offset: 0x08      */
      __IO uint32_t PUPDR;    /*!> GPIO port pull-up/pull-down register,  Address offset: 0x0C      */
      __IO uint32_t IDR;      /*!> GPIO port input data register,         Address offset: 0x10      */
      __IO uint32_t ODR;      /*!> GPIO port output data register,        Address offset: 0x14      */
      __IO uint16_t BSRRL;    /*!> GPIO port bit set/reset low register,  Address offset: 0x18      */
      __IO uint16_t BSRRH;    /*!> GPIO port bit set/reset high register, Address offset: 0x1A      */
      __IO uint32_t LCKR;     /*!> GPIO port configuration lock register, Address offset: 0x1C      */
      __IO uint32_t AFR[2];   /*!> GPIO alternate function registers,     Address offset: 0x20-0x24 */
    } GPIO_TypeDef;
    

    This header file can be found in the Standard Peripheral Library as supplied by ST Microelectronics.

    A careful examination of the members of the struct within the typedef reveals that with one exception, the members of the struct all map directly onto the registers we have been discussing above. The one exception is the BSSR register. This has been split into two components BSSRL and BSSRH. This split nicely maps to the difference in functionality of the two halves of the register, namely Setting and resetting of individual bits in the output data register.

    Locating A GPIO in Memory

    Once we have the layout of the registers (as defined in the struct above), we simply need to map the structure onto the right location in memory. A little further digging in the header file leads us to the following #define statements:

    #define GPIOD             ((GPIO_TypeDef *) GPIOD_BASE)
    
    #define GPIOD_BASE        AHB1PERIPH_BASE + 0x0C00)
    
    #define APB1PERIPH_BASE   PERIPH_BASE
    
    #define PERIPH_BASE       ((uint32_t) 0x40000000) /*!< Peripheral base address in the alias region                                */
    

    Following the chain of #define statements leads us to the the conclusion that the registers for GPIOD are located at memory location 0x40000C000. These definitions mean that we should be able to access individual registers with statements such as:

    GPIOD->MODER = 0x01;    // Set Pin 0 of Port D to input.
    

    A Practical Demonstration

    After all this theory we must be ready for some coding. In this section we will look at creating two small applications:

    • GPIO Toggle – toggling a single pin on a GPIO port
    • Blinky – Flashing a single LED

    The first of the two applications will simply toggle a single GPIO pin as fast as possible using the default reset state of the microcontroller. Note that an oscilloscope will be required in order to prove that the application is working correctly

    The second application will make use of the on board LEDs. This will require a little more coding in order to provide a delay between turning the LED on and off in order to make the flashing visible to the naked eye.

    Application 1 – Toggling A GPIO Pin

    This application is simple and consists of two parts:

    • Initialisation
    • A loop which toggles the GPIO pin

    The full application looks like this:

    #include "stm32f4xx_rcc.h"
    #include "stm32f4xx_gpio.h"
    
    int main()
    {
        //
        //  Initialise the peripheral clock.
        //
        RCC->AHB1ENR |= RCC_AHB1Periph_GPIOD;
        //
        //  Initilaise the GPIO port.
        //
        GPIOD->MODER |= GPIO_Mode_OUT;
        GPIOD->OSPEEDR |= GPIO_Speed_25MHz;
        GPIOD->OTYPER |= GPIO_OType_PP;
        GPIOD->PUPDR |= GPIO_PuPd_NOPULL;
        //
        //  Toggle Port D, pin 0 indefinitely.
        //
        while (1)
        {
            GPIOD->BSRRL = GPIO_Pin_0;
            GPIOD->BSRRH = GPIO_Pin_0;
        }
    }
    

    One thing to note from the above code is that we need to initialise the peripheral clocks (this should be taken as read for the moment and will be covered in future posts). When initialising the GPIO port we should take into consideration the default clock speed of the Discovery board after reset. By default this is 8 MHz and so we should set the speed of the output port accordingly. This leads to a configuration for pin 0 of output with a maximum speed of 25 MHz, push pull with not pull-up or pull-down resistors.

    Once initialised we enter the main program loop. Here the application uses the set/rest registers to toggle pin 0. This shows how the 32-bit register is split into two, one for the set and one for the reset operation.

    If we create a simple STM32 project using IAR, compile and then deploy this application we get the following output on the oscilloscope:

    STM32 Scope Output

    STM32 Scope Output

    And there we have it, our first application deployed to the STM32 Discovery board.

    Blinky – Flashing A Single LED

    This second example is really aimed at those who do not have access to an oscilloscope. Here we will slow down the output of the GPIO port and flash one of the built in LEDs.

    The STM32F4 Discovery board has four built in LEDs which can be accessed by setting/resetting pin 12 through 15 on port D. The LED colours are:

    Pin NumberColour
    12Green
    13Orange
    14Red
    5Blue

    Using the code in the previous example as a starting point we find ourselves with an application which looks something like this:

    #include "stm32f4xx.h"
    #include "stm32f4xx_gpio.h"
    #include "stm32f4xx_rcc.h"
    
    #define LED_GREEN      12
    #define LED_ORANGE     13
    #define LED_RED        14
    #define LED_BLUE       15
    
    int main()
    {
        int pin = LED_RED;
        uint32_t mode = GPIO_Mode_OUT << (pin * 2);
        uint32_t speed = GPIO_Speed_100MHz << (pin * 2);
        uint32_t type = GPIO_OType_PP << pin;
        uint32_t pullup = GPIO_PuPd_NOPULL << (pin * 2);
        //
        //  Initialise the peripheral clock.
        //
        RCC->AHB1ENR |= RCC_AHB1Periph_GPIOD;
        //
        //  Initilaise the GPIO port.
        //
        GPIOD->MODER |= mode;
        GPIOD->OSPEEDR |= speed;
        GPIOD->OTYPER |= type;
        GPIOD->PUPDR |= pullup;
        //
        //  Toggle the selected LED indefinitely.
        //
        int index;
        while (1)
        {
            GPIOD->BSRRL = (1 << pin);
            for (index = 0; index < 500000; index++);
            GPIOD->BSRRH = (1 << pin);
            for (index = 0; index < 500000; index++);
        }
    }
    

    Deploying this application should flash the selected LED just below the STM32 microcontroller on the STM32F4 Discovery board.

    Conclusion

    This post presented two simple applications which toggle GPIO lines on Port D. Using these techniques and the additional information in the register descriptions you should be able to extend the application above to control digital devices such as shift registers etc.

    Setting up GCC for the STM32F4 Discovery Board

    Friday, March 8th, 2013

    A few days ago I wrote this post about the STM32 Discovery board and my experiences setting this board up with the IAR Embedded Workbench Kickstarter for ARM. In that post I mentioned that there are some free development tools available for this board, namely the GCC tool chain. I was going to leave these tools until I reached the point where I needed to remove the code size restriction which is in place for the IAR toolset.

    Well I could not resist investigating this tool chain further.

    Installing the Software

    A quick visit to Google lead me to Hussam Al-Hertani’s blog where there are a number of articles which discuss setting up the GCC tool chain for the STM32F0 Discovery board. These three articles provide a comprehensive overview of the steps you need to follow:

    Also included on the blog is an overview of the GCC compilation process.

    The two boards (STM32F0 and STM32F4) should be similar and so I decided to give the above a go and see if I could use the GCC tools with the STM32F4 Discovery board.

    Installing the Tools

    The installation process went reasonably well with only a couple of issues.

    Part 1 – Setting up the GCC ARM Toolchain

    The installation of the tools went according to the blog until we reached the instructions to compile the sample application. The main problem here was that the application would not compile due to missing header files. This problem was caused by the differences in the directory names and structure of the firmware libraries. The only changes required were to the include and library variables in the makefile.

    Part 2 – Setting up the Eclipse IDE

    Setting up Eclipse was completed without any issues.

    Part 3 – Setting up Debugging with the Eclipse IDE (OpenOCD 0.6.x)

    Setting up OpenOCD and connecting this to Eclipse was also straightforward.

    Creating A New Example

    Remember this code:

    GPIO_InitTypeDef  GPIO_InitStructure;
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
    int flag = 0;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
    while (1)
    {
        if (flag)
        {
            GPIO_SetBits(GPIOD, GPIO_Pin_0);
            flag = 0;
        }
        else
        {
            GPIO_ResetBits(GPIOD, GPIO_Pin_0);
            flag = 1;
        }
    }
    

    In order to generate a new example we start with the code we have compiled and working. There are very few changes required. Theses are main made in the make file. We remove the files which are not required and then verify that the libraries and include files can be accessed by the compiler.

    The final change is to replace the code in main.c with our code above.

    Compilation and deployment from within Eclipse went as expected and the application ran with no issues.

    How About Debugging?

    With Eclipse open and the above project loaded I set a breakpoint on the first line of the application. Starting the debugger stopped the application at the first line of code – things are looking good. Single stepping also appeared to look as though it was working well at first. A few lines further on and this is where the issues started. The debugger and the line of source code started to get out of step. The IDE would skip a line of code in a consistent manner. It looks like the debugger information is slightly out of sync with the breakpoints. After spending a little time looking at this I found that the original makefile I have been using had the optimisation level set to -Os. The debugger/IDE started to behave as expected when I changed this to -O0.

    Conclusion

    The installation of the GCC development environment was simple enough and the instructions on Hertaville are comprehensive and well worth visiting. It is always good to have a free unlimited development environment.

    Change Log:

    • 10th March 2013: Added additional information about the optimisation flag in the build file.

    Rediscovering the STM32 Discovery Board

    Tuesday, March 5th, 2013

    About a year ago I started to look at alternatives to the Netduino boards and came across the STM32 Discovery board. I spent a little time with this board and wrote a simple application which toggled a GPIO pin – the electronic equivalent of Hello, world. I have had very little time to spend with this board since then but now I feel it is time to revisit the STM32 having spent some time cutting my teeth on the STM8S.

    Development Tools

    I’m a hobbyist and this means I do not have a vast amount of money to spend on development tools and equipment. A quick survey of the market gives a few options for development tools (software). The prices put the majority if these out of the question for the home developer who does not intend to recover the costs. There are still a number of options open to us by using the restricted versions of the professional tools. Several of the major players have released limited editions of the full development suite. The normal seems to be restricting the amount of code the development environment can deal with before you are required to purchase the software. I have had a look at the following tools (presented in no particular order) over the past few days:

    • Atollic TRUEStudio
      Free Lite edition with a code restriction of 32K on the Cortex-M4
    • IAR Embedded Workbench
      Free kick starter edition available with a code limit of 32K
    • Keil MDK
      No free version seems to be available and the site has a Quote button but no pricing.
    • GNU C/C++ with Eclipse IDE
      Free with no code restriction
    • TASKING
      No free edition available

    A 32K code restriction does not seem unreasonable for the hobbyist so I decided to start with the IAR Kickstarter edition as I had a really good experience with the STM8S Kickstarter edition of the same development environment. I suppose the major driver was the fact that I will not have to learn a whole new series of key strokes in order to compile/debug as the IDE is the same as the STM8S version of the software which I have been using for nearly a year now.

    Installation

    Installation of the development environment was simple. The setup weighs in at a hefty 913 MBytes. Running the setup was painless and took only a few minutes.

    Testing the installation

    To test the deployment I decided to compile one of ST’s own example applications. These can be found in the firmware package which can be downloaded from ST’s web site. At the time of writing the latest version of the firmware was version 1.1.0. When you unzip the firmware you will find a Project directory which contains a number of samples including a Demonstration example. If you open this directory you will find a number of sub directories containing the projects for the various development tools available. We are interested in the EWARM directory as this contains the IAR project.

    Opening the workspace STM32F4-Discovery_Demo.eww, compiling and deploying the application was simple. Just make sure that you have the STM32 Discovery board plugged into your computer using a mini USB connector through CN1 on the board.

    Once deployed the IDE will halt program execution just before the main method is called. Pressing F5 will start the application running. At this point you should see the LEDs on the main board light up in a chase style pattern.

    Template Application

    The demonstration example shows how to use many of the development board features including the sensors, sound generation and the USB capabilities. The application therefore contains a number of features which we will/may not be using in our applications. I decided to strip the code down to a very basic application which can be used as a starting point for future application development. In order to prove that the template work and that we have not removed too much code we will recreate the previous application which toggled a GPIO pin.

    There is a certain amount of startup code required in order to configure the STM32 and put it into a state where is can run an application. The code for this appears to be in the following files within the project:

    • startup_stm32f4xx.s
    • stm32f4xx_it.c
    • system_stm32f4xx.c

    The code in these file set up the interrupt tables and system clocks before passing control the main.

    In order to ensure that I took as much of the configuration as possible over from the demonstration program I started with a copy of the contents of the entire directory and then started to remove files. Doing this would ensure that the project options were preserved.

    To see some output we will need to add some code to output a signal on the scope. This application will toggle pin 0 on port D in a loop. The main program becomes:

    GPIO_InitTypeDef  GPIO_InitStructure;
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
    int flag = 0;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOD, &amp;GPIO_InitStructure);
    while (1)
    {
        if (flag)
        {
            GPIO_SetBits(GPIOD, GPIO_Pin_0);
            flag = 0;
        }
        else
        {
            GPIO_ResetBits(GPIOD, GPIO_Pin_0);
            flag = 1;
        }
    }
    

    In order to use the GPIO pins we need to compile in the GPIO standard library. Specifically stm32f4xx_gpio.c and stm32f4xx_rcc.c. These are probably better added as a group so we add a group and then the files. This will leave the project structure looking something like the following:

    ProjectStructureInIAR

    Compiling the application gave a missing method/preprocessor directive, namely assert_param. I have come across this in the past. This method validates the parameters passed into the methods in the standard library methods. A quick addition of the following to main.h should make the code compile:

    void assert_param(void *x) {}
    

    Compile this and we get a whole lot of errors but at least it compiles. Strictly speaking this needs resolving but I still have to decide if long term I will be using the standard library or if I will be following another path. I remember getting burned by the STM8S version of the library. A decision for another day, for now I’ll continue with the template and the test application.

    Saving all of this and then running the program with the scope hooked up to Port D, Pin 0 gives the following output on the scope:

    STM32GPIOToggleUsingSTDLibrary

    My only concern was the frequency of the output. The processor is supposed to be running at 168 MHz. I would have expected something higher than the 417 Khz I was getting.

    A quick delve into the standard library and we find that the code which sets and resets the GPIO stat is actually simple. There are the mandatory calls to the assert_param method/preprocessor directive followed by a simple setting of a value. We can substitute the calls in the main loop with the actual code. The main loop now looks something like this:

    while (1)
    {
        if (flag)
        {
            GPIOD->BSRRL = GPIO_Pin_0;
            flag = 0;
        }
        else
        {
            GPIOD->BSRRH = GPIO_Pin_0;
            flag = 1;
        }
    }
    

    Deploying and running this application gives a lot more respectable output:

    STM32GPIOToggle

    As you can see, we are getting a little over 4.1 MHz.

    Conclusion

    I now have a small template STM32 project which I can call upon at any time to give me a starting point for development with the STM32 Discovery board. I still need to work on the assert_param issue but only if I am to carry on working with the standard library.

    If you are interested in using this template then feel free to download the code. You may need to make some adjustments to the default paths for the include directories. To do this:

    • Right click on the project name (Test STM32 – Debug)
    • Select Options…
    • Now select C/C++ Compiler
    • Scroll to the right until you find the Preprocessor tab
    • Enter the paths for your include directories

    A new year, a new journey. Let’s see where this takes us.

    NETMF Timers

    Sunday, January 6th, 2013

    A few days ago in the Netduino chat room we were discussing a problem with the Timer class. Should be a simple problem to solve as I had used timers in .NET applications many times. A short while later it became obvious that the Timer class was not as easy to use as I thought. In this post we will look at the NETMF implementation of the Timer class and how it can be used.

    In all of the examples below I will be working on a 50% duty cycle. So a 100 Hertz signal should be 10ms between the rising edges of the signal where the signal will be high for 5ms followed by low for 5ms.

    All of the following examples will run on the Netduino Plus 2.

    Setting up a Simple Timer

    The basic timer constructor takes four parameters:

    • Callback
    • User defined object
    • Delay
    • Period

    Callback

    The Callback parameter is a TimerCallback object. This will be called by the Timer at the period defined by the period parameter.

    User defined object

    This is an object defined by the user and can be used to identify the source of the callback. Initially we will be setting this to null as we will not be using it.

    Delay

    The number of milliseconds to pause before the callback method is called.

    Period

    Period (in milliseconds) between invocations of the Callback method.

    So now we know how this should work, let’s jump in with a simple example. Here we will generate a 100Hz signal and we will start the timer immediately. The code for this will look like this:

    using System;
    using System.Threading;
    using Microsoft.SPOT.Hardware;
    using SecretLabs.NETMF.Hardware.Netduino;
    
    namespace BasicTimer
    {
        public class Program
        {
            private static Timer oneHundredHertzTimer = null;
            private static OutputPort oneHundredHertzPulse = null;
            private static TimerCallback timerCallback = null;
            private static OutputPort trigger = null;
    
            public static void Main()
            {
                trigger = new OutputPort(Pins.GPIO_PIN_D1, false);
                timerCallback = new TimerCallback(TimerInterrupt);
                oneHundredHertzPulse = new OutputPort(Pins.GPIO_PIN_D7, false);
                trigger.Write(true);
                trigger.Write(false);
                oneHundredHertzTimer = new Timer(timerCallback, null, 0, 5);
                Thread.Sleep(Timeout.Infinite);
            }
    
            private static void TimerInterrupt(object state)
            {
                oneHundredHertzPulse.Write(!oneHundredHertzPulse.Read());
            }
        }
    }
    

    The trigger pin is simply used to indicate the start of the program run. This is used to allow the logic analyser to start data capture.

    If we hook up the logic analyser we should get a trace which looks something like the following:

    Basic Timer

    Basic Timer

    The top trace shows the trigger pulse whilst the trace below shows the output from the timer callback. If we expand the start of the trace we see the following:

    Timer with trigger

    Timer with trigger

    As you can see, there is a small pulse (the trigger) at the start followed by the pulses generated by the timer. The timer between the falling edge of the trigger and the rising edge of the first pulse generated by the timer is approximately 16us. This can be put down to the amount of time it takes for the NETMF instructions to complete the construction of the timer. So the first thing the timer does is to invoke the callback method defined in the constructor.

    If we modify the construction of the timer slightly we can see the impact of the delay parameter. Let’s change the construction to the following:

    oneHundredHertzTimer = new Timer(timerCallback, null, 50, 5);
    

    If we run this application (see the project BasicTimerWithDelay) we will see the following in the logic analyser:

    BasicTimer50msDelay

    As you can see, the start of the timer has been delayed by 50ms.

    Two Timers, One Interrupt

    In this example we will look at the role the user defined object has in the TimerCallback parameter. This object can be used to allow the system to use a single callback from multiple timers. The object can be used to determine which timer invoked the callback.

    The user defined object is an instance of an object which is passed to the callback method when it is called. In the following we start with an enum:

    private enum TimerState { OneHertz, TwoHertz };
    

    Now when we create the timers we create a new object and pass this into the constructor. Our constructors look like the following:

    TimerState oneHertzState = TimerState.OneHertz;
    oneHertzTimer = new Timer(timerCallback, oneHertzState, 0, 500);
    
    for the one hertz timer and:

    TimerState twoHertzState = TimerState.TwoHertz;
    twoHertzTimer = new Timer(timerCallback, twoHertzState, 0, 250);
    

    for the two hertz timer.

    As you can see, both timers have the same method being invoked as the callback method. However, each timer will pass in a different object (albeit of the same type) to the callback method. We can then use this parameter to determine the action we should take. The code for the callback method will look like the following:

    private static void TimerInterrupt(object state)
    {
    	switch ((TimerState) state)
    	{
    		case TimerState.OneHertz:
    			oneHertzPulse.Write(!oneHertzPulse.Read());
    			break;
    		case TimerState.TwoHertz:
    			twoHertzPulse.Write(!twoHertzPulse.Read());
    			break;
    	}
    }
    

    The full application is as follows:

    using System;
    using System.Threading;
    using Microsoft.SPOT.Hardware;
    using SecretLabs.NETMF.Hardware.Netduino;
    
    namespace TimerExample
    {
        public class Program
        {
            private static Timer oneHertzTimer = null;
            private static OutputPort oneHertzPulse = null;
    
            private static Timer twoHertzTimer = null;
            private static OutputPort twoHertzPulse = null;
            
            private static TimerCallback timerCallback = null;
    
            private enum TimerState { OneHertz, TwoHertz };
    
            private static OutputPort trigger = null;
    
            public static void Main()
            {
                trigger = new OutputPort(Pins.GPIO_PIN_D1, false);
                timerCallback = new TimerCallback(TimerInterrupt);
                trigger.Write(true);
                trigger.Write(false);
                //
                //  Set up the one hertz timer.
                //
                oneHertzPulse = new OutputPort(Pins.GPIO_PIN_D7, false);
                TimerState oneHertzState = TimerState.OneHertz;
                oneHertzTimer = new Timer(timerCallback, oneHertzState, 0, 500);
                //
                //  Set up the two hertz timer.
                //
                twoHertzPulse = new OutputPort(Pins.GPIO_PIN_D6, false);
                TimerState twoHertzState = TimerState.TwoHertz;
                twoHertzTimer = new Timer(timerCallback, twoHertzState, 0, 250);
                //
                Thread.Sleep(Timeout.Infinite);
            }
    
            private static void TimerInterrupt(object state)
            {
                switch ((TimerState) state)
                {
                    case TimerState.OneHertz:
                        oneHertzPulse.Write(!oneHertzPulse.Read());
                        break;
                    case TimerState.TwoHertz:
                        twoHertzPulse.Write(!twoHertzPulse.Read());
                        break;
                }
            }
        }
    }
    

    If we run this application we will see the following on the logic analyser:

    Two timers with one interrupt.

    Two timers with one interrupt.

    As you can see, we are generating a one and a two hertz signal using a single callback.

    Stopping A Timer

    So far we have considered starting a timer and the various options for delaying and callbacks. There will come a point where we will want to stop a timer from executing. A quick glance through the methods provided for the Timer class reveals that there is no method do do this. In this scenario, the first instinct is to simply set the variable referencing to the object to null.

    So if we take the first example as out starting point we will add a small amount of code to deal with a button press. The idea is that when the user presses the onboard button on the Netduino Plus 2, the application will terminate the timer by setting to timer object to null. The code becomes:

    using System.Threading;
    using Microsoft.SPOT.Hardware;
    using SecretLabs.NETMF.Hardware.Netduino;
    using Microsoft.SPOT;
    
    namespace StoppingATimer
    {
        public class Program
        {
            private static Timer oneHundredHertzTimer = null;
            private static OutputPort oneHundredHertzPulse = null;
            private static TimerCallback timerCallback = null;
            private static InterruptPort button = null;
    
            public static void Main()
            {
                timerCallback = new TimerCallback(TimerInterrupt);
                oneHundredHertzPulse = new OutputPort(Pins.GPIO_PIN_D7, false);
                button = new InterruptPort(Pins.ONBOARD_BTN, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeHigh);
                button.OnInterrupt += new NativeEventHandler(button_OnInterrupt);
                oneHundredHertzTimer = new Timer(timerCallback, null, 0, 5);
                Thread.Sleep(Timeout.Infinite);
            }
    
            private static void button_OnInterrupt(uint data1, uint data2, System.DateTime time)
            {
                oneHundredHertzTimer = null;
                Debug.Print("Timer set to null.");
            }
    
            private static void TimerInterrupt(object state)
            {
                oneHundredHertzPulse.Write(!oneHundredHertzPulse.Read());
            }
        }
    }
    

    If you deploy this application to the Netduino Plus 2 you will see the same output (on the logic analyser) as the first example in this post. Namely, a 100Hz square wave with a 50% duty cycle.

    So the next thing to try is pressing the button and see what happens. If everything works as expected then the timer should be set to null and the timer should terminate. So let’s press the button and start the logic analyser.

    And the timer keeps on running. In order to kill the timer we must ensure that it is disposed of correctly. We can do this by modifying the button interrupt method as follows:

    private static void button_OnInterrupt(uint data1, uint data2, System.DateTime time)
    {
    	oneHundredHertzTimer.Dispose();
    	oneHundredHertzTimer = null;
    	Debug.Print("Timer set to null.");
    }
    

    Running the application again and pressing the button results in the expected behaviour.

    Changing the Frequency

    In our final example we will look at changing the frequency of the timer. This example uses the button press interrupt from the previous example but this time it will halve the period (i.e. double the frequency of the output signal) of the timer. The application uses the Change method to change the timer on the fly. So let’s dive straight in with some code:

    using System.Threading;
    using Microsoft.SPOT.Hardware;
    using SecretLabs.NETMF.Hardware.Netduino;
    using Microsoft.SPOT;
    
    namespace ChangingTheFrequency
    {
        public class Program
        {
            private static Timer frequencyGenerator = null;
            private static OutputPort frequencyGeneratorOutput = null;
            private static TimerCallback timerCallback = null;
            private static InterruptPort button = null;
            private static int currentPeriod;
    
            public static void Main()
            {
                timerCallback = new TimerCallback(TimerInterrupt);
                frequencyGeneratorOutput = new OutputPort(Pins.GPIO_PIN_D7, false);
                button = new InterruptPort(Pins.ONBOARD_BTN, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeHigh);
                button.OnInterrupt += new NativeEventHandler(button_OnInterrupt);
                currentPeriod = 500;
                frequencyGenerator = new Timer(timerCallback, null, 0, currentPeriod);
                Thread.Sleep(Timeout.Infinite);
            }
    
            private static void button_OnInterrupt(uint data1, uint data2, System.DateTime time)
            {
                if (currentPeriod > 100)
                {
                    currentPeriod /= 2;
                    frequencyGenerator.Change(0, currentPeriod);
                }
            }
    
            private static void TimerInterrupt(object state)
            {
                frequencyGeneratorOutput.Write(!frequencyGeneratorOutput.Read());
            }
        }
    }
    

    As you can see the code is relatively straight forward. Connecting up the logic analyser and running the application generates a 1 Hz signal (500ms period will result in 1Hz). Pressing the button on the Netduino Plus 2 will cause the period to be halved and hence the frequency to be doubled. You logic analyser will confirm this, I know mine did.

    One thing you should note is that the Change method returns a value to indicate if the method has disposed of the old timer. I have never seen this not return true but if you see some odd behaviours with timers still generating interrupts at old frequencies then it may be the result of an old timer still hanging around.

    Conclusion

    This article was inspired by a posting on the Netduino chatrooms regarding the changing/killing of timers. I must admit I was a little astounded to find that there was no Stop or Start method in the class. As you can see, the techniques for doing this are not complex, they are just not obvious.

    There are also some nice feature, like the fact that Timers run in their own threads. Investigation of these features are left as an exercise for the reader.

    As always, the Source code is available for download.