在特殊场景下,需要对NAND的整个分区进行擦除和写入特殊数据。由于NAND的特性是有坏块,如果直接通过open("/dev/mtd0")设备节点对怀块进行擦除读写时则会出现意想不到的的错误。为了解决这个问题,参考了mtd-uitle的源码。具体执行以下步骤:
1.先umount 分区,例如 umount /opt/ ;(假设mtd分区挂载在/opt目录)
2.使用open("/dev/mtd0")打开设备节点;通过ioctl()函数进行操作。具体如下
1)使用ioctl(fd, MEMGETINFO, &meminfo));获取mtd分区信息 ,具有分区大小,块大小等信息;
2)在擦除前使用ioctl(fd, MEMGETBADBLOCK, &test_ofs)函数是否是坏块,如果是坏块则跳过该坏块,继续判断下一个块;
3)如果该块不是坏块则对该块进行擦除,ioctl(fd, MEMERASE, &er);
4)擦除后可以对该块进行写操作,pwrite(fd, data, meminfo.erasesize, ofs);
全部源码:
#define PROGRAM_NAME "nandtest"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <getopt.h>
#include <asm/types.h>
#include "mtd/mtd-user.h"
#include "common.h"
static NORETURN void usage(int status)
{
fprintf(status ? stderr : stdout,
"usage: %s [OPTIONS] <device>\n\n"
" -h, --help Display this help output\n"
" -V, --version Display version information and exit\n"
" -m, --markbad Mark blocks bad if they appear so\n"
" -s, --seed Supply random seed\n"
" -p, --passes Number of passes\n"
" -r <n>, --reads=<n> Read & check <n> times per pass\n"
" -o, --offset Start offset on flash\n"
" -l, --length Length of flash to test\n"
" -k, --keep Restore existing contents after test\n",
PROGRAM_NAME);
exit(status);
}
struct mtd_info_user meminfo;
struct mtd_ecc_stats oldstats, newstats;
int fd;
int markbad=0;
int seed;
static int read_and_compare(loff_t ofs, unsigned char *data,
unsigned char *rbuf)
{
ssize_t len;
int i;
len = pread(fd, rbuf, meminfo.erasesize, ofs);
if (len < meminfo.erasesize) {
printf("\n");
if (len)
fprintf(stderr, "Short read (%zd bytes)\n", len);
else
perror("read");
exit(1);
}
if (ioctl(fd, ECCGETSTATS, &newstats)) {
printf("\n");
perror("ECCGETSTATS");
close(fd);
exit(1);
}
if (newstats.corrected > oldstats.corrected) {
printf("\n %d bit(s) ECC corrected at %08x\n",
&n