注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
gongping11的个人空间 https://home.eeworld.com.cn/space-uid-67414.html [收藏] [复制] [分享] [RSS]
日志

u-boot-2010.06移植到TQ2440过程1

已有 2148 次阅读2011-10-10 21:00 |个人分类:嵌入式学习-uboot移植|

修改时钟和中断设置,关闭看门狗,修改源码添加支持CONFIG_3C2440.
u-boot第一阶段的移植,主要是CPU时钟配置以及Nor Flash 和nand Flash的代码的移植,创建一
个好的堆栈环境为实现第二阶段的C语言创造条件,难点在Nand Flash的移植问题,硬件不一样,方
法也存在差异。
首先分析第一阶段的入口地址,查看lds链接文本,找到源文件的入口
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
//上面是规定输出的数据格式
OUTPUT_ARCH(arm)
//架构体系
ENTRY(_start)
//开始点
SECTIONS
{
. = 0x00000000; //从0x00000000处开始
. = ALIGN(4);// 对齐方式,四个字节
.text :
{
//在代码段存储的形式说明了代码的入口
//因此 arch/arm/cpu/arm920t/start.o对应的源文件就是入口代码
arch/arm/cpu/arm920t/start.o (.text)
*(.text) //其他的代码暂时不需要严格的顺序,因此不用分配存储顺序
}
...
}
对应的其他段都有各自的意义,参看lds详解,了解其中的意义。
找到入口文件arch/arm/cpu/arm920t/start.S,分析其中的基本流程,进行修改
首先看两个头文件
#include <common.h> //关于错误处理等一些通用的操作
#include <config.h> //自动生成,不能修改,主要包含相关的头文件库
 
.globl _start
40 _start: b start_code //定义了入口,开始就是一个跳转命令
//下面定义了一个基本的异常中断处理过程,其中这些异常中断服务程序都是有固定的地址的,具体
查看数据手册。
41 ldr pc, _undefined_instruction
42 ldr pc, _software_interrupt
43 ldr pc, _prefetch_abort
44 ldr pc, _data_abort
45 ldr pc, _not_used
46 ldr pc, _irq
47 ldr pc, _fiq
48
49 _undefined_instruction: .word undefined_instruction
50 _software_interrupt: .word software_interrupt
51 _prefetch_abort: .word prefetch_abort
52 _data_abort: .word data_abort
53 _not_used: .word not_used
54 _irq: .word irq
55 _fiq: .word fiq
注意这段代码中的一个定义方式:
label .word number ;也就是在label这个标记处放一个字宽度的数值number
73 _TEXT_BASE:
74 .word TEXT_BASE
75
76 .globl _armboot_start
77 _armboot_start:
78 .word _start
79
80 /*
81 * These are defined in the board-specific linker script.
82 */
83 .globl _bss_start
84 _bss_start:
85 .word __bss_start
86
87 .globl _bss_end
88 _bss_end:
89 .word _end
90
91 #ifdef CONFIG_USE_IRQ
92 /* IRQ stack memory (calculated at run-time) */
93 .globl IRQ_STACK_START
94 IRQ_STACK_START:
 
95 .word 0x0badc0de
96
97 /* IRQ stack memory (calculated at run-time) */
98 .globl FIQ_STACK_START
99 FIQ_STACK_START:
100 .word 0x0badc0de
101 #endif
这些主要是分配一些段,也是和上面的相同的定义方式,注意其中的 TEXT_BASE,它是一个数,查
看board/samsung/smdk2440/config.mk
[root@Gong-Computer u-boot-2010.06]# vi board/samsung/smdk2440/config.mk
# SMDK2410 has 1 bank of 64 MB DRAM
# 3000'0000 to 3400'0000
# Linux-Kernel is expected to be at 3000'8000, entry 3000'8000
# optionally with a ramdisk at 3080'0000
# we load ourself to 33F8'0000
# download area is 3300'0000
TEXT_BASE = 0x33F80000
接下来就是真正的开始阶段:
start_code:
/*首先进入了管理员模式*/
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr, r0
由于TQ2440中没有LED部分的实现,因此关闭LED
/*关闭AT91的LED初始化*/
/* bl coloured_LED_init*/
/* bl red_LED_on*/
接下来就是关闭关门狗和中断以及配置CPU时钟,S3C2410于S3C2440的中断系统差不多,但是
S3C2440的子中断屏蔽寄存器要多一些,因此中断方便的设置存在差异,需要修改代码。
#ifdef CONFIG_S3C24X0
/* turn off the watchdog */
//S3C24x0的寄存器
# if defined(CONFIG_S3C2400)
# define pWTCON 0x15300000
# define INTMSK 0x14400008 /* Interupt-Controller base addresses */
# define CLKDIVN 0x14800014 /* clock divisor register */
#else 由于S3C2440于S3C2410的寄存器地址相同,因此不需要重新添加,复用代码即可
# define pWTCON 0x53000000
# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
 
# define INTSUBMSK 0x4A00001C
# define CLKDIVN 0x4C000014 /* clock divisor register */
// 关闭看门狗的代码
ldr r0, =pWTCON
mov r1, #0x0
str r1, [r0]
//进行中断屏蔽,关闭了中断控制器中的中断
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0]
//子中断屏蔽寄存器的设置,需要修改
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
//添加S3C2440的子中断屏蔽寄存器控制,具体的值参看手册
# if defined(CONFIG_S3C2440)
ldr r1, =0x7ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
接下来是时钟频率的控制,S3C2440于S3C2410的时钟频率存在较大的差异需要重新配置
/*添加对S3C2440CPU和USB时钟控制的设置*/
/*将时间频率设置为1:4:8*/
/*12.0000MHz 405.00 MHz 127(0x7f) 2 1*/
/*具体的值参考数据手册的255页PLL VALUE SELECTION TABLE*
#if defined(CONFIG_S3C2440)
#define MPLLCON 0x4c000004 /*添加主频率设置寄存器*/
#define UPLLCON 0x4c000008 /*添加USB时钟频率设置寄存器*/
/*设置主时钟频率为405MHZ,1:4:8*/
ldr r0,=CLKDIVN
mov r1,#5
str r1,[r0]
ldr r0,=MPLLCON
ldr r1,=0x7F021
str r1,[r0]
 
/*设置USB的时钟大小为48MHZ*/
ldr r0=UPLLCON
ldr r1,=0x38022
str r1,[r0]
#else
/*下面是其他CPU的时钟控制*/
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#endif
#endif /* CONFIG_S3C24X0 *//*以上是结束时钟控制部分*/
这边是实现了CPU 时钟的控制,板级的速度和频率也要作相应的修改,才能适应下一阶段的运行,
CPU的时钟设置完成以后需要对板级的时钟和速度进行修改,因此设置新的板级的时钟,具体的修
改为如下两个部分.
[root@Gong-Computer u-boot-2010.06]# vi board/samsung/smdk2440/smdk2440.c
/*#define FCLK_SPEED 1*/
#define FCLK_SPEED 2
#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV 0xC3
#define M_PDIV 0x4
#define M_SDIV 0x1
#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
#define M_MDIV 0xA1
#define M_PDIV 0x3
#define M_SDIV 0x1
/*具体参看书册*/
#elif FCLK_SPEED==2 /* Fout = 405 MHZ*/
#define M_MDIV 0x7f
#define M_PDIV 0x2
#define M_SDIV 0x1
#endif
/*#define USB_CLOCK 1*/
#define USB_CLOCK 2
#if USB_CLOCK==0
#define U_M_MDIV 0xA1
#define U_M_PDIV 0x3
#define U_M_SDIV 0x1
#elif USB_CLOCK==1
 
#define U_M_MDIV 0x48
#define U_M_PDIV 0x3
#define U_M_SDIV 0x2
/*具体参卡手册*/
#elif USB_CLOCK==2 /*Uout = 48MHZ*/
#define U_M_MDIV 0x38
#define U_M_PDIV 0x2
#define U_M_SDIV 0x2
#endif
[root@Gong-Computer u-boot-2010.06]# vi arch/arm/cpu/arm920t/s3c24x0/speed.c
/*主时钟的修改FCLK*/
static ulong get_PLLCLK(int pllreg)
.......
m = ((r & 0xFF000) >> 12) + 8;
p = ((r & 0x003F0) >> 4) + 2;
s = r & 0x3;
#if defined(CONFIG_S3C2440)/*设置对应的速度*/
/*参考S3C2440 芯片手册上254页的公式:PLL=(2 * m * Fin)/(p * 2s)*/
if(pllreg==MPLL)
return ((CONFIG_SYS_CLK_FREQ*m*2)/(p<<s));
#endif
/*这个是S3C2410的时钟设置*/
return (CONFIG_SYS_CLK_FREQ * m) / (p << s);
/*HCLK的修改*/
ulong get_HCLK(void)/*这个HCLK肯定也要修改,因为主频律变化了*/
{
struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();/*获得寄存器的值*/
#if defined(CONFIG_S3C2440)
/*为了使得更加具有通用性,采取判断的方式,本来可以直接返回get_FCLK/4,但是通用性下降*/
/*因为CLKDIVN的23位是关于HCLK的设置,参看手册258页*/
if(clk_power->CLKDIVN&0x06)
{
if(clk_power->CLKDIVN&0x06 == 2)
return (get_FCLK()/2);
if ((clk_power->CLKDIVN & 0x6)==6)
return((clk_power->CAMDIVN & 0x100) ? get_FCLK()/6 :get_FCLK()/3);
if ((clk_power->CLKDIVN & 0x6)==4)
return((clk_power->CAMDIVN & 0x200) ? get_FCLK()/8 :get_FCLK()/4);
}
else
return(get_FCLK());
#else/*S3C2410的时钟设置*/
return (readl(&clk_power->CLKDIVN) & 2) ? get_FCLK() / 2 : get_FCLK();
#endif
}
PCLK的时钟不需要修改。
修改部分源码,添加对CONFIG_S3C2440的支持:
这个时候编译我们都是借用了S3C2410的寄存器,还没有添加S3C2440的选项,因此修改存在
CONFIG_S3C2410的区域。这时候最好借助Source Insight跟踪存在CONFIG_S3C2410的区域,并根
据实际情况对其进行修改,存在较大差别的区域进行补充,但是不要改变结构体名字,只能改变其内
容。
首先是:s3c24x0.h中关于CPU外设的寄存器存在较大的差异
80 u32 INTOFFSET;
81 /*S3C2440于S3C2410的差别主要是在子屏蔽寄存器中的配置,寄存器位置相同*/
82 #if defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
83 u32 SUBSRCPND;
84 u32 INTSUBMSK;
85 #endif
/*S3C2440与S3C2410的DMA相同*/
93 #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
94 u32 DISRCC;
95 #endif
96 u32 DIDST;
97 #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
98 u32 DIDSTC;
99 #endif
#if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
109 u32 res[7];
110 #endif
u32 CLKDIVN;
128 /*查看手册,这是不同的地方,在时钟的配置区域得到体现*/
129 #if defined(CONFIG_S3C2440)
130 u32 CAMDIVN;
150 /*修改地方*/
151 #if defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
152 u32 LCDINTPND;
153 u32 LCDSRCPND;
154 u32 LCDINTMSK;
155 #endif
156 #ifdef(CONFIG_S3C2410)
157 u32 LPCSEL;
158 #endif
159 /*查看手册,这只是差别,其实可以不修改*/
160 #ifdef(CONFIG_S3C2440)
161 u32 TCONSEL;
162 #endif
165 #if defined(CONFIG_S3C2410)
166 /* NAND FLASH (see S3C2410 manual chapter 6) */
167 struct s3c2410_nand {
168 u32 NFCONF;
169 u32 NFCMD;
170 u32 NFADDR;
171 u32 NFDATA;
172 u32 NFSTAT;
173 u32 NFECC;
174 };
175 #endif
176 /*该寄存器的差别较大,具体的差别跟踪源码,进行修改*/
177 #if defined(CONFIG_S3C2440)
178 /* NAND FLASH (see S3C2440 manual chapter 6) */
179 struct s3c2410_nand { //不要改变结构体的名字,只是改变其内容
180 u32 NFCONF;
181 u32 NFCONT;
182 u32 NFCMD;
183 u32 NFADDR;
184 u32 NFDATA;
185 u32 NFMECCD0;
186 u32 NFMECCD1;
187 u32 NFSECCD;
188 u32 NFSTAT;
189 u32 NFESTAT0;
190 u32 NFESTAT1;
191 u32 NFMECC0;
192 u32 NFMECC1;
193 u32 NFSECC;
194 u32 NFSBLK;
195 u32 NFEBLK
196 };
197 #endif
436 #if defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
。。。。。。。。
486 #ifdef(CONFIG_S3C2440)
487 u32 res9;
488 u32 DSC0;
489 u32 DSC1;
 
490 u32 MSLCON;
491 u32 GPJCON;
492 u32 GPJDAT;
493 u32 GPJUP;
494 u32 res10;
495 #endif
其次:[root@Gong-Computer u-boot-2010.06]# vi arch/arm/include/asm/arch-s3c24x0/s3c24x0_cpu.h
#elif defined (CONFIG_S3C2410)|| defined(CONFIG_S3C2440)
#include <asm/arch/s3c2410.h>
然后是:
[root@Gong-Computer u-boot-2010.06]# vi drivers/i2c/s3c24x0_i2c.c查找在defined(CONFIG_S3C2410)后面添加||defined(CONFIG_S3C2440)即可。
/*添加新的选项,S3C2440*/
60 #if defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
61 return (readl(&gpio->GPEDAT) & 0x8000) >> 15;
62 #endif
79 #if defined(CONFIG_S3C2410)|| defined(CONFIG_S3C2440)
80 writel((readl(&gpio->GPEDAT) & ~0x4000) | (x & 1) << 14, &gpio->GPEDAT);
81 #endif
131 #if defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
132 ulong old_gpecon = readl(&gpio->GPECON);
133 #endif
140 #if defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
141 /* set I2CSDA and I2CSCL (GPE15, GPE14) to GPIO
166 #if defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
167 writel(old_gpecon, &gpio->GPECON);
最后是:[root@Gong-Computer u-boot-2010.06]# vi common/serial.c
71 #elif defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
72 #if defined(CONFIG_SERIAL1)
160#if defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
161 serial_register(&s3c24xx_serial0_device);
162 serial_register(&s3c24xx_serial1_device);
163 serial_register(&s3c24xx_serial2_device);
[root@Gong-Computer u-boot-2010.06]# vi arch/arm/cpu/arm920t/start.S
/*为了调试方便需要将cpu初始化部分注释掉,在后面阶段还是会打开,现在只是调试*/
207 /*
208 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
209 bl cpu_init_crit
210 #endif
211 */

修改板级相关的头文件:

[root@Gong-Computer u-boot-2010.06]# vi include/configs/smdk2440.h

//#define CONFIG_S3C2410   1

//#define CONFIG_SMDK2410  1

添加

#define CONFIG_S3C244   1

#define CONFIG_SMDK244  1

这样可以分类讨论。因为前面已经添加了CONFIG_S3C2440相关的代码,因此不会出很多的错误。
[root@Gong-Computer u-boot-2010.06]# make -d
采用调试的方式进行编译,但是出现了一些错误,是在 timer.c 中出现 error "tbclk not configured",不
知道怎么办只能查看源码了,查看源码发现是因为屏蔽掉了smdk2440.h中的#define
CONFIG_SMDK2410,根据错误原因我在源码中添加:
[root@Gong-Computer u-boot-2010.06]# vi arch/arm/cpu/arm920t/s3c24x0/timer
.c
176 ulong get_tbclk(void)
177 {
178 ulong tbclk;
179
180 #if defined(CONFIG_SMDK2400) || defined(CONFIG_TRAB)
181 tbclk = timer_load_val * 100;
182 #elif defined(CONFIG_SBC2410X) || \
183 defined(CONFIG_SMDK2410) || \
184 defined(CONFIG_SMDK2440) || \ //添加项
185 defined(CONFIG_VCMA9)
186 tbclk = CONFIG_SYS_HZ;
187 #else
188 # error "tbclk not configured"
189 #endif
190
191 return tbclk;
192 }
修改完成以后,重新编译调试;
[root@Gong-Computer u-boot-2010.06]# make -d
.....
Invoking recipe from Makefile:426 to update target `System.map'.
Putting child 0x9ea4ce0 (System.map) PID 29959 on the chain.
Live child 0x9ea4ce0 (System.map) PID 29959
Reaping winning child 0x9ea4ce0 PID 29959
Removing child 0x9ea4ce0 PID 29959 from chain.
Successfully remade target file `System.map'.
Finished prerequisites of target file `all'.
Must remake target `all'.
Successfully remade target file `all'.
这说明修改完成了,并没有错误了。这样可以很实现调试了。
第一次调试的过程中我将时钟配置部分的代码写反了,导致总是出现data abort错误,
EmbedSky> tftp 0x30000000 u-boot_debug.bin
dm9000 i/o: 0x20000300, id: 0x90000a46
MAC: 0a:1b:2c:3d:4e:5f
TFTP from server 192.168.10.154; our IP address is 192.168.10.122
Filename 'u-boot_debug.bin'.
Load address: 0x30000000

Loading: T #######
done
Bytes transferred = 101152 (18b20 hex)
EmbedSky> go 0x30000000
## Starting application at 0x30000000 ...
data abort
pc : [<300000a0>] lr : [<33d0d5f8>]
sp : 33cbdb74 ip : ffffffff fp : 33cbdde1
r10: 33cbdce1 r9 : 00000000 r8 : 33cbffdc
r7 : 33cbdde1 r6 : 00000002 r5 : 33cbdc94 r4 : 30000000
r3 : 00000002 r2 : 50000000 r1 : 0007f021 r0 : 4c000004
Flags: nZCv IRQs off FIQs off Mode SVC_32
Resetting CPU ...
仔细检查发现是在MPLLCON配置过程中对寄存器赋值的代码出错了,写成了
str r0,[r1]
改写成
str r1,[r0]
就实现了时钟部分最基础的移植,采用TQ2440原来的u-boot通过TFTP上传镜像到SDRAM,即可
实现下面的结果。
##### Boot for Nor Flash Main Menu #####
##### EmbedSky USB download mode #####
........
EmbedSky> tftpboot 0x30000000 u-boot_debug.bin
dm9000 i/o: 0x20000300, id: 0x90000a46
MAC: 0a:1b:2c:3d:4e:5f
TFTP from server 192.168.10.154; our IP address is 192.168.10.122
Filename 'u-boot_debug.bin'.
Load address: 0x30000000
Loading: T #######
done
Bytes transferred = 101152 (18b20 hex)
EmbedSky> go 0x30000000
## Starting application at 0x30000000 ...
U-Boot 2010.06 (Oct 06 2011 - 15:21:00)
DRAM: 64 MiB
Flash: 512 KiB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: CS8900-0
SMDK2410 #
这说明DRAM部分已经没有问题了。
 
评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章