Declic: Linux 2.6 on the International Space Station
The complete Declic contains about ten small microcontrollers for dedicated hardware-related tasks, including the activation of heaters, the acquisition of a pressure or temperature sensor and controlling a stepper motor. The microcontrollers we use in Declic have a UDP/IP interface and run the real-time operating system μC/OS-II. Development of the source code for these controllers, however, was initialized on Linux, using an OS emulation layer.
Developing software for microcontrollers often is an annoying process of switching between downloading cross-compiled data over a serial link to a test board, debugging, recompiling your source code and resetting the test board. If you are lucky, the cross-compiler is Linux-friendly; unfortunately, many compiler environments are not. By using the Microsoft Windows emulator Wine, many of the cross-compilers can work together with Linux. In such a situation, you can use all the Linux tools that make software development so much easier. For our system, we chose μC/OS-II as a small real-time operating system able to run on 8-bit microcontrollers. μC/OS-II (often abbreviated to ucos) is distributed in source code form. You can purchase the book from the author and receive the source files of the OS, which can be ported to numerous microcontroller types. All the fundamental real-time OS aspects are there, including semaphores, mutexes and multitasking.
Every ucos function has a GNU C equivalent. For development, we used fake-ucos, a simple set of wrapper functions around standard GNU C equivalents. By using fake-ucos, it's possible to develop your microcontroller code on Linux. Then, you simply exchange the fake-ucos library for the real ucos source code and cross-compile the code for your favorite microcontroller. Of course, you need to extend all hardware-specific code details afterward, but it's certainly a great help in the early phase of a project.
The Declic microcontrollers need to do different tasks, but the process actually comes down to reading something or controlling/activating something—read an AD converter, activate heater x, move stepper motor 1 to location y. The CRE computer, running generic software, needs to know the capability of each microcontroller and the insert characteristics. Each insert is different, and for a future insert it's impossible to know any characteristic. How do we control an unknown set of things and read an unknown set of sensors of unknown type by software we want to keep as generic as possible?
We moved all hardware-specific control elements (AD conversions, activating heaters and stepper motors) into the microcontroller software. The microcontrollers are inside the insert, so each insert has its own hardware microcontrollers and software. A generic C program runs on the CRE main Linux computer for interfacing the PDHS with all the microcontrollers. This program handles the regulation algorithms and a Tcl command interface, which I cover later, and needs to collect all data coming in at different rates from all the controllers. The program is generic because it can control any type of insert, including future ones. High-accuracy thermal control algorithms are dependent on the type of insert; but these parts of the software are written in as a separate module. The command set is insert-independent, because it references only items and the items are described in XML format. An item can be a sensor (something that has a value we can read) or an actuator (something that can be written to). All these items are described in an Insert Definition File in XML format. A short example is given in Listing 1.
Listing 1. Part of an Insert Definition File
<ins_def> <board> <item> <pseudo_sensor name="BUILD_VERSION" max_sample_frequency="1" device_data_type="CHAR32"> </pseudo_sensor> </item> <item> <sensor name="YSI_PRESSURE" max_sample_frequency="1" device_data_type="INT24" SI_data_type="FP32" </sensor> </item> ..... <item> <desc>The Dallas board temperature sensor. </desc> <sensor name="DAL_ALI_POWER_BOARD2" dallas="1" device_data_type="INT16S" SI_data_type="FP32" unit="C"> <parameter type="CHAR32" value=""> </parameter> </sensor> </item> <item> <actuator name="PWM_OTSF" reg_actuator="1" upper_limit_SI="8.8" device_data_type="INT16U" SI_data_type="FP32" unit="W"> <parameter type="FP32" value="65.0"> <desc>Resistance of heater</desc> </parameter> <parameter type="FP32" value="30.0"> <desc>power supply voltage for this channel</desc> </parameter> </actuator> </item> ..... </board> ... </ins_def>
The Insert Definition File describes the insert from a software point of view. It consists of a description of all sensors and actuators (items) that can be controlled by a certain microcontroller board. Every item can have a device and an SI value. The device value represents the raw data from, for example, an AD converter, while the SI value is the human-readable converted value, such as Watts, Ohms or degrees Celsius. In this way, we are able to write a Watts value to a heater, and it's up to the controller to figure out what exactly should be written to an FPGA to get the heater to produce this number of Watts. The microcontroller uses the parameters for these calculations, which make the source code independent from such hardware characteristics as heater resistance or power supply voltage. When we read the XML file, the items get numbers in two different ways: an incremental counting for all items of the insert and a local counting for the items controlled by a specific microcontroller board. The scientist has a simple list of all available items that can be controlled with a set of Tcl commands.
- Nmap—Not Just for Evil!
- Resurrecting the Armadillo
- High-Availability Storage with HA-LVM
- March 2015 Issue of Linux Journal: System Administration
- Real-Time Rogue Wireless Access Point Detection with the Raspberry Pi
- DNSMasq, the Pint-Sized Super Dæmon!
- Localhost DNS Cache
- Days Between Dates: the Counting
- The Usability of GNOME
- Linux for Astronomers