ESP32forth 🙜 February 12, 2022 TOPICS ------ • Raw Strings • ESP32 variants • Memory const char boot[] = R"""( : ( 41 parse drop drop ; immediate : \ 10 parse drop drop ; immediate ( Now can do comments! ) ( Constants and Variables ) : constant ( n "name" -- ) create , does> @ ; : variable ( "name" -- ) create 0 , ; ... )"""; ESP32 Hardware Explosion 🙜 ESP8266 - Tensilica Xtensa L106 - 80MHz - Single Core ESP32 - Tensilica Xtensa LX6 - 240MHz - Dual Core ESP32-SOLO & ESP32-MINI - Tensilica Xtensa LX6 - 240MHz - Single Core ESP32-S2 - Tensilica Xtensa LX7 - 240MHz - Single Core ESP32-S3 - Tensilica Xtensa LX7 - 240MHz - Single Core ESP32-C3 - RISC-V - 160MHz - Single Core ESP32-C6 - RISC-V - 160MHz - Single Core ESP32 Hardware Explosion 🙜 ESP8266 - 80KiB RAM - 17 GPIO ESP32 - 320KiB RAM - 34 GPIO ESP32-SOLO - 520KiB RAM - 22 GPIO - NO ARDUINO! ESP32-MINI - 520KiB RAM - 28 GPIO - NO ARDUINO! ESP32-S2 - 320KiB RAM - 43 GPIO - USB OTG / No BLE ESP32-S3 - 384KiB RAM - 44 GPIO - USB OTG ESP32-C3 - 400KiB RAM - 22 GPIO (Pin compat 8266) ESP32-C6 - 400KiB RAM - 22 GPIO - NO ARDUINO! ESP32 Hardware Explosion 🙜 ESP8266 - NO SUPPORT ESP32 - SUPPORTED ESP32-SOLO - NO SUPPORT ESP32-MINI - NO SUPPORT ESP32-S2 - SUPPORTED ESP32-S3 - NO SUPPORT ESP32-C3 - SUPPORTED ESP32-C6 - NO SUPPORT MEMORY EMBARRASSMENT -------------------- 100KB Heap 73KB Used up! 27KB Free :-( ESP32 MEMORY MAP ---------------- 0x3FFA_E000 - 0x3FFD_FFFF SRAM2 (200KB) 0x3FFE_FFFF - 0x3FFF_FFFF SRAM1 (128KB) 0x4000_0000 - 0x4005_FFFF ROM 0x4006_0000 - 0x4006_FFFF Reserved 0x4007_0000 - 0x4007_FFFF SRAM0 (64KB) [Cache] 0x4008_0000 - 0x4009_FFFF SRAM0 (128KB) 0x400A_0000 - 0x400B_FFFF SRAM1 (128KB) [Remap] FORTH MEMORY MAP ---------------- base + 0x00000 Float Stack base + 0x00800 Return Stack base + 0x01000 Data Stack base + 0x01800 Forth Heap base + 0x08000 ~ Initially used base + 0x1BC80 ~ Limit ESP32forth v7.0.6.15 - rev b64e43f70152280caffc ESP32-D0WDQ6 240 MHz 2 cores 4194304 bytes flash System Heap: 201476 free + 346176 used = 547652 total (36% free) 97788 bytes max contiguous Forth dictionary: 80956 free + 26692 used = 107648 total (75% free) 3 x Forth stacks: 2048 bytes each ok --> ESP32forth v7.0.6.15 - rev b64e43f70152280caffc FAKE-ESP32 240 MHz 2 cores 4194304 bytes flash System Heap: 90000 free + 327680 used = 417680 total (21% free) 81920 bytes max contiguous Forth dictionary: 1052220 free + 27076 used = 1079296 total (97% free) 3 x Forth stacks: 2048 bytes each ok --> include common/ansi.fs include common/all_tests.fs ----------------------------------------- PASSED: 103 RUN: 103 FOUND: 103 ALL TESTS PASSED ----------------------------------------- ( Lazy loaded Telnet ) : telnetd r| vocabulary telnetd telnetd definitions also sockets ... only forth definitions telnetd | evaluate ; ORIGINAL OPCODES ---------------- 0= 0< + U/MOD */MOD AND OR XOR LSHIFT RSHIFT DUP SWAP OVER DROP @ SL@ SW@ C@ ! L! W! C! SP@ SP! RP@ RP! >R R> R@ : ; EXIT EXECUTE BRANCH 0BRANCH DONEXT DOLIT ALITERAL CELL DOES> IMMEDIATE 'SYS n10 n9 n8 n7 n6 n5 n4 n3 n2 n1 n0 - cell_t integer values c4 c3 c2 c1 c0 - char* values b4 b3 b2 b1 b0 - uint8_t* byte values a4 a3 a2 a1 a0 - void* values void myword(int a, int b, int c); int send_message(const char *message, int code); 🙜 Y(myword, myword(n2, n1, n0); DROPn(3)) \ X("send-message", SEND_MESSAGE, \ n0 = send_message(c1, n0); DROP) \ #define VOCABULARY_LIST \ V(forth) V(internals) ... 🙜 void myword(int a, int b, int c); int send_message(const char *message, int code); 🙜 YV(vocabulary, myword, myword(n2, n1, n0); DROPn(3)) \ XV(vocabulary, "send-message", SEND_MESSAGE, \ n0 = send_message(c1, n0); DROP) \ #define OPCODE_LIST \ X("0=", ZEQUAL, tos = !tos ? -1 : 0) \ X("0<", ZLESS, tos = (tos|0) < 0 ? -1 : 0) \ X("+", PLUS, tos += *sp--) \ X("U/MOD", USMOD, w = *sp; *sp = (ucell_t) w % (ucell_t) tos; \ tos = (ucell_t) w / (ucell_t) tos) \ X("*/MOD", SSMOD, SSMOD_FUNC) \ Y(LSHIFT, tos = (*sp-- << tos)) \ Y(RSHIFT, tos = (*sp-- >> tos)) \ Y(AND, tos &= *sp--) \ Y(OR, tos |= *sp--) \ Y(XOR, tos ^= *sp--) \ Y(DUP, DUP) \ Y(SWAP, w = tos; tos = *sp; *sp = w) \ Y(OVER, DUP; tos = sp[-1]) \ Y(DROP, DROP) \ X("@", AT, tos = *(cell_t *) tos) \ X("SL@", SLAT, tos = *(int32_t *) tos) \ X("SW@", SWAT, tos = *(int16_t *) tos) \ X("C@", CAT, tos = *(uint8_t *) tos) \ X("!", STORE, *(cell_t *) tos = *sp--; DROP) \ X("L!", LSTORE, *(int32_t *) tos = *sp--; DROP) \ X("W!", WSTORE, *(int16_t *) tos = *sp--; DROP) \ X("C!", CSTORE, *(uint8_t *) tos = *sp--; DROP) \ X("SP@", SPAT, DUP; tos = (cell_t) sp) \ X("SP!", SPSTORE, sp = (cell_t *) tos; DROP) \ X("RP@", RPAT, DUP; tos = (cell_t) rp) \ X("RP!", RPSTORE, rp = (cell_t *) tos; DROP) \ X(">R", TOR, *++rp = tos; DROP) \ X(">R", TOR, *++rp = tos; DROP) \ X("R>", FROMR, DUP; tos = *rp; --rp) \ X("R@", RAT, DUP; tos = *rp) \ Y(EXECUTE, w = tos; DROP; JMPW) \ YV(internals, BRANCH, ip = (cell_t *) *ip) \ YV(internals, 0BRANCH, if (!tos) ip = (cell_t *) *ip; else ++ip; DROP) \ YV(internals, DONEXT, *rp = *rp - 1; if (~*rp) ip = (cell_t *) *ip; else (--rp, ++ip)) \ YV(internals, DOLIT, DUP; tos = *ip++) \ YV(internals, ALITERAL, COMMA(g_sys.DOLIT_XT); COMMA(tos); DROP) \ Y(CELL, DUP; tos = sizeof(cell_t)) \ Y(FIND, tos = find((const char *) *sp, tos); --sp) \ Y(PARSE, DUP; tos = parse(tos, sp)) \ XV(internals, "S>NUMBER?", \ CONVERT, tos = convert((const char *) *sp, tos, g_sys.base, sp); \ if (!tos) --sp) \ Y(CREATE, DUP; DUP; tos = parse(32, sp); \ create((const char *) *sp, tos, 0, ADDR_DOCREATE); \ COMMA(0); DROPn(2)) \ X("DOES>", DOES, DOES(ip); ip = (cell_t *) *rp; --rp) \ Y(IMMEDIATE, DOIMMEDIATE()) \ XV(internals, "'SYS", SYS, DUP; tos = (cell_t) &g_sys) \ YV(internals, YIELD, PARK; return rp) \ X(":", COLON, DUP; DUP; tos = parse(32, sp); \ create((const char *) *sp, tos, SMUDGE, ADDR_DOCOLON); \ g_sys.state = -1; --sp; DROP) \ YV(internals, EVALUATE1, DUP; float *tfp = fp; \ sp = evaluate1(sp, &tfp); \ fp = tfp; w = *sp--; DROP; if (w) JMPW) \ Y(EXIT, ip = (cell_t *) *rp--) \ XV(internals, "'builtins", TBUILTINS, DUP; tos = (cell_t) &g_sys.builtins->code) \ XV(forth_immediate, ";", SEMICOLON, COMMA(g_sys.DOEXIT_XT); UNSMUDGE(); g_sys.state = 0) #define EXTRA_OPCODE_LIST \ Y(nip, NIP) \ Y(rdrop, --rp) \ X("*/", STARSLASH, SSMOD_FUNC; NIP) \ X("*", STAR, tos *= *sp--) \ X("/mod", SLASHMOD, DUP; *sp = 1; SSMOD_FUNC) \ X("/", SLASH, DUP; *sp = 1; SSMOD_FUNC; NIP) \ Y(mod, DUP; *sp = 1; SSMOD_FUNC; DROP) \ Y(invert, tos = ~tos) \ Y(negate, tos = -tos) \ X("-", MINUS, tos = (*sp--) - tos) \ Y(rot, w = sp[-1]; sp[-1] = *sp; *sp = tos; tos = w) \ X("-rot", MROT, w = tos; tos = *sp; *sp = sp[-1]; sp[-1] = w) \ X("<", LESS, tos = (*sp--) < tos ? -1 : 0) \ X(">", GREATER, tos = (*sp--) > tos ? -1 : 0) \ X("<=", LESSEQ, tos = (*sp--) <= tos ? -1 : 0) \ X(">=", GREATEREQ, tos = (*sp--) >= tos ? -1 : 0) \ X("=", EQUAL, tos = (*sp--) == tos ? -1 : 0) \ X("<>", NOTEQUAL, tos = (*sp--) != tos ? -1 : 0) \ X("0<>", ZNOTEQUAL, tos = tos ? -1 : 0) \ Y(bl, DUP; tos = ' ') \ Y(nl, DUP; tos = '\n') \ X("1+", ONEPLUS, ++tos) \ X("1-", ONEMINUS, --tos) \ X("2*", TWOSTAR, tos <<= 1) \ X("2/", TWOSLASH, tos >>= 1) \ X("4*", FOURSTAR, tos <<= 2) \ X("4/", FOURSLASH, tos >>= 2) \ X("+!", PLUSSTORE, *(cell_t *) tos += *sp--; DROP) \ X("cell+", CELLPLUS, tos += sizeof(cell_t)) \ X("cells", CELLSTAR, tos *= sizeof(cell_t)) \ X("cell/", CELLSLASH, DUP; tos = sizeof(cell_t); DUP; *sp = 1; SSMOD_FUNC; NIP) \ X("2drop", TWODROP, NIP; DROP) \ X("2dup", TWODUP, DUP; tos = sp[-1]; DUP; tos = sp[-1]) \ X("2@", TWOAT, DUP; *sp = ((cell_t *) tos)[1]; tos = *(cell_t *) tos) \ X("2!", TWOSTORE, DUP; ((cell_t *) tos)[0] = sp[-1]; \ ((cell_t *) tos)[1] = *sp; sp -= 2; DROP) \ Y(cmove, memmove((void *) *sp, (void *) sp[-1], tos); sp -= 2; DROP) \ X("cmove>", cmove2, memmove((void *) *sp, (void *) sp[-1], tos); sp -= 2; DROP) \ Y(fill, memset((void *) sp[-1], tos, *sp); sp -= 2; DROP) \ Y(erase, memset((void *) *sp, 0, tos); NIP; DROP) \ Y(blank, memset((void *) *sp, ' ', tos); NIP; DROP) \ Y(min, tos = tos < *sp ? tos : *sp; NIP) \ Y(max, tos = tos > *sp ? tos : *sp; NIP) \ Y(abs, tos = tos < 0 ? -tos : tos) \ Y(here, DUP; tos = (cell_t) g_sys.heap) \ Y(allot, g_sys.heap = (cell_t *) (tos + (cell_t) g_sys.heap); DROP) \ Y(aligned, tos = CELL_ALIGNED(tos)) \ Y(align, g_sys.heap = (cell_t *) CELL_ALIGNED(g_sys.heap)) \ X(",", COMMA, *g_sys.heap++ = tos; DROP) \ X("c,", CCOMMA, *((uint8_t *) g_sys.heap) = tos; DROP; \ g_sys.heap = (cell_t *) (1 + ((cell_t) g_sys.heap))) \ X(">flags", TOFLAGS, tos = *TOFLAGS(tos)) \ X(">params", TOPARAMS, tos = *TOPARAMS(tos)) \ X(">size", TOSIZE, tos = TOSIZE(tos)) \ X(">link&", TOLINKAT, tos = (cell_t) TOLINK(tos)) \ X(">link", TOLINK, tos = *TOLINK(tos)) \ X(">name", TONAME, DUP; *sp = (cell_t) TONAME(tos); tos = *TONAMELEN(tos)) \ X(">body", TOBODY, tos = (cell_t) TOBODY(tos)) \ XV(internals, "'heap", THEAP, DUP; tos = (cell_t) &g_sys.heap) \ Y(current, DUP; tos = (cell_t) &g_sys.current) \ XV(internals, "'context", TCONTEXT, DUP; tos = (cell_t) &g_sys.context) \ XV(internals, "'latestxt", TLATESTXT, DUP; tos = (cell_t) &g_sys.latestxt) \ XV(internals, "'notfound", TNOTFOUND, DUP; tos = (cell_t) &g_sys.notfound) \ XV(internals, "'heap-start", THEAP_START, DUP; tos = (cell_t) &g_sys.heap_start) \ XV(internals, "'heap-size", THEAP_SIZE, DUP; tos = (cell_t) &g_sys.heap_size) \ XV(internals, "'stack-cells", TSTACK_CELLS, DUP; tos = (cell_t) &g_sys.stack_cells) \ XV(internals, "'boot", TBOOT, DUP; tos = (cell_t) &g_sys.boot) \ XV(internals, "'boot-size", TBOOT_SIZE, DUP; tos = (cell_t) &g_sys.boot_size) \ XV(internals, "'tib", TTIB, DUP; tos = (cell_t) &g_sys.tib) \ X("#tib", NTIB, DUP; tos = (cell_t) &g_sys.ntib) \ X(">in", TIN, DUP; tos = (cell_t) &g_sys.tin) \ Y(state, DUP; tos = (cell_t) &g_sys.state) \ Y(base, DUP; tos = (cell_t) &g_sys.base) \ XV(internals, "'argc", ARGC, DUP; tos = (cell_t) &g_sys.argc) \ XV(internals, "'argv", ARGV, DUP; tos = (cell_t) &g_sys.argv) \ XV(internals, "'runner", RUNNER, DUP; tos = (cell_t) &g_sys.runner) \ Y(context, DUP; tos = (cell_t) (g_sys.context + 1)) \ Y(latestxt, DUP; tos = (cell_t) g_sys.latestxt) QUESTIONS? ⚘ Thank you!