Close

New feature: in NVM mode VARIABLE just works

A project log for eForth for cheap STM8S gadgets

Turn cheap modules from AliExpress into interactive development kits!

thomasThomas 02/26/2017 at 11:370 Comments

Issue 16 introduces "normal" operation of VARIABLE and ALLOT when compiled to non-volatitle memory. The feature also provides transparent RAM allocation.

This may not sound not like much, but it's an essential implementation of the memory allocation by a "linker" in a C programming environment. To give you an idea of the problem, consider the following code:

VARIABLE abc ok
' abc . 168 ok
' abc 5 dump
  A8  CD 83 54  0  0  0  0  4 64 75 6D 70  0  0  0  0  M_T_____dump____ ok
abc . 171 ok
12345 abc ! ok
abc ? 12345 ok

VARIABLE defines a word (abc) in the dictionary, which consists of code CALL DOVAR (CD 83 54) at address 168, and a RAM "CELL" (2 bytes) of storage at address 171. When the word abc is called, DOVAR places the address of the next memory location on the data stack and returns to the caller.

From the programmer's perspective, a variable in Forth is much like an array definition in C. The word VARIABLE, as a "defining word" is akin to a C declaration, we'll come back to this later on :-). Just like in C, access to array elements works with address arithmetics (in C, square brackets are used as "syntactical sugar"). In Forth variables are accessed with words like !, @, C!, C@, and ?.

An array with two bytes might not serve everybody. If more memory is needed (e.g. an array) it can be allocated with ALLOT.

VARIABLE def 8 ALLOT ok
VARIABLE ghj ok
ghj def - . 19 ok
def abc - . 11 ok

The variables abc, def, and ghj use consecutive RAM cells follow in the dictionary. Because of 8 ALLOT the variable def gets 10 byte RAM instead of the 2 bytes of abc. The overhead of 9 bytes is due to 2 link, 1 string length, 3 string, and 3 CALL DOVAR.

So far so good. But what happens when we're in NVM mode and create a variable?

COLD ok
NVM ok
VARIABLE abc ok
HEX abc . 9BD9 ok
' abc . 9BD6 ok

The variable abc is now in Flash (which starts at 0x8000). Unfortunately, the memory location it refers to is also in Flash, which is no good place for a variable, to say the least.

@RigTig provided a prototype implementation for VARIABLE with CREATE-DOES> that works in NVM:

: VARIABLE CREATE HERE , 2 $6E +! DOES> @ ;

This code is a bit tricky: variable is a replacement for the defining word VARIABLE, which works just like the normal one, except that it reserves memory in the RAM dictionary area when defining a new variable, and returns the address of that memory when using the variable, and $6E is the address where the next free location in the RAM dictionary is stored while STM8EF is in NVM mode.

Forth features like CREATE-DOES> are akin to high level language concepts like inheritance, reflection, and prototypes. Extending a 5K programming system that's embedded in a 8K µC on the fly really is something else! RigTig demonstrated the power of CREATE-DOES> by implementing a useful approach to the "Flash/RAM problem".

VARIABLE has been on my ToDo-list for months, and now had no excuse for not to sorting it out.. After some hacking, all the examples above work as expected, no matter whether you're in RAM or in NVM mode. Check out the preliminary docs and the preview code in Issue 16 on GitHub.

EDIT: the code size is now to below 5000 bytes for the MINDEV target (80 bytes down!). The CORE binary size target is still 21 bytes above the self-imposed limit of 4096 bytes (VARIABLE formerly wasn't part of CORE due to its limited usefulness). I pushed new code to the branch variable on GiHub.

EDIT2: the size of the CORE binary is now below 4096 bytes, and a minimal interactive system without NVM, interrupts in Forth code, and the new VARIABLE feature |is below 3700 bytes. The code has been merged from the feature branch variable to the develop branch, and there is a pre-release STM8EF v2.2.8.1.snapshot.

EDIT3: @RigTig did some testing with the new code, and he told me that the results are encouraging (e.g. improved code size in a quite complex application). I'll release the code soon, maybe together with initial support for the W1219 board.

Discussions