我的armlinux移植笔记.docx
《我的armlinux移植笔记.docx》由会员分享,可在线阅读,更多相关《我的armlinux移植笔记.docx(78页珍藏版)》请在冰点文库上搜索。
![我的armlinux移植笔记.docx](https://file1.bingdoc.com/fileroot1/2023-5/27/df9c5018-e8b9-4d96-9f2a-bb41d27ba14c/df9c5018-e8b9-4d96-9f2a-bb41d27ba14c1.gif)
我的armlinux移植笔记
一、uboot1.2.0移植
移植环境:
VMware5.5.2+redhat9
开发板:
SKY_2440B_V5.0或者V3.0
编译器:
cross3.2(下载地址ftp:
//ftp.arm.linux.org.uk/pub/armlinux/toolchain/cross3.2.tar.gz)
Uboot:
u-boot-1.2.0(下载地址:
ftp:
//ftp.denx.de/pub/u-boot/)
先说明一下,移植过程按照tekkaman的blog移植的。
博客地址
其中uboot的移植参照
所下面写的移植过程,很多都是从blog上copy过来的,有不同的地方,我会另外指出。
1.用dk登录linux主机,在dk下创建一个myboard文件夹
2.解压cross3.2:
解压到/usr/local/arm/文件夹下
最好在/usr/local/arm/下创建一个3.2文件夹,把解压在arm文件夹下的文件(夹)全部移到3.2下,因为后面可能还会用到3.4.1的交叉编译器。
3.解压uboot:
将uboot解压到myboard文件夹下
tarxzvfu-boot-1.2.0.tar.bz2–C/home/dk/myboard/
4.进入uboot目录,修改Makefile
cdu-boot-1.2.0
viMakefile
(1)新建我的编译项
在1923行,即smdk2410_config编译项之后增加我的编译项
tekkaman2440_config :
unconfig
@$(MKCONFIG)$(@:
_config=)armarm920ttekkaman2440tekkamans3c24x0
各项的意思如下:
arm:
CPU的架构(ARCH)
arm920t:
CPU的类型(CPU),其对应于cpu/arm920t子目录。
tekkaman2440:
开发板的型号(BOARD),对应于board/tekkaman/tekkaman2440目录。
tekkaman:
开发者/或经销商(vender)。
s3c24x0:
片上系统(SOC)。
(2)修改交叉编译器路径,我用的cross3.2是在/usr/local/arm/
修改128行
CROSS_COMPILE=/usr/local/arm/3.2/bin/arm-linux-
5.在/board子目录中建立自己的开发板tekkaman2440目录
由于我在上一步板子的开发者/或经销商(vender)中填了tekkaman,所以开发板tekkaman2440目录一定要建在/board子目录中的tekkaman目录下,否则编译会出错。
$cdboard
$mkdirtekkamantekkaman/tekkaman2440
$cp-arfsbc2410x/* tekkaman/tekkaman2440/
$cdtekkaman/tekkaman2440
$mvsbc2410x.ctekkaman2440.c
还要记得修改自己的开发板tekkaman2440目录下的Makefile文件,不然编译时会出错:
$viMakefile
COBJS :
=tekkaman2440.oflash.o
6.在include/configs/中建立配置头文件
$cpinclude/configs/sbc2410x.hinclude/configs/tekkaman2440.h
7.测试编译能否成功
$maketekkaman2440_config
Configuringfortekkaman2440board...
(如果出现:
$maketekkaman2440_config
Makefile:
1927:
***遗漏分隔符。
停止。
请在U-boot的根目录下的Makefile的
@$(MKCONFIG)$(@:
_config=)armarm920ttekkaman2440tekkaman)
前加上“Tab”键)
$make
到这一步应该能编译成功,但是我的并没有编译成功,提示/common/cmd_bootm.c文件的464行的U_BOOT_CMD有错误,我是把其中的从#ifdefCONFIG_OF_FLAT_TREE到#endif都屏蔽掉,这样就可以编译过去了。
可能还会出现类似的问题,用同样的方法可以解决。
下面修改Uboot中的文件,以匹配开发板
8.修改/cpu/arm920t/start.S
这个函数是arm920t系列的共有启动的汇编代码,UBOOT执行的第一个程序
(0)修改寄存器地址定义
/*turnoffthewatchdog*/
#ifdefined(CONFIG_S3C2400)
#definepWTCON 0x15300000
#defineINTMSK 0x14400008 /*Interupt-Controllerbaseaddresses*/
#defineCLKDIVN 0x14800014 /*clockdivisorregister*/
#elifdefined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
#definepWTCON 0x53000000这个定义了看门狗的寄存器地址
#defineINTMSK 0x4A000008 /*Interupt-Controllerbaseaddresses*/中断掩码的寄存器地址
#defineINTSUBMSK 0x4A00001C中断掩码的寄存器地址
#defineCLKDIVN 0x4C000014 /*clockdivisorregister*/完成时钟分份的寄存器
#endif
(1)修改中断禁止部分
#ifdefined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)||defined(CONFIG_S3C2440)
ldr r0,=pWTCON把看门狗寄存器地址给了r0
mov r1,#0x0r1等于0
str r1,[r0]看门狗寄存器等于0因为在启动时要关闭看门狗,不能让他产生中断影响启动,此时也根本不需要任何中断
/*
*maskallIRQsbysettingallbitsintheINTMR-default
*/
mov r1,#0xffffffff关闭所有中断
ldr r0,=INTMSK
str r1,[r0]
#ifdefined(CONFIG_S3C2410)
ldr r1,=0x7ff //根据2410芯片手册,INTSUBMSK有11位可用,
//vivi也是0x7ff,不知为什么U-Boot一直没改过来。
ldr r0,=INTSUBMSK
str r1,[r0]
#endif
#if defined(CONFIG_S3C2440)
ldr r1,=0x7fff //根据2440芯片手册,INTSUBMSK有15位可用
ldr r0,=INTSUBMSK
str r1,[r0]
#endif
(2)修改时钟设置(2440的主频可达533MHz,但是我设到533MHz时系统很不稳定,不知是不是SDRAM和总线配置的影响,所以现在先设到405MHz,以后在改进。
)
ldr r0,=CLKDIVN
这个值决定了FCLKHCLKPCLK的频率
FCLK是供给CPU的是主频
HCLK是供给AHB总线(主要用于高性能模块(如CPU、DMA和DSP等)之间的连接,作为SoC的片上系统总线)上的外围设备
PCLK是供给APB总线(APB主要用于低带宽的周边外设之间的连接,例如UART、1284等)上的外围设备
UCLK是两路PLL中一路供给USB的频率
ARM总线技术在这里我不多介绍了,对硬件感兴趣的同学建议多多了解,我有一回面试人家就问我这个了,405MHZ已经很高了,基本都够了,2410的200MHZ就能播放Mplayer视频,据说很流畅。
mov r1,#5/*FCLK:
HCLK:
PCLK=1:
4:
8*/
str r1,[r0]
mrc p15,0,r1,c1,c0,0 /*readctrlregister tekkaman*/
orr r1,r1,#0xc0000000 /*Asynchronous tekkaman*/
mcr p15,0,r1,c1,c0,0 /*writectrlregistertekkaman*/
他是用到了协处理器P15,此处理器主要设置mmu,时钟模式,caches,保护模式的。
先把C0C1的值读出到r1,设置后再写回。
FCLK:
HCLK:
PCLK的比例由CLKDIVN决定的,CLKDIVN寄存器的HDIVN和PDIVN决定比例的大小。
因为此时的HDIVH不为0,将快速总线模式改为异步总线模式,操作协处理器P15改变模式即可,如果HDIVH不为0,而且是快速总线模式的话,那么CPU的主频由hclk控制,这样可以实现不改变HCLK和PCLCK的同时就能使CPU的主频减半或更多。
网上的大虾说没有以上几句主频会是12MHZ,我的观点不同。
这是数据手册原文
IfHDIVNisnot0andtheCPUbusmodeisthefastbusmode,theCPUwilloperatebytheHCLK.ThisfeaturecanbeusedtochangetheCPUfrequencyasahalformorewithoutaffectingtheHCLKandPCLK
#ifdefined(CONFIG_S3C2440)
/*now,CPUclockis405.00Mhz tekkaman*/
mov r1,#CLK_CTL_BASE /*tekkaman*/这是时钟寄存器的基地址
mov r2,#MDIV_405 /*mpll_405mhz tekkaman*/
add r2,r2,#PSDIV_405 /*mpll_405mhz tekkaman*/
str r2,[r1,#0x04] /*MPLLCONtekkaman*/设置MPLLCON
#endif
#ifdefined(CONFIG_S3C2410)
/*now,CPUclockis202.8Mhz tekkaman*/
mov r1,#CLK_CTL_BASE /*tekkaman*/
mov r2,#MDIV_200 /*mpll_200mhz tekkaman*/
add r2,r2,#PSDIV_200 /*mpll_200mhz tekkaman*/
str r2,[r1,#0x04] /*MPLLCONtekkaman*/
#endif
#endif /*CONFIG_S3C2400||CONFIG_S3C2410||CONFIG_S3C2440*/
红色部分是我添加的,利用vivi的代码,将其设为405.00MHz并在前面加上:
#elifdefined(CONFIG_S3C2410)
#definepWTCON 0x53000000
#defineINTMSK 0x4A000008 /*Interupt-Controllerbaseaddresses*/
#defineINTSUBMSK 0x4A00001C
#defineCLKDIVN 0x4C000014 /*clockdivisorregister*/
#defineCLK_CTL_BASE 0x4C000000 /*tekkaman*/
#ifdefined(CONFIG_S3C2440)
#defineMDIV_405 0x7f<<12 /*tekkaman*/
#definePSDIV_405 0x21 /*tekkaman*/
#endif
#ifdefined(CONFIG_S3C2410)
#defineMDIV_200 0xa1<<12 /*tekkaman*/
#definePSDIV_200 0x31 /*tekkaman*/
#endif
#endif〕
(3)将从Flash启动改成从NANDFlash启动。
(特别注意:
这和2410的程序有不同,不可混用!
!
!
是拷贝vivi的代码。
)
将以下U-Boot的重定向语句段:
这段代码将uboot搬运到ram中,这个是没有存放在nand的情况,下面咱们来看一下不在nand启动和在nand启动时此处的区别。
#ifndefCONFIG_SKIP_RELOCATE_UBOOT
relocate:
/*relocateU-BoottoRAM */
adr r0,_start /*r0<-currentpositionofcode */nor中的起始地址给了r0
ldr r1,_TEXT_BASE /*testifwerunfromflashorRAM*/ram中的uboot代码的起始地址(这里关于uboot搬运这块在内存地址的部分,分了很多段,每一段空间具有不同功能,这是你理解uboot必须掌握的,非常关键,解释后续会提到些)
cmp r0,r1 /*don'trelocduringdebug */比较两个地址是否相同,不同则进行下面的搬运工作
beq stack_setup
在这里你会发现搬运了全部uboot,有的uboot把uboot的c部分搬运到内存_TEXT_BASE里面所放的地址处。
ldr r2,_armboot_start
ldr r3,_bss_start
sub r2,r3,r2 /*r2<-sizeofarmboot */_bss_start-_armboot_start=armboot 因为_armboot_end的结束位置就是bss区的开始位置所以能计算出uboot代码的大小
add r2,r0,r2 /*r2<-sourceendaddress */
以下就是把整个代码搬运到_TEXT_BASE里面所放的地址处,记住是内存地址,哈哈!
!
copy_loop:
ldmia r0!
{r3-r10} /*copyfromsourceaddress[r0] */
stmia r1!
{r3-r10} /*copyto targetaddress[r1] */
cmp r0,r2 /*untilsourceendaddreee[r2] */
ble copy_loop
#endif /*CONFIG_SKIP_RELOCATE_UBOOT*/
替换成:
因为nand和nor的启动是有区别的,NORFlash储存器较贵,而NANDFlash则相对便宜,所以很多用户选择在NANDFlash中执行启动代码,在SDRAM中执行主程序。
为支持NANDFlash的BootLader,S3C2440有一个内部SRAM缓冲,称为‘Steppingstone’,启动时,NANDFlash的最先4K字节将被装载到Steppingstone中,装载到Steppingstone中的启动代码将执行。
这都是硬件自动完成的不需要咱们软件参与。
一般来说,启动代码将把NANDFlash的内容拷贝到SDRAM中,ECC将检测NAND的合法性,当拷贝完成时,主程序将在SDRAM中执行电源开启后,或系统重启后,NANDFlash控制器将自动装载4KB的BootLoader代码,载入代码后将执行。
注意在自启动时,ECC不检测,因此,NANDFlash的头4KB要保证无错,下面我来带你分析它的源代码喽,嘿嘿!
!
!
!
忽然想家了,对了nand的硬件连接简单有兴趣的看一下了(NCON-AdvFlash,GPG13-Pagesize,GPG14-Addresscycle,GPG15-总线宽度)
#ifdefCONFIG_S3C2440_NAND_BOOT @tekkaman@在以后会定义它的,不要忘了
@resetNAND
mov r1,#NAND_CTL_BASEnand的寄存器基地址
ldr r2,=((7<<12)|(7<<8)|(7<<4)|(0<<0))CLE&ALE期间设置值|TWRPH0期间设置值|TWRPH0期间设置值|8位总线
str r2,[r1,#oNFCONF]设置NFCONF寄存器,初始化作用
ldr r2,[r1,#oNFCONF]
ldr r2,=((1<<4)|(0<<1)|(1<<0))@ActivelowCEControl初始化ECC解码/编码器(只写)|强制拉低nFCE(允许片选)|允许NAND控制器
str r2,[r1,#oNFCONT]设置NFCONT
ldr r2,[r1,#oNFCONT]
ldr r2,=(0x6) @RnBClear和nandisbusy
str r2,[r1,#oNFSTAT]
ldr r2,[r1,#oNFSTAT]
mov r2,#0xff @RESETcommand
strb r2,[r1,#oNFCMD]
movr3,#0 @wait就是一下段延时
nand1:
add r3,r3,#0x1
cmpr3,#0xa
blt nand1
nand2:
ldr r2,[r1,#oNFSTAT] @waitready
tst r2,#0x4
beq nand2
ldr r2,[r1,#oNFCONT]
orr r2,r2,#0x2 @FlashMemoryChipDisable
str r2,[r1,#oNFCONT]
@getreadtocallCfunctions(fornand_read())
ldr sp,DW_STACK_START @setupstackpointer
movfp,#0 @nopreviousframe,sofp=0初始化frame的起始位置
@copyU-BoottoRAM
ldr r0,=TEXT_BASE设置第1个参数:
UBOOT在RAM中的起始地址
mov r1,#0x0设置第2个参数:
NandFlash的起始地址
movr2,#0x20000设置第3个参数:
UBOOT的长度(128KB)
bl nand_read_ll在board/tekkaman/tekkaman2440/nand_read.c我会解析这个函数的作用
tst r0,#0x0如果函数的返回值为0,表示执行成功.
beq ok_nand_read执行内存比较,比较什么呢?
他比较搬运到内存中的代码和在内部ram的前4kb是否一样
bad_nand_read:
loop2:
b loop2 @infiniteloop
ok_nand_read:
@verify
movr0,#0内部RAM的起始地址
ldr r1,=TEXT_BASEUBOOT在RAM中的起始地址
movr2,#0x400 @4bytes*1024=4K-bytes
go_next:
ldr r3,[r0],#4
ldr r4,[r1],#4
teq r3,r4进行比较
bne notmatch
subsr2,r2,#4
beq stack_setup
bne go_next
notmatch:
内存中的代码和在内部ram的前4kb如果不一样,就无限的循环在这了,如果你不努力的去体会每一句,你的功力就像他一样了,哈哈!
loop3:
b loop3 @infiniteloop
#endif@CONFIG_S3C2440_NAND_BOOT @tekkaman@@
在“ _start_armboot:
.wordstart_armboot ”后加入:
.ali