I recently discovered two very interesting historical (and, I suppose, historic) Forth documents:
- the NRAO FORTH manual for the PDP-11, written by Elizabeth Rather and Chuck Moore
- the technical manual and source code for the RCA 1802 version of microFORTH, courtesy of FORTH, Inc.
The NRAO manual, written in 1974, contains a very concise but readable (and even “friendly”) introduction to Forth, and a detailed description (with some code in the appendix) of the PDP-11 assembler. Forth assemblers have a certain “flavor”, and this description captures it well.
The microFORTH source code, circa 1978, should be read in conjunction with the 1802 datasheet. Curiously, this chip is still available from Renesas in a ceramic 40 pin DIP suitable for “harsh environments”! (Renesas acquired Intersil, whose name is still on the datasheet.)
microFORTH includes a cross-compiler, which is extensively documented in the accompanying technical manual. This is one of the darkest corners of Forth, and is something I care deeply about. Cross-compilation is the sole raison d'être for muforth. I haven’t studied the microFORTH code closely, but I hope to learn something from it. The cross-compilers in muforth are all slightly different from each other, and none of them feels quite “right”.
FORTH, Inc also published a paper proposing a cross-compilation “standard” for Forth and an accompanying glossary.
After re-reading these, I tried a few experiments with muforth, to apply the idea of “scopes” to one of the cross-compilers. I had very mixed results and have shelved the investigation for now.
After that, I started thinking about getting muforth to run under UEFI, and re-researched and re-read everything I could. Before I got too far along – I think I was reading the PE32+ image file specification and trying to follow along in the tianocore/EDK2 code – I had to shelve that as well! UEFI kind of makes my stomach churn, and tianocore/EDK2 seems way too complicated. I still think that using muforth to explore UEFI is an interesting idea, and I’m sure I will return to it, but part of me hopes that something else – maybe LinuxBoot? – will win the firmware wars.
I’m sitting at home here in Calfornia, on voluntary lockdown to slow the spread of corona virus (COVID-19). It’s a scary time, and because I am stuck at home, it seemed like a good time to think about, write about, and work on muforth. What else am I going to do?
I’ve been thinking a lot recently about which platforms (targets) I want to focus on. muforth is a bit scattered; there are a bunch of targets that have just the bare beginnings of support (eg, PIC18), others that have working Forth kernels but no real hardware support (eg, Cortex-M and RISC-V), and one that has been incredibly useful even though I never finished the Forth compiler (Freescale HCS08).
My desiderata for targets are the following:
- a target architecture that is simple and approachable for people new to microcontrollers AND
- EITHER chips available in DIP form factor for easy breadboarding and experimenting, OR very inexpensive boards ($20 or less) available, ideally from the silicon vendor
The ideal is that someone could get started exploring and hacking using only the chip or board and muforth. No other software or programming tools should be necessary.
Unfortunately, very few microcontrollers are available in DIP any more. It used to be that a number of S08 parts were avaialable in DIP packages. While a few still are, they are generally small and underpowered. The S08 also requires an external programmer of some kind to get boostrapped. The chips arrive from the factory totally blank.
TI’s MSP430 has a few DIP members too. I’ve had success getting the MSP430G2553 working. It’s a bit of a pain, but using the BSL (bootstrap loader) it’s possible to get my serial chat code burned onto the chip.
The most promising targets available in DIP are from Microchip. In particular, the PIC18, PIC24, and PIC32 variants. The PICs are all interesting because they are very inexpensive, and several parts have a built-in USB interface. (I’m all about connecting to microcontrollers via USB, since it’s all we have on modern machines, and having control of the USB conversation, by having some kind of custom “USB chat code” running on the chip, can make things much easier too.)
The PIC18 is a bit limited, and is an 8-bit part. The PIC24, while a bit more expensive, runs faster and has more power – it’s a 16-bit processor. The PIC32 is an interesting beast: it’s actually a MIPS32 core! In a DIP! For a few dollars! Could be an interesting adventure.
All these Microchip parts have a downside, however: they all require an external programmer for bootstrapping. I’ve successfully used my JS16 USB board to do this, and I have a PICKit in a box somewhere. But it’s not possible for someone to simply breadboard a chip and start hacking, with no external hardware.
Boards from silicon vendors have the advantage that they have a built-in debug/programming interface. Of course, these are usually terrible, and I try to stop using the interface as soon as possible – by writing and flashing some kind of “chat” program. As an example of terrible, the USB-serial interface that is part of the “ezFET” debug interface on the MSP430FR6989 Launchpad is very badly implemented: it has such high turnaround latency that any protocol with a lot of back-and-forth (such as my serial chat protocol) becomes very slow. Even though the connection is 115,200 bps, it ends up feeling more like a 2400 baud modem. Pulling off the jumpers that connect the ezFET to the MCU and patching in an external USB-serial device – such as a Prolific PL2303 or an FTDI 2232 – dramatically increases the snappiness of the interface. So it is absolutely the fault of the ezFET and not something to do with the host machine’s USB implementation.
My very simple USB chat – implemented on the S08JS16 in fewer than 512 bytes of code! – uses a handful of vendor-specific USB control requests to read and write memory, program the flash, and execute code. It has none of the latency problems of TI’s USB serial interface. It is the main reason why I keep looking for target chips with built-in USB. My ideal is to use the vendor’s debug interface exactly once: to program my own serial or USB chat code, and then ignore the vendor’s interface thereafter.
What interesting and inexpensive boards are available from vendors? And which vendors are we interested in supporting?
This latter question arises from my experience of watching NXP destroy the microcontroller lines they “inherited” when they absorbed Freescale. I am thinking of the HCS08 and Kinetis lines here.
In the case of the HCS08 – a huge personal favorite of mine, for lots of reasons – they seem to be burying it. They are not announcing much activity or new parts. They have also tripled prices, making the parts very unattractive for new users. Generally it seems like they just want the HCS08 to go away.
The Kinetis parts – which were very aggressively priced at their introduction, strongly competing with the HCS08 – are also more expensive now, as are the FRDM boards.
The Cortex-M0+ based Kinetis L is a sort of cousin to the HCS08. In particular, the peripherals are mostly the same 8-bit peripherals as on the HCS08. I was excited about this because the KL25 – the chip on the original FRDM board, the FRDM-KL25Z – has a USB interface on-chip that is a superset of the USB interface on the S08JS16. I had high hopes – still unrealized – of writing USB chat code for this board – which, as I have documented elsewhere, has a truly terrible debug interface that is better avoided.
If we were to give up on NXP, but still want to explore the (very popular) world of Cortex-M parts, where should we turn?
Even though they also have a terrible on-board debug story (see? it’s true everywhere), I have been making an effort to support ST Micro’s STM32 parts. I love the variety of Discovery boards that they offer, and all of them are still very aggressively priced. Because they have on-board ST-LINK (their debug interface) it’s possible to simply plug one into a USB port on your Linux, BSD, or OSX machine, fire up muforth, and say hello.
Two of the Discovery boards in particular – the STM32F072B-DISCOVERY and the STM32F3-DISCOVERY – sport chips with a built-in USB interface, so it should be possible to use the ST-LINK to write and debug custom USB firmware, and then program this onto the board. In fact, ST’s chips with USB interfaces support DFU (device firmware upgrade) over USB in ROM, so it’s in theory possible to plug in a brand-new Discovery board, fire up muforth, and immediately flash the USB chat firmware – completely ignoring the ST-LINK. (Of course, I still have to write the USB chat firmware. And I have to write an interface to the DFU code, but it’s pretty simple and well documented.)
The STM32F072 Discovery costs $10, and the STM32F3 Discovery costs about $15. This is a perfect price point for a classroom setting, or for impoverished students. Since muforth is free, and since using it requires no vendor software, it’s a great way to get started. ;-)
The Cortex-M ARM world is a bit complex for beginners, though. Is there something that is a bit simpler?
Since I first started working with it in 2008, I have remained a huge fan of the Freescale HCS08 – one reason it is so frustrating that NXP is basically burying it. The HCS08 is descended from the 6800, and anyone who is a fan of this kind of architecture will recognize the lineage. While rather register-starved – in particular, having one stack pointer and one index register – putting Forth onto the HCS08 is a challenge, but I figured out an elegant approach.
I have used various HCS08 parts – the S08QG8, S08QE32, and S08JS16 – to program other S08 parts, and also to program AVR and PIC18 parts. It’s very simple and a lot of fun.
The Forth support in muforth is limited, however. I have mostly been using muforth to program the S08 in assembler.
There is a curious architecture which lies between the S08 and the Cortex-M parts: TI’s MSP430.
This is a 16-bit microcontroller family that is strongly reminiscent of the PDP-11 and 68000. In particular, it has really nice auto-increment addressing modes, making writing an indirect-threaded Forth almost trivial. The instruction set – as long as you limit yourself to the pure 16-bit instructions and ignore the CPUX extensions – is very simple and easy to understand. It was an easy task to write an assembler, disassembler, and Forth compiler for this architecture, and I think it would be a nice introduction to the world of microcontrollers.
Having originally targeted a breadboarded MSP430G2553 (using the horrible BSL to get my chat code flashed onto it), I have since added support for the MSP430FR6989 (because of a Launchpad board that supports it). But I recently discovered an even better option: the MSP430F5529. This also has a Launchpad board, and this chip is distinguished by its on-chip USB support. Like the STM32 Discovery boards, it should be possible to write a simple USB chat and flash it onto the chip. Avoiding the broken ezFET debug interface on these boards is a high priority!
The MSP430F5529 Launchpad costs about $13 from TI. It might be the sweet spot of approachability for newcomers to microcontrollers, Forth elegance, and cost.
Read the 2018 journal.