.. index:: zeptoforth: review .. _zeptoforth-review: Zeptoforth Review ================= Zeptoforth is a **LARGE** Forth by Travis A Bemann with an emphasis on computing and a welcome addition to the Cortex-M Forth family. Zeptoforth reuses some Mecrisp-Stellaris code, such as terminal routines (with permission of Matthias Koch) but it is mostly his own source according to Travis. Supported Hardware ------------------ Zeptoforth currently supports the following MCU's * STM32F407 * STM32F746 * STM32L476 * RPi Pico (RP2040) My review was performed on a *STM32F407 Discovery Board* using Zeptoforth 0.16.0. Downloading ----------- Zeptoforth is freely available on Github under the MIT license and may be cloned here. :: git clone https://github.com/tabemann/zeptoforth.git Documentation ------------- zeptoforth/docs contains \*.md files which I personally don't find useful however html files including an index and search facility may be generated by running: :: zeptoforth/html/gmake. The doc looks like the index below, and while it could use a lot more general user info it is actually pretty impressive as regards Dictionary details. .. image:: zeptoforth-doc.jpg Dictionary ---------- Zeptoforth has multitasking, blocks, a block editor, a scheduler, modules and a ton of other stuff. If a Forth is measured by the size and breadth of its Dictionary, Zeptoforth might just be the 100 pound Gorilla of Cortex-M Forths. .. warning:: Zeptoforth is not designed to run on Cortex-M0. Words ~~~~~ Zepoforth is just *PACKED* with heavy duty Words, and I believe there are more available via the module system. :: words restore-state init swd-module init rng-module action-pool-module task-pool-module line-enabled? disable-line enable-line init line-internal-module ansi-term-module lock-module chan-module fchan-module tqueue-module init free! resize! allocate! x-memory-management-failure resize free allocate allocate-module pool-module see-for-gas see see-xt-for-gas see-xt disassemble-for-gas disassemble disassemble-internal-module init led-module schedule-module init ms unused task-unused forget-ram task-module gpio-module init int-io-module ms init systick-module init atanh acosh asinh tanh cosh sinh f** x-domain-error acos asin atan2 atan tan cos sin ln lnp1 exp expm1 factorial sqrt fi** 2r@ d* dmax dmin dabs 2rot 4dup pi 2find-get-value find-get-value 2find-value find-value hfind-value bfind-value 2find-get-index find-get-index 2find-index find-index hfind-index bfind-index 2iter-get iter-get 2iter iter hiter biter count+loop count-loop while-loop loop-until choose option cornerstone marker interrupt-module init unimport import end-module begin-import-module-once begin-import-module begin-module-once begin-module x-module-not-found x-module-already-defined x-order-overflow x-module-stack-underflow x-module-stack-overflow init flush-console wake wake-hook wait wait-hook f. (f.) format-fixed ud. d. (ud.) (d.) format-double-unsigned format-double #> sign #s # <# hold [then] [if] [else] .\( .\" s\" c\" esc-string-module defer@ defer-flash@ defer-ram@ defer! defer-flash! defer-ram! defer x" ;] [: skip-until dump unloop leave j i +loop loop ?do do wordlist ram-wordlist flash-wordlist safe-type-unsigned safe-type-integer safe-type safe-emit end-critical begin-critical 2variable variable hvariable bvariable aligned-buffer: buffer: user-aligned-buffer: user-buffer: 2user user huser buser endcasestr ofstrcase ofstr endcase endof of case equal-strings? 2field: field: hfield: bfield: +field end-structure begin-structure does> no-word-being-built name word-info words lookup execute-defined? defined? suppress triggers averts .s h.16 h.8 h.4 h.2 h.1 depth ?dup align abs -rot max min inlined-flag compiled-flag immediate-flag visible-flag tos cell+ cells cell hex decimal octal binary internal-module forth-module false true init try ?raise f/ f* d/ ud/ d/mod uf/mod ud/mod m/mod um/mod u*/mod u*/ */mod */ udm* ud* m* um* um+ d- d+ dnegate 2arshift 2rshift 2lshift d0>= d0<= d0> d0< d0<> d0= d<= d>= d> d< du<= du>= du> du< d<> d= 2tuck 2nip 2dup 2over 2swap 2drop format-integer format-unsigned reverse move u. . debugu. (u.) (.) [char] char compile-cstring c" s" ." .( word-align, undefer-lit commit-flash end-compress-flash again until repeat while begin then not-following-if else if compile-to-ram-only not-compiling token-expected 2constant constant ; :noname : parse-digit parse-base parse-unsigned parse-integer failed-parse bel nak ack xoff xon refill rstack-underflow rstack-overflow stack-underflow stack-overflow display-normal display-red quit abort evaluate >body find-all find-all-dict find 3dup equal-case-strings? to-upper-char ( \ token token-end token-start newline? ws? isb dsb warm reboot set-order get-order set-current get-current sp! sp@ rp! rp@ rdrop r@ r> >r cstring, ram-align, flash-align, align, 2reserve reserve hreserve breserve 2flash-reserve flash-reserve hflash-reserve bflash-reserve 2ram-reserve ram-reserve hram-reserve bram-reserve 2, , h, b, 2current! current! hcurrent! bcurrent! 2flash, flash, hflash, bflash, 2ram, ram, hram, bram, 2@ @ h@ b@ bit@ hbit@ bbit@ bic! hbic! bbic! bis! hbis! bbis! bit +! h+! b+! 2! ! h! b! unknown-word recurse literal lit, postpone ['] ' token-word compile, compressing-flash compress-flash compiling-to-flash? compile-to-flash compile-to-ram ] [ visible inlined compile-only immediate [inlined] [compile-only] [immediate] init welcome exit pause ?execute execute sleep disable-int enable-int key? key count serial-type type cr space emit? emit allot here flash-latest! ram-latest! latest! flash-latest ram-latest latest flash-here! flash-allot flash-here ram-here! ram-allot pad ram-here u>= u<= u> u< 0>= 0<= 0> 0< 0<> 0= >= <= > < <> = 4/ 2/ 4* 2* 4- 2- 1- 4+ 2+ 1+ umod mod u/ / * - + negate not bic xor or and arshift rshift lshift tuck nip roll pick rot over swap dup drop license copyright kernel-date kernel-version kernel-platform time-4-handler-hook time-3-handler-hook time-2-handler-hook adc-handler-hook exti-4-handler-hook exti-3-handler-hook exti-2-handler-hook exti-1-handler-hook exti-0-handler-hook systick-handler-hook pendsv-handler-hook svcall-handler-hook null-handler-hook fault-handler-hook validate-dict-hook pause-hook refill-hook key?-hook key-hook emit?-hook emit-hook failed-parse-hook handle-number-hook prompt-hook order order-count input-size input input# >in sys-ram-dict-base build-target source parse-buffer parse# >parse handler rstack-end rstack-base stack-end stack-base flash-end flash-base ram-end ram-base dict-base pause-enabled base state init-handlers flash-block-size flash-align, 2flash! flash! erase-all flash!-already-written hflash! bflash! ok Installation ------------ "Gmake: was all that was required and Zeptoforth built everything instantly with no errors or warnings. As it is developed on Linux, this is a good sign. Terminal -------- Zeptoforth offers two types of Terminal connections 1. :ref:`SWDCOM`, a high speed client designed by Jan Bramkamp which uses Stlink via the MCU SWD interface over USB. Works for Linux, FreeBSD etc. 2. USART serial via 3.3v/USB dongle or USB on some boards. No Hardware handshaking provided. .. _zeptoforth-quirks: .. note:: 2. the Serial option requires zeptocom.js or e4thcom due to built in #includes. The former requires Chrome Browser, the latter is Linux only. Swdcom Terminal --------------- .. image:: zeptoforth-terminal.jpg Swdcom connected instantly for the picture above, and is *devastatingly fast* on Zeptoforth on a 168MHz STM32F407. Binaries -------- Zeptoforth creates a zeptoforth.stm32l476.bin in the root directory and a number of binaries for the supported hardware, including previous versions in zeptoforth/bin :: . ├── 0.13.0 ├── 0.13.1 ├── 0.13.2 ├── 0.14.0 ├── 0.14.1 ├── 0.14.2 ├── 0.14.3 ├── 0.14.4 ├── 0.15.0 ├── 0.15.1 ├── 0.15.2 └── 0.16.0 0.16.0 ------ :: . ├── stm32f407 ├── stm32f746 └── stm32l476 stm32f407 --------- :: . ├── zeptoforth_big-0.16.0.bin ├── zeptoforth_big-0.16.0.ihex ├── zeptoforth_big_swdcom-0.16.0.bin ├── zeptoforth_big_swdcom-0.16.0.ihex ├── zeptoforth_full-0.16.0.bin ├── zeptoforth_full-0.16.0.ihex ├── zeptoforth_full_swdcom-0.16.0.bin ├── zeptoforth_full_swdcom-0.16.0.ihex ├── zeptoforth_kernel-0.16.0.bin ├── zeptoforth_kernel-0.16.0.elf ├── zeptoforth_kernel-0.16.0.ihex ├── zeptoforth_mini_no_corner-0.16.0.bin ├── zeptoforth_mini_no_corner-0.16.0.ihex ├── zeptoforth_mini_swdcom_no_corner-0.16.0.bin └── zeptoforth_mini_swdcom_no_corner-0.16.0.ihex Flashing the binary ------------------- I flashed the "zeptoforth_big_swdcom-0.16.0.bin" option above into a stm32f407 Discovery board like this :: st-flash erase st-flash write zeptoforth_big_swdcom-0.16.0.bin 0x08000000 This was fast and painless and gave me the SWDCOM terminal above. Embedded Debugging ------------------ I can't find much in the way of hardware debugging aids in Zeptoforth other than the usual Forth "@" etc. STM32F407 hardware ------------------ :: 91 peripherals 1540 registers 12347 bitfields Debugging Example ~~~~~~~~~~~~~~~~~ Assume you want to find if the HSI clock is enabled and running, and if the PLL is on ? You know these bitfields are in the RCC_CR register and so you look up the Reference Manual and find the Bitfield format as below. .. image:: svd2forth/pics/rcc_cr-tech-manual.jpg You want to find out those values *RIGHT NOW*. Forth is perfect for this, you can just use the interactive terminal to find out. We know that the memory map has already been loaded so the data in the RCC_CR register can easily be found. :: RCC_CR @ hex. 00005183 ok The Reference Manual format is not in Hex so that's not useful. Lets turn it to binary ? :: binary $5183 . 101000110000011 ok. That's better, but I don't like counting bits on the screen because it's too easy to make a mistake and waste hours/days debugging. There is :ref:`another way`, but it's not available on Zeptoforth. Zeptoforth Quirks ----------------- 1. Uses a 'module' system which is just a simple way to abstract the Vocabulary use. While required modules are named in source files their source is not (as it doesn't need to be). The Zeptoforth prebuilt image knows all about these files. However this makes the example sourcecode in the /test directory very hard/impossible to follow if you're interested in the methods used for I2C for example. 2. As mentioned, #includes are used in the sourcefiles which is not standard Forth. This requires specialised terminals or uploaders as mentioned :ref:`above`. Conclusion ---------- I review all the Forths I can find and compare them against my benchmark, Mecrisp-Stellaris, the focal point of this site, as I'm sure you know. Sadly 99% of the Forths I test are broken, incomplete, abandoned or as fragile as glass. Or written in Java and take 3 days to boot up. Zeptoforth is *SOLID*, under constant improvement, and I haven't broken it in my (limited) testing. I think Zeptoforth, while a bit rough around the edges because of it's V-0.16.0 age has a very bright future ahead, Zeptforth Author ---------------- Travis Bemann is approachable and friendly, reads English and German and can crank out a new version with bugfixes and improvements in days. Travis can be reached thru the Zeproforth menus at Github: https://github.com/tabemann/zeptoforth or on IRC: Freenode #mecrisp nick:tabemann EST (USA) time. Written by Terry, 30 April 2021.