TQQ2440第一节:启动代码

发布者:alpha12最新更新时间:2024-11-06 来源: cnblogs关键字:启动代码 手机看文章 扫描二维码
随时随地手机看文章

由于网上和我自己用的开发板有气度代码,所以我打算先把ARM9的外围熟悉了在回来看看启动代码,我也大约的看了一下和ARM7的差不多。只是从NANDFLASH启动多了拷贝代码,和MMU初始化的代码,在这里先裸奔起来,由于网上已经有了关于TQ2440的启动代码的解说,所以暂时先复制过来,过段时间在自己重写一下:


下面主要内容来自:http://blog.csdn.net/zhaocj/archive/2010/02/09/5302370.aspx


;=========================================

; NAME: 2440INIT.S

; DESC: C start up codes

;       Configure memory, ISR ,stacks

;      Initialize C-variables

;=========================================

  

;GET类似于C语言的include,option.inc文件内定义了一些全局变量,memcfg.inc文件内定义了关于内存bank的符号和数字常量,2440addr.inc文件内定义了用于汇编的s3c2440寄存器变量和地址

       GET option.inc

       GET memcfg.inc

       GET 2440addr.inc

  

;SDRAM自刷新位,把寄存器REFRESH的第22位处置1

BIT_SELFREFRESH   EQU    (1<<22)

  

;CPSR中的低5位定义了处理器的七种工作模式,为以后切换模式时使用

;Pre-defined constants

USERMODE    EQU     0x10

FIQMODE      EQU                0x11

IRQMODE      EQU               0x12

SVCMODE     EQU      0x13

ABORTMODE   EQU        0x17

UNDEFMODE   EQU        0x1b

MODEMASK    EQU        0x1f

;CPSR中的I位和F位置1,表示禁止任何中断

NOINT       EQU      0xc0

  

;定义了7种处理器模式下的栈的起始地址,其中用户模式和系统模式共有一个栈空间

;_STACK_BASEADDRESS在option.inc文件内定义,值为0x33ff8000

;The location of stacks

UserStack     EQU      (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~

SVCStack    EQU      (_STACK_BASEADDRESS-0x2800) ;0x33ff5800 ~

UndefStack  EQU      (_STACK_BASEADDRESS-0x2400) ;0x33ff5c00 ~

AbortStack   EQU      (_STACK_BASEADDRESS-0x2000) ;0x33ff6000 ~

IRQStack     EQU      (_STACK_BASEADDRESS-0x1000) ;0x33ff7000 ~

FIQStack     EQU      (_STACK_BASEADDRESS-0x0)       ;0x33ff8000 ~

  

ARM处理器的两种工作状态:16位和32位

编译器有相对应的用16位和32位两种编译方式

;这段的目的是统一目前的处理器工作状态和软件编译方式

;Check if tasm.exe(armasm -16 ...@ADS 1.0) is used.

       GBLL    THUMBCODE                   ;声明一个全局逻辑变量

       [ {CONFIG} = 16                                 ;if CONFIG == 16

THUMBCODE SETL  {TRUE}               ;THUMBCODE = TRUE

           CODE32                                        ;指示编译器为ARM指令

             |                                                ;else

THUMBCODE SETL  {FALSE}                    ;THUMBCODE = FALSE

    ]

  

;宏定义,在后面出现MOV_PC_LR时,这个宏会被自动展开

;该宏的作用是跳出子程序,返回被调用处

             MACRO

       MOV_PC_LR

             [ THUMBCODE              ;if THUMBCODE == TRUE

           bx lr

             |                                  ;else 即THUMBCODE == FALSE

           mov      pc,lr

             ]

       MEND

;该宏定义的作用是有条件地(当Z=1时)跳出子程序,返回被调用处

             MACRO

       MOVEQ_PC_LR

             [ THUMBCODE

        bxeq lr

             |

           moveq pc,lr

             ]

       MEND

  

;该宏定义是把中断服务程序的首地址装载到pc中

;在后面当遇到HandlerXXX HANDLER HandleXXX时,该宏被展开

;注意:HANDLER前的符号HandlerXXX比其后的符号HandleXXX多了一个r

;HandlerXXX为ARM体系中统一定义的几种异常中断

;HandleXXX为每个ARM处理器各自定义的中断,见该文件最后部分的中断向量表

             MACRO

$HandlerLabel HANDLER $HandleLabel

  

$HandlerLabel          

       sub  sp,sp,#4 ;ATPCS规定数据栈为FD类型

 ;即栈指针指向栈顶元素,数据栈向内存地址减小的方向增长

 ;该语句是使栈地址减小4个字节,以留出空间装载中断服务函数首地址

       stmfd     sp!,{r0} ;由于要利用r0寄存器来传递数据,所以要保存r0数据,使其入栈

       ldr     r0,=$HandleLabel     ;把HandleXXX的地址装到r0

       ldr     r0,[r0]    ;装载中断服务函数的起始地址

       str     r0,[sp,#4]               ;中断函数首地址入栈

       ldmfd   sp!,{r0,pc} ;将事先保存的r0数据和中断函数首地址出栈

                      ;并使系统跳转到相应的中断处理函数

       MEND

  

;导入连接器事先定义好的运行域中三个段变量

;ARM的可执行映像文件由RO、RW、ZI三个段组成

;RO为代码段,RW为已初始化的全局变量,ZI为未初始化的全局变量

       IMPORT  |Image$$RO$$Base|    ;RO段起始地址

       IMPORT  |Image$$RO$$Limit|   ;RO段结束地址加1,等于RW段起始地址

       IMPORT  |Image$$RW$$Base|   ;RW段起始地址

       IMPORT  |Image$$ZI$$Base|      ;ZI段起始地址

       IMPORT  |Image$$ZI$$Limit|     ;ZI段结束地址加1

  

;导入两个关于MMU的函数,用于设置时钟模式为异步模式和快速总线模式

       IMPORT      MMU_SetAsyncBusMode

       IMPORT      MMU_SetFastBusMode  ;

  

;导入Main,它为C语言程序入口函数

       IMPORT  Main        ; The main entry of mon program

;导入用于复制从Nand Flash中的映像文件到SDRAM中的函数

       IMPORT  RdNF2SDRAM   ; Copy Image from Nand Flash to SDRAM

  

;定义代码段,名为Init

       AREA    Init,CODE,READONLY

  

;在入口处(0x0)开始的8个字单元空间内,存放的是ARM异常中断向量表,每个字单元空间都是一条跳转指令,当异常发生时,ARM会自动跳转到相应的中断向量处,并由该处的跳转指令再跳转到相应的执行函数处

       ENTRY        ;程序入口处

       EXPORT     __ENTRY           ;导出__ENTRY,即导出代码段入口地址

__ENTRY                                ;主要用于MMU

ResetEntry

       ;1)The code, which converts to Big-endian, should be in little endian code.

       ;2)The following little endian code will be compiled in Big-Endian mode.

       ;  The code byte order should be changed as the memory bus width.

       ;3)The pseudo instruction,DCD can not be used here because the linker generates error.

;在0x0处的异常中断是复位异常中断,是上电后执行的第一条指令

;变量ENDIAN_CHANGE用于标记是否要从小端模式改变为大端模式,因为编译器初始模式是小端模式,如果要用大端模式,就要事先把该变量设置为TRUE,否则为FLASE

;变量ENTRY_BUS_WIDTH用于设置总线的宽度,因为用16位和8位宽度来表示32位数据时,在大端模式下,数据的含义是不同的

;由于要考虑到大端和小端模式,以及总线的宽度,因此该处看似较复杂,其实只是一条跳转指令:当为大端模式时,跳转到ChangeBigEndian函数处,否则跳转到ResetHandler函数处

       ASSERT      :DEF:ENDIAN_CHANGE    ;判断是否定义了ENDIAN_CHANGE

                                ;如果没有定义,则报告该处错误信息

       [ ENDIAN_CHANGE                   ;if ENDIAN_CHANGE ==TRUE

              ASSERT  :DEF:ENTRY_BUS_WIDTH  ;判断是否定义了ENTRY_BUS_WIDTH

                                       ;如果没有定义,则报告该处错误信息

  

              [ ENTRY_BUS_WIDTH=32         ;if ENTRY_BUS_WIDTH ==32

;跳转到ChangeBigEndian(ChangeBigEndian在0x24),因此该条指令的机器码为0xea000007

;所以该语句与在该处(即0x0处)直接放入0xea000007数据(即DCD 0xea000007)作用相同

                     b     ChangeBigEndian     

              ]

  

              [ ENTRY_BUS_WIDTH=16         ;if ENTRY_BUS_WIDTH ==16

;在小端模式下,用16位或8位数据总线宽度表示32位数据,与用32位总线宽度表示32位数据,格式完全一致。但在大端模式下,格式就会发生变化

;在复位时,系统默认的是小端模式,所以就要人为地改变数据格式,使得用16位大端数据表示的32位数据也能被小端模式的系统识别

;该语句的目的也是跳转到ChangeBigEndian,即机器码也应该是0xea000007,但为了让小端模式系统识别,就要把机器码的顺序做一下调整,改为0x0007ea00,那么我们就可以用DCD 0x0007ea00把机器码装载进去了,但由于该处不能使用DCD伪指令,因此我们就要用一条真实的指令来代替DCD 0x0007ea00,即该指令编译后的机器码也为0x0007ea00,而andeq  r14,r7,r0,lsl #20就是一条编译后机器码为0x0007ea00的指令,所以我们在该处写上该条指令

                     andeq    r14,r7,r0,lsl #20   ;DCD 0x0007ea00

              ]

  

              [ ENTRY_BUS_WIDTH=8           ;if ENTRY_BUS_WIDTH ==8

;该语句的分析与上一段代码的分析相似

;streq  r0,[r0,-r10,ror #1]编译后的机器码为0x070000ea

                     streq      r0,[r0,-r10,ror #1] ;DCD 0x070000ea

              ]

              |             ;else 即ENDIAN_CHANGE ==FALSE

              b     ResetHandler             ;跳转到ResetHandler处,复位

       ]

[1] [2] [3] [4] [5]
关键字:启动代码 引用地址:TQQ2440第一节:启动代码

上一篇:TQQ2440第二节:流水灯
下一篇:TQQ2440第三节:串口

推荐阅读最新更新时间:2026-03-25 12:43

关于STM32启动文件startup_stm32f10x_hd.s的代码
本文对STM32启动文件startup_stm32f10x_hd.s的代码进行讲解,此文件的代码在任何一个STM32F10x工程中都可以找到。 启动文件使用的ARM汇编指令汇总 Stack——栈 Stack_Size EQU 0x00000400 AREA STACK, NOINIT, READWRITE, ALIGN=Stack_Mem SPACE Stack_Size__initial_sp 开辟栈的大小为 0X00000400(1KB),名字为 STACK, NOINIT 即不初始化,可读可写, 8(2^3)字节对齐。 栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部SRAM 的大小。
[单片机]
关于STM32<font color='red'>启动</font>文件startup_stm32f10x_hd.s的<font color='red'>代码</font>
STM32启动文件startup_stm32f10x_hd.s的代码讲解
本文对STM32启动文件startup_stm32f10x_hd.s的代码进行讲解,此文件的代码在任何一个STM32F10x工程中都可以找到。 启动文件使用的ARM汇编指令汇总 Stack——栈 Stack_Size EQU 0x00000400 AREA STACK, NOINIT, READWRITE, ALIGN= Stack_Mem SPACE Stack_Size __initial_sp 开辟栈的大小为 0X00000400(1KB),名字为 STACK, NOINIT 即不初始化,可读可写, 8(2^3)字节对齐。 栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部SRA
[单片机]
STM32<font color='red'>启动</font>文件startup_stm32f10x_hd.s的<font color='red'>代码</font>讲解
关于mini2440启动代码中中断的产生原理分析
一.首先,我们先看一下它的中断向量表: 由中断向量表,可知如果有任何一个IRQ中断源产生中断,CPU都会到0x18地址读指令。 二.在启动代码中,下面的指令分别在中断向量地址中: 即0x18地址处是指令 b HandlerIRQ b ResetHandler b HandlerUndef ;handler for Undefined mode b HandlerSWI ;handler for SWI interrupt b HandlerPabort ;handler for PAbort b HandlerDabort ;handler for DAbort b . ;reserved bH
[单片机]
关于mini2440<font color='red'>启动</font><font color='red'>代码</font>中中断的产生原理分析
移植u-boot-2010.09到S3C2440(三)——判断NAND还是NOR启动的汇编代码
参考文档:s3c2440的nandflash启动 guess_flash: #define BWSCON 0x48000000 ldr r4, =BWSCON ldr r6, ands r6, r6, #0x6 mov r6, r6, LSL#4 ldr r5, =GPBDAT str r6, bl guess_flash 这几行的意思是: 获取0X48000000地址的值,获得其 位,在LEDs显示其值。 结论: 通过LED的显示,可以发现在NAND和在NOR运行的显示效果不同。
[单片机]
23. 基于Cortex-A9 uboot代码启动分析
前言 我们在前面的arm系列课程,已经讲解了arm的架构、汇编指令、异常、常用外设的控制器驱动,那么我们已经具备开发arm系列产品的基本技能。 本篇给大家介绍一款比较常用的bootloader:uboot,通过uboot的介绍以及源代码的详细分析,让大家把之前所有ARM相关的知识点融会贯通起来。 一、uboot 1. 概念 U-Boot 是一个主要用于嵌入式系统的引导加载程序,可以支持多种不同的计算机系统结构,包括PPC、ARM、AVR32、MIPS、x86、68k、Nios与MicroBlaze。这也是一套在GNU通用公共许可证之下发布的自由软件。 U-Boot不仅仅支持嵌入式Linux系统的引导,它还支持NetBS
[单片机]
23. 基于Cortex-A9 uboot<font color='red'>代码</font><font color='red'>启动</font>分析
stm32f4启动代码分析(一)
因为使用的开发板是stm32f407discovery,所以启动代码为st公司的官方库文件里的startup_stm32f40_41xxx.s,至于如何去找官方库文件,不在本节讨论的范围内,本节只是初步的分析startup_stm32f40_41xxx.s,其中更深入的东西需要在以后的章节中分析。 在startup_stm32f40_41xxx.s中,有一段注释: ;* File Name : startup_stm32f40_41xxx.s ;* Author : MCD Application Team ;* @version : V1.7.0 ;* @date : 22-April-2016 ;* Description
[单片机]
stm32 启动代码应用技巧
前段时间对stm32的启动代码进行了一个小小的研究,发现了一些比较好用的技巧,在这分享下! 总体上说,整个启动代码就是中断初始化为主,以及中断之后如何进行调配函数! 首先看这么一段代码:Reset_Handler ; Reset handler Reset_Handler PROC EXPORT Reset_Handler IMPORT __main IMPORT SysInit IMPORT SystemInit LDR R0, =SystemInit BLX R0 LDR R0, =SysInit BLX R0
[单片机]
stm32 <font color='red'>启动</font><font color='red'>代码</font>应用技巧
如何选择STM32的启动代码
●小容量产品是指闪存存储器容量在16K 至32K 字节之间的STM32F101xx、STM32F102xx和 STM32F103xx微控制器。 对应后缀ld ● 中容量产品是指闪存存储器容量在64K 至128K字节之间的STM32F101xx、STM32F102xx 和STM32F103xx微控制器。 对应后缀md ● 大容量产品是指闪存存储器容量在256K至512K字节之间的STM32F101xx和STM32F103xx 微控制器。对应后缀hd 闪存存储器容量在768K至1m字节之间的STM32F101xx和STM32F103xx 微控制器。对应后缀xl ● 互联型产品是STM32F105xx和STM32F107xx微控制器
[单片机]
如何选择STM32的<font color='red'>启动</font><font color='red'>代码</font>
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved