Starting Forth on an STM32F1 Feb 2016

Here is what we’re after, as Forth Development Environment (would that be an “FDE”?):

There are a number of steps needed to use Mecrisp-Stellaris Forth in your own projects (for these articles, we’ll be focusing on the STM32F103 µC series with 64..512 KB flash memory):

  1. getting the Mecrisp core “flashed” onto the microcontroller
  2. setting up a convenient connection between your laptop and the µC board
  3. streamlining the iterative coding cycle as much as possible

Note that this is in some way quite similar to hooking up an Arduino or JeeNode, and developing software for it through the Arduino IDE. But there also some substantial differences:

The Arduino approach puts all complexity in the “host” laptop setup. The Mecrisp approach builds words in the µC, on the fly, when they’re typed in (or uploaded, i.e. “simulated typing”).

Installing Mecrisp

Step 1) is not Mecrisp-specific. It’s the same stumbing block with every µC setup which needs specific firmware. You need to download the latest Mecrisp-Stellaris release from SourceForge, and “get it onto that darn chip… somehow” !

Here are some ways to do this, depending on what interface tools you have and your O/S:

The firmware in the Mecrisp distribution is available in two versions, a “.bin” and a “.hex” file:

stm32f103/mecrisp-stellaris-stm32f103.bin
stm32f103/mecrisp-stellaris-stm32f103.hex

It depends on the upload mechanism as to which one you need. With a Black Magic Probe (BMP) and arm-none-eabi-gdb, for example, the following commands should do the trick:

% arm-none-eabi-gdb
[...]
(gdb) tar ext /dev/cu.usbmodemD5D1AAB1    (adjust as needed, of course)
(gdb) mon swdp
(gdb) at 1
(gdb) mon erase                                (essential for Mecrisp!)
(gdb) load mecrisp-stellaris-stm32f103.hex 0x08000000
(gdb) q

Then, again if you are using a BMP and running on Mac OSX or Linux:

% screen /dev/cu.usbmodemD5D1AAB3 115200
Mecrisp-Stellaris 2.2.1a for STM32F103 by Matthias Koch
  ok.
(quit with "ctrl-a ctrl-\" or "ctrl-a \" - depending on your setup)

The serial connection must be set up as 115200 Baud for Mecrisp - 8 bits, no parity, 1 stop bit.

If you’re using an ST-Link to upload the firmware, these two commands will do the trick:

st-flash erase                                # essential for Mecrisp!
st-flash write mecrisp-stellaris-stm32f103.bin 0x08000000

It’s very simple and quick, but only · a f t e r · you’ve got all those Pesky Little Details just right. Getting firmware onto a bare STM32F103 µC can still be a hit-and-miss affair. There are simply too many variables involved to come up with a procedure here which will work for everyone.

The good news is that with a little care, you will not have to repeat this step again. Mecrisp is quite good at keeping itself intact (it refuses to re-flash itself, for example).

Installing PicoCom

One of the things you’ll notice if you try out the above setup with screen, is that it doesn’t quite get the line endings right (which are bare LFs in Mecrisp, not CR+LF). It’s better to install a slightly more elaborate terminal emulator - and PicoCom is in fact a very good option for Mac OSX and Linux, as will become clear below. For Windows, there is TeraTerm.

To install PicoCom on Mac OSX with Homebrew, enter this in a command shell:

brew install picocom

To install PicoCom on Debian/Raspbian/Ubuntu Linux, type:

sudo apt-get install picocom

The benefit of PicoCom is that it allows specifying a program to use for uploads. We don’t want to manually enter text, we also need to send entire source files to Mecrisp Forth over serial. The problem is that a bare Mecrisp installation only supports polled serial I/O without handshake. This can only handle text if it’s not coming in “too fast”. In Mecrisp, each word on a line needs to be looked up and compiled, and it all happens on a line-by-line basis. This means that you have to wait for its “ok.” prompt after each line, before sending more text.

One solution is to send all text · v e r y · s l o w l y · but that’ll make it extremely time-consuming.

Installing msend

A better solution is to send full speed and wait for that final prompt before sending the next line, to avoid input characters getting lost. This little utility has been created to do just that: msend.

If you have Go installed, getting msend (Mac OSX and Linux only, for now) is again a one-liner:

go get github.com/jeelabs/embello/tools/msend

Otherwise, you can get the latest binary release for a few platforms from GitHub.

With “msend” installed, PicoCom can now be started up as follows:

picocom -b 115200 --imap lfcrlf -s msend /dev/cu.usbmodemD5D1AAB3

Or even as “mcom /dev/cu.usbmodemD5D1AAB3” - if you add an alias to your .bashrc init file:

alias mcom='picocom -b 115200 --imap lfcrlf -s msend'

And now line endings not only work properly, you also get a very effective upload facility. This will be worth its own article, but you can see a transcript of an upload with includes over here.

Sending a file with PicoCom is triggered by typing “ctrl-a ctrl-s”.

To quit PicoCom, type “ctrl-a ctrl-x” - see also the manual page for further details.

Windows

Neither PicoCom nor msend are available for Windows, but there’s another solution:

This combination should accomplish more or less the same as picocom + msend, i.e. terminal access, throttling text sends, and inserting “include” files.

Optimising workflow

Forth software development is about flow and insanely fast turnaround times between coming up with an idea and trying it out. There are no compilers or other tools to slow you down, and as a result you can type and try out an idea the moment it pops into your head. Total interactivity!

At the same time, the last thing we want, is to constantly re-enter code, let alone lose it for good if the µC crashes. The challenge is to find a proper balance between volatile commands (typed in directly at the Mecrisp prompt, on the µC) and re-sending lots of text from a laptop all the time.

Mecrisp has an elegant and simple approach to help with this:

The thing is that in Mecrisp Forth, a hard crash is no big deal - you should expect to run into stuck code, awful crashes, weird things happening, non-responsive terminal I/O, etc. There’s a reset button on the µC which will get you back to a working state the (sub-) second you use it.

It could be a typo. There could be a hint in what’s on the screen. But even if not, if you make your coding cycles short and frequent, then chances are that you’ll quickly discover what went wrong.

Otherwise… the interactive Forth prompt is your friend: examine the values of variables, or the settings in hardware registers, and invent whatever words you need to help figure out this issue. Words can be one-liners, written only for use in the next few minutes of your investigation!

The more loosely coupled your words are, i.e. called in sequence, not nested too deeply, the easier it will be to set up the stack and call any one of them, in isolation, from the prompt. If something fails, you can take over and repeat the rest of the words by hand, verifying that the stack is as expected (check out the “.s” word!), and peeking around to see what’s going on.

Looking at the diagram above, you’ll see that there are two kinds of permanence in this context: source code in files, and words defined in flash memory. The latter cannot easily be turned back into source, alas. That means they should be either one-offs or created by an earlier upload.

Although the best workflow has yet to be found, some comments on what is likely to work well:

Maybe the rlwrap tool can be made to work with PicoCom - for command history and editing.

There is a lot more to say about this. The “msend” utility recognizes lines starting with the word “include” as special requests to fetch a file from the system and send its contents (this can be nested). This allows keeping various word sets in their own files, and then selectively include them in each project. You can add “compiletoflash” to save the more stable words in flash.

For more ideas on how to organise the code, see the README in the Embello area on GitHub.

There is no need for large nested source file trees. Forth source code tends to be very compact - a single page of code is usually more than enough to implement a complete well-defined module. One directory with a few dozen files is plenty. Put them under source code control in GitHub or elsewhere, and you’ll have your entire project under control for the long-term. Each project can contain all the files it needs to be re-created (i.e. re-uploaded to a µC running Mecrisp Forth).

Enough for now, this’ll get you started. Now go Forth, and create lots of embedded µC projects!

Weblog © Jean-Claude Wippler. Generated by Hugo.