-
STM8L101: some new findings
09/19/2020 at 13:08 • 0 commentsUsing the methods described in the previous log entry, I tried programming the STM8L101, and using STM8-GDB and OpenOCD already proves to be *very* useful!
Connecting with OpenOCD works. I first used openocd -f interface/st-link.cfg -f target/stm8l152.cfg -c "init" -c "reset halt"). but it turned out that the that target configuration uses 128 bytes block size - Low Density devices have 64 bytes block size - and programming failed after the 5th block (setting breakpoints with GDB and inspecting memory with x/i helped a lot).
I'm now using the following OpenOCD configuration (stored as target/stm8l101.cfg):
#config script for STM8L101 set FLASHEND 0x9FFF set BLOCKSIZE 0x40 proc stm8_reset_rop {} { mwb 0x4800 0xaa mwb 0x4800 0xaa reset halt } source [find target/stm8l.cfg]
With this file programming an STM8L101F3P6 chip actually works!
I made a trimmed-down STM8 eForth board configuration without background task but running it results in a reset
(gdb) run Starting program: /home/thomas/source/stm8s/stm8ef/out/STM8L101F3/STM8L101F3.elf Remote debugging using localhost:3333 0x00008bd2 in ?? () Loading section SSEG, size 0x1 lma 0x1 Loading section HOME, size 0x73 lma 0x8000 Loading section GSINIT, size 0x1a lma 0x8073 Loading section GSFINAL, size 0x3 lma 0x808d Loading section CODE, size 0x1152 lma 0x8090 Start address 0x8073, load size 4579 Transfer rate: 7 KB/sec, 915 bytes/write. (gdb) Program stopped. 0x00008000 in ?? ()
I tentatively set a breakpoints and single stepped execution until I learned that returning from a LITERAL (implemented with TRAP) doesn't work. That's very good (and very fast!) progress :-)
-
For STM8 programming OpenOCD is cool stuff
09/19/2020 at 10:37 • 0 commentsThe combination OpenOCD / GDB for the STM8 appears to be a bit inaccessible. In fact it's a really good "text adventure game", and I've had fun finding my way in a "software landscape" with a long history and a specific patois.
It turns out that one can set breakpoints or watchpoints and inspect memory with OpenOCD alone - GDB required for that, and instead one can use commands from the built-in gdbserver through a telnet session. The combination of STM8-GDB and OpenOCD can replace stm8flash for most (if not all) use case. I guess that writing STM8 flash, configuration, and option bytes with a script, instead of using GDB, is possible too.
New applications, like writing a tethered Forth that runs on a PC and interacts with the target device through OpenOCD is within reach, and it might be interesting to explore work by @Lars Brinkhoff and in that direction (@RigTig once started there).
What's more, both OpenOCD and GDB are scriptable. OpenOCD in the TCL dialect Jim (Rule #1: Everything is a string, Rule #2: If you think otherwise, See Rule #1).
I guess it's about time to get one of those unloved STM8L101F3P6 and STM8L001J3M3 devices from the basement. Maybe I now have the tools to program some Forth into them :-)
-
STM8L at the center of the STM8 eForth 2.2.26 development cycle
08/22/2020 at 06:29 • 0 commentsThis release will be about STM8L devices (i.e. the likes of STM8L051F3, STM8L151R6 or STM8L162R8). While STM8S peripherals are simple and the pin and clock configuration is trivial, the STML designers clearly had both many more, and much larger, spec sheets.
Many "more specs" one can clearly see in the number of configuration dependencies one has to infer when configuring one of the many features of the peripherals. @Andrew Clapp started with the C code abstractions for STM8L051 provided by ST: it turned out that it's easy to get results but the code uses the peripherals in a quite wasteful way (e.g. repeated initialization). The code, however, shows that ST's library designers also had a hard time creating something that's both flexible and lean.
For STM8 eForth this means that some things that were implicit or hard-coded need to be reviewed and restructured, and tested. A good example is Issue #340: the background task priority now works across devices and families (although STM8L is still limited to using TIM2 for the BG interrupt).
Another target is symbol files: @Eelco provided a first draft of an STM8L151.efr file. I then made a synthesis of datasheets and improved the generic STM8L.efr so that it covers most STM8L devices (that is all except the STM8L101 family).
On GitHub you'll find a new pre-release STM8 eForth 2.2.26.pre2 that contains the changes mentioned above and some more goodies.
-
Accessing STM8 Far Memory
07/28/2020 at 05:21 • 0 commentsSTM8 architects some 16bit on top of the ST7 6800-like architecture (at least some fast arithmetic instructions), and the address space for programs was extended by 24bit "Far adressing".
Unfortunately, access to the "Far" 24bit memory space (in practice it's just 19bit [see edit]) is only possible for the following instructions:
- 8 bit load/store instructions, limited to "absolute" and "indirect addressing" memory access
- Jump, call and interrupt vectors for code access
That's OK since RAM and EEPROM are in an 8bit (zero page) or 16bit memory space, and it doesn't matter where they're executed. Forth, however, cares a lot about ROM addresses: as XTs (Execution Tokens) are data, too, there is no easy way to put "threaded Forth code" into 32K to 96K Flash memory in the extended address space of "High Density" devices like STM8S207 or STM8L162.
In Forth, the address space can be used for (carefully crafted) interrupt service routines (there is no need to keep these in the dictionary), and for library code written Forth, assembler or C that has an entry point in the 16bit address space.
Using the STM8 eForth compiler for creating code that runs in the Far address space must take care not to use anything that's based on BRANCH, ?BRANCH or 16 bit addresses on the data stack (that is IF, ELSE, THEN, BEGIN, UNTIL, WHILE REPEAT, FOR, AFT, NEXT, DO, LOOP...).
That doesn't mean that it's impossible, though: by compiling code that only uses words from 16 bit ROM to RAM and that's limited to relative addressing for control structures, and then copying that code to Far memory, it should work. Anchoring such structures in the 16 bit address space would, of course, still be necessary.
At least, from release 2.2.26.pre1 on, STM8 eForth provides the words FC@ and FC! for accessing memory in the far address space. Words for moving memory between Far memory and the 16bit address space (using block programming and transfer) are planned. As Flash block write code must be executed from RAM, the whole thing is a bit more complicated. As soon as that's available, some of the advanced use cases can be addressed.
EDIT: I used to believe that the address space is 18bit but there is evidence that there were STM8AF51B High Density devices on offer with 256K Flash memory (and 12K RAM, two I2C, two SPI, 3 x UART, 4x16bit timer... ). References to it have almost disappeared since.
-
Release STM8 eForth 2.2.25 - A bit too fast! A bug-fix and an extra.
07/10/2020 at 15:06 • 5 commentsOne can never test enough - literally.
The STM8 eForth test automation in Travis-CI tests the background task, but it doesn't test its cadence. Maybe that can be done, and maybe it would have been worth doing that. I could have done a manual test - just flashing a W1209 would have shown a flickering LED display - but I didn't. You live and learn...@Andrew Clapp first discovered that something was wrong. I then identified the cause: a classic "don't use LDW for timers"-error. I first thought that it only hits STM8L devices but also STM8S, this means the whole release was affected. A quick bug-fix release therefore is the best option.
@Eelco the praise came too soon - please check if the 2.2.25 release still solves your problem!
On the plus side: I added INTRX for buffered console RX to the library. Compilation to RAM at 115200 baud really feels much faster than at 9600 baud!
-
Release STM8 eForth 2.2.24 - Has it really been a year?
07/04/2020 at 06:15 • 8 comments"Has it really been a year?" isn't a question - it's the name of the latest release. It's been more than a year since the last release, and there are certainly many reasons for that.
There were so many changes in the build infrastructure ("modular build"), supported by modularization and some generalizations, that there have been no less than four pre-releases.
The motivation behind it was a number of STM8 eForth applications that each required some kind of "board support" in drivers, vocabulary selections, peripherals usage and whatnot while the STM8 eForth core itself hardly changed at all.
On the other hand, configuration options for the following things have improved by a lot:
- Binaries through "modular build": it's now trivially easy to create a downstream GitHub repository with build automation
- Peripherals abstraction for timers and serial interfaces used in the core: it's now possible to use any 16 bit timer for ticking the background task, both UARTs of STM8S High Density µCs can be used
- STM8L devices received more love (e.g. simulated serial interface, peripherals abstraction)
- Most of the code for anything "non-core" (e.g. board I/O) is now in include files and variants can be put in a board folder where it has precedence
And feature creep, of course. I'll have to spend some time to document all new features ;-)
Now there is finally some stability as the following POCs showed the desired results:
- stm8ef-modbus since 2.2.24.pre3
- W1209 Data-Logging Thermostat since 2.2.24.pre3
- XY-LPWM since 2.2.24.pre4 (timers and 7S-LED code)
- stm8l051led since 2.2.24 (simulated serial interface and other things for STM8L)
It's safe to say that STM8 eForth is now quite mature and that it will support a range of applications with little effort. Future developments are planned for exploring options in less frugal systems.
-
Improved support for STM8L devices
06/26/2020 at 14:40 • 0 commentsWere it not for @Eelco and @Ivan Alf STM8L support in STM8 eForth would still be very basic (call me lazy but I don't like comparing th e STM8S and the STM8L reference manual - in my opinion ST should have written it in a way that makes it more visible where things changed and where not.
Lately. @Andrew Clapp needed a simulated second serial interface for the STM8L051F3, which was only available for STM8S devices. Supporting the TIM4 based UART simulation to the STM8L was quite simple (STM8L TIM4 is like a STM8S TIM6 with minor improvements) but getting the GPIO configuration right required many changes in the way interrupts are defined in the STM8 eForth core code. It was also a good opportunity to test and improve the modular build feature.
A repository with the working STM8 eForth code for STM8L051F3 is here. In the next STM8 eForth release it will be easier to apply configurations for STM8L.
-
STM8 eForth Wiki: Discussion of `FOR .. NEXT` updated
05/29/2020 at 08:31 • 1 commentThe STM8 eForth wiki has a page on the usage of eForth `FOR .. NEXT` and its variants. It's a good example why people think that Forth is strange, and that eForth is even more so but it deserves a closer look.
I updated the page to better explain different loop constructs. The short read provides some insight into building simple code generators.
-
Some STM8S peripherals are equal, some are the same
05/24/2020 at 19:58 • 0 commentsAcross the STM8S family, the reference manual RM0016 describes peripherals such as GPIOs, timers, UARTS, I2C, SSC, ADC, watchdog timers and control of interrupt or control. Variants of these peripherals are often described in great detail, and the variants are given names such as USART, UART1, UART2, UART3, UART4 or even USART and LINUART. Sometimes the same peripheral has a different name in the datasheet of commercial/industrial and automotive grades of the same chip.
It turns out that subsets of peripheral register addresses are almost always the same. Almost. The timers TIM2 and TIM4 have the same register names in LD (Low Density) as in MD (Medium Density) and HD (High Density) devices but the addresses differ a bit.
UART irregularities are of a different kind: there are two sets of address and interrupt vectors, let's call them 1st UART and 2nd UART. A LD device has a 1st UART, MD a 2nd UART and HD has both of them.
For writing device independent low-level code some workarounds can be used:
- provide a symbol file that contains a shared functional sub-set of peripheral register addresses
- provide identical symbols for peripheral registers with common functionality in different symbol files
- first define device independent symbols in low-level application code from device specific symbol files, first then load device independent code
Workaround 1 has now been implemented by STM8s.efr in the current master branch of STM8 eForth. It should work for most applications that use common peripherals (e.g, GPIOs, I2C or SSC) and for almost all peripherals of STM8S MD or HD devices (e.g. STM8S105K4 or STM8S207RB).
For UART addresses there is a partial implementation of workaround 2 in STM8S103.efr, STM8S105.efr and STM8S207.efr: a default UART can be accessed using the alias UART (which is wither the 1st UART or the 2nd UART).
Code that implements workaround 3 turned out to be quite ugly and difficult to maintain. I'll now try to combine the first two options based on the use case (common peripheral addresses or peripheral register alias). Hopefully that works better.
-
Simple buffered UART RX
05/23/2020 at 15:54 • 0 commentsThe MODBUS project has buffered UART, which is necessary because the protocol works in the background.
A UART buffer for the Forth console also makes sense, especially when a baud rate higher than 9600 baud is to be used. The solution INTRX, with an ISR written in Forth, is really simple.
Edit1: INTRX has been updated and now supports the new device independent UART symbols. The code will be included in the upcoming STM8 eForth 2.2.24 release. Compiling with a 38400 baud console is really a lot faster.
The In PulseView screenshot below shows a situation where the Background Task blocks the foreground console execution most of the time:
An interactive console still works. For some reason compiling is much more picky : the background task is allowed to run for a 2.5 out of 5 ms (that is 2-3 char intervals at 9600 baud). I still don't understand why but it has nothing to do with delays due to Flash programming.
Edit2: the solution is, very simply, that the receive buffer wasn't big enough for this much delay. If I use 80 bytes (the same length as the TIB) uploading Forth code works without problems:
Also Flash programming works as expected - this is no surprise since the programming process starts at the end of a line and stalls all, also the background task.