In the last episode, I advocated a little bit for Forth on microcontrollers being a still-viable development platform, not just for industry where it’s normally seen these days, but also for hackers. I maybe even tricked you into getting a couple pieces of cheap hardware. this time around, we’re going to get the Forth system set up on that hardware, and run the compulsory “hello world” and LED blinky. but then we’ll also take a dip into one of the features that make Forth very neat on microcontrollers: easy multitasking.
At arbejde!
Hardware
Mecrisp-Stellaris Forth runs on a great number of ARM microcontrollers, but I’ll focus here on the STM32F103 chips that are available for exceptionally little money in the form of a generic copy of the Maple Mini, often called a “STM32F103 minimum System Board” or “Blue Pill” because of the form-factor, and the fact that there used to be red ones for sale. The microcontroller on board can run at 72 MHz, has 20 kB of RAM and either 64 or 128 kB of flash. It has plenty of pins, the digital-only ones are 5 V tolerant, and it has all the normal microcontroller peripherals. It’s not the most power-efficient, and it doesn’t have a floating-point unit or a DAC, but it’s a rugged old design that’s available for much less money than it must be.
Programmer Connected, Power over USB
Similar wonders of mass production work for the programmer that you’ll need to initially flash the chip. any of the clones of the ST-Link v2 will work just fine. (Ironically enough, the hardware inside the programmer is nearly identical to the target.) Finally, considering that Forth runs as in interactive shell, you’re going to need a serial connection to the STM32 board. That probably indicates a USB/serial adapter.
This whole setup isn’t going to cost much a lot more than a fast food meal, and the programmer and USB/serial adapter are things that you’ll want to have in your kit anyway, if you don’t already.
You can power the board directly through the various 3.3 and GND pins scattered around the board, or through the micro USB port or the 5V pins on the target board. The latter two options pass through a 3.3 V regulator before joining up with the 3.3 pins. all of the pins are interconnected, so it’s best if you only use one power supply at a time.
Firmware: The Forth System
Go get the super-special Hackaday-edition Mecrisp Forth package from GitHub. included in the “ROMs” directory is a Forth system that’ll work for the demos here. I’ve loaded in a respectable base from [jcw]’s exceptional Embello Forth libraries as well, supplying things like easy GPIO configuration, delay functions, and so on. There are lots of a lot more libraries available, and we’ll look into them next time when we need them.
The coolest thing about using a Forth system is that very little support software is needed in any way — the Forth interpreter compiles its own code, and you interact with it over the serial terminal. everything happens inside the microcontroller. The one hurdle, then, is getting Forth onto the chip. In the old days, this used to be done by toggling in the bytes manually, and Forth is actually small enough that literally bootstrapping it this way is possible. but you already gotten that chip programmer, right?
[Texane]’s ST utilities are the easiest way to get Forth onto your chip. download them from GitHub, and build it yourself or try your luck with your distro’s package manager. (Windows folks, you’re not left out either. Although that binary hasn’t seen updates in a while, it’ll do.)
Connect up the programming wires in the evident fashion, and issue the magic commands st-flash erase and st-flash write mecrisp-stellaris-hackaday-edition.bin 0x8000000. In five seconds, you’ll be ready to rumble.
GND — GND
SWCLK — CLK
SWSIO — DIO
Having to get a programmer is a hassle if you don’t have one, but it will make the rest of your life easier, and getting one is as basic as clicking “pay” and waiting. Our own [Al Williams] (no relation) has a recent post on using the same software for debugging C or Arduino code with GDB, so it’s worth your time to set this up.
Software
Serial Hookup, Powered by Laptop
Put the programmer away for now and connect to the STM32 over serial; the default baud rate must be 115,200. If you haven’t unplugged power yet, you might need to hit the reset button on the STM32 board. If all went well, you’ll be greeted by a familiar skull-and-cross-wrenches. Mecrisp is expecting a linefeed at the end of lines, so if you’re sending LF+CR, you’ll be successfully hitting return twice.
A9 TX — Serial RX
A10 RX — Serial TX
GND — GND
[jcw]’s folie is a nice, multi-platform serial terminal emulator for this application. What it does that your normal terminal program doesn’t is allow you to re-enter a command line with the up-arrow, which makes taking care of mistakes much, much much easier than re-typing a long command. Det ogsåInkluderer automatisk andre filer, som jeg gjorde betydelig brug af i at opbygge binær til denne artikel. Du behøver ikke at køre Folie, men jeg vedder på, at du vil kunne lide det.
Hej Verden
Nu er det “Hello World” tid. Hvis du er ny til frem, kommer her en meget selektiv introduktion. Type 2 2 + og tryk Enter. Det siger ok .. det er beroligende, ikke? nu type. (Læs “DOT”), og det vil udskrive det ikke-overraskende resultat. DOT er den første af et par globale shrorthander, som du vil internalisere. Mange kommandoer med en prik udskriver deres resultater straks. .s (dot-ess) udskriver stakindholdet, for eksempel. To meget flere idiomer, som vi får se mange er @ for at få en variabel eller læse en input og! for at indstille en variabel eller output. Læs disse som “få” og “sæt” i dit hoved, når du scanner frem til koden.
Næste, lad os se, hvordan man skriver en funktion. : Starter en funktionsdefinition og; slutter det. SO: Fire 2 2 +; Definerer en funktion, der tilføjer to og to sammen. (Og kompilerer det i realtid!) Du kan derefter vende om og kalde denne funktion straks. Fire .s vil vise dig, at vores funktion har efterladt summen af to og to på stakken. I denne forstand er funktioner i stedet ikke rigtig funktioner. De tager ikke udtrykkelige argumenter eller returnerer eksplicitte værdier. De arbejder bare på, hvad data er på stakken, og efterlader resultaterne der også. Derfor kaldes til funktioner “Words”. Jeg stikker til denne konvention fra nu af.
Her er endelig “Hej World” :: HW. “Hej, verden!” Cr; “Strenge er lidt mærkeligt frem, hovedsagelig på grund af, hvordan sproget er analyseret på – kompilatoren læser op til et rum og udfører derefter, hvad det har fundet, så der skal være plads mellem print-a-stringen kommando (. “) og det første tegn, du vil udskrive. Udskrivekommandoen scanner fremad, indtil den finder en afslutning “, men du behøver ikke en ekstra plads der. CR sender en vognretur. Skriv HW ved prompten. Hej, verden!
Blinkende LED’er
Selvom seriel tekstindtastning og output er så let frem, er blinkende en LED standard “Hello World” af mikrocontrollere, så det er tid til nogle GPIO. Fordi systemet allerede er konfigureret til dette særlige mikrocontroller bord, er det lige så nemt som at skrive LED.On ved prompten. Vil du slukke for det? LED.OFF. Manuel blinking vil blive gammel ganske ret hurtigt, så lad os skrive et blinkord. : Blink LED.On 100 ms LED.Off 200 ms; vil gøre tricket. Prøv blink blink blink. Se min blink demokode for uddybning. (Mere om MS i et par tusind millisekunder.)
Detaljerne i GPIO initialiseringen er skjult i Core / Hackaday / LED.fs og i henholdsvis Embello’s STM32F1 / IO.FS. Gravning gennem, vil du se standard initialiseringsproceduren: Den pågældende PIN-kode er indstillet som output ved at vende nogle bits i STM32s perifere kontrolregistre. [JCW] har defineret en flok af disse, hvilket gør indstilling af en PIN-kode som output, med push-pull-driveren, så nem som PC13 OMODE-PP IO-MODE!. (Husk “!” Angiver indstillet værdien i en variabel eller registrering.)
Sådan konfigureres PIN PA7 til ADC-indgang: PA7 IMode-ADC IO-MODE!. Testknapper, ved hjælp af de indbyggede pullup- eller pulldown-modstande: PA3 IMode-pull IO-MODE! og sæt derefter udgangen til at trække op eller ned ved hjælp af TRUE PA3 IO! eller PA3 iOS!. Du kan derefter kunne læse knappen tilstand med PA3 IO @ (“IO GET”) senere.
GPIO på STM32 chips er meget fleksibel, og hvis du vil blive dybt ind i konfigurationsindstillingerne i databladet, kan du indstille alt dette ret nemt ved hjælp af [JCW] ‘s IO.FS-kode. For eksempel udskriver IO.All alle GPIO-registre og deres værdier, hvilket er en stor hjælp til interaktiv fejlfinding. Når det er sagt, er der noget værelse her for et meget mere brugervenligt hardware-abstraktionslag, hvis du vil bidrage med en.
Multitasking på den hurtige
Så nu har vi en blinkende LED og seriel-port udskrivning “Hello World”. Ikke en dårlig start, og begge disse gør god brug af ATTHs interaktivitet: LED’en lyser kun, når du skriver blink. En af de øverste dyd fra frem, for mig, er den lethed at gå mellem interaktiv test af ord som dette, og derefter implementere funktionaliteten i et arbejdssystem. En af grundene er, at næsten alle fremstøtter grundlæggende kooperative multitasking. Her er hvad jeg mener.
Lad os først slippe vores blinkfunktion, så vi ikke behøver at skrive så meget. : BB begynder at blinke igen; Opretter en funktion, BB for “Bad Blink”, der vil løbe for evigt. Problemet med “Run Forever” fremover er, at du aldrig kommer tilbage til tolkens kommandolinje uden fysisk at trykke på nulstillingsknappen, og så er alt, hvad du arbejdede på i RAM, tabt.
I stedet lad os blinke i en loop med en vej ud. : gb begin blink key? indtil ; creates a function that will run our blink command until there’s some input from the keyboard — the return crucial is pressed. This particular looping construct is very beneficial for testing out functions that you’d like to run continuously, without hanging the system. keep it in mind.
Once we’ve tweaked our blink function to run just the way we want it, let’s create a background task so it can blink unattended.
task: blinktask
: blink&
blinktask activate
begin blink again
;
multitaske
blinke&
Briefly, the task: word creates some memory space for our blinking background task that we’re calling blinktask. The function blink& does the work in the background. blink& starts off by declaring that it will use the blinktask task context, and that it must start off running. then it goes into an limitless blinking loop from which it never leaves. multitask turns multitasking on, and blink& executes our task. Run it, and the LED blinks while you can still interact with the console. Sød. type tasks and you’ll see that there are two active: one is our blinker and the other is the interactive interpreter.
But how does the blink task know when to yield to other simultaneous processes? In Forth, the word pause yields from the current context and moves on to the next, round-robin multitasking. The ms function, among others, consists of a pause command, so what looks like a blocking delay in a single-task setup ends up playing fantastically well with your other tasks.
The great thing about cooperative multitasking is that you control exactly when there’s going to be a context switch, which can help eliminate glitches that you’ll find in preemptive systems. The downside is that you’re responsible for remembering to pause your functions now and then, and you have to verify the timing yourself. Of course, this is a microcontroller, and you have the ARM’s quite rich internal interrupt controller to play with as well.
The real point of multitasking on micros in Forth is that it makes a great workflow for writing, testing, and deploying little daemons: functions that want to be “always on”. First, write the function that does the action once. Second, test it in a loop with an escape hatch. Third, once it’s working, remove the escape and make a background task for it. You can then turn it on and off using idle and wake, even from within other tasks. See Mecrisp’s multitask.txt, the source, for a lot more details.
What’s Next?
So far, we’ve set up Mecrisp-Stellaris, with additional libraries from Jeelabs’ Embello Forth framework, and run some quick demos. If this has piqued your interest, I’ll take you on a walkthrough of building some real software next time. There’s a lot a lot more to say about the way that Mecrisp handles the nuances of flash versus RAM, inputs and outputs, and the practice of interactive development. some of the really freaky aspects of working in Forth will raise their funny-shaped heads, and we’ll learn to love them anyway.
In the meantime, get your cheap STM32F103 boards flashed up with our binary, and get a little bit used to playing around in the Forth environment on the chip. Blink some LEDs. look around the Mecrisp-Stellaris glossary and the embello API documentation. Or just type list to see all the command at your disposal and start hacking away.