单片机
返回首页

u-boot移植之三 uboot-2015.04的移植过程

2022-07-25 来源:csdn

1. 生成mini2440的文件,并修改对应的Kconfig

(1)将smdk2410特有的文件拷贝到一个以mini2440命令的副本。(注:使用find查看smdk2410相关文件并修改为mini2440)

(1.1)cp configs/smdk2410_defconfig configs/mini2440_defconfig

并修改CONFIG_TARGET_SMDK2410为CONFIG_TARGET_MINI2440

(1.2)cp include/configs/smdk2410.h include/configs/mini2440.h

暂时只修改部分内容,剩余的在其他功能中说明修改。

(1.2.1)修改配制宏

//#define CONFIG_S3C2410  /* specifically a SAMSUNG S3C2410 SoC */

//#define CONFIG_SMDK2410  /* on a SAMSUNG SMDK2410 Board */

#define CONFIG_S3C2440  /* specifically a SAMSUNG S3C2440 SoC */

#define CONFIG_MINI2440  /* on a FriendlyArm mini2440 Board */

(1.2.2)CONFIG_SYS_PROMPT修改为'mini2440 # ',实质是uboot命令行。

(1.2.3)删除CONFIG_ENV_IS_IN_FLASH的宏定义,并添加语句define CONFIG_ENV_IS_IN_NAND

(1.2.3)CONFIG_SYS_TEXT_BASE修改为0x33f00000(有问题稍后说明),是uboot链接的时候的基地址。

(1.3)cp board/samsung/smdk2410/ board/samsung/mini2440 -rf

(1.3.1)board/samsung/mini2440/Kconfig

把smdk2410相关内容都改成mini2440

(1.3.2)board/samsung/mini2440/lowlevel_init.S稍后修改

(1.3.3)board/samsung/mini2440/MAINTAINERS

暂时不清楚其作用,照样子把smdk2410相关内容都改成mini2440

(1.3.4)board/samsung/mini2440/Makefile

修改obj-y为mini2440.o

(1.4)mv board/samsung/mini2440/smdk2410.c board/samsung/mini2440/mini2440.c

修改MACH_TYPE_SMDK2410为MACH_TYPE_MINI2440

最新的u-boot-2015.04有关于MACH_TYPE_MINI2440的定义,这里不用重复定义了。

(2)'grep smdk2410 * -r'搜索smdk2410相关内容,并根据其更改mini2440相关。

(2.1)machine_is_smdk2410未使用,忽略处理。

(2.2)arch/arm/Kconfig

首先,在TARGET_SMDK2410配置项后增加MINI2440的配置项

config TARGET_MINI2440

bool 'Support mini2440'

select CPU_ARM920T

然后source 'board/samsung/smdk2410/Kconfig'这句话后面加上如下语句:

source 'board/samsung/mini240/Kconfig'



2. 修改源文件

按照启动的顺序进行修改,一般代码添加在原有S3C2410代码的后面,后面不再说明功能位置。

(1)arch/arm/cpu/arm920t/start.S

(1.1)在原来配置看门狗,时钟分频寄存器的位置添加S3C2440的代码

#elif defined(CONFIG_S3C2440)  

# define pWTCON  0x53000000  

# define INTMSK  0x4A000008  

# define INTSUBMSK  0x4A00001C  

# define CLKDIVN  0x4C000014  

# define MPLLCON  0x4C000004  

# define UPLLCON  0x4C000008


(1.2)添加S3C2440关中断代码

# if defined(CONFIG_S3C2440)  

ldr  r1, =0x7fff  

ldr  r0, =INTSUBMSK  

str  r1, [r0]  

# endif


(1.3)修改lowlevel_init代码

指定位置修改为如下信息

#define B1_BWSCON     (DW16)

#define B3_BWSCON     (DW16 + UBLB)

#define B4_BWSCON     (DW16 + WAIT + UBLB)

#define B5_BWSCON     (DW8)

#define B4_Tcos   0x3  /*  4clk */

#define B4_Tcoh   0x1  /*  1clk */

#define B4_Tah   0x3  /*  4clk */

#define B4_Tacp   0x6 /*  6clk */

#define REFCNT   0x4f4  /* period=7.8125, HCLK=100Mhz, (2048+1-7.8125*100) */

倒数第三行修改为.word 0xb1



(1.4)修改board_early_init_f函数

board_early_init_f在board/samsung/mini2440/board_f.c中。

首先增加转为异步模式的代码

__asm__(   'mrc  p15, 0, r1, c1, c0, 0n'  /* read ctrl register  */  

'orr  r1, r1, #0xc0000000n'  /* Asynchronous */  

'mcr  p15, 0, r1, c1, c0, 0n'  /* write ctrl register  */  

:::'r1'

);

然后修改时钟相关寄存器的值

#define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x04<<4)|(0x01))

#define S3C2440_UPLL_48MHZ      ((0x28<<12)|(0x01<<4)|(0x03))

#define S3C2440_CLKDIV          0x03    /* FCLK:HCLK:PCLK = 1:2:4 */


(1.5)修改include/configs/mini2440.h网卡信息

#define CONFIG_DRIVER_DM9000  1  

#define CONFIG_DM9000_USE_16BIT 1  

#define CONFIG_DM9000_BASE  0x20000000  //网卡在BANK4上,地址是0x20000000

#define DM9000_IO  0x20000000     

#define DM9000_DATA  0x20000004  


3. 配置

make smdk2410_defconfig


4. 编译生成uboot

4.1编译

修改主Makefile,增加如下语句

CROSS_COMPILE:= arm-linux- 

ARCH := arm

然后执行make all

4.1 u-boot环境变量的设置

提示需要定义CONFIG_ENV_OFFSET

这里增加两个宏如下:

#define CONFIG_ENV_SIZE  0x50000

#define CONFIG_ENV_OFFSET  0x100000  

并修改CONFIG_ENV_ADDR如下:

#define CONFIG_ENV_ADDR  (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)

环境变量的配置参数设置于nand的0x100000地址,长度为0x20000。

这里规定:  

uboot存放在0x0-0x100000地址处。

环境变量放在0x100000-0x150000地址处。

0x150000-0x550000放置linux内核,即0x150000开始的4M空间。

同时加入如下环境变量,作为启动参数和mtd文件系统挂载的参数等

#define CONFIG_BOOTCOMMAND  'nand read.jffs2 0x30007FC0 0x140000 0x400000; bootm 0x30007FC0'

#define CONFIG_BOOTARGS  'mtdparts=nandflash0:1M(uboot)ro,256K(env),5M(kernel)ro,-(rootfs) root=/dev/mtdblock3 rw rootfstype=jffs2'


4.2 u-boot.lds语法错误

编译出现了u-boot.lds语法错误,根据前面分析主目录的arch/arm/cpu/u-boot.lds拷贝过来,开头包含了config.h,其中在config.h中包含的内容中有一个mini2440.h,而主目录的的错误信息恰巧就是mini2440.h中以//开头注释的行(笔者之前修改的源代码都用//注释并未删除),这里删除后重新编译。

这时候编译已经成功了,可以得到u-boot.bin

4.3 nandflash移植

回头看一下mini2440.h,还有nandflash部分没有修改,仍然是2410的代码。

搜索CONFIG_NAND_S3C2410,发现在drivers/mtd/nand/s3c2410_nand.c有关于2410的

(1)cp drivers/mtd/nand/s3c2410_nand.c drivers/mtd/nand/s3c2440_nand.c

(2)并在drivers/mtd/nand/Makefle中增加如下语句:

obj-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o

(3)修改s3c2440_nand.c

(3.1)board_nand_init函数

将2410部分代码删掉,并将修改寄存器的代码和nand_chip代码改为如下内容:

#if defined(CONFIG_S3C2440)

#define TACLS   2

#define TWRPH0  1

#define TWRPH1  0

#define BusWidth  0

nand_reg->nfconf =  (BusWidth<<0) | (TWRPH1<<4) | (TWRPH0<<8) | (TACLS<<12);

nand_reg->nfcont &= ~((1<<4) | (1<<1) | (1<<0)) ;

nand_reg->nfcont |= ((1<<4) | (0<<1) | (1<<0));

nand->IO_ADDR_R = (void *)&nand_reg->nfdata;

nand->IO_ADDR_W = (void *)&nand_reg->nfdata;

nand->select_chip = NULL;

nand->cmd_ctrl = s3c24x0_hwcontrol;

nand->dev_ready = s3c24x0_dev_ready;  

nand->options     = 0; //8-bit 

nand->ecc.mode  = NAND_ECC_SOFT;

#endif

(3.2)s3c24x0_hwcontrol

这里简单分析下该函数,由于2410的函数是已经有的,按照这个分析,2440照着改便可以。值得注意的是该函数中IO_ADDR_W是是一个指针,对它进行或运算,实质就是加法,更换寄存器。这里只要把ctrl变量用NAND_CLE或NAND_ALE代替,IO_ADDR_W就自然定位到指定的寄存器。

处理ctrl那些if语句删掉,修改为如下格式

if(ctrl & NAND_CLE)

{

IO_ADDR_W = 0x4E000008;

}

else if(ctrl & NAND_ALE)

{

IO_ADDR_W = 0x4E00000C;

}

else

{

IO_ADDR_W = 0x4E000010;

}

由于2410与2440的片选信号的寄存器位置不同,修改代码如下:

#define S3C2440_NFCONF_nFCE (1<<1)

if (ctrl & NAND_NCE)

writel(readl(&nand->nfcont) & ~S3C2440_NFCONF_nFCE,

  &nand->nfconf);

else

writel(readl(&nand->nfcont) | S3C2440_NFCONF_nFCE,

  &nand->nfconf);



4.4 增加启动参数

#define CONFIG_BOOTCOMMAND  'nand read.jffs2 0x30007FC0 0x150000 0x400000; bootm 0x30007FC0'


4.5 uboot命令的配置

u-boot-1.1.6版本命令是在CONFIG_COMMANDS宏定义的,但是在u-boot-2015.04模范的linux的Kconfig,是在Kconfig中配置的。


5. openjtag调试

下载到nandflash中,无反应,因此需要使用openjtag调试,查看问题,同时需要得到反汇编文件u-boot.dis作为调试使用。

需要在主Makefile的All-y的定义处增加u-boot.dis

5.1 问题之nandfalsh程序未拷贝到SDRAM中

经过jlink调试发现lowlevel_init处异常,用jlink命令mem 0 1010查看发现原因是超过4K内存了,超过4K内存的部分不能再steppingstone中使用。

所以需要把lowlevel_init的链接地址放在4K地址空间内,然后添加或修改把nandflash的数据拷贝到sdram的代码。

5.1.1将lowlevel_init移到4K地址空间内。

arch/arm/cpu/u-boot.lds中在start.o后增加如下内容:

board/samsung/mini2440/lowlevel_init.o (.text*)

并在board/samsung/mini2440/Makefile中lowlevel_init.o前面的内容修改为extra-y,防止编译入built-in.o使lowlevel_init.o多次链接。

5.1.2增加拷贝NANDFLASH程序到SDRAM的代码

新增加的代码放在boardsamsungmini2440mni2440_init.c中,因为与之前的裸机操作时钟和NANDFLASH代码基本一致,这里不再粘贴。

同时在boardsamsungmini2440Makefile增加如下代码:

extra-y   += mini2440_init.o

注:这里使用extra-y,而不是使用obj-y。因为obj-y会编译到built-in.o,而后面u-boot.lds有会加入mini2440_init.o,所以会提示多次定义错误。

为了保证mini2440_init.o在4K之前内,需要在arch/arm/cpu/u-boot.lds中'CPUDIR/start.o (.text*)'下一行增加如下代码:

boardsamsungmini2440mni2440_init.o (.text*)

为了把NANDFLASH代码移植到SDRAM中,需要保证时钟和存储控制器正确初始化,并增加适当的nandflash处理函数。

其中,控制器初始化在cpu_init_crit完成。因此需要增加一个时钟的初始化。

另外需要考虑的是堆栈空间,这里设置4K内存处为堆栈栈顶,因此实际能用的内存是不到4K的。

    然后通过ldr  pc, =afterCopyCode2Ram字节跳到SDRAM中执行。  

在之前加上另外一段代码,判断当前是否已经在SDRAM中。

注:adr  r0, my_copy与ldr  r2,my_copy区别在于adr寻址范围小,如果在SDRAM中,r0会得到链接地址,在stepping stone则为0。使用ldr则r2一定为链接地址。

注意:在u-boot-1.6中使用了_start编号判断是否在SDRAM中,这里使用该标号的时候编译不通过,可能是因为超越了adr的寻址范围,这里选择就近的编号my_copy来判断是否已经运行在SDRAM中。

在cpu_init_crit前增加代码如下:

ldr sp,=0x1000  

bl  clock_init

因此, 在arch/arm/cpu/arm920t/start.S的'bl  _main'前增加这样一段代码:  

my_copy:

adr  r0, my_copy  

ldr  r1,=my_copy  

cmp  r0,r1

beq  afterCopyCode2Ram

mov  r0,#0

ldr  r1,=CONFIG_SYS_TEXT_BASE

ldr  r2,=_start

ldr  r3,=_end  

sub  r2, r3, r2  

bl  copyCode2Ram

afterCopyCode2Ram:

ldr  pc, =afterCopyCode2Ram  

注:尽管relocate.S里面已经有了重定位代码,但是这里还是有一步重定位判断,是因为该u-boot重定位代码之前调用了board_init_f,已经超出了4K地址空间,并且该函数用到的空间过大,不便于移到4K地址空间内。


5.2 问题之内存区域重叠

在board_init_f中调用了init_sequence_f函数指针指向的一组函数。其中,最后一个是jump_to_copy,简单观察上下文初步认定该版本的u-boot会把自己加载到CONFIG_SYS_TEXT_BASE指向的地址,然后将起移到内存区的地址最高端。这里CONFIG_SYS_TEXT_BASE为0x33f00000,uboot.bin长度达到了549.5K,这里拷贝的内存区的源地址和目的地址有地址重叠区域。这里将CONFIG_SYS_TEXT_BASE修改为0x32000000。


5.3 nand命令失败

uboot启动已经可以正常启动,而使用nand系列的命令的时候会出现“no devices available”的提示。

经过调试定位,发现是nand_scan=> nand_scan_ident =>nand_get_flash_type返回值异常。这个函数大量调用了nand_chip的指针函数,回想之前增加的s3c2440_nand.c代码,应该是这个函数出现了问题。

经过检查是s3c24x0_hwcontrol函数写寄存器的时候writel第三个参数忘记改会来了。


5.4 uboot参数地址的设置

修改过后,nandflash可以正常操作了,但是后来无法启动,是因为之前无法读取nandflash的uboot参数,所以使用自动的参数。

追踪发现uboot是以块为单位处理uboot参数的,一个块大小是0x20000,而之前设置的uboot为0x50000(即CONFIG_ENV_SIZE),这里改为0x40000. 

至此,nandflash空间调整如下:

0 - 0x100000  1M  u-boot

0x100000 - 0x140000  256K  u-boot环境参数

0x140000 - 0x540000 4M  linux内核

0x540000 - 最后   文件系统


5.5 网卡驱动的移植

在include/configs/mini2440.h中删除CS8900网卡的宏定义,然后添加如如下定义

#define CONFIG_DRIVER_DM9000  1  

#define CONFIG_DM9000_USE_16BIT 1  

#define CONFIG_DM9000_BASE  0x20000000  /*网卡在BANK4上,地址是0x20000000*/

#define DM9000_IO  0x20000000     

#define DM9000_DATA  0x20000004  


5.6 网络功能异常

进入uboot命令模式下执行tftp或ping命令,发现没有网卡,有这样的警告信息'No ethernet found'

发现是没有增加CONFIG_CMD_NET,导致board_init_r中部分网络功能的函数没有被加入.把CONFIG_CMD_NET宏定义加入到include/configs/mini2440.h中.尽管新的网络初始化工作已经加入,但是仍然是'No ethernet found'. 继续追踪发现是board/samsung/mini2440/mini2440.c中board_eth_init函数的代码还没有写如DM9000的代码,加入一条'rc = dm9000_initialize(NULL);'即可. 这样uboot就可以正常使用网络功能了.


5.7 nand write功能失败

分析了好久原因,原来是未擦出就直接写导致的.首先执行nand erase命令再执行nand write即可.


至此,u-boot-2015.04移植全部完成

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 简洁的过零调功器电路设计与分析

  • 单稳态控制电路设计与分析

  • 开关电源的基本组成及工作原理

  • MT3608构成3.7V转12V的升压电路图

  • 比较常见的功率整流器和滤波电路

  • 基于CA3193的热电偶放大器电路

    相关电子头条文章