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:
parent
bc1cc591ce
commit
b8e52707e9
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user