基于TQ2440开发板的U-boot-1.1.6的start.S代码分析

2024-04-18 13:32

本文主要是介绍基于TQ2440开发板的U-boot-1.1.6的start.S代码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

start.S汇编源文件是U-boot执行的起始代码文件,也是不容易理解的实现部分。执行流程如下:

.globl _start  //定义_start是全局标签,其他文件也可以使用。.globlGNU汇编语法。

_start:     b       reset  //跳转到reset标签出执行,由于reset操作是在MMU工作之前/之后都有可能使用,所以这里用b来跳转。

       /*下面定义ARM异常向量表对应的跳转代码*/

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

 

_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

/*其中.word的语法是用来指定该变量可以被C语言直接引用*/

       .balignl 16,0xdeadbeef /* 这个指令用来填写一个长字,即内容长度为长字,即4个字节的长度,填写内容为0xdeadbeef */

当一个异常出现以后,ARM会自动执行以下几个步骤:

1)把下一条指令的地址放到连接寄存器LR(通常是R14),这样就能够在处理异常返回时从正确的位置继续执行。

2)将相应CPSR(当前程序状态寄存器)复制到SPSR(备份的程序状态寄存器)中。从异常退出的时候,就可以由SPSR来恢复CPSR

3)根据异常类型,强制设置CPSR的运行模式位。

4)强制PC(程序计数器)从相关异常向量地址取出下一条指令执行,从而跳转到相应的异常处理程序中。

reset:

       /*

        * set the cpu to SVC32 mode

        */

       mrs  r0,cpsr   /*传送CPSR的内容到通用寄存器指令*/

       bic   r0,r0,#0x1f    /*位清除指令,即=r0&(~0x1f)*/

       orr   r0,r0,#0xd3   /*逻辑或指令,即=r0|0xd3*/

       msr  cpsr,r0   /*传送通用寄存器到CPSR指令*/

 

/* turn off the watchdog */

#if defined(CONFIG_S3C2400)

# define pWTCON        0x15300000

# define INTMSK          0x14400008    /* Interupt-Controller base addresses */

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

#elif defined(CONFIG_S3C2410)

# define pWTCON        0x53000000

# define INTMOD     0X4A000004

# define INTMSK          0x4A000008   /* Interupt-Controller base addresses */

# define INTSUBMSK   0x4A00001C

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

#endif

 

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)

       ldr     r0, =pWTCON

       mov     r1, #0x0  /*0x0值传入r1寄存器*/

       str     /*r1, [r0] r1种的内容写入到r0*/

 

       /*

        * mask all IRQs by setting all bits in the INTMR - default

        */

       mov r1, #0xffffffff

       ldr   r0, =INTMSK

       str   r1, [r0]

# if defined(CONFIG_S3C2410)

       ldr   r1, =0x3ff

       ldr   r0, =INTSUBMSK

       str   r1, [r0]

# endif

#endif     /* CONFIG_S3C2400 || CONFIG_S3C2410 */

cpu_init_crit 主要完成内存管理相关的寄存器设置,CP15协处理器,配置内存区控制寄存器。另外这段代码中调用了lowlevel_init 函数,进行寄存器的具体设置,与采用的内存芯片有关。

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

       bl     cpu_init_crit  /*bl是带跳转返回指令*/

#endif

接下来看一下cpu_init_crit标签的实现,如下:

cpu_init_crit:

       /*

        * flush v4 I/D caches

        */

       mov r0, #0

       mcr p15, 0, r0, c7, c7, 0      /* ARM 处理器寄存器到协处理器寄存器的数据传送指令,清除ID cache分支运算缓存(BTB*/

       mcr p15, 0, r0, c8, c7, 0      /* flush v4 TLBTranslation Lookaside Buffers */

 

       /*

        * disable MMU stuff and caches

        */

       mrc p15, 0, r0, c1, c0, 0

       bic   r0, r0, #0x00002300      @ clear bits 13, 9:8 (--V- --RS)

       bic   r0, r0, #0x00000087      @ clear bits 7, 2:0 (B--- -CAM)

       orr   r0, r0, #0x00000002      @ set bit 2 (A) Align

       orr   r0, r0, #0x00001000      @ set bit 12 (I) I-Cache

       mcr p15, 0, r0, c1, c0, 0

 

       /*

        * before relocating, we have to setup RAM timing

        * because memory timing is board-dependend, you will

        * find a lowlevel_init.S in your board directory.

        */

       mov ip, lr

       bl     lowlevel_init /*跳转到lowlevel_init,处理完返回*/

       mov lr, ip

       mov pc, lr

lowlevel_init实现是在board/tq2440/ lowlevel_init.S中,主要完成初始化内存控制器,即SDRAM的初始化。

.globl lowlevel_init

lowlevel_init:

       /* memory control configuration */

       /* make r0 relative the current location so that it */

       /* reads SMRDATA out of FLASH rather than memory ! */

       ldr     r0, =SMRDATA

       ldr   r1, _TEXT_BASE

       sub  r0, r0, r1

       ldr   r1, =BWSCON       /* Bus Width Status Controller */

       add     r2, r0, #13*4

0:

       ldr     r3, [r0], #4

       str     r3, [r1], #4

       cmp     r2, r0

       bne     0b

 

       /* everything is fine now */

       mov pc, lr

接下来是设置堆栈,设置后的逻辑位置如下图所示:

 

stack_setup:

       ldr   r0, _TEXT_BASE         /* upper 128 KiB: relocated uboot   */

       sub  r0, r0, #CFG_MALLOC_LEN       /* malloc area                      */

       sub  r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */

       sub  sp, r0, #12             /* leave 3 words for abort-stack    */

接下来调用:bl clock_init 用来完成初始化时钟的目的。

下面的代码是将NandFlash数据搬运到SDRAM的核心实现代码,其最主要由C语言函数CopyCode2Ram函数来完成复制目的,该函数在board/tq2440/boot_init.c中实现。

relocate:                       /* relocate U-Boot to RAM        */

       adr   r0, _start        /* r0 <- current position of code   */

       ldr   r1, _TEXT_BASE         /* test if we run from flash or RAM */

       cmp     r0, r1                  /* don't reloc during debug         */

       beq     clear_bss

 

       ldr   r2, _armboot_start

       ldr   r3, _bss_start

       sub  r2, r3, r2        /* r2 <- size of armboot            */

       bl  CopyCode2Ram      /* r0: source, r1: dest, r2: size */

       接下来就是清除BSS段,并进入C语言阶段的高级初始化过程实现。

clear_bss:

       ldr   r0, _bss_start         /* find start of bss segment        */

       ldr   r1, _bss_end          /* stop here                        */

       mov       r2, #0x00000000           /* clear                            */

 

clbss_l:str       r2, [r0]           /* clear loop...                    */

       add  r0, r0, #4

       cmp r0, r1

       ble   clbss_l

 

       ldr   pc, _start_armboot

_start_armboot:      .word start_armboot   /*start_armbootC代码函数,在lib_arm/board.c中实现*/

这篇关于基于TQ2440开发板的U-boot-1.1.6的start.S代码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/914918

相关文章

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

python实现pdf转word和excel的示例代码

《python实现pdf转word和excel的示例代码》本文主要介绍了python实现pdf转word和excel的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、引言二、python编程1,PDF转Word2,PDF转Excel三、前端页面效果展示总结一

在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码

《在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码》在MyBatis的XML映射文件中,trim元素用于动态添加SQL语句的一部分,处理前缀、后缀及多余的逗号或连接符,示... 在MyBATis的XML映射文件中,<trim>元素用于动态地添加SQL语句的一部分,例如SET或W

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

Redis主从复制的原理分析

《Redis主从复制的原理分析》Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、... 目录Redis主从复制的原理主从复制概述配置主从复制数据同步过程复制一致性与延迟故障转移机制监控与维

python多进程实现数据共享的示例代码

《python多进程实现数据共享的示例代码》本文介绍了Python中多进程实现数据共享的方法,包括使用multiprocessing模块和manager模块这两种方法,具有一定的参考价值,感兴趣的可以... 目录背景进程、进程创建进程间通信 进程间共享数据共享list实践背景 安卓ui自动化框架,使用的是

SpringBoot生成和操作PDF的代码详解

《SpringBoot生成和操作PDF的代码详解》本文主要介绍了在SpringBoot项目下,通过代码和操作步骤,详细的介绍了如何操作PDF,希望可以帮助到准备通过JAVA操作PDF的你,项目框架用的... 目录本文简介PDF文件简介代码实现PDF操作基于PDF模板生成,并下载完全基于代码生成,并保存合并P

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

SpringBoot基于MyBatis-Plus实现Lambda Query查询的示例代码

《SpringBoot基于MyBatis-Plus实现LambdaQuery查询的示例代码》MyBatis-Plus是MyBatis的增强工具,简化了数据库操作,并提高了开发效率,它提供了多种查询方... 目录引言基础环境配置依赖配置(Maven)application.yml 配置表结构设计demo_st