diff --git a/blk/690 b/blk/690 index 0a3ade7..27feaaa 100644 --- a/blk/690 +++ b/blk/690 @@ -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 diff --git a/blk/691 b/blk/691 index cb76f2f..2b618ba 100644 --- a/blk/691 +++ b/blk/691 @@ -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 ; diff --git a/blk/692 b/blk/692 new file mode 100644 index 0000000..37f2327 --- /dev/null +++ b/blk/692 @@ -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 ; diff --git a/blk/693 b/blk/693 new file mode 100644 index 0000000..3c931c4 --- /dev/null +++ b/blk/693 @@ -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 ; diff --git a/doc/avr.txt b/doc/avr.txt index a40318c..70b3a47 100644 --- a/doc/avr.txt +++ b/doc/avr.txt @@ -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.