Installing FlashForth

Select the processor type in the IDE. Update relevant include file with clock configuration and frequency and other settings.

To get the smallest memory footprint use the following linker setting in XC16-LD

Init data sections         OFF
Pack data template         ON
Create handles             OFF
Create default isr         ON
Exclude standard libraries ON

The floating point words need the standard libraries and handles.

Init data sections         OFF
Pack data template         ON
Create handles             ON
Create default isr         ON
Exclude standard libraries OFF

Compile the project and program the HEX file to the PIC with your favourite device programmer.

FlashForth has been run at least on these chips.

dsPIC30F4012, dsPIC30F4013 
dsPIC33FJ128GP802 dsPIC33EP256GP502
PIC24EP256GP202 PIC24HJ128GP502 PIC24F16KA102 PIC24FV16KM PIC24FV32KA302 PIC24FV16KL402

FlashForth should work on all 16-bit PIC chips with enough flash(>=24Kbytes) and enough ram.

Inlining of words

FF can compile location independent assembler primitives as inline code. The shortest of these words have the inline bit set in the word header for automatic inlining.

Individual words can be inlined by prefixing the word with INLINE.

: newrot inline rot ; 

When compiling a new word that should be inlined automatically, the inline flag can be set with the word INLINED.

On the PIC24 the following words are automatically inlined by the compiler.

cwd ivt aivt [i i] ei di u1txq u1rxq drop over >r r> r@
invert negate 1+ 2+ 1- 2- 2* 2/ !p>r r>p p+ p2+ >body
cell cell+ cells char+ chars 2drop 0 1 nip endit
rdrop bl ticks cpu_clk false true + - and or xor !p @p

On PIC24 the following words can be inlined with INLINE.

mset mclr mset bset bclr lshift rshift sp! sp@ swap rot m+
um* um/mod u/mod m* sm/rem /mod mod /

Also words defined by CONSTANT, VARIABLE, 2CONSTANT and 2VARIABLE can be inlined. They compile the constant and the variable address as inline literal code.

If you append the definition with INLINED, the compiler will later compile the constant as an inline literal.

34 constant thirtyfour inlined
: native-inline-34 thirtyfour ;

Interrupt handling

Interrupt routines can be written in assembly or in Forth. FF interrupt words have to be ended with ;I .

On PIC24-30-33, the interrupts use an 8 cell frame on the return stack as the parameter stack.

In general Forth words that normally would be used in an interrupt word are interrupt safe.
Words that start the interpreter or compile new words should not be used in an interrupt.
It is not possible to store to flash or eeprom in an interrupt routine.

The following registers are saved on the return stack by [I and restored by I] :

PIC24: TBLPAG W13 RCOUNT
PIC30: W0 W1 W2 W3 TBLPAG W13 RCOUNT
PIC33: TBLPAG W13 RCOUNT

The following registers are always preserved before the interrupt word is executed:

PIC24: W0 W1 W2 W3
PIC30: 
PIC33: W0 W1 W2 W3

To activate the interrupt you store the interrupt word xt into the interrupt vector.

' my_irq 10 int!

The dsPIC30, and the PIC24FK interrupt vectors are stored in flash in the Alternate Interrupt Vector Table. Other PIC24 and dsPIC33 interrupt vectors are stored in ram, pointed to from the Alternate Interrupt Vector Tables. The PIC24/33 E series only has a main Interrupt Vector Table which points to a ram area. The PIC24 and dsPIC33 interrupt vectors in ram are cleared at warm start, so to enable the interrupt word at startup, a initialization word must be used.

: irq_init ['] my_irq 10 int! ; 
' irq_init is turnkey

To use individual interrupt sources the interrupt enable bits and flag bits for each interrupt source must be used.

On the dsPIC30 and PIC24FK that stores the interrupt vectors in flash, the original vector can be restored with INT/ .

10 int/

Register usage and memory usage

The return stack pointer is W15.
The parameter stack pointer is W14.
The P register uses W13
Assembly words use W0..W3.
In addition SKIP, SCAN, N= use W4 and W5.

Sample session for dsPIC 30F

warm
FlashForth V4.3 on dsPIC30F
(C) Mikael Nordman GPL V3
ESC
flash ok <$,flash>
eeprom ok <$,eeprom>
ram ok <$,ram>
decimal ok <#,ram>
bin ok <%,ram>
hex ok <$,ram>
see see
41b0 0007 faad rcall '
41b2 0007 f61f rcall cr
41b4 0007 f7c3 rcall hex
41b6 0078 0f3e mov.w [W14++], [W14]           \ DUP
41b8 0007 fe2e rcall u.4
41ba 0078 0f3e mov.w [W14++], [W14]           \ DUP
41bc 0007 f1c4 rcall cf@
41be 0007 fe2b rcall u.4
41c0 0007 fe2a rcall u.4
41c2 0007 ffd8 rcall (see)
41c4 0007 f616 rcall cr
41c6 00e0 001e cp0 [W14]                      \ IF also DUP
41c8 003a fff6 bra nz, 41b6                   \ IF also 0=
41ca 0057 0762 sub W14, 2, W14                \ DROP
41cc 0006 0000 return
ok <$,ram>
see ms
3aa2 0007 fff9 rcall ticks
3aa4 0007 f7e7 rcall +
3aa6 0007 f488 rcall pause
3aa8 0078 0f3e mov.w [W14++], [W14]           \ DUP
3aaa 0007 fff5 rcall ticks
3aac 0007 f7ef rcall -
3aae 0007 f83a rcall 0<
3ab0 00e0 002e cp0 [W14--]                    \ IF 
3ab2 0032 fff9 bra z, 3aa6                    \ IF
3ab4 0057 0762 sub W14, 2, W14                \ DROP
3ab6 0006 0000 return
ok <$,ram>
see t1go
441c 0024 3fe0 mov 43fe , W0                 \ literal for tloop address
441e 0078 2f00 mov.w W0, [++W14]
4420 0007 ffe3 rcall t1
4422 0007 ff2e rcall tinit
4424 0007 ffe1 rcall t1
4426 0007 ff63 rcall run
4428 0006 0000 return
ok <$,ram>
tasks operator t1 ok <$,ram>
1 ok <$,ram>1
2 ok <$,ram>1 2
34 ok <$,ram>1 2 34
+ ok <$,ram>1 36
- ok <$,ram>ffcb
. -35 ok <$,ram>