Marvell had a problem. Its Kinoma Create development platform had two tiny microcontrollers acting as programmable I/O controllers. Each MCU could be programmed through the GUI running on their main processor to handle multiple interfaces. However, when the user wanted two or more interfaces, data got lost. The tiny MCUs couldn't handle more than one I/O port without losing data. An OS called SynthOS fixed their problem.
SynthOS is a software tool for the creation of a custom, optimized application specific operation system (ASOS). With system constraints and configuration information specified in a project file, SynthOS analyzes the application and driver code, and generates the source code that includes the original user code and all the code needed to run the requirement for the specific ASOS.
The ASOS generated by SynthOS is an efficient multi-tasking kernel that can coax new capabilities out of low-end system, especially small 8- or 16-bit low speed processors, and enable them to be used in advanced IoT devices while providing security, portability, and low power consumption. The resulting ASOS is a form of unikernel, a small footprint, single address space system that's gaining in popularity for efficiently running directly on a hypervisor or bare metal system.
Kinoma Create, shown in Figure 1, is a hardware and software prototyping system for connected devices and the IoT, based on Marvell's PXA166 processor. Kinoma Create is designed to work with external hardware and sensors in a connected environment.
To connect the Kinoma Create to external hardware, the system has a 50-pin interface on the back side; those pins are dedicated for fixed functions. The system also has two identical 8-pin headers on the front, defined in Table 1, with each 8 bits controlled by one of two 8-bit Microchip PIC 16 MCUs that operate as general-purpose I/O (GPIO) processors. The functionality of these pins is dynamically assigned to a physical pin using the built-in Front Pin app communicating to these GPIOs. The goal of this project was to develop the code for the two GPIOs that could run multiple I/O interfaces simultaneously, without losing data, yet still fit in the 4 kbytes of flash and the 256 bytes of RAM of the PIC 15 MCU.
Any of the pins on the front panel interface can support the functionality shown in the table.
The hardware architecture is shown in Figure 2. The PIC16 is a small but capable MCU with a sophisticated interface and configuration setup. The Kinoma Create uses two PIC16F1508 microcontrollers, each with the following features:
· Mid-range instruction set: 48 instructions, 16 stack levels
· Flash program memory: 4 kbytes
· RAM: 256 bytes
· Oscillator: 16 MHz
· PWM: Four standalone
· ADC converter: 12 channel 10-bit
· DAC: 5-bit
· Timers: Two 8-bit, one 16-bit
The controller is clocked from the internal 16-MHz clock. At 4 cycles/command, it's equivalent to 4 MIPS. The communication with the host processor occurs over a hardware I2C interface.
Given the limitation of the PIC16 processor in terms of memory space and processing speed SynthOS is suited for this project. An ASOS created by SynthOS is efficient in terms of memory use, processor power, and speed. It's also useful for a small MCU like the Microchip device used in the Kinoma Create. SynthOS allowed the code to be ritten in C. When one task needed to call another task, or wait for another task to complete, a special line of code was inserted that's recognized by SynthOS, called a "primitive."
SynthOS was then run on all of the task code to insert the appropriate semaphores and flags for each task into the code at the appropriate points. SynthOS also created task management code to schedule the task and administer the associated flags and semaphores. The software architecture of the SynthOS-Kinoma Create Project is shown in Figure 3.
The System Init module sets up the system configuration and hardware configuration upon power up, reset, and any other initialization condition. The I2C Host Communication module is the main task in the system. It communicates with the host, gets configuration information and data from it, and sends data back in a response to a host request. It uses the PIC's integrated I2C mechanism. The data from the host is divided into two categories: data with no constraints and data that needs to be verified against a set of allowed values. The latter data is saved into a set of shadow registers and handled in the Shadow Registers module.
Some of the data sent from the host can get the system into an unstable state or conflict with other data. This category of data is saved into a set of shadow registers, contained in the Shadow Registers module, and compared against the allowed values for the corresponding registers. Only after it's verified as an allowable value will it be loaded into the registers and take effect in the system. If the system detects an error in a shadow register's data, it won't load that data into the corresponding register, but will indicate the error.
The Analog Input and A/D module handles the analog input. The module uses the PIC's internal 10-bit analog-to-digital converter and stores the data in registers that the host can retrieve via the I2C interface.
Digital I/O Port Manager
The Digital I/O Port Manager module handles the digital I/O port status and the I/O. This functionality is divided between this module and some of the other modules. Setting the pins as power, ground, or NC is done in the Shadow Registers module after verifying that there are no conflicts between the settings (e.g., a pin defined as power and ground at the same time).
The PWM Port Manager module controls the pulse width modulation (PWM) output and is executed in an interrupt service routine (ISR). The PWM is defined using two registers, the first defining the cycle time and the second defining the time period that the signal is high within the cycle time. The PWM mechanism relies on the timer interrupt to generate the required waveforms. Due to the PIC's limited capabilities, the system is limited to a three PWM outputs.
In the I2C with Peripheral Devices module, the PIC is the master on the I2C network. The clock and data are generated by the PIC by twiddling bits on the pins to emulate the I2C protocol. The system can send single-byte data messages or do buffer transfers if needed.
Interrupt Service Routine (ISR)
The PIC's limited capabilities and the interrupt support architecture require a deviation from the standard implementation of an ISR with SynthOS. The PIC has effectively only one interrupt vector, and all interrupts are directed to this same address. It's the firmware’s responsibility to detect the active interrupt and respond to it. This architecture requires the firmware to support the interrupt before exiting the ISR and resetting the interrupt flag. For this reason, this system executes the host I2C and the PWM in the ISR to minimize the code size and maximize performance.
The ASOS manages the system's different tasks and lets them run in parallel, achieving higher efficiency. SynthOS defines a task as an Init Task, Loop Task, Call Task, or ISR, and each task type in the system must be specified in the project file. We created a project file to specify the type of each task and its attributes such as the task’s priority and its frequency, all shown in the listing.
Next, we'll describe the tasks for the SynthOS-Kinoma Create Project. An Init Task is executed once during the software's initialization. Since this implementation is relatively simple, and due to memory limitations, we moved all system initialization into one task. This task includes the system configuration, interrupt setup, and variable initialization.
A Loop Task is executed periodically by the ASOS using an algorithm defined by the scheduler selected in the SynthOS project file. Due to the PIC's limited memory, we use only Loop Tasks in this project, which also simplifies the configuration file and the SynthOS-generated scheduler.
I2C Master task manages the communication with the host on the I2C bus. The Shadow Task verifies information from the host processor by using shadow registers and updating the system configuration and data only after the data in the shadow registers has been verified.
The Analog Input task runs in the background, reading the analog input from the ports specified by the host and saving it in the shared memory. A Call Task is one that's not executed unless it's specifically started by an executing task. In this implementation, we didn't use any Call Tasks.
Interrupt service routines are executed when interrupts occur, just like in a typical embedded system. The ISRs in the system are either a Timer interrupt for PWM, which manages the PWM timing based on the duty-cycle defined by the host processor, or an I2C host interrupt that manages the communication with the host processor.
After implementing the system using SynthOS, the GPIOs worked as intended, allowing multiple I/Os to operate simultaneously without any data loss, enabling multiple A/D and digital I/Os, up to four PWMs, and an I2C interface on the eight pins, supported by just the one PIC MCU. Considering the functionality, the system memory utilization is highly efficient at 3360 bytes of flash (82% utilization) and 198 bytes of RAM (77% utilization).
Note that the code for this project can be downloaded from www.zeidman.biz/Kinoma, and SynthOS is available to use online completely free at www.SynthOSonline.com.