Skip to content

Releases: TG9541/stm8ef

The Long Overdue Release

10 Jul 18:50
9c50a74
Compare
Choose a tag to compare

About the Release

This is the release after the "long past due pre-release". Since the last release Travis-CI.org services had been terminated, and other things in life of the maintainer insisted to be more important than learning about GitHub Actions. For a long time many improvements didn't make it into a binary release.

Now the transition to GitHub Actions is complete. In addition to the old features the volatile release tag contains binaries from the latest successful build-test workflow.

New Features

Improved CREATE ... DOES>

Issue #427 provides a much better implementation of DOES> - and better means both faster and leaner.

The execution speed of the new solution is on par with an ordinary CREATE, VARIABLE or CONSTANT as can be shown in the following example:

: EMPTY CREATE DOES> ;      \ just return the address   
: CONS  CREATE , DOES> @ ;  \ return data

      CREATE   tcreate 
      VARIABLE tvar
      EMPTY    tempty
  0  CONS      tcons
  0  CONSTANT  tconstant

The following measurements where done with PulseView on a STM8S001J3M3 with 16MHz HSI and code compiled to Flash ROM.

Test runtime cycles
tcreate 1.3µs 21
tempty 1.82µs 29
tvariable 1.89µs 30
tconstant 3.2µs 51
tcons 3.3µs 53

This means that a runtime of an "empty" DOES>, which returns the address of any data stored by a word definition, is 1.82µs. That's marginally faster than VARIABLE and just a bit slower than CREATE.

The simple constant value implementation : CONS CREATE , DOES> @ ; is also just a bit slower than the literal stored by CONSTANT. The latter uses the STM8 instruction TRAP and requires just 3 byte, just like the CALL to the word defined through CONS).

The memory requirements compare as follows:

[bytes] old new diff
: empty CREATE DOES> ; 22 18 4
empty a 13 7 6
STM8S001J3 binary 4697 4662 35

The old implementation needs 4 bytes more for a "defining word" and 6 bytes more for a "defined" (the new DOES> has the same memory needs as a word defined by CREATE, CONSTANT or VARIABLE).

Also the STM8 eForth binary is 35 bytes smaller than before.

Improved >REL

>REL is an implementation of IF ... ELSE ... THEN using relative addressing modes. It's meant to be used as a compiler extension loaded into RAM as a scaffold for, e.g., compiling fast and extra compact ISRs (interrupt service routines) into Flash ROM.

@Eelkhoorn noticed that RAM space for the scaffolding code can be reduced and provided an improved implementation.

Words for Forth Standard compatibility

Issue #430 and #438 added library words for making STM8 eForth a bit more compatible with the Forth Standard. Some of the words are just "No Operation" dummy words (e.g. ALIGN), some aliases (e.g., INVERT), some simple definitions (e.g. >BODY and some genuine extensions (e.g., VALUE ... TO).

Please be aware that not all of these Forth Standard words will always do what you expect, e.g.:

  • VALUE ... TO (like DEFER ... IS) assumes a writable dictionary
  • some words like STATE emulate some just of the standard semantics
Forth Standard STM8 eForth implementation
>BODY : >BODY ( xt -- a-addr ) 3 + ;
ALIGN no op
ALIGNED no op
C" ' $" ALIAS C"
CHAR+ ' 1+ ALIAS CHAR+ ( c-addr1 -- c-addr2 )
CHAR : CHAR ( "char" -- c ) BL WORD CHAR+ C@ ;
CHARS no op
[CHAR] : [CHAR] ( "name"<spaces -- ) CHAR POSTPONE LITERAL ; IMMEDIATE
COMPILE, ' CALL, ALIAS COMPILE, ( xt -- )
ENVIRONMENT? : ENVIRONMENT? ( c-addr u -- false ) 2DROP 0 ;
INVERT ' NOT ALIAS INVERT ( x1 -- x2 )
J like I (only for DO ... LOOP, not FOR ... NEXT)
STATE "kludge" using STATE? and a variable stateflag
TO see VALUE
VALUE limited to writable dictionary (RAM or NVM when writable) see lib/VALUE

Issue #430 refactored CREATE and VARIABLE in order to facilitate implementing the Forth Standard words VALUE and TO.

The following additional words are already available in volatile and they will be available in the next release (2.2.29):

Forth Standard STM8 eForth implementation
CELL+ ' 2+ ALIAS CELL+ ( c-addr1 -- c-addr2 )
CELLS ' 2* ALIAS CELLS ( n1 -- n2 )
FALSE ' 0 ALIAS FALSE ( -- false )
RSHIFT like LSHIFT ( n1 u -- n2 )
TRUE ' -1 ALIAS TRUE ( -- true )

Improved "pictured number" words

While working on optional words for Forth Standard compatibility it became clear that while Forth Standard compliant "pictured number output" with # ( ud -- ud) instead of # ( u -- u) (double instead of single math) would increase the code size only marginally but the math would make printing numbers in a background process slower. This might break applications that print numbers in a background task as the limit of 1ms task run-time is exceeded (unless a fast 32bit/8bit division or buffered I/O is used).

Issue #433 explored options for improving the code. It turned out that # can be made faster by using the instruction DIV X,A (with the DIV/DIVW erratum work-around). The code could also be made leaner by in-lining the code of DIGIT and EXTRACT (these are eForth words which are not available in other 16bit Forth implementations, e.g., the well known F83 - they also don't appear in the Forth Standard).

PulseView and the word .. (which toggles a GPIO with PLo and PHi) were used for testing:

: .. ( u -- u ) PLo <# PHi #S PLo #> PHi TYPE ;

For example, here is the timing for DECIMAL 65535 ..:

image

The following table shows that # and #S are much faster now:

.. Base <# #S #> old [µs] <# #S #> improved [µs]
65535 10 155 31
6 10 53 22
65535 16 131 29
65535 2 446 60

The toggles around <# and #> revealed that about 4µs can be saved by coding the 16bit <literal> + in PAD in assembler (13µs to 9µs - the numbers in the table contain this optimization). In a BG task PAD is slightly faster as it returns a constant address. When using numeric output in a background task, e.g. for presenting measurements on a LED display with CR ., the more efficient "pictured number words" makes a real difference.

Note: Forth Standard compatible "pictured number" words with double number output (e.g. D.) can be provided later through library words. in In a 16bit Forth it's important to keep in mind that a limitation of UM/MOD ( ud un -- ur uq ) - the 16bit result - correct output for double numbers is limited to "65536 x BASE - 1" (e.g., 655359 for base 10). For larger numbers a 32bit division with 32bit result is required (with 8bit divisor).

Bug fixes and other improvements

Improved .0 (3-digit signed number print)

Issue #432 fixes a few edge cases of .0, the signed number output for 3 digit (LED) displays: numbers smaller than -994 or larger than 9994 had digit overruns - and thus potentially wrong display values.

The updated version was shown to work for the following values:

-999 .0 DEF. ok
-995  .0 -99 ok
-99  .0 -9.9 ok
0    .0 0.0 ok
999  .0 99.9 ok
1000 .0 100 ok
7876 .0 788 ok
9995 .0 DEF. ok

Leaner console text input words

Issue #435 saved some ROM space in the input words ACCEPT, KTAP, and QUERY.

CREATE and VARIABLE refactored

Common functionality from CREATE and VARIABLE was refactored into the new word ENTRY (used by VALUE).

Set INT_TLI to COLD

@Eelkhoorn ran into a problem when changing ISR code in a development cycle:

Uploading the I2C interrupt service routine to STM8L (both 051F3 and 151K4) can lead to corrupted ITC_SPR registers, persistent even after power cycle. Writing xt of COLD to INT_TLI (reset vector) solved the issue.
The last four entries of the interrupt vector table (0x8070 to 0x8080) seem to be corrupted after boot for STM8L.

Pull request #440 appears to solve the issue (but the problem needs further analysis and the code may change in the future).

codeload.py: broken #ifdef and #ifndef repaired

Tests with #ifndef <word> \res MCU: ... worked in e4thcom but made codeload.py crash. Issue #448 solved the problem.

A 5x8 font for dot-matrix displays

A simple 5x8 font for dot-matrix displays `FONT5X8 has been added. It's intended to be used with an additional 6th column (6x8) - an example is provided.

The Long Overdue (Pre-) Release

19 Feb 19:11
f68e3c2
Compare
Choose a tag to compare
Pre-release

About the Release

This pre-release is long past due. In the meantime Travis-CI.org services were terminated, and other things in life of the maintainer insisted to be more important than learning about GitHub Actions. For a long time many improvements didn't make it into a binary release.

Now the transition to GitHub Actions is complete. In addition to the old features the volatile release tag will contain the binaries from the latest successful build-test workflow.

New Features

Improved CREATE ... DOES>

Issue #427 provides a much better implementation of DOES> - and better means both faster and leaner.

The execution speed of the new solution is on par with an ordinary CREATE, VARIABLE or CONSTANT as can be shown in the following example:

: EMPTY CREATE DOES> ;      \ just return the address   
: CONS  CREATE , DOES> @ ;  \ return data

      CREATE   tcreate 
      VARIABLE tvar
      EMPTY    tempty
  0  CONS      tcons
  0  CONSTANT  tconstant

The following measurements where done with PulseView on a STM8S001J3M3 with 16MHz HSI and code compiled to Flash ROM.

Test runtime cycles
tcreate 1.3µs 21
tempty 1.82µs 29
tvariable 1.89µs 30
tconstant 3.2µs 51
tcons 3.3µs 53

This means that a runtime of an "empty" DOES>, which returns the address of any data stored by a word definition, is 1.82µs. That's marginally faster than VARIABLE and just a bit slower than CREATE.

The simple constant value implementation : CONS CREATE , DOES> @ ; is also just a bit slower than the literal stored by CONSTANT. The latter uses the STM8 instruction TRAP and requires just 3 byte, just like the CALL to the word defined through CONS).

The memory requirements compare as follows:

[bytes] old new diff
: empty CREATE DOES> ; 22 18 4
empty a 13 7 6
STM8S001J3 binary 4697 4662 35

The old implementation needs 4 bytes more for a "defining word" and 6 bytes more for a "defined" (the new DOES> has the same memory needs as a word defined by CREATE, CONSTANT or VARIABLE).

Also the STM8 eForth binary is 35 bytes smaller than before.

Improved >REL

>REL is an implementation of IF ... ELSE ... THEN using relative addressing modes. It's meant to be used as a compiler extension loaded into RAM as a scaffold for, e.g., compiling fast and extra compact ISRs (interrupt service routines) into Flash ROM.

@Eelkhoorn noticed that RAM space for the scaffolding code can be reduced and provided an improved implementation.

Words for Forth Standard compatibility

Issue #430 and #438 added library words for making STM8 eForth a bit more compatible with the Forth Standard. Some of the words are just "No Operation" dummy words (e.g. ALIGN), some aliases (e.g., INVERT), some simple definitions (e.g. >BODY and some genuine extensions (e.g., VALUE ... TO).

Please be aware that not all of these Forth Standard words will always do what you expect, e.g.:

  • VALUE ... TO (like DEFER ... IS) assumes a writable dictionary
  • some words like STATE emulate some just of the standard semantics
Forth Standard STM8 eForth implementation
>BODY : >BODY ( xt -- a-addr ) 3 + ;
ALIGN no op
ALIGNED no op
C" ' $" ALIAS C"
CHAR+ ' 1+ ALIAS CHAR+ ( c-addr1 -- c-addr2 )
CHAR : CHAR ( "char" -- c ) BL WORD CHAR+ C@ ;
CHARS no op
[CHAR] : [CHAR] ( "name"<spaces -- ) CHAR POSTPONE LITERAL ; IMMEDIATE
COMPILE, ' CALL, ALIAS COMPILE, ( xt -- )
ENVIRONMENT? : ENVIRONMENT? ( c-addr u -- false ) 2DROP 0 ;
INVERT ' NOT ALIAS INVERT ( x1 -- x2 )
J like I (only for DO ... LOOP, not FOR ... NEXT)
STATE "kludge" using STATE? and a variable stateflag
TO see VALUE
VALUE limited to writable dictionary (RAM or NVM when writable) see lib/VALUE

Issue #430 refactored CREATE and VARIABLE in order to facilitate implementing the Forth Standard words VALUE and TO.

The following additional words are already available in volatile and they will be available in the next release (2.2.29):

Forth Standard STM8 eForth implementation
CELL+ ' 2+ ALIAS CELL+ ( c-addr1 -- c-addr2 )
CELLS ' 2* ALIAS CELLS ( n1 -- n2 )
FALSE ' 0 ALIAS FALSE ( -- false )
RSHIFT like LSHIFT ( n1 u -- n2 )
TRUE ' -1 ALIAS TRUE ( -- true )

Improved "pictured number" words

While working on optional words for Forth Standard compatibility it became clear that while Forth Standard compliant "pictured number output" with # ( ud -- ud) instead of # ( u -- u) (double instead of single math) would increase the code size only marginally but the math would make printing numbers in a background process slower. This might break applications that print numbers in a background task as the limit of 1ms task run-time is exceeded (unless a fast 32bit/8bit division or buffered I/O is used).

Issue #433 explored options for improving the code. It turned out that # can be made faster by using the instruction DIV X,A (with the DIV/DIVW erratum work-around). The code could also be made leaner by in-lining the code of DIGIT and EXTRACT (these are eForth words which are not available in other 16bit Forth implementations, e.g., the well known F83 - they also don't appear in the Forth Standard).

PulseView and the word .. (which toggles a GPIO with PLo and PHi) were used for testing:

: .. ( u -- u ) PLo <# PHi #S PLo #> PHi TYPE ;

For example, here is the timing for DECIMAL 65535 ..:

image

The following table shows that # and #S are much faster now:

.. Base <# #S #> old [µs] <# #S #> improved [µs]
65535 10 155 31
6 10 53 22
65535 16 131 29
65535 2 446 60

The toggles around <# and #> revealed that about 4µs can be saved by coding the 16bit <literal> + in PAD in assembler (13µs to 9µs - the numbers in the table contain this optimization). In a BG task PAD is slightly faster as it returns a constant address. When using numeric output in a background task, e.g. for presenting measurements on a LED display with CR ., the more efficient "pictured number words" makes a real difference.

Note: Forth Standard compatible "pictured number" words with double number output (e.g. D.) can be provided later through library words. in In a 16bit Forth it's important to keep in mind that a limitation of UM/MOD ( ud un -- ur uq ) - the 16bit result - correct output for double numbers is limited to "65536 x BASE - 1" (e.g., 655359 for base 10). For larger numbers a 32bit division with 32bit result is required (with 8bit divisor).

Bug fixes and other improvements

Improved .0 (3-digit signed number print)

Issue #432 fixes a few edge cases of .0, the signed number output for 3 digit (LED) displays: numbers smaller than -994 or larger than 9994 had digit overruns - and thus potentially wrong display values.

The updated version was shown to work for the following values:

-999 .0 DEF. ok
-995  .0 -99 ok
-99  .0 -9.9 ok
0    .0 0.0 ok
999  .0 99.9 ok
1000 .0 100 ok
7876 .0 788 ok
9995 .0 DEF. ok

Leaner console text input words

Issue #435 saved some ROM space in the input words ACCEPT, KTAP, and QUERY.

CREATE and VARIABLE refactored

Common functionality from CREATE and VARIABLE was refactored into the new word ENTRY (used by VALUE).

Set INT_TLI to COLD

@Eelkhoorn ran into a problem when changing ISR code in a development cycle:

Uploading the I2C interrupt service routine to STM8L (both 051F3 and 151K4) can lead to corrupted ITC_SPR registers, persistent even after power cycle. Writing xt of COLD to INT_TLI (reset vector) solved the issue.
The last four entries of the interrupt vector table (0x8070 to 0x8080) seem to be corrupted after boot for STM8L.

Pull request #440 appears to solve the issue. The problem needs further analysis.

Latest unstable binaries (volatile)

20 Feb 07:03
Compare
Choose a tag to compare
Pre-release

About this release

This isn't really a release but a container for the binary artifacts from the latest build (see this GH Release issue). It's not only unstable (if tested!) but also volatile.

This means that the artifacts in the "volatile" release can be used for testing or prototyping but they won't last. In order to keep a trace to the Git version at the end of the file forth.asm packed in the attached binary archives there is an identification record like the following:

; ##########################################
; # Release info added by GitHub action:
; #   repository:   TG9541/stm8ef
; #   branch name:  refs/heads/master
; #   sha:   8ee3453ce577181ef5e9bddda94f56d448dbf962
; ##########################################

The Git version used for creating the binary archive in this example is 8ee3453.

Please take note that not all archives provided in the release are up-to-date:

File Description
stm8ef-bin.tgz full binary release, suitable for STM8 eForth Modular Build method
stm8ef-bin.zip binary release
stm8ef-rst.tgz list file for debugging
Source code (zip) GitHub source snapshot from original tag (outdated)
Source code (tar.gz) GitHub source snapshot from original tag (outdated)

POSTPONE, DEFER and an ISR/BG bug fix

08 Apr 19:43
dde829e
Compare
Choose a tag to compare

About the Release

The 2.2.28 development cycle had just started - the plan was to start making STM8 eForth a little bit more standard compliant so that using code from other embedded Forth systems gets easier when @Eelkhoorn found a configuration error of the BG task data stack size: since #377 the stack size as exactly "0" so that the ISR data stack was used (see #424 ).

Other than that, this release contains a potentially braking change: POSTPONE was introduced and since it has some many advantages over COMPILE and COMPILE it's now the default. Please refer to #413 for a discussion of the differences.

New Features

POSTPONE instead of COMPILE or [COMPILE]

Modern Forth systems use POSTPONE instead of COMPILE or [COMPILE]. The main objective is code simplification, both for the programmer but also for a Forth system that generate machine code: in STM8 eForth COMPILE has to analyze the call type (absolute or relative) - which makes the code more complicated.

Why this is important

Making "Forth macros", words that compile code (e.g., IF ... ELSE ... THEN), requires compiling "compilation instructions" into a word instead of executing them during compilation.

For instance IF can be implemented as follows:

: >MARK ( --A ) HERE 0 , ;
: IF ( --A )   COMPILE ?branch >MARK ; IMMEDIATE

Since the dictionary entry of IF is flagged IMMEDIATE it will be executed, not compiled, when using a condition structure (e.g., 0< IF DROP 0 THEN). When executed, the word COMPILE takes the call address (xt, the execution token) of the next word (?branch) and compiles it into the destination code (e.g. the conditional phrase above). Note that ?branch isn't flagged IMMEDIATE - if it were different it would be executed, not compiled, and COMPILE would not receive the expected xt.

Sometimes IMMEDIATE words need to be compiled into a new word, not executed. In order to get the desired effect [COMPILE] would be required to enforce compilation of the immediate word, e.g.:

: WHILE ( a --A a )    [COMPILE] IF SWAP ; IMMEDIATE

Here [COMPILE] overrides the IMMEDIATE flag of IF and compiles a call to this immediate word into the code of WHILE. It would also be possible to write COMPILE [COMPILE] IF, which would create a macro that compiles IF into the target code (just like using COMPILE on a regular word). In practice such a use case is rare.

From this release on it's sufficient to write POSTPONE instead of COMPILE or [COMPILE]. This also makes porting code from more modern Forth systems easier since it's no longer necessary to figure out if it's COMPILE or [COMPILE] that you'll have to use instead.

Legacy code can use #require COMPILE or #require [COMPILE], which will load an alias to POSTPONE, to cover all but the most exotic use cases. If that does't work the legacy words can be re-enabled in the board configuration (and please file an issue).

More examples and technical details are in the following issues:

#413 POSTPONE supersedes COMPILE and [COMPILE]
#414 make COMPILE and [COMPILE] replaceable with ALIAS to POSTPONE
#414 add test for POSTPONE
#417 use COMPILIT instead of COMPILE in core
#419 use POSTPONE in lib
#419 use POSTPONE in >REL
#419 use POSTPONE in [']
#419 use POSTPONE in ALIAS
#419 use POSTPONE in DEFER
#419 use POSTPONE in :NVM
#419 use POSTPONE in S"
#419 use POSTPONE in EVALUATE
#419 use POSTPONE in CONSTANT
#419 use POSTPONE in MARKER
#419 use POSTPONE in VOC
#419 use POSTPONE in VOCABULARY

Add ['] and DEFER ... IS

Issue #411 adds the words ['] (compile literal with xt of the following word) and DEFER ... IS.

Please refer to the Forth Standard entries of ['], DEFER and IS.

Other changes

Core optimizations

Issue #416 introduces a more compact CALL, with COMPILIT and some other core optimizations, especially for the transition from COMPILE and [COMPILE] to POSTPONE.

Tool changes

Issue #421 makes the codeload.py line length check less restrictive (trailing comments don't count).

Docs changes

Issue #409 proposes a work around for an STM8L151 serial bootloader erratum

Bug fixes

BG task data stack size configuration error

Issue #424 describes a critical problem of the BG task data stack size configuration:

  1. Applications that use the BG task and an ISR that uses Forth code may suffer from BG task data stack corruption
  2. The BG stack has been 8 cells deep since the bug was introduced - this can also lead to foreground task stack corruption!

The regression was introduced when the BG code was factored out in #377. It was still OK until the 2.2.26 release. The first release that contained this bug was 2.2.27.pre1. 2.2.27 was released 9/Mar/2021.

Incorrect TIB constant export

Issue #420 fixes an incorrect TIB constant export that broke EVALUATE. The bug was introduced in release 2.2.24. An automated test of EVALUATE was added.

Start 2.2.28 Development Cycle: POSTPONE and DEFER

07 Apr 19:34
Compare
Choose a tag to compare

About the Pre-Release

This release is going to modernize eForth by introducing some Forth-Standard words.

fixes #409: work around for STM8L151 serial bootloader erratum

fixes #411: add ['] and DEFER ... IS
#411 add test for DEFER ... IS and [']

fixes #413 POSTPONE supersedes COMPILE and [COMPILE]
fixes #413 POSTPONE supersedes COMPILE and [COMPILE]

fixes #414 implement POSTPONE
#414 add test for POSTPONE
#414 make COMPILE and [COMPILE] replaceable with ALIAS to POSTPONE

#416 some minor core optimizations
#416 some minor core optimizations
#416 more compact CALL,

fixes #417 use COMPILIT instead of COMPILE in core

fixes #419 use POSTPONE in lib
#419 use POSTPONE in >REL
#419 use POSTPONE in [']
#419 use POSTPONE in ALIAS
#419 use POSTPONE in DEFER
#419 use POSTPONE in :NVM
#419 use POSTPONE in S"
#419 use POSTPONE in EVALUATE
#419 use POSTPONE in CONSTANT
#419 use POSTPONE in MARKER
#419 use POSTPONE in VOC
#419 use POSTPONE in VOCABULARY

fixes #420 incorrect TIB constant export
#420 incorrect TIB constant export

#421 codeload.py: less restrictive line length check

UM/MOD Bugfix and Improvements Release

09 Mar 05:49
22185fd
Compare
Choose a tag to compare

About the release

Whether or not you need any of the new features in this release there is a very good reason to use it: it fixes a very old bug in UM/MOD. It's possible that this bug can be traced to an early FIG-Forth release for the 6502:

Bill Ragsdale: UM/MOD had this or a similar range error in my first published fig-FORTH Model. Fixed in the second edition but by then the damage was done. I suspect that error propagated much later.

The good news: as long as the divisor is smaller than $8000 all is well. More about the bug below.

New Features

A simple debug console

It's sometimes useful to inspect the system (e.g. the stack) while executing a word in an application. That can be done by calling OUTER, the Forth interpreter, from user code. The new word BYE leaves this interpreter (but not that of the normal console).

Here is an example session:

#require BYE
\ ...
Closing: ./lib/BYE  ok 
: test 1 2 3 OUTER . . . ; ok
test<ENTER>.S<ENTER>
 1 2 3 <sp  ok
. 3 ok
4 ok
bye 4 2 1 ok

Note that there is no prompt indication when the "debug interpreter" gets active after test<ENTER>. Also note that any ?response from the interpreter means that the stack was emptied. Only a debug interpreter with a different type of error response would be able to prevent that.

The issue #372 "better BYE for debug console" contains technical details.

Fully Modular Background Task code

The BG code is now "fully modular" which means that it can be replaced with user code by placing a modified copy of bgtask.inc into a Board folder.

Now the background task can also be run by the STM8L RM0031 device RTC (think "alarm") or by the Wakeup Timer.

Details are in the issues #375 "improve BG task interrupt configuration options" and #377 "factor out BG task code".

Better control of interrupt vectors in the C interface

In STM8 eForth the linker is called by SDCC (which is the main task of SDCC in this project). The C interface in main.c used to depend on a fixed a set of interrupt vectors which limited the configuration of core features, e.g. the Background Task. This definition is now done by an include file in the Board folder.

Details are in the issue #379 "re-order C-Stub infrastructure".

Relative Addressing for IF .. ELSE .. THEN

Some use cases require STM8 machine code branch instructions instead of ?branch or branch that use absolute addressing (e.g. relocatable code in RAM, fast ISRs). Calculating the branch offset is better left to the compiler.

This feature is implemented by exchanging control structures on the fly (i.e. by loading a bit of the compiler into RAM).

#require >REL

NVM
: test ( f -- )  IF ."  True" ELSE ."  False" THEN ;
RAM

Here, IF will compile to >Y JREQ rel and ELSE to JRA rel:

' test 20 dump
955B CD 8A C 27 B CD 89 91 5 20 54 72 75 65 20 A ___'_____ True _
956B CD 89 91 6 20 46 61 6C 73 65 81 0 0 0 0 0 ____ False______ ok

While this already solves the problem of relocatable code the most important use case of this solution is using fast bit test ([ a #b ]B@IF) or anything that can be done with Forth - Assembler interface (e.g. [ c ]A<IF).

Details are in the issue #382 "IF .. ELSE .. THEN with relative addressing".

More machine code generating words

STM8 eForth doesn't have STM8 assembler words (yet). Instead "macros" are used to generate assembler instructions (e.g. conditional branch, bit and byte transfers). A number of new "macros" have been added to better support time critical ISRs (Interrupt Service Routine).

Word What it does
[ a ]@ push contents of word at literal a to TOS
[ a ]@IF test contents of word at literal a and perform IF w\ relative branch
[ ... c ]A<IF test if A is < literal c and perform IF w\ relative branch
[ f a #b ]B! set bit #b in byte at literal a to literal f
[ a #b ]B? push flag with value of bit #b in byte at literal a to TOS
[ a #b ]B@IF test bit #b at literal a and perform IF w\ relative branch
[ a #b ]BC copy bit #b in byte at literal a to carry flag
[ a #b ]BCPL complement bit #b in byte at literal a
[ c a ]C! set byte at literal a to literal c
[ a ]C@IF test contents of byte at literal a and perform IF w\ relative branch
[ a #b ]CB copy carry flag to bit #b in byte at literal a
[ f a #b ]SPIN spin until bit #b at literal a is equal to f
[ ... n ]Y<IF test if Y is < literal n and perform IF w\ relative branch

Also see #383 "machine code generating words for ISR programming"

Examples are in the I2C code below.

An I2C Master driver

On the face of it the STM8 I2C interface is a bit difficult to use. An easy to use driver has been added to the core. Example code is here.

Issue #385 implements a generic STM8 I2C Master using the STM8 I2C peripheral. The code is event driven and can be used as a low-level driver for implementing higher-level device drivers.

The file I2CMA contains an application example. More examples are in this GitHub Gist.

Tools updates

Upgrade to Python3

Issue #390: upgrades build tools to Python3: tools like codeload.py for build and test still depended on Python2.7, which is now all but dead. Upgrading to Python3 is overdue.

The docker image TG9541/docker-sdcc also received an upgrade: the new version 3.9.9 uses Python3 and SDCC 3.9.0 (issues with the COM port simulation in uCsim in SDCC 4.0.7 couldn't immediately be resolve).

Improved codeload.py

Issue #394 improved the codeload.py serial line target response tolerance (e.g. test output) and improved the usefulness of error messages.

Issue #392 introduced support for e4thcom "conditional transfer":

From version 0.8.5 on e4thcom supports conditional transfer code after #ifdef name, e.g.

\ example: skip the rest of the file if test is defined
#ifdef test \\

\ example define test unless it's defined
#ifndef test : test ;

\ example: load PD_DDR unless it's defined
#ifndef PD_DDR \res MCU: STM8S103
#ifndef PD_DDR \res export PD_DDR

The following rules apply:

  • the conditionals #ifdef <name> or #ifndef <name> have to be the first word on a line
  • ordinary STM8 eForth console input may follow a conditional
  • #require, #include, \res or \\ may follow a conditional and have to be the first word on a line in all other cases

The change will be added to codeload3.py (update to Python3 in #390) and the new version will be the new default. The Python2.7 version will be preserved as codeload2.py.

Bug fixes

UM/MOD bug

@MrMarkB and @Picatout identified and fixed a number of bugs in UM/MOD that mode quotient and/or remainder invalid in the following cases:

  • divisor larger than $7FFF
  • MSB of the 32 bit dividend larger than the divisor
  • invalid remainder in some other cases

The defect also has some impact on M/MOD, */MOD (edge cases and remainder) and */ (remainder). There is no known effect on /MOD, MOD and /.

Following a discussion in the Forth2020 User Group (on FaceBook) it became clear that the bug has indeed a very long history: it's likely that its origin is in an early FIG Forth release for the 6502, and it has since been copied to different architectures and addressed in different ways.

Following the discussion @JeeeK provided a variant of the algorithm with improved entry and exit, and more efficient loop code.

The fixed (and impoved) code was tested with random arguments using a script provided by @MrMarkB.

Please refer to #400 and #401 for details!

Improvements and Other Changes

  • issue #396 adds the inc folder to tgz binary archives
  • issue #407 add the words LSHIFT and CRC8 for implementations of the 1-Wire ROMSEARCH algorithm

Bug fix UM/MOD

09 Feb 06:18
c3d755f
Compare
Choose a tag to compare
Bug fix UM/MOD Pre-release
Pre-release

Bug Fix

@MrMarkB and @Picatout identified and fixed a number of bugs in UM/MOD that mode quotient and/or remainder invalid in the following cases:

  • divisor larger than $7FFF
  • MSB of the 32 bit dividend larger than the divisor
  • invalid remainder in some other cases

The defect also has some impact on M/MOD, */MOD (edge cases and remainder) and */ (remainder).

There is no known effect on /MOD, MOD and /.

Please refer to #400 and #401 for details!

Tools improvements

30 Jan 20:14
2a7c278
Compare
Choose a tag to compare
Tools improvements Pre-release
Pre-release

Tools now use Python3

fixes #390: upgrade build tools to Python3

codeload.py: #ifdef for conditional transfer and other improvements

fixes #392 support e4thcom conditional transfer
fixes #394 codeload.py: improve serial line target response and error…

Minor fix

fixes #396 add inc folder to tgz binary archive

Known Bugs

  • The hi message will state that the version umber is 2.2.27.pre1 not 2.2.27.pre2 as it should

More features release

22 Dec 14:04
Compare
Choose a tag to compare
More features release Pre-release
Pre-release

STM8 eForth 2.2.27 development cycle

As most STM8 devices are now officially supported, this release is going to concentrate on features, e.g. drivers for STM8 peripherals or support of the Wakeup Timer for the Background Task (instead of using TIM2).

A simple debug console

It's sometimes useful to inspect the system (e.g. the stack) while executing a word in an application. That can be done by calling OUTER, the Forth interpreter, from user code. The new word BYE leaves this interpreter (but not that of the normal console).

Here is an example session:

#require BYE
\ ...
Closing: ./lib/BYE  ok 
: test 1 2 3 OUTER . . . ; ok
test<ENTER>.S<ENTER>
 1 2 3 <sp  ok
. 3 ok
4 ok
bye 4 2 1 ok

Note that there is no prompt indication when the "debug interpreter" gets active after test<ENTER>. Also note that any ?response from the interpreter means that the stack was emptied. Only a debug interpreter with a different type of error response would be able to prevent that.

The issue #372 "better BYE for debug console" contains technical details.

Fully Modular Background Task code

The BG code is now "fully modular" which means that it can be replaced with user code by placing a modified copy of bgtask.inc into a Board folder.

Now the background task can also be run by the STM8L RM0031 device RTC (think "alarm") or by the Wakeup Timer.

Details are in the issues #375 "improve BG task interrupt configuration options" and #377 "factor out BG task code".

Better control of interrupt vectors in the C interface

In STM8 eForth the linker is called by SDCC (which is the main task of SDCC in this project). The C interface in main.c used to depend on a fixed a set of interrupt vectors which limited the configuration of core features, e.g. the Background Task. This definition is now done by an include file in the Board folder.

Details are in the issue #379 "re-order C-Stub infrastructure".

Relative Addressing for IF .. ELSE .. THEN

Some use cases require STM8 machine code branch instructions instead of ?branch or branch that use absolute addressing (e.g. relocatable code in RAM, fast ISRs). Calculating the branch offset is better left to the compiler.

This feature is implemented by exchanging control structures on the fly (i.e. by loading a bit of the compiler into RAM).

#require >REL

NVM
: test ( f -- )  IF ."  True" ELSE ."  False" THEN ;
RAM

Here, IF will compile to >Y JREQ rel and ELSE to JRA rel:

' test 20 dump
955B CD 8A C 27 B CD 89 91 5 20 54 72 75 65 20 A ___'_____ True _
956B CD 89 91 6 20 46 61 6C 73 65 81 0 0 0 0 0 ____ False______ ok

While this already solves the problem of relocatable code the most important use case of this solution is using fast bit test ([ a #b ]B@IF) or anything that can be done with Forth - Assembler interface (e.g. [ c ]A<IF).

Details are in the issue #382 "IF .. ELSE .. THEN with relative addressing".

More machine code generating words

STM8 eForth doesn't have STM8 assembler words (yet). Instead "macros" are used to generate assembler instructions (e.g. conditional branch, bit and byte transfers). A number of new "macros" have been added to better support time critical ISRs (Interrupt Service Routine).

Word Explanation
[ a ]@ push contents of word at literal a to TOS
[ a ]@IF test contents of word at literal a and perform IF w\ relative branch
[ ... c ]A<IF test if A is < literal c and perform IF w\ relative branch
[ f a #b ]B! set bit #b in byte at literal a to literal f
[ a #b ]B? push flag with value of bit #b in byte at literal a to TOS
[ a #b ]B@IF test bit #b at literal a and perform IF w\ relative branch
[ a #b ]BC copy bit #b in byte at literal a to carry flag
[ a #b ]BCPL complement bit #b in byte at literal a
[ c a ]C! set byte at literal a to literal c
[ a ]C@IF test contents of byte at literal a and perform IF w\ relative branch
[ a #b ]CB copy carry flag to bit #b in byte at literal a
[ f a #b ]SPIN spin until bit #b at literal a is equal to f
[ ... n ]Y<IF test if Y is < literal n and perform IF w\ relative branch

Also see #383 "machine code generating words for ISR programming"

An I2C Master driver

On the face of it the STM8 I2C interface is a bit difficult to use. An easy to use driver has been added to the core. Example code is here.

Refr tp #385 "generic STM8 I2C Master" for details.

The STM8L Release

23 Oct 22:02
e9f7a61
Compare
Choose a tag to compare

About the release

This is release is very much about fully supporting STM8L devices (i.e. the likes of STM8L051F3, STM8L151C6 or STM8L152R8).

While STM8S peripherals are simple and the pin and clock configuration is trivial, the STM8L designers clearly had both "larger" and "many more" spec sheets. The "many more" one can be seen in the number of configuration dependencies the programmer has to infer when trying to use one of the many features of the peripherals. For STM8 eForth this means that things that were implicit or hard-coded needed to be restructured and tested. The device families STM8S and STM8L now are on equal footing and the generalizations gained when adding STM8L support now also makes supporting STM8S variants easier.

This release (finally) adds support for the low-end RM0013 STM8L device STM8L101, and, at the other end of the spectrum, STM8L "High density" devices like STM8L152R8 (also STM8L162 devices can be expected to work).

Configuration folders with docs for typical "Low", "Medium" and High density" devices in both families have been added (refer to Generic Targets for a list of supported devices). So far the hypothesis holds that memory and peripheral properties are the same across a range of package and memory specs variants the devices for which these "6+1 device types" and there is no evidence that the "small world of STM8 devices" is much more complicated than that. If you have reason to believe that a device doesn't fit in this simple schema please file an issue!

Devices in the following device families have not been examined:

  • STM8L RM0312 family touch sensing MCUs, e.g. STM8TL5xxx
  • STM8S STLUX lighting MCUs and STNRGxxxA power conversion MCUs (including wireless charging STWBC)

It shouldn't be big problem to get a Forth console on any of these devices, but for using the specialized peripherals it's maybe a good idea to apply ST's proprietary C-code libraries and configuration tools.

New Features

STM8L: Peripheral addresses

New or improved register address (efr-) files for e4thcom and codeload.py are now available. @Eelkhoorn first provided an improved STM8L151.efr file, and in #342 efr files for specific STM8L variants were created.

STM8L "Medium" and "High density" should work with the generic STM8L151.efr.

Peripheral register addresses of RM0031 "Low density" devices differ from STM8L "Medium density" and "High density" devices. Constants should be imported with \res MCU: STM8L051.

The final group is RM0013 "Low density" devices like STM8L101F3 or STM8L001J3: here \res MCU: STM8L101 should be used.

STM8 Timers and interrupts

Some applications, like XY-LPWM, need to use a different timer than TIM2 for the background task.
Issue #369 adds this option to the STM8L device families.

By setting BG_USE_TIM3 = 1 in globconf.inc the Background task (BG) timer will use TIM3 instead of TIM2 in STM8L "Low density" devices. STM8L "Medium" and "High density" devices can also set BG_USE_TIM1 = 1 for using TIM1. There is currently no support for TIM5 in STM8L "High density" devices.

A conflict between a simulated serial port and the background task in an STM8L051F3 device was discovered and fixed in issue #340 STM8L interrupt priority of BG task.

STM8S UART and STM8L USART configurations

STM8L devices in the RM0031 family support USART GPIO function remapping. This can easily lead to a mismatch between the USART GPIO mapping an the GPIO output initialization.

The following issues provide a solution:

  • #358 USART options for STM8L High Density devices
  • #364 STM8L: general options for USART configuration
  • #360 half-duplex USART console option for STM8L devices

Common elements in boardcore.inc of all STM8L devices, together with docs in the target folders, that also show the default mapping, make the configuration easy.

STM8S "Low" and "High density" devices use matching configuration items. STM8L152R8 has the most options.

Configuration of STM8 memory variants

Issue #330 made EEPROMBASE, the EEPROM start address, a target.inc configuration item which can be used to write device independent code.

The new feature was used in issue #339 which removed hard-coded addresses in EEALIAS so that offloading a part of the dictionary to the EEPROM now works for both STM8S and STM8L devices. STM8L "Low density" devices have a much smaller EEPROM than those in the STM8S family, of course.

Issue #355 introduced a PAGESIZE constant so that device independent code for "Flash ROM page write" can load it with #require PAGESIZE.

Note that memory variants should be defined in the configuration folder's target.inc based on the device type (STM8L or STM8S, "Low", "Medium" or "High density"). If you're engineering a product you should care for selecting the device with the right specs. For casual use memory specs are most likely not that important (if there is evidence of the opposite please share it and file an issue).

Make target for OpenOCD / stm8-gdb

OpenOCD and stm8-gdb can be of great help, especially when dealing with new devices. Issue #350 added support for an ELF target so that binaries that can be loaded into stm8-gdb can be built with make BOARD=<boardname> debug.

There are notes about using OpenOCD and stm8-gdb is in this Gist which also contain OpenOCD target configuration files for STM8L101 and STM8L051 "Low density" devices.

Experimental debug console

At times it's interesting to examine the state of a Forth program in the middle of the execution. Issue #372 introduces a very simple debug console with the words OUTER and BYE.

Here is a simple example:

#require BYE

: test ( n -- )
  FOR
    I DUP . 2 MOD 0= IF
      CR ."  Break - mind the stack - continue with BYE" CR
      OUTER THEN
  NEXT ."  done"
;

A debug session on a STM8S003F3, where a FOR ... NEXT loop is terminated manually by changing the loop counter on the return stack ($3FF growing down), looks like this:

66 7 test 7 6
 Break - mind the stack - continue with BYE
$03F0 10 dump
 3F0  23  0  0  A 8D 1E 8D 12  1 1D  0  6 8D 1E 8D 12  1_______________ ok
bye 5 4      
 Break - mind the stack - continue with BYE
$03F0 10 dump
 3F0  23  0  0  A 8D 1E 8D 12  1 1D  0  4 8D 1E 8D 12  1_______________ ok
$3FA ? 4 ok
0 $3FA ! ok  
bye done ok
. 66 ok

Note that a single misspelled word will clear both the data and the return stacks. This will not only reset the console but it will terminate the program and typing BYE in this situation will crash the system! There is clearly room for improvement.

Boards and target support

STM8L101F3 Low density support

Several differences between the STM8L101 and other STM8L devices (e.g. option bytes) delayed STM8 eForth support for a long time. STM8 eForth now supports RM0013 devices with NVM, the TIM2 based BG task and also the simulated serial interface. A binary release is available and the ordinary STM8 eForth workflows can be used.

Please refer to the docs in the configuration folder STM8L101F3 and the following issues:

  • #349 Add support for STM8L101 and STM8L001
  • #356 improve STM8L101 docs and efr file
  • #356 STM8L101F3: improve target.inc and docs Documentation

Note that statements in the Wiki and other docs that the STM8L101 would not be supported have been changed. Using OpenOCD and gdb-stm8 were instrumental for adding support of this MCU.

STM8L051F3 Low density support

Support for RM0031 STM8L "Low density" devices has long been available. Test results with STM8L devices from applications in the community were used to revise support. Configuration options (e.g. USART, BG timer, simulated serial interface) and docs are now consistent with other STM8L devices.

Please refer to the docs in the STM8L051F3 configuration folder.

STM8L Medium density support

Although there has long been the STM8L-Discovery configuration by @plumbum requests for a more active support of STM8L "Medium density" devices like STM8L151K4 was a recurrent issue (e.g. #218, #267, #268 or #287).

@Eelkhoorn finally sent an STM8L151K4 breakout board to @TG9541 and contributed to configuration files and to testing. Issue #354 implemented support for RM0031 STM8L "Medium density" devices, independent of "Medium+" and "High density" devices.

Please refer to the docs in the STM8L151K4 configuration folder where console configuration options are listed.

STM8L High density support

STM8L "High density" devices have a rather rich feature set and more memory than other STM8L devices. Issue #358 added support for these devices and also describes the various console options. It's possible that this configuration also works for "Medium+ density" devices like the STM8L152R6 but no samples have been tested and feedback would be appreciated.

Please refer to the ...

Read more