recipes/arduinouno/at28: improve reliability

Previously, it could never write more than a few bytes before pingpong
getting a mismatch error. Now, I can pingpong Collapse OS binary
without a mismatch.
This commit is contained in:
Virgil Dupras 2020-07-28 15:18:26 -04:00
parent bc1cc591ce
commit b8e52707e9
4 changed files with 54 additions and 24 deletions

View File

@ -14,10 +14,10 @@ all: $(TARGET)
@echo Done!
send: $(PROGNAME).hex
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$<
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$(PROGNAME).hex
$(TARGET): at28wr.asm
$(AVRA) -o $@ at28wr.asm
$(TARGET): $(PROGNAME).asm
$(AVRA) -o $@ $(PROGNAME).asm
clean:
rm -f $(TARGET) *.S.eep.hex *.S.obj

View File

@ -23,6 +23,11 @@ on the Arduino's right side (except for VCC, which needs to be wired).
PD0 and PD1 are not used because they're used for the UART.
AT28 selection pins are pulled up to avoid accidental writes due to their line
floating before Arduino's initialization.
I've put 1uf decoupling caps next to each IC.
## Software
The software in at28wr.asm listens to the UART and writes every byte it receives

View File

@ -8,6 +8,17 @@
; with PD7:2 for bits 7:2 and PB1:0 for bits 1:0 (PD1 and PD0 are used for
; UART).
;
; *** Timing, matching and CE ***
;
; A lot of trial-and-errors went into those NOPs being place to give time for
; latching. All these timing are well, well above maximums given in the specs,
; but when I wasn't going well, well above those specs, I was experiencing
; read/write errors. It seems we live in an imperfect world!
;
; I'm also not sure, in "writedata", whether toggling CE along with WE is
; actually needed, but until I did, I was experiencing random write failures.
; So, we end up with this...
;
; *** Register Usage ***
;
; r0: holds whether last received char was tty-escaped (0 = no, 1=yes)
@ -92,6 +103,10 @@ sendaddr:
; send r20 to EEPROM's I/O7:0 through PD7:2 and PB1:0
writedata:
cbi PORTB, FLCE
; addr is latched on WE falling edge
cbi PORTB, FLWE
; send bits 7:2
mov r16, r20
andi r16, 0xfc
@ -106,49 +121,59 @@ writedata:
andi r17, 0xfc
or r16, r17
out PORTB, r16
; data is latched on rising edge
sbi PORTB, FLWE
sbi PORTB, FLCE
nop ; Give the AT28 time to latch
nop
nop
ret
; push r20 to the rom and increase the memory counter
pushdata:
nextaddr:
; first, set up addr
mov r23, r21
rcall sendaddr
mov r23, r22
rcall sendaddr
inc r22
brne pushdata_0 ; no overflow? skip
brne nextaddr_0 ; no overflow? skip
inc r21
pushdata_0:
; addr is latched on WE falling edge
cbi PORTB, FLWE
; now, lets set up data. Plenty enough instructions to ensure a 100ns
; minimum delay.
rcall writedata
; data is latched on rising edge
sbi PORTB, FLWE
nextaddr_0:
ret
; wait until I/O7 stops toggling
waitio7:
cbi PORTB, FLCE
cbi PORTB, FLOE
nop ; Give the AT28 time to latch
nop
nop
in r16, PIND
sbi PORTB, FLOE
sbi PORTB, FLCE
andi r16, 0xfc
cbi PORTB, FLCE
cbi PORTB, FLOE
nop ; Give the AT28 time to latch
nop
nop
in r17, PIND
sbi PORTB, FLOE
sbi PORTB, FLCE
andi r17, 0xfc
cp r16, r17
brne waitio7
ret
; read EEPROM's I/O7:0 through PD7:2 and PB1:0 and put result in r20.
; read EEPROM's I/O7:0 through PD7:2 and PB1:0 into r20
readdata:
cbi PORTB, FLCE
cbi PORTB, FLOE
nop ; Give the AT28 time to latch
nop
nop
; read bits 7:2
in r20, PIND
andi r20, 0xfc
@ -157,13 +182,14 @@ readdata:
andi r16, 0x03
or r20, r16
sbi PORTB, FLOE
sbi PORTB, FLCE
ret
; Set PD7:2 and PB1:0 to output
ioout:
ldi r16, 0xfc ; PD7:2
out DDRD, r16
ldi r16, 0x3f ; PB5:0 (WE, OE and CE too)
ldi r16, 0x3f ; PB5:0 (CP, WE, OE and CE too)
out DDRB, r16
ret
@ -181,11 +207,9 @@ main:
ldi r16, high(RAMEND)
out SPH, r16
; We begin with WE and OE disabled (high), but CE stays enabled (low)
; the whole time.
sbi PORTB, FLWE
sbi PORTB, FLOE
cbi PORTB, FLCE
sbi PORTB, FLCE
; Clear counters and flags
clr r0
@ -204,7 +228,8 @@ main:
loop:
rcall uartrd
rcall ioout
rcall pushdata
rcall nextaddr
rcall writedata
rcall ioin
rcall waitio7
rcall readdata

View File

@ -12,7 +12,7 @@ properly set up, TTY-wise. You'll probably want to do that with `stty`. The tool
itself takes care of setting the regular stuff (`cs8`, `-parenb`, etc), but you
need to set the speed. Here's an example working on OpenBSD:
$ ( stty 115200 ; ./upload - a000 os.bin ) <>/dev/cuaU0
$ ( stty 115200 raw ; ./upload - a000 os.bin ) <>/dev/cuaU0
To be honest, I'm having a bit of troubles making these tools work as well on
OpenBSD as they do in Linux. But it *does* work. Here are some advices: