Update: Preliminary details about GoBus v1.5 have been released on the Netduino Forums. The following information still applies to the original GoBus implementation that currently exists on Netduino Go and its modules.
Hello, and welcome to the Komodex Blog!
This is the first of a series of blog posts I have planned that will cover a few different electronics subjects, most of which will be related to building modules for the Netduino Go.
Since this is a relatively new platform, I thought a good place to start would be an introduction to Netduino Go from a developer’s perspective, including an overview of how go!bus actually works. The information in this post has been gathered from both my own development efforts and the Netduino Community (including the Netduino Forums and Wiki).
All Netduino hardware is open source, including the Netduino Go mainboard and the modules built by Secret Labs. The schematics for these boards can be downloaded from the Netduino website:
- Netduino Go Mainboard
- RGB LED Module (click Attachments in the top right)
- Button Module
- Potentiometer Module
- Shield Base
The mainboard is powered by an STM32F4 microcontroller and the shield base is powered by an STM32F2. The RGB LED and potentiometer modules are powered by low-cost STM8S microcontrollers, and the button module simply uses a shift register for identification.
The Netduino Go mainboard has a total of 8 sockets for connecting go!bus modules. All sockets have the same capabilities, and any go!bus module can be plugged into any go!bus socket. Each socket has 10 pins with the following functions:
- 3.3V Power (switched per socket)
- 5V Power (switched per socket)
- GPIO/IRQ (bidirectional, unique per socket)
- UART RX (from the module’s perspective) (shared per bus)
- UART TX (from the module’s perspective) (shared per bus)
- SPI Chip Select (unique per socket)
- SPI MOSI (shared per bus)
- SPI MISO (shared per bus)
- SPI Clock (shared per bus)
- Ground (always connected)
Community member ItsDan posted a diagram on the Netduino Forums showing the layout of these pins on the socket connector.
The sockets are grouped into two channels: channel 1 contains sockets 1-4, and channel 2 contains sockets 5-8. Each channel has its own SPI and UART channel, so it’s actually possible to communicate with two modules in parallel, provided that they are connected to different channels.
Each module has access to two power rails running at 3.3V and 5V. The mainboard has two MOSFETs for each socket — these are used to switch the power for each socket on or off. Each socket’s ground line is always connected.
It’s important to keep power management in mind when building modules. go!bus modules can use up to 200 mA (at 3.3V), but to ensure reliable operation, each module must use less than 60 mA during enumeration (more on that later) and must also be able to run at 60 mA or less indefinitely (for situations where more power is not available). If a module needs more power, it may be necessary to provide an external power connection.
go!bus data lines run at 3.3V. Since there are still many components that run at 5V, voltage level conversion may be necessary for some modules. There are numerous ways to convert signals between different voltage levels, and the “right” one usually depends on the system’s specific needs (such as one-way vs. bidirectional communication, tri-stating, etc.). When building a module, you should run the module’s primary microcontroller (that is, the microcontroller that implements the go!bus interface) at 3.3V and do level shifting to other peripherals on the module where necessary.
The primary medium of communication for go!bus modules is SPI. While it is possible to communicate with modules over UART (and this is currently how the beta shield base firmware communicates), all module communication will eventually take place over SPI.
There is also a general-purpose, bidirectional I/O line connected to each socket on pin #3. This can be used for any general-purpose I/O needs, but it is most commonly used as an IRQ line. When a module has some data that needs to be sent to the mainboard, it can send a signal via the GPIO/IRQ line. Some time later, when the mainboard is ready to service that request it reads the incoming message via SPI.
Note that when used as an IRQ, the GPIO line is “active low” and should remain high when inactive.
One of the requirements for go!bus compatibility is that modules must be able to be reprogrammed from the mainboard. If you look at the schematics for the RGB LED and potentiometer modules, you’ll notice that the UART TX/RX lines are connected to the STM8 microcontroller’s programming lines — reset and SWIM. Once code is available, this will allow the mainboard to send firmware upgrades to these modules as they become available. Similar configurations are provided for other microcontrollers, including the STM32 and a few others that have not yet been released.
It’s important to note that, while some details of the go!bus protocol are still being worked out, all Netduino Go hardware currently being sold is final, production-level quality and will receive firmware updates to take advantage of the planned go!bus protocol upgrades. Even the shield base, which is currently in beta, will receive a firmware update to take it out of beta in the next few months.
There are numerous current and planned features for go!bus, including:
- Dynamic enumeration — any go!bus module can be plugged into any go!bus socket. It’s usually not necessary to specify which socket a module is plugged into when instantiating modules (but it is possible to do so).
- DMA — allows for high-speed transfers on STM32-based modules.
- Hardware CRC — helps ensure communication reliability with little overhead.
- Virtualized I/O — allows you to use module pins as though they were directly connected to the mainboard.
- Module chaining — modules can be designed to be linked together. To maintain high speeds, modules that implement downstream go!bus ports must be based on the STM32, but any type of module — even something as simple as the button module — could be plugged into that downstream port.
Regarding virtualized I/O, some of this functionality can already be seen on the shield base module. For example, if you open up a PWM port on the shield base, the PWM is managed by the shield base itself — communication over go!bus is only necessary to set the PWM parameters.
Each go!bus module must be able to, at minimum, respond to enumeration requests from the Netduino Go mainboard. When looking at Netduino Go modules, you might notice that all modules have at least one IC. This is most often a microcontroller, but some simple modules like the Button Module and Nwazet’s Relay Module have only a parallel-to-serial shift register.
In order to provide dynamic enumeration, each module must be able to identify itself. That is, a button module must be able to identify itself as a button module, an RGB LED module must be able to identify as an RGB LED module, and so on. The process of a module identifying itself to the Netduino Go mainboard is referred to as enumeration.
To make this process work, each module is given a unique, 128-bit universally unique identifier (UUID). When queried, the module must respond with its own UUID to allow the mainboard to determine what is connected to each port.
Let’s take a look at what module enumeration looks like when observed with a logic analyzer:
The enumeration message is 18 bytes long, starting with
0xFE and followed with 16
0xFF bytes. The 18th byte,
0x15, is a CRC8 byte used to verify message integrity.
The first byte of the module’s response (
0x2A in the above screenshot) is ignored. The following 16 bytes represent the module’s UUID, and the 18th byte is the valid CRC8 value for the message.
If the mainboard receives an invalid response (or, more specifically, a message with an invalid CRC value) from a particular port during enumeration, it will attempt to re-enumerate that port several times before giving up and moving on to the next port.
So that’s what enumeration looks like with a microcontroller-based module, but what happens when you enumerate a shift register-based module such as the button?
For shift register-based modules, the last CRC byte is not actually used. The MOSI line is connected to the shift register’s Parallel Load line and, as a result, the shift register’s position is reset after the first enumeration byte (due to the transition that occurs when sending
0xFE). After that, the Button Module’s unique ID (
0x02) is sent and the enumeration procedure is complete.
Since shift register-based modules cannot implement CRC, they are actually enumerated twice for verification.
Currently there are only two modules that use a shift register: the button module and Nwazet’s relay module. There really aren’t too many modules that are simple enough to get by with only a shift register, so in most cases you only really need to focus on standard microcontroller-style enumeration with a CRC byte.
Once the module has been enumerated, the module driver (running on the mainboard) can open the SPI channel for further communication. Currently, the rest of the module communication procedures are handled “manually” by each module and its driver. This is set to change in the coming months (when the standard module firmware is released) but for now, the actual communication protocol used between the mainboard and connected modules is completely custom per module.
Let’s take a look at the protocol used with the RGB LED. Whenever you use the
SetColor() method, three SPI messages are sent. Here’s what the communication looks like:
- The mainboard sends the new color value to the module. (screenshot)
- The mainboard requests the current value from the module for verification. (screenshot)
- The module signals via the GPIO/IRQ line when it is ready to respond with the requested data. (see end of previous screenshot)
- The mainboard reads the data in from the module. (screenshot)
The procedure for reading the value from the potentiometer is very similar:
- The mainboard requests the current value. (screenshot)
- The potentiometer module signals when it is ready to respond. (see end of previous screenshot)
- The mainboard reads in the data from the module. (screenshot)
The potentiometer uses a 10-bit ADC, so the high and low bits are set as separate bytes.
Once virtualized I/O is available for STM8-based modules, the protocol used for the RGB LED and potentiometer modules will change dramatically. The RGB LED module could be implemented in its driver as three different virtual PWM outputs. The potentiometer module simply becomes a virtual AnalogInput.
If you’re developing modules today with go!bus 1.0, you’ll need to devise your own protocol to communicate with your modules, similar to what appears above.
In a few months, firmware and driver updates will be released to upgrade existing Netduino Go hardware to go!bus 1.1+, an updated version that brings feature profiles to go!bus modules. This firmware not only brings new features to go!bus, but changes the way modules actually communicate over the physical SPI interface as well. Rather than simply sending data directly to a module over SPI, modules that implement go!bus profiles will send and receive standardized data packets. These packets contain addressing information and profile messages and are fully compatible with the advanced features coming in go!bus 2.0, including module chaining.
To help enable the use and implementation of these features, Secret Labs and members of the community are currently working on building a standard firmware library for STM8 and STM32-based modules. This firmware will handle all go!bus communication and will allow you to easily implement different go!bus profiles, including a GPIO profile, PWM profile, serial port profile, etc.
Virtualized I/O and being able to access module pins directly from the mainboard is great, but it’s not a one-size-fits-all solution. Some modules require more advanced processing to take place on the module itself — for example, a multiplexed LED display. For a module like that, continuously updating the output pins of the module over the bus would be needlessly inefficient and, in some cases, perhaps even too slow. For situations like this, you will be able to write your own firmware on top of the standard libraries and open a serial communication channel to send and receive custom messages with your module as necessary. This is similar to implementing your own custom protocol, but in a better-defined, more reliable fashion.
Information about the specific capabilities and behaviors of the standard firmware library hasn’t been released just yet, but as soon as it is available more information will be posted on the Netduino Forums. Be sure to check back there regularly for the latest news.
- Netduino Wiki – Module Builder’s Guide
- Netduino Wiki – Module Firmware Development
- Netduino Go Forum
- Netduino Forums – Building custom go!bus modules for Netduino Go
Thanks for reading! I have a few more posts planned about the development process for go!bus modules so make sure you follow me on Twitter if you want to know when those are posted.
Also, be sure to check out my Seven Segment Display module for Netduino Go, which should start shipping later this week!
6 thoughts on “A Developer's Introduction to GoBus”
This is awesome article!
One minor correction, though: the MOSI data received from mainboard (step #4, resp. #3 in your communication examples) is not ignored, the first byte is checked to determine what the mainboard requests -module identifier (= 0xFE) or the data (!= 0xFE).
Looking forward to reading the next installment of this topic 🙂
THIS is the overview I’ve been looking for!
Nice job. Fantastic job!
Looking forward to more, including a post on STM8/32 programming for noobs. (And ways to avoid it.)
Oh, good point! Just updated the post.
This is an awesome article 🙂
As has been said already i too am very much looking forward the next instalment.
Keep up the good work!