Code Reviews and Libraries

Code Review, is the act of collaborating with other programmers to check code for mistakes.

A library is a collection of code reused to develop software.

Disclaimer: I’m not a programmer, I’m a electronics technician/designer who stumbles and fumbles his way thru code. I enjoy the process of writing code but only when the end result is a working hardware solution.

Can Forth Code be Reviewed, are Libraries Useful ?

What follows are just a few of my thoughts on these matters, my opinion only, and I’m often wrong.

Every Forth Program is a Different Programming Language

Because Forth programs soon morph into the language of the problem they solve, technically every Forth program is a different programming language, unlike say Pascal or C where the language syntax is always the same from one program to the next.

Note

Would you ask a Haskell programmer to review your Perl code ?

Every Forth Implementation Targets a Specific MCU or MCU Family

Forth is as different as the hardware it runs on. Even in the same hardware family, say STM32xx, Mecrisp-Stellaris Forth may have different Kernel Words between models, depending on the hardware variations.

Examples

Set a BIT:-

Mecrisp-Stellaris for STM32Fxx

$48000800 constant PORTC_Base
PORTC_BASE $18 + constant PORTC_BSRR
4 constant Anode    \ PC4
1 Anode lshift PORTC_BSRR !   ( Anode high )

Flashforth for PIC:-

$ffc2 constant adcon0
%10 adcon0 mset \ Start conversion

Note

Would a Mecrisp-Stellaris user ask a Flashforth user to review their code ?

Most Forth Development Environments Are Different

Forth allows a programmer to design their own Development Environment.

Matthias Koch

Will write his memory mapped code something like this:-

$48000000 constant PORTA_Base
$48000400 constant PORTB_Base
$48000800 constant PORTC_Base
$48000C00 constant PORTD_Base
$48001400 constant PORTF_Base

PORTC_BASE $00 + constant PORTC_MODER    \ Reset 0 Port Mode Register - 00=Input  01=Output  10=Alternate  11=Analog
PORTC_BASE $04 + constant PORTC_OTYPER   \ Reset 0 Port Output type register - (0) Push/Pull vs. (1) Open Drain
PORTC_BASE $08 + constant PORTC_OSPEEDR  \ Reset 0 Output Speed Register - 00=2 MHz  01=25 MHz  10=50 MHz  11=100 MHz
PORTC_BASE $0C + constant PORTC_PUPDR    \ Reset 0 Pullup / Pulldown - 00=none  01=Pullup  10=Pulldown
PORTC_BASE $10 + constant PORTC_IDR      \ RO      Input Data Register
PORTC_BASE $14 + constant PORTC_ODR      \ Reset 0 Output Data Register
PORTC_BASE $18 + constant PORTC_BSRR     \ WO
PORTC_BASE $20 + constant PORTC_AFRL     \ Reset 0 Alternate function  low register
PORTC_BASE $24 + constant PORTC_AFRH     \ Reset 0 Alternate function high register
PORTC_BASE $28 + constant PORTC_BRR      \ Reset 0 Bit Reset Register

He will then use this memory mapping code like so :-

4 constant Anode    \ PC4
5 constant Cathode  \ PC5

%01 Anode   2* lshift
%01 Cathode 2* lshift or PORTC_MODER bis! \ Set anode and cathode as output

Note

“The above code may seem simple enough, but try using this method to set PC4 and PC5 to mode INPUT ? Be sure to test your code and make sure it works first.

The Author

My memory mapping code is different, because I parse it automatically from CMSIS-SVD :-

$48000000 constant GPIOA_MODER ( GPIO port mode register )
$48000004 constant GPIOA_OTYPER ( GPIO port output type register )
$48000008 constant GPIOA_OSPEEDR ( GPIO port output speed  register )
$4800000C constant GPIOA_PUPDR ( GPIO port pull-up/pull-down  register )
$48000010 constant GPIOA_IDR ( GPIO port input data register )
$48000014 constant GPIOA_ODR ( GPIO port output data register )
$48000018 constant GPIOA_BSRR ( GPIO port bit set/reset  register )
$4800001C constant GPIOA_LCKR ( GPIO port configuration lock  register )
$48000020 constant GPIOA_AFRL ( GPIO alternate function low  register )
$48000024 constant GPIOA_AFRH ( GPIO alternate function high  register )
$48000028 constant GPIOA_BRR ( Port bit reset register )

I also prefer to not have to consult the databook when manipulating Register Bitfields of more than ONE BIT, such as GPIOx_MODER which is TWO BITS wide, so I automatically generate Words to make it easy for me.

My thanks to Manfred Mahlow [manfredmahlow] for his bf! code.

: bf! ( bits bf-offs a-addr mask -- )
  swap >r over lshift >r lshift r@ and r> r@ bic! r> bis! ;

%00 constant INPUT
%01 constant OUTPUT
%10 constant ALT-FUNCT
%11 constant ANALOG

: GPIOA_MODER_MODER12 24 $48000000 %11 ;   ( PA12 mode )

OUTPUT GPIOA_MODER_MODER12 bf!     ( PA12 --> OUTOUT --> LED1 Anode )
1 GPIOA_ODR_ODR12 bf!              ( LED1 --> ON )

Jeelabs

\ Set anode and cathode as output
 OMODE-PP Anode    io-mode!
 OMODE-PP Cathode  io-mode!

[jeelabs] has made great use of the STM32F103 based “Blue Pill” from China. This board is incredibly cheap, but before you race out and buy 20 of them, be aware that the quality does vary a lot.

A friend recently bought seven ‘Blue Pills’ from two Amazon sellers and not one worked properly, they were 100% defective, but luckily Amazon refunded her money. She then bought two ST Nucleo STM32F103 boards and both worked perfectly.

The Jeelabs development environment includes libraries such as io.fs hal.fs and pins48.fs etc. To find out what “io-mode!” does, you’d have to grab the library and understand it.

Personally I feel that “libraries” are a waste of time with Forth on STM32Fxx (my opinion only, please don’t burst a blood vessel if you’re a C library addict) because the permutations are astronomical. For instance the STM32F103 has:-

  • 38 Peripherals
  • 549 Registers
  • 3857 Register Bitfields.

Would any Author live long enough to implement Forth libraries for all the permutations for all the STM32F103 peripherals ? Take a look at Arduino for the STM32F103, how complete are the libraries ? and they have been at it for years.

I feel that the massive configuration options, coupled with small embedded non volatile memory size and small RAM size require purpose targeted code along with intimate hardware knowledge, to use Forth on a STM32Fxx.

Note

Charles Moore, the inventor of forth said ” Don’t add extra code that your Forth program doesn’t need, add it later when you need it”.