青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 60, 文章 - 0, 評論 - 197, 引用 - 0
數據加載中……

學習 ARM 系列 -- FS2410 開發板上 Nand Flash 到內存的代碼搬移

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

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

   @ 文件 head.s
   @ 作用:關閉看門狗、SDRAM 的初始化設置、搬移 Nand Flash 4K 以后
   @ 的代碼到 SDRAM 的指定位置、執行 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 的初始化設置
   @ 關于初始化的更多細節,請參考我的前一篇隨筆
   .global memory_setup         @ 導出 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
   @ 作用:設置 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 中讀取一塊數據到 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 的設置和讀取數據的主要流程簡單介紹如下:
   1. NFCONF = 0xf830
   2. 在第一次操作NAND Flash前,通常復位一下:
      NFCONF &= ~0x800 (使能NAND Flash)
      NFCMD = 0xff (reset命令)
      循環查詢NFSTAT位0,直到它等于1
   3. NFCMD = 0 (讀命令)
   4. 這步得稍微注意一下,請打開K9F1208U0M數據手冊第7頁,那個表格列出了在地址操
      作的4個步驟對應的地址線,A8沒用到:
      NFADDR = addr & 0xff
      NFADDR = (addr>>9) & 0xff (注意了,左移9位,不是8位)
      NFADDR = (addr>>17) & 0xff (左移17位,不是16位)
      NFADDR = (addr>>25) & 0xff (左移25位,不是24位)
   5. 循環查詢NFSTAT位0,直到它等于1
   6. 連續讀NFDATA寄存器512次,得到一頁數據(512字節)
   7. NFCONF |= 0x800 (禁止NAND Flash)


   /* 文件 sdram.c
    * 作用:循環點 FS2410 開發板上的 D9、D10、D11、D12
    * 四個發光二極管。
    */
   #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 處復制到 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}: 決定哪些內容放在本段,可以是整個目標文件,也可是目標文件中的某段


   # 文件 Makefile
   # 由代碼文件生成目標文件,并依據連接腳本 nand.lds 連接目標文件,
   # 最后將連接生成的目標文件轉換成二進制格式
   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
一下開發板, 呵呵,欣賞我們的成果吧!

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

評論

# re: 學習 ARM 系列 -- FS2410 開發板上 Nand Flash 到內存的代碼搬移  回復  更多評論   

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

# re: 學習 ARM 系列 -- FS2410 開發板上 Nand Flash 到內存的代碼搬移  回復  更多評論   

LZ 強人呀!學習......
2008-01-07 11:11 | kyle

# re: 學習 ARM 系列 -- FS2410 開發板上 Nand Flash 到內存的代碼搬移  回復  更多評論   

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

# re: 學習 ARM 系列 -- FS2410 開發板上 Nand Flash 到內存的代碼搬移  回復  更多評論   

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

SECTIONS {
first 0x00000000 : { boot.o}
second 0x00000000 : AT(4096) { main.o }
third 0x00000000 : AT(8192) { apply.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: 學習 ARM 系列 -- FS2410 開發板上 Nand Flash 到內存的代碼搬移  回復  更多評論   

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

# re: 學習 ARM 系列 -- FS2410 開發板上 Nand Flash 到內存的代碼搬移[未登錄]  回復  更多評論   

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

# re: 學習 ARM 系列 -- FS2410 開發板上 Nand Flash 到內存的代碼搬移  回復  更多評論   

我是新手,想問個問題,就是你的這幾篇文章的程序可以使用串口或者USB下載到開發板嗎?如果行怎么下載,地址是多少,迫切的想知道,其他熱心的朋友也可以幫忙回答一下,謝謝!
2008-10-28 16:20 | 李強
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲在线成人| 亚洲午夜在线观看| 欧美激情第10页| 欧美怡红院视频| 欧美一区2区三区4区公司二百| 亚洲综合色在线| 久久成人一区| 久久精品国产综合精品| 久久精品在线免费观看| 蜜桃伊人久久| 亚洲清纯自拍| 99www免费人成精品| 日韩午夜一区| 午夜精品福利电影| 玖玖国产精品视频| 国产精品成人一区二区网站软件| 国产精品视频午夜| 在线日本高清免费不卡| 日韩小视频在线观看| 午夜一区二区三区不卡视频| 久久精品国产999大香线蕉| 免费看黄裸体一级大秀欧美| 亚洲美女视频在线观看| 欧美有码在线观看视频| 欧美精品日韩www.p站| 国产精品永久免费观看| 亚洲欧洲日本一区二区三区| 午夜精品短视频| 亚洲第一精品久久忘忧草社区| 亚洲精品乱码久久久久久久久| 午夜激情一区| 欧美精品aa| 韩国在线视频一区| 亚洲一卡二卡三卡四卡五卡| 久久久久欧美精品| 正在播放欧美视频| 欧美国产日韩免费| 激情欧美一区| 午夜精品久久| 亚洲精品国产精品乱码不99| 久久成人综合视频| 国产精品亚发布| 中文精品视频一区二区在线观看| 欧美xx69| 亚洲欧美日韩一区在线| 免费的成人av| 亚洲电影网站| 浪潮色综合久久天堂| 午夜激情亚洲| 国产欧美日韩精品专区| 亚洲性夜色噜噜噜7777| 亚洲国产网站| 免费中文字幕日韩欧美| 国产噜噜噜噜噜久久久久久久久| 亚洲美女精品一区| 久久婷婷国产综合国色天香| 午夜精品免费在线| 国产精品一区免费视频| 亚洲午夜电影网| 99国产欧美久久久精品| 欧美激情日韩| 一区二区三区久久精品| 亚洲精品永久免费| 欧美日韩国产综合视频在线观看中文 | 久久久精品国产99久久精品芒果| 在线视频你懂得一区二区三区| 欧美成人高清视频| 亚洲国产精品久久91精品| 麻豆乱码国产一区二区三区| 久久激五月天综合精品| 激情综合色丁香一区二区| 久久亚洲精品欧美| 狼狼综合久久久久综合网| 亚洲国产一二三| 亚洲黄色在线| 国产精品美女久久久| 亚洲女同同性videoxma| 亚洲伊人久久综合| 国产一区欧美| 欧美高清视频在线播放| 欧美激情中文不卡| 午夜精品偷拍| 久久这里只有精品视频首页| 91久久综合亚洲鲁鲁五月天| 亚洲精品少妇| 国产精品一区二区你懂的| 久久久一本精品99久久精品66| 久久久福利视频| 日韩视频在线一区二区| 中文欧美在线视频| 激情成人在线视频| 最新日韩欧美| 国产欧美精品一区二区色综合| 久久久天天操| 女人天堂亚洲aⅴ在线观看| 亚洲天堂偷拍| 久久精品人人做人人综合| 夜夜爽99久久国产综合精品女不卡| 亚洲视频成人| 亚洲人精品午夜| 亚洲综合日韩中文字幕v在线| 一区二区在线观看av| 日韩亚洲欧美一区| 一区二区自拍| 亚洲欧美成人网| 亚洲乱码精品一二三四区日韩在线 | 欧美一区二区成人| 亚洲乱码视频| 久久精品女人天堂| 亚洲欧美一区二区在线观看| 老巨人导航500精品| 欧美一区二区三区日韩视频| 欧美电影免费网站| 久久久噜噜噜久久久| 欧美日韩精品欧美日韩精品 | 亚洲精品乱码久久久久久| 国产在线观看精品一区二区三区 | 中文精品在线| 国产在线拍揄自揄视频不卡99| 亚洲欧洲在线一区| 曰韩精品一区二区| 欧美在线亚洲| 欧美一区二区三区在线观看视频| 欧美日韩大片一区二区三区| 欧美a级理论片| 国产日韩一区二区| 亚洲午夜一区二区三区| 99在线|亚洲一区二区| 另类av一区二区| 美女免费视频一区| 国产一区美女| 欧美亚洲免费高清在线观看| 亚洲欧美在线x视频| 欧美揉bbbbb揉bbbbb| 亚洲免费观看在线视频| 亚洲精品乱码久久久久久蜜桃91 | 国产精品五区| 亚洲一区二区三区免费观看| 亚洲线精品一区二区三区八戒| 欧美a级大片| 亚洲激情成人在线| 亚洲久色影视| 欧美久久久久免费| 99热在这里有精品免费| 亚洲一区亚洲二区| 国产精品久久久久久亚洲调教 | 欧美性一区二区| 亚洲视频一区在线| 午夜精品久久久99热福利| 国产精品国产一区二区| 亚洲视频一区二区免费在线观看| 亚洲视频在线一区| 国产精品久久久久毛片软件 | 欧美激情视频一区二区三区免费 | 欧美成人有码| 日韩一级片网址| 性欧美videos另类喷潮| 国产亚洲精品一区二555| 久久久精品午夜少妇| 亚洲高清二区| 亚洲一区精彩视频| 国产午夜精品福利| 农夫在线精品视频免费观看| 日韩视频在线一区二区三区| 亚洲综合精品一区二区| 国内偷自视频区视频综合| 快射av在线播放一区| 一区二区三区四区精品| 久久久蜜桃精品| 亚洲最新在线视频| 国产亚洲成av人在线观看导航| 久热精品视频在线观看| 一区二区不卡在线视频 午夜欧美不卡' | 夜夜嗨一区二区三区| 久久av一区| 亚洲毛片一区二区| 亚洲欧美成人一区二区在线电影| 久久亚洲私人国产精品va媚药| 亚洲三级观看| 国产小视频国产精品| 欧美成人中文字幕| 亚洲欧美日韩另类精品一区二区三区| 久久天天躁狠狠躁夜夜av| 一区二区高清| 在线电影国产精品| 国产精品国产成人国产三级| 羞羞答答国产精品www一本| 欧美第一黄色网| 欧美在线视频a| 国产亚洲一区二区在线观看| 欧美日本一道本在线视频| 先锋影音国产一区| 99re视频这里只有精品| 欧美国产乱视频| 久久久91精品| 亚洲一区制服诱惑| 亚洲乱码精品一二三四区日韩在线| 国产亚洲日本欧美韩国| 欧美风情在线| 免费视频亚洲|