20.1實(shí)驗(yàn)內(nèi)容
通過本實(shí)驗(yàn)主要學(xué)習(xí)以下內(nèi)容:
GD32F303 SPI操作方式,參考19.2.2東方紅開發(fā)板使用手冊(cè)
NAND FLASH基本原理
SPI NAND介紹
使用GD32F303 SPI接口實(shí)現(xiàn)對(duì)GD5F1GQ5UEYIGY的讀寫操作
20.2實(shí)驗(yàn)原理
20.2.1NAND FLASH基本原理
NAND Flash和NOR Flash都是兩種非易失性存儲(chǔ)器,其讀寫速度、讀寫方式,存儲(chǔ)區(qū)結(jié)構(gòu)、成本、容量、擦寫壽命都有很大區(qū)別。NAND在壽命、速度、讀寫方式上都不如NOR,但在成本和容量上有很大區(qū)別,故而決定了大容量數(shù)據(jù)存儲(chǔ)是NAND的主要應(yīng)用領(lǐng)域,而快速啟動(dòng)、快速數(shù)據(jù)讀取等場(chǎng)景是NOR的主要應(yīng)用領(lǐng)域。而SPI是目前NAND和NOR的主要通信接口形式,降低了器件體積,標(biāo)準(zhǔn)化了器件接口。
NAND Flash結(jié)構(gòu)示例
如上圖所示,以GD5F1GQ5UEYIGY為例,一個(gè)1Gb的存儲(chǔ)結(jié)構(gòu)下是由1024個(gè)block組成,每個(gè)block又64page組成,每個(gè)page是2K Main Area+Spare Area(ECC ON:64B;ECC OFF:128B)組成。
NAND的擦除單位是blocks,寫入單位是page,所以尋址的方式上和nor是有本質(zhì)區(qū)別的,需要按blocks、page、page字節(jié)偏移地址進(jìn)行一個(gè)數(shù)據(jù)的尋址。
20.2.2SPI NAND介紹
SPI NAND簡(jiǎn)化了NAND的接口設(shè)計(jì)和尺寸,SPI接口更是降低了主控對(duì)接口的要求,同時(shí)內(nèi)置ECC。下圖是GD5F1GQ5UEYIGY的命令表,常用的命令為擦除、編程、讀取命令。
block擦除命令
編程
編程流程
先用數(shù)據(jù)緩存寫入指令將數(shù)據(jù)寫入緩沖區(qū)
然后發(fā)送寫使能命令,并確認(rèn)寫使能成功
然后發(fā)送數(shù)據(jù)載入命令執(zhí)行緩沖區(qū)數(shù)據(jù)到FLASH的寫
最后查詢讀寄存器確認(rèn)P_FAIL是否有錯(cuò),OIP是否完成
注意(84h/C4h/34h) 和(FFh)指令是不會(huì)清除緩存中的內(nèi)容的,所以下次編程時(shí)要注意是否緩存區(qū)都是需要更新的數(shù)據(jù),所以必須是一次更新整個(gè)緩沖區(qū),不要部分更新。
編程page地址按照塊的順序
數(shù)據(jù)緩存寫入命令
數(shù)據(jù)載入命令
讀取
讀取流程
讀需要先通過讀cache命令從FLASH中讀出數(shù)據(jù)到緩存中
然后通過讀cache指令從緩沖區(qū)中開始讀出數(shù)據(jù)
讀到2048+128后繞回從0開始繼續(xù)。
20.3硬件設(shè)計(jì)
紅楓派開發(fā)板SPI——NAND FLASH的硬件設(shè)計(jì)如下:
從圖中可以看出,本實(shí)驗(yàn)使用的是普通單線SPI,GD5F1GQ5UEYIGY的片選由GD32F303ZET6的PG13控制(因PG14不是SPI的NSS管腳,所以本實(shí)驗(yàn)用主機(jī)NSS軟件模式,,通過普通IO控制片選),GD25Q32ESIGR的SO、SI和SCLK分別和GD32F303ZET6的PB4(SPI2_MISO)、PB5(SPI2_MOSI)以及PB3(SPI2_CLK)相連。
20.4代碼解析
20.4.1SPI初始化和讀寫B(tài)YTE函數(shù)實(shí)現(xiàn)
SPI初始化配置流程可參考19.4.1東方紅開發(fā)板使用手冊(cè);
SPI讀寫B(tài)YTE函數(shù)實(shí)現(xiàn)可參考19.4.2東方紅開發(fā)板使用手冊(cè);
20.4.2SPI NAND FLASH BSP驅(qū)動(dòng)層實(shí)現(xiàn)
操作NAND FLASH的函數(shù)都定義在bsp層文件bsp_spi_nand.c中,這個(gè)文件中定義的函數(shù)都是針對(duì)NAND FLASH命令來實(shí)現(xiàn)的,我們選取幾個(gè)函數(shù)進(jìn)行介紹。
NOR FLASH按block擦除函數(shù)bsp_nandflash_block_erase,輸入block號(hào)即可擦除;該函數(shù)流程是:使能NAND FLASH的寫功能->向NOR FLASH發(fā)送block擦除指令0xD8->發(fā)送左移6位的Block NO->查詢OIP標(biāo)志等待完成
C
/*!
brief erase the nandflash blcok
param[in] block_No:the serial number of erase block
param[out] none
retval SPI_NAND_FAIL: erase the nandflash block fail
retval SPI_NAND_SUCCESS: erase the nandflash block success
*/
uint8_t bsp_spi_nandflash_block_erase(uint32_t block_No)
{
uint8_t result = SPI_NAND_SUCCESS;
block_No<<=6; //block_No=block_No*64
bsp_spi_nandflash_write_enable();
/* select the flash: chip select low */
bsp_spi_nand_cs_low();
/* send 'ERASE BLOCK' command */
driver_spi_master_transmit_receive_byte(&BOARD_SPI,SPI_NAND_BLOCK_ERASE);
/* send the address of memory */
driver_spi_master_transmit_receive_byte(&BOARD_SPI,(block_No>>16)&0xFF);
driver_spi_master_transmit_receive_byte(&BOARD_SPI,(block_No>>8)&0xFF);
driver_spi_master_transmit_receive_byte(&BOARD_SPI,block_No&0xFF);
/* deselect the flash: chip select high */
bsp_spi_nand_cs_high();
while(bsp_spi_nandflash_get_status_flag(OIP)==SPI_NAND_BUSY);
/* check program result */
return result;
}
NOR FLASH按page寫入函數(shù)bsp_nandflash_page_program,輸入待寫入數(shù)據(jù)指針、block號(hào)、page號(hào);該函數(shù)流程是:
寫緩沖區(qū),實(shí)現(xiàn)流程:向NOR FLASH發(fā)送寫緩沖區(qū)指令0x02->發(fā)送寫入的page偏移地址->發(fā)送待寫入數(shù)據(jù)
載入數(shù)據(jù)到page,實(shí)現(xiàn)流程:使能NAND FLASH的寫功能->發(fā)送載入命令0x10->發(fā)送寫入的page號(hào)
查詢OIP標(biāo)志等待完成
C
/*!
brief send the program load command,write data to cache
param[in] buffer: the data of array
param[in] address_in_page: the address in nandflash page
param[in] byte_cnt: the number of data
param[out] none
retval none
*/
void bsp_spi_nandflash_program_load(uint8_t *buffer,uint16_t address_in_page,uint32_t byte_cnt)
{
uint32_t i=0;
/* select the flash: chip select low */
bsp_spi_nand_cs_low();
#ifdef SPI_NANDFLASH
/* send 'PAGE READ' command */
driver_spi_master_transmit_receive_byte(&BOARD_SPI,SPI_NAND_PAGE_LOAD);
/* send the serial number of page */
driver_spi_master_transmit_receive_byte(&BOARD_SPI,(address_in_page>>8)&0xFF);
driver_spi_master_transmit_receive_byte(&BOARD_SPI,address_in_page&0xFF);
#endif
/* deselect the flash: chip select high */
for(i=0;i driver_spi_master_transmit_receive_byte(&BOARD_SPI,*buffer++);
}
//printf('cache program %x %xnr',m32record[0],m32record[1]);
bsp_spi_nand_cs_high();
qspi_disable(BOARD_SPI.spi_x);
}
/*!
brief send the program excute command
param[in] page_No: the serial number of nandflash page
param[out] none
retval none
*/
void bsp_spi_nandflash_program_execute(uint32_t page_No)
{
/* enable the write access to the flash */
bsp_spi_nandflash_write_enable();
/* select the flash: chip select low */
bsp_spi_nand_cs_low();
/* send 'PAGE READ' command */
driver_spi_master_transmit_receive_byte(&BOARD_SPI,SPI_NAND_PROGRAM_EXEC);
/* send the serial number of page */
driver_spi_master_transmit_receive_byte(&BOARD_SPI,(page_No>>16)&0xFF);
driver_spi_master_transmit_receive_byte(&BOARD_SPI,(page_No>>8)&0xFF);
driver_spi_master_transmit_receive_byte(&BOARD_SPI,page_No&0xFF);
/* deselect the flash: chip select high */
bsp_spi_nand_cs_high();
}
/*!
brief write the data to nandflash
param[in] *buffer:the data of array
param[in] page_No: the serial number of nandflash page
param[in] address_in_page: the address of nandflash page
param[in] byte_cnt:the number of data
param[out] none
retval SPI_NAND_FAIL,SPI_NAND_SUCCESS
*/
uint8_t spi_nandflash_write_data(uint8_t *buffer,uint32_t page_No,uint16_t address_page,uint32_t byte_cnt)
{
/*sned the program load command,write data to cache*/
bsp_spi_nandflash_program_load(buffer, address_page, byte_cnt);
/*sned the program excute command*/
bsp_spi_nandflash_program_execute(page_No);
/* Check program result */
while(bsp_spi_nandflash_get_status_flag(OIP)==SPI_NAND_BUSY);
#ifdef WRITE_PAGE_VERIFY_EN
spi_nandflash_read_data (tem_buffer,page_No, address_page, byte_cnt);
if (memcmp(tem_buffer, buffer, byte_cnt) != 0){
return SUCCESS;
}
#endif
return 1;
}
NOR FLASH按page讀取函數(shù)spi_nandflash_read_data,輸入讀取數(shù)據(jù)指針、page號(hào)、page內(nèi)地址偏移、讀取長(zhǎng)度;該函數(shù)流程是:
讀page到緩沖區(qū),實(shí)現(xiàn)流程:向NOR FLASH發(fā)送寫緩沖區(qū)指令0x13->送要讀取的page號(hào)
等待OIP標(biāo)志(NAND讀取page到緩沖區(qū)完成)
從緩沖區(qū)讀取數(shù)據(jù),實(shí)現(xiàn)流程:發(fā)送讀cache命令0x03->發(fā)送要讀取的page地址偏移->讀取所需長(zhǎng)度的數(shù)據(jù)
查詢是否有ecc錯(cuò)誤
C
/*!
brief send the read page command
param[in] page_No: the serial number of nandflash page
param[out] none
retval none
*/
void bsp_spi_nandflash_page_read(uint32_t page_No)
{
/* select the flash: chip select low */
bsp_spi_nand_cs_low();
/* send 'PAGE READ' command */
driver_spi_master_transmit_receive_byte(&BOARD_SPI,SPI_NAND_PAGE_READ);
/* send the serial number of page */
driver_spi_master_transmit_receive_byte(&BOARD_SPI,(page_No>>16)&0xFF);
driver_spi_master_transmit_receive_byte(&BOARD_SPI,(page_No>>8)&0xFF);
driver_spi_master_transmit_receive_byte(&BOARD_SPI,page_No&0xFF);
/* deselect the flash: chip select high */
bsp_spi_nand_cs_high();
}
/*!
brief send the read cache command
param[in] buffer: a pointer to the array
param[in] address_in_page: the address in nandflash page
param[in] byte_cnt: the number of data
param[out] none
retval none
*/
void bsp_spi_nandflash_read_cache(uint8_t *buffer,uint16_t address_in_page,uint32_t byte_cnt)
{
uint32_t i=0;
/* select the flash: chip select low */
bsp_spi_nand_cs_low();
#ifdef SPI_NANDFLASH
/* send 'PAGE READ' command */
driver_spi_master_transmit_receive_byte(&BOARD_SPI,SPI_NAND_READ_CACHE);
//driver_spi_master_transmit_receive_byte(&BOARD_SPI,DUMMY_BYTE);//Q4UC ++ Q5 --
/* send the address of page */
driver_spi_master_transmit_receive_byte(&BOARD_SPI,(address_in_page>>8)&0xFF);
driver_spi_master_transmit_receive_byte(&BOARD_SPI,address_in_page&0xFF);
driver_spi_master_transmit_receive_byte(&BOARD_SPI,DUMMY_BYTE);//Q4UC -- Q5 ++
#endif
for(i=0;i *buffer++=driver_spi_master_transmit_receive_byte(&BOARD_SPI,DUMMY_BYTE);
}
/* deselect the flash: chip select high */
bsp_spi_nand_cs_high();
qspi_disable(BOARD_SPI.spi_x);
}
/*!
brief read the data from nandflash
param[in] *buffer:the data of array
param[in] page_No: the serial number of nandflash page
param[in] address_in_page: the address in nandflash page
param[in] byte_cnt:the number of data
param[out] none
retval SPI_NAND_FAIL,SPI_NAND_SUCCESS
*/
uint8_t spi_nandflash_read_data(uint8_t *buffer,uint32_t page_No,uint32_t address_in_page,uint32_t byte_cnt)
{
uint8_t result = SPI_NAND_SUCCESS;
uint8_t status = 0;
uint8_t retrycnt = 0;
/* the capacity of page must be equal or greater than the taotal of address_in_page and byte_cnt */
if((address_in_page+byte_cnt)>SPI_NAND_PAGE_TOTAL_SIZE){
return SPI_NAND_FAIL;
}
ReadRetry:
/* send the read page command */
bsp_spi_nandflash_page_read(page_No);
/* wait for NANDFLASH is ready */
while(bsp_spi_nandflash_get_status_flag(OIP)==SPI_NAND_BUSY);
/* read data from cache */
bsp_spi_nandflash_read_cache(buffer, address_in_page, byte_cnt);
bsp_spi_nandflash_get_feature( STATUS, &status );
if(( (status & ECCS0) == 0 )&&( (status & ECCS1) == ECCS1 )){ //UECC
if(retrycnt < 3)
{
retrycnt++;
printf('rReadretry:%x %xn',retrycnt,page_No);
goto ReadRetry;
}
else
{
printf('rRead Fail %xn',page_No);
}
}
return result;
}
20.4.3main函數(shù)實(shí)現(xiàn)
main函數(shù)中實(shí)現(xiàn)了擦除一個(gè)block,并對(duì)該block中的page進(jìn)行寫入操作,然后讀取后進(jìn)行數(shù)據(jù)對(duì)比校驗(yàn)的功能。
C
/*!
* 說明 main函數(shù)
* 輸入 無
* 輸出 無
* 返回值 無
*/
int main(void)
{
//延時(shí)、共用驅(qū)動(dòng)部分初始化
driver_init();
//初始化LED組和默認(rèn)狀態(tài)
bsp_led_group_init();
bsp_led_on(&LED0);
bsp_led_off(&LED1);
//初始化UART打印
bsp_uart_init(&BOARD_UART);
//初始化SPI
bsp_spi_init(&BOARD_SPI);
//初始化SPI NAND
bsp_spi_nand_init();
printf('nrSPI NAND:GD5F1G configured...nr');
//讀取flash id
flash_id=bsp_spi_nandflash_read_id();
printf('nrThe NAND_ID:0x%Xnr',flash_id);
//比對(duì)flash id是否一致
if(NAND_ID != flash_id)
{
printf('nrnrWrite to tx_buffer:nrnr');
//準(zhǔn)備數(shù)據(jù)
for(uint16_t i = 0; i < BUFFER_SIZE; i ++){
tx_buffer[i] = i;
printf('0x%02X ',tx_buffer[i]);
if(15 == i%16)
printf('nr');
}
printf('nrnrRead from rx_buffer:nr');
//擦除要寫入的block
bsp_nandflash_block_erase(0);
//寫入數(shù)據(jù)
bsp_nandflash_page_program((uint8_t*)tx_buffer,0,0,0);
//回讀寫入數(shù)據(jù)
bsp_nandflash_page_read(rx_buffer,0,0);
/* printf rx_buffer value */
for(uint16_t i = 0; i <= 255; i ++){
printf('0x%02X ', rx_buffer[i]);
if(15 == i%16)
printf('nr');
}
//比較回讀和寫入數(shù)據(jù)
if(ERROR == memory_compare(tx_buffer,rx_buffer,BUFFER_SIZE)){
printf('Err:Data Read and Write aren't Matching.nr');
/* spi flash read id fail */
printf('nrSPI nand: Read ID Fail!nr');
//寫入錯(cuò)誤
/* turn off all leds */
bsp_led_on(&LED0);
/* turn off all leds */
bsp_led_on(&LED1);
while(1);
}else{
printf('nrSPI-GD5F1G Test Passed!nr');
}
}else{ //ID讀取錯(cuò)誤
/* spi flash read id fail */
printf('nrSPI Nand:Read ID Fail!nr');
/* turn off all leds */
bsp_led_on(&LED0);
/* turn off all leds */
bsp_led_on(&LED1);
上一篇:GD32F303固件庫開發(fā)(13)----定時(shí)器TIM捕獲PWM測(cè)量頻率與占空比
下一篇:GD32330C-START開發(fā)板試用體驗(yàn):GD32F330開發(fā)環(huán)境構(gòu)建
推薦閱讀最新更新時(shí)間:2025-06-12 15:45



設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦
- 神經(jīng)形態(tài)芯片可能是革新機(jī)器人實(shí)時(shí)電機(jī)控制的未來
- 從三個(gè)方面理解ARM嵌入式系統(tǒng)
- 自動(dòng)報(bào)警 基于MCU的家庭防盜報(bào)警系統(tǒng)的設(shè)計(jì)
- 存儲(chǔ)控制器及其訪問外設(shè)的原理
- 基于51系列單片機(jī)的智能照明控制系統(tǒng)設(shè)計(jì)方案
- 基于STM32的四旋翼飛行器控制系統(tǒng)
- 單片機(jī)應(yīng)用編程技巧解析
- 基于89C52的教室智能節(jié)能照明系統(tǒng)設(shè)計(jì)
- 一種新型的雨量光照傳感器的設(shè)計(jì)
- AD8532ARUZ 單電源、立體聲耳機(jī)驅(qū)動(dòng)器的典型應(yīng)用
- AD8546ARMZ-RL反相運(yùn)算放大器配置的典型應(yīng)用電路
- LT6656ACDC-5、5V 電壓基準(zhǔn)作為微功率穩(wěn)壓器的典型應(yīng)用
- 適用于STM32F042K6 MCU的STM32 Nucleo-32開發(fā)板,支持Arduino nano連接
- DN05113/D,采用 NCP786A 超高壓線性穩(wěn)壓器的電源參考設(shè)計(jì)
- LTC3867EUF 高效同步降壓控制器的典型應(yīng)用電路
- 擴(kuò)展塢
- LT4256-3 演示板,正電壓熱插拔控制器
- 適用于工業(yè)應(yīng)用的 C8051F540 MCU 的 C8051F540DK、8051 開發(fā)系統(tǒng)
- [Remix]FP6296核心,10A單鋰升壓快充模塊
- 超聲波液位計(jì)和雷達(dá)液位計(jì)有哪些不同
- 是德科技推出64GBd多模光電一體化模塊
- 昉?星光單板計(jì)算機(jī)正式發(fā)售,加速RISC-V生態(tài)發(fā)展
- 三星S20系列推送One UI 4.0正式版
- TD-SCDMA終端綜合測(cè)試儀功能特點(diǎn)及儀器物理層部分的軟硬件設(shè)計(jì)介紹
- 51單片機(jī)的靜態(tài)和動(dòng)態(tài)數(shù)碼管的顯示
- Diodes 公司推出 60V 額定同步降壓轉(zhuǎn)換器,提高汽車負(fù)載點(diǎn) (PoL) 產(chǎn)品應(yīng)用的效率
- GPT-15000系列電氣安全分析儀的應(yīng)用型號(hào)及特點(diǎn)分析
- 意法半導(dǎo)體推出先進(jìn)的 1600 V IGBT,面向高性價(jià)比節(jié)能家電市場(chǎng)
- EDPF-NT+分散控制系統(tǒng)網(wǎng)絡(luò)防護(hù)解決方案
- 基于PLC控制的易驅(qū)變頻器在布袋除塵器上的應(yīng)用
- 如何利用伺服自動(dòng)化實(shí)現(xiàn)成本降低和產(chǎn)能最大化?
- 壓力傳感器有哪些抗干擾措施?
- 破局!補(bǔ)盲dToF固態(tài)激光雷達(dá)輪番“出手”,禾賽FT120也要靠邊
- 利用正壓送風(fēng)壓力傳感器自動(dòng)控制火災(zāi)風(fēng)口壓力
- 多個(gè)傳感器間相互位置關(guān)系校準(zhǔn)方法
- 樓宇自控BA系統(tǒng)傳感器有哪些?
- 常見壓力傳感器工業(yè)原理匯總
- 挖角蘋果高級(jí)計(jì)算機(jī)視覺專家 Mapillary地圖更新添一員大將
- 瑞士研發(fā)L4級(jí)自動(dòng)駕駛卡車 “未來感”爆棚
- 第一批被AI累死的人
- 機(jī)器人打造的智能停車庫,我國(guó)的停車難問題將得到有效解決
- Bourns推出新型抗硫化固定電阻系列
- “和諧”升級(jí)“復(fù)興”萬億級(jí)市場(chǎng),且看他們?nèi)绾梧⒌妙^湯
- 人工智能、5G、無人駕駛……3月來e星球看未來電子行業(yè)發(fā)展
- 盤點(diǎn)近年應(yīng)用于汽車發(fā)動(dòng)機(jī)的新技術(shù)
- 汽車座艙交互方式迎來變革期,或成為人工智能發(fā)展創(chuàng)新突
- 分析2018年汽車電子行業(yè)前景及投資軌跡
- 玩具車上的小板,不能正常工作
- 關(guān)于在鄂爾多斯創(chuàng)立一個(gè)遙控玩具的生產(chǎn)基地的實(shí)踐
- 28335怎么實(shí)現(xiàn)float轉(zhuǎn)Uint16或者取整函數(shù)?
- 門電平模型化pdf文檔
- 急求啊!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- APP搜索不到 sensortile box是電池問題
- GD32L233C-START 開發(fā)板 學(xué)習(xí)筆記(五)
- 求助??!butterword低通濾波問題 。
- 【AutoChips AC7801x電機(jī)demo板測(cè)評(píng)】無感模式驅(qū)動(dòng)直流無刷電機(jī)
- EEWORLD大學(xué)堂----Wally Rhines - 2015 Phil Kaufman Award Winner