基于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

相关文章

SpringBoot中四种AOP实战应用场景及代码实现

《SpringBoot中四种AOP实战应用场景及代码实现》面向切面编程(AOP)是Spring框架的核心功能之一,它通过预编译和运行期动态代理实现程序功能的统一维护,在SpringBoot应用中,AO... 目录引言场景一:日志记录与性能监控业务需求实现方案使用示例扩展:MDC实现请求跟踪场景二:权限控制与

慢sql提前分析预警和动态sql替换-Mybatis-SQL

《慢sql提前分析预警和动态sql替换-Mybatis-SQL》为防止慢SQL问题而开发的MyBatis组件,该组件能够在开发、测试阶段自动分析SQL语句,并在出现慢SQL问题时通过Ducc配置实现动... 目录背景解决思路开源方案调研设计方案详细设计使用方法1、引入依赖jar包2、配置组件XML3、核心配

Java NoClassDefFoundError运行时错误分析解决

《JavaNoClassDefFoundError运行时错误分析解决》在Java开发中,NoClassDefFoundError是一种常见的运行时错误,它通常表明Java虚拟机在尝试加载一个类时未能... 目录前言一、问题分析二、报错原因三、解决思路检查类路径配置检查依赖库检查类文件调试类加载器问题四、常见

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

Spring Boot中JSON数值溢出问题从报错到优雅解决办法

《SpringBoot中JSON数值溢出问题从报错到优雅解决办法》:本文主要介绍SpringBoot中JSON数值溢出问题从报错到优雅的解决办法,通过修改字段类型为Long、添加全局异常处理和... 目录一、问题背景:为什么我的接口突然报错了?二、为什么会发生这个错误?1. Java 数据类型的“容量”限制

利用Python调试串口的示例代码

《利用Python调试串口的示例代码》在嵌入式开发、物联网设备调试过程中,串口通信是最基础的调试手段本文将带你用Python+ttkbootstrap打造一款高颜值、多功能的串口调试助手,需要的可以了... 目录概述:为什么需要专业的串口调试工具项目架构设计1.1 技术栈选型1.2 关键类说明1.3 线程模

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模

Spring Boot 整合 SSE的高级实践(Server-Sent Events)

《SpringBoot整合SSE的高级实践(Server-SentEvents)》SSE(Server-SentEvents)是一种基于HTTP协议的单向通信机制,允许服务器向浏览器持续发送实... 目录1、简述2、Spring Boot 中的SSE实现2.1 添加依赖2.2 实现后端接口2.3 配置超时时