In my day job, I develop electronic systems, many of which have embedded microprocessors. The prototype or production systems need to be tested in both the prototype/development phase and during production at the manufacturing plant. These tests can be anything from “does this button work?” to “is the noise on this power rail below 50mV?”. In both cases, software on the system itself and an external PC is used to drive the tests. The external PC is the master controller and the system-under-test responds to command from the PC.
The commands sent from the PC are pretty simple: “pull this pin high/low” or “produce a sine wave on this DAC output”. So simple, in fact, that developing testing firmware for each product seems superfluous. There are, however, always specific tests unique to one product which means that, in practice, every product has its own testing firmware that has to be written an maintained.
In an attempt to reduce the workload of developing the testing firmware, I looked around for a more generic approach to writing testing software. I hope I’ve found a solution in Forth.
Wat is Forth?
Forth is a stack-based extensible programming language and virtual machine invented by Charles Moore. A complete Forth system also has an interpreter through which programs can be interactively created, much like the BASIC interpreter on early personal computers.
The advantage of Forth is that most of the Forth system is programmed in a small subset of Forth itself, making it largely self hosted. This means that a Forth system can be created with modest effort, even in assembly language. In fact, this was one of the primary goals of the system — to be able to get a system up and running quickly when no other compilers or languages are available.
Nowadays, C compilers are ubiquitous and it might seem that there is no need for systems like Forth. However, Forth has one big advantage over compiled code: it is interactive.
In an automated hardware test setup, the interactivity is used by the external PC to control the device under test (DUT). This way, the test engineer can create, add or change test procedures without having to change the software running on the DUT — at least, that’s the idea!
The Forth system has two stacks: a data stack and a return stack. The data stack is by far the most important stack and is therefore referred to as the stack.
Forth commands, also called words, reside on the data stack. When a word is executed, the Forth virtual machine puts the next command’s address on the return stack. When the command has been executed, it pops the address from the return stack and continues executing the next command. The return stack is also used to store the parameters of do..while loops.
Say we want to add two numbers 123 and 456. In Forth this is achieved by entering:
123 456 +
The numbers 123 and 456 are pushed onto the stack first, followed by the forth word ‘+’. The virtual machine pops the first word off the stack, which is ‘+’ and executes it. In turn, the ‘+’ word pops two numbers from the stack, in this case 123 and 456, and adds them together, pushing the result onto the stack.
A Forth system has a number of primitive words. The actions associated with these words have been hard-coded into the virtual machine. Some do simple data or return stack manipulation, while others perform arithmetic operations or print data to the console.
A Forth system is extensible by defining new words, each of which are made up of words that have already been defined. These new words are added to the Forth dictionary.
For hardware testing, it makes sense to have primitive words for low-level functions such as configuring pins, reading from and writing to memory addresses, and writing to a debug UART. More high-level functions will be defined interactively to give the test engineer maximum flexibility whilst keeping the development effort of the Forth system to a minimum.
<to be continued>