移植uboot到2440
来源:互联网 发布:ubuntu 电源设置打不开 编辑:程序博客网 时间:2024/06/05 15:00
一、修改顶层Makefile,加入:
shanl2440_config :unconfig@$(MKCONFIG) $(@:_config=) arm arm920t shanl2440 NULL s3c24x0arm: CPU 的架构(ARCH)
arm920t: CPU 的类型(CPU),其对应于 cpu/arm920t 子目录。
shanl2440: 开发板的型号(BOARD),对应于 board/shanl2440 目录。
NULL: 开发者/或经销商(vender)。(此处没加 vender,为 NULL。) ,如果有vendor,则开发板的目录就在board/vendor/shanl下
s3c24x0: 片上系统(SOC)。
二、建立自己开发板的board信息:
在board下面建立shanl2440目录,并把smdk2410目录中的内容复制过来:
shanl@shanl-Aspire-4740:~/Kernel/u-boot-1.1.6/board$ mkdir shanl2440shanl@shanl-Aspire-4740:~/Kernel/u-boot-1.1.6/board$ cp smdk2410/* shanl2440/
三、编译:
发现出现一下错误:
/home/shanl/Kernel/u-boot-1.1.6/include/config.h:2: fatal error: configs/shanl2440.h: 没有那个文件或目录解决办法:
进入相应的目录,将2410的配置复制一份shanl2440.h
shanl@shanl-Aspire-4740:~/Kernel/u-boot-1.1.6$ cd include/configs/shanl@shanl-Aspire-4740:~/Kernel/u-boot-1.1.6/include/configs$ cp smdk2410.h shanl2440.h重新make一下,问题解决,会在根目录下面生成u-boot.bin.
这个u-boot.bin只是披了一层2440外衣的2410可执行程序。下面需要对代码做相关的修改从而支持2440
四、加入板子的配置:
在include\configs\Shanl2440.h中加入:
#defineCONFIG_SHANL24401/* in a SAMSUNG S3C2440 SoC */五、关闭看门狗和中断:
将:
/* turn off the watchdog */#if defined(CONFIG_S3C2400)# define pWTCON0x15300000# define INTMSK0x14400008/* Interupt-Controller base addresses */# define CLKDIVN0x14800014/* clock divisor register */#elif defined(CONFIG_S3C2410)# define pWTCON0x53000000# define INTMSK0x4A000008/* Interupt-Controller base addresses */# define INTSUBMSK0x4A00001C# define CLKDIVN0x4C000014/* clock divisor register */#endif#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] /* * mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0]# if defined(CONFIG_S3C2410) ldr r1, =0x3ff ldr r0, =INTSUBMSK str r1, [r0]# endif修改为:
/* turn off the watchdog */#if defined(CONFIG_S3C2400)# define pWTCON0x15300000# define INTMSK0x14400008/* Interupt-Controller base addresses */# define CLKDIVN0x14800014/* clock divisor register */#elif defined(CONFIG_S3C2410) || defined(CONFIG_SHANL2440)# define pWTCON0x53000000# define INTMSK0x4A000008/* Interupt-Controller base addresses */# define INTSUBMSK0x4A00001C# define CLKDIVN0x4C000014/* clock divisor register */#endif#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_SHANL2440) ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] /* * mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0]# if defined(CONFIG_S3C2410) || defined(CONFIG_SHANL2440) ldr r1, =0x3ff ldr r0, =INTSUBMSK str r1, [r0]# endif
六、MMU和SDRAM的设置:
将:
/* * we do sys-critical inits only at reboot, * not when booting from ram! */#ifndef CONFIG_SKIP_LOWLEVEL_INITblcpu_init_crit#endif改为:
/* * we do sys-critical inits only at reboot, * not when booting from ram! */#ifndef CONFIG_SKIP_LOWLEVEL_INITadr 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 */blnecpu_init_crit#endif对当前所在地址做一下判断,是运行到sdram上还是nand上,如果已经在sdram上了,就跳过mmu和sdram的设置
七、设置时钟:
首先设置栈,将栈的设置代码放到mmu和sdram设置的后面:
代码如下:
blnecpu_init_crit#endif/* Set up the stack */stack_setup:ldrr0, _TEXT_BASE/* upper 128 KiB: relocated uboot */subr0, r0, #CFG_MALLOC_LEN/* malloc area */subr0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */#ifdef CONFIG_USE_IRQsubr0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)#endifsubsp, r0, #12/* leave 3 words for abort-stack */然后跳用c函数对时钟进行设置:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT bl clock_init#endif在 board\shanl2440下面建立文件Boot_init.c
加入时钟的初始化代码:
static inline void delay (unsigned long loops){ __asm__ volatile ("1:\n" "subs %0, %1, #1\n" "bne 1b":"=r" (loops):"0" (loops));}/* S3C2440: Mpll = (2*m * Fin) / (p * 2^s), UPLL = (m * Fin) / (p * 2^s) * m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2 */#define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))#define S3C2440_UPLL_48MHZ ((0x38<<12)|(0x02<<4)|(0x02))#define S3C2440_CLKDIV (0x05) // | (1<<3)) /* FCLK:HCLK:PCLK = 1:4:8, UCLK = UPLL/2 */void clock_init(void){S3C24X0_CLOCK_POWER *clk_power = (S3C24X0_CLOCK_POWER *)0x4C000000; /* FCLK:HCLK:PCLK = 1:4:8 */ clk_power->CLKDIVN = S3C2440_CLKDIV; /* change to asynchronous bus mod */ __asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register */ "orr r1, r1, #0xc0000000\n" /* Asynchronous */ "mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register */ :::"r1" ); /* to reduce PLL lock time, adjust the LOCKTIME register */ clk_power->LOCKTIME = 0xFFFFFFFF; /* configure UPLL */ clk_power->UPLLCON = S3C2440_UPLL_48MHZ; /* some delay between MPLL and UPLL */ delay (4000); /* configure MPLL */ clk_power->MPLLCON = S3C2440_MPLL_400MHZ; /* some delay between MPLL and UPLL */ delay (8000);}修改board\shanl2440下的Makefile:
COBJS := shanl2440.o flash.o board_init.o SOBJS := lowlevel_init.o
时钟设置好了,还要修改一个文件speed.c,这个文件供uboot第2阶段使用,修改后的文件如下(以后再分析):
#include <common.h>#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB)#if defined(CONFIG_S3C2400)#include <s3c2400.h>#elif defined(CONFIG_S3C2410) || defined (CONFIG_SHANL2440) #include <s3c2410.h>#endifDECLARE_GLOBAL_DATA_PTR;#define MPLL 0#define UPLL 1/* ------------------------------------------------------------------------- *//* NOTE: This describes the proper use of this file. * * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL. * * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of * the specified bus in HZ. *//* ------------------------------------------------------------------------- */static ulong get_PLLCLK(int pllreg){ S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); ulong r, m, p, s; if (pllreg == MPLL) r = clk_power->MPLLCON; else if (pllreg == UPLL) r = clk_power->UPLLCON; else hang(); m = ((r & 0xFF000) >> 12) + 8; p = ((r & 0x003F0) >> 4) + 2; s = r & 0x3; /* support both of S3C2410 and S3C2440, by www.100ask.net */ return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s)); /* S3C2440 */}/* return FCLK frequency */ulong get_FCLK(void){ return(get_PLLCLK(MPLL));}/* for s3c2440 */#define S3C2440_CLKDIVN_PDIVN (1<<0)#define S3C2440_CLKDIVN_HDIVN_MASK (3<<1)#define S3C2440_CLKDIVN_HDIVN_1 (0<<1)#define S3C2440_CLKDIVN_HDIVN_2 (1<<1)#define S3C2440_CLKDIVN_HDIVN_4_8 (2<<1)#define S3C2440_CLKDIVN_HDIVN_3_6 (3<<1)#define S3C2440_CLKDIVN_UCLK (1<<3)#define S3C2440_CAMDIVN_CAMCLK_MASK (0xf<<0)#define S3C2440_CAMDIVN_CAMCLK_SEL (1<<4)#define S3C2440_CAMDIVN_HCLK3_HALF (1<<8)#define S3C2440_CAMDIVN_HCLK4_HALF (1<<9)#define S3C2440_CAMDIVN_DVSEN (1<<12)/* return HCLK frequency */ulong get_HCLK(void){ S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); unsigned long clkdiv; unsigned long camdiv; int hdiv = 1; clkdiv = clk_power->CLKDIVN; camdiv = clk_power->CAMDIVN; /* work out clock scalings */ switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) { case S3C2440_CLKDIVN_HDIVN_1: hdiv = 1; break; case S3C2440_CLKDIVN_HDIVN_2: hdiv = 2; break; case S3C2440_CLKDIVN_HDIVN_4_8: hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4; break; case S3C2440_CLKDIVN_HDIVN_3_6: hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3; break; return get_FCLK() / hdiv; }}/* return PCLK frequency */ulong get_PCLK(void){ S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); unsigned long clkdiv; unsigned long camdiv; int hdiv = 1; clkdiv = clk_power->CLKDIVN; camdiv = clk_power->CAMDIVN; /* work out clock scalings */ switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) { case S3C2440_CLKDIVN_HDIVN_1: hdiv = 1; break; case S3C2440_CLKDIVN_HDIVN_2: hdiv = 2; break; case S3C2440_CLKDIVN_HDIVN_4_8: hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4; break; case S3C2440_CLKDIVN_HDIVN_3_6: hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3; break; } return get_FCLK() / hdiv / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1); }/* return UCLK frequency */ulong get_UCLK(void){ return(get_PLLCLK(UPLL));}#endif /* defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) */
八、重定位代码:
将
#ifndef CONFIG_SKIP_RELOCATE_UBOOTrelocate:/* relocate U-Boot to RAM */adrr0, _start/* r0 <- current position of code */ldrr1, _TEXT_BASE/* test if we run from flash or RAM */cmp r0, r1 /* don't reloc during debug */beq stack_setupldrr2, _armboot_startldrr3, _bss_startsubr2, r3, r2/* r2 <- size of armboot */addr2, r0, r2/* r2 <- source end address */copy_loop:ldmiar0!, {r3-r10}/* copy from source address [r0] */stmiar1!, {r3-r10}/* copy to target address [r1] */cmpr0, r2/* until source end addreee [r2] */blecopy_loop#endif/* CONFIG_SKIP_RELOCATE_UBOOT */
修改为:
#ifndef CONFIG_SKIP_RELOCATE_UBOOTrelocate:/* relocate U-Boot to RAM */adrr0, _start/* r0 <- current position of code */ldrr1, _TEXT_BASE/* test if we run from flash or RAM */cmp r0, r1 /* don't reloc during debug */beq clear_bssldrr2, _armboot_startldrr3, _bss_startsubr2, r3, r2/* r2 <- size of armboot */#if 1bl CopyCode2Ram/* r0: source, r1: dest, r2: size */#elseaddr2, r0, r2/* r2 <- source end address */copy_loop:ldmiar0!, {r3-r10}/* copy from source address [r0] */stmiar1!, {r3-r10}/* copy to target address [r1] */cmpr0, r2/* until source end addreee [r2] */blecopy_loop#endif#endif/* CONFIG_SKIP_RELOCATE_UBOOT */对于CopyCode2Ram的实现可以在boot_init.c中添加,主要是nandflash的读操作:
#define BUSY 1#define NAND_SECTOR_SIZE 512#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)#define NAND_SECTOR_SIZE_LP 2048#define NAND_BLOCK_MASK_LP (NAND_SECTOR_SIZE_LP - 1)/* 供外部调用的函数 */void nand_init_ll(void);void nand_read_ll(unsigned char *buf, unsigned long start_addr, int size);/* NAND Flash操作的总入口, 它们将调用S3C2410或S3C2440的相应函数 */static void nand_reset(void);static void wait_idle(void);static void nand_select_chip(void);static void nand_deselect_chip(void);static void write_cmd(int cmd);static void write_addr(unsigned int addr);static unsigned char read_data(void);/* S3C2440的NAND Flash处理函数 */static void s3c2440_nand_reset(void);static void s3c2440_wait_idle(void);static void s3c2440_nand_select_chip(void);static void s3c2440_nand_deselect_chip(void);static void s3c2440_write_cmd(int cmd);static void s3c2440_write_addr(unsigned int addr);static unsigned char s3c2440_read_data(void);/* S3C2440的NAND Flash操作函数 *//* 复位 */static void s3c2440_nand_reset(void){ s3c2440_nand_select_chip(); s3c2440_write_cmd(0xff); // 复位命令 s3c2440_wait_idle(); s3c2440_nand_deselect_chip();}/* 等待NAND Flash就绪 */static void s3c2440_wait_idle(void){ int i;S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT; while(!(*p & BUSY)) for(i=0; i<10; i++);}/* 发出片选信号 */static void s3c2440_nand_select_chip(void){ int i;S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; s3c2440nand->NFCONT &= ~(1<<1); for(i=0; i<10; i++); }/* 取消片选信号 */static void s3c2440_nand_deselect_chip(void){S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; s3c2440nand->NFCONT |= (1<<1);}/* 发出命令 */static void s3c2440_write_cmd(int cmd){S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD; *p = cmd;}/* 发出地址 */static void s3c2440_write_addr(unsigned int addr){ int i;S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR; *p = addr & 0xff; for(i=0; i<10; i++); *p = (addr >> 9) & 0xff; for(i=0; i<10; i++); *p = (addr >> 17) & 0xff; for(i=0; i<10; i++); *p = (addr >> 25) & 0xff; for(i=0; i<10; i++);}/* 发出地址 */static void s3c2440_write_addr_lp(unsigned int addr){ int i;S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;int col, page;col = addr & NAND_BLOCK_MASK_LP;page = addr / NAND_SECTOR_SIZE_LP; *p = col & 0xff;/* Column Address A0~A7 */ for(i=0; i<10; i++); *p = (col >> 8) & 0x0f;/* Column Address A8~A11 */ for(i=0; i<10; i++); *p = page & 0xff;/* Row Address A12~A19 */ for(i=0; i<10; i++); *p = (page >> 8) & 0xff;/* Row Address A20~A27 */ for(i=0; i<10; i++); *p = (page >> 16) & 0x03;/* Row Address A28~A29 */ for(i=0; i<10; i++);}/* 读取数据 */static unsigned char s3c2440_read_data(void){S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000; volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA; return *p;}/* 在第一次使用NAND Flash前,复位一下NAND Flash */static void nand_reset(void){ s3c2440_nand_reset();}static void wait_idle(void){ s3c2440_wait_idle();}static void nand_select_chip(void){ int i; s3c2440_nand_select_chip(); for(i=0; i<10; i++);}static void nand_deselect_chip(void){ s3c2440_nand_deselect_chip();}static void write_cmd(int cmd){ s3c2440_write_cmd(cmd);}static void write_addr(unsigned int addr){ s3c2440_write_addr(addr);}static void write_addr_lp(unsigned int addr){ s3c2440_write_addr_lp(addr);}static unsigned char read_data(void){ return s3c2440_read_data();}/* 初始化NAND Flash */void nand_init_ll(void){S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;#define TACLS 0#define TWRPH0 2#define TWRPH1 0/* 设置时序 */ s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4); /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */ s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);/* 复位NAND Flash */nand_reset();}/* 读函数 */void 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 ; /* 地址或长度不对齐 */ } /* 选中芯片 */ nand_select_chip(); for(i=start_addr; i < (start_addr + size);) { /* 发出READ0命令 */ write_cmd(0); /* Write Address */ write_addr(i); wait_idle(); for(j=0; j < NAND_SECTOR_SIZE; j++, i++) { *buf = read_data(); buf++; } } /* 取消片选信号 */ nand_deselect_chip(); return ;}/* 读函数 * Large Page */void nand_read_ll_lp(unsigned char *buf, unsigned long start_addr, int size){ int i, j; if ((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP)) { return ; /* 地址或长度不对齐 */ } /* 选中芯片 */ nand_select_chip(); for(i=start_addr; i < (start_addr + size);) { /* 发出READ0命令 */ write_cmd(0); /* Write Address */ write_addr_lp(i); write_cmd(0x30); wait_idle(); for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) { *buf = read_data(); buf++; } } /* 取消片选信号 */ nand_deselect_chip(); return ;}int bBootFrmNORFlash(void){ volatile unsigned int *pdw = (volatile unsigned int *)0; unsigned int dwVal; /* * 无论是从NOR Flash还是从NAND Flash启动, * 地址0处为指令"bReset", 机器码为0xEA00000B, * 对于从NAND Flash启动的情况,其开始4KB的代码会复制到CPU内部4K内存中, * 对于从NOR Flash启动的情况,NOR Flash的开始地址即为0。 * 对于NOR Flash,必须通过一定的命令序列才能写数据, * 所以可以根据这点差别来分辨是从NAND Flash还是NOR Flash启动: * 向地址0写入一个数据,然后读出来,如果没有改变的话就是NOR Flash */ dwVal = *pdw; *pdw = 0x12345678; if (*pdw != 0x12345678) { return 1; } else { *pdw = dwVal; return 0; }}int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size){ unsigned int *pdwDest; unsigned int *pdwSrc; int i; if (bBootFrmNORFlash()) { pdwDest = (unsigned int *)buf; pdwSrc = (unsigned int *)start_addr; /* 从 NOR Flash启动 */ for (i = 0; i < size / 4; i++) { pdwDest[i] = pdwSrc[i]; } return 0; } else { /* 初始化NAND Flash */nand_init_ll(); /* 从 NAND Flash启动 */ nand_read_ll_lp(buf, start_addr, (size + NAND_BLOCK_MASK_LP)&~(NAND_BLOCK_MASK_LP));return 0; }}然后在 include\S3c24x0.h加入2440nand寄存器的定义:
/* NAND FLASH (see S3C2440 manual chapter 6, www.100ask.net) */typedef struct { S3C24X0_REG32 NFCONF; S3C24X0_REG32 NFCONT; S3C24X0_REG32 NFCMD; S3C24X0_REG32 NFADDR; S3C24X0_REG32 NFDATA; S3C24X0_REG32 NFMECCD0; S3C24X0_REG32 NFMECCD1; S3C24X0_REG32 NFSECCD; S3C24X0_REG32 NFSTAT; S3C24X0_REG32 NFESTAT0; S3C24X0_REG32 NFESTAT1; S3C24X0_REG32 NFMECC0; S3C24X0_REG32 NFMECC1; S3C24X0_REG32 NFSECC; S3C24X0_REG32 NFSBLK; S3C24X0_REG32 NFEBLK;} /*__attribute__((__packed__))*/ S3C2440_NAND;
到这里,将uboot烧写到nandflash上就可以启动了:
U-Boot 1.1.6 (Mar 22 2013 - 11:33:36)DRAM: 64 MBFlash: 512 kB*** Warning - bad CRC, using default environmentIn: serialOut: serialErr: serialSMDK2410 # SMDK2410 #
- 移植uboot到2440
- uboot移植到mini2440
- uboot移植到mini2440
- 2440移植内核到uboot上,打印乱码
- 移植uboot到ARMer9开发系统上
- 移植uboot到ARMer9开发系统上
- 移植最新版uboot到44B0板
- uboot-1.3.2移植到s3c2410
- uboot-2009.03成功移植到mini2440
- uboot移植到Keil(mdk-arm)笔记
- uboot-2009.03成功移植到mini2440
- uboot 移植到最新的2013上
- uboot 2012.10移植到at91sam9260ek草稿之一
- Uboot 2012.10移植到at91sam9260ek草稿之一
- 移植DM9000网卡驱动到uboot
- 移植uboot到mini2440(一)
- omap4460 uboot移植到EMMC2说明
- uboot-2009.03成功移植到mini2440
- HDU 4506
- 堆内存和栈内存的区别
- android系统移植emmc记录(5)-- fastboot命令分析
- Mac下配置Redis服务器(自启动、后台运行)
- 2013腾讯编程马拉松初赛第0场(3月20)(HDU 4500 HDU4501 HDU4502 HDU4503 HDU4504)
- 移植uboot到2440
- Android HAL的被调用流程
- vb.net机房收费总结——数据库应用之链接篇
- java中的实例变量
- git用法
- Android异步加载图片
- 创建Writable Materialized View在DB之间增量同步数据
- PACS相关知识
- 2013腾讯编程马拉松初赛第1场(3月21)(HDU 4505 HDU4506 HDU4507 HDU4508 HDU4509)