avr: allow writing to flash

This commit is contained in:
Virgil Dupras 2020-09-05 14:07:13 -04:00
parent 4910b9caef
commit 5b4917dbe9
5 changed files with 53 additions and 13 deletions

View File

@ -4,4 +4,4 @@ This program allows you to access AVR chips Flash memory, EEPROM
and fuses using a SPI relay. This requires drivers that imple-
ment the SPI Relay protocol.
Load range: B691-BXXX
Load range: B691-B693

25
blk/691
View File

@ -1,14 +1,15 @@
: _cmd ( b4 b3 b2 b1 -- r4 )
(spix) DROP DUP (spix) DROP SWAP (spix) = ( b4 f )
SWAP (spix) SWAP ( r4 f ) NOT IF ABORT" AVR err" THEN ;
( page size in words, 64 is default on atmega328P )
CREATE aspfpgsz 64 ,
VARIABLE aspprevx
: _x ( a -- b ) DUP aspprevx ! (spix) ;
: _xc ( a -- b ) DUP (spix) ( a b )
DUP aspprevx @ = NOT IF ABORT" AVR err" THEN ( a b )
SWAP aspprevx ! ( b ) ;
: _cmd ( b4 b3 b2 b1 -- r4 ) _xc DROP _x DROP _xc DROP _x ;
: asprdy ( -- ) BEGIN 0 0 0 0xf0 _cmd 1 AND NOT UNTIL ;
: asp$ ( -- )
( RESET pulse ) (spie) (spid) (spie)
( wait 20ms ) 2000 0 DO LOOP
( enable prog ) 0 0 0x53 0xac _cmd DROP ;
: asprdy ( -- f ) 0 0 0 0xf0 _cmd NOT ;
: aspfl@ ( -- lfuse ) 0 0 0 0x50 _cmd ;
: aspfh@ ( -- hfuse ) 0 0 0x08 0x58 _cmd ;
: aspfe@ ( -- efuse ) 0 0 0x00 0x58 _cmd ;
: aspfl! ( lfuse -- ) 0 0xa0 0xac _cmd ;
: aspfh! ( hfuse -- ) 0 0xa8 0xac _cmd ;
: aspfe! ( efuse -- ) 0 0xa4 0xac _cmd ;
( wait >20ms ) 5000 0 DO LOOP
( enable prog ) 0xac (spix) DROP
0x53 _x DROP 0 _xc DROP 0 _x DROP ;
: asperase 0 0 0x80 0xac _cmd asprdy ;

7
blk/692 Normal file
View File

@ -0,0 +1,7 @@
( fuse access. read/write one byte at a time )
: aspfl@ ( -- lfuse ) 0 0 0 0x50 _cmd ;
: aspfh@ ( -- hfuse ) 0 0 0x08 0x58 _cmd ;
: aspfe@ ( -- efuse ) 0 0 0x00 0x58 _cmd ;
: aspfl! ( lfuse -- ) 0 0xa0 0xac _cmd ;
: aspfh! ( hfuse -- ) 0 0xa8 0xac _cmd ;
: aspfe! ( efuse -- ) 0 0xa4 0xac _cmd ;

13
blk/693 Normal file
View File

@ -0,0 +1,13 @@
: aspfb! ( n a --, write word n to flash buffer addr a )
SWAP 256 /MOD ( a lo hi ) SWAP ROT ( hi lo a )
DUP ROT ( hi a a lo ) SWAP ( hi a lo a )
0 0x40 ( hi a lo a 0 0x40 ) _cmd DROP ( hi a )
0 0x48 _cmd DROP ;
: aspfp! ( page --, write buffer to page )
0 SWAP aspfpgsz @ * 256 /MOD ( 0 lsb msb )
0x4c _cmd DROP asprdy ;
: aspf@ ( page a -- n, read word from flash )
SWAP aspfpgsz @ * OR ( addr ) 256 /MOD ( lsb msb )
2DUP 0 ROT ROT ( lsb msb 0 lsb msb )
0x20 _cmd ( lsb msb low )
ROT ROT 0 ROT ROT ( low 0 lsb msb ) 0x28 _cmd 8 LSHIFT OR ;

View File

@ -48,3 +48,22 @@ batch, that is, running your commands right after the "asp$" command, ending
your batch with "(spid)" so that the next batch works. In my tests, interacting
with the chip "live" in a single "asp$" session sometimes resulted in unreliable
data that didn't properly detect sync errors. TODO: investigate further.
# Writing data to Flash
Writing to AVR's flash is done in batch mode, page by page. To this end, the
chip has a buffer which is writable byte-by-byte. To write to the flash, you
begin by writing to that buffer using aspfb! and then write to a page using
aspfp!.
Please note that aspfb! deals with *words*, not bytes. If, for example, you want
to hook it to A!*, make sure you use AMOVEW instead of AMOVE. You will need to
create a wrapper word around aspfb! that divides dst addr by 2 because AMOVEW
use byte-based addresses but aspfb! uses word-based ones. You also have to make
sure that A@* points to @ (or another word-based fetcher) instead of its default
value of C@.
Beware of bootloader sections! By default, AVR chips have a bootloader using the
first few pages (by default, the ATMega328P uses 4 pages for its bootloader).
Check (or modify) the BOOTSZ fuses to confirm where you whould start writing
your program.