【Linux 移植 】——4、移植 u-boot-2012.04.01 之 支持NAND启动

时间:2022-09-27 16:34:54

三、移植 u-boot-2012.04.01 之 支持NAND启动

需要进行修改和添加的文件:

1、添加的文件:init.c   包含NAND Flash 的相关配置

 board/samsung/smdk2440目录, 修改Makefile

2、需要修改的文件:

a、去掉-pie选项,修改arch/arm/config.mk

b、start.S

c、smdk2440.h

d、common.h

e、board.c

f、arch/arm/cpu/u-boot.lds  


1、添加的文件:init.c 

init.c 代码如下:

/* NAND FLASH控制器 */
#define NFCONF (*((volatile unsigned long *)0x4E000000))
#define NFCONT (*((volatile unsigned long *)0x4E000004))
#define NFCMMD (*((volatile unsigned char *)0x4E000008))
#define NFADDR (*((volatile unsigned char *)0x4E00000C))
#define NFDATA (*((volatile unsigned char *)0x4E000010))
#define NFSTAT (*((volatile unsigned char *)0x4E000020))

/* GPIO */
#define GPHCON (*(volatile unsigned long *)0x56000070)
#define GPHUP (*(volatile unsigned long *)0x56000078)

/* UART registers*/
#define ULCON0 (*(volatile unsigned long *)0x50000000)
#define UCON0 (*(volatile unsigned long *)0x50000004)
#define UFCON0 (*(volatile unsigned long *)0x50000008)
#define UMCON0 (*(volatile unsigned long *)0x5000000c)
#define UTRSTAT0 (*(volatile unsigned long *)0x50000010)
#define UTXH0 (*(volatile unsigned char *)0x50000020)
#define URXH0 (*(volatile unsigned char *)0x50000024)
#define UBRDIV0 (*(volatile unsigned long *)0x50000028)

#define TXD0READY (1<<2)

void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len);

static int isBootFromNorFlash(void)
{
volatile int *p = (volatile int *)0;
int val;

val = *p;
*p = 0x12345678;
if (*p == 0x12345678)
{
/* 写成功, 是nand启动 */
*p = val;
return 0;
}
else
{
/* NOR不能像内存一样写 */
return 1;
}
}

void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
{
int i = 0;

/* 如果是NOR启动 */
if (isBootFromNorFlash())
{
while (i < len)
{
dest[i] = src[i];
i++;
}
}
else
{
//nand_init();
nand_read_ll((unsigned int)src, dest, len);
}
}

void clear_bss(void)
{
extern int __bss_start, __bss_end__;
int *p = &__bss_start;

for (; p < &__bss_end__; p++)
*p = 0;
}

void nand_init_ll(void)
{
#define TACLS 0
#define TWRPH0 1
#define TWRPH1 0
/* 设置时序 */
NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
/* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
NFCONT = (1<<4)|(1<<1)|(1<<0);
}

static void nand_select(void)
{
NFCONT &= ~(1<<1);
}

static void nand_deselect(void)
{
NFCONT |= (1<<1);
}

static void nand_cmd(unsigned char cmd)
{
volatile int i;
NFCMMD = cmd;
for (i = 0; i < 10; i++);
}

static void nand_addr(unsigned int addr)
{
unsigned int col = addr % 2048;
unsigned int page = addr / 2048;
volatile int i;

NFADDR = col & 0xff;
for (i = 0; i < 10; i++);
NFADDR = (col >> 8) & 0xff;
for (i = 0; i < 10; i++);

NFADDR = page & 0xff;
for (i = 0; i < 10; i++);
NFADDR = (page >> 8) & 0xff;
for (i = 0; i < 10; i++);
NFADDR = (page >> 16) & 0xff;
for (i = 0; i < 10; i++);
}

static void nand_wait_ready(void)
{
while (!(NFSTAT & 1));
}

static unsigned char nand_data(void)
{
return NFDATA;
}

void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len)
{
int col = addr % 2048;
int i = 0;

/* 1. 选中 */
nand_select();

while (i < len)
{
/* 2. 发出读命令00h */
nand_cmd(0x00);

/* 3. 发出地址(分5步发出) */
nand_addr(addr);

/* 4. 发出读命令30h */
nand_cmd(0x30);

/* 5. 判断状态 */
nand_wait_ready();

/* 6. 读数据 */
for (; (col < 2048) && (i < len); col++)
{
buf[i] = nand_data();
i++;
addr++;
}

col = 0;
}

/* 7. 取消选中 */
nand_deselect();
}

同时在 board/samsung/smdk2440目录, 修改Makefile

Makefile:28: COBJS:= smdk2440.o init.o 



2、需要修改的文件:

a、去掉-pie选项,不需要附加“*(.rel*)”、“*(.dynsm)”等信息

命令:grep "\-pie" * -nR
arch/x86/config.mk:43:LDFLAGS_FINAL += --gc-sections -pie
arch/arm/config.mk:75:LDFLAGS_u-boot += -pie
doc/README.arm-relocation:3:At arch level: add linker flag -pie

然后输入命令: vim arch/arm/config.mk

去掉/config.mk去掉75行LDFLAGS_u-boot += -pie


b、修改start.S  参考以前写的start.S 修改代码

前一篇我们对u-boot 进行了时钟、SDRAM 以及串口的相关设定;这一篇的目的是要让u-boot 支持NAND 启动。

在进行是时钟设定之后需要对重定向的代码进行修改:

        ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)	
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

/* 重定位 : 把bootloader本身的代码从flash复制到它的链接地址去 */
bl nand_init_ll
mov r0, #0
ldr r1, _TEXT_BASE
ldr r2, _bss_start_ofs
bl copy_code_to_sdram
bl clear_bss
ldr pc, = board_init_f

/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:

ldr r0,=0x00000000
bl board_init_f


ldr r1, _TEXT_BASE
bl board_init_r

同时对将CONFIG_SYS_TEXT_BASE修改为0x33f80000

 自己写了重定位,就去掉它写的重定位函数
    注释掉掉board.c中board_init_f中//relocate_code(addr_sp, id, addr);
    删掉start.S中下面不需要的代码

  1. /*------------------------------------------------------------------------------*/  
  2.   
  3. /*  
  4.  * void relocate_code (addr_sp, gd, addr_moni)  
  5.  *  
  6.  * This "function" does not return, instead it continues in RAM  
  7.  * after relocating the monitor code.  
  8.  *  
  9.  */  
  10.     .globl  relocate_code  
  11. relocate_code:  
  12.     mov r4, r0  /* save addr_sp */  
  13.     mov r5, r1  /* save addr of gd */  
  14.     mov r6, r2  /* save addr of destination */  
  15.   
  16.     /* Set up the stack                         */  
  17. stack_setup:  
  18.     mov sp, r4  
  19.   
  20.     adr r0, _start  
  21.     cmp r0, r6  
  22.     moveq   r9, #0      /* no relocation. relocation offset(r9) = 0 */  
  23.     beq clear_bss       /* skip relocation */  
  24.     mov r1, r6          /* r1 <- scratch for copy_loop */  
  25.     ldr r3, _bss_start_ofs  
  26.     add r2, r0, r3      /* r2 <- source end address      */  
  27.   
  28. copy_loop:  
  29.     ldmia   r0!, {r9-r10}       /* copy from source address [r0]    */  
  30.     stmia   r1!, {r9-r10}       /* copy to   target address [r1]    */  
  31.     cmp r0, r2          /* until source end address [r2]    */  
  32.     blo copy_loop  
  33.   
  34. #ifndef CONFIG_SPL_BUILD  
  35.     /*  
  36.      * fix .rel.dyn relocations  
  37.      */  
  38.     ldr r0, _TEXT_BASE      /* r0 <- Text base */  
  39.     sub r9, r6, r0      /* r9 <- relocation offset */  
  40.     ldr r10, _dynsym_start_ofs  /* r10 <- sym table ofs */  
  41.     add r10, r10, r0        /* r10 <- sym table in FLASH */  
  42.     ldr r2, _rel_dyn_start_ofs  /* r2 <- rel dyn start ofs */  
  43.     add r2, r2, r0      /* r2 <- rel dyn start in FLASH */  
  44.     ldr r3, _rel_dyn_end_ofs    /* r3 <- rel dyn end ofs */  
  45.     add r3, r3, r0      /* r3 <- rel dyn end in FLASH */  
  46. fixloop:  
  47.     ldr r0, [r2]        /* r0 <- location to fix up, IN FLASH! */  
  48.     add r0, r0, r9      /* r0 <- location to fix up in RAM */  
  49.     ldr r1, [r2, #4]  
  50.     and r7, r1, #0xff  
  51.     cmp r7, #23         /* relative fixup? */  
  52.     beq fixrel  
  53.     cmp r7, #2          /* absolute fixup? */  
  54.     beq fixabs  
  55.     /* ignore unknown type of fixup */  
  56.     b   fixnext  
  57. fixabs:  
  58.     /* absolute fix: set location to (offset) symbol value */  
  59.     mov r1, r1, LSR #4      /* r1 <- symbol index in .dynsym */  
  60.     add r1, r10, r1     /* r1 <- address of symbol in table */  
  61.     ldr r1, [r1, #4]        /* r1 <- symbol value */  
  62.     add r1, r1, r9      /* r1 <- relocated sym addr */  
  63.     b   fixnext  
  64. fixrel:  
  65.     /* relative fix: increase location by offset */  
  66.     ldr r1, [r0]  
  67.     add r1, r1, r9  
  68. fixnext:  
  69.     str r1, [r0]  
  70.     add r2, r2, #8      /* each rel.dyn entry is 8 bytes */  
  71.     cmp r2, r3  
  72.     blo fixloop  
  73. #endif  
  74.   
  75. clear_bss:  
  76. #ifndef CONFIG_SPL_BUILD  
  77.     ldr r0, _bss_start_ofs  
  78.     ldr r1, _bss_end_ofs  
  79.     mov r4, r6          /* reloc addr */  
  80.     add r0, r0, r4  
  81.     add r1, r1, r4  
  82.     mov r2, #0x00000000     /* clear                */  
  83.   
  84. clbss_l:cmp r0, r1          /* clear loop... */  
  85.     bhs clbss_e         /* if reached end of bss, exit */  
  86.     str r2, [r0]  
  87.     add r0, r0, #4  
  88.     b   clbss_l  
  89. clbss_e:  
  90.   
  91.     bl coloured_LED_init  
  92.     bl red_led_on  
  93. #endif  


c、smdk2440.h

上一篇我们在 smdk2440.h 定义了CONFIG_S3C2440 并且注释了CONFIG_S3C2410 

注释了  #define CONFIG_CMD_NAND 

前面我们已经对smdk2440.h 的#define CONFIG_SYS_TEXT_BASE 进行了修改

还需要修改的:

注释掉  #define CONFIG_YAFFS2,解决nand_info 没有定义的错误。


d、common.h

修改include/common.h 276:

void board_init_f  (ulong) __attribute__ ((noreturn));

改为unsigned int board_init_f  (ulong);



e、board.c

259:将void board_init_f(ulong bootflag)

修改为 unsigned int board_init_f(ulong bootflag)

372:修改如下

//addr -= gd->mon_len;
//addr &= ~(4096 - 1);
addr = _TEXT_BASE;//**add return sp to start.s

439:修改如下

//relocate_code(addr_sp, id, addr);
return (unsigned int) id;// add it


f、arch/arm/cpu/u-boot.lds  

修改链接脚本,确保重定位之前的代码编译在最前面

在arch/arm/cpu/u-boot.lds 38:增加如下

board/samsung/smdk2440/libsmdk2440.o (.text)



3、重新配置、编译

 make distclean
make smdk2440_config
make


4、烧写、测试

记住这里是烧到NAND,我用NOR Flash里的u-boot烧写,拨到NOR Flash启动,设置串口 115200 8 n 1

 U-Boot 2012.04.01 (Oct 05 2015 - 17:08:15)

CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB
WARNING: Caches not enabled 

这个结果是加了补丁之后出现的!我按照视频操作之后,注释了 #define CONFIG_YAFFS2,发现编译出来的.bin 文件只有三百多K,烧进去没有出现这个结果,问题正在排查。。