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.
לעבוד!
חוּמרָה
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.
תוֹכנָה
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. זה גםautomatically includes other files, which I made substantial use of in building the binary for this article. You don’t need to run folie, but I bet you’ll like it.
שלום עולם
Now it’s “Hello World” time. If you’re new to Forth, here comes an very selective introduction. type 2 2 + and hit enter. It says ok.. That’s reassuring, right? now type . (read “dot”) and it will print out the not-surprising result. dot is the first of a few global Forth shorthands that you’ll want to internalize. a lot of commands with a dot print out their results immediately. .s (dot-ess) prints out the stack contents, for instance. two a lot more idioms that we’ll see a lot of are @ for getting a variable or reading an input and ! for setting a variable or output. read these as “get” and “set” in your head when scanning Forth code.
Next, let’s see how to write a function. : starts a function definition and ; ends it. So : four 2 2 + ; defines a function that adds two and two together. (And compiles it in real time!) You can then turn around and call this function immediately. four .s will show you that our function has left the sum of two and two on the stack. In this sense, functions in Forth aren’t really functions. They don’t take explicit arguments or return explicit values. They just operate on whatever data is on the stack, and leave the results there too. That’s why Forth functions are called “words”. I’ll be sticking to this convention from now on.
Here, finally, is “Hello World”: : hw .” Hello, World!” cr ;” Strings are a little odd in Forth, mainly because of the way the language is parsed — the compiler reads up to a space and then executes what it has found, so there has to be a space between the print-a-string command (.”) and the first character that you want to print. The print command scans forward until it finds a closing “, though, so you don’t need an extra space there. cr sends a carriage return. type hw at the prompt. Hello, World!
Blinking LEDs
Even though serial text input and output is so easy in Forth, blinking an LED is the standard “hello world” of microcontrollers, so it’s time for some GPIO. because the system is already configured for this particular microcontroller board, turning an LED on is as easy as typing led.on at the prompt. want to turn it off? הוביל את. manual blinking will get old pretty quickly, though, so let’s write a blink word. : blink led.on 100 ms led.off 200 ms ; will do the trick. try blink blink blink. See my blink demo code for elaboration. (More on ms in a few thousand milliseconds.)
The details of the GPIO initialization are hidden in core/Hackaday/LED.fs and in Embello’s stm32f1/io.fs respectively. Digging through, you’ll see the standard initialization procedure: the particular pin is set as output by flipping some bits in the STM32’s peripheral control registers. [jcw] has defined a bunch of these, making setting a pin as output, with the push-pull driver, as easy as PC13 OMODE-PP io-mode!. (Remember the “!” indicates set the value in a variable or register.)
To configure pin PA7 for ADC input: PA7 IMODE-ADC io-mode!. testing buttons, using the built-in pullup or pulldown resistors: PA3 IMODE-PULL io-mode! and then set the output to pull up or down using true PA3 io! or PA3 ios!. You’ll then be able to read the button state with PA3 io@ (“io get”) later on.
GPIO on the STM32 chips is very flexible, and if you want to get deep into the configuration options in the datasheet, you can set all of this fairly easily using [jcw]’s io.fs code. For instance, io.all prints all of the GPIO registers and their values, which is a great help for interactive debugging. That said, there’s some room here for a a lot more user-friendly hardware-abstraction layer, if you want to contribute one.
Multitasking on the Quick
So now we’ve got a blinking LED and serial-port printing “Hello World”. Not a bad start, and both of these make good use of Forth’s interactivity: the LED only lights up when you type blink. one of the chief virtues of Forth, for me, is the ease of going between interactive testing of words like this, and then deploying the functionality in a working system. One reason is that nearly all Forths support basic cooperative multitasking. Here’s what I mean.
First, let’s loop our blink function so that we don’t have to type so much. : bb begin blink again ; creates a function, bb for “bad blink”, that will run forever. The problem with “run forever” in Forth is that you never get back to the interpreter’s command line without physically pressing the reset button, and then everything you were working on in RAM is lost.
Instead, let’s blink in a loop with a way out. : gb begin blink key? עד ; 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.
ברגע שיש לנו tweaked הפונקציה שלנו להבהב לרוץ בדיוק כמו שאנחנו רוצים את זה, בואו ליצור משימה רקע אז זה יכול למצמץ ללא השגחה.
משימה: Blinktask.
: Blink &
Blinktask להפעיל את
להתחיל שוב למצמץ
–
multitask
לְמַצְמֵץ&
בקצרה, את המשימה: Word יוצר קצת שטח זיכרון עבור המשימה שלנו ממצמימת רקע שאנחנו קוראים blinktask. הפונקציה להבהב & עושה את העבודה ברקע. למצמץ & מתחיל על ידי הכרזה כי הוא ישתמש בהקשר המשימה Blinktask, וכי הוא חייב להתחיל לרוץ. אז זה נכנס לולאה מהבהב בלתי מוגבל שממנו הוא אף פעם לא עוזב. Multitask הופך ריבוי משימות, ולהבהב & מבצע את המשימה שלנו. הפעל אותו, ואת הוביל מהבהב בזמן שאתה עדיין יכול אינטראקציה עם קונסולת. מתוק. סוג משימות ותראה כי יש שני פעיל: אחד הוא מהבהב שלנו והשני הוא המתורגמן אינטראקטיבי.
אבל איך המשימה מהבהבת יודעת מתי להניב לתהליכים סימולטניים אחרים? קדימה, המילה שתיקה תשואות מההקשר הנוכחי ומהלכים על הריבוי-משקל הבא, סביב רובין. הפונקציה MS, בין היתר, מורכבת מפקודה הפסקת השהייה, אז מה שנראה כמו עיכוב חסימת בהגדרת משימה אחת בסופו של דבר משחק היטב עם המשימות האחרות שלך.
הדבר הגדול על ריבוי משימות שיתופי הוא שאתה שולט בדיוק כאשר יהיה הולך להיות מתג הקשר, אשר יכול לעזור לחסל תקלות שתמצא במערכות מנע. החיסרון הוא שאתה אחראי לזכור להשהות את הפונקציות שלך עכשיו, ואתה צריך לאמת את העיתוי עצמך. כמובן, זוהי מיקרו-בקר, ויש לך את הבקר הפנימי של הזרוע עשירה למדי לשחק עם גם כן.
הנקודה האמיתית של multitasking על micros קדימה היא שזה עושה זרימת עבודה גדולה לכתיבה, בדיקה, ופריסת דמונים קטנים: פונקציות שרוצים להיות “תמיד”. ראשית, כתוב את הפונקציה שעושה את הפעולה פעם אחת. שנית, לבדוק אותו בלולאה עם בוקח להימלט. שלישית, ברגע שזה עובד, להסיר את הבריחה ולעשות משימה רקע עבור זה. You can then turn it on and off using idle and wake, even from within other tasks. ראה multitask של mecrisp.txt, המקור, עבור הרבה פרטים נוספים.
מה הלאה?
עד כה, הקמנו mecrisp-stellaris, עם ספריות נוספות של Jeeelabs ’embello framework, ולהפעיל כמה הדגמות מהירות. אם זה עורר את העניין שלך, אני אקח אותך על הדרכה של בניית כמה תוכנה אמיתית בפעם הבאה. יש הרבה יותר מה לומר על הדרך שבה Mecrisp מטפל nuances של פלאש לעומת רם, תשומות ופלטים, ואת התרגול של פיתוח אינטראקטיבי. כמה מההיבטים המפרקים באמת של עבודו יעלו את ראשיהם בצורת מצחיק, ואנחנו למד לאהוב אותם בכל מקרה.
בינתיים, לקבל זול שלך stm32f103 לוחות הבזיקו עם הבינארי שלנו, ולקבל קצת המשמש לשחק בסביבה ההדזור על שבב. למצמץ כמה נוריות. 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.