Tags:
view all tags
%DASHBOARD{ section="dashboard_start" }% %DASHBOARD{ section="banner" image="%PUBURLPATH%/Cosmac/RaspiElf/raspi-elfmemcard-s.jpg" title="Serial EEPROMs as Mass Storage" titlestyle="color:#F00000;" }% %DASHBOARD{ section="box_start" title="Intro" width="485" height="200"}% Forth without mass storage (blocks, screens) is a not complete. A SD-Card [[http://www.elf-emulation.com/hardware/ide8.html][interface]] could be a reasonable solution but it is an overkill for a small Forth system. Small serial EEPROMs are for my opinion more suitable. %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" title="Contents" width="460" height="200"}% %TOC% %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" width="992" height="600" title="SPI EEPROMs " }% ---+ SPI EEPROMs The Serial Peripheral Interface [[https://en.wikipedia.org/wiki/Serial_Peripheral_Interface][SPI]] or four-wire serial bus is easy to use. The CDP1802 (MC) is the SPI master, the EEPROM is the slave. There are many different EEPROM types and sizes available e.g. [[http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-8832C-SEEPROM-AT25M02-Datasheet.pdf][AT25M02]] (2Mbit, 256 !KiB, $3), [[http://ww1.microchip.com/downloads/en/DeviceDoc/22064B.pdf][25LC1024]] (128 !KiB, $2), or [[http://ww1.microchip.com/downloads/en/DeviceDoc/20005265A.pdf][25LC512]] (64 !KiB, $1.50). All available in DIL8 packages. 64/128/256 !KiB seems very small for today's standards where storage is quantified in !GiB, but I think it's more than enough for a small Forth system, the size is similar to early floppy disks. If you want more memory there are 16 !MiB serial _Flash_ chips e.g. from WINBOND [[http://www.winbond.com/resource-files/w25q128jv%20spi%20revc%2011162016.pdf][W25Q128J]] or [[https://www.mouser.ch/datasheet/2/198/25LP-WP128F-1146765.pdf][IS25LP128F]], please note they are 3.3 V devices and in SMT! <verbatim> CLK MC ->- host MOSI MC ->- host MISO MC -<- host SS MC ->- host or other peripherals (optional) </verbatim> A high-to-low transition on the _CS_ pin is required to start an operation and a low-to-high transition is required to end an operation. _Invalid Opcode_: If an invalid opcode is received, no data will be shifted into AT25M02 and the Serial Data Output (SO) pin will remain in a high impedance state until the falling edge of CS is detected again. This will reinitialize the serial communication. While in _Hold_ mode, the SO pin will be in a high impedance state. In addition, both the SI pin and the SCK pin will be ignored. From 1024 Kibit up there are 24 address bits, 8 Kibit to 512 Kibit have 16 address bits. 1, 2, and 4 Kibit have 8 bit address bits. !25LCxxxx Instruction Set | *Name* | *Format* | *Description* | | _READ_ | 0000 0011 | Read data from memory array beginning at selected address | | _WRITE_ | 0000 0010 | Write data to memory array beginning at selected address | | _WREN_ | 0000 0110 | Set the write enable latch (enable write operations) | | _WRDI_ | 0000 0100 | Reset the write enable latch (disable write operations) | | _RDSR_ | 0000 0101 | Read STATUS register | | _WRSR_ | 0000 0001 | Write STATUS register | | PE | 0100 0010 | Page Erase erase one page in memory array | | SE | 1101 1000 | Sector Erase erase one sector in memory array | | CE | 1100 0111 | Chip Erase erase all sectors in memory array | | RDID | 1010 1011 | Release from Deep power-down and read electronic signature | | DPD | 1011 1001 | Deep Power-Dow | !AT25M02 Instruction Set | *Name* | *Format* | *Description* | | _READ_ | 0000 0011 | Read from Memory Array | | _WRITE_ | 0000 0010 | Write to Memory Array | | _WREN_ | 0000 0110 | Set Write Enable Latch (WEL) | | _WRDI_ | 0000 0100 | Reset Write Enable Latch (WEL) | | _RDSR_ | 0000 0101 | Read Status Register (SR) | | _WRSR_ | 0000 0001 | Write Status Register (SR) | | LPWP | 0000 1000 | Low Power Write Poll | %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" width="992" height="600" title="EEPROM Connected to MC's Centronics Connector (Switches and LEDs)" }% ---+ EEPROM Connected to MC's Centronics Connector (Switches and LEDs) Sharing the LED and Switch port, you loose three LEDs and one switch or IN. Possible conflict with the bootstrap loader, if there is a read sequence (CS and read pattern 0000 0011). To prevent this, set the EEPROM into HOLD state e.g. with the <SPAN STYLE="text-decoration:overline">WAIT</SPAN> signal. | *SPI* | *MC (Master)* | *25LCxxxx (Slave)* | *Interface* | | MISO | J2.1 <SPAN STYLE="text-decoration:overline">IN</SPAN> EF4 | 2 SO | diode e.g. 1N4148 | | MOSI | J2.11 O7 LED7 | 5 SI | direct | | CLK | J2.10 O6 LED6 | 6 SCK | direct | | CS | J2.12 O5 LED5 | 1 <SPAN STYLE="text-decoration:overline">CS</SPAN> | direct | | | P4.3 VDD | 8 VCC | +5V capacitor 100 nF to GND | | | " | 3 <SPAN STYLE="text-decoration:overline">WP</SPAN> | +5V | | | J2.14 <SPAN STYLE="text-decoration:overline">WAIT</SPAN> | 7 <SPAN STYLE="text-decoration:overline">HOLD</SPAN> | direct | | | 21 GND | 4 GND | GND | %IMAGE{"%PUBURLPATH%/Cosmac/McForth/mc-eeprom-conn.png" type="thumb" caption="Schematic"}% Raspberry Pi can emulate SPI EEPROM. On RaspiElf the switches/LEDs are already connected to Raspi's GPIOs. No need for additional hardware. But I have to write an SPI server for the Raspberry Pi. Raspi's SPI interfaces can't be used because of conflicting port usage. ---++ Read Byte <pre> CS0 EQU 0b1101111 CS1 EQU 0b0010000 CLK0 EQU 0b1011111 CLK1 EQU 0b0100000 DATA0 EQU 0b0111111 DATA1 EQU 0b1000000 ; MSB first READBYTE: LDI 0 PLO R5 LDI 0xFF PHI R6 LDI 0xFF - 8 PLO R6 SEX R0 BITLOOP: OUT4,0b01000000 ; CLK for SPI OUT4,0b00000000 INC R6 GHI R6 ; set CARRY SHRC GLO R5 B4 SETBIT ; branch if bit set SHL ; bit not set BR SAVEBIT SETBIT: SHLC SAVEBIT: PLO R5 GLO R6 BNZ BITLOOP </pre> about 230 cycles for one byte -> 1 ms -> 1 KiB takes about 1 s @ 1.79 MHz ---++ Write Byte <pre> WRITEBYTE: LDI 0 PHI R6 LDI 8 PLO R6 SEX R0 BITLOOP: GLO R5 ; get the next bit SHLC , next bit is in the carry PLO R5 BDF SETBIT OUT4,0b01000000 ; CLK for SPI with data bit cleared OUT4,0b00000000 BR NEXT SETBIT: OUT4,0b11000000 ; CLK for SPI with data bit set OUT4,0b10000000 NEXT: DEC R6 GLO R6 BNZ BITLOOP </pre> %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" width="992" height="600" title="EEPROM patched on MC PCB" }% ---+ EEPROM patched on MC PCB SPI Mode 0, data is always latched in on the rising edge of SCK and always output on the falling edge of SCK. For CS one output port bis is needed e.g. O7 or N0 (INP1) to start/end operation (A high-to-low transition on the _CS_ pin is required to start an operation and a low-to-high transition is required to end an operation). | *SPI* | *MC (Master)* | *25LCxxxx (Slave)* | *Interface* | | MISO | <SPAN STYLE="text-decoration:overline">EF2</SPAN> | 2 SO | direct | | MOSI | D0 | 5 SI | direct | | CLK | TPB & N1 (OUT2) | 6 SCK | [[https://en.wikipedia.org/wiki/Wired_logic_connection][wired AND]]; Pullup 10 k, 2 1N4148 | | CS | N0 | 1 <SPAN STYLE="text-decoration:overline">CS</SPAN> | direct | | | | 8 VCC | +5V | | | | 3 <SPAN STYLE="text-decoration:overline">WP</SPAN> | +5V | | | J2.14 <SPAN STYLE="text-decoration:overline">WAIT</SPAN> | 7 <SPAN STYLE="text-decoration:overline">HOLD</SPAN> | direct | | | | 4 GND | GND | %IMAGE{"%PUBURLPATH%/Cosmac/McForth/mc-eeprom-u1.png" type="thumb" caption="Schematic"}% ---++ Read Byte <pre> GHI R0 ; D = 0 PLO R5 ; reset all bits LDI 0 - 8 ; counting up 8 times PLO R6 ; bit counter RDBITLOOP GLO R4 ; set CARRY SHR GLO R5 BN2 SETBIT ; branch if bit set (EF2 == 0) SHL ; bit not set BR SAVEBIT SETBIT SHLC SAVEBIT OUT P2 ; CLK for SPI, INC Rx PLO R5 GLO R6 BNZ RDBITLOOP </pre> about 200 cycles for one byte -> 1 ms -> 1 KiB takes about 1 s ---++ Write Byte <pre> WRITEBYTE PLO R5 ; save transmit byte LDI 8 ; counter 8 bits PLO R6 WRBITLOOP GLO R5 ; get the next bit SHL ; next bit is in the carry PLO R5 LSNF ; skip if bit is 0 OUT P2 BYTE 00000001B ; CLK for SPI with data bit cleared LSDF ; skip if bit is 1 OUT P2 BYTE 00000000B ; CLK for SPI with data bit set DEC R6 GLO R6 BNZ WRBITLOOP </pre> %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" width="992" height="600" title="EEPROM Connected to Raspberry Pi" }% ---+ EEPROM Connected to Raspberry Pi * http://www.netzmafia.de/skripten/hardware/RasPi/RasPi_SPI.html * https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md * http://wiringpi.com/reference/spi-library/ | *SPI Function* | *BCM/GPIO* | *RaspiElf* | | _SPI0 MISO_ | 9 | IN4 | | _SPI0 MOSI_ | 10 | IN3 | | _SPI0 SCLK_ | 11 | IN6 | | SPI0 CS0 | 8 | IN7 | | _SPI0 CS1_ | 7 | O0 | | EEPROM CS | 5 | O1 | | SPI1 MISO | 19 | O5 | | SPI1 MOSI | 20 | - | | SPI1 SCLK | 21 | shutdown | | SPI1 CS0 | 18 | <SPAN STYLE="text-decoration:overline">CLR</SPAN> | | SPI1 CS1 | 17 | <SPAN STYLE="text-decoration:overline">WAIT</SPAN> | | %IMAGE{"%PUBURLPATH%/Cosmac/MassStorage/raspi-eeprom.png" type="thumb" caption="Schematic"}% | %IMAGE{"%PUBURLPATH%/Cosmac/MassStorage/raspi-zero-eeprom.jpg" type="thumb" caption="Raspberry Pi Zero and EEPROM interface"}% | ---++ eeprom2bin (download tool) $ *NAME*: eeprom2bin - Copies the EEPROM memory to a binary file on the Raspberry Pi. $ *SYNOPSIS*: eeprom2bin [-s hexadr] [-e hexadr] [file] $ *DESCRIPTION*: Copies the EEPROM memory to a binary file (or stdout) on the Raspberry Pi. The Raspberry Pi GPIO SPI0.1 is used as interface to the SPI EEPROM (24 bit address, at least a 1024 Kibit type, 256 byte page). The generated data is written to the standard output stream or to a _file_. Caution: Overwrite file if it exists. Use > for redirecting (save the file) or | for piping to another command (e.g. hexdump). $ *OPTIONS*: Non argument options that are duplicated on the command line are not harmful. For options that require an argument, each duplication will override the previous argument value. $ *-s* _hexadr_: start address in hex (0 is default) $ *-e* _hexadr_: end adress in hex (0x1FFFF is default) ---++ bin2eeprom (upload tool) $ *NAME*: bin2eeprom - Copies the content of binary file on the Raspberry Pi to EEPROM. $ *SYNOPSIS*: bin2eeprom [-s hexadr] [-e hexadr] [file] $ *DESCRIPTION*: Copies the content of binary file on the Raspberry Pi to EEPROM memory. The Raspberry Pi GPIO SPI0.1 is used as interface to the SPI EEPROM (24 bit address, at least a 1024 Kibit type, 256 byte page). Use < for redirecting or | for piping from another command. $ *OPTIONS*: Non argument options that are duplicated on the command line are not harmful. For options that require an argument, each duplication will override the previous argument value. $ *-s* _hexadr_: start address in hex (0 is default) $ *-e* _hexadr_: end adress in hex (0x1FFFF is default) ---++ How to get and build the EEPROM tools Get the source from the [[https://github.com/spyren/RaspiElf][GIT repository]] (if you have not installed GIT yet, then install it with =sudo apt-get install git=), type only the bold text after the $ sign: <pre> pi@cosmac:~/elf $ <b>git clone https://github.com/spyren/RaspiElf</b> Cloning into 'RaspiElf'... pi@cosmac:~/elf $ </pre> Build (compile) from the sources: <pre> pi@cosmac:~/elf $ <b>cd RaspiElf</b> pi@cosmac:~/elf/RaspiElf $ <b>cd eeprom</b> pi@cosmac:~/elf/RaspiElf/eeprom $ <b>make</b> cc -g -c eeprom2bin.c cc -g -o eeprom2bin -lwiringPi eeprom2bin.o cc -g -c bin2eeprom.c cc -g -o bin2eeprom -lwiringPi bin2eeprom.o pi@cosmac:~/elf/RaspiElf/eeprom $ </pre> Install the binaries into =/usr/local/bin= <pre> pi@cosmac:~/elf/RaspiElf/eeprom $ <b>sudo make install</b> install -m 557 eeprom2bin bin2eeprom /usr/local/bin </pre> Install !wiringPi (GPIO Interface library for the Raspberry Pi), details see http://wiringpi.com/download-and-install/ Enable the SPI interface <pre> @cosmac:~/elf/RaspiElf/eeprom $ <b>sudo raspi-config</b> </pre> * 5 Interfacing Options Configure connections to peripherals * P4 SPI Enable/Disable automatic loading of SPI kernel module %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" width="992" height="600" title="Mini Boot Loader" }% ---+ Mini Boot Loader <pre> ; TITL "EEPROM Boot Loader for Elf Memebership Card" ; EJCT 60 CPU 1802 NUMBER EQU 0 ; ; Register Definitions: ; R0 EQU 0 R1 EQU 1 R2 EQU 2 R3 EQU 3 R4 EQU 4 R5 EQU 5 R6 EQU 6 R7 EQU 7 R8 EQU 8 R9 EQU 9 R10 EQU 10 R11 EQU 11 R12 EQU 12 R13 EQU 13 R14 EQU 14 R15 EQU 15 ; ; I/O Port Definitions: ; P1 EQU 1 P2 EQU 2 P3 EQU 3 P4 EQU 4 P5 EQU 5 P6 EQU 6 P7 EQU 7 ORG 0H ; R0 program counter ; R1 subroutine pc ; R2 stack pointer ; R5.0 byte (read/write) ; R6.0 bit counter ; R4.0 carry bits ; R7 destination address ; R8 length BOOTLOADER 0000 f8:11111000 LDI 080H ; set destination address 0001 80:10000000 0002 b7:10110111 PHI R7 0003 f8:11111000 LDI 080H ; set length 0004 80:10000000 0005 b8:10111000 PHI R8 0006 90:10010000 GHI R0 ; D = 00H 0007 a7:10100111 PLO R7 ; destination address begins at page 0008 a8:10101000 PLO R8 ; lenght in pages 0009 b1:10110001 PHI R1 ; high byte subroutine 000a a2:10100010 PLO R2 ; stack pointer = 0100H 000b f8:11111000 LDI 01H 000c 01:00000001 000d b2:10110010 PHI R2 000e f8:11111000 LDI LOW WRITEBYTE ; low byte subroutine 000f 48:01001000 0010 a1:10100001 PLO R1 0011 f8:11111000 LDI 01H ; for the carry 0012 01:00000001 0013 a4:10100100 PLO R4 0014 61:01100001 OUT P1 ; deactivate CS to start operation 0015 00:00000000 BYTE 00H 0016 e1:11100001 SEX R1 ; for immediate OUT in subroutine 0017 f8:11111000 LDI 03H ; EEPROM read command 0018 03:00000011 0019 d1:11010001 SEP R1 ; CALL WRITEBYTE 001a 90:10010000 GHI R0 ; address bit 16 to 23 = 0 001b d1:11010001 SEP R1 ; CALL WRITEBYTE, replace by NOP for ; 8 to 512 Kibit EEPROMs 001c 90:10010000 GHI R0 ; address bit 8 to 15 = 0 001d d1:11010001 SEP R1 ; CALL WRITEBYTE, replace by NOP for ; 1 to 4 Kibit EEPROMs 001e 90:10010000 GHI R0 ; address bit 0 to 7 = 0 001f d1:11010001 SEP R1 ; CALL WRITEBYTE 0020 e6:11100110 SEX R6 ; Rx for OUT 0021 90:10010000 BLOCKLOOP GHI R0 ; D = 0 0022 a5:10100101 PLO R5 ; reset all bits 0023 f8:11111000 LDI 0 - 8 ; counting up 8 times 0024 f8:11111000 0025 a6:10100110 PLO R6 ; bit counter 0026 84:10000100 RDBITLOOP GLO R4 ; set CARRY 0027 f6:11110110 SHR 0028 85:10000101 GLO R5 0029 3d:00111101 BN2 SETBIT ; branch if bit set (EF2 == 0) 002a 2e:00101110 002b fe:11111110 SHL ; bit not set 002c 30:00110000 BR SAVEBIT 002d 2f:00101111 002e 7e:01111110 SETBIT SHLC 002f 62:01100010 SAVEBIT OUT P2 ; CLK for SPI, INC Rx 0030 a5:10100101 PLO R5 0031 86:10000110 GLO R6 0032 3a:00111010 BNZ RDBITLOOP 0033 26:00100110 0034 85:10000101 GLO R5 ; get byte 0035 57:01010111 STR R7 ; save byte 0036 17:00010111 INC R7 0037 28:00101000 DEC R8 0038 88:10001000 GLO R8 0039 3a:00111010 BNZ BLOCKLOOP 003a 21:00100001 003b e2:11100010 SEX R2 ; one page finished 003c 98:10011000 GHI R8 003d 52:01010010 STR R2 003e 64:01100100 OUT P4 ; show page count on LEDs 003f 22:00100010 DEC R2 0040 3a:00111010 BNZ BLOCKLOOP-1 0041 20:00100000 0042 61:01100001 OUT P1 ; deactivate CS to stop operation 0043 e0:11100000 SEX R0 0044 c0:11000000 LBR 08000H ; start loaded program 0045 80:10000000 0046 00:00000000 0047 d0:11010000 SEP R0 0048 a5:10100101 WRITEBYTE PLO R5 ; save transmit byte 0049 f8:11111000 LDI 8 ; counter 8 bits 004a 08:00001000 004b a6:10100110 PLO R6 004c 85:10000101 WRBITLOOP GLO R5 ; get the next bit 004d fe:11111110 SHL ; next bit is in the carry 004e a5:10100101 PLO R5 004f c7:11000111 LSNF ; skip if bit is 0 0050 62:01100010 OUT P2 0051 01:00000001 BYTE 00000001B ; CLK for SPI with data bit cleared 0052 cf:11001111 LSDF ; skip if bit is 1 0053 62:01100010 OUT P2 0054 00:00000000 BYTE 00000000B ; CLK for SPI with data bit set 0055 26:00100110 DEC R6 0056 86:10000110 GLO R6 0057 3a:00111010 BNZ WRBITLOOP 0058 4c:01001100 0059 30:00110000 BR WRITEBYTE-1 005a 47:01000111 END </pre> %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" width="992" height="600" title="Kermit/ZModem" }% ---+ Kermit/ZModem What about using KERMIT or ZMODEM protocol for the file transfer and use the file system on the host? No need to add additional hardware (SD-card is anyway to modern ;-) You could use an old CP/M or even a PDP11 as host. The C-Kermit Local Server mode, e.g. MC can read/write the blocks as files =block.0=, =block.2=, =block.255=. The serial communication is really slow, not only because of the 9600 baud, but you have to wait after each character to give CDP1802 some computation time. https://github.com/utoh/pygmy-forth/blob/master/extras/kermit/pfkerm.doc %DASHBOARD{ section="box_end" }% * https://shop.pimoroni.com/products/sparkfun-level-shifting-microsd-breakout * https://learn.adafruit.com/adafruit-micro-sd-breakout-board-card-tutorial * http://elm-chan.org/docs/mmc/mmc_e.html %DASHBOARD{ section="dashboard_end" }% -- %USERSIG{PeterSchmid - 2019-01-24}% ---++ Comments %COMMENT%
Attachments
Attachments
Topic attachments
I
Attachment
History
Action
Size
Date
Who
Comment
png
raspi-eeprom.png
r3
r2
r1
manage
25.8 K
2019-01-27 - 21:22
PeterSchmid
jpg
raspi-zero-eeprom.jpg
r1
manage
201.6 K
2019-01-27 - 21:40
PeterSchmid
Edit
|
Attach
|
Watch
|
P
rint version
|
H
istory
:
r23
|
r16
<
r15
<
r14
<
r13
|
B
acklinks
|
V
iew topic
|
Raw edit
|
More topic actions...
Topic revision: r14 - 2019-02-05
-
PeterSchmid
Home
Site map
Cosmac web
MRR web
MecrispCube web
SuperRandonnee web
TWiki web
Ursula web
Velo web
Cosmac Web
Create New Topic
Index
Search
Changes
Notifications
RSS Feed
Statistics
Preferences
View
Raw View
Print version
Find backlinks
History
More topic actions
Edit
Raw edit
Attach file or image
Edit topic preference settings
Set new parent
More topic actions
Account
Log In
Edit
Attach
Copyright © 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