I am happy to announce Mecrisp-Quintus, a native code Forth for RV32IM instruction set written entirely in assembler. It is available in the download area of mecrisp.sourceforge.net
Its first targets are Picosoc by Clifford Wolf on a Lattice HX8K FPGA breakout board, and the LM4F120 Stellaris Launchpad, as I wrote an emulator called Mamihlapinatapai which allows to run RV32IM opcodes on ARM Cortex M3/M4.
Now, it is time to support real RISC-V hardware. It is difficult for me to find an HiFive1 here in Germany, therefore, I am looking for help. Is there a Forth freak who has hardware available and wishes to help ? Technically, a bare metal UART echo written in plain assembler is necessary to port Mecrisp-Quintus to a new piece of hardware, along with adjustments to the memory map.
If you are interested, just drop me a line. I am available for assistance.
Best wishes from Germany and hats off to the SiFive team,
Matthias
thank you for donating a board for me thru JĂĽrgen Pintaske, your surprise is very much appreciated and I released Mecrisp-Quintus 0.4 today, with support for the HiFive1.
A disassembler and a s31.32 fixpoint math library by Andrew Palm are included.
My main stumbling block right now is, how do I interface to the hardware I2C on the HiFive1 Rev B from Forth? Is Mecrisp-Quintus a “bare metal” implementation? Do I need to write an I2C driver in Forth? I can probably find one written in C and translate it, assuming that Quintus provides the basic mechanism for poking the control registers.
Mecrisp-Quintus is bare metal, you need to write your own I2C driver by reading the datasheet of the chip and poking the IO registers mentioned there. By the way, it’s usually easier to bit-bang I2C. Have a look at mecrisp-stellaris-2.5.0/stm32f303/imu.txt for an example. You’ll just have to change the GPIO access code.
\ -----------------------------
\ Bit-Bang I2C Implementation
\ -----------------------------
\ Low-level target specific pin configurations
1 6 lshift constant i2c-scl
1 7 lshift constant i2c-sda
: scl-high ( -- ) i2c-scl portb_bsrr ! ;
: scl-low ( -- ) i2c-scl 16 lshift portb_bsrr ! ;
: sda-high ( -- ) i2c-sda portb_bsrr ! ;
: sda-low ( -- ) i2c-sda 16 lshift portb_bsrr ! ;
: scl-@ ( -- f ) 20 0 do loop i2c-scl portb_idr bit@ ;
: sda-@ ( -- f ) 20 0 do loop i2c-sda portb_idr bit@ ;
: I2C-Init ( -- )
%01 6 2* lshift
%01 7 2* lshift or portb_moder bis! \ Set both I2C lines as outputs
i2c-scl i2c-sda or portb_otyper bis! \ Open Drain mode
scl-high sda-high \ Bus free default state. During communication, SCL is low for default.
;
\ Low-Level I2C-Protocol
: I2C-Start ( -- ) sda-high scl-high sda-low scl-low ;
: I2C-Stop ( -- ) sda-low scl-high sda-high ;
: I2C-Bit-TX ( f -- )
if sda-high else sda-low then
scl-high begin scl-@ until
scl-low
;
: I2C-Bit-RX ( -- f )
sda-high
scl-high begin scl-@ until
sda-@
scl-low
;
\ Higher level I2C-Protocol
: I2C-TX ( b -- f )
dup $80 and I2C-Bit-TX
dup $40 and I2C-Bit-TX
dup $20 and I2C-Bit-TX
dup $10 and I2C-Bit-TX
dup $08 and I2C-Bit-TX
dup $04 and I2C-Bit-TX
dup $02 and I2C-Bit-TX
$01 and I2C-Bit-TX
I2C-Bit-RX 0=
;
: I2C-RX ( f -- b )
I2C-Bit-RX $80 and
I2C-Bit-RX $40 and or
I2C-Bit-RX $20 and or
I2C-Bit-RX $10 and or
I2C-Bit-RX $08 and or
I2C-Bit-RX $04 and or
I2C-Bit-RX $02 and or
I2C-Bit-RX $01 and or
swap 0= I2C-Bit-TX
;
\ I2C device detection
: u.2 s>d <# # # #> type ;
: i2c-ping? ( addr - f ) i2c-start shl i2c-tx i2c-stop ;
: i2c-7bitaddr? ( addr -- f ) dup $7 u>= swap $77 u<= and ;
: i2c-detect ( -- )
i2c-init cr
base @ hex
4 spaces $10 0 do i space u.2 loop
$80 0 do
i $0f and 0= if
cr i u.2 [char] : emit space
then
i i2c-7bitaddr? if
i i2c-ping? if \ does device respond?
i space u.2
else
." --"
then
else
." "
then
loop
cr base !
;
Bare metal is fine for this application. And it builds now! w00t. I have the Linux version working too. Thank you. I will study the I2C spec and these examples while waiting for my device to arrive. This should be a good way to build my project while also learning the new RISC-V stuff (really tired of Atmel and Cortex M0) and getting back into the innards of Forth.
What is the command to include and compile a Forth source file? Or more generally, exactly which dialect of Forth is this?