Hexabitz arrays are fully-distributed, multiprocessor systems. Each configurable module has its own MCU. Modules connect with each other to form an array, similar to the way computers connect to form a network. Having separate processors -instead of embedded multi-cores- in the same array gives you the flexibility of running them at different clock speeds or even mixing powerful, expensive processors with small and cheap ones.
This architecture dictates having a separate firmware uploaded to each module. You are required currently to write, debug and compile code for each module separately -while keeping in mind all the interactions between these modules- since there is no technology to support intuitive multi-processor software development. I’m looking forward to the day where we can write a single software -as if we were developing for a single target- and the intelligent compiler would then dissect this software into small pieces, figuring out all the required interactions between these modules on its own. Hopefully, it won’t be that long!
Until we get our hands on such a revolutionary tool, we have to figure out ways to design and develop code for complex arrays so that an array of 10 modules does not take 20x development efforts. Fortunately, there are lots of tricks and solutions to substantially reduce the amount of work needed. We will discuss some here and in future posts.
In order to support a wide array of users, Hexabitz is designed for three developer levels/personalities:
- Advanced Developers (The Do-It-Yourself Folks): Users with critical needs and very high skills in embedded systems development can take Hexabitz hardware and write their own software from scratch using low-level, third-party hardware drivers available from chip manufacturers. Being an open-source hardware system gives these hardcore users the freedom of developing their own system without the hassle of hardware design and the nightmares of production lines and supply chains!
- Experienced and Mid-level Developers (Mix-n-Match Heros): You do not have to start from scratch! We laid down the ground work for software development through our operating system (BOS), APIs and module drivers, all coupled with a set of optimized third-party middleware (e.g., real-time operating system, FAT system, etc.). Users can either use all of the above and focus on application-level development or pick the level of integration and design the components that they feel are important to differentiate their product (e.g., using only BOS or only module drivers).
- Noobs (The I-Have-No-Idea Newbies): Newbies and beginners can still utilize Hexabitz through Command Line Interface (CLI). CLI is a set of plain-English commands that you can send to the modules to execute. These commands are very handy to perform quick tests and run simple applications. In fact, probably 80% of simple applications can be executed through a set of CLI commands. The CLI command set will be expanded regularly to offer more features while preserving simplicity and easy-access as much as possible.
Any Other Options?
We will focus, in the time being, on developing and supporting hardware and software tools and components mentioned above. We will do our best to offer more options in the future, especially in higher-level programming languages (e.g., visual programming, Python, MATLAB, etc.)
Hexabitz Software Components
Figure 6 illustrates the hierarchy of Hexabitz software components how they map to different users. We will discuss next these components and detail the important ones.
1. Low-level Hardware Drivers - Developed by ST & ARM
The Hardware Abstraction Layer (HAL) and the Cortex Microcontroller Software Interface Standard (CMSIS) developed by ST and ARM, respectively, are the core low-layer drivers for Hexabitz mainstream-implementation MCU hardware. They interface directly with MCU registers and perform the most basic tasks. Most developers do not need to worry about these drivers but it helps to understand how they work and how they can be implemented if you want to dig in further in embedded systems development and optimize the code for your application.
2. Third-party Middleware - Developed by various vendors
A higher-level of third-party drivers is required to perform advanced functionality such as real-time control and data storage management. Two major third-party, middleware components are currently used in Hexabitz software: FreeRTOS and FATfs. It is also very likely that we add more components in the future as functionality expands.
FreeRTOS is the de-facto real-time operating system (RTOS) for MCUs and small embedded systems. It is open-source and free to use in its standard format, thus, accessible to everyone. An RTOS is a critical tool to ensure synchronous, predictable and real-time execution of software in embedded systems. Although FreeRTOS does not have all the capabilities of a computer-grade RTOS, it does have basic multi-threading (multi-tasking), memory management and access control. FreeRTOS code is complex and difficult to understand for non-specialists. However, from a user perspective, interactions with FreeRTOS become minimal if Hexabitz’s BOS and module drivers are utilized. Currently, Hexabitz is not making use of all of FreeRTOS features but as the platform evolves, we will integrate more and more of these powerful features. In general, each module is always running the following threads (tasks) in parallel (Note that parallel here is an over-simplified notion as MCUs can only execute code serially. The FreeRTOS scheduler, however, cycles between these tasks on every RTOS beat to simulate parallel execution.)
- N Communication Tasks (where N is the number of module array ports): These tasks handle communication with other modules and external hardware via BOS messages and streams. All N tasks can run simultaneously, transmitting and receiving data, without affecting each other. Their impact on MCU performance can be effectively reduced when using DMAs.
- CLI Task: This task is responsible about communicating with human users. It handles the delay in human interaction without blocking the system. This means you can connect to the module to inquire and update its parameters and send new commands at any given time (and from any array port) without stopping or delaying front-end processing and array communication. Right now, you can only open one CLI session on the same module at any given time. You can, however, open as many CLI sessions as you want on different modules in the same array! This means you can connect to two different modules and simultaneously send two different commands across the array and they will be transferred and executed properly. It is possible to open and utilize a CLI session by non-human entity (e.g., an external hardware). However, it is much more efficient to use Messages for this.
- Default Task: This task is running in the background and is used by the BOS to execute some behind-the-scene activities such as initiating array ports scan and controlling module indicator LED.
- Module Task (optional): Some modules have their own task(s) running in the background as well. This task is concealed from the end user and is used to run various module-specific, background applications.
- Front-end Task: This empty task is exposed to the user through the project main.c file. It is essentially a scratch pad that can be customized for each project. The end-user can effectively ignore all other running tasks and treat the system as a single-thread program with the front-end task simulating the super-loop used in traditional, single-threaded, C programs.
Figure 7. shows a screen capture of the CLI interface displaying tasks running in H01R00 module along with their running time (i.e., CPU utilization) percentage.
File Allocation Table (FAT) is a system to manage files on storage media. It is used on personal computers and many embedded systems. FATfs is a free, memory-optimized FAT module for small embedded systems. It enables you to read and write files stored on various storage media (e.g., SD/MMC cards, Flash memory, SRAM memory, etc.) and same files can be viewed or modified on personal computers as well. Storage-related modules utilize FATfs as part of their module drivers. FATfs code is highly optimized and difficult to read and understand. As with FreeRTOS, using module drivers effectively relieves the user from understanding FATfs intricacies while utilizing its features.
3. Bitz Operating System (BOS) - Developed by Hexabitz
BOS is Hexabitz own operating system, built on top of FreeRTOS, and specifically designed to support Hexabitz arrays. It relieves the user from writing code to perform initialization, inter-array communication and housekeeping tasks, among others. BOS also manages the Command Line Interface (CLI)-a simple and intuitive tool for user interaction, as well as non-volatile storage of module and array parameters (and syncing these parameters across the array). Future software releases will introduce more intelligence and automation to let users focus on their end-application and delegate all background activities to the BOS. BOS is an essential part of every Hexabitz software project. Both the BOS and module drivers have the following sub-components:
- Commands: CLI Commands are a set of easy-to-use control commands in plain-English language. They can be sent to the module from any serial terminal tool (e.g., RealTerm) via any of the array ports. Commands can be executed locally (i.e., on the module itself), forwarded to another module (or a group of modules) or broadcasted to all modules in the array. There are Commands available to control BOS and most of Hexabitz configurable modules. In general, most Commands return a textual response to the user, either from the local module or from a remote one. The response can be turned on/off by the user.
- Messages: Messages are the machine-format version of CLI Commands. They are transferred across the array in short packets that are faster and more efficient but not human-decipherable. They can be used by external hardware to control Hexabitz modules. They are also used inside the array for inter-array communication. When you send a Command to a remote module, it is forwarded to its destination via a special Message. The textual response is also a packed into another Message that is sent back to the source module, which eventually displays it to the user. As with Commands, there are specific Messages for BOS and for the modules. Messages have globally unique IDs that help identify each one anywhere it is used in the array. Modules only respond to their own Messages and to BOS Messages. They can, however, forward any Message to any other module regardless of its content.
- Data Streams: You can setup Data Streams to transfer a large amount of data across the array. Streams utilize Direct Memory Access (DMA) mechanisms and thus transfer data efficiently without much CPU intervention. Streams form physical connections (pipelines) between array ports and disable any other interaction with these ports (e.g., Commands and Messages). You can setup a Stream to transfer a specific amount of bytes or to timeout after a specific time. This guarantees that utilized ports go back to their default state when the Stream is no longer needed. You can setup complex single-input-single-output (SISO) or single-input-multiple-output (SIMO) data Streams across the array easily using our APIs, Messages or Commands. Streaming speed will be close to maximum speed allowed by the MCU UART peripherals regardless of Stream complexity. (Streaming speed can reach or exceed 1 Mbps in Hexabitz mainstream implementation with custom configuration.)
- APIs: Application Programming Interfaces (APIs) are functions available to the user to programatically access all BOS and module functionality. They are exported in BOS and module header files and thus can be called from the Front-end Task (or from other places) as part of user application. APIs provide much more flexibility than CLI Commands since they allow standard embedded C-based programming. APIs are only executed locally. If you want to call an API in a remote module, you can send the appropriate Message to that module and it will automatically trigger the esecution of the appropriate API once it reaches there.
- Internal Functions: These functions are hidden from the user and are utilized by the module itself (or BOS) for internal use.
- Peripheral Drivers: These are sets of higher-level hardware drivers that sit between low-level drivers (e.g., HAL) and the BOS and module drivers. Peripheral drivers are usually added to the project in separate files that handle each peripheral (e.g., UART, DMA) and are hidden from users (i.e, not exported).
Routing and Array Topology
The BOS is responsible about routing Messages and Streams within the array. Routing is based on an internal routing table that defines the number of connected modules, their Hexabitz part number and how they are connected to each other, as well as the polarity of each of the serial array ports. The last one is particular important for duplex (two-way) communication. As mentioned before, the default state of all communication (array) ports is to have the transmit pad (TXD) on top and the receive pad (RXD) on bottom in order to offer complete modularity and flexibility in assembling modules. For bidirectional communication to take place, however, you need the TXD line of first module to connect with the RXD line of second module and vice-versa. This is possible by programatically swapping one of these port pins whenever the modules are connected and putting the port back into normal polarity when they are separated.
Routing tables can be generated in two ways:
- Predefined routing tables are created offline, either manually or automatically, and then added to each module project as a topology header file.
- Routing tables are generated online via the BOS explore API/Command. Users can program array modules with standard single-module firmware (called native modules) and then connect them together and power up the array. The explore API/Command can then be used to query all connected modules and figure out array topology and assign appropriate port polarities. The generated routing table is broadcasted to all modules and stored in their non-volatile memory.
Every time the array boots up, it verifies its actual connections against the stored routing table so that any topology change can be accounted for. We will provide later a detailed anatomy of a sample topology header file and instructions on how to generate one.
4. Module Drivers - Developed by Hexabitz
Module drivers provide all module-specific functionality, i.e., all the software needed to use and configure module front-end. Similar to BOS, modules have their own APIs, Messages, Streams and Commands. Each software project is usually created for a single module (because it will be loaded on a single MCU) and thus you should not add another module drivers to the same project. If you have an array of similar modules (e.g., multiple H01R00 modules), you can create a single project and use Targets feature in the software development tool (uVision) to account for the few variations between these modules (e.g., their IDs, etc.) This way you are able to generate, with a single click, firmware images for all modules from that same software project.
5. Command Line Interface (CLI) - Developed by Hexabitz
In order to make the platform easily accessible for non-embedded-programmers, Hexabitz features a Command Line Interface (CLI) based on the core CLI functionality of FreeRTOS. CLI is available at all array ports and can be accessed from any computer (or any device!) running a serial terminal tool. There are plenty of serial terminal tools that are free and require no or minimal drivers installation. We use a free terminal tool called RealTerm but users can use any other similar software as well. All you need to use the CLI is a cable the bridges module UART ports with other common PC communication ports (e.g., USB-RS232 cable).
Commands sent via CLI are executed instantly and thus there is no need to compile any code. Once the command is sent you cannot go back and change it and it is difficult to execute complex logic efficiently in the CLI. It is still, though, a very handy tool to perform quick tests and build small applications without the need to read a single line in the code! We will post later more details about using the CLI.
6. User Applications
As mentioned before, user application ideally reside in the Front-end Task. Users can forget about other threads and develop their own application just like they would do on a single-thread platform (with few exceptions). Confining user application to the Front-end Task makes it practically effortless to upgrade any existing project to use the latest release of Hexabitz BOS and module drivers.
All Hexabitz software will be released with MIT license. This means you are free to use our software in your own projects/products for personal or commercial applications. You are not required to open-source your projects/products as a result of using Hexabitz code inside it.
To our best knowledge, all third-party components currently included with Hexabitz software follow similar licenses (MIT, modified GPL, etc.). We will do our best to not include third-party components that require licensing or have restricted open-source terms (i.e., forcing you to open-source your project). There is no guarantee, however, that this does not happen. If we ever include a software component that requires buying a license or one that forces restrictive, open-source terms, we will mention this clearly. We advise you to verify the license of each third-party component with its vendor.
HEXABITZ SOFTWARE AND HARDWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE AND HARDWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE AND HARDWARE.