• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 60, 文章 - 0, 評論 - 197, 引用 - 0
            數(shù)據(jù)加載中……

            學(xué)習(xí) ARM 系列 -- FS2410 開發(fā)板上 Nand Flash 到內(nèi)存的代碼搬移

            一、目的
               前面做過一個實驗,搬移 Nand Flash 里的前 4k 代碼到內(nèi)存指定位置,這其實是把
            SRAM 從 0x40000000 開始的 4K 代碼復(fù)制到 SDRAM 的指定位置,并沒有涉及到對 Nand
            Flash 的操作。究其原因,開發(fā)板上電后,Nand Flash 開始的前 4K 數(shù)據(jù)會被自動復(fù)制到
            SRAM 0x40000000 開始的 4K 區(qū)域里,這個區(qū)域被稱為 "Steppingstone"。那我們這次就來
            操作 Nand Flash,讀取它 4K 后的代碼到 SDRAM 指定位置,并執(zhí)行 SDRAM 中的代碼。

            二、代碼
               通過前面做的幾個實驗,我們已經(jīng)熟悉了 ARM 開發(fā)的基本流程,這可以讓我們更關(guān)注于
            代碼的邏輯。好,先來分析文件 head.s:

               @ 文件 head.s
               @ 作用:關(guān)閉看門狗、SDRAM 的初始化設(shè)置、搬移 Nand Flash 4K 以后
               @ 的代碼到 SDRAM 的指定位置、執(zhí)行 SDRAM 中的代碼
               .text
               .global _start
               _start:
                ldr r0, =0x53000000 @ Close Watch Dog Timer
                mov r1, #0x0
                str r1, [r0]
              
                bl  memory_setup  @ Initialize memory setting
                bl  flash_to_sdram @ Copy code to sdram
                
                ldr sp, =0x34000000 @ Set stack pointer
                ldr pc, =main              @ execute the code in SDRAM
              

               @ 文件 mem.s
               @ 作用:SDRAM 的初始化設(shè)置
               @ 關(guān)于初始化的更多細(xì)節(jié),請參考我的前一篇隨筆
               .global memory_setup         @ 導(dǎo)出 memory_setup, 使其對鏈接器可見
               memory_setup:
                mov  r1, #0x48000000
                adrl r2, mem_cfg_val
                add  r3, r1, #13*4
               1: 
                @ write initial values to registers
                ldr  r4, [r2], #4
                str  r4, [r1], #4
                cmp  r1, r3
                bne  1b
                mov  pc, lr
                
                .align 4
               mem_cfg_val:
                .long 0x22111110 @ BWSCON
                .long 0x00000700 @ BANKCON0
                .long 0x00000700 @ BANKCON1
                .long 0x00000700 @ BANKCON2
                .long 0x00000700 @ BANKCON3
                .long 0x00000700 @ BANKCON4
                .long 0x00000700 @ BANKCON5
                .long 0x00018005 @ BANKCON6
                .long 0x00018005 @ BANKCON7 9bit
                .long 0x008e07a3 @ REFRESH
                .long 0x000000b2 @ BANKSIZE
                .long 0x00000030 @ MRSRB6
                .long 0x00000030 @ MRSRB7


               @ 文件 flash.s
               @ 作用:設(shè)置 Nand Flash 的控制寄存器、讀取 Nand Flash
               @ 中的代碼到 SDRAM 的指定位置
               .equ NFCONF, 0x4e000000
               .equ NFCMD,  0x4e000004
               .equ NFADDR, 0x4e000008
               .equ NFDATA, 0x4e00000c
               .equ NFSTAT, 0x4e000010
               .equ NFECC,  0x4e000014
               .global flash_to_sdram
               flash_to_sdram:
                    @ Save return addr
                    mov r10,lr
                
                    @ Initialize Nand Flash
                    mov r0,#NFCONF
                    ldr r1,=0xf830
                    str r1,[r0]
               
                    @ First reset and enable Nand Flash
                    ldr r1,[r0]
                    bic r1, r1, #0x800
                    str r1,[r0]
               
                    ldr r2,=NFCMD
                    mov r3,#0xff
                    str r3,[r2]
                
                    @ for delay
                    mov r3, #0x0a
               1:
                    subs r3, r3, #1
                    bne 1b
              
               @ Wait until Nand Flash bit0 is 1
               wait_nfstat:
                    ldr r2,=NFSTAT
                    ldr r3,[r2]
                    tst r3,#0x01
                    beq wait_nfstat
                      
                    @ Disable Nand Flash
                    ldr r0,=NFCONF
                    ldr r1,[r0]
                    orr r1,r1,#0x8000
                    str r1,[r0]
               
                    @ Initialzie stack
                    ldr sp,=4096
              
                    @ Set arguments and call 
                    @ function nand_read defined in nand_read.c
                    ldr r0,=0x30000000
                    mov r1,#4096
                    mov r2,#1024
                    bl nand_read
               
                    @ return
                    mov pc,r10


               /* 文件 nand_read.c
                * 作用:從 Nand Flash 中讀取一塊數(shù)據(jù)到 SDRAM 中的指定位置
                */
               #define NFCONF (*(volatile unsigned long *)0x4e000000)
               #define NFCMD  (*(volatile unsigned long *)0x4e000004)
               #define NFADDR (*(volatile unsigned long *)0x4e000008)
               #define NFDATA (*(volatile unsigned long *)0x4e00000c)
               #define NFSTAT (*(volatile unsigned long *)0x4e000010)
               #define NFECC  (*(volatile unsigned long *)0x4e000014)
              
               #define NAND_SECTOR_SIZE 512
               #define NAND_BLOCK_MASK  0x1ff
              
               void wait_idle() {
                 int i;
                 for (i = 0; i < 50000; ++i) ;
               }
              
               int nand_read(unsigned char *buf, unsigned long start_addr, int size){
                 int i, j;
                 /*
                  * detect the argument
                  */ 
                 if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
                   return -1;    
                 }
               
                 /* chip Enable */
                 NFCONF &= ~0x800;
                 for (i=0; i<10; i++) {
                   ;
                 }
               
                 for (i=start_addr; i < (start_addr + size); i+=NAND_SECTOR_SIZE) {
                   NFCMD = 0;
               
                   /* Write Address */
                   NFADDR = i & 0xff;
                   NFADDR = (i >> 9)  & 0xff;
                   NFADDR = (i >> 17) & 0xff;
                   NFADDR = (i >> 25) & 0xff;
               
                   wait_idle();
               
                   for(j=0; j < NAND_SECTOR_SIZE; j++) {
                     *buf++ = (NFDATA & 0xff);
                   }
                 }
               
                 NFCONF |= 0x800;    /* chip disable */
                 return 0;
               }

            注:Nand Flash 的設(shè)置和讀取數(shù)據(jù)的主要流程簡單介紹如下:
               1. NFCONF = 0xf830
               2. 在第一次操作NAND Flash前,通常復(fù)位一下:
                  NFCONF &= ~0x800 (使能NAND Flash)
                  NFCMD = 0xff (reset命令)
                  循環(huán)查詢NFSTAT位0,直到它等于1
               3. NFCMD = 0 (讀命令)
               4. 這步得稍微注意一下,請打開K9F1208U0M數(shù)據(jù)手冊第7頁,那個表格列出了在地址操
                  作的4個步驟對應(yīng)的地址線,A8沒用到:
                  NFADDR = addr & 0xff
                  NFADDR = (addr>>9) & 0xff (注意了,左移9位,不是8位)
                  NFADDR = (addr>>17) & 0xff (左移17位,不是16位)
                  NFADDR = (addr>>25) & 0xff (左移25位,不是24位)
               5. 循環(huán)查詢NFSTAT位0,直到它等于1
               6. 連續(xù)讀NFDATA寄存器512次,得到一頁數(shù)據(jù)(512字節(jié))
               7. NFCONF |= 0x800 (禁止NAND Flash)


               /* 文件 sdram.c
                * 作用:循環(huán)點 FS2410 開發(fā)板上的 D9、D10、D11、D12
                * 四個發(fā)光二極管。
                */
               #define GPFCON (*(volatile unsigned long *)0x56000050)
               #define GPFDAT (*(volatile unsigned long *)0x56000054)
              
               int main()
               {
                 int i,j;
                 while(1) {
                   for (i = 0; i <4; ++i) {
                     GPFCON = 0x1<<(8+i*2);
                     GPFDAT = 0x0;
              
                     // for delay
                     for(j=0;j<50000;++j) ;
                   }
                 }
               }


               /*
                * 文件 nand.lds (lds 文件是連接腳本)
                */
               SECTIONS {
                   first  0x00000000 : { head.o mem.o flash.o nand_read.o }
                   second 0x30000000 : AT(4096) { sdram.o }
               }
              
            注:這個鏈接腳本是用來傳給鏈接器的,其作用如下:
              1. 將 head.o 放在 0x00000000 開始的地址處, mem.o、flash.o、and_read.o
                 依次放在 head.o 后面, 它們的運行地址是 0x00000000
              2. 將 sdram.o 放在地址 4096 開始處, 但它的運行地址是 0x30000000, 運行前需要
                 從 4096 處復(fù)制到 SDRAM 的 0x300000000 處

            完整的連接腳本文件形式如下:
            SECTIONS {
            ...
            secname start BLOCK(align) (NOLOAD) : AT(ldadr) {contents} >region :phdr =fill
            ...
            }

            并非每個選項都是必須的,僅從 nand.lds 用到的來看:
            (1) secname: 段名,對于 nand.lds, 段名為 first 和 second
            (2) start: 本段的運行時地址,如果沒有 AT(xxx),則本段的存儲地址也是 start
            (3) AT(ldadr): 定義本段存儲(加載)的地址
            (4) {contents}: 決定哪些內(nèi)容放在本段,可以是整個目標(biāo)文件,也可是目標(biāo)文件中的某段


               # 文件 Makefile
               # 由代碼文件生成目標(biāo)文件,并依據(jù)連接腳本 nand.lds 連接目標(biāo)文件,
               # 最后將連接生成的目標(biāo)文件轉(zhuǎn)換成二進(jìn)制格式
               sdram:head.s flash.s mem.s sdram.c
                    arm-linux-gcc -c -o head.o head.s
                    arm-linux-gcc -c -o mem.o mem.s
                    arm-linux-gcc -c -o flash.o flash.s
                    arm-linux-gcc -c -o nand_read.o nand_read.c
                    arm-linux-gcc -c -o sdram.o sdram.c
                    arm-linux-ld  -Tnand.lds head.o mem.o flash.o nand_read.o sdram.o -o sdram_tmp.o
                    arm-linux-objcopy -O binary -S sdram_tmp.o sdram
               clean:
                    rm -f *.o
                    rm -f sdram

            三、編譯、燒寫、測試
            Make 一下就會生成我們要的文件 sdram, 將其通過 JTAG 燒入 Nand Flash ,Reset
            一下開發(fā)板, 呵呵,欣賞我們的成果吧!

            posted on 2008-01-06 21:43 Normandy 閱讀(4668) 評論(7)  編輯 收藏 引用 所屬分類: Embeded Area

            評論

            # re: 學(xué)習(xí) ARM 系列 -- FS2410 開發(fā)板上 Nand Flash 到內(nèi)存的代碼搬移  回復(fù)  更多評論   

            好東西,支持。最好在介紹一下abc.c文件及其作用。
            2008-01-06 22:02 | hukq

            # re: 學(xué)習(xí) ARM 系列 -- FS2410 開發(fā)板上 Nand Flash 到內(nèi)存的代碼搬移  回復(fù)  更多評論   

            LZ 強人呀!學(xué)習(xí)......
            2008-01-07 11:11 | kyle

            # re: 學(xué)習(xí) ARM 系列 -- FS2410 開發(fā)板上 Nand Flash 到內(nèi)存的代碼搬移  回復(fù)  更多評論   

            請教摟住:
            在用SJF2410燒寫程序的時候,如果我想把BOOT程序燒寫在0000H,MAIN程序燒寫在1000H處,而APPLY程序燒寫在2000H處,應(yīng)該如何操作??
            一定要燒寫三次才可以嗎?
            謝謝摟主
            2008-03-09 14:23 | 葫蘆瓜

            # re: 學(xué)習(xí) ARM 系列 -- FS2410 開發(fā)板上 Nand Flash 到內(nèi)存的代碼搬移  回復(fù)  更多評論   

            @葫蘆瓜
            有兩種思路:
            (1) 如果你編譯后生成三個二進(jìn)制程序, 可通過sjf2410 分三次將三個文件燒入 Nand Flash的不同位置, 具體請看 sjf2410.exe 的用法。
            (2) 如果你編譯后只生成一個二進(jìn)制文件, 即把 boot 、main 、apply 三個目標(biāo)文件連接成一個文件,可通過sjf2410 一次燒寫即可。要點是在連接時指定連接腳本。 連接腳本如下:

            SECTIONS {
            first 0x00000000 : { boot.o}
            second 0x00000000 : AT(4096) { main.o }
            third 0x00000000 : AT(8192) { apply.o }
            }

            然后在連接程序中這樣調(diào)用連接腳本:
            arm-linux-ld -Tnand.lds boot.o main.o apply.o -o prog_tmp.o
            arm-linux-objcopy -O binary -S prog_tmp.o prog


            2008-03-10 09:47 | Normandy

            # re: 學(xué)習(xí) ARM 系列 -- FS2410 開發(fā)板上 Nand Flash 到內(nèi)存的代碼搬移  回復(fù)  更多評論   

            如果從nand boot的話
            SRAM是從0-4096
            不是從0x40000000開始吧
            2008-08-08 01:00 |

            # re: 學(xué)習(xí) ARM 系列 -- FS2410 開發(fā)板上 Nand Flash 到內(nèi)存的代碼搬移[未登錄]  回復(fù)  更多評論   

            @毛
            實際上板子加電啟動時,SRAM 從 0x40000000 開始的 4096 字節(jié)區(qū)域被映射成 從 0x00000000 開始的 4096 字節(jié)區(qū)域, 手冊上有說明
            2008-08-11 13:06 | Normandy

            # re: 學(xué)習(xí) ARM 系列 -- FS2410 開發(fā)板上 Nand Flash 到內(nèi)存的代碼搬移  回復(fù)  更多評論   

            我是新手,想問個問題,就是你的這幾篇文章的程序可以使用串口或者USB下載到開發(fā)板嗎?如果行怎么下載,地址是多少,迫切的想知道,其他熱心的朋友也可以幫忙回答一下,謝謝!
            2008-10-28 16:20 | 李強
            一本色道久久88精品综合| 热99re久久国超精品首页| 久久精品国产99国产电影网| 伊人色综合久久天天人手人婷 | 国产精品久久久久影院色| 9久久9久久精品| 韩国免费A级毛片久久| 久久亚洲高清观看| 思思久久好好热精品国产| 国产精品美女久久久m| 999久久久免费国产精品播放| 精品久久久久久99人妻| 综合网日日天干夜夜久久| 国产99久久九九精品无码| 久久99久国产麻精品66| 久久精品免费观看| 久久久久久久综合狠狠综合| 国产精品久久网| 久久午夜伦鲁片免费无码| 精品一区二区久久| 一本久久a久久精品亚洲| 精品久久久久久无码国产| 久久狠狠高潮亚洲精品| 伊人久久大香线蕉无码麻豆| 久久免费线看线看| 亚洲精品蜜桃久久久久久| 久久亚洲精品无码观看不卡| 亚洲天堂久久精品| 99久久中文字幕| 久久成人国产精品二三区| 久久99亚洲网美利坚合众国| 国产精品美女久久久久AV福利| 久久精品国产亚洲精品2020| 亚洲精品tv久久久久久久久久| 精品久久久久久无码人妻蜜桃| 精品999久久久久久中文字幕| 久久久噜噜噜久久中文福利| 国内精品九九久久精品| 99久久精品免费观看国产| 青青草国产成人久久91网| 国产国产成人久久精品|