For a stand-alone Forth system, especially a embedded system, a block storage (on internal Flash or external Media) or no mass storage at all fill the bill.
Flash Memory Layout
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K 20 KiB Forth Core 140 KiB Middleware (debug 210 KiB) FLASH_FORTH (rx) : ORIGIN = 0x08040000, LENGTH = 128K 128 KiB Flash Dictionary FLASH_DRIVE (rx) : ORIGIN = 0x08060000, LENGTH = 384K 384 KiB future use for built in flash drive FLASH_BLESTACK (rx) : ORIGIN = 0x080C0000, LENGTH = 256K
Create a 384 KiB FAT filesystem as a loop device on Linux (or use the already prepared fd-384k.img):
$ dd if=/dev/zero of=fd-384k.img bs=512 count=768 768+0 Datensätze ein 768+0 Datensätze aus 393216 bytes (393 kB, 384 KiB) copied, 0,00155426 s, 253 MB/s # losetup /dev/loop1 fd-384k.img # mkfs -t vfat /dev/loop1 # mount -o loop /dev/loop1 /mnt
Copy the the files and directories with cp
or tar
to the mounted image, e.g.
# cd sdcard # tar cf - etc fsr home man README.md | tar xvf - -C /mnt # umount /mnt
Umount the loop-device and copy the file to a SD-card.
Copy the filesystem to the flash disk on the target Mecrisp-Cube system:
dd 1:/boot/fd-384k.img 0:
The STM32F405 Feather has a 2 MiB Serial Flash W25Q16 on board. The smallest erasable chunk of data is the 4 KiB sector. But the default FAT block is 512 Bytes, that means if you want to write something to a not erased block, you have to erase the whole sector. For this the sector has to be buffered in RAM. For details see:
You can use the local CLI commands like mkfs
, mkdir
and cp
to populate the serial flash with files and directories. But this is tedious job because there is no recursive copy. It is easier to use a real GNU/Linux for this.
Create a 2 MiB FAT filesystem as a loop device on Linux (or use the already prepared fd-2MiB.img):
$ dd if=/dev/zero of=fd-2MiB.img bs=512 count=4096 # losetup /dev/loop1 fd-2MiB.img # mkfs -t vfat /dev/loop1 # mount -o loop /dev/loop1 /mnt
Copy the the files and directories with cp
or tar
to the mounted image, e.g.
# cd sdcard # tar cf - etc fsr home man README.md | tar xvf - -C /mnt
Umount the loop-device and copy the file to a SD-card.
Copy the filesystem to the flash disk on the target Mecrisp-Cube F405 system:
dd 1:/boot/fd-2MiB.img 0:
The SST25VF016B seems to be compatible.
16 MiB Quad SPI NOR Flash chip S25FL128SDSMFV001. Uniform 64-KB sectors with Hybrid 4-KB sectors.
The main flash array is divided into erase units called sectors. The sectors are organized either as a hybrid combination of 4-KB and 64-KB sectors, or as uniform 256-KB sectors.
32 4 KiB sectors and 254 64 KiB sectors. What a pain, why use STM this Flash? To simplify writing, only the first 4 KiB of the 64 KiB sectors are used. That means (32 + 254) * 4 KiB = 1140 KiB are available for the volume. To make it even simpler, I use only 64 KiB sectors, that means there are 256 sectors and therefore 1 MiB available for the volume. For implementation see fd.c and fd_spi.c
Create a 1 MiB FAT filesystem as a loop device on Linux (or use the already prepared fd-1MiB.img):
$ dd if=/dev/zero of=fd-1MiB.img bs=512 count=2048 # losetup /dev/loop1 fd-1MiB.img # mkfs -t vfat /dev/loop1 # mount -o loop /dev/loop1 /mnt
Copy the the files and directories with cp
or tar
to the mounted image, e.g.
# cd sdcard # tar cf - etc fsr home man README.md | tar xvf - -C /mnt
Umount the loop-device and copy the file to a SD-card.
Copy the filesystem to the flash disk on the target Mecrisp-Cube WB5M Discovery system:
dd 1:/boot/fd-1MiB.img 0:
The W25Q128JVPIQ. There are 4,096 erasable 4 KiB sectors. That means 16 MiB are available for the volume.
Create a 16 MiB FAT filesystem as a loop device on Linux (or use the already prepared fd-16MiB.img):
$ dd if=/dev/zero of=fd-16MiB.img bs=512 count=32768 # losetup /dev/loop1 fd-16MiB.img # mkfs -t vfat /dev/loop1 # mount -o loop /dev/loop1 /mnt
Copy the the files and directories with cp
or tar
to the mounted image, e.g.
# cd sdcard # tar cf - etc fsr home man README.md | tar xvf - -C /mnt
Umount the loop-device and copy the file to a SD-card.
Copy the filesystem to the flash disk on the target Mecrisp-Cube WB Feather system:
dd 1:/boot/fd-16MiB.img 0:
There is no serial NOR flash on board, but there is an QSPI interface on connector CN10.
It is easy to connect a MIKROE-4067 or Sparkfun SPX-17115
with a W25Q128JV (128M-bit) NOR flash memory on it. See also Winbond W25Q128JVPIQ
.
The driver (fd_spi.c, fd.c
) is based on the STM example project for the N25Q128A
There are 4,096 erasable 4 KiB sectors. That means 16 MiB are available for the volume.
Name | Port | Nucleo | MIKROE-4067 | SPX-17115 |
---|---|---|---|---|
QS_CS | PG6 | CN10.13 | CS | 2 QSPI-CS |
QS_CS | PB10 | CN10.32 | CS | 2 QSPI-CS |
QS_CLK | PB2 | CN10.15 | CLK | 3 QSPI-CLK |
GND | CN10.17 | GND | 8 GND | |
QS_D3 | PD13 | CN10.19 | IO3 | 7 QSPI3 |
QS_D1 | PD12 | CN10.21 | MISO SDO | 5 QSPI1 |
QS_D0 | PD11 | CN10.23 | MOSI ŜDI | 4 QSPI0 |
QS_D2 | PE2 | CN10.25 | IO2 | 6 QSPI2 |
+3.3V | CN8.7 | +3.3V | 1 3.3V |
Copy the filesystem to the flash disk on the target Mecrisp-Cube STM32H743 Nucleo system:
dd 1:/boot/fd-16MiB.img 0:
See above (MicroSdBlocks#STM32WB_Feather_SPI_W25Q128) for creating the image fd-16MiB.img
.
The Macronix MX25L12833F is compatible to the Winbond W25Q128JVPIQ. See above MicroSdBlocks#STM32H743_Nucleo_QSPI_W25Q128 for details.
You can build a very cheap microSD adapter by yourself with a microSD to SD adapter. You have to solder only 7 wires to a pin header. The breakout board for microSD cards from Adafruit have a level shifter, but this is not needed because the levels on the Nucleo are already 3.3 V. Only the CD pin is missing, this could be handy to detect a microSD card.
![]() |
![]() |
SD pin | microSD pin | Name | Description | Arduino/Nucleo Pin | Nucleo Dongle |
---|---|---|---|---|---|
1 | 2 | nCS | Card Select [CS] | D10 (1) | PB2 CN1.7 |
2 | 3 | DI | Serial Data In [MOSI] | D11 (2) | PA7 CN1.10 |
3 | - | VSS | Ground | GND (5) | GND CN1.1 |
4 | 4 | VDD | Power 3.3 V | 3V3 (6) | 3V3 CN1.6 |
5 | 5 | CLK | Serial Clock [SCLK] | D13 (4) | PA5 CN1.8 |
6 | 6 | VSS | Ground | GND (5) | GND CN1.1 |
7 | 7 | DO | Serial Data Out [MISO] | D12 (3) | PA6 CN1.9 |
8 | 8 | NC | Unused | ||
9 | 1 | NC | Unused |
Block size 512 Bytes, SPI mode 0 (CPHA=0, CPOL=0), Pull-up on MISO.
![]() |
![]() |
SDIO Interface is well supported by the STM32F405, there is no need to use the slower SPI.
SDIO (SDMMC) Interface is well supported by the STM32H74x, there is no need to use the slower SPI.
SD pin | microSD pin | Name SPI | Name SDMMC | Nucleo Pin CN8 |
---|---|---|---|---|
1 | 2 | nCS | SDIO_D3 | 8 |
2 | 3 | DI | SDIO_CMD | 12 |
3 | - | VSS | GND | 11 |
4 | 4 | VDD | VDD | 7 |
5 | 5 | CLK | SDIO_CLK | 10 |
6 | 6 | VSS | GND | 11 |
7 | 7 | DO | SDIO_D0 | 2 |
8 | 8 | NC | SDIO_D1 | 4 |
9 | 1 | NC | SDIO_D2 | 6 |
SD pin | microSD pin | Name | Description | Feather Pin |
---|---|---|---|---|
1 | 2 | nCS | Card Select [CS] | D10 |
2 | 3 | DI | Serial Data In [MOSI] | MO (D4) |
3 | - | VSS | Ground | GND |
4 | 4 | VDD | Power 3.3 V | 3V3 |
5 | 5 | CLK | Serial Clock [SCLK] | SCK (D2) |
6 | 6 | VSS | Ground | GND |
7 | 7 | DO | Serial Data Out [MISO] | MI (D3) |
8 | 8 | NC | Unused | |
9 | 1 | NC | Unused |
JTAG Pin | JTAG STM 14pin | CN1 Dongle | CN2 Dongle | Description |
---|---|---|---|---|
1 | NC | |||
2 | NC | |||
1 | 3 | 6 | VDD | |
2 | 4 | 3 | SWDIO | |
3 | 5 | 1 | GND | |
4 | 6 | 4 | SWCLK | |
5 | 7 | 1 | GND | |
6 | 8 | 5 | SWO | |
7 | 9 | NC | ||
8 | 10 | NC | ||
9 | 11 | 1 | GND_DETECT | |
10 | 12 | 2 | NRST | |
13 | 7 (PB7) | VCP_RX Target | ||
14 | 6 (PB6) | VCP_TX Target |
FAT is the de-facto standard for embedded systems and mobile devices.
The FAT filesystem for Mecrisp-Cube is based on FatFs - Generic FAT Filesystem Module and supports FAT (12, 16, and 32) and exFAT formatted SD cards.
Forth source files. I propose
.fs
extension for Forth source files the same as GForth does. But anyway you can use what you want (.f
, .4th
, .fth
, etc).
include ( i*x "name" -- j*x ) Interprets the content of the file <name>. included ( i*x c-addr u -- j*x ) Interprets the content of the file. coredump ( "name" -- ) Dumps the flash memory (core) into the file <name>. user variables which contain file desciptor (pointer address a to file object structure) stdin ( -- a ) for fs-emit and fs-emit? stdout ( -- a ) for fs-key and fs-key? stderr ( -- a ) not used yet fs-emit ( c -- ) Emits a character c to a file (stdout) fs-emit? ( -- ? ) Ready to send a character to a file? (stdout) fs-key ( -- c ) Waits for and fetches a character from file. <0 for EOF or error. (stdin) fs-key? ( -- ? ) Checks if a character is remaining (stdin)
Words from redirection.fs
>f_open ( a1 a2 -- ior ) open a file a1 to redirect to a2 (emit, type, ...) >>f_open ( a1 a2 -- ior ) open a file to redirect to (emit, type, ...). Append to file >file ( -- a1 a2 ) redirect to a file (emit, type, ...) >f_close ( -- ior ) close redirection to file <f_open ( a1 a2 -- ior ) open a file to redirect from (key, accept, ...) <file ( -- a1 a2) redirection from a file (key, accept, ...) <f_close ( -- ior ) close redirection from file >term ( a1 a2 -- ) terminate to-file redirection <term ( a1 a2 -- ) terminate from-file redirection <>term ( a1 a2 a3 a4 -- ) terminate redirection >uart ( -- a1 a2 ) redirection to uart <uart ( -- a1 a2 ) redirection from uart (key, accept, ...) <>uart ( -- a1 a2 a3 a4 ) redirection from and to uart >cdc ( -- a1 a2 ) redirection to cdc (USB serial) <cdc ( -- a1 a2 ) redirection from cdc (key, accept, ...) <>cdc ( -- a1 a2 a3 a4 ) redirection from and to cdc >crs ( -- a1 a2 ) redirection to crs (BLE serial) <crs ( -- a1 a2 ) redirection from crs(key, accept, ...) <>crs ( -- a1 a2 a3 a4 ) redirection from and to crs >oled ( -- a1 a2 ) redirection to oled >plex ( -- a1 a2 ) redirection to plex LED display
Words from conditional.fs. See also https://forth-standard.org/standard/tools
.
query
not working in include! All the conditionals have to be on the same line.
[IF] ( flag | flag "<spaces>name ..." -- ) If flag is true, do nothing. Otherwise parse and discard words from the parse area [ELSE] ( "<spaces>name ..." -- ) Parse and discard words from the parse area [THEN] ( -- ) Does nothing. [THEN] is an immediate word. [ENDIF] ( -- ) Does nothing. [ENDIF] is an immediate word. [IFDEF] ( "<spaces>name ..." -- ) If the name can be found, do nothing. Otherwise parse and discard words from the parse area [IFNDEF] ( "<spaces>name ..." -- ) If the name can´t be found, do nothing. Otherwise parse and discard words from the parse area [DEFINED] ( "<spaces>name ..." -- flag ) Return a true flag if name is the name of a word that can be found [UNDEFINED] ( "<spaces>name ..." -- flag ) Return a false flag if name is the name of a word that can be found
The C function prototype for f_open
looks like this:
FRESULT f_open ( FIL* fp, /* [OUT] Pointer to the file object structure */ const TCHAR* path, /* [IN] File name */ BYTE mode /* [IN] Mode flags */ );
The parameter order for the Forth Word is the same: addr1
is address of the file object data structure FIL,
addr2
is the address of the filename array (0 terminated string).
f_open ( addr1 addr2 u -- ior ) opens a file.
The FIL data structure can be created as follows:
create fil /FIL allot ok.
See also f_open.
Print current directory:
256 buffer: path[RET] ok. path 256 f_getcwd drop strlen type[RET] 0:/ ok.or easier with unix like command
pwd
:
pwd[RET] 0:/ ok.
Change current directory
path 256 accept[RET] common[RET] ok. path swap 2dup str0term drop f_chdir .[RET] 0 ok. pwd[RET] 0:/common ok.
path dup .str" /fsr" f_chdir .[RET] 0 ok. pwd[RET] 0:/fsr ok.
Change drive (if you have a microSD connected):
chdrv 1:[RET] ok. pwd[RET] 1:/ ok. cd home[RET] ok. pwd[RET] 1:/home ok. 0:[RET] ok. pwd[RET] 0:/fsr ok.
emit
, type
or print something to the console. It is also possible to fetch user input like key
, accept
, etc. All these words can be used on files. Nothing new for a UNIX user. Mecrisp use hooks for redirection terminal IO, these hooks can also be used for file redirection.
hook-emit
for redirection output from ls -l
to a file.
Open file test.tmp
path .str" test.tmp[RET] ok. fil path FA_WRITE FA_OPEN_ALWAYS + f_open .[RET] 0 ok.
Save file descriptor to stdout
user variable
fil stdout ![RET] ok.
Push current hook to the stack
hook-emit @[RET] ok.
Redirect emit
to fs-emit
(there is no ok.)
' fs-emit hook-emit ! [RET]
Type ls -l
, there is no echo on the console
ls -l[RET]
Restore old hook:
hook-emit ! [RET] ok.
Close file
fil f_close .[RET] 0 ok.
Show the contents of the file test.tmp
cat test.tmp[RET] drw- 0 2021-03-06T14:36:40 man drw- 0 2021-03-06T14:36:40 fsr -rwa 7219 2021-03-06T14:04:12 README.md drw- 0 2021-03-26T18:47:12 boot drw- 0 2021-04-18T17:40:14 etc drw- 0 2021-03-06T14:36:40 home -rwa 0 2000-01-01T00:11:12 test.tmp ok. hook-emit ! ok.
create fil /FIL allot 256 buffer: path path .str" test.tmp" fil path >f_open drop >file ls -l >term >f_close drop
Some helper words in redirection.fs
: >f_open ( addr c-addr -- ior ) \ open a file to redirect to (emit, type, ...) swap dup stdout ! swap FA_WRITE FA_OPEN_ALWAYS + f_open ; : >>f_open ( addr c-addr -- ior ) \ open a file to redirect to (emit, type, ...). Append to file swap dup stdout ! swap FA_WRITE FA_OPEN_APPEND + f_open ; : >file ( -- addr1 addr2 ) \ redirect to a file (emit, type, ...) hook-emit @ hook-emit? @ ['] fs-emit hook-emit ! ['] fs-emit? hook-emit? ! ; : >term ( addr1 addr2 -- ) \ terminate to-file redirection hook-emit? ! hook-emit ! ; : >f_close ( -- ior ) stdout @ f_close 0 stdout ! ; : <f_open ( addr1 c-addr -- ior ) \ open a file to redirect from (key, accept, ...) swap dup stdin ! swap FA_READ f_open ; : <file ( -- addr2 addr3) \ redirection from a file (key, accept, ...) hook-key @ hook-key? @ ['] fs-key hook-key ! ['] fs-key? hook-key? ! ; : <term ( addr1 addr2 -- ) \ terminate from-file redirection hook-key? ! hook-key ! ; : <f_close ( -- ior ) stdin @ f_close 0 stdin ! ;
The file 0:/etc/rc.local
is included on the startup:
\ this file will be included on startup cr .( include 0:/etc/rc.local ) cr .time cr watchdog? [IF] .( Watchdog has bitten, # bites: ) watchdog# . cr [THEN] assert? [IF] assert@ hex. .assert cr [THEN]
https://github.com/spyren/Mecrisp-Cube/blob/master/sdcard/etc/rc.local
FS_init()
. We have only two drives.
For details see FATFS
/FATFS ( -- u ) Gets the FATFS structure size
/FIL ( -- u ) Gets the FIL structure size FA_READ ( -- u ) Gets the Mode Flag FA_READ FA_WRITE ( -- u ) Gets the Mode Flag FA_WRITE FA_OPEN_EXISTING ( -- u ) Gets the Mode Flag FA_OPEN_EXISTING FA_CREATE_NEW ( -- u ) Gets the Mode Flag FA_CREATE_NEW FA_CREATE_ALWAYS ( -- u ) Gets the Mode Flag FA_CREATE_ALWAYS A_OPEN_ALWAYS ( -- u ) Gets the Mode Flag FA_OPEN_ALWAYS FA_OPEN_APPEND ( -- u ) Gets the Mode Flag FA_OPEN_APPEND
POSIX | FatFs |
---|---|
"r" | FA_READ |
"r+" | FA_READ FA_WRITE or |
"w" | FA_CREATE_ALWAYS FA_WRITE or |
"w+" | FA_CREATE_ALWAYS FA_WRITE or FA_READ or |
"a" | FA_OPEN_APPEND FA_WRITE or |
"a+" | FA_OPEN_APPEND FA_WRITE or FA_READ or |
"wx" | FA_CREATE_NEW FA_WRITE or |
"w+x" | FA_CREATE_NEW or FA_WRITE FA_READ or |
/DIR ( -- u ) Gets the DIR structure size
/FILINFO ( -- u ) Gets the FILINFO structure size fsize+ ( -- u ) Gets the FILINFO structure fsize offset fdate+ ( -- u ) Gets the FILINFO structure fdate offset ftime+ ( -- u ) Gets the FILINFO structure ftime offset fattrib+ ( -- u ) Gets the FILINFO structure fattrib offset fname+ ( -- u ) Gets the FILINFO structure fname offset altname+ ( -- u ) Gets the FILINFO structure altname offset
f_
words in compiler mode. Spaces in path und file names are not allowed. Verly limited wildcards (only * and ?) for ls
. No standard input/ouptut/err redirection.
: init ; : prompt ( -- ) begin tib 256 f_getcwd drop strlen type \ show current working directory ." > " \ show ">" for prompt. Could show "OK." query interpret cr again ; : init init ['] prompt hook-quit ! ; \ make new prompt init quit
: str0term ( cadr len -- cadr len ) + 0 swap c! ; strlen ( cadr -- cadr len ) \ 0-Terminated String to Forth String
ls [-a] [-l] [-1] [FILE] -a show hidden files -l use a long listing format -1 list one file per line ls ( "line<EOL>" -- ) list directory contents
pwd pwd ( -- ) print name of current/working directory
cd [DIR] cd ( "line<EOL>" -- ) change the working directory
chdrv [0:|1:|FD:|SD:] chdrv ( "line<EOL>" -- ) changes the current drive.
cat [-n] [> NEWFILE] [>> FILE] [<< EOF] FILES... -n line numbers > redirect output to NEWFILE >> redirect output and append to FILE << redirect input till EOF cat ( "line<EOL>" -- ) concatenate files and print on the console
mkdir [DIR]... mkdir ( "line<EOL>" -- ) make directories
rm FILE... rm ( "line<EOL>" -- ) remove files or directories
mv SOURCE DEST mv ( "line<EOL>" -- ) move (rename) files
cp SOURCE DEST cp ( "line<EOL>" -- ) copy files
chmod [-a] [+l] [=1] FILE... -rwa selected file mode bits removed +rwa selected file mode bits added =rwa selected file mode bits set chmod ( "line<EOL>" -- ) change file mode bits
touch FILE... -c do not create any files A FILE argument that does not exist is created empty. touch ( "line<EOL>" -- ) change file timestamps
df [VOLUME] df ( "line<EOL>" -- ) report file system disk space usage (1 KiB blocks)
du [FILE] -h print sizes in powers of 1024 (e.g., 1023 MiB) du ( "line<EOL>" -- ) estimate file space usage
vol [-d NUMBER] [-n NAME] -d drive number -n change drive name to NAME vol ( "line<EOL>" -- ) get and set volume label
mount [0:|1:|FD:|SD:] mount ( -- ) mount default drive
umount [0:|1:|FD:|SD:] umount ( -- ) unmount default drive
vi [-R] [-h] [-c <COLUMNS>] [-r <ROWS>] [FILE] -h show features -R Read-only mode. You can still edit the buffer, but will be prevented from overwriting a file. -e erase the text buffer -c <COLUMNS> screen columns, range 40..128 default 80 -r <ROWS> screen rows, range 16..30 default 24 vi ( "line<EOL>" -- ) a (Forth) programmer's text editor
split [-l NUMBER] FILE -l NUMBER put NUMBER lines/records per output fileline numbers (default 1000 lines) suffix length is only 1, generated file names are like this: xa, xb, xc, ... split ( "line<EOL>" -- ) split a file into pieces
wc FILE... wc ( "line<EOL>" -- ) Word count, print newline, word, and byte counts for each file
mkfs [-f FAT|FAT32|EXTFAT] 0:|1: -f FAT type mkfs ( "line<EOL>" -- ) make a filesystem
dd 0:|FILE FILE|0: dd ( "line<EOL>" -- ) Convert and copy files (Disk Destroyer :-)
coredump [-a] FILE -a dump everything (768 KiB) coredump ( "line<EOL>" -- ) dump the flash contents (flash dictionary) to a file
c-addr u-count
, where c-addr
is the address of the first character and u-count
is the number of characters in the string.
str0term ( c-addr len -- ) make Forth string null-terminated, be sure the buffer is long enough to accept an additional 0 character. strlen ( c-addr -- c-addr len ) calculate the length of a C string, Forth string compatible .str" ( c-addr "text" -- ) copy string into buffer. String is null-terminated s0" ( "text" -- c-addr len ) Compiles a 0-terminated string and gives back its address and length when executed similar to s" but with 0-termination .( ( "text) -- ) Mecrisp's ." is working only in compile mode
The blocks can be used as buffers. As long as you use less or equal than 4 blocks, nothing is stored on the SD card.
block ( n -- a ) Return address of buffer for block n. 0 on error. buffer ( n -- a ) Return address of buffer for block n. Does not get the block from disk. 0 on error. empty-buffers ( -- ) Marks all block buffers as empty. update ( -- ) Marks most recent block as updated (dirty). save-buffers ( -- ) Transfers the contents of each updated block buffer to disk. flush ( -- ) save-buffers empty-buffers list ( n -- ) Display block n. The block is displayed as 16 numbered lines, each of 64 characters. load ( n -- ) Interprets the content of block n. drive ( u -- ) Initializes the drive (0 flash drive, 1 SD drive) and makes it current, sets the block count. #blocks ( -- n ) Gets the block count from current drive. erasedrv ( -- ) Erase current Drive (Chip Erase)
VI or EMACS keybindings? VI has a line editing mode too, fine for really dumb terminals.
Example 2 GiB microSD FAT16 formatted, show the disk parameter with fdisk:
# fdisk /dev/sdf ... Befehl (m für Hilfe): p Festplatte /dev/sdf: 1,91 GiB, 2032664576 Bytes, 3970048 Sektoren Festplattenmodell: FCR-HS219/1 Einheiten: Sektoren von 1 * 512 = 512 Bytes Sektorgröße (logisch/physikalisch): 512 Bytes / 512 Bytes E/A-Größe (minimal/optimal): 512 Bytes / 512 Bytes Festplattenbezeichnungstyp: dos Festplattenbezeichner: 0x00000000 Gerät Boot Anfang Ende Sektoren Größe Kn Typ /dev/sdf1 249 3967487 3967239 1,9G 6 FAT16
Fill the SD with zeros (1'000'000 sectors à 512 Bytes), that takes about 5 Minutes:
# dd if=/dev/zero of=/dev/sdf count=1000000 1000000+0 Datensätze ein 1000000+0 Datensätze aus 512000000 Bytes (512 MB, 488 MiB) kopiert, 271,43 s, 1,9 MB/s
Write the first block with the famous F example letter-f.block from Starting Forth, Leo Brodie:
# dd if=letter-f.block of=/dev/sdf 2+0 Datensätze ein 2+0 Datensätze aus 1024 Bytes (1,0 kB, 1,0 KiB) kopiert, 0,00226272 s, 453 kB/sPut the microSD card into the SD adapter and startup the Mecrisp-Cube Nucleo:
Mecrisp-Cube 1.2.0 for STM32WB55 (C) peter@spyr.ch. Based on Mecrisp-Stellaris 2.5.2 by Matthias Koch. 0 list Block# 0 0 \ Large letter F 1 : STAR [CHAR] * EMIT ; 2 : STARS 0 DO STAR LOOP ; 3 : MARGIN CR 30 SPACES ; 4 : BLIP MARGIN STAR ; 5 : BAR MARGIN 5 STARS ; 6 : F BAR BLIP BAR BLIP BLIP CR ; 7 8 F 9 10 11 12 13 14 15 ok. 0 load ***** * ***** * * ok. ok. 0 block hex. 200216F8 ok. 0 block 1200 dump 200216F0 : 00 01 00 00 D9 86 03 00 5C 20 4C 61 72 67 65 20 | ........ \ Large | 20021700 : 6C 65 74 74 65 72 20 46 20 20 20 20 20 20 20 20 | letter F | 20021710 : 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | 20021720 : 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | 20021730 : 20 20 20 20 20 20 20 20 3A 20 53 54 41 52 20 20 | : STAR | 20021740 : 20 20 5B 43 48 41 52 5D 20 2A 20 45 4D 49 54 20 | [CHAR] * EMIT | 20021750 : 3B 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | ; | 20021760 : 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | 20021770 : 20 20 20 20 20 20 20 20 3A 20 53 54 41 52 53 20 | : STARS | 20021780 : 20 20 30 20 44 4F 20 20 53 54 41 52 20 20 4C 4F | 0 DO STAR LO | 20021790 : 4F 50 20 3B 20 20 20 20 20 20 20 20 20 20 20 20 | OP ; | 200217A0 : 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | 200217B0 : 20 20 20 20 20 20 20 20 3A 20 4D 41 52 47 49 4E | : MARGIN | 200217C0 : 20 20 43 52 20 33 30 20 53 50 41 43 45 53 20 3B | CR 30 SPACES ; | 200217D0 : 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | 200217E0 : 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | 200217F0 : 20 20 20 20 20 20 20 20 3A 20 42 4C 49 50 20 20 | : BLIP | 20021800 : 20 20 4D 41 52 47 49 4E 20 53 54 41 52 20 3B 20 | MARGIN STAR ; | 20021810 : 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | 20021820 : 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | 20021830 : 20 20 20 20 20 20 20 20 3A 20 42 41 52 20 20 20 | : BAR | 20021840 : 20 20 4D 41 52 47 49 4E 20 35 20 53 54 41 52 53 | MARGIN 5 STARS | 20021850 : 20 3B 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | ; | 20021860 : 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | 20021870 : 20 20 20 20 20 20 20 20 3A 20 46 20 20 20 20 20 | : F | 20021880 : 20 20 42 41 52 20 42 4C 49 50 20 42 41 52 20 42 | BAR BL IP BAR B | 20021890 : 4C 49 50 20 42 4C 49 50 20 43 52 20 3B 20 20 20 | LIP BLIP CR ; | 200218A0 : 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | | ... 20021AF0 : 20 20 20 20 20 20 20 20 00 00 00 00 01 00 00 00 | ........ | ... 20021BB0 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ........ ........ | ok.
Init flash drive
0 drive[RET] ok. #blocks .[RET] 16384 ok. erasedrv [RET] ok.
there are 16384 blocks, this means 16 MiB.
get the address of block 100 and write "Hallo Velo"
100 buffer hex.[RET] 24017588 ok. 100 block .str" Hallo Velo"[RET] ok. 100 block strlen type[RET] Hallo Velo ok.
Save Block 100 to the disk:
update save-buffers[RET] ok.
Restart the Forth System (power cycle, reset, or Ctrl-C):
Mecrisp-Cube 1.4.4 for STM32H743, 256/1024 KiB RAM/FLASH dictionary (C) 2022 peter@spyr.ch * Firmware Package STM32Cube H7 V1.10.0, USB-CDC (C) 2021 STMicroelectronics * CMSIS-RTOS V2 FreeRTOS wrapper, FreeRTOS Kernel V10.3.1 (C) 2020 Amazon.com * FatFs for internal flash and microSD - Generic FAT fs module R0.12c (C) 2017 ChaN * tiny vi - part of BusyBox (C) 2000, 2001 Sterling Huxley 0:/etc/rc.local: can't find file 0 drive[RET] ok. 100 block strlen type[RET] Hallo Velo ok.
This work by Peter Schmid is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
I | Attachment | History | Action | Size | Date | Who | Comment |
---|---|---|---|---|---|---|---|
![]() |
MMC-SD-miniSD-microSD-Color-Numbers-Names.gif | r1 | manage | 19.7 K | 2020-06-03 - 07:39 | PeterSchmid | |
![]() |
W25Q16.png | r1 | manage | 5.7 K | 2021-03-30 - 13:38 | PeterSchmid | |
![]() |
letter-f.block | r1 | manage | 1.0 K | 2020-06-12 - 19:46 | PeterSchmid | |
![]() |
nucleo-dongle-sdcard.jpg | r1 | manage | 279.6 K | 2020-08-13 - 11:21 | PeterSchmid | |
![]() |
nucleo-dongle-sdcard2.jpg | r1 | manage | 221.1 K | 2020-08-13 - 11:21 | PeterSchmid | |
![]() |
nucleo-sd-adapter.jpg | r1 | manage | 347.2 K | 2020-06-14 - 14:52 | PeterSchmid | |
![]() |
prompt.fth | r2 r1 | manage | 1.2 K | 2020-08-10 - 13:19 | PeterSchmid | |
![]() |
sd-header.jpg | r1 | manage | 75.4 K | 2021-02-07 - 10:23 | PeterSchmid | |
![]() |
sd-socket.jpg | r1 | manage | 71.7 K | 2021-03-30 - 13:13 | PeterSchmid | |
![]() |
sdio-schematic.png | r1 | manage | 26.8 K | 2021-03-30 - 13:17 | PeterSchmid | |
![]() |
serial-flash.jpg | r1 | manage | 82.8 K | 2021-03-30 - 13:44 | PeterSchmid |