Skip to content

UM/MOD Bugfix and Improvements Release

Compare
Choose a tag to compare
@TG9541 TG9541 released this 09 Mar 05:49
22185fd

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