Colibri Forth
Colibri Forth is built upon MECRISP (https://mecrisp.sourceforge.net, written by Matthias Koch), the Stellaris variant, an advanced Forth, that compiles to machine code on the target itself, for optimal performance. Additional work/inspiration has been source from Peter Schmid's Mecrisp-Cube project (https://github.com/spyren/Mecrisp-Cube).
Architecture
Forth is a stack-oriented language that has 2 stacks, one for data and one call stack for with return addresses. It has very simple syntactic rules;
1. Everything is a "word" which must be surrounded by whitespace. All non-whitespace bytes are allowed in word. 1. Backslash is start of comment, and everything will be filtered out until parser reaches new line. 1. Everything between a pair of parentheses " ( xyz ) " is a comment. They can be stretching multiple lines. Nested parentheses are not supported. 1. Thereafter, try to locate word in dictionary. If found, "use" (depends on whether compiling or executing) it. 1. If word is not found in dictionary, try to parse it as a number. If successful, push number on stack. 1. All words operate on the stacks. Typically manipulating the Top-Of-Stack (TOS), by popping value(s) off the top and pushing the result back on top. 1. Forth is NOT a unified/standardized language and except for a small number of core words, there is no consensus of what the base vocabulary is. Many think that the nearest a standard (ANS Forth) is too bloated and not suitable for all the target devices that a more lean Forth can run on. This means that many libraries won't work out-of-the-box and will require tweaking by the user.
Colon ":" is the word to define other words, and the definition ends with semicolon ";". Example
: add4 4 + ; \ adds 4 to the value on TOS.
It is common to put the stack manipulation info as a comment after the defined word. Example
: add4 ( n -- n+4 ) 4 + ;
It is the same thing, just human-readable comment to hint at what the word does.
The Full Documentation of Mecrisp is written by Terry Porter and published at https://mecrisp-stellaris-folkdoc.sourceforge.io/
Mecrisp and Colibri Forth are not case-sensitive, but many other Forth variants are.
Interactivity
Forth is an interactive language, which is awesome for embedded development. One can simply hook up a serial terminal and do development on the target itself. One can interactively work with the MCU registers and peripherals to figure out the proper configuration/operation without doing a full erase+write cycle to the flash memory. We can execute code directly from RAM and not commit it to Flash until we have worked out the details.
Cookbook
We are going to assemble useful snippets and words that will be useful, but not common enough to be included in the standard vocabulary. We call this the Colibri Forth Cookbook and will be a slowly growing document of Forth for the Colibri family.
Resources
https://mecrisp-stellaris-folkdoc.sourceforge.io/ https://www.spyr.ch/twiki/bin/view/MecrispCube
Default Word List
(It will take a while to document all this)
dup drop ?dup swap nip over tuck rot -rot pick 2dup (n m -- n m n m ) Duplicates the two top cells. 2drop (n m -- ) Drops the two top cells 2swap ( n1 n2 n3 n4 -- n3 n4 n1 n2 ) Swaps the two top cells with then next two cells 2nip ( n1 n2 n3 n4 -- n3 n4 ) Removes the two cells below the two top cells 2over ( n1 n2 n3 n4 -- n1 n2 n3 n4 n1 n2 ) Duplicates the two cells below the top two cells. 2tuck ( n1 n2 n3 n4 -- n3 n4 n1 n2 n3 n4 ) Put a two cell duplicate below the next two cells. 2rot 2-rot ( n1 n2 n3 n4 n5 n6 -- n5 n6 n1 n2 n3 n4 ) Rotates the top two cells down two levels 2>r 2r> 2r@ 2rdrop d2/ d2* dshr dshl dabs dnegate d- d+ s>d um* m* ud* udm* */ */mod u*/ u*/mod um/mod m/mod ud/mod d/mod d/ x* x/ 2! 2@ du< du> d< d> d0< d0= d<> d= sp@ sp! rp@ rp! depth rdepth >r r> r@ rdrop rpick roll -roll and bic or xor * clz ror rol arshift rshift lshift 0= 0<> 0< true false >= <= < > u>= u<= u< u> <> = min max umax umin move fill @ ! +! h@ h! h+! c@ c! c+! bis! bic! xor! bit@ hbis! hbic! hxor! hbit@ cbis! cbic! cxor! cbit@ 8flash! flashpageerase eraseflash eraseflashfrom initflash hflash! flushflash + - 1- 1+ 2- 2+ cell+ negate not shr shl 2* cells 2/ abs u/mod /mod mod / even base binary decimal hex hook-emit hook-key hook-emit? hook-key? emit key emit? key? hook-pause pause uart redirect unredirect serial-emit serial-key serial-emit? serial-key? baudrate! wordlength! paritybit! stopbits! cexpect accept tib >in current-source setsource source query compare cr bl space spaces [char] char ( \ ." c" s" count ctype type hex. h.s u.s .s words unused 12bitencoding registerliteral, movwmovt, call, literal, create does> <builds ['] ' postpone inline, ret, exit recurse state ] [ : ; execute immediate inline compileonly 0-foldable 1-foldable 2-foldable 3-foldable 4-foldable 5-foldable 6-foldable 7-foldable constant 2constant smudge setflags aligned align align8, h, , ><, string, allot forgetram compiletoram? compiletoram compiletoflash (create) variable 2variable nvariable buffer: dictionarystart dictionarynext skipstring find hook-find (find) cjump, jump, here flashvar-here then else if ahead repeat while until again begin k j i leave unloop +loop loop do ?do case ?of of endof endcase token parse digit number .digit hold hold< sign #> x#S x# #S # <# x. x.n ud. d. u. . evaluate interpret hook-quit quit TCB threadid argument attr XT R0 S0 #user /user his task /task construct start-task stop awaken skeleton osNewDataStack [C C] terminate suspend resume halt kill mutex-init /mutex get release /osThreadAttr thName+ thAttrBits+ thCbMem+ thCbSize+ thStackMem+ thStackSize+ thPriority+ thTzModule+ /osEventFlagsAttr /osMessageQueueAttr /osMutexAttr /osSemaphoreAttr osKernelGetTickCount osKernelGetTickFreq osKernelGetSysTimerCount osKernelGetSysTimerFreq osDelay osDelayUntil osThreadNew osThreadGetId osThreadGetState osThreadGetName osThreadSetPriority osThreadGetPriority osThreadYield osThreadSuspend osThreadResume osThreadExit osThreadTerminate osThreadGetStackSpace osThreadGetCount osThreadEnumerate xPortGetFreeHeapSize pvPortMalloc vPortFree vTaskSetThreadLocalStoragePointer pvTaskGetThreadLocalStoragePointer osThreadFlagsSet osThreadFlagsClear osThreadFlagsGet osThreadFlagsWait osTimerNew osTimerGetName osTimerStart osTimerStop osTimerIsRunning osTimerDelete osEventFlagsNew osEventFlagsSet osEventFlagsClear osEventFlagsGet osEventFlagsWait osEventFlagsDelete osMutexNew osMutexAcquire osMutexRelease osMutexGetOwner osMutexDelete osSemaphoreNew osSemaphoreAcquire osSemaphoreRelease osSemaphoreGetCount osSemaphoreDelete osMessageQueueNew osMessageQueuePut osMessageQueueGet osMessageQueueGetCapacity osMessageQueueGetMsgSize osMessageQueueGetCount osMessageQueueGetSpace osMessageQueueReset osMessageQueueDelete eint? eint dint ipsr nop unhandled reset
Pre-loaded for Colibri MCU1
sm7391-pressure sm7391-rd sm7391-raw sm7391-init SM7391.ADDR ring> >ring ring? ring# ring-step c++@ init-ring crc16 crc16h crc16@ crc16-table buffer. buffer-cpy stack>buffer spi!ssel fix-ssel spiN> >spiN spi2> >spi2 spi-push0 spi-push spi-rxdrop spi-rxrdy spi-txrdy spi1>dr >spi spi> >spi> -spi +spi spi? SPI1-DR SPI1-SR SPI1-CR2 SPI1-CR1 SPI1 ssel.bit ssel.addr MOSI MISO SCLK ssel i2c-inspect i2c-xfer i2c-rd i2c-wr i2c-setn i2c-stop i2c-start i2c>h i2c> >i2c i2c++ i2c-addr i2c-reset i2c.ptr i2c.buf i2c. I2C2-TXDR I2C2-RXDR I2C2-ICR I2C2-ISR I2C2-TIMINGR I2C2-CR2 I2C2-CR1 I2C2 SDA SCL PA15 PA14 PA13 PB12 PA12 PA11 PA10 PA9 PA8 PB7 PA7 PB6 PA6 PB5 PA5 PB4 PA4 PB3 PA3 PB2 PA2 PA1 PA0 io. io-mode! io-config OMODE-FAST OMODE-SLOW OMODE-WEAK OMODE-OD OMODE-PP OMODE-AF-OD OMODE-AF-PP IMODE-ADC IMODE-LOW IMODE-HIGH IMODE-FLOAT iox! io! ioc! ios! io@ io-base io-port io-mask io# io bit! bit GPIO.AFRH GPIO.AFRL GPIO.BSRR GPIO.ODR GPIO.IDR GPIO.PUPDR GPIO.OSPEEDR GPIO.OTYPER GPIO.MODER GPIO-BASE dump dump16 hexdump hex.empty h.2 h.4 u.2 u.4 .v [ifndef] [ifdef] [if] [then] [else] [else-match] nexttoken