一.下载U-boot源码:ftp://ftp.denx.de/pub/u-boot/

二.uboot的启动过程:

 部分硬件初始化——>加载完整uboot到RAM——>跳转到第二阶段入口开始执行,整个过程最重要的两个文件:

  /arch/arm/cpu/arm920t/start.S,涉及到特定硬件设备的读写寄存器操作以及特定体系结构的汇编语言(中断、时钟等)。

  board/samsung/smdk2440/lowlevel_init.S,完成底层的初始化(内存控制器等)。

具体流程如下:

1 set the cpu to SVC32 mode
2 turn off the watchdog
3 mask all IRQs by setting all bits in the INTMR
4 设置时钟比例
5 设置内存控制器
6 设置栈,调用C函数board_init_f
7 调用函数数组init_sequence里的各个函数
7.1 board_early_init_f : 设置系统时钟、设置GPIO
......
8 重定位代码:
8.1 从NOR FLASH把代码复制到SDRAM
8.2 程序的链接地址是0,访问全局变量、静态变量、调用函数时是使"基于0地址编译得到的地址"
      现在把程序复制到了SDRAM
      需要修改代码,把"基于0地址编译得到的地址"改为新地址
8.3 程序里有些地址在链接时不能确定,要到运行前才能确定:fixabs
9   clear_bss
10 调用C函数board_init_r:第2阶段的代码

三.源码修改及编译:

  1.编译:make smdk2410_config && make

  2.源码修改,移植到JZ2440开发板:   

 新建一个单板:(之后通过 make smdk2440_config 配置)
    cp -rf board/samsung/smdk2410  board/samsung/smdk2440
    cp include/configs/smdk2410.h  include/configs/smdk2440.h
         修改boards.cfg ,仿照2410增加:  (较新版的u-boot源码已经去掉boadrs.cfg,而是使用make menuconfig配置,config文件在configs目录下)

smdk2440                     arm         arm920t     -                   samsung        s3c24x0

    原来的代码在链接时加了"-pie"选项, 使得u-boot.bin里多了"*(.rel*)", "*(.dynsym)",使得程序非常大,不利于从NAND启动(重定位之前的启动代码应该少于4K)
    因此可以注释掉 arch/arm/config.mk 该参数:LDFLAGS_u-boot += -pie  -> #LDFLAGS_u-boot += -pie

 设置PLL的时钟操作在/board/samsung/smdk2440/smdk2410.cboard_early_init_f 函数中,MPLL倍频值应在设置分频系数和初始化内存控制器之前设置,

所以可以注释掉如下部分代码:  

      /* to reduce PLL lock time, adjust the LOCKTIME register */
   //writel(0xFFFFFF, &clk_power->locktime);    /* configure MPLL */
   //writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV,
// &clk_power->mpllcon);

   在/arch/arm/cpu/arm920t/start.S中再设置:

/* IRQ stack memory (calculated at run-time) + 8 bytes */
.globl IRQ_STACK_START_IN
IRQ_STACK_START_IN:
.word 0x0badc0de
//添加:
.globl base_sp
base_sp:
.long 0
//修改:
#if 0
  /* FCLK:HCLK:PCLK = 1:2:4 */
  /* default FCLK is 120 MHz ! */
  ldr r0, =CLKDIVN
  mov r1, #3
  str r1, [r0]
#else
/* 2. 设置时钟 400MHz */
ldr r0, =0x4c000014
// mov r1, #0x03; // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
mov r1, #0x05; // FCLK:HCLK:PCLK=1:4:8
str r1, [r0] /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
mrc p15, , r1, c1, c0, /* 读出控制寄存器 */
orr r1, r1, #0xc0000000 /* 设置为“asynchronous bus mode” */
mcr p15, , r1, c1, c0, /* 写入控制寄存器 */   #define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01)) /* MPLLCON = S3C2440_MPLL_200MHZ */
ldr r0, =0x4c000004
ldr r1, =S3C2440_MPLL_400MHZ
str r1, [r0] /* 启动ICACHE */
mrc p15, , r0, c1, c0, @ read control reg
orr r0, r0, #(<<)
mcr p15, , r0, c1, c0, @ write it back
#endif /* CONFIG_S3C24X0 */ /*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) /* sp = 30000f80 */
bic sp, sp, # /* 8-byte alignment for ABI compliance */ bl nand_init_ll
mov r0, #
//ldr r1, =_start
ldr r1, _TEXT_BASE ldr r2, _bss_start_ofs bl copy_code_to_sdram
bl clear_bss ldr pc, =call_board_init_f /* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr r0,=0x00000000
bl board_init_f /* unsigned int的值存在r0里, 正好给board_init_r */
ldr r1, _TEXT_BASE
ldr sp, base_sp /* 重新设置栈 */ /* 调用第2阶段的代码 */
bl board_init_r

修改arch/arm/lib/board.c 的 board_init_f 函数如下:

unsigned int board_init_f(ulong bootflag) //修改返回值为id
{
bd_t *bd;
init_fnc_t **init_fnc_ptr;
gd_t *id;
ulong addr, addr_sp;
extern ulong base_sp; //栈指针 #ifdef CONFIG_PRAM
ulong reg;
#endif bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f"); /* Pointer is writable since we allocated a register for it */
gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);
/* compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__("": : :"memory"); memset((void *)gd, , sizeof(gd_t)); gd->mon_len = _bss_end_ofs;
#ifdef CONFIG_OF_EMBED
/* Get a pointer to the FDT */
gd->fdt_blob = _binary_dt_dtb_start;
#elif defined CONFIG_OF_SEPARATE
/* FDT is at end of image */
gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE);
#endif
/* Allow the early environment to override the fdt address */
gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", ,
(uintptr_t)gd->fdt_blob); for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != ) {
hang ();
}
} #ifdef CONFIG_OF_CONTROL
/* For now, put this check after the console is ready */
if (fdtdec_prepare_fdt()) {
panic("** CONFIG_OF_CONTROL defined but no FDT - please see "
"doc/README.fdt-control");
}
#endif debug("monitor len: %08lX\n", gd->mon_len);
/*
* Ram is setup, size stored in gd !!
*/
debug("ramsize: %08lX\n", gd->ram_size);
#if defined(CONFIG_SYS_MEM_TOP_HIDE)
/*
* Subtract specified amount of memory to hide so that it won't
* get "touched" at all by U-Boot. By fixing up gd->ram_size
* the Linux kernel should now get passed the now "corrected"
* memory size and won't touch it either. This should work
* for arch/ppc and arch/powerpc. Only Linux board ports in
* arch/powerpc with bootwrapper support, that recalculate the
* memory size from the SDRAM controller setup will have to
* get fixed.
*/
gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE;
#endif addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size; #ifdef CONFIG_LOGBUFFER
#ifndef CONFIG_ALT_LB_ADDR
/* reserve kernel log buffer */
addr -= (LOGBUFF_RESERVE);
debug("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN,
addr);
#endif
#endif #ifdef CONFIG_PRAM
/*
* reserve protected RAM
*/
reg = getenv_ulong("pram", , CONFIG_PRAM);
addr -= (reg << ); /* size is in kB */
debug("Reserving %ldk for protected RAM at %08lx\n", reg, addr);
#endif /* CONFIG_PRAM */ #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
/* reserve TLB table */
addr -= ( * ); /* round down to next 64 kB limit */
addr &= ~(0x10000 - ); gd->tlb_addr = addr;
debug("TLB table at: %08lx\n", addr);
#endif /* round down to next 4 kB limit */
addr &= ~( - );
debug("Top of RAM usable for U-Boot at: %08lx\n", addr); #ifdef CONFIG_LCD
#ifdef CONFIG_FB_ADDR
gd->fb_base = CONFIG_FB_ADDR;
#else
/* reserve memory for LCD display (always full pages) */
addr = lcd_setmem(addr);
gd->fb_base = addr;
#endif /* CONFIG_FB_ADDR */
#endif /* CONFIG_LCD */ /*
* reserve memory for U-Boot code, data & bss
* round down to next 4 kB limit
*/
//addr -= gd->mon_len;
//addr &= ~(4096 - 1);
addr = CONFIG_SYS_TEXT_BASE; /* addr = _TEXT_BASE */ debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> , addr); #ifndef CONFIG_SPL_BUILD
/*
* reserve memory for malloc() arena
*/
addr_sp = addr - TOTAL_MALLOC_LEN;
debug("Reserving %dk for malloc() at: %08lx\n",
TOTAL_MALLOC_LEN >> , addr_sp);
/*
* (permanently) allocate a Board Info struct
* and a permanent copy of the "global" data
*/
addr_sp -= sizeof (bd_t);
bd = (bd_t *) addr_sp;
gd->bd = bd;
debug("Reserving %zu Bytes for Board Info at: %08lx\n",
sizeof (bd_t), addr_sp); #ifdef CONFIG_MACH_TYPE
gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
#endif addr_sp -= sizeof (gd_t);
id = (gd_t *) addr_sp;
debug("Reserving %zu Bytes for Global Data at: %08lx\n",
sizeof (gd_t), addr_sp); /* setup stackpointer for exeptions */
gd->irq_sp = addr_sp;
#ifdef CONFIG_USE_IRQ
addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);
debug("Reserving %zu Bytes for IRQ stack at: %08lx\n",
CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp);
#endif
/* leave 3 words for abort-stack */
addr_sp -= ; /* 8-byte alignment for ABI compliance */
addr_sp &= ~0x07;
#else
addr_sp += ; /* leave 32 words for abort-stack */
gd->irq_sp = addr_sp;
#endif debug("New Stack Pointer is: %08lx\n", addr_sp); #ifdef CONFIG_POST
post_bootmode_init();
post_run(NULL, POST_ROM | post_bootmode_get());
#endif gd->bd->bi_baudrate = gd->baudrate;
/* Ram ist board specific, so move it to board code ... */
dram_init_banksize();
display_dram_config(); /* and display it */ gd->relocaddr = addr;
gd->start_addr_sp = addr_sp;
gd->reloc_off = addr - _TEXT_BASE;
debug("relocation Offset is: %08lx\n", gd->reloc_off);
memcpy(id, (void *)gd, sizeof(gd_t)); base_sp = addr_sp; //relocate_code(addr_sp, id, addr);
return (unsigned int)id; /* NOTREACHED - relocate_code() does not return */
}

修改 include/common.h 的patch如下:

 /* arch/$(ARCH)/lib/board.c */
-void board_init_f (ulong) __attribute__ ((noreturn));
-void board_init_r (gd_t *, ulong) __attribute__ ((noreturn));
+unsigned int board_init_f (ulong) ;
+void board_init_r (gd_t *, ulong) ;

修改 include/configs/smdk2440.h

#define CONFIG_SYS_TEXT_BASE    0x33f00000 //重定义代码段基地址
...
/*注释以下部分:*/
//#define CONFIG_USB_OHCI
//#define CONFIG_USB_KEYBOARD
//#define CONFIG_USB_STORAGE
//#define CONFIG_DOS_PARTITION
...
//#define CONFIG_RTC_S3C24X0
...
//#define CONFIG_BOOTP_BOOTFILESIZE
//#define CONFIG_BOOTP_BOOTPATH
//#define CONFIG_BOOTP_GATEWAY
//#define CONFIG_BOOTP_HOSTNAME
...
//#define CONFIG_CMD_DATE
//#define CONFIG_CMD_DHCP
...
//#define CONFIG_CMD_USB
...
/*修改终端信息*/
#define CONFIG_SYS_PROMPT "U-boot-2012# "
...
/*定义*/
#define CONFIG_CMD_NAND_YAFFS //支持nand write.yaffs #define CONFIG_BOOTARGS "console=ttySAC0 root=/dev/mtdblock3"
//后面用了ubi文件系统所以参数设置如下:
//bootargs=console=ttySAC0,115200 ubi.mtd=3 root=ubi0:rootfs rootfstype=ubifs
#define CONFIG_BOOTCOMMAND "nand read 30000000 kernel;bootm 30000000" /*修改*/
#define CONFIG_SYS_MAX_FLASH_SECT (128)

#if 0
#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x070000)
#define CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_SIZE 0x10000
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#endif
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET 0x40000
#define CONFIG_ENV_SIZE 0x20000
#define CONFIG_ENV_RANGE CONFIG_ENV_SIZE
...
//设置mtd分区为:uboot:256k; params:128k; kernel:4m; rootfs:余下大小;
#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define MTDIDS_DEFAULT "nand0=jz2440-0"
#define MTDPARTS_DEFAULT  "mtdparts=jz2440-0:256k(u-boot)," \
  "128k(params)," \
  "4m(kernel)," \
  "-(rootfs)" \ //注释掉原来文件系统部分定义:
#if 0
#define CONFIG_CMD_FAT
#define CONFIG_CMD_EXT2
#define CONFIG_CMD_UBI
#define CONFIG_CMD_UBIFS
#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define CONFIG_MTD_PARTITIONS
#define CONFIG_YAFFS2
#define CONFIG_RBTREE
#endif

添加 board/samsung/smdk2440/init.cstart.S调用,内容如下:

/* 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 *);
int val; val = *p;
*p = 0x12345678;
if (*p == 0x12345678)
{
/* 写成功, 是nand启动 */
*p = val;
return ;
}
else
{
/* NOR不能像内存一样写 */
return ; }
} void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
{
int i = ; /* 如果是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 = ;
} void nand_init_ll(void)
{
#define TACLS 0
#define TWRPH0 1
#define TWRPH1 0 /* 设置时序 */
NFCONF = (TACLS<<)|(TWRPH0<<)|(TWRPH1<<); /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
NFCONT = (<<)|(<<)|(<<);
} static void nand_select(void)
{
NFCONT &= ~(<<);
} static void nand_deselect(void)
{
NFCONT |= (<<);
} static void nand_cmd(unsigned char cmd)
{
volatile int i;
NFCMMD = cmd;
for (i = ; i < ; i++);
} static void nand_addr(unsigned int addr)
{
unsigned int col = addr % ;
unsigned int page = addr / ;
volatile int i; NFADDR = col & 0xff;
for (i = ; i < ; i++);
NFADDR = (col >> ) & 0xff;
for (i = ; i < ; i++); NFADDR = page & 0xff;
for (i = ; i < ; i++);
NFADDR = (page >> ) & 0xff;
for (i = ; i < ; i++); NFADDR = (page >> ) & 0xff;
for (i = ; i < ; i++);
} static void nand_wait_ready(void)
{
while (!(NFSTAT & ));
} static unsigned char nand_data(void)
{
return NFDATA;
} void nand_read_ll(unsigned int addr, unsigned char *buf, unsigned int len)
{
int col = addr % ;
int i = ; /* 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 < ) && (i < len); col++)
{
buf[i] = nand_data();
i++;
addr++;
}
col = ;
} /* 7. 取消选中 */       
nand_deselect();
}

修改Makefile增加编译 init.c :

COBJS    := smdk2410.o init.o

④.内存控制器的设置值改为如下:/board/samsung/smdk2440/lowlevel_init.S

SMRDATA:
#if 0
.word (+(B1_BWSCON<<)+(B2_BWSCON<<)+(B3_BWSCON<<)+(B4_BWSCON<<)+(B5_BWSCON<<)+(B6_BWSCON<<)+(B7_BWSCON<<))
.word ((B0_Tacs<<)+(B0_Tcos<<)+(B0_Tacc<<)+(B0_Tcoh<<)+(B0_Tah<<)+(B0_Tacp<<)+(B0_PMC))
.word ((B1_Tacs<<)+(B1_Tcos<<)+(B1_Tacc<<)+(B1_Tcoh<<)+(B1_Tah<<)+(B1_Tacp<<)+(B1_PMC))
.word ((B2_Tacs<<)+(B2_Tcos<<)+(B2_Tacc<<)+(B2_Tcoh<<)+(B2_Tah<<)+(B2_Tacp<<)+(B2_PMC))
.word ((B3_Tacs<<)+(B3_Tcos<<)+(B3_Tacc<<)+(B3_Tcoh<<)+(B3_Tah<<)+(B3_Tacp<<)+(B3_PMC))
.word ((B4_Tacs<<)+(B4_Tcos<<)+(B4_Tacc<<)+(B4_Tcoh<<)+(B4_Tah<<)+(B4_Tacp<<)+(B4_PMC))
.word ((B5_Tacs<<)+(B5_Tcos<<)+(B5_Tacc<<)+(B5_Tcoh<<)+(B5_Tah<<)+(B5_Tacp<<)+(B5_PMC))
.word ((B6_MT<<)+(B6_Trcd<<)+(B6_SCAN))
.word ((B7_MT<<)+(B7_Trcd<<)+(B7_SCAN))
.word ((REFEN<<)+(TREFMD<<)+(Trp<<)+(Trc<<)+(Tchr<<)+REFCNT)
.word 0x32
.word 0x30
.word 0x30
#else .long 0x22011110 //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
.long 0x008C04F4 //REFRESH
.long 0x000000B1 //BANKSIZE
.long 0x00000030 //MRSRB6
.long 0x00000030 //MRSRB7 #endif

⑤设置串口波特率(get_HCLK函数),修改 /include/configs/smdk2440.h(拷贝的2410) 的宏定义为 CONFIG_S3C2440

//#define CONFIG_S3C2410        /* specifically a SAMSUNG S3C2410 SoC */
#define CONFIG_S3C2440
...
#define CONFIG_SYS_MAX_FLASH_SECT (128)

⑥支持NOR-FLASH: 在 /drivers/mtd/jedec_flash.c 的 jedec_table[] 中增加一项匹配板子上的NOR-Flash厂商ID和设备ID:

 /* JZ2440使用的MT29LV160DB */
{
.mfr_id = (u16)MX_MANUFACT, /* 厂家ID */
.dev_id = 0X2249, /* 设备ID */
.name = "MXIC MT29LV160DB",
.uaddr = { /* NOR flash看到解锁地址 */
        [] = MTD_UADDR_0x0555_0x02AA /* x16 */
},
.DevSize = SIZE_2MiB, /* 总大小 */
.CmdSet = P_ID_AMD_STD,
.NumEraseRegions= ,
.regions = {
ERASEINFO(*, ),
ERASEINFO(*, ),
ERASEINFO(*, ),
ERASEINFO(*, ),
}
},
},

 Ps: flinfo : 查看flash信息,RO块通过"protect off all"指令后擦写。

    测试一下norflash能否正确读写,用以下u-boot命令:

    cp.b 0 30000000 80
    cmp.b 0 30000000 80
    发现读norflash没有问题。再用以下几条命令测试写norflash:
    mw.b 30000000 12 3
    protect off all
    erase 0 ffff
    cp.b 30000000 0 3
    md.b 0 3
    发现也是121212;因此写norflash成功,至此u-boot已经支持JZ2440开发板的norflash。

支持NAND-FLASH:

  修改 include/configs/smdk2440.h

//根据配置定义对应的宏:
#ifdef CONFIG_S3C2410
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#else
#define CONFIG_NAND_S3C2440
#define CONFIG_SYS_S3C2440_NAND_HWECC
#endif

   仿照 drivers/mtd/nand/s3c2410_nand.c 编写s3c2440_nand.c

/*
* (C) Copyright 2006 OpenMoko, Inc.
* Author: Harald Welte <laforge@openmoko.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/ #include <common.h> #include <nand.h>
#include <asm/arch/s3c24x0_cpu.h>
#include <asm/io.h> #define S3C2410_NFCONF_EN (1<<15)
#define S3C2410_NFCONF_512BYTE (1<<14)
#define S3C2410_NFCONF_4STEP (1<<13)
#define S3C2410_NFCONF_INITECC (1<<12)
#define S3C2410_NFCONF_nFCE (1<<11)
#define S3C2410_NFCONF_TACLS(x) ((x)<<8)
#define S3C2410_NFCONF_TWRPH0(x) ((x)<<4)
#define S3C2410_NFCONF_TWRPH1(x) ((x)<<0) #define S3C2410_ADDR_NALE 4
#define S3C2410_ADDR_NCLE 8 #ifdef CONFIG_NAND_SPL /* in the early stage of NAND flash booting, printf() is not available */
#define printf(fmt, args...) static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
{
int i;
struct nand_chip *this = mtd->priv; for (i = ; i < len; i++)
buf[i] = readb(this->IO_ADDR_R);
}
#endif /* ctrl : 表示做什么, 选中芯片/取消选中, 发命令还是发地址
*
* dat : 命令值或地址值
*/
static void s3c2440_hwcontrol(struct mtd_info *mtd, int dat, unsigned int ctrl)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand(); if (ctrl & NAND_CLE)
{
/* 发命令 */
writeb(dat, &nand->nfcmd);
}
else if(ctrl & NAND_ALE)
{
/* 发地址 */
writeb(dat, &nand->nfaddr);
} } static int s3c2440_dev_ready(struct mtd_info *mtd)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand();
debug("dev_ready\n");
return readl(&nand->nfstat) & 0x01;
} static void s3c2440_nand_select(struct mtd_info *mtd, int chipnr)
{
struct s3c2440_nand *nand = s3c2440_get_base_nand(); switch (chipnr) {
case -: /* 取消选中 */
nand->nfcont |= (<<);
break;
case : /* 选中 */
nand->nfcont &= ~(<<);
break; default:
BUG();
}
} int board_nand_init(struct nand_chip *nand)
{
u_int32_t cfg;
u_int8_t tacls, twrph0, twrph1;
struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
struct s3c2440_nand *nand_reg = s3c2440_get_base_nand(); debug("board_nand_init()\n"); writel(readl(&clk_power->clkcon) | ( << ), &clk_power->clkcon); /* initialize hardware */
#if defined(CONFIG_S3C24XX_CUSTOM_NAND_TIMING)
tacls = CONFIG_S3C24XX_TACLS;
twrph0 = CONFIG_S3C24XX_TWRPH0;
twrph1 = CONFIG_S3C24XX_TWRPH1;
#else
tacls = ;
twrph0 = ;
twrph1 = ;
#endif #if 0
cfg = S3C2410_NFCONF_EN;
cfg |= S3C2410_NFCONF_TACLS(tacls - );
cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - );
cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - );
#endif
/* 初始化时序 */
cfg = ((tacls-)<<)|((twrph0-)<<)|((twrph1-)<<);
writel(cfg, &nand_reg->nfconf); /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
writel((<<)|(<<)|(<<), &nand_reg->nfcont); /* initialize nand_chip data structure */
nand->IO_ADDR_R = (void *)&nand_reg->nfdata;
nand->IO_ADDR_W = (void *)&nand_reg->nfdata; nand->select_chip = s3c2440_nand_select; /* read_buf and write_buf are default */
/* read_byte and write_byte are default */
#ifdef CONFIG_NAND_SPL
nand->read_buf = nand_read_buf;
#endif /* hwcontrol always must be implemented */
nand->cmd_ctrl = s3c2440_hwcontrol; nand->dev_ready = s3c2440_dev_ready; #ifdef CONFIG_S3C2410_NAND_HWECC
nand->ecc.hwctl = s3c2410_nand_enable_hwecc;
nand->ecc.calculate = s3c2410_nand_calculate_ecc;
nand->ecc.correct = s3c2410_nand_correct_data;
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
#else
nand->ecc.mode = NAND_ECC_SOFT;
#endif #ifdef CONFIG_S3C2410_NAND_BBT
nand->options = NAND_USE_FLASH_BBT;
#else
nand->options = ;
#endif debug("end of nand_init\n"); return ;
}

Makefile添加编译:

COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o

另外 drivers/mtd/nand/nand_util.c 修改patch如下:

@@ -, +, @@
return -EINVAL;
} - if (!need_skip && !(flags & WITH_DROP_FFS)) {
+
+  /* 并且标志没有yaffs*/
+ if (!need_skip && !(flags & WITH_DROP_FFS) && !(flags & WITH_YAFFS_OOB) ) {
rval = nand_write (nand, offset, length, buffer);
if (rval == )
return ;
@@ -, +, @@ ops.len = pagesize;
ops.ooblen = nand->oobsize;
- ops.mode = MTD_OOB_AUTO;
+ ops.mode = MTD_OOB_RAW;
ops.ooboffs = ; pages = write_size / pagesize_oob;
@@ -, +, @@
ops.oobbuf = ops.datbuf + pagesize; rval = nand->write_oob(nand, offset, &ops);
- if (!rval)
+ if (rval)
break; offset += pagesize;

  可以修改 drivers/mtd/cfi_flash.c 关闭调试:

 #include <mtd/cfi_flash.h>
#include <watchdog.h> //#define DEBUG 1
//#define _DEBUG 1

⑧支持DM9000网卡:

    启动uboot,打印出Net: CS8900-0,而我们的网卡是DM9000,于是在代码中搜索“Net:”,定位到common/board_r.c的initr_net函数,一路追踪eth_initialize,                eth_common_init,一直到 \board\samsung\smdk2440(拷贝的2410)\smdk2410.c的board_eth_init函数:

  1. int board_eth_init(bd_t *bis)
  2. {
  3. int rc = 0;
  4. #ifdef CONFIG_CS8900
  5. rc = cs8900_initialize(0, CONFIG_CS8900_BASE);
  6. #endif
  7. return rc;
  8. }

  这里是对CS8900进行了初始化,我们要对DM9000进行初始化,通过查看drivers/net/Makefile,发现要包含dm9000x.c的文件,要定义CONFIG_DRIVER_DM9000这个宏,我们也要注释掉CONFIG_CS8900宏。同时查看dm9000x.c,里面有一个dm9000_initialize函数,于是仿照cs8900来写dm9000的初始化函数,修改smdk2410.c:

int board_eth_init(bd_t *bis)
{
int rc = ;
#ifdef CONFIG_CS8900
rc = cs8900_initialize(, CONFIG_CS8900_BASE);
#endif #ifdef CONFIG_DRIVER_DM9000
rc = dm9000_initialize(bis);
#endif
return rc;
}

配置文件smdk2440.h(拷贝的2410)修改如下:

/*
* Hardware drivers
*/
#if 0
#define CONFIG_CS8900 /* we have a CS8900 on-board */
#define CONFIG_CS8900_BASE 0x19000300
#define CONFIG_CS8900_BUS16 /* the Linux driver does accesses as shorts */
#else
#define CONFIG_DRIVER_DM9000
#define CONFIG_DM9000_BASE 0x20000000
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE + 4)
#endif

设置CONFIG_ETHADDR宏:

#define CONFIG_ETHADDR      00:0c:29:4d:e4:f4

保存,编译,烧写,启动Uboot,网卡正常启动。设置一下开发板ip:set ipaddr 192.168.0.2。网线连接开发板和路由器,ping一下主机ip:

ping 192.168.0.100,能够Ping通。再试试能不能用tftp下载文件,

set serverip 192.168.0.100

tftp 30000000 u-boot.bin

使用tftp下载文件也成功,至此,DM9000网卡已经支持。

问题:

新的uboot可能在不插串口线时无法自动启动内核,因为串口引脚没接上拉电阻导致误认为有按键输入而进入了uboot模式,可以修改uboot源码默认只在输入空格进入uboot,可以参考如下path:

diff -urN u-boot-2012.04./common/main.c u-boot-2012.04.01_4m/common/main.c
--- u-boot-2012.04./common/main.c -- ::50.000000000 -
+++ u-boot-2012.04.01_4m/common/main.c -- ::44.351768306 -
@@ -, +, @@
*/
if (bootdelay >= ) {
if (tstc()) { /* we got a key press */
- (void) getc(); /* consume input */
+ //(void) getc(); /* consume input */
puts ("\b\b\b 0");
- abort = ; /* don't auto boot */
+ if(' ' == getc())/* if got space */
+ abort = ; /* don't auto boot */
}
}

-end-

Linux学习 :移植U-boot_2016.09到JZ2440开发板的更多相关文章

  1. Linux学习 :移植U-boot_2012.04.01到JZ2440开发板

    一.下载U-boot源码:ftp://ftp.denx.de/pub/u-boot/ 二.uboot的启动过程: 部分硬件初始化——>加载完整uboot到RAM——>跳转到第二阶段入口开始 ...

  2. Linux学习 :移植linux-4.7.4到JZ2440开发板

    一.编译环境搭建: 1.linux源码下载:https://www.kernel.org/2.安装交叉编译工具链: ①手动下载配置工具链: (1):解压 arm-linux-gcc-3.4.1.tar ...

  3. Linux学习 :移植linux-3.4.83到JZ2440开发板

    一.编译环境搭建: 1.linux源码下载:https://www.kernel.org/ (最新)  https://mirrors.edge.kernel.org/pub/linux/kernel ...

  4. JZ2440开发板:用按键点亮LED灯(学习笔记)

    本文是对韦东山嵌入式第一期学习的记录之一,如有您需要查找的信息,可以继续往下阅读. 想要用按键点亮LED灯,就需要知道按键和LED灯的相关信息,这样才可以进行之后的操作.阅读JZ2440的原理图,可以 ...

  5. JZ2440开发板:UART(串口)使用(学习笔记)

    查看UART在硬件上的信息,阅读JZ2440原理图可以看到: JZ2440开发板的UART0是可以跟USB相接的,用于打印调试,UART1,UART2两个串口用来外接模块.所以本文仅对UART0进行操 ...

  6. JZ2440开发板:修改ARM芯片时钟(学习笔记)

    想要修改ARM芯片的时钟,需要去查询芯片手册和原理图,获取相关的信息(见下方图片) 首先来看时钟的结构图 根据结构图可以看出,时钟源有两种选择:1. XTIpll和XTOpll所连接的晶振 2. EX ...

  7. 基于JZ2440开发板编写bootloader总结(一)

    凡走过必留下痕迹,学点什么都会有用的. 本系列博文总结了自己在学习嵌入式Linux编程过程中的收获,若有错误,恳请指正,谢谢! --参考教材韦东山系列教材 bootloader 是一个用于启动linu ...

  8. Jz2440开发板熟悉

    title: Jz2440开发板熟悉 tags: ARM date: 2018-10-14 15:05:56 --- 概述 外部晶振为12M Nand Flash 256M,Nor Flash 2M, ...

  9. Linux学习 : 移植qt 5.6.3 及 tslib 1.4

    (一) 移植 qt5.6.3 一.qt简介: Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具 ...

随机推荐

  1. 1006. Sign In and Sign Out (25)

    At the beginning of every day, the first person who signs in the computer room will unlock the door, ...

  2. CSUOJ_1000

    /* * Title : A+B(I) * Data : 2016/11/09 * Author : Andrew */ #include <iostream> int main() { ...

  3. Deep Learning 23:dropout理解_之读论文“Improving neural networks by preventing co-adaptation of feature detectors”

    理论知识:Deep learning:四十一(Dropout简单理解).深度学习(二十二)Dropout浅层理解与实现.“Improving neural networks by preventing ...

  4. mysql复制一列到另一列

    mysql复制一列到另一列   UPDATE 表名 SET B列名=A列名 需求:把一个表某个字段内容复制到另一张表的某个字段. 实现sql语句1: 复制代码代码如下: UPDATE file_man ...

  5. Rigidbody相关的操作最好放在FixedUpdate中,update中可能会无效果

    void Turning() { // Create a ray from the mouse cursor on screen in the direction of the camera. Ray ...

  6. Markdown渲染后文章标题收缩控件

    文章首发于szhshp的第三边境研究所(szhshp.org), 转载请注明 一个让Markdown-Post的标题拥有Collapse功能的JS 直接把鼠标放在这篇文章下方的header上,点击标题 ...

  7. express+gulp构建项目(四)env环境变量

    这里的文件的作用是负责设置env环境变量和日志. index.js try { require('dotenv').load({silent: true}); //dotenv从一个.env文件中读取 ...

  8. 不断弹出svchost.exe错误框

    同事的一台电脑,xp系统,启动后就弹出svchost错误的对话框,不论确定还是取消,关闭后立刻又弹出. 打开任务管理器,尝试对一些后安装的软件结束进程,结束一个,关闭一次,看看结束哪一个,关闭后不再弹 ...

  9. ajax和sap以及网络安全

    1.sap(single page  applaction)一个页面通过众多ajax请求完成的一个app 优点是:减少页面跳转,UI公用部分的重复加载 缺点: 1.ajax过多的请求,对服务器性能有所 ...

  10. RHEL 6.0服务器安装Oracle 11G R2 最终版

    RHEL6安装Oracle 11g R2最终版 结合网上教程 服务器实战所得 1.使用DVD做yum源新建dvd挂载目录[root@fxq-dp ~]# mkdir /media/iso进入到DVD挂 ...