Installing FlashForth

Install MPLABX and XC16. Select the processor type in the MPLABX.
Update the chip specific include file ( etc.) with frequency, PLL, serial, pin and other settings.
Update with memory and include file details, if not alreday present.
Update the configs.c file with settings for your chip. These can be generated by MPLABX.
The clock frequency setting in the chip specific include file must match configuration used in configs.c.

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

FlashForth has been run at least on
dsPIC33CK64MC105,dsPIC30F4012, dsPIC30F4013, dsPIC33FJ128GP802, dsPIC33EP256GP502, dsPIC33CK64MP205,
PIC24FJ64GU205, PIC24EP256GP202, PIC24FJ128GB202, PIC24FJ128GA704, PIC24F32KA304 and PIC24HJ128GP502.

FlashForth should work on all 16-bit PIC chips with enough flash(>=64Kbytes) and enough ram. New chips may require some adpatation, typically in the flash write routines.

FlashForth works on the Curiosity Nano boards with dsPIC33CK64MP105 or PIC24FJ64GU205.

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 nfa>lfa 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 and Atmega, the interrupts use the parameter stack of task that happened to be executing when the interrupt occured.

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] :


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

PIC24: W0 W1 W2 W3
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 interrupt vectors are stored in flash in the Alternate Interrupt Vector Table. The PIC24 and dsPIC33 interrupt vectors are stored in ram, pointed to from the Alternate Interrupt Vector Tables. 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 10int! ; 
' irq_init is turnkey

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

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

FlashForth V4.3 on dsPIC30F
(C) Mikael Nordman GPL V3
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>