精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux驅(qū)動開發(fā)-編寫W25Q64(Flash)驅(qū)動

DS小龍哥-嵌入式技術(shù) ? 2022-09-17 15:09 ? 次閱讀

【摘要】 本篇文章就介紹如何在Linux系統(tǒng)下編寫W25Q64芯片的驅(qū)動,完成數(shù)據(jù)存儲,W25Q64支持標(biāo)準(zhǔn)SPI總線,當(dāng)前驅(qū)動程序底層的代碼寫了兩種方式,一種是采用內(nèi)核提供的SPI子系統(tǒng)框架,一種直接采用軟件模擬SPI時(shí)序的方式驅(qū)動,具體代碼在第3章貼出來了。

1. W25QXX介紹

W25Q64是一顆SPI接口的Flash存儲芯片,是華邦W25QXX系列里的一個(gè)具體型號,這個(gè)系列里包含了W25Q16,W25Q32,W25Q64,W5Q128等等。編程代碼邏輯都差不多,主要是容量的區(qū)別。

本篇文章就介紹如何在Linux系統(tǒng)下編寫W25Q64芯片的驅(qū)動,完成數(shù)據(jù)存儲,W25Q64支持標(biāo)準(zhǔn)SPI總線,當(dāng)前驅(qū)動程序底層的代碼寫了兩種方式,一種是采用內(nèi)核提供的SPI子系統(tǒng)框架,一種直接采用軟件模擬SPI時(shí)序的方式驅(qū)動,具體代碼在第3章貼出來了。

下面是來至W25Qxx中文手冊的介紹

W25Q64 (64M-bit), W25Q16(16M-bit)和 W25Q32(32M-bit)是為系統(tǒng)提供一個(gè)最小的空間、引腳和功耗的存儲器解決方案的串行 Flash 存儲器。 25Q 系列比普通的串行 Flash 存儲器更靈活,性能更優(yōu)越。基于雙倍/四倍的 SPI,它們能夠可以立即完成提供數(shù)據(jù)給 RAM, 包括存儲聲音、文本和數(shù)據(jù)。芯片支持的工作電壓 2.7V 到 3.6V,正常工作時(shí)電流小于 5mA,掉電時(shí)低于 1uA。所有芯片提供標(biāo)準(zhǔn)的封裝。

W25Q64/16/32 由每頁 256 字節(jié)組成。 每頁的 256 字節(jié)用一次頁編程指令即可完成。 每次可以擦除 16 頁(1 個(gè)扇區(qū))、 128 頁(32KB 塊)、 256 頁(64KB 塊)和全片擦除。W25Q64 的內(nèi)存空間結(jié)構(gòu): 一頁 256 字節(jié), 4K(4096 字節(jié))為一個(gè)扇區(qū), 16 個(gè)扇區(qū)為 1 塊, 容量為 8M 字節(jié),共有 128 個(gè)塊,2048 個(gè)扇區(qū)。W25Q64/16/32 支持標(biāo)準(zhǔn)串行外圍接口(SPI),和高速的雙倍/四倍輸出,雙倍/四倍用的引腳:串行時(shí)鐘、片選端、串行數(shù)據(jù) I/O0(DI)、 I/O1(DO)、 I/O2(WP)和 I/O3(HOLD)。 SPI 最高支持 80MHz,當(dāng)用快讀雙倍/四倍指令時(shí),相當(dāng)于雙倍輸出時(shí)最高速率 160MHz,四倍輸出時(shí)最高速率 320MHz。這個(gè)傳輸速率比得上 8 位和 16 位的并行 Flash 存儲器。HOLD 引腳和寫保護(hù)引腳可編程寫保護(hù)。此外,芯片支持 JEDEC 標(biāo)準(zhǔn),具有唯一的 64 位識別序列號。

●SPI 串行存儲器系列
-W25Q64:64M 位/8M 字節(jié)
-W25Q16:16M 位/2M 字節(jié)
-W25Q32:32M 位/4M 字節(jié)
-每256字節(jié)可編程頁

2. 硬件環(huán)境

當(dāng)前測試使用的開發(fā)板采用友善之臂的Tiny4412開發(fā)板,芯片是三星的EXYNOS-4412,最高主頻1.5GHZ。

開發(fā)板引出了SPI的IO口,這里使用的W25Q64是外置的模塊,使用杜邦線與開發(fā)板的IO口連接。

開發(fā)板上引出的IO口都是5V和1.8V,為了方便供電,采用了一個(gè)USB轉(zhuǎn)TTL模塊提供電源,測試驅(qū)動。

W25Q64模塊接在開發(fā)板的SPI0接口上面的。

image-20220106103405322

Linux內(nèi)核自帶有SPI子系統(tǒng)的設(shè)備端示例代碼:

Linux 內(nèi)核自帶的 SPI 驅(qū)動注冊示例代碼: \drivers\spi\spidev.c
Linux 內(nèi)核自帶的 SPI APP 注冊示例代碼: \Documentation\spi

如果要使用內(nèi)核自帶SPI驅(qū)動,可以在內(nèi)核編譯時(shí)配置一下。

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

Tiny4412自帶內(nèi)核里的SPI設(shè)備端結(jié)構(gòu):

image-20220106103638018

?

SPI0的具體GPIO口位置:

image-20220106103712723

3. 案例代碼

3.1 模擬SPI時(shí)序-編寫驅(qū)動

下面是W25Q64的驅(qū)動測試代碼,沒有注冊字符設(shè)備框架,只是在驅(qū)動的入口里測試時(shí)序是否OK,打印了ID,讀寫了數(shù)據(jù)進(jìn)行測試。

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

/*--------------------------------W25Q64相關(guān)操作代碼---------------------------------------------*/
/*定義指針,用于接收虛擬地址*/
volatile unsigned int *W25Q64_GPBCON;
volatile unsigned int *W25Q64_GPBDAT;
/*
函數(shù)功能:W25Q64初始化
Tiny4412硬件連接:
	DO--MISO :GPB_2 //輸入模式
	DI--MOSI :GPB_3 //輸出模式
	CLK-SCLK :GPB_0 //時(shí)鐘
	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
}
/*
函數(shù)功能:SPI時(shí)序讀寫一個(gè)字節(jié)
說    明:SPI底層時(shí)序,程序的移植接口
*/
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; //繼續(xù)發(fā)送下一個(gè)數(shù)據(jù)

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

/*
函數(shù)功能:寫使能
*/
void  W25Q64_WriteEnabled(void)
{
	*W25Q64_GPBDAT &= ~(1 << 1); //選中W25Q64
	W25Q64_SPI_ReadWriteOneByte(0x06);
	*W25Q64_GPBDAT |= (1 << 1); //取消選中W25Q64
}
/*
函數(shù)功能:讀狀態(tài)
*/
void W25Q64_GetBusyStat(void)
{
	unsigned char stat=1;
	while(stat&0x01)  //判斷狀態(tài)最低位
	{
		*W25Q64_GPBDAT &= ~(1 << 1);
		W25Q64_SPI_ReadWriteOneByte(0x05);
		stat=W25Q64_SPI_ReadWriteOneByte(0xFF);  //讀取狀態(tài)寄存器的值
		*W25Q64_GPBDAT |= (1 << 1);
	}
}
/*
函數(shù)功能:讀取設(shè)備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);   //設(shè)備ID
	*W25Q64_GPBDAT |= (1 << 1);
	return ID;
}
/*
函數(shù)功能:全片擦除
*/
void W25Q64_ClearAll(void)
{
	W25Q64_WriteEnabled(); //寫使能
	W25Q64_GetBusyStat();  //檢測狀態(tài)寄存器
	*W25Q64_GPBDAT &= ~(1 << 1);
	W25Q64_SPI_ReadWriteOneByte(0xC7);
	*W25Q64_GPBDAT |= (1 << 1);
	W25Q64_GetBusyStat();  //檢測狀態(tài)寄存器
}
/*
函數(shù)功能:頁編程
參    數(shù):
		unsigned int addr:寫入的地址
        void  *p:將要寫入的數(shù)據(jù)
		unsigned int  len:寫入的長度
說    明:每次最多只能寫入256字節(jié)
*/
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();  //檢測狀態(tài)寄存器
}
/*
函數(shù)功能:數(shù)據(jù)讀取
參    數(shù):
*/
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;
	} 
}
/*
函數(shù)功能:在任意地址寫入任意數(shù)據(jù),對扇區(qū)進(jìn)行校驗(yàn)
參    數(shù):
	unsigned int addr:寫入數(shù)據(jù)的地址
	void *p :寫入的數(shù)據(jù)
	unsigned int len :寫入數(shù)據(jù)的長度
說明:一個(gè)扇區(qū)的空間4096字節(jié)
*/
unsigned char W25Q64_BUFF[1024*4]; //用來檢驗(yàn)一個(gè)扇區(qū)的數(shù)據(jù)是否需要擦除

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. 寫入數(shù)據(jù)*/
	char buff[]="W25Q64-test-123456789ABCDEFG";
	W25Q64_WriteData(100,buff,strlen(buff));
	printk("write-data:%s\n",buff);
	
	/*4. 讀出數(shù)據(jù)*/
	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子系統(tǒng)框架-編寫驅(qū)動

下面代碼使用SPI子系統(tǒng)框架編寫的驅(qū)動測試代碼,注冊了字符設(shè)備框架,但是只是做了簡單的測試,目的只是測試W25Q64是否可以正常驅(qū)動,能讀寫存儲。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include    /*雜項(xiàng)字符設(shè)備頭文件*/
#include            /*文件操作集合*/
#include 

/*--------------------------------W25Q64相關(guān)操作代碼---------------------------------------------*/
struct spi_device *w25q64_spi_Device;
/*
函數(shù)功能:W25Q64初始化
Tiny4412硬件連接:
	DO--MISO :GPB_2 //輸入模式
	DI--MOSI :GPB_3 //輸出模式
	CLK-SCLK :GPB_0 //時(shí)鐘
	CS--CS   :GPB_1 //片選
*/
/*
函數(shù)功能:讀取設(shè)備ID和制造商ID
W25Q64: EF16
W25QQ128:EF17

參數(shù):0x90表示讀取ID號的指令
*/
unsigned short W25Q64_ReadDeviceID(void)
{
	/*使用硬件SPI同步讀寫時(shí)序*/
	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值*/
}
/*
函數(shù)功能:指定位置讀取指定長度的數(shù)據(jù)
參    數(shù):
0x03 表示讀取數(shù)據(jù)的指令。
*/
void  W25Q64_ReadData(unsigned int addr,void *p,unsigned int len)
{	
	/*使用硬件SPI同步讀寫時(shí)序*/
	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);
}
/*
函數(shù)功能:寫使能
*/
void  W25Q64_WriteEnabled(void)
{
	/*使用硬件SPI同步讀寫時(shí)序*/
	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);
}
/*
函數(shù)功能:讀狀態(tài)
*/
void W25Q64_GetBusyStat(void)
{
	unsigned char stat=1;
	/*使用硬件SPI同步讀寫時(shí)序*/
	char tx_buf[2]={0x05,0xFF};
	char rx_buf[2];
	while(stat&0x01)  //判斷狀態(tài)最低位
	{	
		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]; //得到狀態(tài)寄存器
	}
}
/*
函數(shù)功能:扇區(qū)擦除
參    數(shù):
		unsigned int addr:扇區(qū)的地址
說   明:一個(gè)扇區(qū)是4096字節(jié),擦除一個(gè)扇區(qū)時(shí)間至少150ms
*/
void W25Q64_ClearSector(unsigned int addr)
{
	W25Q64_WriteEnabled(); //寫使能
	W25Q64_GetBusyStat();  //檢測狀態(tài)寄存器
	
	/*使用硬件SPI同步讀寫時(shí)序*/
	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();  //檢測狀態(tài)寄存器
}
/*
函數(shù)功能:頁編程
參    數(shù):
		unsigned int addr:寫入的地址
        void  *p:將要寫入的數(shù)據(jù)
		unsigned int  len:寫入的長度
說    明:每次最多只能寫入256字節(jié)
*/
void W25Q64_PageWrite(unsigned int addr,void*p,unsigned int len)
{
	 unsigned short i;
	 unsigned char *buff=p;
	 W25Q64_WriteEnabled(); //寫使能
	 
	/*使用硬件SPI同步讀寫時(shí)序*/
	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);
	
	//寫數(shù)據(jù)
	spi_write(w25q64_spi_Device,tx_buf,4);
	//寫數(shù)據(jù)
	spi_write(w25q64_spi_Device,p,len);
	W25Q64_GetBusyStat();  //檢測狀態(tài)寄存器
}
/*
函數(shù)功能:在任意地址寫入任意數(shù)據(jù),不進(jìn)行校驗(yàn)
參    數(shù):
	unsigned int addr:寫入數(shù)據(jù)的地址
	void *p :寫入的數(shù)據(jù)
	unsigned int len :寫入數(shù)據(jù)的長度
*/
void W25Q64_WriteDataONCheck(unsigned int addr,void *p,unsigned int len)
{
	unsigned char *buff=p;
	unsigned short page_remain=256-addr%256;  //當(dāng)前地址開始一頁剩下的空間
	unsigned short remain_len;      //剩余未寫入的長度
	if(len256)page_remain=256;
		else page_remain=len;
	} 
}

/*
函數(shù)功能:在任意地址寫入任意數(shù)據(jù),對扇區(qū)進(jìn)行校驗(yàn)
參    數(shù):
	unsigned int addr:寫入數(shù)據(jù)的地址
	void *p :寫入的數(shù)據(jù)
	unsigned int len :寫入數(shù)據(jù)的長度
說明:一個(gè)扇區(qū)的空間4096字節(jié)
*/
static unsigned char W25Q64_BUFF[1024*4]; //用來檢驗(yàn)一個(gè)扇區(qū)的數(shù)據(jù)是否需要擦除
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;
		}
	}
}
/*
雜項(xiàng)字符設(shè)備注冊示例----->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. 寫入數(shù)據(jù)*/
	char buff[100]="打印廠商芯片ID打印廠商芯片ID";
	W25Q64_WriteData(0,buff,100);
	
	/*4. 讀出數(shù)據(jù)*/
	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
};
/*
核心結(jié)構(gòu)體
*/
static struct miscdevice tiny4412_misc=
{
	.minor=MISC_DYNAMIC_MINOR,  /*自動分配次設(shè)備號*/
	.name="tiny4412_W25q64",       /*設(shè)備文件,指定/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);
	
	/*雜項(xiàng)設(shè)備注冊*/
    misc_register(&tiny4412_misc);
	return 0;
}
static int __devexit w25q64_remove(struct spi_device *spi)
{
	/*雜項(xiàng)設(shè)備注銷*/
	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");)>)>
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • FlaSh
    +關(guān)注

    關(guān)注

    10

    文章

    1598

    瀏覽量

    147339
  • 驅(qū)動
    +關(guān)注

    關(guān)注

    12

    文章

    1790

    瀏覽量

    84910
  • w25Q64
    +關(guān)注

    關(guān)注

    1

    文章

    15

    瀏覽量

    2988
收藏 人收藏

    評論

    相關(guān)推薦

    W25Q128FV中文手冊

    W25Q128FV(128Mbit)型串行 Flash 存儲器面向受限于空間、引腳和功耗的系統(tǒng),提供了一種存儲解決方案。
    發(fā)表于 09-18 11:33 ?0次下載

    linux驅(qū)動程序如何加載進(jìn)內(nèi)核

    Linux系統(tǒng)中,驅(qū)動程序是內(nèi)核與硬件設(shè)備之間的橋梁。它們允許內(nèi)核與硬件設(shè)備進(jìn)行通信,從而實(shí)現(xiàn)對硬件設(shè)備的控制和管理。 驅(qū)動程序的編寫 驅(qū)動
    的頭像 發(fā)表于 08-30 15:02 ?193次閱讀

    Linux 驅(qū)動開發(fā)與應(yīng)用開發(fā),你知道多少?

    一、Linux驅(qū)動開發(fā)與應(yīng)用開發(fā)的區(qū)別開發(fā)層次不同:Linux
    的頭像 發(fā)表于 08-30 12:16 ?166次閱讀
    <b class='flag-5'>Linux</b> <b class='flag-5'>驅(qū)動</b><b class='flag-5'>開發(fā)</b>與應(yīng)用<b class='flag-5'>開發(fā)</b>,你知道多少?

    FLASH芯片從W25Q80BL換為W25Q80DV后,系統(tǒng)運(yùn)行經(jīng)常崩潰怎么解決?

    之前我們用的W25Q80BL,工作在40Mhz QIO ,系統(tǒng)運(yùn)行正常 本次生產(chǎn)時(shí),供應(yīng)商反饋W25Q80BL要停產(chǎn)了,后續(xù)供貨是W25Q80DV,測試時(shí)我們發(fā)現(xiàn),在頻繁地FLASH
    發(fā)表于 07-10 06:11

    使用W25Q64JVSIQ芯片時(shí)提示報(bào)錯(cuò)如何解決?

    系統(tǒng)使用W25Q64JVSIQ芯片時(shí)提示 Read SFDP parameter header information failed. The W25Q64 is not support JEDEC SFDP。 請問有沒有辦法解決,謝謝
    發(fā)表于 07-09 06:32

    W25M02G NAND FLASH做U盤,請問有沒有nand flash的U盤驅(qū)動

    最近在用W25M02G這款NAND FLASH做U盤,之前用的W25Q64,不需要壞塊管理,讀寫也是以頁的,NAND FLASH多了壞塊,多了扇區(qū)重入的交換區(qū)管理,請問有沒有比較好的
    發(fā)表于 04-25 06:44

    如何使用SPI的DMA模式讀寫FLASH

    環(huán)境:HAL庫 + USB + W25Q64 + Fatfs 硬件:stm32f103c8t6 + MX25L64 我使用普通模式,完成在W25Q64中寫入文件,通過USB可以再PC中讀取
    發(fā)表于 04-16 07:59

    使用STM32H750 QSPI W25Q64作為外部FLASH,映射后讀0X90010000地址的數(shù)據(jù)讀到的是0XFF的原因?

    我使用STM32H750QSPIW25Q64 作為外部FLASH,使用非映射方式讀寫FLASH 正常,映射后,讀0X90000000地址的數(shù)據(jù)也正常,但是讀0X90010000 地址的數(shù)據(jù)讀到
    發(fā)表于 04-01 06:24

    關(guān)于STM32F103從外設(shè)到存儲器DMA通道數(shù)據(jù)格式的問題

    在基于STM32F103開發(fā)過程中遇到了一個(gè)瓶頸,就是圖片取模后的數(shù)據(jù)放在W25Q64當(dāng)中,通過硬件SPI+DMA的方式直接將數(shù)據(jù)發(fā)送給FSMC,F(xiàn)SMC被用來驅(qū)動16bit的LCD屏,問題是硬件
    發(fā)表于 03-07 07:11

    E203外接外部flash時(shí),OPENOCD已經(jīng)正確識別flash ID,但還是燒寫失敗的原因?

    在黑金7A200FPGA上移植E203軟核,外接WIN W25Q64 FLASH時(shí),燒寫報(bào)錯(cuò) FLASH原理圖如下圖 球球各位大佬救救孩子
    發(fā)表于 01-10 06:20

    linux安裝網(wǎng)卡驅(qū)動教程

    Linux系統(tǒng)中安裝網(wǎng)卡驅(qū)動是一個(gè)比較基礎(chǔ)的操作,下面我將為你詳細(xì)講解如何安裝網(wǎng)卡驅(qū)動。 第一步,檢查網(wǎng)卡型號和驅(qū)動支持情況:首先,你需要確定你的網(wǎng)卡型號,并查看該網(wǎng)卡型號在
    的頭像 發(fā)表于 11-17 11:11 ?3409次閱讀

    STM32驅(qū)動FLASH(W25Q64)

    W25Q64 將 **8M** 的容量分為 **128 個(gè)塊(Block)** ,每個(gè)塊大小為 **64K 字節(jié)** ,每個(gè)塊又分為 **16個(gè)扇區(qū)(Sector)** ,每個(gè)扇區(qū) **4K 個(gè)字節(jié)** 。
    的頭像 發(fā)表于 10-24 09:50 ?996次閱讀
    STM32<b class='flag-5'>驅(qū)動</b><b class='flag-5'>FLASH</b>(<b class='flag-5'>W25Q64</b>)

    一文總結(jié)linux的platform驅(qū)動

    linux設(shè)備驅(qū)動中,有許多沒有特定總線的外設(shè)驅(qū)動,在實(shí)際開發(fā)中,又需要使用到總線、驅(qū)動和設(shè)備模型這三個(gè)概念,故而
    的頭像 發(fā)表于 10-16 16:45 ?803次閱讀
    一文總結(jié)<b class='flag-5'>linux</b>的platform<b class='flag-5'>驅(qū)動</b>

    Linux模塊相關(guān)命令 Linux驅(qū)動模塊的編寫與掛載

    Linux模塊相關(guān)命令 Linux驅(qū)動模塊的編寫與掛載
    發(fā)表于 10-01 12:20 ?363次閱讀
    <b class='flag-5'>Linux</b>模塊相關(guān)命令 <b class='flag-5'>Linux</b><b class='flag-5'>驅(qū)動</b>模塊的<b class='flag-5'>編寫</b>與掛載

    Linux內(nèi)核reset驅(qū)動實(shí)例

    reset驅(qū)動實(shí)例 類似于clock驅(qū)動,reset驅(qū)動也是編進(jìn)內(nèi)核的,在Linux啟動時(shí),完成reset驅(qū)動的加載。 設(shè)備樹 reset
    的頭像 發(fā)表于 09-27 14:21 ?588次閱讀