Inside the JANOS Operating System
Welcome to my world…
JANOS Core:
Pictured is the core processing section of the first 412DMX hand-assembled prototype. This is typical of a core for the Series 4 JNIOR.
So there is hardware but it ain’t worth the FR4 it sits upon without Firmware.
No one today would argue that statement unless, of course, they just like to argue. But 50 years ago (yes its about 50 years!) few would understand.
That Renesas RX63NE micro-controller’s internal high speed Flash initially is blank. This board would do nothing until we put something in there. I will tell what we put in there and how it came to be in this forum section.
So we see here that the micro-controller has a basic RS-232 serial port (COM Diagnostic Port); It has access to the Ethernet LAN through an external PHY chip; And, there is a variety of external memory components.
One of the key aspects or the hardware that the Operating System must determine is the configuration. The 412DMX pictured above supports 128MB of NAND Flash. The JNIORs in production at this point use 32MB Serial Flash. So this NAND is being introduced here. It provides for lower cost, larger storage capacity, faster access, and more flexibility. It may find its way back into the entire series 4 line when revisions come up.
Every JNIOR has that battery backed-up low power SRAM. In production today we supply the 2MB chip. Some early JNIORs were built with 4MB chips. This is non-volatile memory. It contains the root of the file system (everything outside of the /flash
and /temp
folders). It maintains the Registry as the Series 4 does not reload from the /flash/jnior.ini
file on boot. And, it holds other immutable memory blocks as might be needed for the system and its applications. All of that being the choice of the Operating System and we will discuss it a bit later.
The 64MB DRAM is high-speed volatile memory that serves as the memory heap for the system. memory here is allocated, managed, freed, cleaned-up and formatted at the pleasure of the Operating System. JANOS has mastered the art of garbage collection making Java applications almost real-time. We will get in to all of that as well.
Early JNIOR Series 4 and the Series 3 versions did not utilize DRAM. These depended entirely on the SRAM for non-volatile storage and memory heap. Life back then was limited. The DRAM offered much greater capacity and lower cost. It also provided for faster access.
So that is the lay of the land where JANOS lives. Shortly we will get to know JANOS at an unprecedented level.
By the way, and as an aside, JANOS is only available in the Series 4 JNIOR at the moment. It will appear in other INTEG products as time goes on. It will also make itself at home in other other processors (ARM for instance). In fact, it may even be available to anchor the operation of products developed by other companies. It was conceived of and born just a short 5 years ago. Only time will tell. Now, at least, it has us spoiled.
With hardware just waiting to be programmed we encountered the first hurdle.
Project Name?
The first thing the IDE wanted was a name for the project. This gave me pause since it would be the code base for the new operating system. So what do we call this OS?
Knowing that we could change the name at any point we decided to get creative. I came up with JANOS which is an acronym standing for (J)nior (A)utomation (N)etwork (O)perating (S)ystem. The ‘J’ being a bit questionable as it could stand for (J)ava like that in JNIOR. Or it could just be because we like starting names with ‘J’.
But JANOS started to make sense when we learned that Janus was an ancient Roman figure, spirit or god that guarded doorways and archways. Depicted with his face pointing in both directions he was the god that dealt with all things coming and going, past and future, beginning and ending. This could loosely be considered to be the controller or god of I/O, right? Bingo!
So unless something better were to come up everyone seemed cool with the name and we quickly made it over our first real hurdle. A quick scan of the Internet led us to believe that “JANOS” would be relatively unencumbered for this use. The first C files were cast with a Copyright header referring to the code as JANOS. The earliest inception date seems to be the 15th of December 2011. That would be for main.c
.
Processor Selection
I suppose that I could get into the reasoning behind the selection of the Renesas RX600 processor. Initially we developed using the RX62N and then moved to the RX63N when that became available.
To start I would have to say that there certainly wasn’t an exhaustive search and very few processors were considered for JNIOR. Basically it was between some flavor of ARM and one or two micro-controllers that we had briefly looked into some years earlier. Luckily the local sales support for Renesas stepped in to tell us about the RX600 series. We had been inquiring about an earlier product. I had just wanted to pick something with the proper I/O mix that can handle the job and to pick it quickly.
Processors these days are quite complex. Most of the techniques employed in their design are now common place but 50 years ago things were somewhat simpler. Pipelining is an example. We want code to execute efficiently and quickly. Speed being somewhat of concern as we were growing tired of the performance (or lack of) in the Series 3 JNIORs. Most all processors these days employ a form of pipelining wherein multiple instructions at various stages are being processed simultaneously. This manages memory access and calculations making optimum use of each and every clock cycle.
I had been figuring on around a 100MHz system clock. That by itself isn’t fast given that PCs and smart phones all run an order of magnitude faster. But the JNIOR is just a controller and cost is a consideration. I also had wanted to avoid some of the concerns that come with high frequency circuit design.
At the same time I was concerned about code size. The operating system would surely be quite large and the ARM appeared to have a fixed 32-bit instruction size. That means that to simply increment a register that instruction would consume 4 bytes of program memory. I will have to admit that I have no experience with ARM at this point. I figure that migrating JANOS to it is inevitable. But I was attracted to the RX line as it boasted both fast execution and compact code size. Having variable length instructions and instructions that combine operations makes the pipeline design difficult if not nearly impossible. But the RX has apparently gotten it done.
Beyond the I/O pin count of the micro-controller and the included set of peripherals, I had also wanted a good amount of high-speed internal Flash for program storage. The processor also needed a good amount of high speed internal RAM for stacks. There also needed to be some form of internal EEPROM or erasable Data Flash for critical configuration settings. I had hoped to be less dependent upon the external memory devices which necessitate longer access timing. The RX62N seemed to cover my needs.
So a quick decision was made and I proceeded to pick up an RX62N evaluation kit. That was the sum and total of our (not so) elaborate processor selection process.
Considerations for Coding
Of concern is the IDE supplied for the RX line. Looking back I can’t give Renesas good grades on this front. Their home grown IDE was full of rookie GUI bugs among other things. They quickly moved to an Eclipse based IDE which caused a bit of a headache at one point. The IDE gets the job done but there are soooo many configuration settings that even creating a branch in code for development is a challenge. It works though.
But for operating system development you absolutely need good access to assembly code. Unlike 50 years ago the IDE now has you developing directly in C and hides any assembly aspect by supplying hidden initialization files and built-in libraries. That is all good if you are writing a simple single-threaded program but I was not. So to start I took the usual “Hello World” sample and had to dig into it to find all of the hidden code. We were not going to develop JANOS dependent on any one IDE or processor. So I needed access to each and every byte generated and incorporated in the resulting object files.
Once the startup code was located and I proved that I could pull that out of hiding, I had to deal with libraries. The IDE supplies its own “Standard C Libraries”. Again that is great for simple program development. But here again taking JANOS to another platform would mean different library code and therefore uncertainty in result. I would also be developing a preemptive multi-tasking environment and C libraries that are not guaranteed to be reentrant or that use even a single static variable spell disaster.
So JANOS required its own C Library code. Trying to prevent the IDE from supplying its own library code proved to be an issue. I managed to find the right balance that kept the built-in libraries out of the way. Even today it remains a concern. I’ve had to utilize uniquely named headers supplying standard named functions (i.e. pintf, etc.). It has been a challenge where the IDE should just have let me tell it that I did not want any libraries.
Even at the instruction level there are macros that need to be considered. If you add two 64-bit variables on a 32-bit processor there is no single instruction available. The IDE inserts a block of code that performs the operation. So that sum becomes several instructions the code for which is IDE or manufacturer specific. This you cannot prevent and it is a necessity but I needed the source code for those macros. Again this is to insure proper operation of the preemptive tasking system and to increase confidence in moving to other platforms. None of these seemingly personal requirements of mine seemed to be received by Renesas with any evidence of understanding. Simply put, reverse engineering is also a necessity.
I also needed to understand the approach the Renesas compiler uses for function calls. What processor registers are used and how stack space allocated and released. In addition I needed to understand the precise response to interrupts. This is key in creating a pure multi-tasking environment. Fortunately those topics are covered (briefly) in the Renesas compiler documentation. This does present a hurdle say if I want to use the IAR RX compiler at any point.
Obviously JANOS exists and I managed to find some level of comfort and control over the development environment.
If you are setting out to write an Operating System on par with Linux or JANOS you don’t want to do this. This is akin to standing at the edge of a cliff and looking straight down. If you realize how much work you have ahead of you, you will likely lose confidence in yourself. Then again, if you are staffing up to get the job done then understanding what needs to be done is critical.
Here I am going to list the sections of code that had to be developed to get JANOS to where it is. I would bet that this list will be missing some of it but here goes. This will also be in rough chronological order. At least as to when coding for the section was started.
Startup – Basically the main.c
for the OS program. It is responsible for configuring hardware and each subsystem. Eventually this terminates and becomes the “Idle Process” executing an infinite wait look and collecting unused process time.
Diagnostic Serial Port – The RS-232 (COM) port code so boot messages can be output and the command line interface developed.
Process Management – The ability to execute more than one process through preemptive multitasking. Requires a 1 millisecond tick interrupt and the ability to swap process context with minimum overhead. This also allows processes to terminate or be terminated. This subsytem maintains the uptime and realtime clocks.
Ethernet Interface – Configures the Ethernet peripherals and external PHY. This handles the delivery of outgoing packets and the reception of packets. This establishes the high-priority Network process needed to insure that network traffic can be received and processed quickly and efficiently. The Network Process was the first process created for JANOS and the first to run outside of the Startup/Idle Process.
Command Process – The Command Line executes as its own process. This process is awakened by a keystroke on the RS-232 (COM) port and will handle all Command Line access. You will also be able to access this through a Telnet connection and via the Websockets Interface as well.
Command Line – Prompts for command entry and allows for convenient entry of textual commands. Includes a set of built-in commands and facilitates the execution of application programs. Maintains command history allowing commands to be easily repeated.
Memory Manager – Maintains Heap memory. This gives processes the ability to allocate memory for different purposes and then to return it for reuse. Efficiently manages the free memory block pool. Strives to minimize fragmentation and improve the availability.
Date & Time – Provides the ability to set and read the hardware RTC. Maintains the time of day in milliseconds since some epoch. Provides the ability to convert the millisecond count into year-month-day formats. Handles time zones and Daylight Saving Time.
System Process – The operating system itself has a number of background tasks it must attend to while other processes are busy with their own tasks. These are performed by the System Process.
Network Protocol Stack – To exist on the network the JNIOR must handle standard protocols at a low level such as ARP, ICMP, DHCP and DNS. Then once IP addressing is established the higher level protocols like IP, UDP/IP and TCP/IP are required.
Digital I/O – Subsytem handles the Digital Inputs and Relay Outputs. Handles counters and usage metering.
File System – Provides that ability to store and retrieve data as files. This handles file storage as it distributed across memory technologies. The JNIOR stores files in the non-volatile SRAM, in Flash (/flash), and in volatile Heap (/temp). This includes static content from the Program ROM (/etc). Provides for file access controls using permissions modeled after Unix.
C Libraries – JANOS is written in C and requires the standard C library. In order to insure the re-entrant and thread-safe aspect of the C Library you have to have the source code and therefore have written a custom library.
AUX Serial Port – While very similar to the Diagnostics port, the AUX port includes handshaking capabilities and can support RS-485 communications.
FTP Server – Required to get files on to and off of the JNIOR.
WebServer – Used to serve files and create web sites.
Websockets – WebServer HTTP/HTTPS connections can be upgraded to handle the Websockets Protocol. This provides for the ability to remotely monitor and control the JNIOR.
JNIOR Protocol Sever – Provides for legacy support of the JNIOR protocol which allows for remote monitoring and control of the JNIOR.
Registry System – Subsystem to manage name-value pairs for system configuration.
JVM – Java Virtual Machine permitting programs written in Java to be executed. This includes a complete stand-alone Java Runtime Environment for the JNIOR. Uses a Native interface with the operating system.
Library File Handling – The ability to access and decompress files stored in ZIP and JAR files. Necessary for the execution of externally compiled Java programs. Also expands the File System allowing the WebServer to serve files directly out of a ZIP library.
External Module Support – Configures and utilizes the Sensor Port to manage external expansion modules.
Network Time Protocol – NTP synchronizes the JNIOR clock with the rest of the world.
Beacon Protocol – Required to facilitate initial network configuration. Used by the Support Tool in managing collections of JNIORs.
Field Update – The ability to update JANOS in the field. Allows a UPD file to be loaded and the operating system updated on reboot. This must be a fault tolerant procedure.
Sockets – The means by which Java application programs integrate with the network stack.
Users – The ability to create users, maintain credentials and require login. Users can be created, disabled and removed. There are different user permissions/capabilities.
Email – JANOS has the ability to send email notifications.
Inter-process Messaging – JANOS supports a Message Pump which is a system by which messages can be circulated between processes. JANOS can notify applications of certain events.
I/O Logging – The ability to log and display DIgitial I/O events and serial communications.
Network Capture – The ability to capture network traffic for use in debugging. JANOS creates files compatible with WireShark.
Security – Implements SSL/TLSv1.2 secure communications. This includes multi-precision math libraries, message digest calculations, encryption and decryption. Supports RSA, RC4, DES and others. Automatically generates self-signed certificates.
Server-side Scripting – Handle PHP-like server side scripting to support the development of sophisticated dynamic websites.
Regex Engine – Support the ability to perform search and replacement operations using Regular Expressions.
Watchdogs – The ability to detect when program operation has failed and then to take action to restore operation.
User Groups – Create user groups and assign users for use in handling file permissions.
If I am missing anything feel free to ask about it. Some of these items are extremely complex in and by themselves while others were not all that complicated. It has taken some 5 years in development. The OS consists of over 400 individual source files and countless lines of code. Does anyone really know how to count code lines? Anyway, slowly I will proceed to describe the implementation details.