嵌入式linux下关于flash的一些操作

目录

获取flash类型

读写flash

nand

判断nand是否有怀快


获取flash类型

嵌入式开发常用的flash类型有nor和nand

不同flash的擦写方法不同,因此需要对flash的类型进行判断

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <mtd/mtd-abi.h>


static unsigned char get_flash_type(const char *p_dev)
{
	if (NULL == p_dev)
	{
		printf("get null pointer!\n");
		return -1;
	}

	int app_fd = open(p_dev, O_RDWR, 0666);
	if (-1 == app_fd)
	{
		printf("open %s failed:%m\n", p_dev);
		return -1;
	}

	struct mtd_info_user mtd_info;
	if (-1 == ioctl(app_fd, MEMGETINFO, &mtd_info))
	{
		close(app_fd);
		printf("ioctl MEMGETINFO failed!\n");
		return -1;
	}

	close(app_fd);

	return mtd_info.type;
}

int main()
{
	unsigned char flash_type = get_flash_type("/dev/mtd4");
	if (MTD_NANDFLASH == flash_type)
	{
		printf("The flash type if MTD_NANDFLASH, FLASH_APP_NAME\n");
		
	}
	else if (MTD_NORFLASH == flash_type)
	{
		printf("The flash type if MTD_NORFLASH, FLASH_APP_NAME\n");
			
	}
	else
	{
		printf("not support flash type=%d\n", flash_type);
			
	}

	return -1;
}
//boot中fw_printenv中的实现
struct mtd_info_user mtdinfo;
	struct stat st;
	int rc;

	rc = fstat(fd, &st);
	if (rc < 0) {
		fprintf(stderr, "Cannot stat the file %s\n",
			DEVNAME(dev_current));
		return -1;
	}

	if (S_ISCHR(st.st_mode)) { //判断文件是否为字符设备
		rc = ioctl(fd, MEMGETINFO, &mtdinfo);
		if (rc < 0) {
			fprintf(stderr, "Cannot get MTD information for %s\n",
				DEVNAME(dev_current));
			return -1;
		}
		if (mtdinfo.type != MTD_NORFLASH &&
		    mtdinfo.type != MTD_NANDFLASH &&
		    mtdinfo.type != MTD_DATAFLASH &&
		    mtdinfo.type != MTD_UBIVOLUME) {
			fprintf (stderr, "Unsupported flash type %u on %s\n",
				 mtdinfo.type, DEVNAME(dev_current));
			return -1;
		}
	} else {
		memset(&mtdinfo, 0, sizeof(mtdinfo));
		mtdinfo.type = MTD_ABSENT;
	}

读写flash

 nor

static int flash_app_erase(const char *flash_name)
{
	int app_fd = open(flash_name, O_RDWR, 0666);
	if (-1 == app_fd)
	{
		printf("open %s failed:%m\n", flash_name);
		return -1;
	}

	int fs_len = flash_app_len(app_fd);
	if (0 >= fs_len)
	{
		close(app_fd);
		printf("get flash app len failed!\n");
		return -1;
	}

	//获取MTD设备信息
	struct mtd_info_user mtd_info;
	if (-1 == ioctl(app_fd, MEMGETINFO, &mtd_info))
	{
		close(app_fd);
		printf("ioctl MEMGETINFO failed!\n");
		return -1;
	}

	//擦除falsh
	if (-1 == lseek(app_fd, 0, SEEK_SET))
	{
		close(app_fd);
		printf("lseek SEEK_SET failed!\n");
		return -1;
	}

	if (0 != (fs_len % mtd_info.erasesize))
	{
		close(app_fd);
		printf("erasesize=%d  fs_len=%d  fs_len not align!\n", mtd_info.erasesize, fs_len);
		return -1;
	}

	printf("start erase flash:\n");
	uint32 block_cnt = (fs_len / mtd_info.erasesize);
	struct erase_info_user argp;
	for (uint32 i = 0; i < block_cnt; i++)
	{
		//擦除对应块数据
		argp.start = i * mtd_info.erasesize;
		argp.length = mtd_info.erasesize;
		if (-1 == ioctl(app_fd, MEMERASE, &argp))
		{
			close(app_fd);
			printf("ioctl MEMERASE failed!\n");
			return -1;
		}
		fprintf(stderr, ".");
		fflush(stderr);
	}
	printf("\n");
	printf("erase flash size=%d success!\n", fs_len);

	close(app_fd);

	return 0;
}

static int flash_mtd_len(const char * p_mtd_name)
{
	int len = 0;

	if (NULL == p_mtd_name)
	{
		return -1;
	}

	int fd = open(p_mtd_name, O_RDWR, 0666);
	if (fd < 0)
	{
		printf("open %s failed:%m\n", p_mtd_name);
		return -1;
	}

	len = flash_app_len(fd);

	close(fd);
	fd = -1;

	return len;
}

int nor_flash_app_write(const char * p_buf, uint32 buf_len, const char *flash_name)
{
	int ret = 0;

	if (NULL == p_buf || buf_len <= 0)
	{
		printf("p_buf==null or buf_len<=0, check!\n");
		return -1;
	}

	int fs_len = flash_mtd_len(flash_name);
	if (fs_len < 0)
	{
		printf("get flash app len failed!\n");
		return -1;
	}

	if (buf_len > fs_len)
	{
		printf("buf len=%d > flash len=%d, error!\n", buf_len, fs_len);
		return -1;
	}

	/* 擦除整个 app 分区 */
	ret = flash_app_erase(flash_name);
	if (ret < 0)
	{
		printf("erase flash app failed!\n");
		return -1;
	}

	/* 写flash */
	int app_fd = open(flash_name, O_RDWR, 0666);
	if (-1 == app_fd)
	{
		printf("open %s failed:%m\n", flash_name);
		return -1;
	}

	if (-1 == lseek(app_fd, 0, SEEK_SET))
	{
		printf("lseek %s to SEEK_SET failed!\n", flash_name);
		close(app_fd);
		return -1;
	}

	printf("start write image to flash......\n");

	// int w_len = write(app_fd, p_buf, buf_len);
	int w_len = 0;
	int cnt = buf_len / (1024 * 1024);
	int i = 0;
	for (; i < cnt; ++i)
	{
		w_len += write(app_fd, p_buf + i * 1024 * 1024, 1024 * 1024);
		usleep(10000);
	}
	if (buf_len - w_len > 0)
	{
		w_len += write(app_fd, p_buf + w_len, buf_len - w_len);
	}

	close(app_fd);

	if (w_len != buf_len)
	{
		printf("write image to %s failed:%m\n", flash_name);
		return -1;
	}

	printf("write app image to flash done!\n\n");

	return 0;
}

nand

使用flash_eraseall 和 nandwrite进行擦写。如果默认不支持这两个命令,可能是busybox没配置。

使用nandwrite 写时 要加上 -p选项,表示按页写,否则如果文件不是页大小的整数倍,会写不成功。nandwrite  -p  /dev/mtd1  file

判断nand是否有怀快

fd是打开的块设备 比如 /dev/mtd2

/*
 * Test for bad block on NAND, just returns 0 on NOR, on NAND:
 * 0	- block is good
 * > 0	- block is bad
 * < 0	- failed to test
 */
static int flash_bad_block (int fd, uint8_t mtd_type, loff_t *blockstart)
{
	if (mtd_type == MTD_NANDFLASH) {
		int badblock = ioctl (fd, MEMGETBADBLOCK, blockstart);

		if (badblock < 0) {
			perror ("Cannot read bad block mark");
			return badblock;
		}

		if (badblock) {
#ifdef DEBUG
			fprintf (stderr, "Bad block at 0x%llx, "
				 "skipping\n", *blockstart);
#endif
			return badblock;
		}
	}

	return 0;
}

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值