嵌入式平台S3C6410的UBoot分析与移植*

2017-11-24 11:54
单片机与嵌入式系统应用 2017年11期
关键词:波特率寄存器内存

(1.西南交通大学 信息科学与技术学院,成都 611756;2.西南交通大学 交通与运输学院)

ldrpc, _start_armboot

_start_armboot:

.word start_armboot

董君,倪少权2

(1.西南交通大学 信息科学与技术学院,成都 611756;2.西南交通大学 交通与运输学院)

详细分析基于S3C6410的嵌入式平台的U-Boot源代码和启动过程。在此基础上成功移植了U-Boot软件,实现了S3C6410处理器时钟初始化、串口通信、内存初始化、MMU初始化、NAND Flash初始化。通过移植NAND Flash驱动,实现读写NAND Flash和从NAND Flash启动的功能,使得整个系统能够正常运行。

U-Boot;分析;移植;NAND Flash驱动

引 言

U-Boot全称 Universal BootLoader,是遵循GPL条款的开放源码项目。U-Boot在嵌入式设备中起着初始化硬件、引导系统、为操作系统做准备的作用,因此分析与移植U-Boot有着重要的意义。

首先找到board/samsung/smdk6410/的u-boot.lds(连接器脚本),连接器脚本的作用主要是配置U-Boot程序的布局,由其中的.text部分可知,第一部分代码从cpu/s3c64xx/start.S开始执行。因此分析start.S是U-Boot分析的第一阶段。

(1)建立异常向量表

由于ARM处理器有7种异常,分别是:复位、未定义指令、软中断、指令预取终止、数据终止、外部中断请求、快速中断请求,所以有7个异常向量。

(2)设置处理器工作模式

设置ARM的运行模式为32位管理模式。

(3)CPU初始化

首先冲洗指令/数据缓存、关闭MMU和cache、设置外设基地址。接着通过bl lowlevel_init指令跳转到标号 lowlevel_init处执行,其位于boardsamsungsmdk6410下。

(4)点亮LED/关闭看门狗/关闭中断

点亮LED能够检验之前的步骤是否正确,关闭看门狗/中断能够让系统不受外界的影响正常启动。S3C6410中断控制器有64个中断源,其中有VIC0和VIC1两个中断矢量控制器。

(5)S3C6410时钟初始化

S3C6410系统控制器主要包含系统时钟控制单元和系统电源管理单元,其中时钟控制单元主要包括APLL、 MPLL、 EPLL三个锁相环。

APLL主要供给S3C6410核心ARM1176使用,最大能达到667 MHz,一般为533 MHz。MPLL主要给系统时钟使用,主要用在AXI、AHB和 APB总线,在AXI/AHB上时钟最大能达133 MHz,在APB上能达到66 MHz。EPLL主要给外围的设备提供时钟。三星提供了可供选择的时钟配置参数:APLL=533 MHz,MPLL=266 MHz,HCLKX2=266 MHz,HCLK=133 MHz,PCLK=66 MHz。

S3C6410时钟配置步骤如下:

① 首先配置APLL_CON/MPLL_CON寄存器,根据三星提供的配置参数,当FIN=12 MHz,输出为533 MHz时,MDIV=266,PDIV=3, SDIV=1。

② 设置分频系数,S3C6410主要有三个控制器存器CLK_DIV0、CLK_DIV1、CLK_DIV2。APLL 和MPLL 输出的频率由CLK_DIV0中的ARM_RATIO、MPLL_RATIO决定。HCLKX2、HCLK、PCLK频率分别由CLK_DIV0中的HCLKX2_RATIO、HCLK_RATIO、PCLK_RATIO决定。参考值:ARM_RATIO =0,MPLL_RATIO=1,HCLKX2_RATIO=1,HCLK_RATIO=1,PCLK_RATIO=3。

(6)串口初始化

S3C6410串口控制器主要是UART(通用异步接收发送器)。S3C6410的UART提供了4路独立的异步串行I/O端口,每个UART主要包含控制单元、波特率发生器、发送器、接收器。波特率需要的时钟源可以是PCLK, EXT_UCLK0 或者EXT_UCLK1。

S3C6410寄存器主要包括:ULCONn(线控制寄存器),控制数据传输格式,主要包含一个起始位、5~8个数据位、1个奇偶校验位和1~2个停止位;UCONn(UART控制寄存器),选择产生UART波特率的时钟,控制数据传输/接收方式(中断/轮询)等;UFCONn(UART FIFO控制器寄存器),选择是否启用FIFO(主要是用来存储发送/接收的数据);UTRSTATn(UART 发送/接收寄存器),第0位和第1位分别表示接收和发送数据的缓冲的状态;UTXHn/URXHn,8位发送/接收数据寄存器;UBRDIVn,波特率配置器存器。

波特率计算公式:

DIV_VAL=(PCLK /(bps×16 ))-1

DIV_VAL=(EXT_UCLKn/(bps×16))-1(n=0/1)

UBRDIVn=DIV_VAL的整数部分

UDIVSLOTn= DIV_VAL的小数部分×16

(7)NANDFlash初始化

NAND Flash时序初始化,主要配置寄存器NFCONF中的TACLS=7、TWRPH0=7、WRPH1=7。使能NAND Flash,主要寄存器NFCONT中的MODE=1、Reg_nCE0=0。

(8)内存初始化

内存初始化主要是配置其中的寄存器,主要包括P1REFRESH、P1CASLAT、P1T_DQSS、P1T_MRD、P1T_RAS、P1T_RC、P1T_RCD等一系列寄存器,对应的U-Boot源码在cpu_init.S文件中。

(9)U-Boot将代码从NANDFlash拷贝到内存中

本次移植使用的开发板CPU是S3C6410, 其steppingstone(0xc00 0000~0xc00 1fff)。

ldr r0, =0xff00 0fff

bic r1, pc, r0

ldr r2, _TEXT_BASE

bic r2, r2, r0

cmp r1, r2

mov r0, #0x1000

bl copy_from_nand

当前的PC值是在0xc00 0000~0xc00 1fff之间,执行bic r1, pc, r0 将PC高8位和低12位清零,得到0x0~0x1000(这是在steppingstone中运行r1的值)。_TEXT_BASE = 0xc7e0 0000 ,执行bic r2, r2, r0后 r2的范围为0xe0 0000~0xef f000),因为开启了MMU。经过比较后执行bl copy_from_nand 指令(主要是拷贝4 KB大小的数据到内存中0x57e0 0000)。

(10)开启MMU

首先建立映射表(从虚拟地址到物理地址的映射,主要是段映射)。由lowlevel_init.S(mmu_table)可知:第一段主要是用来调试,可读(0~0xa000 0000)(2560 MB);第二段保留(0xa000 0000~0xc000 0000)-->(512 MB);第三段是主要用来映射的(128 MB)-->将虚拟基地址0xc000 0000 映射到物理基地址0x5000 0000;第三段没法访问(896 MB)。

然后设置TTB寄存器,将建立的映射表的基地址写入到TTB寄存器中:mcrp15, 0, r1, c2, c0, 0。

接着使能MMU:mcrp15, 0, r0, c1, c0, 0。

(11)设置栈

因为开启了MMU,所以栈的大小为:ldrsp=(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0xc),其中CFG_UBOOT_BASE=0xc7e0 0000、CFG_UBOOT_SIZE=2 MB。

(12)清除BSS段

主要是为后面的数据使用。

(13)跳转到start_armboot

ldrpc, _start_armboot

_start_armboot:

.word start_armboot

当执行了上面的指令后,PC执行绝对跳转到内存中,PC的值应该是0xc7e0 0000 之后的某个值(开启了MMU)。

关于bl指令和ldr指令:bl指令是相对跳转指令,只是相对当前PC的值跳转,跳转大小编译器编译时就已确定。ldr指令是绝对跳转指令,PC的值会变成赋给的值。这也是这里用ldr的原因。

(1)设置结构体gd_t和bd_t

gd_t主要用来存储全局数据区的数据。bd_t主要用来存放板级相关的全局数据。U-Boot启动内核时要给内核传递参数,需要用gd_t和bd_t中的数据来设置标记列表。

(2)执行init_sequence数组中的函数

通过调用在init_sequence指针数组中的函数指针,从而执行相应的函数,接下来分析主要的函数。

ⓐ board_init( )

主要配置开发板的信息,初始化网卡,设置GPIO寄存器,设置U-Boot机器码和内核启动参数地址。

ⓑ interrupt_init( )

该函数主要是配置定时器,为系统运行提供相应的时间。

ⓒ env_init( )

初始化gd_t中环境变量,这里是系统默认的环境变量default_environment[0]。

ⓓ init_baudrate( )

初始化波特率,即gd->baudrate = 115200。

ⓔ dram_init( )

填充gd_t的内存信息,start = 0x5000 0000; size = 256M

ⓕ flash_init( )

初始化Flash的起始地址、bank数目,主要是放在flash_info[ ]中。

ⓖ nand_init( )

取得Nandflash的信息,放在nand_chip和nand_dev_desc结构体中。

ⓗ env_relocate()

将环境变量地址重新定位,将新的地址赋值给gd->env_addr(主要涉及到数据的搬移Nandflash->Dram)。

ⓘ 填充gd_t中bd的IP地址/MAC地址

gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");

gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0。

ⓙ devices_init()

初始化设备列表,作者这里为空。

○k jumptable_init()

初始化跳转表,填充gd_t中的jt指针数组里面的元素(函数),后面可以快速执行里面的函数。

○l console_init_r( )

初始化控制台,初始化标准输入、输出、和错误设备。

使能中断。

填充硬件MAC地址。

进入main_loop循环,执行第三阶段的代码(实际上是两阶段),在mian_loop循环中主要执行的主要代码是:

s = GETenv ("bootcmd");

if (bootdelay >= 0 && s && !abortboot (bootdelay)) {

run_command (s, 0); }

首先获取bootcmd环境变量,然后调用run_command( )函数来执行相应的命令。bootm命令执行的路线:bootm->do_bootm()->do_bootm_Linux()->theKernel( )。最后通过调用theKernel函数从而执行Linux内核代码,U-Boot引导功能完成,将控制权交给内核。

3 移植NAND Flash驱动

NAND Flash是嵌入式设备中最常用的存储设备。通常将移植好的U-Boot烧写到NAND Flash中,直接从NAND Flash里面启动U-Boot。

首先要配置NAND Flash的控制时序位和使能位(之前),通过CONFIG_NAND来控制。然后在Nand_ids.c文件中找到结构体nand_flash_ids,添加相应的NAND Flash设备信息——{“NAND 1GiB 3,3V 8-bit”,0xD3, 0, 1024, 0, LP_OPTIONS},其已经在U-Boot中存在。最后重新编译U-Boot,然后烧写到NAND Flash中,从NAND Flash启动开发板,U-Boot顺利启动,启动页面如图1所示。

图1 U-Boot顺利启动后显示情况

结 语

[1] 田泽.嵌入式系统开发与应用[M].北京:北京航空航天大学出版社,2005.

[2] 郑灵翔.嵌入式Linux系统设计[M].北京:北京航空航天大学出版社,2008.

[3] 范展源,刘韬.深度实践嵌入式Linux系统移植[M].北京:机械工业出版社,2015.

[4] 韦东山.嵌入式Linux应用开发完全手册[M].北京:人民邮电出版社,2008.

[5] 何景波,孙运强,姚爱琴.U-Boot在嵌入式系统上的移植分析与实现[J].机械工程与自动化,2009(4).

[6] 黄荐渠,秦东兴,赵曦,等.U-Boot的启动及移植分析[J].微计算机信息,2008(11).

[7] 杨帆,顾亚平,彭翔,等.一种小型嵌入式Linux Boot Loader的设计与实现[J].计算机应用与软件,2008(1):225-226.

[8] Sumsuang Electronics.S3C6410x User’s Manual,2008.

[9] Sumsuang Electronics.K9F2G08UXA Datasheet,2007.

董君(硕士研究生),主要研究方向为交通运输信息技术;倪少权(博士),主要研究方向为计算机编制列车运行图、交通运输信息技术、铁路行车组织、物流信息技术。

AnalysisandPortingofU-BootinEmbeddedPlatformS3C6410

DongJun1,NiShaoquan2

(1.School of Information Science and Technology,Southwest Jiaotong University,Chengdu 611756,China;2.School of Transportation and Logistics,Southwest Jiaotong University)

In the paper,the U-Boot source code and start process based on S3C6410 embedded platform are analyzed.On the basis, the U-Boot software is successfully ported and S3C6410 processor clock initialization,serial communication,memory initialization,MMU initialization and NAND Flash initialization are realized.Through the porting of NAND Flash driver,the read and write NAND Flash and start from NAND Flash are realized. So that the whole system can operate normally.

U-Boot;analysis;porting;NAND Flash driver

国家自然基金项目(61403317,61273242,60776826);中国铁路总公司科技研究计划项目(2016X006-D);四川省科技计划项目(2017ZR0149,2017RZ0007);中央高校基本科研业务费专项资金资助(2682017ZDPY04,2682017CX022)。

TP368.1

A

2017-08-15)

猜你喜欢
波特率寄存器内存
STM32和51单片机寄存器映射原理异同分析
外部高速缓存与非易失内存结合的混合内存体系结构特性评测
CAN 总线波特率自适应程序设计
Lite寄存器模型的设计与实现
“春夏秋冬”的内存
基于内存的地理信息访问技术
C*Core芯片SCI串口波特率容限优化
高速数模转换器AD9779/AD9788的应用
UART波特率发生电路设计
一种可重构线性反馈移位寄存器设计