u-boot移植(九)---代碼修改---NAND

1、NAND原理

  

  NAND 無地址空間,地址和數據的發送都依賴於LDATA[0:7]這一串數據總線。linux

  

   不看隨機頁編程,看到從高位到低位的頁,總共分爲64個頁面,每一個頁的組成是2K + 64  個byte,一個塊的大小是(128K + 4K)byte,64頁組成一塊。編程

1.1 NAND Flash的編址

  nand flash的的頁的大小是(2048 + 64)byte,64這個數據是不參與編址的。函數

  訪問 nand flash:工具

    • 發出命令:讀、寫、擦除
    • 發出地址
    • 傳輸數據

   命令設置以下:ui

  

1.2 nand flash的訪問

  

  能夠看看上面的模式選擇,而後對應引腳進行操做,就能夠進行讀寫操做。命令和數據就經過這些引腳來進行操做。可是沒必要直接操做這些引腳,能夠經過寄存器來進行操做。this

  查看S3C2440的手冊,能夠看到以下的信息:spa

  

  寫命令寄存器就至關於NAND Flash寄存器命令週期,寫地址寄存器就至關於NAND Flash寄存器的地址週期......code

   咱們的NAND Flash是X8的,便是8位NAND Flash,對應2440上面的一些控制寄存器:blog

  NAND Flash命令寄存器:內存

  

  地址寄存器:

  

  數據寄存器:

  

  狀態寄存器:

  

  還有一些其餘寄存器是與讀寫有關的。

  操做這些寄存器,2440會自動驅動PIN腳給出信號。

2、u-boot中設置nand啓動

2.1 創建init.c

  這是NAND啓動的初始化文件,裏面包含了nand啓動的初始化函數。代碼添加到 borad/samdung/jz2440/ 目錄下:

 1 /* NAND FLASH控制器 */
 2 #define NFCONF (*((volatile unsigned long *)0x4E000000))
 3 #define NFCONT (*((volatile unsigned long *)0x4E000004))
 4 #define NFCMMD (*((volatile unsigned char *)0x4E000008))
 5 #define NFADDR (*((volatile unsigned char *)0x4E00000C))
 6 #define NFDATA (*((volatile unsigned char *)0x4E000010))
 7 #define NFSTAT (*((volatile unsigned char *)0x4E000020))
 8 
 9 /* GPIO */
 10 #define GPHCON              (*(volatile unsigned long *)0x56000070)
 11 #define GPHUP               (*(volatile unsigned long *)0x56000078)
 12 
 13 /* UART registers*/
 14 #define ULCON0              (*(volatile unsigned long *)0x50000000)
 15 #define UCON0               (*(volatile unsigned long *)0x50000004)
 16 #define UFCON0              (*(volatile unsigned long *)0x50000008)
 17 #define UMCON0              (*(volatile unsigned long *)0x5000000c)
 18 #define UTRSTAT0            (*(volatile unsigned long *)0x50000010)
 19 #define UTXH0               (*(volatile unsigned char *)0x50000020)
 20 #define URXH0               (*(volatile unsigned char *)0x50000024)
 21 #define UBRDIV0             (*(volatile unsigned long *)0x50000028)
 22 
 23 #define TXD0READY   (1<<2)
 24 
 25 
 26 void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len);  27 
 28 /* 斷定是不是nor啓動 */
 29 static int isBootFromNorFlash(void)  30 {  31     volatile int *p = (volatile int *)0;  32     int val;  33 
 34     val = *p;  35     *p = 0x12345678;  36     if (*p == 0x12345678)  37  {  38         /* 寫成功, 是nand啓動 */
 39         *p = val;  40         return 0;  41  }  42     else
 43  {  44         /* NOR不能像內存同樣寫 */
 45         return 1;  46  }  47 }  48 
 49 /* 拷貝代碼到sdram */
 50 void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)  51 {  52     int i = 0;  53     
 54     /* 若是是NOR啓動 */
 55     if (isBootFromNorFlash())  56  {  57         while (i < len)  58  {  59             dest[i] = src[i];  60             i++;  61  }  62  }  63     else
 64  {  65         //nand_init();
 66         nand_read_ll((unsigned int)src, dest, len);  67  }  68 }  69 
 70 /* 清除BSS */
 71 void clear_bss(void)  72 {  73     extern int __bss_start, __bss_end;  74     int *p = &__bss_start;  75     
 76     for (; p < &__bss_end; p++)  77         *p = 0;  78 }  79 
 80 /* nand初始化 */
 81 void nand_init_ll(void)  82 {  83 #define TACLS   0
 84 #define TWRPH0  1
 85 #define TWRPH1  0
 86     /* 設置時序 */
 87     NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);  88     /* 使能NAND Flash控制器, 初始化ECC, 禁止片選 */
 89     NFCONT = (1<<4)|(1<<1)|(1<<0);  90 }  91 
 92 static void nand_select(void)  93 {  94     NFCONT &= ~(1<<1);  95 }  96 
 97 static void nand_deselect(void)  98 {  99     NFCONT |= (1<<1); 100 } 101 
102 static void nand_cmd(unsigned char cmd) 103 { 104     volatile int i; 105     NFCMMD = cmd; 106     for (i = 0; i < 10; i++); 107 } 108 
109 static void nand_addr(unsigned int addr) 110 { 111     unsigned int col  = addr % 2048; 112     unsigned int page = addr / 2048; 113     volatile int i; 114 
115     NFADDR = col & 0xff; 116     for (i = 0; i < 10; i++); 117     NFADDR = (col >> 8) & 0xff; 118     for (i = 0; i < 10; i++); 119     
120     NFADDR  = page & 0xff; 121     for (i = 0; i < 10; i++); 122     NFADDR  = (page >> 8) & 0xff; 123     for (i = 0; i < 10; i++); 124     NFADDR  = (page >> 16) & 0xff; 125     for (i = 0; i < 10; i++); 126 } 127 
128 static void nand_wait_ready(void) 129 { 130     while (!(NFSTAT & 1)); 131 } 132 
133 static unsigned char nand_data(void) 134 { 135     return NFDATA; 136 } 137 
138 void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len) 139 { 140     int col = addr % 2048; 141     int i = 0; 142         
143     /* 1. 選中 */
144  nand_select(); 145 
146     while (i < len) 147  { 148         /* 2. 發出讀命令00h */
149         nand_cmd(0x00); 150 
151         /* 3. 發出地址(分5步發出) */
152  nand_addr(addr); 153 
154         /* 4. 發出讀命令30h */
155         nand_cmd(0x30); 156 
157         /* 5. 判斷狀態 */
158  nand_wait_ready(); 159 
160         /* 6. 讀數據 */
161         for (; (col < 2048) && (i < len); col++) 162  { 163             buf[i] = nand_data(); 164             i++; 165             addr++; 166  } 167         
168         col = 0; 169  } 170 
171     /* 7. 取消選中 */        
172  nand_deselect(); 173 }

  修改 borad/samdung/jz2440/ 目錄下的 makefile:

  

2.2 去掉代碼重定位

  去掉 -pie 選項:

  

  註釋掉第82行:

  

2.3 修改代碼連接地址

  Jz2440.h (include\configs) 

  

2.4 修改連接腳本文件

  U-boot.lds (arch\arm\cpu) 連接腳本的修改,本版本u-boot將一個文件夾下面的c文件都連接成一個.o文件,名字爲built-in.o,因此咱們直接寫上built-in.o便可。

  

  

  將這兩個built-in.o放入連接腳本當中:

  

2.5 修改 board_init_f

  在crt0.S中設置nand 啓動的代碼:

  

  這一段代碼就是 nand 重定位代碼了。CONFIG_SYS_TEXT_BASE 是本身設置的,能夠自行設置大小。

  接下來的代碼就是跳轉到 board_init_f_mem 和 board_init_f 中執行初始化。

   init_sequence_f 鏈表中要註釋掉下面兩行,並更改:

  

2.6 修改重定位代碼

  首先在board_init_f(Board_f.c (common) )添加返回函數:

  

 1 unsigned int board_init_f(ulong boot_flags)  2 {  3 
 4     gd->flags = boot_flags;  5     gd->have_console = 0;  6 
 7     if (initcall_run_list(init_sequence_f))  8  hang();  9 #if 0 10 #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \ 11 !defined(CONFIG_EFI_APP) 12 /* NOTREACHED - jump_to_copy() does not return */ 13 hang(); 14 #endif 15 #endif
16     return (unsigned int)(gd->new_gd);  //添加的返回值,返回id供 board_init_r調用 17 }

  board_init_f 函數原型記得在 include/common中也修改。

  修改crt0.S 代碼以下:

ENTRY(_main) /* * Set up initial C runtime environment and call board_init_f(0). * 初始化C運行環境而且調用 board_init_f(0) 函數 */

 /* * 初始化棧地址 */
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) ldr sp, =(CONFIG_SPL_STACK) #else
    /* Generic-asm-offsets.h (include\generated) * #define GENERATED_GBL_DATA_SIZE 192 * JZ2440.h(include\config) * #define PHYS_SDRAM_1 0x30000000 * #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 * #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE) * * CONFIG_SYS_INIT_SP_ADDR = 0x30000000 + 0x1000 - 192(0xc0) = 0x30000f40 */ ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)        /* 設置CFIG_SYS_INIT_SP_ADDR定義的地址,include/configs/jz2440.h中定義 */
#endif
#if defined(CONFIG_CPU_V7M)    /* v7M forbids using SP as BIC destination */ mov r3, sp bic r3, r3, #7 mov sp, r3 #else
    /* sp 的8字節對齊 */ bic sp, sp, #7    /* 8-byte alignment for ABI compliance */
#endif
 /* 設置nand 啓動 */ bl nand_init_ll /* 跳轉到borad/samsung/jz2440/init.c 中執行 nand_init_ll 函數 */ mov r0, #0 ldr r1, =(CONFIG_SYS_TEXT_BASE) /*CONFIG_SYS_TEXT_BASE=0x33f00000 程序的連接地址*/ ldr r2, =0x100000 /* 程序大小 */ bl copy_code_to_sdram /* 拷貝代碼到SDRAM */ bl clear_bss /* 清除bss */ ldr pc, =call_board_init_f            /* 執行第一階段初始化 */ bl call_board_init_r /* 執行第二階段代碼 */ adr lr, here /*設置返回地址爲下面的here,重定位到sdram後返回here運行*/ ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off 取重定位地址偏移值 */ add lr, lr, r0 /*返回地址加偏移地址等於重定位後在sdram中的here地址*/ here: /*返回後跳到sdram中運行 */ /* * now relocate vectors */ bl relocate_vectors /* Set up final (full) environment */ bl c_runtime_cpu_setup /* we still call old routine here */ call_board_init_f: mov r0, sp /* r0 = sp */ bl board_init_f_mem /*跳轉到 board_init_f_mem 執行*/ mov sp, r0 mov r0, #0 bl board_init_f /* 調用單板的初始化函數,跳轉到 borad_init_f 處執行 */ call_board_init_r: ldr r1, =CONFIG_SYS_TEXT_BASE /* call board_init_r */ bl board_init_r /* this is auto-relocated! */ ENDPROC(_main)

  here的代碼必定不能註釋掉,註釋掉後就啓動不了

2.7 去掉-pie選項

  以下圖:

  

  

 3、編譯燒寫

  make CROSS_COMPILE=arm-2440-linux-gnueabi-

  

  生成的 u-boot.bin 有470K 左右。

  而後經過jtag 工具直接燒寫進nand 的  0地址中,撥碼開關撥到 nand 啓動,顯示以下:

  

相關文章
相關標籤/搜索