nand flash按照我的理解,在開發(fā)板上就類似我們所用的電腦中的硬盤,用來保存系統(tǒng)運行的操作系統(tǒng),應用程序,數(shù)據(jù)等,掉電之后還可以永久得保存數(shù)據(jù)(不包括臨時數(shù)據(jù))。通過控制或配置NAND Flash的控制器寄存器,即可完成對nand的操作:包括讀、寫、擦除等。
恩陽ssl適用于網(wǎng)站、小程序/APP、API接口等需要進行數(shù)據(jù)傳輸應用場景,ssl證書未來市場廣闊!成為成都創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:028-86922220(備注:SSL證書合作)期待與您的合作!而控制、配置這些寄存器是根據(jù)板子的原理圖、用戶手冊以及nand flash芯片手冊上的說明來配置的。
通過原理圖,可見nand flash與cpu之間的數(shù)據(jù)傳輸主要是通過LDDATA0~7這8根引腳線,其中傳輸?shù)摹皵?shù)據(jù)”可以是地址、數(shù)據(jù),也可以是命令,這就要靠CLE、ALE引腳的狀態(tài)進行選擇。
對于命令的傳輸,主要是對NFCMD寄存器寫以上相對應的命令值,但這個命令是分兩個周期進行的。
而對于數(shù)據(jù)的傳輸,在數(shù)據(jù)傳輸模式下,傳輸數(shù)據(jù)也是要根據(jù)以上的格式去進行傳輸,分5個周期,每一個周期傳輸?shù)臄?shù)據(jù)都十分講究,這就要求要有一個符合這種格式的巧妙算法(在接下來的代碼中體現(xiàn))。
了解了這些命令、數(shù)據(jù)的傳輸格式之后,就是要對具體的寄存器進行相應的配置了。首先要介紹這些寄存器的作用(數(shù)據(jù)手冊上對各寄存器都有說明):
(1)NFCONF:用來設置時序參數(shù),設置位寬。
(2)NFCMD:命令寄存器。
(3)NFADDR:地址寄存器。
(4)NFDATA:數(shù)據(jù)寄存器,用于讀寫數(shù)據(jù)。
(5)NFSTAT:狀態(tài)寄存器,只用到最低1位,表示是否忙碌。
編程舉例:
實現(xiàn)從nand flash中拷貝程序到sdram中運行,其中涉及到啟動代碼的編程,初始化內(nèi)存控制器,讀取并拷貝nand flash上的數(shù)據(jù)。(只展示部分核心代碼)
head.S
.text .global _start _start: ldr sp,=4096 @設置堆棧 bl disable_watch_dog @關閉看門狗 bl set_mem @設置內(nèi)存控制器 bl nand_init @nand初始化 ldr r0,=0x30000000 ldr r1,=4096 ldr r2,=4096 @傳遞參數(shù) bl nand_read @從nand中拷貝 ldr sp,=0x38000000 ldr lr, =halt @設置返回地址 ldr pc, =main halt: b halt
nand.c
typedef struct s3c2440_nand { unsigned int NFCONF; unsigned int NFCONT; unsigned int NFCMMD; unsigned int NFADDR; unsigned int NFDATA; unsigned int NFMECCD0; unsigned int NFMECCD1; unsigned int NFSECCD; unsigned int NFSTAT; unsigned int NFESTAT0; unsigned int NFESTAT1; unsigned int NFMECC0; unsigned int NFMECC1; unsigned int NFSECC; unsigned int NFSBLK; unsigned int NFEBLK; }s3c2440_nand; //定義nandflash控制器的起始地址 static s3c2440_nand* nand_base = (s3c2440_nand*)0x4E000000; //片選 void select_chip_or_not(int flag)//0不片選,1片選 { if(flag == 1) { nand_base->NFCONT |= (0x1<<1); } if(flag == 0) { nand_base->NFCONT &= ~(0x1<<1); } } void write_command(unsigned char cmd) { volatile unsigned char *p = (volatile unsigned char *)&nand_base->NFCMMD; *p = cmd; } void write_addr(unsigned int addr) { int i; volatile unsigned char* p = (volatile unsigned char *)nand_base->NFADDR; *p = addr & 0xff; for(i=0; i<10; i++); *p = (addr >> 9) & 0xff; for(i=0; i<10; i++); *p = (addr >> 17) & 0xff; for(i=0; i<10; i++); *p = (addr >> 25) & 0xff; for(i=0; i<10; i++); } //等待nand flash就緒 void wait_ldle(void) { volatile unsigned char* p = (volatile unsigned char*)nand_base->NFSTAT; int flag = *p & 1; while(!flag) { int i; for(i=0;i<20;i++); } } unsigned char read_data(void) { volatile unsigned char *p= (volatile unsigned char*)nand_base->NFDATA; return *p; } void nand_read(unsigned char* buf,unsigned char base_addr,unsigned int size) { int i,j; //片選 select_chip_or_not(1); //復制數(shù)據(jù) for(i=base_addr;iNFCONF = (0<<12)|(3<<8)|(0<<4); nand_base->NFCONT = (1<<4)|(1<<1)|(1<<0); nand_reset(); }
還要說下Makefile
objs := head.o init.o nand.o main.o nand.bin : $(objs) arm-linux-ld -Tnand.lds $^ -o nand_elf arm-linux-objcopy -O binary -S nand_elf $@ %.o : %.S arm-linux-gcc -c $< -o $@ %.o : %.c arm-linux-gcc -c $< -o $@ clean : rm -f nand.bin *.o nand_elf
平時寫的Makefile不一樣,這里使用了一個名為nand.lds的鏈接腳本,這樣做主要是為了試驗讓編譯好的程序在鏈接時存放的地址和理論運行地址都不同且不在同一個存儲設備上,方便看試驗效果。
nand.lds
SECTIONS { first 0x00000000 : {head.o init.o nand.o} second 0x30000000 : AT(4096) {main.o} }
鏈接腳本上的第一段是放head.S init.c nand.c編譯出的內(nèi)容,從0地址開始存放和執(zhí)行,而main.o則是需要從nand flash手動復制到sdram中去執(zhí)行。
實現(xiàn)的效果如圖:
創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國云服務器,動態(tài)BGP最優(yōu)骨干路由自動選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡助力業(yè)務部署。公司持有工信部辦法的idc、isp許可證, 機房獨有T級流量清洗系統(tǒng)配攻擊溯源,準確進行流量調(diào)度,確保服務器高可用性。佳節(jié)活動現(xiàn)已開啟,新人活動云服務器買多久送多久。