Author: wmb Date: 2007-05-04 11:00:05 +0200 (Fri, 04 May 2007) New Revision: 355
Added: cpu/x86/adpcm.fth cpu/x86/k6cputest.fth Modified: cpu/x86/pc/olpc/devices.fth cpu/x86/pc/olpc/disptest.fth cpu/x86/pc/olpc/olpc.bth dev/geode/ac97/ac97.fth dev/geode/ac97/selftest.fth dev/olpc/cafenand/methods.fth dev/olpc/cafenand/selftest.fth Log: OLPC - Added a bunch of selftests from Lilian.
Added: cpu/x86/adpcm.fth =================================================================== --- cpu/x86/adpcm.fth (rev 0) +++ cpu/x86/adpcm.fth 2007-05-04 09:00:05 UTC (rev 355) @@ -0,0 +1,223 @@ +\ See license at end of file +purpose: decode IMA/DVI ADPCM .wav file + +\ Uncompressed data format: +\ 16-bit Left, 16-bit Right, ... +\ +\ Compressed data format: +\ nibbles 0.hi 0.lo 1.hi 1.lo 2.hi 2.lo 3.hi 3.lo 4.hi 4.lo 5.hi 5.lo ... +\ L1 L0 L3 L2 L5 L4 L7 L6 R1 R0 R3 R2 ... + +\ Work on one channel at a time. + +0 value val-pred \ predicted value +0 value index \ current step change index +0 value in-val \ place to keep (encoded) input value +0 value in-skip \ # bytes to skip on channel input +0 value out-skip \ # bytes to skip on channel output +0 value buf-skip \ toggle flag for writing values + +0 value #ch \ # channels +0 value blk-size \ # bytes per compressed block +0 value #sample/blk \ (blk-size-(#ch*4)) + 1 + +decimal +create index-table -1 , -1 , -1 , -1 , 2 , 4 , 6 , 8 , + -1 , -1 , -1 , -1 , 2 , 4 , 6 , 8 , + +create stepsize-table \ 89 entries + 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 16 , 17 , + 19 , 21 , 23 , 25 , 28 , 31 , 34 , 37 , 41 , 45 , + 50 , 55 , 60 , 66 , 73 , 80 , 88 , 97 , 107 , 118 , + 130 , 143 , 157 , 173 , 190 , 209 , 230 , 253 , 279 , 307 , + 337 , 371 , 408 , 449 , 494 , 544 , 598 , 658 , 724 , 796 , + 876 , 963 , 1060 , 1166 , 1282 , 1411 , 1552 , 1707 , 1878 , 2066 , + 2272 , 2499 , 2749 , 3024 , 3327 , 3660 , 4026 , 4428 , 4871 , 5358 , + 5894 , 6484 , 7132 , 7845 , 8630 , 9493 , 10442 , 11487 , 12635 , 13899 , + 15289 , 16818 , 18500 , 20350 , 22385 , 24623 , 27086 , 29794 , 32767 , +hex + +0 value 'index-table +0 value 'stepsize-table + +: init-ch-vars ( in out -- in' out' ) + over <w@ dup to val-pred \ The first entry is the initial value + over w! + over 2 + c@ to index \ And the initial index + out-skip + + swap in-skip + swap +; + +code adpcm-decode-sample ( in out sample# -- in' out' ) + \ Get the delta value + eax pop ( in out ) + 7 # eax and 0= if + 4 [esp] ecx mov \ Read the next 4 bytes + 0 [ecx] ebx mov + 'user in-skip ecx mov \ Increment in to the next data for the channel + ecx 4 [esp] add + else + 'user in-val ebx mov + ebx 4 # shr + then + ebx 'user in-val mov \ Save the input data + h# f # ebx and \ delta + + \ Compute difference and new predicated value + \ Computes 'vpdiff = (delta+0.5)*step/4', but see comment in adpcm-coder. + 'user index eax mov \ index + 'user 'stepsize-table ecx mov \ address of stepsize-table + 0 [ecx] [eax] *4 ecx mov \ step = stepsize-table[index] + + ecx eax mov eax 3 # shr \ vpdiff + + 4 # bl test 0<> if ecx eax add then + 2 # bl test 0<> if ecx edx mov edx 1 # shr edx eax add then + 1 # bl test 0<> if ecx edx mov edx 2 # shr edx eax add then + + \ Clamp down output value + 'user val-pred edx mov + 8 # ebx test 0= if + eax edx add + else + eax edx sub + then + d# 32767 # edx cmp > if d# 32767 # edx mov then + d# -32768 # edx cmp < if d# -32768 # edx mov then + edx 'user val-pred mov \ Update valpred + 0 [esp] eax mov \ out + op: dx 0 [eax] mov \ [out] = valpred + 'user out-skip eax mov + eax 0 [esp] add \ Advance out pointer + + \ Update index value + 'user 'index-table eax mov \ address of index-table + 0 [eax] [ebx] *4 eax mov \ index-table[delta] + + 'user index eax add \ index+index-table[delta] + 0 # eax cmp < if eax eax xor then + d# 88 # eax cmp > if d# 88 # eax mov then + eax 'user index mov \ Update index +c; + +: adpcm-decode-ch ( in out #sample -- ) + 0 ?do + i adpcm-decode-sample ( in' out' ) + loop 2drop +; + +: adpcm-decode-blk ( in out #sample -- ) + #ch 0 ?do ( in out #sample ) + 2 pick i /l * + ( in out #sample in' ) + 2 pick i /w * + ( in out #sample in out' ) + init-ch-vars ( in out #sample in' out' ) + 2 pick 1- ( in out #sample in out #sample-1 ) + adpcm-decode-ch ( in out #sample ) + loop 3drop ( ) +; + +: adpcm-decoder ( in out #sample #ch blk-size -- ) + index-table to 'index-table + stepsize-table to 'stepsize-table + + dup to blk-size ( in out #sample #ch blk-size ) + over 4 * - 1+ to #sample/blk ( in out #sample #ch ) + dup to #ch ( in out #sample #ch ) + dup /l * to in-skip ( in out #sample #ch ) + /w * to out-skip ( in out #sample ) + + begin dup 0> while ( in out #sample ) + 3dup #sample/blk min adpcm-decode-blk + rot blk-size + ( out #sample in' ) + rot #sample/blk #ch * wa+ ( #sample in out' ) + rot #sample/blk - ( in out #sample' ) + repeat 3drop +; + +\ Decode an .wav file +\ +\ .wav file format: +\ "RIFF" L<len of file> "WAVE" +\ "fmt " L<len of fmt data> W<compression code> W<#channels> L<sample rate> +\ L<bytes/second>] W<block align> W<bits/sample> W<extra bytes> +\ W<#samples/block>] +\ "fact" L<len of fact> L<#samples> +\ "data" L<len of data> <blocks of data> +\ +\ Each <block of data> contains: +\ W<sample> B<index> B<0> per channel +\ (block size - 1) samples of compressed data + +: find-wav-chunk? ( in chunk$ -- in' true | false ) + rot dup 4 + le-l@ over + swap h# c + ( chunk$ in-end in' ) + begin 2dup u> while ( chunk$ in-end in ) + dup 4 pick 4 pick comp 0= if ( chunk$ in-end in ) + nip nip nip true exit ( in true ) + then + 4 + dup le-l@ + 4 + ( chunk$ in-end in' ) + repeat 4drop + false +; + +: wav-ok? ( in -- ok? ) + dup " RIFF" comp swap 8 + " WAVE" comp or 0= +; + +: fmt-ok? ( in -- #ch blk-size true | false ) + " fmt " find-wav-chunk? 0= if false exit then ( in' ) + dup 8 + le-w@ h# 11 = \ compression code: DVI_ADPCM + over h# 16 + le-w@ 4 = and if \ bits/sample + dup h# a + le-w@ ( #ch ) + swap h# 14 + le-w@ true ( #ch blk-size true ) + else + drop false ( false ) + then +; + +: fact-ok? ( in -- #sample true | false ) + " fact" find-wav-chunk? dup if swap 8 + le-l@ swap then +; + +: data-ok? ( in -- in' true | false ) + " data" find-wav-chunk? dup if swap 8 + swap then +; + +: adpcm-decode ( in out -- actual ) + over wav-ok? not if 2drop 0 exit then ( in out ) + swap dup data-ok? not if 2drop 0 exit then ( out in in' ) + -rot dup fact-ok? not if 3drop 0 exit then ( in' out in #sample ) + swap fmt-ok? not if 3drop 0 exit then ( in' out #sample #ch blk-size ) + 2 pick 2 pick /w * * >r ( in' out #sample #ch blk-size ) ( R: actual ) + adpcm-decoder r> ( actual ) +; + +: adpcm-size ( in -- actual ) + dup wav-ok? not if drop 0 exit then ( in ) + dup fact-ok? not if drop 0 exit then ( in #sample ) + swap fmt-ok? not if drop 0 exit then ( #sample #ch blk-size ) + drop /w * * ( actual ) +; + +\ LICENSE_BEGIN +\ Copyright (c) 2007 FirmWorks +\ +\ Permission is hereby granted, free of charge, to any person obtaining +\ a copy of this software and associated documentation files (the +\ "Software"), to deal in the Software without restriction, including +\ without limitation the rights to use, copy, modify, merge, publish, +\ distribute, sublicense, and/or sell copies of the Software, and to +\ permit persons to whom the Software is furnished to do so, subject to +\ the following conditions: +\ +\ The above copyright notice and this permission notice shall be +\ included in all copies or substantial portions of the Software. +\ +\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +\ +\ LICENSE_END
Property changes on: cpu/x86/adpcm.fth ___________________________________________________________________ Name: svn:executable + *
Added: cpu/x86/k6cputest.fth =================================================================== --- cpu/x86/k6cputest.fth (rev 0) +++ cpu/x86/k6cputest.fth 2007-05-04 09:00:05 UTC (rev 355) @@ -0,0 +1,116 @@ +purpose: Burnin diagnostic for AMD K6 and similar CPUs +\ See license at end of file + +hex + +also assembler definitions +: finit ( -- ) 9b asm8, db asm8, e3 asm8, ; +: fldpi ( -- ) d9 asm8, eb asm8, ; +: fldl ( disp mr rmid -- ) dd asm8, 0 mem, ; +: fmull ( disp mr rmid -- ) dc asm8, 1 mem, ; +: faddp ( -- ) de asm8, c1 asm8, ; +: fsubp ( -- ) de asm8, e1 asm8, ; +: fcompp ( -- ) de asm8, d9 asm8, ; +: fstswax ( -- ) 9b asm8, df asm8, e0 asm8, ; + +\ Returns an addressing mode that refers to the end of the datum +: 'user+8 ( -- offset reg ) 'user swap 8 + swap ; + +previous definitions + + +dev /cpu + +d# 60 constant default#passes +d# 10,000,000 constant spins/pass +0 value #cnt +7fff.ffff value #half +0000.0000 value #half2 +ffff.ffff 3fdf.ffff 2value #e +ffff.ffff 3fef.ffff 2value #rt + +code burnK6 ( count -- error? ) + ecx pop \ Loop count + + finit + esi push + + 'user #half edx mov \ DX: '#half + eax eax xor \ AX: 0 + eax ebx mov \ BX: 0 + -1 [eax] esi lea \ Index = -1 + fldpi + nop nop + + begin + 'user+8 #rt [esi] *8 fldl \ Account for -1 index + 'user+8 #e [esi] *8 fmull + 'user+8 #half [esi] *8 edx add + 75 c, 0 c, \ jnz .+2 + faddp + 'user+8 #rt [esi] *8 fldl + ebx dec + 'user+8 #half [esi] *8 edx sub + eb c, 0 c, \ jmp .+2 + 'user+8 #e [esi] *8 fmull + ebx inc + 'user+8 #cnt [esi] *8 dec + fsubp + loopa + + esi pop + + ebx ebx test 0<> if 1 # ebx mov then + 'user #half edx cmp <> if 2 # ebx or then + fldpi + fcompp \ compare ST(0) and ST(1) and pop them + fstswax + sahf 0<> if 4 # ebx or then + + ebx push +c; + +: selftest ( -- error? ) + my-args dup if + push-decimal + $number abort" Argument to /cpu selftest must be a decimal number" + pop-base + else + 2drop + default#passes + then + + dup .d ." passes of CPU Burnin. Press a key to abort." cr + 0 ?do + (cr ." Pass " i .d + spins/pass burnk6 if true exit then + key? if key drop cr leave then + loop + false +; + +device-end + +\ LICENSE_BEGIN +\ Copyright (c) 2007 FirmWorks +\ +\ Permission is hereby granted, free of charge, to any person obtaining +\ a copy of this software and associated documentation files (the +\ "Software"), to deal in the Software without restriction, including +\ without limitation the rights to use, copy, modify, merge, publish, +\ distribute, sublicense, and/or sell copies of the Software, and to +\ permit persons to whom the Software is furnished to do so, subject to +\ the following conditions: +\ +\ The above copyright notice and this permission notice shall be +\ included in all copies or substantial portions of the Software. +\ +\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +\ +\ LICENSE_END
Property changes on: cpu/x86/k6cputest.fth ___________________________________________________________________ Name: svn:executable + *
Modified: cpu/x86/pc/olpc/devices.fth =================================================================== --- cpu/x86/pc/olpc/devices.fth 2007-05-04 07:29:47 UTC (rev 354) +++ cpu/x86/pc/olpc/devices.fth 2007-05-04 09:00:05 UTC (rev 355) @@ -123,6 +123,7 @@ ;
fload ${BP}/cpu/x86/pc/cpunode.fth +fload ${BP}/cpu/x86/k6cputest.fth \ Burnin test for K6 CPU
0 [if] fload ${BP}/ofw/console/bailout.fth @@ -306,6 +307,8 @@
fload ${BP}/dev/geode/acpi.fth \ Power management
+fload ${BP}/cpu/x86/adpcm.fth \ ADPCM decoding + [ifdef] notdef-olpc \ fload ${BP}/dev/olpc/plccflash.fth \ PLCC LPC debug FLASH
Modified: cpu/x86/pc/olpc/disptest.fth =================================================================== --- cpu/x86/pc/olpc/disptest.fth 2007-05-04 07:29:47 UTC (rev 354) +++ cpu/x86/pc/olpc/disptest.fth 2007-05-04 09:00:05 UTC (rev 355) @@ -1,3 +1,6 @@ +purpose: Display test +\ See license at end of file + dev /display
d# 100 constant bar-int @@ -21,14 +24,80 @@ i test-color16 i 0 bar-int 4 pick " fill-rectangle" $call-screen bar-int +loop drop ; + +instance variable rn \ Random number +d# 60,000 constant burnin-time \ 1 minute + +: random ( -- n ) + rn @ d# 1103515245 * d# 12345 + h# 7FFFFFFF and dup rn ! +; + +: randomize-color ( -- c ) + random h# 1f and d# 11 << + random h# 3f and d# 5 << or + random h# 1f and or +; +: randomize-xy ( -- x y ) + dimensions ( width height ) + random 3ff and min swap ( y width ) + random 7ff and min swap ( x y ) +; +: randomize-wh ( x y -- w h ) + dimensions ( x y width height ) + rot - -rot ( max-h x width ) + swap - swap ( max-w max-h ) + randomize-xy ( max-w max-h w h ) + rot min -rot min swap ( w' h' ) +; +: .random-rect ( -- ) + randomize-color ( c ) + randomize-xy ( c x y ) + 2dup randomize-wh ( c x y w h ) + " fill-rectangle" $call-screen ( ) +; + +: random-selftest ( -- error? ) + get-msecs rn ! + get-msecs burnin-time + + begin get-msecs over u< key? not and while + .random-rect + repeat +; + : selftest ( -- error? ) bytes/pixel 2 <> if false exit then .horizontal-bars16 d# 2000 ms .vertical-bars16 d# 2000 ms + ." Press a key to abort." cr + d# 1000 ms + random-selftest false ;
device-end
+\ LICENSE_BEGIN +\ Copyright (c) 2007 FirmWorks +\ +\ Permission is hereby granted, free of charge, to any person obtaining +\ a copy of this software and associated documentation files (the +\ "Software"), to deal in the Software without restriction, including +\ without limitation the rights to use, copy, modify, merge, publish, +\ distribute, sublicense, and/or sell copies of the Software, and to +\ permit persons to whom the Software is furnished to do so, subject to +\ the following conditions: +\ +\ The above copyright notice and this permission notice shall be +\ included in all copies or substantial portions of the Software. +\ +\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +\ +\ LICENSE_END
Modified: cpu/x86/pc/olpc/olpc.bth =================================================================== --- cpu/x86/pc/olpc/olpc.bth 2007-05-04 07:29:47 UTC (rev 354) +++ cpu/x86/pc/olpc/olpc.bth 2007-05-04 09:00:05 UTC (rev 355) @@ -72,7 +72,8 @@ " sourceurl" " sourceurl" $add-dropin
[ifndef] lx-devel - " ${BP}/clients/memtest86/memtest" " memtest" $add-deflated-dropin + " ${BP}/clients/memtest86/memtest" " memtest" $add-deflated-dropin + " ${BP}/cpu/x86/pc/olpc/images/olpc-t0.wav" " splash" $add-deflated-dropin [then] [ifdef] lx-devel " ${BP}/dev/pci/build/pcibridg.fc" " class060400" $add-deflated-dropin
Modified: dev/geode/ac97/ac97.fth =================================================================== --- dev/geode/ac97/ac97.fth 2007-05-04 07:29:47 UTC (rev 354) +++ dev/geode/ac97/ac97.fth 2007-05-04 09:00:05 UTC (rev 355) @@ -295,8 +295,9 @@ prd-out-phys false out-channel start-dma ( len ) ;
+: open-args ( -- arg$ ) my-args ascii : left-parse-string 2swap 2drop ; : parse-args ( -- flag ) - my-args begin dup while \ Execute mode modifiers + open-args begin dup while \ Execute mode modifiers ascii , left-parse-string ( rem$ first$ ) my-self ['] $call-method catch if ( rem$ x x x ) ." Unknown argument" cr
Modified: dev/geode/ac97/selftest.fth =================================================================== --- dev/geode/ac97/selftest.fth 2007-05-04 07:29:47 UTC (rev 354) +++ dev/geode/ac97/selftest.fth 2007-05-04 09:00:05 UTC (rev 355) @@ -35,7 +35,6 @@ negate 1+ 2* 3 / dup bwjoin to glevel ;
- : play ( -- ) open-out plevel set-pcm-gain glevel h# 38 codec! record-base record-len audio-out drop write-done @@ -93,30 +92,70 @@ ;
: make-wave ( -- ) - record-base record-len 2/ bounds ( endadr startadr ) - begin 2dup u> while cycle repeat ( endadr startadr ) - 2drop + record-base record-len 2/ bounds ( endadr startadr ) + begin 2dup u> while cycle repeat ( endadr startadr ) + 2drop
- record-base record-len bounds ( endadr startadr ) - record-len 2/ + wa1+ - begin 2dup u> while cycle repeat ( endadr startadr ) - 2drop + record-base record-len bounds ( endadr startadr ) + record-len 2/ + wa1+ + begin 2dup u> while cycle repeat ( endadr startadr ) + 2drop ; + +0 value raw-buf +0 value /raw-buf + +: selftest-args ( -- arg$ ) my-args ascii : left-parse-string 2drop ; + +: ?play-wav-file ( -- ) + selftest-args dup 0= if drop exit then + + \ Read the .wav file + 2dup ." Play " type cr + " boot-read" evaluate + + \ Allocate raw audio buffer + " loaded" evaluate 0= if drop exit then \ No data loaded + " adpcm-size" evaluate ( /raw-buf ) + ?dup 0= if exit then \ Not an IMA ADPCM .wav file + dup to /raw-buf alloc-mem to raw-buf ( ) + + \ Decode the .wav file + " load-base" evaluate ( in ) + raw-buf " adpcm-decode" evaluate ( /raw-buf ) ( R: len wav-buf ) + ?dup 0= if exit then \ Not an IMA ADPCM .wav file + + \ Play the raw audio data + ." Press a key to abort" cr + open-out plevel set-pcm-gain glevel h# 38 codec! + begin + raw-buf /raw-buf audio-out drop + key? until write-done + key drop + + \ Release the raw audio buffer + raw-buf /raw-buf free-mem 0 to raw-buf 0 to /raw-buf +; + : selftest ( -- error? ) open 0= if ." Failed to open /audio" cr true exit then + 0 set-plevel 0 set-glevel + ?play-wav-file record-len alloc-mem to record-base ." Play tone" cr 0 set-plevel d# -12 set-glevel make-wave play - ." Record and playback" cr + ." Recording ..." cr 0 set-plevel 0 set-glevel - record play + record + ." Playing ..." cr + play record-base record-len free-mem close false ;
\ LICENSE_BEGIN -\ Copyright (c) 2006 FirmWorks +\ Copyright (c) 2007 FirmWorks \ \ Permission is hereby granted, free of charge, to any person obtaining \ a copy of this software and associated documentation files (the
Modified: dev/olpc/cafenand/methods.fth =================================================================== --- dev/olpc/cafenand/methods.fth 2007-05-04 07:29:47 UTC (rev 354) +++ dev/olpc/cafenand/methods.fth 2007-05-04 09:00:05 UTC (rev 355) @@ -24,6 +24,8 @@ total-pages 0= \ Error if there are no chips ;
+: open-args ( -- arg$ ) my-args ascii : left-parse-string 2swap 2drop ; + external
: dma-alloc ( len -- adr ) " dma-alloc" $call-parent ; @@ -62,7 +64,7 @@
get-bbt
- my-args dup if ( arg$ ) + open-args dup if ( arg$ ) ascii , left-parse-string ( arg2$ arg1$ ) 2dup " zip" $= if ( arg2$ arg1$ ) 2drop ( arg2$ )
Modified: dev/olpc/cafenand/selftest.fth =================================================================== --- dev/olpc/cafenand/selftest.fth 2007-05-04 07:29:47 UTC (rev 354) +++ dev/olpc/cafenand/selftest.fth 2007-05-04 09:00:05 UTC (rev 355) @@ -1,11 +1,18 @@ \ See license at end of file purpose: Selftest for NAND FLASH section of the OLPC CaFe chip
-0 value test-block# -0 value sbuf \ Original content of block -0 value obuf \ Block data written -0 value ibuf \ Block data read -: test-page# ( -- n ) test-block# pages/eblock * ; +instance variable rn \ Random number + +: random ( -- n ) + rn @ d# 1103515245 * d# 12345 + h# 7FFFFFFF and dup rn ! +; + +false value selftest-err? +: record-err ( error? -- ) if true to selftest-err? then ; + +0 value sbuf \ Original content of block +0 value obuf \ Block data written +0 value ibuf \ Block data read : alloc-test-bufs ( -- ) sbuf 0= if erase-size alloc-mem to sbuf @@ -20,40 +27,164 @@ ibuf erase-size free-mem 0 to ibuf then ; -: determine-test-block# ( -- error? ) - -1 to test-block# - size erase-size um/mod nip 1- ( block# ) - begin dup 0> test-block# -1 = and while - dup pages/eblock * block-bad? not if dup to test-block# then - 1- ( block#' ) - repeat drop - test-block# -1 = +: read-eblock ( adr page# -- error? ) + pages/eblock read-blocks pages/eblock <> ; -: read-eblock ( adr -- error? ) - test-page# pages/eblock read-blocks pages/eblock <> +: write-eblock ( adr page# -- error? ) + dup erase-block + pages/eblock write-blocks pages/eblock <> ; -: write-eblock ( adr -- error? ) - test-page# erase-block - test-page# pages/eblock write-blocks pages/eblock <> -; -: test-eblock ( pattern -- error? ) - obuf erase-size 2 pick fill obuf write-eblock if true exit then - ibuf erase-size rot invert fill ibuf read-eblock if true exit then +: test-eblock ( page# pattern -- error? ) + obuf erase-size 2 pick fill + ibuf erase-size rot invert fill + obuf over write-eblock if true exit then + ibuf swap read-eblock if true exit then ibuf obuf erase-size comp ; -: write-test ( -- error? ) - determine-test-block# if true exit then + +\ Destroy content of flash. No argument. +: erase ( subarg$ -- ) 2drop ." Erasing..." cr wipe ; + +\ Destroy content of flash. Argument is hex byte pattern value. +: .skip-bad ( page# -- ) cr ." Skipping bad block" .page-byte cr ; +: fill ( subarg$ -- ) + $number if 0 else 0 max h# ff min then + ." Fill nandflash with h# " dup u. cr + + usable-page-limit 0 ?do + i block-bad? if + i .skip-bad + else + (cr i . i over test-eblock record-err + then + pages/eblock +loop drop +; + +\ Non-destructive. Argument is number of blocks to test. +: random-page ( -- n ) random total-pages 1- and usable-page-limit min ; +: fast ( subarg$ -- ) + $number if d# 10 else 0 max usable-page-limit pages/eblock / min then + ." Fill " dup .d ." random blocks with h# 55, h# aa and h# ff" cr + + 0 ?do + i 1 > if random-page else i 0<> if usable-page-limit 1- else 0 then then + pages/eblock 1- invert and + + dup block-bad? not if + (cr dup . + sbuf over read-eblock dup record-err 0= if + dup h# 55 test-eblock record-err + dup h# aa test-eblock record-err + dup h# ff test-eblock record-err + then + sbuf swap write-eblock record-err + then + loop +; + +\ Non-destructive. Argument is <#blk>,<blk#> +\ <#blk>+1 is number of blocks as a test unit +\ If <#blk> is absent, all blocks are tested. +\ <blk#> is the block to test in the test unit, in range of 0..<#blk> +\ If <blk#> is absent, 0 is assumed. +\ For example: test /nandflash::full test all blocks +\ test /nandflash::full,1,0 test even blocks +\ test /nandflash::full,1,1 test odd blocks +\ test /nandflash::full,2,<0-2> test 33% +\ test /nandflash::full,3,<0-3> test 25% +\ test /nandflash::full,4,<0-4> test 20% +\ test /nandflash::full,9,<0-9> test 10% +: parse-full-args ( subarg$ -- #blk blk# ) + ?dup 0= if drop 0 0 exit then + ascii , left-parse-string ( blk#$ #blk$ ) + $number if 2drop 0 0 exit then ( blk#$ #blk ) + 0 max usable-page-limit pages/eblock 1- / min + -rot $number if 0 else 0 max over min then ( #blk blk# ) +; +: .full-arg ( #blk blk# -- ) + ." Test " + over 0= if 2drop ." every block" cr exit then + ." block " u. ." every " 1+ u. ." blocks" cr +; +: full ( subarg$ -- ) + parse-full-args ( #blk blk# ) + 2dup .full-arg ( #blk blk# ) + + pages/eblock * swap 1+ pages/eblock * ( page# #page ) + usable-page-limit rot ?do ( #blk+1 ) + i block-bad? not if + (cr i . + sbuf i read-eblock dup record-err 0= if + i h# 55 test-eblock record-err + i h# aa test-eblock record-err + then + sbuf i write-eblock record-err + then + dup +loop drop +; + +: none ( subarg$ -- ) 2drop exit ; + +: help ( subarg$ -- ) + 2drop + ." Usage:" cr + ." test /nandflash[::<arg>[;<arg>[;<arg>...]]]" cr + cr + ." If no <arg> is present, the fast test is performed." cr + cr + ." <arg> can be one of the following:" cr + ." none to do nothing" cr + ." help to get this usage guide" cr + ." erase to erase the flash (destructive)" cr + ." fill[,<data>] to fill the flash with hex byte pattern <data> (destructive)" cr + ." Default <data> is 00" cr + ." fast[,<#blk>] to non-destructively test the specified <#blk> of flash" cr + ." Default <#blk> is decimal 10" cr + ." full[,<#blk>[,<blk#>]" cr + ." to non-destructively test the specified <blk#> every" cr + ." <#blk>+1 number of blocks" cr + ." Default <#blk> and <blk#> are 0" cr + ." E.g., full,1,0 test even blocks" cr + ." full,1,1 test odd blocks" cr + ." full,2,0 test 33% of the flash" cr + cr +; + +: parse-selftest-args ( arg$ -- ) + begin ( arg$ ) + ascii ; left-parse-string ?dup if ( rem$ arg$' ) + ascii , left-parse-string ( rem$ subarg$ method$ ) + my-self ['] $call-method catch if ( rem$ x x x x x ) + ." Unknown argument" cr + 3drop 2drop 2drop + true to selftest-err? + exit + then ( rem$ ) + else + drop ( rem$ ) + then + ?dup 0= until drop ( ) +; +: selftest-args ( -- arg$ ) my-args ascii : left-parse-string 2drop ; + +: (selftest) ( -- error? ) + false to selftest-err? alloc-test-bufs - sbuf read-eblock if free-test-bufs true exit then - h# 5a test-eblock if free-test-bufs true exit then - h# a5 test-eblock if free-test-bufs true exit then - sbuf write-eblock \ Restore original content + selftest-args ?dup if + parse-selftest-args + else + drop " " fast + then free-test-bufs + selftest-err? ; + : selftest ( -- error? ) open 0= if true exit then - show-bbt - write-test + get-msecs rn ! + read-id 1+ c@ h# dc <> if close true exit then + show-bbt cr + (selftest) close ;