Notes from the vault – 0x05 – RTX-51, an embedded scheduler

Part of group NOTES FROM THE VAULT. Theme from 1988, moved here 12Apr2022. Updated: 09Aug2024. Finished

Intro

This note, in a wider context, is about how I learned about the need for a task concept, and «below» tasks, about an early but necessary runtime system of mine.

The thing that started this text was that I already had published a description of a small, «home brewed» real-time executive (rx or scheduler or runtime), the RTX-51, RTX51 or RX51. I designed this in 1988. It was for the Intel MCS-51 8051- or 8052- type microcomputers. Up to 8 concurrent processes (or tasks) could be defined. A synchronising primitive consisting of a protected mailbox was also implemented. These were part of a fire detection system from the company I worked for all my professional life: Autronica AS, later Autronica Fire and Security.

Getting there

1988: the world from my desk

Ten years to become readied for occam and transputer

In 1988 I had not yet heard about the transputer (by INMOS), and the accompanying occam language. Still it was no surprise that when these arrived it was me, at work, who asked my boss if I could attend a course in occam. The course came to be in June 1989 and the location was at Inmos in Bristol, UK. But it had taken some years to get to that point. (More at Notes from the vault – 0x02 – Transputers)

1978: MCS-48 and ASM (no tasks)

Fig.3 – Hand coded MCS-48 hex instructions (1977)

I started working for Autronica for real in 1976, at the age of 26 – after my NTH university exam. In 1978 I coded the company’s first microcontroller product, containing an Intel MCS-48 type processor – the same type that was used in the first IBM PC’s keyboard. I literally «coded» in assembler, using a Prompt-48 box, where the hand compiled and relocated hex instructions had to be filled in, byte by byte. Up to this date I have kept some of the large A3 sheets. I scanned one to show here. See how I have used the eraser when I needed to redo. It looks like this piece of code takes care of some aspect of the RPM of a rather huge generator. No task concept, the code was running its loop every some ms. It didn’t even use interrupt. But it surveilled the mains power supply to radio link stations, and if the mains was lost, then the radio was kept on batteries for some time (settable by pot-meters). After this timeout it would start a large diesel engine connected to a generator (max three trials) which then powered the radio link and charged the batteries. My code then shut the generator down at some time after the mains came back. The voltage levels were also set by pot-meters, which had its variable center part connected to an output, to be used by a multimeter. 2.20V DC at the multimeter corresponded to 220V AC. Then onto the next limit to set. It had no other display than lamps and indicators in switches. The unit controlled some really large high power contactors. All the described functionality fit in some 10 bytes less than one kilobyte of code. I never repeated that feat – and I never wanted to

I recollect that this microcontroller only had 8 bits long conditional jumps. So, for the few jumps or calls across a 256 bytes page boundary I had to make a short landing table table at the end of each of the pages, for a JUMP or CALL instruction, to get across the boundary. This was my first encounter on such boundary crossing «by hand». There should be two more. A disclaimer is appropriate here. Much of this is re-collected from the brains of a 72 years old man (=me), and I was around 30-40 back then. Even if I still have the manuals and Google search – I still might get some details wrong.

1980ies: Intel and Texas and a dawning on tasking

My boss didn’t agree to purchase on an Intel Intellec blue box (the large one, with screen: the Intel MDS 80 – Microcomputer Development System running the ISIS operating system), before around 1980. We then had programmed in PL/M-51 and PL/M-80 for about a year. Around that time I was introduced to the Texas Instrument development system for the TMS9900 (or «990») series microprocessors.  So we started to code in MPP Pascal (MicroProcessor Pascal) and I learned about tasks for the first time. The learning curve was steep. I think that this was based on ideas by Per Brinch Hansen, one of the great theoreticians of the time. And he had friends like Dijkstra and Hoare. All giants who influenced each other. The TI 990 system ran on the TX990 operating system, and also had a fantastic HW emulator called AMPL, governed by its own control language. All this stuff filled a small room, with its own cooling system. The computer box contained an air «absolute filter» for the huge disks. Also see [1].

So, when we in 1980 started with 8080 and PL/M-80 we bought a runtime system from NTH (Norges Tekniske Høgskole, later NTNU). It did have a task concept and it had semaphores and freepoolsemaphores, I recollect. I think the latter was a semaphore pre-associated with some storage. Thank you, Trond Børsting, who designed that SW. For sure, we never found any bugs in it, just as you had promised.

1983: MCS-48 and a simple scheduler in ASM

Some times development isn’t linear. In 1983 we went back to coding in assembly code for one of the next products, but this time using an assembler sw. No hand generation of hex codes any more. But the processor family was the same: MCS-48. This was in the fire detection system Autronica BS-30. We had now learned something about tasks. I therefore wrote a small runtime system, supporting a flavour of a task model. This product had one processor for the panel, and one on each of the extension boards. However, I remember that we had to set off a full year to fix and fix again and rewrite the code for that board. The panel, with the task concept, had to make task code and interrupts in some kind of system – contrary to the solution in the extension board. Like interrupts, they have to push and pop all used registers, but which registers are actually used when the interrupt appears? While the few error messages that did appear on the panel board appeared, the installations we had done were kept afloat until all was fine and we could update them all.

Fig.1 MCS-48 bank switching

The MCS-48 8035 version could only address 4k bytes. But our program used almost 16 kB. This time there was no JUMP or CALL across, so I had to do the bank switching by hand. My second encounter. I used the extra three banks for subroutine calls only. In my files I found the diagram that tells how I did this with JMP across the banks and two extra pins set out to address more of the external EEPROM. Scanned and available here. I had to unsolder a ring in the ring binder to scan it. It’s in Norwegian but it looks rather international to me. Its heading is «KRYSSING MELLOM 4K BANKER» = «Crossing between 4k banks». The return also was through a JMP back again. CALL and RETR were used while not doing the crossing. This was one of the reasons why all my tasks ran on the primary 0-4k bank, and that there was no context switch while a subroutine was running. The single-stack scheduler needed only to check the stack level to detect this. Since then I have discovered that this isn’t far from the concurrency model of JavaScript. I also used this scheme in RTX-51, I’ll come back to this. (Well, it’s actually a chapter in the RTX-51 document, here.)

1982: More Texas and tasking in Pascal

Then over to MPP Pascal again, and lots of signal processing. We used the TMS99105 16 bits processor, and a double-sided board I designed. I recollect that it also had a ground plane and a power plane, because we were talking about high speed. 24 MHz! I think was a four-layer board. We enjoyed MPP Pascal for all it was worth. This was for the Autronica GL-90 radar-based fluid level measurement system. (In April 2022 I even found a GLL-90 board on eBay for about one thousand dollars! Yes, it’s from Kongsberg now, they bought that part of Autronica around year 2000)

Then we did a MIP calculator (Mean Indicated Pressure) to calculate the delivered energy (in kW) and the condition of the rings on the pistons (plus plus), on very large diesel engines for ships. MPP Pascal again – and a TMS processor. This was Autronica NK-5.

1988: Modula-2 and Logitech RTK

Modula-2 Real Time Kernel by Logitech (external anchor) (Wikipedia: Modula-2‎)

if empty field, press to see

Fig.2 – Photo of the 5¼-inch floppy disk: MODULA-2 «Real Time Kernel» by Logitech. (A scan is here)

The Logitech Real Time Kernel was used for the main board of the Autronica BS-100 fire detection system. I saved this diskette from the waste bin at some time. The Modula-2 compiler was also by Logitech, see here. I have some about it in «CHANnels to deliver memory?» (CPA-2001) (via here).

Modula-2 had hooks for coroutines from the onset: «Modula-2 as defined by Wirth implements coroutines as part of the standard SYSTEM library. The procedure NEWPROCESS() fills in a context given a code block and space for a stack as parameters, and the procedure TRANSFER() transfers control to a coroutine given the coroutine’s context as its parameter.» (Wikipedia 29May2022: Coroutinehere).

There is more to it than the above. From the definition module of coroutines we have COROUTINE, INTERRUPTSOURCE, NEWCOROUTINE, TRANSFER, IOTRANSFER, ATTACH, DETACH, IsATTACHED, CURRENT, LISTEN, PROT ([2]). This is quite elegant!

1988: MCS-51 and a simple scheduler in PL/M-51

The next project I was set to work on was the loop controller BSU-50 for the Autronica BS-100 fire detection system. I think we started in 1986 or 87 – but we released it in 1988. Then a fix in 1990. These were PROM’ed MCS-51 microcontrollers. This is what this note started up with. We’ve come to the main theme.

Much about this is also described in Notes from the vault – 0x03 – Two early Autronica VLSI chips. These chips were used across both for the BS-30 and BS-100 fire detection systems

The RTX-51

Description

My original 1988 paper about the RTX-51, uploaded to my private home page in 2011 is referenced here. In that reference these pages are linked up: HTML and PDF (25 MB searchable). I have corrected «excutive» here:

Real-time executive for 8051-type single-chip microcomputers
Author  : 0yvind Teig. 
Date    : 26.09.88 
Address : Autronica A/S
        : P.O.Box 3010, N 7001
        : Trondheim, Norway
        : Telephone: 47 7 918080

Flow diagrams and source code

Some flow diagrams and the source code is available at rtx-51 PL/M-51 listing Autronica 1988 Øyvind Teig (18.6 MB PDF). Even if this code is still running at lots of fire detection locations, the copyright should be outdated. 9Aug2022 minus 4Nov1988 is almost 34 years. In the spirit of Notes from the vault – 0x03 – Two early Autronica VLSI chips, in my view, the importance of keeping some history rather than letting it completely disappear, is rather important. The first page goes like this:

PL/M-51 COMPILER
    DOS 3.30 (038-N) PL/M-51 V1.2
    COMPILER INVOKED BY: C:\MCS51\PLM\PLM51.EXE RX51-080.PLM
                  $  optimize (3)
                  $  debug
                  $  symbols
                  /*
Autronica A/S.
Realtime executive for MCS51.

Observe        : The author does not guarantee that this program is free from
               : error. However, every attempt has been made to make it error-
               : free. In case an error is found, the user MUST report to the
               : original author.
Parts          : 1. Introduction and user part of RX51.
               : 2. Kernel part of RX51.
               : 3. User part of RX51.
               : 4. Power-up part of RX51.
               : 5. Compiler appendix.
Copying        : No copying to a third part. All copying via original author
               : COPYRIGHT (C) 1988 BY AUTRONICA
Used in        : BSU-50.
Orig. author   : Øyvind Teig.

This file      : rx51-nnn.plm (nnn: see next page)
Files          : A. rx51-nnn.plm -> this file.
               : B. note-nnn.inc -> included in this file. (PcWrite 2.71 file size max. is 60 K)
               : C. rx51-nnn.inc -> must be included in user process files.
               : D. rxiv-nnn.asm -> interrupt vectors and interrupt return.
PUBLICS        : No PUBLIC vars, EXTERNAL vars must be PUBLIC in user file.
Text editor    : PCWRITE 2.71. PLM list file through PR.
non-ascii      : Alt E (heart)           : Is carriage return and boldface.
               : Alt B (face)            : Is boldface.
               : Alt G dot R colon alt C : Is compressed print mode (top of this page).
Ruler files    : in directory pcwr
nnn next page  : Version of this file.
                 */

Epilogue

I guess I’ve come to the end of this note. I have described how we learnt about the task concept, and referred to the original documents of the RTX-51.

After this we used occam on transputers for some years. When we didn’t have the transputers any more, we had occam translated to C to run on a Texas DSP. This was done with the Southampton Portable occam Compiler (SPoC).

This note does not discuss the CHAN_CSP and ChanSched schedulers I wrote at work after 2000. (The latter was in cooperation with a colleague). I have already documented this some, see f.ex. New ALT for Application Timers and Synchronisation Point Scheduling.

After I retired in 2017 I have worked with XMOS and programmed in xC. It certainly has a task concept built into the language. See My XMOS pages. But now I guess I’ll have to go back to task by C library lib_xcore. See C plus lib_xcore black-boxes xC. As I said, history isn’t always linear, is it?

References

Wiki-refs:

  1. 990 Computer Family Software by Texas Instruments, see http://s3data.computerhistory.org/brochures/ti.990.1977.102646120.pdf – at the Computer History Museum (CHM, California) pages
  2. Modula-2 reference, see www.modula2.org/reference/isomodules/isomodule.php?m=COROUTIN.DEF
  3. PL/M on Wikipedia, see https://en.wikipedia.org/wiki/PL/M