成功在skyeye 上實現U-Boot 的Nand命令並從Nand中啟動Linux

來源:互聯網
上載者:User
http://www.linuxfans.org/bbs/thread-182694-1-1.html

1. 下載u-boot-1.1.4.tar.bz2,並解壓
2. 將arm-linux-2.95.3複製到/usr/local/arm/2.95.3/
3. 編輯u-boot跟目錄的Makefile檔案

include $(TOPDIR)/config.mk
CROSS_COMPILE=/usr/local/arm/2.95.3/bin/arm-linux-
ifndef CROSS_COMPILE

smdk2410_config : unconfig
    @./mkconfig $(@:_config=) arm arm920t smdk2410 NULL s3c24x0

sky2410_config : unconfig
    @./mkconfig $(@:_config=) arm arm920t sky2410 NULL s3c24x0

SX1_config :    unconfig
    @./mkconfig $(@:_config=) arm arm925t sx1
   
   
4. 複製必要的檔案
cp -arf board/smdk2410/ board/sky2410
mv board/sky2410/smdk2410.c board/sky2410/sky2410.c
cp include/configs/smdk2410.h include/configs/sky2410.h

5. 修改board/smdk2410/Makefile
LIB = lib$(BOARD).a

OBJS  := sky2410.o flash.o
SOBJS := lowlevel_init.o

6. make 測試一下
make sky2410_config
make
出現錯誤
cc1: Invalid option `abi=apcs-gnu'
修改檔案cpu/arm920t/config.mk
PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu)
改成:
PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,$(call cc-option,-mabi=apcs-gnu),)
再make成功

7. 開始移植nand
修改cpu/arm920t/start.S

將從Flash啟動改成從NAND Flash啟動。
將以下U-Boot的重新導向語句段:

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:                /* relocate U-Boot to RAM        */
    adr    r0, _start        /* r0 <- current position of code   */
    ldr    r1, _TEXT_BASE        /* test if we run from flash or RAM */
    cmp     r0, r1                 /* don't reloc during debug         */
    beq     stack_setup

    ldr    r2, _armboot_start
    ldr    r3, _bss_start
    sub    r2, r3, r2        /* r2 <- size of armboot            */
    add    r2, r0, r2        /* r2 <- source end address         */

copy_loop:
    ldmia    r0!, {r3-r10}        /* copy from source address [r0]    */
    stmia    r1!, {r3-r10}        /* copy to   target address [r1]    */
    cmp    r0, r2            /* until source end addreee [r2]    */
    ble    copy_loop
#endif    /* CONFIG_SKIP_RELOCATE_UBOOT */

替換成:

#ifdef CONFIG_S3C2410_NAND_BOOT
@ reset NAND
  mov r1, #NAND_CTL_BASE
  ldr   r2, =0xf830           @ initial value
  str   r2, [r1, #oNFCONF]
  ldr   r2, [r1, #oNFCONF]
  bic  r2, r2, #0x800              @ enable chip
  str   r2, [r1, #oNFCONF]
  mov r2, #0xff         @ RESET command
  strb r2, [r1, #oNFCMD]

  mov r3, #0                   @ wait
nand1:
  add  r3, r3, #0x1
  cmp r3, #0xa
  blt   nand1

nand2:
  ldr   r2, [r1, #oNFSTAT]      @ wait ready
  tst    r2, #0x1
  beq  nand2

  ldr   r2, [r1, #oNFCONF]
  orr  r2, r2, #0x800              @ disable chip
  str   r2, [r1, #oNFCONF]

@ get read to call C functions (for nand_read())
  ldr   sp, DW_STACK_START       @ setup stack pointer
  mov fp, #0                    @ no previous frame, so fp=0

@ copy U-Boot to RAM
  ldr   r0, =TEXT_BASE
  mov     r1, #0x0
  mov r2, #0x20000
  bl    nand_read_ll
  tst    r0, #0x0
  beq  ok_nand_read

bad_nand_read:
loop2:    b     loop2          @ infinite loop

ok_nand_read:
@ verify
  mov r0, #0
  ldr   r1, =TEXT_BASE
  mov r2, #0x400     @ 4 bytes * 1024 = 4K-bytes
go_next:
  ldr   r3, [r0], #4
  ldr   r4, [r1], #4
  teq   r3, r4
  bne  notmatch
  subs r2, r2, #4
  beq  stack_setup
  bne  go_next

notmatch:
loop3:     b     loop3         @ infinite loop

#endif /* CONFIG_S3C2410_NAND_BOOT */

在 “  _start_armboot:    .word start_armboot  ” 後加入:
    .align     2
DW_STACK_START:  .word  STACK_BASE+STACK_SIZE-4

8.
(I)修改board/smdk2410/Makefile
OBJS  := sky2410.o flash.o

(II)修改board/sky2410/lowlevel_init.S
#define UBLB      (0x1<<3)

#define B1_BWSCON     (DW16)
#define B2_BWSCON     (DW16)
#define B3_BWSCON     (DW16 + WAIT + UBLB)
#define B4_BWSCON     (DW16)

(III)建立board/smdk2410/nand_read.c檔案
#include <config.h>
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE  0x4e000000
#define NFCONF  __REGi(NF_BASE + 0x0)
#define NFCMD  __REGb(NF_BASE + 0x4)
#define NFADDR  __REGb(NF_BASE + 0x8)
#define NFDATA  __REGb(NF_BASE + 0xc)
#define NFSTAT  __REGb(NF_BASE + 0x10)
#define BUSY 1
inline void wait_idle(void) {
int i;
while(!(NFSTAT & BUSY))
for(i=0; i<10; i++);
}
/* low level nand read function */
int
nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
{
int i, j;
if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
return -1; /* invalid alignment */
}
/* chip Enable */
NFCONF &= ~0x800;
for(i=0; i<10; i++);
for(i=start_addr; i < (start_addr + size);) {
/* READ0 */
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++, i++) {
*buf = (NFDATA & 0xff);
buf++;
}
}
/* chip Disable */
NFCONF |= 0x800; /* chip disable */
return 0;
}

9.修改include/configs/sky2410.h
在檔案的後部添加
/*
 * Nandflash Boot
 */
#define CONFIG_S3C2410_NAND_BOOT 1
#define STACK_BASE    0x33f00000
#define STACK_SIZE    0x8000
//#define UBOOT_RAM_BASE    0x33f80000
/* NAND Flash Controller */
#define NAND_CTL_BASE            0x4E000000
#define bINT_CTL(Nb)        __REG(INT_CTL_BASE + (Nb))
/* Offset */
#define oNFCONF               0x00
#define oNFCMD                0x04
#define oNFADDR               0x08
#define oNFDATA               0x0c
#define oNFSTAT               0x10
#define oNFECC                0x14

10.
make 測試一下啊
到這裡 u-boot 已經可以從nand啟動了
下面我們對u-boot添加nand指令的支援

11. 修改include/configs/sky2410.h
(I)去掉CFG_CMD_NAND的注釋
#define CONFIG_COMMANDS /
      (CONFIG_CMD_DFL  | /
      CFG_CMD_CACHE  | /
      CFG_CMD_NAND   | /
      /*CFG_CMD_EEPROM |*/ /
      /*CFG_CMD_I2C  |*/ /
      /*CFG_CMD_USB  |*/ /
      CFG_CMD_REGINFO  | /
      CFG_CMD_DATE   | /
      CFG_CMD_ELF)

(II) 修改我們在第9步修改的內容
#define CFG_NAND_LEGACY
#define CFG_ENV_OFFSET  0X20000
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#define CFG_NAND_BASE 0x4E000000
/* NandFlash控制器在SFR區起始寄存器地址 */
#define CFG_MAX_NAND_DEVICE 1
 /* 支援的最在Nand Flash資料 */
#define SECTORSIZE 512
/* 1頁的大小 */
#define NAND_SECTOR_SIZE SECTORSIZE
#define NAND_BLOCK_MASK 511
/* 頁掩碼 */
#define ADDR_COLUMN 1
/* 一個位元組的Column地址 */
#define ADDR_PAGE 3
/* 3位元組的頁塊地址!!!!!*/
#define ADDR_COLUMN_PAGE 4
/* 總共4位元組的頁塊地址!!!!! */
#define NAND_ChipID_UNKNOWN 0x00
/* 未知晶片的ID號 */
#define NAND_MAX_FLOORS 1
#define NAND_MAX_CHIPS 1
/* Nand Flash命令層底層介面函數 */
#define WRITE_NAND_COMMAND(d, adr) {rNFCMD = d;}
#define WRITE_NAND_ADDRESS(d, adr) {rNFADDR = d;}
#define WRITE_NAND(d, adr) {rNFDATA = d;}
#define READ_NAND(adr) (rNFDATA)
#define NAND_WAIT_READY(nand) {while(!(rNFSTAT&(1<<0)));}
#define NAND_DISABLE_CE(nand) {rNFCONF |= (1<<11);}
#define NAND_ENABLE_CE(nand) {rNFCONF &= ~(1<<11);}
/* the following functions are NOP's because S3C24X0 handles this in hardware  一定要加上 */
#define NAND_CTL_CLRALE(nandptr)
#define NAND_CTL_SETALE(nandptr)
#define NAND_CTL_CLRCLE(nandptr)
#define NAND_CTL_SETCLE(nandptr)
/* 允許Nand Flash寫校正 */
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
/*
* Nandflash Boot
*/
#define CONFIG_S3C2410_NAND_BOOT 1
#define STACK_BASE    0x33f00000
#define STACK_SIZE    0x8000
//#define UBOOT_RAM_BASE    0x33f80000
/* NAND Flash Controller */
#define NAND_CTL_BASE            0x4E000000
#define bINT_CTL(Nb)        __REG(INT_CTL_BASE + (Nb))
/* Offset */
#define oNFCONF               0x00
#define oNFCMD                0x04
#define oNFADDR               0x08
#define oNFDATA               0x0c
#define oNFSTAT               0x10
#define oNFECC                0x14
#define rNFCONF (*(volatile unsigned int *)0x4e000000)
#define rNFCMD (*(volatile unsigned char *)0x4e000004)
#define rNFADDR (*(volatile unsigned char *)0x4e000008)
#define rNFDATA (*(volatile unsigned char *)0x4e00000c)
#define rNFSTAT (*(volatile unsigned int *)0x4e000010)
#define rNFECC (*(volatile unsigned int *)0x4e000014)
#define rNFECC0 (*(volatile unsigned char *)0x4e000014)
#define rNFECC1 (*(volatile unsigned char *)0x4e000015)
#define rNFECC2 (*(volatile unsigned char *)0x4e000016)
#endif /* CONFIG_COMMANDS & CFG_CMD_NAND*/

12. 修改 board/sky2410/sky2410.c
在檔案尾部添加
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
typedef enum {
NFCE_LOW,
NFCE_HIGH
} NFCE_STATE;

static inline void NF_Conf(u16 conf)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

nand->NFCONF = conf;
}

static inline void NF_Cmd(u8 cmd)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

nand->NFCMD = cmd;
}

static inline void NF_CmdW(u8 cmd)
{
NF_Cmd(cmd);
udelay(1);
}

static inline void NF_Addr(u8 addr)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

nand->NFADDR = addr;
}

static inline void NF_SetCE(NFCE_STATE s)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

switch (s) {
case NFCE_LOW:
nand->NFCONF &= ~(1<<11);
break;

case NFCE_HIGH:
nand->NFCONF |= (1<<11);
break;
}
}

static inline void NF_WaitRB(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

while (!(nand->NFSTAT & (1<<0)));
}

static inline void NF_Write(u8 data)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

nand->NFDATA = data;
}

static inline u8 NF_Read(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

return(nand->NFDATA);
}

static inline void NF_Init_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

nand->NFCONF |= (1<<12);
}

static inline u32 NF_Read_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

return(nand->NFECC);
}

#endif
/*

* NAND flash initialization.
*/
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
extern ulong nand_probe(ulong physadr);

static inline void NF_Reset(void)
{
int i;

NF_SetCE(NFCE_LOW);
NF_Cmd(0xFF); /* reset command */
for(i = 0; i < 10; i++); /* tWB = 100ns. */
NF_WaitRB(); /* wait 200~500us; */
NF_SetCE(NFCE_HIGH);
}

static inline void NF_Init(void)
{
#if 0 /* a little bit too optimistic */
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 0
#else
#define TACLS 0
#define TWRPH0 4
#define TWRPH1 2
#endif

NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0));
/*nand->NFCONF = (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); */
/* 1 1 1 1, 1 xxx, r xxx, r xxx */
/* En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 */

NF_Reset();
}

void
nand_init(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();

NF_Init();
#ifdef DEBUG
printf("NAND flash probing at 0x%.8lX/n", (ulong)nand);
#endif
printf ("%4lu MB/n", nand_probe((ulong)nand) >> 20);
}
#endif

現在我問對uboot的nand指令的修改也完成了

上面的步驟基本的在網上也能找到
但是,如果就真麼直接使用的話 skyeye1.2.4就會報錯

SMDK2410 # nand read 33000000 0 20000
NAND read: device 0 offset 0, size 131072 ... warning when RE  falling,do nothing
  0 bytes read: ERROR

最後花費一天的時間跟蹤 skyeye 和u-boot 終於找到錯誤的原因了

在u-boot讀取oob資料時
NanD_Command(nand, NAND_CMD_READOOB)
然後
NanD_Address(nand, ADDR_COLUMN_PAGE
這個時候 skyeye類比的nand就準備好資料了
其實直接就可以 READ_NAND (nandptr)了

但是在u-boot的NanD_ReadBuf函數中又發送了一次NanD_Command (nand, NAND_CMD_READ0);
結果skyeye就認為命令發生了改變 然後就開始等待NanD_Address(nand, ADDR_COLUMN_PAGE了
可是u-boot在發送NanD_Command (nand, NAND_CMD_READ0);後就直接開始讀取
skyeye 就認為是沒有發送地址然後就報錯了

最簡單的辦法就是吧NanD_ReadBuf中的NanD_Command (nand, NAND_CMD_READ0);這一行注釋掉

就沒有問題了~~
而且我也測試過將修改後的u-boot下載的我的開發板中 經過檢測沒有任何問題的

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.