启动编译相关内容
ARM_Startup.s¶
File : ARM_Startup.s
Purpose : Generic startup and exception handlers for ARM devices.
Additional information:
Preprocessor Definitions
__FLASH_BUILD
If defined,
additional code can be executed in Reset_Handler,
which might be needed to run from Flash but not to run from RAM.
__SUPERVISOR_START
If defined,
application starts in supervisor mode instead of system mode.
__HYPERVISOR_START
If != 0 (default on ARMv8A and ARMv8R)
Check if system is in Hypervisor mode and leave it.
Might be necessary for at least ARMv8A/R,
because stack setup requires mode change, which cannot be
done in Hypervisor mode.
If == 0 (default otherwise)
Do not check mode before stack setup.
__SOFTFP__
Defined by the build system.
If not defined, the FPU is enabled for floating point operations.
文件:ARM_Startup.s
用途:ARM 设备的通用启动与异常处理代码。
预处理宏说明
__FLASH_BUILD
若定义,则 Reset_Handler 里会额外执行一段代码;
这段代码仅在“从 Flash 启动”时才需要,从 RAM 启动则不需要。
__SUPERVISOR_START
若定义,应用程序启动后直接进入 Supervisor 模式,而非默认的 System 模式。
__HYPERVISOR_START
≠ 0(ARMv8-A/R 默认)
先检查当前是否处于 Hypervisor 模式,如果是就退出该模式;
在 ARMv8-A/R 上必须这样做,因为后面要切模式来初始化栈,而 Hypervisor 模式下禁止切模式。
= 0(其它架构默认)
初始化栈之前不做模式检查。
__SOFTFP__
由编译系统自动定义。
若未定义,则表示使用硬件 FPU 做浮点运算。
*/
.syntax unified
#ifndef __HYPERVISOR_START
#if defined(__ARM_ARCH_8A__) || defined(__ARM_ARCH_8R__)
#define __HYPERVISOR_START 1
#else
#define __HYPERVISOR_START 0
#endif
#endif
/*********************************************************************
*
* Macros
*
**********************************************************************
*/
//
// Declare an interrupt handler
// 定义一个带默认参数的可调用宏
//
.macro ISR_HANDLER Name=
//
// Insert vector in vector table
//
// 切到向量表段,属性可分配(a)、可执行(x)。
// 标志字符串,a = allocatable(将来要装进 ELF 段头,占用 Flash),x = executable(允许 CPU 取指)。
.section .vectors, "ax"
ldr PC, =\Name
//
// Insert dummy handler in init section
//
// 再切到以函数名命名的独立段,用来放“默认的哑处理函数”。
.section .init.\Name, "ax"
.code 32 // 告诉汇编器后面的指令按 32-bit ARM 编码(和 Thumb 无关)。
.type \Name, function // 给符号打 STT_FUNC 类型,调试/链接更友好。
.weak \Name // 声明为“弱符号”。
.balign 4 // 4 字节对齐,保证指令地址合法。
\Name: // 标号,也就是默认处理函数入口。
1: b 1b // Endless loop // 原地跳自己,无限循环——典型的“未实现中断/异常就卡死”的默认行为。
END_FUNC \Name // 一般是个宏,等价于 .size \Name, .-\Name 把函数大小写进符号表,方便调试。
.endm // 宏定义结束。
//
// Place a reserved isr handler
//
.macro ISR_RESERVED
.section .vectors, "ax" // nop 指令的机器码是 0xE1A00000(ARM)或 0xBF00(Thumb-2 16-bit),占 4 字节,正好填满一个向量槽
nop
.endm
//
// Mark the end of a function and calculate its size
// . - \name 就是“光标位置 - 入口位置”
// .size \name , . - my_func 只是把算出来的这个差值填进符号表,告诉工具链 \name 这段机器码一共这么长。
.macro END_FUNC name
.size \name,.-\name
.endm
#if defined(__ARM_ARCH_4T__)
.macro blx reg
mov lr, pc
bx \reg
.endm
#endif
/*********************************************************************
*
* Global data
*
**********************************************************************
*/
/*********************************************************************
*
* Setup of the exception table
*
*/
.section .vectors, "ax"
.code 32
.balign 4
.global _vectors
_vectors:
ldr PC, =Reset_Handler
ISR_HANDLER undef_handler
ISR_HANDLER swi_handler
ISR_HANDLER pabort_handler
ISR_HANDLER dabort_handler
ISR_RESERVED
//ISR_HANDLER irq_handler
//增加新的
ldr PC, =IRQ_Handler
ISR_HANDLER fiq_handler
.section .vectors, "ax"
.size _vectors, .-_vectors
_vectors_end:
/*********************************************************************
*
* Global functions
*
**********************************************************************
*/
/*********************************************************************
*
* Reset_Handler
*
* Function description
* Exception handler for reset.
* Generic bringup of a system.
*/
.section .init.Reset_Handler, "ax"
.code 32
.balign 4
.global reset_handler
.global Reset_Handler
.equ reset_handler, Reset_Handler
.type Reset_Handler, function
Reset_Handler:
cpsid i /* 关闭全局中断 */
/* 关闭I,DCache和MMU
* 采取读-改-写的方式。
*/
mrc p15, 0, r0, c1, c0, 0 /* 读取CP15的C1寄存器到R0中 */
bic r0, r0, #(0x1 << 12) /* 清除C1寄存器的bit12位(I位),关闭I Cache */
bic r0, r0, #(0x1 << 2) /* 清除C1寄存器的bit2(C位),关闭D Cache */
bic r0, r0, #0x2 /* 清除C1寄存器的bit1(A位),关闭对齐 */
bic r0, r0, #(0x1 << 11) /* 清除C1寄存器的bit11(Z位),关闭分支预测 */
bic r0, r0, #0x1 /* 清除C1寄存器的bit0(M位),关闭MMU */
mcr p15, 0, r0, c1, c0, 0 /* 将r0寄存器中的值写入到CP15的C1寄存器中 */
#if 0
/* 汇编版本设置中断向量表偏移 */
ldr r0, =0X87800000
dsb
isb
mcr p15, 0, r0, c12, c0, 0
dsb
isb
#endif
/* 设置各个模式下的栈指针,
* 注意:IMX6UL的堆栈是向下增长的!
* 堆栈指针地址一定要是4字节地址对齐的!!!
* DDR范围:0X80000000~0X9FFFFFFF
*/
/* 进入IRQ模式 */
mrs r0, cpsr
bic r0, r0, #0x1f /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */
orr r0, r0, #0x12 /* r0或上0x13,表示使用IRQ模式 */
msr cpsr, r0 /* 将r0 的数据写入到cpsr_c中 */
ldr sp, =0x80600000 /* 设置IRQ模式下的栈首地址为0X80600000,大小为2MB */
/* 进入SYS模式 */
mrs r0, cpsr
bic r0, r0, #0x1f /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */
orr r0, r0, #0x1f /* r0或上0x13,表示使用SYS模式 */
msr cpsr, r0 /* 将r0 的数据写入到cpsr_c中 */
ldr sp, =0x80400000 /* 设置SYS模式下的栈首地址为0X80400000,大小为2MB */
/* 进入SVC模式 */
mrs r0, cpsr
bic r0, r0, #0x1f /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */
orr r0, r0, #0x13 /* r0或上0x13,表示使用SVC模式 */
msr cpsr, r0 /* 将r0 的数据写入到cpsr_c中 */
ldr sp, =0X80200000 /* 设置SVC模式下的栈首地址为0X80200000,大小为2MB */
cpsie i /* 打开全局中断 */
#if 0
/* 使能IRQ中断 */
mrs r0, cpsr /* 读取cpsr寄存器值到r0中 */
bic r0, r0, #0x80 /* 将r0寄存器中bit7清零,也就是CPSR中的I位清零,表示允许IRQ中断 */
msr cpsr, r0 /* 将r0重新写入到cpsr中 */
#endif
b _start /* 跳转到main函数 */
/* IRQ中断!重点!!!!! */
IRQ_Handler:
push {lr} /* 保存lr地址 */
push {r0-r3, r12} /* 保存r0-r3,r12寄存器 */
mrs r0, spsr /* 读取spsr寄存器 */
push {r0} /* 保存spsr寄存器 */
mrc p15, 4, r1, c15, c0, 0 /* 从CP15的C0寄存器内的值到R1寄存器中
* 参考文档ARM Cortex-A(armV7)编程手册V4.0.pdf P49
* Cortex-A7 Technical ReferenceManua.pdf P68 P138
*/
add r1, r1, #0X2000 /* GIC基地址加0X2000,也就是GIC的CPU接口端基地址 */
ldr r0, [r1, #0XC] /* GIC的CPU接口端基地址加0X0C就是GICC_IAR寄存器,
* GICC_IAR寄存器保存这当前发生中断的中断号,我们要根据
* 这个中断号来绝对调用哪个中断服务函数
*/
push {r0, r1} /* 保存r0,r1 */
cps #0x13 /* 进入SVC模式,允许其他中断再次进去 */
push {lr} /* 保存SVC模式的lr寄存器 */
ldr r2, =SystemIrqHandler /* 加载C语言中断处理函数到r2寄存器中*/
blx r2 /* 运行C语言中断处理函数,带有一个参数,保存在R0寄存器中 */
pop {lr} /* 执行完C语言中断服务函数,lr出栈 */
cps #0x12 /* 进入IRQ模式 */
pop {r0, r1}
str r0, [r1, #0X10] /* 中断执行完成,写EOIR */
pop {r0}
msr spsr_cxsf, r0 /* 恢复spsr */
pop {r0-r3, r12} /* r0-r3,r12出栈 */
pop {lr} /* lr出栈 */
subs pc, lr, #4 /* 将lr-4赋给pc */
/*************************** End of file ****************************/
SEGGER_ARM_Startup.s¶
FLASH1 RX 0x00910000 0x00010000;RAM1 RWX 0x00900000 0x00010000;FLASH2 RX 0x86800000 0x01000000;RAM2 RWX 0x80000000 0x01000000;
FLASH1 RX 0x00910000 0x00010000
RAM1 RWX 0x00900000 0x00010000
FLASH2 RX 0x86800000 0x01000000
RAM2 RWX 0x80000000 0x01000000