• 首页
  • 中国
  • 从零开始移植U-boot到mini2440(三)——CPU初始化篇

从零开始移植U-boot到mini2440(三)——CPU初始化篇

2023-11-01 137浏览
百检网是一家专业的第三方检测平台,汇聚众多拥有权威资质的第三方检测机构为你提供一站式的检测服务,做检测就上百检网。百检网让检测从此检测,一份报告全国通用,专业值得信赖。

经过前两节的准备,我们现在可以开始肝u-boot的代码了

U-boot版本:2020/5/2

编译环境:Ubuntu 16.04

arm-none-eabi-gcc version 4.9.3 20150529 (prerelease) (15:4.9.3+svn231177-1)

运行环境:mini2440(s3c2440,arm920t)

代码仓库:git@github.com:JingyeLi/u-boot_2440.git

https://github.com/JingyeLi/u-boot_2440/tree/v0.1

u-boot.lds

这是一个很容易被人忽略的一个文件,包括我自己,以前一般用keil的时候都是自动生成的,但其实想要理解一个芯片的启动代码,*好先从lds文件开始(不过在此之前,希望你能对编译-链接-运行有所理解)。众所周知一个程序会分成对应的几段,而lds文件的用途就是规定好这几段会放在什么地方。

而lds的重点是开头的这几句,与程序入口密切相关,程序虽然还是从_start开始,但与老版的u-boot不同,新版的多了__image_copy_start和vectors,__image_copy_start我们放在后面relocate的时候一起理解,这里可以先忽略。

ENTRY(_start) /* 表明可执行文件代码从_start开始 */

SECTIONS

{

. = 0x00000000; /* 指定这个段从0x0开始*/

. = ALIGN(4); /* 4字节对齐,32位指令* /

.text : /* 具体TEXT段的结构 */

{

*(.__image_copy_start)

*(.vectors)

CPUDIR/start.o (.text*)

}

}

lib/vectors.S

在芯片启动后,会自动执行load 0x0的指令,而在u-boot.lds中,我们知道0x0的位置对应的指令应该就是_start标签所在的地方。找了一圈发现,新版的u-boot将arm的中断向量表都放在lib/vectors.S中。这个文件其实也简单,十分的好理解,找到_start然后发现就是跳到reset

.macro ARM_VECTORS

b reset /* 这个指令将会保存在_start的地址 */

ldr pc, _undefined_instruction

ldr pc, _software_interrupt

ldr pc, _prefetch_abort

ldr pc, _data_abort

ldr pc, _not_used

ldr pc, _irq

ldr pc, _fiq

.endm

_start:

ARM_VECTORS

_undefined_instruction:.word undefined_instruction

_software_interrupt:.word software_interrupt

_prefetch_abort:.word prefetch_abort

_data_abort:.word data_abort

_not_used:.word not_used

_irq:.word irq

_fiq:.word fiq

S3C2440初始化 - start.S/lowlevel_init.S

U-boot在0x0会跳转到’reset’ label,而这个label对应在arch/arm/cpu/arm920t的start.S中。

具体代码的分析就不贴了,基本和旧的u-boot版本没什么区别。这里推荐一篇blog,虽然他用到的u-boot版本还是很旧的,但是确实讲得很清楚很好。

https://blog.csdn.net/qq_16933601/article/details/105685770

CPU的初始化分为几步,

设置为特权模式(SVC32)

关闭看门狗

关闭中断

关闭MMU和cache

初始化时钟

初始化SRAM

https://blog.csdn.net/dndxhej/category_9261234.html?spm=1001.2014.3001.5482

不过初始化时钟值得仔细讲一下,一开始移植的时候,执行到某条跳转指令程序就跑飞了,出现data abort或者unhandled exception,百思不得其解,后来就是看到上述那篇博文,找到了思路。

**我们应该理解ARM的时钟系统。

S3C2440有两个PLL,MPLL用于提供系统时钟,UPLL用于USB模块,而在编程手册上提到一点。

Although the MPLL starts just after a reset, the MPLL output (Mpll) is not used as the system clock until the software

writes valid settings to the MPLLCON register. Before this valid setting, the clock from external crystal or EXTCLK source

will be used as the system clock directly. Even if the user does not want to change the default value of MPLLCON

register, the user should write the same value into MPLLCON register.

对于频率的计算方法,在编程手册上也有,

MPLL = (2 * m * Fin) / (p * 2^s)

m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2

同时还有一个建议,建议*终的频率大于200MHz

FCLKOUT must be bigger than 200MHz (It does not mean that the ARM core has to run more than 200MHz).

而和时钟设置相关的两个寄存器分别是CLKDIVN和MPLLCON

因为刚reset的时候MPLLCON是不生效的,FCLK直接使用晶振时钟,同时manual的下面还有推荐的频率,这里我们就设置MPLL为400MHz方便计算,下面NOTE还提示到要有7个NOP时钟才能生效

MPLLCON = ((0x5c << 12) | (0x01 << 4) | (0x01))

同时CLKDIVN设置为0x5,则得到

FCLK = 400MHz

HCLK = 100MHz

PCLK = 50MHz

所以我们能得到以下初始化时钟代码加在start.S里面:

# define MPLLCON 0x4C000004

# define CLKDIVN 0x4C000014 /* clock divisor register */

# define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))

/* default FCLK is 12 MHz ! */

ldr r0, =CLKDIVN

mov r1, #0x03 // FCLK:HCLK:PCLK=1:2:4

str r1, [r0]

mrc p15, 0, r1, c1, c0, 0 /* 读出控制寄存器 */

orr r1, r1, #0xc0000000 /* 设置为“asynchronous bus mode” */

mcr p15, 0, r1, c1, c0, 0 /* 写入控制寄存器 */

/* MPLLCON = S3C2440_MPLL_400MHZ */

ldr r0, =MPLLCON

ldr r1, =S3C2440_MPLL_400MHZ

str r1, [r0]

在控制时钟寄存器设置好后,接下来的初始化步骤就是按上述所讲,就不再多解释了。也可以理解为,当程序执行到_main(start.S的*后一步),CPU就初始化好了,可以正常执行所有功能。

附 uboot调试方法

在bringup CPU的时候,其实出现的问题远比记录在博客上的多,收集了两个在串口没好前的调试方法

AXD

由于uboot是使用命令行Makefile直接编译的,没有使用Keil,不能直接使用JTAG的单步调试,这时我们可以借用AXD,参考:

https://blog.csdn.net/xautfengzi/article/details/6306323

OpenOCD

这是一个功能比JLink更强大的工具

https://blog.csdn.net/qingwufeiyang12346/article/details/45954595

说一下自己的感想,其实自己作为嵌入式工程师工作也有好几年了,突然想搞u-boot的移植并且用博客记录下来,是出于自己的初心,在技术道路上,就是要无限进步。现在网上搜索,都2021年了,大部分人移植还拿着200x年的u-boot在捣鼓,能参考的资料多是没错,但是计算机技术从来就不是守旧主义,我们要理解的是一颗芯片如何bringup,如何从一条条的机器指令到整个系统跑起来,我们要提供什么样的代码,初始化的思路是什么。u-boot作为一个经典的底层开源项目,我们从中能吸取到什么。在招聘面试中,要问的从来不是做了多少项目,而是问怎么去做这个项目。

百检网秉承“客户至上,服务为先,精诚合作,以人为本”的经营理念,始终站在用户的角度解决问题,为客户提供“一站购物式”的新奇检测体验,打开网站,像挑选商品一样简单,方便。打破行业信息壁垒,建构消费和检测机构之间高效的沟通平台