blob: 80dbfcd11b3f727d699e768f552296d099da8ded [file] [log] [blame]
#!/usr/bin/python
# Copyright 2012 Google Inc. All Rights Reserved.
#
"""A tool for a burnin Flash test."""
__author__ = 'dgentry@google.com (Denton Gentry)'
import os
import os.path
import subprocess
import sys
import time
import options
import py_mtd
try:
import monotime # pylint: disable=unused-import,g-import-not-at-top
except ImportError:
pass
try:
gettime = time.monotonic
except AttributeError:
gettime = time.time
optspec = """
burnin-flash [options...] /path/to/write/to
--
m,mtd= /dev/mtd# to check for errors.
p,print-interval= Seconds between printouts [10]
r,runtime= Number of seconds to run the test [60]
"""
def main():
o = options.Options(optspec)
(opt, flags, extra) = o.parse(sys.argv[1:]) # pylint: disable=W0612
if not opt.mtd:
o.fatal('an mtd argument is required')
if len(extra) != 1:
o.fatal('exactly one path expected')
filename = extra[0]
if os.path.isdir(filename):
filename = os.path.join(filename, 'burnin.tmp')
f = open(filename, 'w+')
# we still have the file open; this will ensure it gets deleted upon
# process exit.
os.unlink(filename)
start_time = now = last_print_time = gettime()
nbytes = 0
start_ecc = py_mtd.eccstats(opt.mtd)
while now - start_time < opt.runtime:
try:
# strongly random data so as to not compress well.
dsiz = 1048576
randdata = subprocess.check_output(['randomdata', '0', str(dsiz)])
# write random data to flash
f.seek(0, os.SEEK_SET)
f.write(randdata)
f.flush()
os.fsync(f.fileno())
# read back, to notice ECC errors.
open('/proc/sys/vm/drop_caches', 'w+').write('3')
f.seek(0, os.SEEK_SET)
readback = f.read(dsiz)
if readback != randdata:
sys.stderr.write('Read back from %s != written\n' % filename)
return 2
nbytes += dsiz
except (OSError, IOError) as e:
sys.stderr.write('%s write: %s\n' % (filename, e))
return 2
now = gettime()
if opt.print_interval and now - last_print_time > opt.print_interval:
print ('%-15s %7.2fM in %5.2fs = %6.2fM/s'
% (filename + ':',
nbytes / 1024. / 1024.,
now - last_print_time,
nbytes / 1024. / 1024. / (now - last_print_time)))
sys.stdout.flush()
last_print_time = now
nbytes = 0
ecc = py_mtd.eccstats(opt.mtd)
# Ignore ecc.corrected, they are uncommon but normal.
print '%s: Corrected ECC error = %d' % (opt.mtd, ecc.corrected)
if ecc.failed != start_ecc.failed:
print('%s: Uncorrectable ECC error during test, %d != %d' %
(opt.mtd, ecc.failed, start_ecc.failed))
return 2
if ecc.badblocks != start_ecc.badblocks:
print('%s: bad blocks developed during test, %d != %d' %
(opt.mtd, ecc.badblocks, start_ecc.badblocks))
return 2
if ecc.bbtblocks != start_ecc.bbtblocks:
print('%s: bad block table error during test, %d != %d' %
(opt.mtd, ecc.bbtblocks, start_ecc.bbtblocks))
return 2
return 0
if __name__ == '__main__':
rc = main()
sys.exit(rc)