Author: wmb Date: 2009-11-25 23:27:54 +0100 (Wed, 25 Nov 2009) New Revision: 1515
Added: dev/am29lv008b.fth dev/en29lv800.fth Log: Added drivers for some FLASH ROM variants.
Added: dev/am29lv008b.fth =================================================================== --- dev/am29lv008b.fth (rev 0) +++ dev/am29lv008b.fth 2009-11-25 22:27:54 UTC (rev 1515) @@ -0,0 +1,210 @@ +purpose: Flash ROM programming for AMD 29LV008B and relatives - untested +copyright: Copyright 1996-2001 FirmWorks All Rights Reserved + +\ This file depends on an environment-specific file containing +\ /flash, fctl!, fdata!, fc@ and enable-flash-writes +\ There is a simple user interface to these primitive routines +\ in pkg/flash/flash.fth + +hex +10.0000 value /flash +d# 19 value #sectors +defer enable-flash-writes ' noop to enable-flash-writes +defer fctl! +defer fdata! + +\ magic numbers +h# 5555 constant addr0 +h# 2aaa constant addr1 + +create bb-sectors 0 l, h# 4000 l, h# 6000 l, h# 8000 l, + h# 1.0000 l, h# 2.0000 l, h# 3.0000 l, h# 4.0000 l, + h# 5.0000 l, h# 6.0000 l, h# 7.0000 l, h# 8.0000 l, + h# 9.0000 l, h# a.0000 l, h# b.0000 l, h# c.0000 l, + h# d.0000 l, h# e.0000 l, h# f.0000 l, + +create bt-sectors 0 l, + h# 1.0000 l, h# 2.0000 l, h# 3.0000 l, h# 4.0000 l, + h# 5.0000 l, h# 6.0000 l, h# 7.0000 l, h# 8.0000 l, + h# 9.0000 l, h# a.0000 l, h# b.0000 l, h# c.0000 l, + h# d.0000 l, h# e.0000 l, + h# f.0000 l, h# f.8000 l, h# f.a000 l, h# f.c000 l, + +defer sector-map ' bb-sectors to sector-map +: sector>offset ( sector -- offset ) /l * sector-map + l@ ; +: sector>size ( sector -- size ) + dup 1+ #sectors = if /flash else dup 1+ sector>offset then + swap sector>offset - +; +: offset>sector ( offset -- sector ) + #sectors 1- #sectors 0 do + over i sector>offset i sector>size + u< if drop i leave then + loop nip +; +: offset+len>sectors ( offset len -- end#+1 start# ) + over offset>sector -rot + + 1- offset>sector 1+ swap +; + +\ the command sequence +: unlock-write ( -- ) h# aa addr0 fctl! h# 55 addr1 fctl! ; +: flashmode ( n -- ) addr0 fctl! ; + +\ normal mode, acts like a ROM +: read-mode ( -- ) h# f0 flashmode ; + +\ note side effect: writes stay enabled! +: autoselect-mode ( -- ) + enable-flash-writes + unlock-write h# 90 flashmode +; + +\ these need to recognize more cases. What are the numbers? +: .fl-manuf ( n -- ) + case + 1 of ." AMD " endof + h# 1f of ." ATMEL" endof + h# 89 of ." Intel " endof + dup . + endcase +; +: .fl-dev ( n -- ) + case + h# 37 of ." 29LV008BB " endof + h# 3e of ." 29LV008BT " endof + dup . + endcase +; +: flash-type ( -- device-type manufacturer ) + autoselect-mode 1 fc@ 0 fc@ read-mode +; +: .flash-type ( -- ) flash-type .fl-manuf .fl-dev ; +: .flash ( -- ) .flash-type ; +: (?programmable) ( -- ) + flash-type 1 = if + case + h# 37 of ['] bb-sectors to sector-map endof + h# 3e of ['] bt-sectors to sector-map endof + ( default ) + collect( + ." Unsupported Flash device type: " .flash + ." This firmware can currently program AMD 29LV008B devices." + )collect alert + abort + endcase + then +; +' (?programmable) to ?programmable + +: .flash-protection ( -- ) + autoselect-mode + #sectors 0 do + ." sector " i .d + i sector>offset ." offset = " 8 u.r + i sector>size ." size = " 8 u.r + i sector>offset 2 + fc@ if ." protected" else ." unprotected" then + cr + loop + read-mode +; +: ?partial-protected ( offset len -- ) + 2dup + /flash > if + collect( + ." Image is too big." cr + )collect alert + abort + then + ['] (?programmable) catch if 2drop abort then + autoselect-mode + offset+len>sectors ?do + i sector>offset 2 + fc@ if + read-mode + collect( + ." Cannot program flash." cr + ." Sector " i .d ." is protected." cr + )collect alert + abort + then + loop + read-mode +; + +: clear-status ( -- ) f0 flashmode ; +\ wait until done, check for errors +: data-poll ( n a -- hung? ) + begin + 2dup fc@ xor h# 80 and while ( n a ) \ busy? + dup fc@ h# 20 and if ( n a ) \ error? + fc@ xor h# 80 and abort" write failed " \ abort on still busy + exit \ okay + then + repeat 2drop +; + +: sector-erase ( sector -- ) + enable-flash-writes + unlock-write h# 80 flashmode \ setup + unlock-write dup sector>offset h# 30 over fctl! + swap sector>size + 1- h# ff swap ['] data-poll catch drop + read-mode +; +: sector-erase-suspend ( -- ) b0 addr0 fctl! ; +: sector-erase-resume ( -- ) 30 addr0 fctl! ; +: partial-erase ( offset len -- ) + offset+len>sectors ?do i sector-erase loop +; +: chip-erase ( -- ) + enable-flash-writes + unlock-write h# 80 flashmode \ setup + unlock-write h# 10 flashmode \ chip erase + h# ff /flash 1- ['] data-poll catch drop + read-mode +; +' chip-erase to erase-flash + +: write-byte ( n a -- ) + 2dup unlock-write h# a0 flashmode + fdata! + ['] data-poll catch if clear-status then +; +: write-bytes ( source-address dest-offset length -- ) + 0 ?do over i + c@ over i + write-byte loop + 2drop read-mode +; + +: verify-bytes ( source-address dest-offset length -- ) + 0 ?do + over i + c@ over i + fc@ <> if + ." erify failed. At " dup i + dup . ." got " fc@ . + ." expected " over i + c@ . abort + then + loop 2drop +; +' verify-bytes to verify-flash + +: verify-erase ( sector# -- error? ) + dup sector>offset swap sector>size bounds ?do + i fc@ h# ff <> if + ." erase error at " i . ." got " i fc@ . cr + true leave + then + loop false +; +: program-sector ( address length sector -- ) + dup push-decimal 1 .r pop-base ." E" + dup sector-erase ( address length sector ) + dup verify-erase if ( address length sector ) + dup sector-erase dup verify-erase abort" Erase failure" + then ( address length sector ) + dup sector>offset -rot sector>size min ( address sector-addr length' ) + bs emit ." W" + 3dup write-bytes ( address sector-addr length' ) + bs emit ." V" ( address sector-addr length' ) + verify-bytes ( ) + space +; + +0 value start-sector +: (program-flash) ( address length -- ) start-sector sector>offset swap write-bytes ; +' (program-flash) to program-flash +
Added: dev/en29lv800.fth =================================================================== --- dev/en29lv800.fth (rev 0) +++ dev/en29lv800.fth 2009-11-25 22:27:54 UTC (rev 1515) @@ -0,0 +1,215 @@ +purpose: Flash ROM programming for EON EN29LV800 - untested +\ See license at end of file + +\ This file depends on an environment-specific file containing +\ /flash, fctl!, fdata!, fc@ and enable-flash-writes + +hex +10.0000 to /flash +d# 19 value #sectors +defer enable-flash-writes ' noop to enable-flash-writes +defer fctl! +defer fdata! + +\ magic numbers +h# 5555 constant addr0 +h# 2aaa constant addr1 + +create bb-sectors 0 l, h# 4000 l, h# 6000 l, h# 8000 l, + h# 1.0000 l, h# 2.0000 l, h# 3.0000 l, h# 4.0000 l, + h# 5.0000 l, h# 6.0000 l, h# 7.0000 l, h# 8.0000 l, + h# 9.0000 l, h# a.0000 l, h# b.0000 l, h# c.0000 l, + h# d.0000 l, h# e.0000 l, h# f.0000 l, + +create bt-sectors 0 l, + h# 1.0000 l, h# 2.0000 l, h# 3.0000 l, h# 4.0000 l, + h# 5.0000 l, h# 6.0000 l, h# 7.0000 l, h# 8.0000 l, + h# 9.0000 l, h# a.0000 l, h# b.0000 l, h# c.0000 l, + h# d.0000 l, h# e.0000 l, + h# f.0000 l, h# f.8000 l, h# f.a000 l, h# f.c000 l, + +defer sector-map ' bb-sectors to sector-map +: sector>offset ( sector -- offset ) /l * sector-map + l@ ; +: sector>size ( sector -- size ) + dup 1+ #sectors = if /flash else dup 1+ sector>offset then + swap sector>offset - +; +: offset>sector ( offset -- sector ) + #sectors 1- #sectors 0 do + over i sector>offset i sector>size + u< if drop i leave then + loop nip +; +: offset+len>sectors ( offset len -- end#+1 start# ) + over offset>sector -rot + + 1- offset>sector 1+ swap +; + +\ the command sequence +: unlock-write ( -- ) h# aa addr0 fctl! h# 55 addr1 fctl! ; +: flashmode ( n -- ) addr0 fctl! ; + +\ normal mode, acts like a ROM +: read-mode ( -- ) h# f0 flashmode ; + +\ note side effect: writes stay enabled! +: autoselect-mode ( -- ) + enable-flash-writes + unlock-write h# 90 flashmode +; + +\ these need to recognize more cases. What are the numbers? +: .fl-manuf ( n -- ) + case + 1 of ." AMD " endof + 1c of ." EON " endof + h# 1f of ." ATMEL" endof + h# 89 of ." Intel " endof + dup . + endcase +; +: .fl-dev ( n -- ) + case + h# 37 of ." 29LV008BB " endof + h# 3e of ." 29LV008BT " endof + h# da of ." 29LV800bt " endof + h# 5b of ." 29LV800bb " endof + dup . + endcase +; +: flash-type ( -- device-type manufacturer ) + autoselect-mode 1 fc@ 0 fc@ read-mode +; +: .flash-type ( -- ) flash-type .fl-manuf .fl-dev ; +: .flash ( -- ) .flash-type ; +: (?programmable) ( -- ) + flash-type 1 = if + case + h# 37 of ['] bb-sectors to sector-map endof + h# 3e of ['] bt-sectors to sector-map endof + h# da of ['] bt-sectors to sector-map endof + h# 5b of ['] bb-sectors to sector-map endof + ( default ) + collect( + ." Unsupported Flash device type: " .flash + ." This firmware can currently program 29LV008B and 29LV800 devices." + )collect alert + abort + endcase + then +; +' (?programmable) to ?programmable + +: .flash-protection ( -- ) + autoselect-mode + #sectors 0 do + ." sector " i .d + i sector>offset ." offset = " 8 u.r + i sector>size ." size = " 8 u.r + i sector>offset 2 + fc@ if ." protected" else ." unprotected" then + cr + loop + read-mode +; +: ?partial-protected ( offset len -- ) + 2dup + /flash > if + collect( + ." Image is too big." cr + )collect alert + abort + then + ['] (?programmable) catch if 2drop abort then + autoselect-mode + offset+len>sectors ?do + i sector>offset 2 + fc@ if + read-mode + collect( + ." Cannot program flash." cr + ." Sector " i .d ." is protected." cr + )collect alert + abort + then + loop + read-mode +; + +: clear-status ( -- ) f0 flashmode ; +\ wait until done, check for errors +: data-poll ( n a -- hung? ) + begin + 2dup fc@ xor h# 80 and while ( n a ) \ busy? + dup fc@ h# 20 and if ( n a ) \ error? + fc@ xor h# 80 and abort" write failed " \ abort on still busy + exit \ okay + then + repeat 2drop +; + +: sector-erase ( sector -- ) + enable-flash-writes + unlock-write h# 80 flashmode \ setup + unlock-write dup sector>offset h# 30 over fctl! + swap sector>size + 1- h# ff swap ['] data-poll catch drop + read-mode +; +' sector-erase to flash-erase-block + +: sector-erase-suspend ( -- ) b0 addr0 fctl! ; +: sector-erase-resume ( -- ) 30 addr0 fctl! ; +: partial-erase ( offset len -- ) + offset+len>sectors ?do i sector-erase loop +; +: chip-erase ( -- ) + enable-flash-writes + unlock-write h# 80 flashmode \ setup + unlock-write h# 10 flashmode \ chip erase + h# ff /flash 1- ['] data-poll catch drop + read-mode +; +\ ' chip-erase to erase-flash + +: write-byte ( n a -- ) + 2dup unlock-write h# a0 flashmode + fdata! + ['] data-poll catch if clear-status then +; +: (flash-write) ( source-address length dest-offset -- ) + rot 0 ?do over i + c@ over i + write-byte loop ( src dst ) + 2drop read-mode +; +' (flash-write) to flash-write + +: (flash-verify) ( source-address length dest-offset -- ) + rot 0 ?do ( src dst ) + over i + c@ over i + fc@ <> if ( src dst ) + ." Verify failed. At " dup i + dup . ." got " fc@ . + ." expected " over i + c@ . abort + then ( src dst ) + loop 2drop ( ) +; +' (flash-verify to flash-verify + +: verify-erase ( sector# -- error? ) + dup sector>offset swap sector>size bounds ?do + i fc@ h# ff <> if + ." erase error at " i . ." got " i fc@ . cr + true leave + then + loop false +; +: program-sector ( address length sector -- ) + dup push-decimal 1 .r pop-base ." E" + dup sector-erase ( address length sector ) + dup verify-erase if ( address length sector ) + dup sector-erase dup verify-erase abort" Erase failure" + then ( address length sector ) + dup sector>offset -rot sector>size min ( address sector-addr length' ) + bs emit ." W" + 3dup write-bytes ( address sector-addr length' ) + bs emit ." V" ( address sector-addr length' ) + verify-bytes ( ) + space +; + +0 value start-sector +: (program-flash) ( address length -- ) start-sector sector>offset swap write-bytes ; +' (program-flash) to program-flash