0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux驱动开发-编写W25Q64(Flash)驱动

DS小龙哥-嵌入式技术 2022-09-17 15:09 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

【摘要】 本篇文章就介绍如何在Linux系统下编写W25Q64芯片的驱动,完成数据存储,W25Q64支持标准SPI总线,当前驱动程序底层的代码写了两种方式,一种是采用内核提供的SPI子系统框架,一种直接采用软件模拟SPI时序的方式驱动,具体代码在第3章贴出来了。

1. W25QXX介绍

W25Q64是一颗SPI接口的Flash存储芯片,是华邦W25QXX系列里的一个具体型号,这个系列里包含了W25Q16,W25Q32,W25Q64,W5Q128等等。编程代码逻辑都差不多,主要是容量的区别。

本篇文章就介绍如何在Linux系统下编写W25Q64芯片的驱动,完成数据存储,W25Q64支持标准SPI总线,当前驱动程序底层的代码写了两种方式,一种是采用内核提供的SPI子系统框架,一种直接采用软件模拟SPI时序的方式驱动,具体代码在第3章贴出来了。

下面是来至W25Qxx中文手册的介绍

W25Q64 (64M-bit), W25Q16(16M-bit)和 W25Q32(32M-bit)是为系统提供一个最小的空间、引脚和功耗的存储器解决方案的串行 Flash 存储器。 25Q 系列比普通的串行 Flash 存储器更灵活,性能更优越。基于双倍/四倍的 SPI,它们能够可以立即完成提供数据给 RAM, 包括存储声音、文本和数据。芯片支持的工作电压 2.7V 到 3.6V,正常工作时电流小于 5mA,掉电时低于 1uA。所有芯片提供标准的封装。

W25Q64/16/32 由每页 256 字节组成。 每页的 256 字节用一次页编程指令即可完成。 每次可以擦除 16 页(1 个扇区)、 128 页(32KB 块)、 256 页(64KB 块)和全片擦除。W25Q64 的内存空间结构: 一页 256 字节, 4K(4096 字节)为一个扇区, 16 个扇区为 1 块, 容量为 8M 字节,共有 128 个块,2048 个扇区。W25Q64/16/32 支持标准串行外围接口(SPI),和高速的双倍/四倍输出,双倍/四倍用的引脚:串行时钟、片选端、串行数据 I/O0(DI)、 I/O1(DO)、 I/O2(WP)和 I/O3(HOLD)。 SPI 最高支持 80MHz,当用快读双倍/四倍指令时,相当于双倍输出时最高速率 160MHz,四倍输出时最高速率 320MHz。这个传输速率比得上 8 位和 16 位的并行 Flash 存储器。HOLD 引脚和写保护引脚可编程写保护。此外,芯片支持 JEDEC 标准,具有唯一的 64 位识别序列号。

●SPI 串行存储器系列
-W25Q64:64M 位/8M 字节
-W25Q16:16M 位/2M 字节
-W25Q32:32M 位/4M 字节
-每256字节可编程页

2. 硬件环境

当前测试使用的开发板采用友善之臂的Tiny4412开发板,芯片是三星的EXYNOS-4412,最高主频1.5GHZ。

开发板引出了SPI的IO口,这里使用的W25Q64是外置的模块,使用杜邦线与开发板的IO口连接。

开发板上引出的IO口都是5V和1.8V,为了方便供电,采用了一个USB转TTL模块提供电源,测试驱动。

W25Q64模块接在开发板的SPI0接口上面的。

image-20220106103405322

Linux内核自带有SPI子系统的设备端示例代码:

Linux 内核自带的 SPI 驱动注册示例代码: \drivers\spi\spidev.c
Linux 内核自带的 SPI APP 注册示例代码: \Documentation\spi

如果要使用内核自带SPI驱动,可以在内核编译时配置一下。

root# make menuconfig
Device Drivers  --->  
[*] SPI support  --->  
<*>   Samsung S3C64XX series type SPI                                          
	  [*]     Samsung S3C64XX Channel 0 Support.

Tiny4412自带内核里的SPI设备端结构:

image-20220106103638018

SPI0的具体GPIO口位置:

image-20220106103712723

3. 案例代码

3.1 模拟SPI时序-编写驱动

下面是W25Q64的驱动测试代码,没有注册字符设备框架,只是在驱动的入口里测试时序是否OK,打印了ID,读写了数据进行测试。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

/*--------------------------------W25Q64相关操作代码---------------------------------------------*/
/*定义指针,用于接收虚拟地址*/
volatile unsigned int *W25Q64_GPBCON;
volatile unsigned int *W25Q64_GPBDAT;
/*
函数功能:W25Q64初始化
Tiny4412硬件连接:
	DO--MISO :GPB_2 //输入模式
	DI--MOSI :GPB_3 //输出模式
	CLK-SCLK :GPB_0 //时钟
	CS--CS   :GPB_1 //片选
*/
void W25Q64_Init(void)
{
	/*1. 初始化GPIO*/
	/*映射物理地址*/
	W25Q64_GPBCON=ioremap(0x11400040,4);
	W25Q64_GPBDAT=ioremap(0x11400044,4);
	
	*W25Q64_GPBCON &= ~(0xf  << 0 * 4);*W25Q64_GPBCON |=  (0x1   << 0 * 4);
	*W25Q64_GPBCON &= ~(0xf  << 1 * 4);*W25Q64_GPBCON |=  (0x1   << 1 * 4);
	*W25Q64_GPBCON &= ~(0xf  << 2 * 4);
	*W25Q64_GPBCON &= ~(0xf  << 3 * 4);*W25Q64_GPBCON |=  (0x1   << 3 * 4);
	
	/*2. 上拉GPIO口*/
	//*W25Q64_GPBDAT &= ~(1 << 4);//输出0
	*W25Q64_GPBDAT |= (1 << 0);   //输出1
	*W25Q64_GPBDAT |= (1 << 1);   //输出1
	*W25Q64_GPBDAT |= (1 << 3);   //输出1
}
/*
函数功能:SPI时序读写一个字节
说    明:SPI底层时序,程序的移植接口
*/
u8 W25Q64_SPI_ReadWriteOneByte(u8 data_tx)
{
	 u8 data_rx=0;
	 u8 i;
	 for(i=0;i<8;i++)
	 {
		*W25Q64_GPBDAT &= ~(1 << 0);//输出0
		if(data_tx&0x80)*W25Q64_GPBDAT |= (1 << 3);   //输出1
		else *W25Q64_GPBDAT &= ~(1 << 3);//输出0
		data_tx<<=1; //继续发送下一个数据

		*W25Q64_GPBDAT |= (1 << 0);   //输出1
		data_rx<<=1;
		if((*W25Q64_GPBDAT & (1 << 2)))data_rx|=0x01;
	 }
	 return data_rx;
}

/*
函数功能:写使能
*/
void  W25Q64_WriteEnabled(void)
{
	*W25Q64_GPBDAT &= ~(1 << 1); //选中W25Q64
	W25Q64_SPI_ReadWriteOneByte(0x06);
	*W25Q64_GPBDAT |= (1 << 1); //取消选中W25Q64
}
/*
函数功能:读状态
*/
void W25Q64_GetBusyStat(void)
{
	unsigned char stat=1;
	while(stat&0x01)  //判断状态最低位
	{
		*W25Q64_GPBDAT &= ~(1 << 1);
		W25Q64_SPI_ReadWriteOneByte(0x05);
		stat=W25Q64_SPI_ReadWriteOneByte(0xFF);  //读取状态寄存器的值
		*W25Q64_GPBDAT |= (1 << 1);
	}
}
/*
函数功能:读取设备ID和制造商ID
W25Q64: EF16
W25QQ128:EF17
*/
unsigned short W25Q64_ReadDeviceID(void)
{
	unsigned short ID;
	*W25Q64_GPBDAT &= ~(1 << 1);
	W25Q64_SPI_ReadWriteOneByte(0x90);
	W25Q64_SPI_ReadWriteOneByte(0x0); 
	W25Q64_SPI_ReadWriteOneByte(0x0); 
	W25Q64_SPI_ReadWriteOneByte(0x0);

	ID=W25Q64_SPI_ReadWriteOneByte(0xFF)<<8; //制造商ID
	ID|=W25Q64_SPI_ReadWriteOneByte(0xFF);   //设备ID
	*W25Q64_GPBDAT |= (1 << 1);
	return ID;
}
/*
函数功能:全片擦除
*/
void W25Q64_ClearAll(void)
{
	W25Q64_WriteEnabled(); //写使能
	W25Q64_GetBusyStat();  //检测状态寄存器
	*W25Q64_GPBDAT &= ~(1 << 1);
	W25Q64_SPI_ReadWriteOneByte(0xC7);
	*W25Q64_GPBDAT |= (1 << 1);
	W25Q64_GetBusyStat();  //检测状态寄存器
}
/*
函数功能:页编程
参    数:
		unsigned int addr:写入的地址
        void  *p:将要写入的数据
		unsigned int  len:写入的长度
说    明:每次最多只能写入256字节
*/
void W25Q64_PageWrite(unsigned int addr,void*p,unsigned int len)
{
	 unsigned short i;
	 unsigned char *buff=p;
	 W25Q64_WriteEnabled(); //写使能
	 *W25Q64_GPBDAT &= ~(1 << 1);
	 W25Q64_SPI_ReadWriteOneByte(0x02);
	 W25Q64_SPI_ReadWriteOneByte(addr>>16); 
	 W25Q64_SPI_ReadWriteOneByte(addr>>8); 
	 W25Q64_SPI_ReadWriteOneByte((unsigned char)addr);
	 for(i=0;i>16); 
	W25Q64_SPI_ReadWriteOneByte(addr>>8); 
	W25Q64_SPI_ReadWriteOneByte((unsigned char)addr);
	*W25Q64_GPBDAT |= (1 << 1);
	W25Q64_GetBusyStat();  //检测状态寄存器
}
/*
函数功能:数据读取
参    数:
*/
void  W25Q64_ReadData(unsigned int addr,void *p,unsigned int len)
{
	unsigned int i=0;
	unsigned char *buff=p;
	*W25Q64_GPBDAT &= ~(1 << 1);
	W25Q64_SPI_ReadWriteOneByte(0x03);
	W25Q64_SPI_ReadWriteOneByte(addr>>16); 
	W25Q64_SPI_ReadWriteOneByte(addr>>8); 
	W25Q64_SPI_ReadWriteOneByte((unsigned char)addr);
	for(i=0;i256)page_remain=256;
		else page_remain=len;
	} 
}
/*
函数功能:在任意地址写入任意数据,对扇区进行校验
参    数:
	unsigned int addr:写入数据的地址
	void *p :写入的数据
	unsigned int len :写入数据的长度
说明:一个扇区的空间4096字节
*/
unsigned char W25Q64_BUFF[1024*4]; //用来检验一个扇区的数据是否需要擦除

void W25Q64_WriteData(unsigned int addr,void *p,unsigned int len)
{
	unsigned int sector_len=4096-addr%4096;  //剩余空间大小 
	unsigned char *buff=p;
	unsigned int i=0;
	if(len4096)
		{
			sector_len=4096;
		}
		else
		{
			sector_len=len;
		}
	}
}
static int __init w25q64_init(void)
{
	/*1. 初始化GPIO口*/
	W25Q64_Init();
	
	/*2. 打印厂商芯片ID*/
	unsigned short id=W25Q64_ReadDeviceID();
	printk("id=0x%X\n",id);
	
	/*3. 写入数据*/
	char buff[]="W25Q64-test-123456789ABCDEFG";
	W25Q64_WriteData(100,buff,strlen(buff));
	printk("write-data:%s\n",buff);
	
	/*4. 读出数据*/
	char buff_rx[100];
	W25Q64_ReadData(100,buff_rx,strlen(buff));
	printk("read-data:%s\n",buff_rx);
	return 0;
}
static void __exit w25q64_exit(void)
{
	/*释放虚拟地址*/
	iounmap(W25Q64_GPBCON);
	iounmap(W25Q64_GPBDAT);
	printk("w25q64 driver exit ok!\n");
}

module_exit(w25q64_exit);
module_init(w25q64_init);
MODULE_LICENSE("GPL");
)>;i++)>;i++)>

3.2 采用SPI子系统框架-编写驱动

下面代码使用SPI子系统框架编写的驱动测试代码,注册了字符设备框架,但是只是做了简单的测试,目的只是测试W25Q64是否可以正常驱动,能读写存储。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include    /*杂项字符设备头文件*/
#include            /*文件操作集合*/
#include 

/*--------------------------------W25Q64相关操作代码---------------------------------------------*/
struct spi_device *w25q64_spi_Device;
/*
函数功能:W25Q64初始化
Tiny4412硬件连接:
	DO--MISO :GPB_2 //输入模式
	DI--MOSI :GPB_3 //输出模式
	CLK-SCLK :GPB_0 //时钟
	CS--CS   :GPB_1 //片选
*/
/*
函数功能:读取设备ID和制造商ID
W25Q64: EF16
W25QQ128:EF17

参数:0x90表示读取ID号的指令
*/
unsigned short W25Q64_ReadDeviceID(void)
{
	/*使用硬件SPI同步读写时序*/
	char tx_buf[6]={0x90,0x0,0x0,0x0,0xFF,0xFF};
	char rx_buf[6];

	struct spi_message m;
	struct spi_transfer t=
	{
		.tx_buf=tx_buf,
		.rx_buf=rx_buf,
		.len=6,
		.delay_usecs=0,
		.speed_hz=1000000,
		.bits_per_word=8
	};
	spi_message_init(&m);
	spi_message_add_tail(&t,&m);
	spi_sync(w25q64_spi_Device,&m);
	return rx_buf[4]<<8|rx_buf[5]; /*得到ID值*/
}
/*
函数功能:指定位置读取指定长度的数据
参    数:
0x03 表示读取数据的指令。
*/
void  W25Q64_ReadData(unsigned int addr,void *p,unsigned int len)
{	
	/*使用硬件SPI同步读写时序*/
	char tx_buf[4];
	tx_buf[0]=0x03;       //读指令
	tx_buf[1]=addr>>16;   //以下是地址指令
	tx_buf[2]=addr>>8;
	tx_buf[3]=addr;
	spi_write(w25q64_spi_Device,tx_buf,4);
	spi_read(w25q64_spi_Device,p,len);
}
/*
函数功能:写使能
*/
void  W25Q64_WriteEnabled(void)
{
	/*使用硬件SPI同步读写时序*/
	char tx_buf[1]={0x06};
	struct spi_message m;
	struct spi_transfer t=
	{
		.tx_buf=tx_buf,
		.len=1,
		.delay_usecs=0,
		.speed_hz=1000000,
		.bits_per_word=8
	};
	spi_message_init(&m);
	spi_message_add_tail(&t,&m);
	spi_sync(w25q64_spi_Device,&m);
}
/*
函数功能:读状态
*/
void W25Q64_GetBusyStat(void)
{
	unsigned char stat=1;
	/*使用硬件SPI同步读写时序*/
	char tx_buf[2]={0x05,0xFF};
	char rx_buf[2];
	while(stat&0x01)  //判断状态最低位
	{	
		struct spi_message m;
		struct spi_transfer t=
		{
			.tx_buf=tx_buf,
			.rx_buf=rx_buf,
			.len=2,
			.delay_usecs=0,
			.speed_hz=1000000,
			.bits_per_word=8
		};
		spi_message_init(&m);
		spi_message_add_tail(&t,&m);
		spi_sync(w25q64_spi_Device,&m);
		stat=rx_buf[1]; //得到状态寄存器
	}
}
/*
函数功能:扇区擦除
参    数:
		unsigned int addr:扇区的地址
说   明:一个扇区是4096字节,擦除一个扇区时间至少150ms
*/
void W25Q64_ClearSector(unsigned int addr)
{
	W25Q64_WriteEnabled(); //写使能
	W25Q64_GetBusyStat();  //检测状态寄存器
	
	/*使用硬件SPI同步读写时序*/
	unsigned char tx_buf[4];
	tx_buf[0]=0x20;
	tx_buf[1]=addr>>16;
	tx_buf[2]=addr>>8;
	tx_buf[3]=addr;
	
	char rx_buf[4];
	struct spi_message m;
	struct spi_transfer t=
	{
		.tx_buf=tx_buf,
		.rx_buf=rx_buf,
		.len=4,
		.delay_usecs=0,
		.speed_hz=1000000,
		.bits_per_word=8
	};
	spi_message_init(&m);
	spi_message_add_tail(&t,&m);
	spi_sync(w25q64_spi_Device,&m);
	W25Q64_GetBusyStat();  //检测状态寄存器
}
/*
函数功能:页编程
参    数:
		unsigned int addr:写入的地址
        void  *p:将要写入的数据
		unsigned int  len:写入的长度
说    明:每次最多只能写入256字节
*/
void W25Q64_PageWrite(unsigned int addr,void*p,unsigned int len)
{
	 unsigned short i;
	 unsigned char *buff=p;
	 W25Q64_WriteEnabled(); //写使能
	 
	/*使用硬件SPI同步读写时序*/
	unsigned char tx_buf[4];
	tx_buf[0]=0x02;       //页写指令
	tx_buf[1]=(addr>>16)&0xFF;   //以下是地址指令
	tx_buf[2]=(addr>>8)&0xFF;
	tx_buf[3]=(addr&0xFF);
	
	//写数据
	spi_write(w25q64_spi_Device,tx_buf,4);
	//写数据
	spi_write(w25q64_spi_Device,p,len);
	W25Q64_GetBusyStat();  //检测状态寄存器
}
/*
函数功能:在任意地址写入任意数据,不进行校验
参    数:
	unsigned int addr:写入数据的地址
	void *p :写入的数据
	unsigned int len :写入数据的长度
*/
void W25Q64_WriteDataONCheck(unsigned int addr,void *p,unsigned int len)
{
	unsigned char *buff=p;
	unsigned short page_remain=256-addr%256;  //当前地址开始一页剩下的空间
	unsigned short remain_len;      //剩余未写入的长度
	if(len256)page_remain=256;
		else page_remain=len;
	} 
}

/*
函数功能:在任意地址写入任意数据,对扇区进行校验
参    数:
	unsigned int addr:写入数据的地址
	void *p :写入的数据
	unsigned int len :写入数据的长度
说明:一个扇区的空间4096字节
*/
static unsigned char W25Q64_BUFF[1024*4]; //用来检验一个扇区的数据是否需要擦除
void W25Q64_WriteData(unsigned int addr,void *p,unsigned int len)
{
	unsigned int sector_len=4096-addr%4096;  //剩余空间大小 
	unsigned char *buff=p;
	unsigned int i=0;
	if(len4096)
		{
			sector_len=4096;
		}
		else
		{
			sector_len=len;
		}
	}
}
/*
杂项字符设备注册示例----->LED
*/
static int tiny4412_open(struct inode *my_inode, struct file *my_file)
{
	return 0;
}

static int tiny4412_release(struct inode *my_inode, struct file *my_file)
{
	return 0;
}

static ssize_t tiny4412_read(struct file *my_file, char __user *buf, size_t len, loff_t *loff)
{
	/*2. 打印厂商芯片ID*/
	unsigned short id=W25Q64_ReadDeviceID();
	printk("-ID=0x%X\n",id);
	
	/*3. 写入数据*/
	char buff[100]="打印厂商芯片ID打印厂商芯片ID";
	W25Q64_WriteData(0,buff,100);
	
	/*4. 读出数据*/
	char buff_rx[100];
	W25Q64_ReadData(0,buff_rx,100);
	printk("Read=%s\n",buff_rx);
	return 0;
}
static ssize_t tiny4412_write(struct file *my_file, const char __user *buf, size_t len, loff_t *loff)
{
	return 0;
}

/*文件操作集合*/
static struct file_operations tiny4412_fops=
{
	.open=tiny4412_open,
	.read=tiny4412_read,
	.write=tiny4412_write,
	.release=tiny4412_release
};
/*
核心结构体
*/
static struct miscdevice tiny4412_misc=
{
	.minor=MISC_DYNAMIC_MINOR,  /*自动分配次设备号*/
	.name="tiny4412_W25q64",       /*设备文件,指定/dev/生成的文件名称*/
	.fops=&tiny4412_fops
};
static int __devinit w25q64_probe(struct spi_device *spi)
{
	/*配置SPI模式*/
	spi->bits_per_word = 8;
	spi->mode = SPI_MODE_0;
	spi->max_speed_hz=1*1000000; //1Mhz	
	if(spi_setup(spi)<0)//配置
	{
		printk("SPI配置失败!\n");
	}
	
	/*保存指针指向*/
	w25q64_spi_Device=spi;
	
	printk("w25q64 probe ok!\n");
	printk("SpiNum=%d\n",spi->dev.id);
	
	/*杂项设备注册*/
    misc_register(&tiny4412_misc);
	return 0;
}
static int __devexit w25q64_remove(struct spi_device *spi)
{
	/*杂项设备注销*/
	misc_deregister(&tiny4412_misc);
	return 0;
}
static struct spi_driver w25q64_spi_driver = {
	.driver = {
		.name =	"spidev",
		.owner =THIS_MODULE,
	},
	.probe =w25q64_probe,
	.remove = __devexit_p(w25q64_remove),
};
/*-------------------------------------------------------------------------*/
static int __init w25q64_init(void)
{
	spi_register_driver(&w25q64_spi_driver);
	printk("w25q64 driver install ok!\n");
	return 0;
}
static void __exit w25q64_exit(void)
{
	spi_unregister_driver(&w25q64_spi_driver);
	printk("w25q64 driver exit ok!\n");
}

module_exit(w25q64_exit);
module_init(w25q64_init);
MODULE_LICENSE("GPL");)>)>
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FlaSh
    +关注

    关注

    10

    文章

    1718

    浏览量

    154783
  • 驱动
    +关注

    关注

    12

    文章

    1929

    浏览量

    88249
  • w25Q64
    +关注

    关注

    1

    文章

    15

    浏览量

    3225
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Linux驱动开发的必备知识

    、内核模块编程: 掌握内核模块的编写、编译、加载和卸载方法。 了解内核模块的初始化和清理函数的编写。 5、设备驱动框架: 熟悉字符设备、块设备、网络设备等驱动框架。 能够根据
    发表于 12-04 07:58

    FPGA实现基于SPI协议的Flash驱动控制芯片擦除

    本篇博客具体包括SPI协议的基本原理、模式选择以及时序逻辑要求,采用FPGA(EPCE4),通过SPI通信协议,对flashW25Q16BV)存储的固化程序进行芯片擦除操作。
    的头像 发表于 12-02 10:00 2031次阅读
    FPGA实现基于SPI协议的<b class='flag-5'>Flash</b><b class='flag-5'>驱动</b>控制芯片擦除

    【免费送书】成为硬核Linux开发者:《Linux 设备驱动开发(第 2 版)》

    Linux系统的设备驱动开发,一直给人门槛较高的印象,主要因内核机制抽象、需深度理解硬件原理、开发调试难度大所致。2021年,一本讲解驱动
    的头像 发表于 11-18 08:06 563次阅读
    【免费送书】成为硬核<b class='flag-5'>Linux</b><b class='flag-5'>开发</b>者:《<b class='flag-5'>Linux</b> 设备<b class='flag-5'>驱动</b><b class='flag-5'>开发</b>(第 2 版)》

    【书籍评测活动NO.67】成为硬核Linux开发者:《Linux 设备驱动开发(第 2 版)》

    开发设备驱动和板级支持包。截至目前,Linux仍是嵌入式系统领域的主流内核,几乎广泛应用于工业界的所有领域,这主要得益于其功能强大的子系统。因此,约翰·马迪厄编写本书,向广大
    发表于 11-17 17:52

    W25Q128JVSIM与GD25Q128ESIGR引脚兼容分析

    华邦W25Q128JVSIM作为常用的128Mbit SPI NOR Flash芯片,其兼容替代方案兆易创新GD25Q128ESIGR已获得批量客户的认可及使用。
    的头像 发表于 10-13 09:33 692次阅读
    <b class='flag-5'>W25Q</b>128JVSIM与GD<b class='flag-5'>25Q</b>128ESIGR引脚兼容分析

    SFUD QSPI读写w25q64jv失败是什么原因导致的?

    rtthread 版本: 5.1.0 芯片: stm32H743XI, 接口 qspi 20MHz Flash: w25q64jv 第一次上电能正常读取到ID, 但是只有这一次成功, 之后就都是0
    发表于 09-29 07:37

    如何在rtt studio中进行外部flash的调试?

    app下载到了外部flashw25q64)程序可以运行但调试不了
    发表于 09-25 07:53

    华邦电子W25Q-RV系列NOR Flash的四大本领

    在汽车、物联网和工业自动化等应用场景中,存储器是否能够稳定运行直接影响产品的可靠性。华邦推出的 W25Q-RV 系列 NOR Flash,成功通过 105°C 的工业级高温循环测试和储能测试,以超越 JEDEC 标准的性能,在严苛环境下为产品保驾护航。
    的头像 发表于 08-16 17:14 1377次阅读

    GD25Q64ESIG宽温导航芯

    兆易创新GD25Q64ESIG NOR FLASH凭借64Mb容量、8Mbx8架构及2.7V 3.6V宽电压支持,其SOP 8封装适配紧凑设计,高速SPI接口(133MHz)确保快速数据读取,满足
    的头像 发表于 08-07 09:45 780次阅读
    GD<b class='flag-5'>25Q64</b>ESIG宽温导航芯

    W25X16W25X32\W25X64 数据手册

    电子发烧友网站提供《W25X16W25X32\W25X64 数据手册.pdf》资料免费下载
    发表于 07-10 16:10 4次下载

    itop-3568开发驱动开发指南-实验程序的编写

    本实验对应的网盘路径为:iTOP-RK3568 开发板【底板 V1.7 版本】\\\\03_【iTOP-RK3568开发板】指南教程\\\\02_Linux 驱动配套资料\\\\04_
    发表于 05-19 10:26

    DLPC3479上电初始化失败的原因?

    我们做了两块电路板,使用DLPC3479驱动光机,3005作为电源,使用W25Q64作为FLASH。接上光机之后,上电发现3005的1.1V,1.8V,3.3V均输出正常,-14V,10V,18V
    发表于 02-21 10:05

    DLPC3479上电初始化失败的原因?

    使用DLPC3479驱动光机,3005作为电源,使用W25Q64作为FLASH。接上光机之后,上电发现3005的1.1V,1.8V,3.3V均输出正常,-14V,10V,18V电压输出后掉下来
    发表于 02-21 06:44

    迅为RK3568开发驱动指南Linux中通用SPI设备驱动

    迅为RK3568开发驱动指南Linux中通用SPI设备驱动
    的头像 发表于 01-23 11:02 3480次阅读
    迅为RK3568<b class='flag-5'>开发</b>板<b class='flag-5'>驱动</b>指南<b class='flag-5'>Linux</b>中通用SPI设备<b class='flag-5'>驱动</b>

    迅为RK3568开发板SPI驱动指南-mcp2515驱动编写:读寄存器函数

    迅为RK3568开发板SPI驱动指南-mcp2515驱动编写:读寄存器函数
    的头像 发表于 01-20 14:43 1539次阅读
    迅为RK3568<b class='flag-5'>开发</b>板SPI<b class='flag-5'>驱动</b>指南-mcp2515<b class='flag-5'>驱动</b><b class='flag-5'>编写</b>:读寄存器函数