新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM開發步步深入之NandFlash 4KB突圍

        ARM開發步步深入之NandFlash 4KB突圍

        作者: 時間:2016-12-07 來源:網絡 收藏

          實驗目的:突破4KB的Steppingstone存儲空間限制,讀取NandFlash中4KB后的代碼實現“點燈大法”,借此掌握NandFlash的操作。

        本文引用地址:http://www.104case.com/article/201612/341245.htm

          實驗環境及說明:恒頤S3C2410開發板H2410。H2410核心板的NandFlash選用的是三星片上(SOP)K9F1208U0M,該NandFlash容量為64MB。

          實驗思路:開發板上電啟動后,自動將NandFlash開始的4K數據復制到SRAM中,然后跳轉到0地址開始執行。然后初始化存儲控制器SDRAM,調用NandFlash讀函數操作把4KB后的點燈代碼復制到SDRAM中,跳到點燈代碼的入口點實現點燈操作。

          知識掌握:NandFlash內部結構、命令字及存儲控制器

          一、NandFlash內部結構

          不同開發板使用的NandFlash的型號可能不一樣,本文只是以K9F1208U0M為例做個簡單介紹。引腳描述如下所示:

          '700')this.width='700';if(this.offsetHeight>'700')this.height='700';" src="http://www.arm79.com/attachment/Mon_1005/73_67_af4843899d603e0.jpg" onclick="if(this.width>=700) window.open('http://www.arm79.com/attachment/Mon_1005/73_67_af4843899d603e0.jpg');" border="0">

          NandFlash存儲單元結構圖如下所示:

          '700')this.width='700';if(this.offsetHeight>'700')this.height='700';" src="http://www.arm79.com/attachment/Mon_1005/73_67_b53cf1b5e09813b.jpg" onclick="if(this.width>=700) window.open('http://www.arm79.com/attachment/Mon_1005/73_67_b53cf1b5e09813b.jpg');" border="0" width="700">

          Device、 Block和Page之間的關系---1 Device = 4,096 Blocks = 4096*32 Pages = 128K Pages;1 Block = 32 Page;1 Page = 528 Byte = 512 Byte + 16 Byte。其中1 Page中包含有數據寄存器512 Byte和16 Byte的備用位用于ECC校驗存儲。所以有528 columns * 128K rows(Pages)。1 Page中的512 Byte的數據寄存器又分為兩個部分1st 256 Bytes和 2nd 256 Bytes。用于數據存儲的單元有 512 Bytes * 32 Pages * 4096 Blocks = 64 MB,用于ECC校驗單元有16 Bytes * 32 Pages * 4096 Blocks = 2MB 。

          二、NandFlash命令字

          操作NandFlash時,先傳輸命令,然后傳輸地址,最后進行數據的讀/寫。K9F1208U0M的命令字如下所示:

          '700')this.width='700';if(this.offsetHeight>'700')this.height='700';" src="http://www.arm79.com/attachment/Mon_1005/73_67_9f90461920e6b01.jpg" onclick="if(this.width>=700) window.open('http://www.arm79.com/attachment/Mon_1005/73_67_9f90461920e6b01.jpg');" border="0" width="700">

          由于尋址需要26bit的地址,該26bit地址通過四個周期發送到NandFlash,如下圖所示:

          '700')this.width='700';if(this.offsetHeight>'700')this.height='700';" src="http://www.arm79.com/attachment/Mon_1005/73_67_e8c052eed36f8b9.jpg" onclick="if(this.width>=700) window.open('http://www.arm79.com/attachment/Mon_1005/73_67_e8c052eed36f8b9.jpg');" border="0">

          Read 1操作:該操作是對512 Bytes * 32 Pages * 4096 Blocks = 64 M的數據寄存器進行尋址。第一個周期發送A7~A0的8bit Column地址,8bit的尋址范圍是0~255,只能對1st 256 Bytes部分進行尋址。00h命令是1st 256 Bytes部分尋址。當發送01h命令時,A8將會被置1,此時尋址范圍變成了256~511了,所以01h命令是對2nd 256 Bytes部分進行尋址。(*注意:A8在發送00h命令后被清0,在發送01h命令后被置1,并且在發送01h對2nd尋址完畢后,A8會自動清0,指 針會自動地指向1st);第二個周期的A9~A13的5bit是對Page進行尋址(因為1 Block = 32 Pages,5bit的尋址范圍是0~31,可以對1 Block里面的所有Page進行尋址)。A14~A25的12bit則是對Block進行尋址,12bit的尋址范圍是0~4095,對整個 Device的4096個Blocks進行尋址。Read 2操作:該操作是對16 Bytes * 32 Pages * 4096 Blocks =2MB的備用位(ECC)進行尋址。50h命令為Read2操作,對1 Page里面的后16 Byte尋址。這樣,通過四個周期的發送即可對整個Device的所有存儲單元進行尋址。

          三、NandFlash存儲控制器

          S3C2410 為簡化對NandFlash的操作,提供了一組NandFlash控制器來實現對K9F1208U0M命令字的操作,主要有配置寄存器NFCONF、控制 寄存器NFCONT、命令寄存器NFCMD、地址寄存器NFADDR、數據寄存器NFDATA和狀態寄存器NFSTAT。

          ★NFCONF被用來使 能/禁止NandFlash控制器、使能/禁止控制引腳信號nFCE、初始化ECC、設置NandFlash的時序參數。TACLS、TWRPH0、 TWRPH1---這三個參數控制著NandFlash信號線CLE/ALE與寫控制信號new的時序關系。根據NandFlash的Datasheet 中對其最小讀/寫/控制時間的要求,聯系HCLK實際取值一般為100MHz,可以設這三個參數分別為1:3:1個HCLK即可(貌似ViVi中是 1:3:1),這樣可以滿足其時序要求。

          ★NandFlash狀態寄存器NFSTAT。只用到最低位[0],0:busy;1:ready。

          NandFlash 存儲控制器根據OM[1:0]位的取值可以工作在①自動啟動模式---OM[1:0]=00時,復位之后,NandFlash的最先4KB的代碼被復制到 Steppingstone中即內部4KB的SRAM。Steppingstone被映射為Bank0(nGS0),且CPU在此4KB內部SRAM中開 始執行啟動代碼;②NandFlash模式。

          示例代碼解析:

          ★head.S頭文件來設置SDRAM,設置SDRAM,將第二部分代碼復制到SDRAM,然后跳到SDRAM繼續執行。

          .equ MEM_CTL_BASE, 0x48000000

          .text

          .global _start

          _start:

          bl disable_watch_dog @關門喂狗

          bl mem_control_setup @設置存儲控制器

          ldr sp, =4096 @設置棧指針,以下C函數調用前需要設好棧

          bl nand_init @初始化NandFlash

          @將NandFlash中地址4096開始的1024字節代碼(led.c編譯得到)復制到SDRAM中

          ldr r0, =0x30000000 @目標地址=0x30000000,SDRAM起始地址

          mov r1, #4096 @源地址=4096,連接的時候led代碼在4096開始處

          mov r2, #1024 @復制長度=1024,對于本實驗的led足夠

          bl nand_read @調用C函數nand_read

          ldr lr, =halt_loop @設置返回地址

          ldr sp, =0x34000000 @重新設置棧

          ldr pc, =main @使用向pc賦值的方法進行跳轉到點燈代碼

          halt_loop:

          b halt_loop

          ★nand.c文件實現NandFlash的初始化和數據讀取

          #define BUSY 1

          typedef unsigned long S3C2410_REG32; //貌似此處定義為unsigned int反匯編結果一樣的,也沒問題。猜可能是指令直接按32位存儲了吧,知道的可以和我說一下!

          /* NandFlash結構體 */

          typedef struct {

          S3C2410_REG32 NFCONF;

          ......

          S3C2410_REG32 NFECC;

          }S3C2410_NAND;

          static S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;

          /* 供外部調用的函數聲明 */

          void nand_init(void);

          void nand_read(unsigned char *buf, unsigned long start_addr, int size);

          /* S3C2410的NandFlash處理函數聲明 */

          static void s3c2410_nand_reset(void);

          ......

          static unsigned char s3c2410_read_data();

          /* S3C2410的NandFlash操作函數實現 */

          /* 復位 */

          static void s3c2410_nand_reset(void)

          {

          s3c2410_nand_select_chip();

          s3c2410_write_cmd(0xff); //發命令字0xFF實現復位操作復位

          s3c2410_wait_idle();

          s3c2410_nand_deselect_chip();

          }

          /* 等待NandFlash就緒 */

          static void s3c2410_wait_idle(void)

          {

          int i;

          volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFSTAT;

          while(!(*p & BUSY))

          for(i=0; i<10; i++);

          }

          /* 發出片選信號 */

          static void s3c2410_nand_select_chip(void)

          {

          int i;

          s3c2410nand->NFCONF &= ~(1<<11); //對NFCONF的11位寫0,激活NandFlash

          for(i=0; i<10; i++);

          }

          /* 取消片選信號 */

          static void s3c2410_nand_deselect_chip(void)

          {

          s3c2410nand->NFCONF |= (1<<11); //對NFCONF的11位寫1,使NandFlash不活動

          }

          /* 發出命令 */

          static void s3c2410_write_cmd(int cmd)

          {

          volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFCMD;

          *p = cmd;

          }

          /* 發出地址 */

          static void s3c2410_write_addr(unsigned int addr)

          {

          int i;

          volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->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++);

          }

          /* 讀取數據 */

          static unsigned char s3c2410_read_data(void)

          {

          volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFDATA;

          return *p;

          }

          //設置TACLS、TWRPH0、TWRPH1三者的值,貌似ViVi等代碼中TWRPH0設為3,不知這樣的好處,知道的可以告訴我!

          #define TACLS 0

          #define TWRPH0 2

          #define TWRPH1 0

          /* 初始化NandFlash */

          void nand_init(void)

          {

          /* 使能NandFlash控制器, 初始化ECC, 禁止片選, 設置時序 */

          s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);

          /* 復位s3c2410 NandFlash */

          s3c2410_nand_reset();

          }

          #define NAND_SECTOR_SIZE 512

          #define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)

          /* 讀函數 */

          void nand_read(unsigned char *buf, unsigned long start_addr, int size)

          {

          int i, j;

          if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {

          return ; /* 地址或長度不對齊 */

          }

          /* 選中芯片 */

          s3c2410_nand_select_chip();

          for(i=start_addr; i < (start_addr + size);) {

          /* 發出READ0命令 */

          s3c2410_write_cmd(0);

          /* 寫地址*/

          s3c2410_write_addr(i);

          /*等待*/

          s3c2410_wait_idle();

          for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {

          *buf = s3c2410_read_data();

          buf++;

          }

          }

          /* 取消片選信號 */

          s3c2410_nand_deselect_chip();

          return ;

          };



        關鍵詞: ARM NandFlash

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 彭州市| 临城县| 寻甸| 若尔盖县| 饶平县| 朝阳市| 凯里市| 鹿邑县| 上林县| 平度市| 武安市| 永仁县| 斗六市| 麻栗坡县| 乌什县| 宜宾县| 潮安县| 缙云县| 夹江县| 边坝县| 报价| 武义县| 莎车县| 丹巴县| 杭锦旗| 谢通门县| 革吉县| 安达市| 都江堰市| 明溪县| 富蕴县| 龙游县| 忻城县| 汽车| 陆丰市| 闽清县| 毕节市| 深水埗区| 宜阳县| 元江| 凤阳县|