fmql之Linux flash读写

ubuntu在板卡启动后,会占用部分flash的内存。

目前用的是256Mb的flash,型号是w25q256。

数据手册:华邦W25Q256系列flash数据手册

ubuntu系统和启动文件(BOOT.bin等)都放在SD卡。前者放在SD卡的第三个分区,后者放在第一个分区。

现在要进行flash和SD卡的读写测试。

【代码贴到最后了】

flash读写测试

设备名称

首先,要知道板卡中,flash和SD卡分别对应的设备名称。

linux下flash操作命令 • Worktile社区

这样就很清楚了:

  • mtdblock0是flash,大小是32MB (= 256Mb);
  • mmcblk0是SD卡(因为它有三个分区)。

MAJ:MIN是设备的主设备号、次设备号。

【后面才发现,flash读写的设备不能用mtdblock0,而是通过查找/dev/下设备的方式,寻找以mtd开头的设备】

mtd-utils:

嵌入式linux下Flash使用 - 耿通宇 - 博客园

代码测试

接下来就是代码部分: (失败)

Linux下spi读写flash_linux spi flash-CSDN博客

代码中,用的设备是"/dev/mtd4",要把它改成自己对应的flash设备名称。

测试:失败。

驱动代码分析 & 用户驱动代码:

linux块驱动程序分析 之 nand flash 驱动编写过程分析-CSDN博客

https://news.eeworld.com.cn/mcu/ic624239.html

APP代码: (失败)

linux 下对 flash 设备操作的应用程序(嵌入式参考用)_linux 应用层怎么操作flash-CSDN博客

擦除、写入失败。

百度AI给的代码:

flashAPP4.c

cpp 复制代码
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <mtd/mtd-user.h>
#include <string.h>

#define FLASH_DEVICE	"/dev/mtd"	// Flash设备
#define ERASE_SIZE		(256 * 8)			// 擦除块大小

int main() {
	int fd;
	char *data_to_write = "Hello, NOR Flash!";	// 写入的数据
	char *read_buffer;
	struct mtd_info_user mtd_info;
	struct erase_info_user erase_params;
	int result;
	off_t offset = 0; // 假设我们从0字节的位置开始读写

	// 打开Flash设备文件
	fd = open(FLASH_DEVICE, O_RDWR);
	if (fd < 0) {
		perror("Failed to open flash device");
		return -1;
	}

	// 获取Flash信息
	result = ioctl(fd, MEMGETINFO, &mtd_info);
	if (result < 0) {
		perror("Failed to get flash info");
		close(fd);
		return -1;
	}

	// 擦除Flash
	erase_params.start = 0;       // 从0地址开始擦除
	erase_params.length = ERASE_SIZE; // 擦除块大小
	result = ioctl(fd, MEMERASE, &erase_params);
	if (result < 0) {
		perror("Failed to erase flash");
		close(fd);
		return -1;
	} else{
		printf("erase sucessfully\r\n");
	}

	// 写入数据到Flash
	lseek(fd, offset, SEEK_SET); // 设置文件偏移到offset
	result = write(fd, data_to_write, strlen(data_to_write) + 1); // +1是为了包含字符串结尾的null字符
	if (result < 0) {
		perror("Failed to write to flash");
		close(fd);
		return -1;
	} else{
		printf("write sucessfully\r\n");
	}

	// 从Flash读取数据
	lseek(fd, offset, SEEK_SET);
	result = read(fd, read_buffer, sizeof(read_buffer) - 1);
	if (result < 0) {
		perror("Failed to read from flash");
		close(fd);
		return -1;
	}
	read_buffer[result] = '\0'; // 确保字符串结尾有null字符

	// 输出读取的数据
	printf("Read from flash: %s\n", read_buffer);

	// 关闭Flash设备文件
	close(fd);

	return 0;
}

shell命令

shell命令读写擦除flash测试 (应该先做这一步,再写程序)

  • fmql官方给的:
  • 正点原子pdf:
  • 测试:

原来是flash设备名称不对。

代码

修改了flash设备名称后,继续测试:

  • flashAPP4.c 成功
  • flashAPP3.c 成功

贴代码(修正过的):

cpp 复制代码
/***************************************************************
 文件名                 : flashAPP3.c
 作者                   : Skylar
 版本                   : V1.0
 描述                   : flash 读写测试	    w25q256		
 其他                   : /dev/mtd0
 ***************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>

#define FLASH_DEV	"/dev/mtd0"

/* w25q256 */		// 单位是字节
#define FLASH_MAX_SIZE      (32 * 1024 * 1024)		// 256Mb
#define FLASH_PAGE_SIZE     (256)				// 256B
#define FLASH_SECT_SIZE		(16 * 256)			// 4KB
// #define FLASH_BLOCK_SIZE	(32 * 1024)			// 32KB

int main() {
	int fd;
	unsigned char buffer[FLASH_PAGE_SIZE];
	ssize_t bytes_read;
	ssize_t bytes_written;
	off_t offset = 256; // 假设我们从256字节的位置开始读写
	unsigned char erase_buf[4];
	
	// write_data
	int i;
	for(i = 0; i < 256; i++){
		buffer[i] = i + 1;
	}
 
	// 打开NOR Flash设备文件
	fd = open(FLASH_DEV, O_RDWR);
	if (fd == -1) {
		perror("open");
		exit(EXIT_FAILURE);
	}
 
	// 读取数据
	lseek(fd, offset, SEEK_SET); // 移动到指定的文件偏移量
	bytes_read = read(fd, buffer, sizeof(buffer));
	if (bytes_read == -1) {
		perror("read");
		exit(EXIT_FAILURE);
	}
	// 输出读取的数据
	printf("Read from flash: %s\n", buffer);

	// 擦出数据
	lseek(fd, offset, SEEK_SET); // 移动到擦出的起始位置
	bytes_written = write(fd, buffer, sizeof(buffer));
	if (bytes_written == -1) {
		perror("erase");
		exit(EXIT_FAILURE);
	}else{
		printf("erase sucessfully\r\n");
	}
 
	// 写入数据
	// 修改buffer中的数据...
	lseek(fd, offset, SEEK_SET); // 移动到写入的起始位置
	bytes_written = write(fd, buffer, sizeof(buffer));
	if (bytes_written == -1) {
		perror("write");
		exit(EXIT_FAILURE);
	}else{
		printf("write sucessfully\r\n");
	}
 
	close(fd);
	return 0;
}
cpp 复制代码
/***************************************************************
 文件名                 : flashAPP4.c
 描述                   : flash 读写测试	w25q256		
 其他                   : /dev/mtd0		
 ***************************************************************/

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <mtd/mtd-user.h>
#include <string.h>

#define FLASH_DEVICE	"/dev/mtd0"	// Flash设备
#define ERASE_SIZE		(256 * 8 * 32)			// 擦除块大小

int main() {
	int fd;
	char *data_to_write = "Hello, NOR Flash!";	// 写入的数据
	char read_buffer[ERASE_SIZE];
	struct mtd_info_user mtd_info;
	struct erase_info_user erase_params;
	int result;
	off_t offset = 0; // 假设我们从0字节的位置开始读写

	// 打开Flash设备文件
	fd = open(FLASH_DEVICE, O_RDWR);
	if (fd < 0) {
		perror("Failed to open flash device");
		return -1;
	}

	// 获取Flash信息
	result = ioctl(fd, MEMGETINFO, &mtd_info);
	if (result < 0) {
		perror("Failed to get flash info");
		close(fd);
		return -1;
	}

	// 擦除Flash
	erase_params.start = offset;       // 从0地址开始擦除
	erase_params.length = offset + ERASE_SIZE; // 擦除块大小
	result = ioctl(fd, MEMERASE, &erase_params);
	if (result < 0) {
		perror("Failed to erase flash");
		close(fd);
		return -1;
	} else{
		printf("erase sucessfully\r\n");
	}

	// 写入数据到Flash
	lseek(fd, offset, SEEK_SET); // 设置文件偏移到offset
	result = write(fd, data_to_write, strlen(data_to_write) + 1); // +1是为了包含字符串结尾的null字符
	if (result < 0) {
		perror("Failed to write to flash");
		close(fd);
		return -1;
	} else{
		printf("write sucessfully\r\n");
	}

	// 从Flash读取数据
	lseek(fd, offset, SEEK_SET);
	result = read(fd, read_buffer, sizeof(read_buffer) - 1);
	if (result < 0) {
		perror("Failed to read from flash");
		close(fd);
		return -1;
	}
	read_buffer[result] = '\0'; // 确保字符串结尾有null字符

	// 输出读取的数据
	printf("Read from flash: %s\n", read_buffer);

	// 关闭Flash设备文件
	close(fd);

	return 0;
}

读写地址计算:

如何编写linux下nand flash驱动-3 - xmj - 博客园

其他-内核配置修改&编译

内核编译失败!!!

kernel编译失败。

应该是之前make menuconfig修改了某些配置,然后今天编译的时候才发现不通过了。

但是已经忘了修改了什么配置。

目前只知道是AXI Ethernet有关的。

解决了: (花了一整天)

是因为在内核的目录下,make menuconfig之前,没有在FMQL-bsp包的目录下输入source env.sh

!!!!!

和内核的配置没关系!!!

相关推荐
丶Darling.几秒前
vscode在windows和linux如何使用cmake构建项目并make生成可执行文件,两者有什么区别
linux·windows·vscode
ken223216 分钟前
distrobox install in ubuntu 22.04 / 在 ubuntu 22.04 上安装 distrobox (***) OK
linux
秃头佛爷21 分钟前
linux命令总结
linux·运维·服务器
Mr.王8351 小时前
架构学习第四周--高可用与NoSQL数据库
linux·nosql
C++忠实粉丝2 小时前
Linux系统基础-多线程超详细讲解(5)_单例模式与线程池
linux·运维·服务器·c++·算法·单例模式·职场和发展
华纳云IDC服务商2 小时前
CentOS系统中查看内网端口映射的多种方法
linux·运维·centos
光芒再现dev3 小时前
CentOS—OpenEulerOS系统联网指南
linux·运维·centos
蓝莓星冰乐3 小时前
Linux入门(2)
linux·运维·服务器
重生之我是数学王子4 小时前
网络编程 UDP编程 Linux环境 C语言实现
linux·c语言·开发语言·网络·网络协议·udp