microSD Mass Storage for Blockheads and Fatties
Intro
Raw blocks or filesystem? A real filesystem is hefty and several times larger than the Forth kernel itself. But if you really want to exchange data with other systems you need some sort of compatible storage medium like a microSD with a FAT filesystem. For a standalone Forth system, especially a embedded system, a block storage (on internal Flash or external Media) or no mass storage at all fill the bill.

Hardware

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.
MMC-SD-miniSD-microSD-Color-Numbers-Names.gif nucleo-sd-adapter.jpg

SD pin microSD pin Name Description Arduino/Nucleo Pin
1 2 nCS Card Select [CS] D10
2 3 DI Serial Data In [MOSI] D11
3 - VSS Ground GND
4 4 VDD Power 3.3 V 3V3
5 5 CLK Serial Clock [SCLK] D13
6 6 VSS Ground GND
7 7 DO Serial Data Out [MISO] D12
8 8 NC Unused  
9 1 NC Unused  

http://elm-chan.org/docs/mmc/mmc_e.html

Block size 512 Bytes, SPI mode 0 (CPHA=0, CPOL=0), Pull-up on MISO.

Raw Blocks

One Forth block consists of two microSD sectors. No filesystem is involved, blocks are mapped direct to the sectors: block_number = sector_number / 2. Caution! If you write a block on a formatted disk you will destroy the filesystem. Block 0 for example is the Master Boot Sector, to overwrite this sector/block would end in a disaster. If you really want to share blocks and filesystem on the same disk you have to create an additional partition for the Forth blocks. Or if you only want to play with some toy blocks, you can abuse the boot loader, because it is usually not required and you can therefore use blocks from 10 to 100. But be warned, do not do this on the SD card with the vacation pictures!

Block (Virtual Memory) Words

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. 

sdinit         ( -- )          Initializes the sd, sets the block count.
sdblocks       ( -- n )        Gets the block count.

Block Editor

VI or EMACS keybindings? VI has a line editing mode too, fine for really dumb terminals.

Raw Blocks and GNU/Linux

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/s
Put 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  |                    |
200218B0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
200218C0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
200218D0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
200218E0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
200218F0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021900 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021910 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021920 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021930 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021940 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021950 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021960 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021970 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021980 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021990 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
200219A0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
200219B0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
200219C0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
200219D0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
200219E0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
200219F0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021A00 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021A10 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021A20 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021A30 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021A40 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021A50 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021A60 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021A70 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021A80 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021A90 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021AA0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021AB0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021AC0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021AD0 :  20 20 20 20 20 20 20 20   20 20 20 20 20 20 20 20  |                    |
20021AE0 :  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  |           ........ |
20021B00 :  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00  | ........  ........ |
20021B10 :  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00  | ........  ........ |
20021B20 :  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00  | ........  ........ |
20021B30 :  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00  | ........  ........ |
20021B40 :  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00  | ........  ........ |
20021B50 :  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00  | ........  ........ |
20021B60 :  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00  | ........  ........ |
20021B70 :  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00  | ........  ........ |
20021B80 :  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00  | ........  ........ |
20021B90 :  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00  | ........  ........ |
20021BA0 :  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00  | ........  ........ |
20021BB0 :  00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00  | ........  ........ |
 ok.


FAT Filesystem

FAT is the de-facto standard for embedded systems and mobile devices. Based on FatFs - Generic FAT Filesystem Module. It supports FAT (12, 16, and 32) and exFAT formatted SD cards.

Forth source files

include   filename    ( -- )      Interprets the content of the file. 
included              ( a u -- )  Interprets the content of the file.

Filesystem API

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: a1 is address of the file object structure, a2 is the address of the filename array (0 terminated string).

f_open  ( a1 a2 w -- u )   opens a file.

typedef struct {
    FFOBJID obj;          /* Object identifier */
    BYTE    flag;         /* File object status flags */
    BYTE    err;          /* Abort flag (error code) */
    FSIZE_t fptr;         /* File read/write pointer (Byte offset origin from top of the file) */
    DWORD   clust;        /* Current cluster of fptr (One cluster behind if fptr is on the cluster boundary. Invalid if fptr == 0.) */
    LBA_t   sect;         /* Current data sector (Can be invalid if fptr is on the cluster boundary.)*/
#if !FF_FS_READONLY
    LBA_t   dir_sect;     /* Sector number containing the directory entry */
    BYTE*   dir_ptr;      /* Ponter to the directory entry in the window */
#endif
#if FF_USE_FASTSEEK
    DWORD*  cltbl;        /* Pointer to the cluster link map table (Nulled on file open. Set by application.) */
#endif
#if !FF_FS_TINY
    BYTE    buf[FF_MAX_SS]; /* File private data transfer buffer (Always valid if fptr is not on the sector boundary but can be invalid if fptr is on the sector boundary.) */
#endif
} FIL;

FIL name ( -- a ) creates a file object

See also f_open

File Access

  • f_open - Open/Create a file
  • f_close - Close an open file
  • f_read - Read data from the file
  • f_write - Write data to the file
  • f_lseek - Move read/write pointer, Expand size
  • f_truncate - Truncate file size
  • f_sync - Flush cached data
  • f_forward - Forward data to the stream
  • f_expand - Allocate a contiguous block to the file
  • f_gets - Read a string
  • f_putc - Write a character
  • f_puts - Write a string
  • f_printf - Write a formatted string
  • f_tell - Get current read/write pointer
  • f_eof - Test for end-of-file
  • f_size - Get size
  • f_error - Test for an error

Directory Access

  • f_opendir - Open a directory
  • f_closedir - Close an open directory
  • f_readdir - Read a directory item
  • f_findfirst - Open a directory and read the first item matched
  • f_findnext - Read a next item matched

File and Directory Management

  • f_stat - Check existance of a file or sub-directory
  • f_unlink - Remove a file or sub-directory
  • f_rename - Rename/Move a file or sub-directory
  • f_chmod - Change attribute of a file or sub-directory
  • f_utime - Change timestamp of a file or sub-directory
  • f_mkdir - Create a sub-directory
  • f_chdir - Change current directory
  • f_chdrive - Change current drive
  • f_getcwd - Retrieve the current directory and drive

Volume Management and System Configuration

  • f_mount - Register/Unregister the work area of the volume
  • f_mkfs - Create an FAT volume on the logical drive
  • f_fdisk - Create partitions on the physical drive
  • f_getfree - Get free space on the volume
  • f_getlabel - Get volume label
  • f_setlabel - Set volume label
  • f_setcp - Set active code page

UNIX like Shell Commands

Do not expect real UNIX commands not even comparable to Busybox.
  • ls
  • pwd
  • cd
  • cp
  • mv
  • rm
  • chmod
  • cat
  • less
  • mkdir
  • mount
  • umount
  • mkfs
  • dd
  • df
  • du
  • touch

  • date
  • ps
  • kill
  • vi

-- Peter Schmid - 2020-06-03

Comments

Topic attachments
I Attachment History Action Size Date Who Comment
GIFgif MMC-SD-miniSD-microSD-Color-Numbers-Names.gif r1 manage 19.7 K 2020-06-03 - 07:39 PeterSchmid  
Unknown file formatblock letter-f.block r1 manage 1.0 K 2020-06-12 - 19:46 PeterSchmid  
JPEGjpg nucleo-sd-adapter.jpg r1 manage 347.2 K 2020-06-14 - 14:52 PeterSchmid  
Edit | Attach | Watch | Print version | History: r105 | r18 < r17 < r16 < r15 | Backlinks | Raw View | Raw edit | More topic actions...
Topic revision: r16 - 2020-06-30 - PeterSchmid
 
  • Edit
  • Attach
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback