概述
全志v3s裸机启动需要初始化堆栈,需要使用汇编代码,这个是从NXP官方例程中借鉴进行修改的,启动后先关闭中断,cache,mmu等,然后初始化堆栈指针,3个不同状态下的堆栈,中断模式,SVC模式,正常模式下的堆栈。
我是使用IAR进行开发的,这个.S文件只能用于IAR.
//startup.s
MODULE ?cstartup
;; Forward declaration of sections.
SECTION CSTACK:DATA:NOROOT(3)
SECTION IRQ_STACK:DATA:NOROOT(3)
SECTION SVC_STACK:DATA:NOROOT(3)
SECTION .intvec:CODE:NOROOT(2)
PUBLIC __vector_table
DATA
__vector_table
ARM
LDR PC, Reset_Word ; Reset
LDR PC, Undefined_Word ; Undefined instructions
LDR PC, SVC_Word ; Supervisor Call
LDR PC, PrefAbort_Word ; Prefetch abort
LDR PC, DataAbort_Word ; Data abort
DCD 0 ; RESERVED
LDR PC, IRQ_Word ; IRQ interrupt
LDR PC, FIQ_Word ; FIQ interrupt
DATA
Reset_Word DCD __iar_program_start ;复位地址
Undefined_Word DCD Undefined_Handler ;未定义指令异常
SVC_Word DCD SVC_Handler ;软件中断,管理模式
PrefAbort_Word DCD PrefAbort_Handler ;中止预取模式
DataAbort_Word DCD DataAbort_Handler ;中止数据模式
Reserve_Word DCD 0 ;保留
IRQ_Word DCD IRQ_Handler ;中断模式
FIQ_Word DCD FIQ_Handler ;快速中断模式
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Default interrupt handlers.
;;
PUBLIC __iar_program_start
SECTION .text:CODE:REORDER:NOROOT(2)
REQUIRE __vector_table
EXTERN __cmain
EXTERN SystemInit
EXTERN __iar_data_init3
VFPEnable EQU (0x40000000) ;VFP使能设置
ARM
__iar_program_start
CPSID I ; Mask interrupts
; Reset SCTLR Settings
MRC P15, 0, R0, C1, C0, 0 ; Read CP15 System Control register
BIC R0, R0, #(0x1 << 12) ; Clear I bit 12 to disable I Cache
BIC R0, R0, #(0x1 << 2) ; Clear C bit 2 to disable D Cache
BIC R0, R0, #0x2 ; Clear A bit 1 to disable strict alignment
BIC R0, R0, #(0x1 << 11) ; Clear Z bit 11 to disable branch prediction
BIC R0, R0, #0x1 ; Clear M bit 0 to disable MMU
MCR P15, 0, R0, C1, C0, 0 ; Write value back to CP15 System Control register
; Set up stack for IRQ, System/User and Supervisor Modes
; Enter IRQ mode
CPS #0x12
LDR SP, =SFE(IRQ_STACK) ; Set up IRQ handler stack
; Enter System mode
CPS #0x1F
LDR SP, =SFE(CSTACK) ; Set up System/User Mode stack
; Enter Supervisor mode
CPS #0x13
LDR SP, =SFE(SVC_STACK) ; Set up Supervisor Mode stack
LDR R0, =SystemInit
BLX R0
CPSIE I ; Unmask interrupts
; Application runs in Supervisor mode
LDR R0, =__cmain
BX R0
PUBWEAK Undefined_Handler
PUBWEAK SVC_Handler
PUBWEAK PrefAbort_Handler
PUBWEAK DataAbort_Handler
PUBWEAK IRQ_Handler
PUBWEAK FIQ_Handler
SECTION .text:CODE:REORDER:NOROOT(2)
EXTERN SystemIrqHandler
ARM
Undefined_Handler
B . ; Undefined instruction at address LR-Off (Off=4 in ARM mode and Off=2 in THUMB mode)
SVC_Handler
B . ; Supervisor call from Address LR
PrefAbort_Handler
B . ; Prefetch instruction abort at address LR-4
DataAbort_Handler
B . ; Load data abort at instruction address LR-8
IRQ_Handler
PUSH {LR} ; Save return address+4
PUSH {R0-R3, R12} ; Push caller save registers
MRS R0, SPSR ; Save SPRS to allow interrupt reentry
PUSH {R0}
MRC P15, 4, R1, C15, C0, 0 ; Get GIC base address
ADD R1, R1, #0x2000 ; R1: GICC base address
LDR R0, [R1, #0xC] ; R0: IAR 读取IAR寄存器,获取中断源
PUSH {R0, R1}
CPS #0x13 ; Change to Supervisor mode to allow interrupt reentry
PUSH {LR} ; Save Supervisor LR
LDR R2, =SystemIrqHandler
BLX R2 ; Call SystemIrqHandler with param IAR
POP {LR}
CPS #0x12 ; Back to IRQ mode
POP {R0, R1}
STR R0, [R1, #0x10] ; Now IRQ handler finished: write to EOIR
POP {R0}
MSR SPSR_CXSF, R0
POP {R0-R3, R12}
POP {LR}
SUBS PC, LR, #4
FIQ_Handler
B . ; Unexpected FIQ
END
上面代码完成了初始化堆栈以及中断向量入库等操作,SystemIrqHandler函数报错可以自己随便实现一个即可,保留为空,这个是后面使用中断时会用得上,函数原型为 void SystemIrqHandler(int irq);
上面的代码中没有指定IRAM IROM 中断向量表其实地址,堆栈大小,这几个参数要修改.icf文件,将一下的代码保存到工程目录下,名称为v3s.icf文件。
//v3s.icf
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$configideIcfEditora_tz_hyp_v1_1.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x41000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_IROM1_start__ = 0x41000000;
define symbol __ICFEDIT_region_IROM1_end__ = 0x41FFFFFF;
define symbol __ICFEDIT_region_IROM2_start__ = 0x0;
define symbol __ICFEDIT_region_IROM2_end__ = 0x0;
define symbol __ICFEDIT_region_EROM1_start__ = 0x0;
define symbol __ICFEDIT_region_EROM1_end__ = 0x0;
define symbol __ICFEDIT_region_EROM2_start__ = 0x0;
define symbol __ICFEDIT_region_EROM2_end__ = 0x0;
define symbol __ICFEDIT_region_EROM3_start__ = 0x0;
define symbol __ICFEDIT_region_EROM3_end__ = 0x0;
define symbol __ICFEDIT_region_IRAM1_start__ = 0x40000000;
define symbol __ICFEDIT_region_IRAM1_end__ = 0x40FFFFFF;
define symbol __ICFEDIT_region_IRAM2_start__ = 0x0;
define symbol __ICFEDIT_region_IRAM2_end__ = 0x0;
define symbol __ICFEDIT_region_ERAM1_start__ = 0x0;
define symbol __ICFEDIT_region_ERAM1_end__ = 0x0;
define symbol __ICFEDIT_region_ERAM2_start__ = 0x0;
define symbol __ICFEDIT_region_ERAM2_end__ = 0x0;
define symbol __ICFEDIT_region_ERAM3_start__ = 0x0;
define symbol __ICFEDIT_region_ERAM3_end__ = 0x0;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x0400;
define symbol __ICFEDIT_size_svcstack__ = 0x400;
define symbol __ICFEDIT_size_irqstack__ = 0x400;
define symbol __ICFEDIT_size_fiqstack__ = 0x200;
define symbol __ICFEDIT_size_undstack__ = 0x200;
define symbol __ICFEDIT_size_abtstack__ = 0x200;
define symbol __ICFEDIT_size_monstack__ = 0x0;
define symbol __ICFEDIT_size_hypstack__ = 0x0;
define symbol __ICFEDIT_size_heap__ = 0x0400;
/**** End of ICF editor section. ###ICF###*/
define memory mem with size = 4G;
define region IROM_region = mem:[from __ICFEDIT_region_IROM1_start__ to __ICFEDIT_region_IROM1_end__]
| mem:[from __ICFEDIT_region_IROM2_start__ to __ICFEDIT_region_IROM2_end__];
define region EROM_region = mem:[from __ICFEDIT_region_EROM1_start__ to __ICFEDIT_region_EROM1_end__]
| mem:[from __ICFEDIT_region_EROM2_start__ to __ICFEDIT_region_EROM2_end__]
| mem:[from __ICFEDIT_region_EROM3_start__ to __ICFEDIT_region_EROM3_end__];
define region IRAM_region = mem:[from __ICFEDIT_region_IRAM1_start__ to __ICFEDIT_region_IRAM1_end__]
| mem:[from __ICFEDIT_region_IRAM2_start__ to __ICFEDIT_region_IRAM2_end__];
define region ERAM_region = mem:[from __ICFEDIT_region_ERAM1_start__ to __ICFEDIT_region_ERAM1_end__]
| mem:[from __ICFEDIT_region_ERAM2_start__ to __ICFEDIT_region_ERAM2_end__]
| mem:[from __ICFEDIT_region_ERAM3_start__ to __ICFEDIT_region_ERAM3_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block SVC_STACK with alignment = 8, size = __ICFEDIT_size_svcstack__ { };
define block IRQ_STACK with alignment = 8, size = __ICFEDIT_size_irqstack__ { };
define block FIQ_STACK with alignment = 8, size = __ICFEDIT_size_fiqstack__ { };
define block UND_STACK with alignment = 8, size = __ICFEDIT_size_undstack__ { };
define block ABT_STACK with alignment = 8, size = __ICFEDIT_size_abtstack__ { };
define block MON_STACK with alignment = 8, size = __ICFEDIT_size_monstack__ { };
define block HYP_STACK with alignment = 8, size = __ICFEDIT_size_hypstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
do not initialize { section .noinit };
initialize by copy { readwrite };
if (isdefinedsymbol(__USE_DLIB_PERTHREAD))
{
// Required in a multi-threaded application
initialize by copy with packing = none { section __DLIB_PERTHREAD };
}
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place in IROM_region { readonly };
place in EROM_region { readonly section application_specific_ro };
place in IRAM_region { readwrite,
block CSTACK, block SVC_STACK, block IRQ_STACK, block FIQ_STACK,
block UND_STACK, block ABT_STACK, block MON_STACK, block HYP_STACK, block HEAP };
place in ERAM_region { readwrite section application_specific_rw };
其中__ICFEDIT_intvec_start__ 是中断向量位置
__ICFEDIT_region_IROM1_start__ ROM开始位置,就是代码下载位置
__ICFEDIT_region_IROM1_start__ RAM开始位置
我的代码里面已经使用了外部SDRAM,所以地址是0x40000000开始的位置了,你如果使用的时候还没使用到SDRAM(后面文章会教你如何使用),就使用内部SRAM作为ROM与RAM即可,比如使用
SRAM A1作为RAM SRAM C作为ROM即可
define symbol __ICFEDIT_intvec_start__ = 0x4000;
define symbol __ICFEDIT_region_IROM1_start__ = 0x4000;
define symbol __ICFEDIT_region_IROM1_end__ = 0xEFFF;
define symbol __ICFEDIT_region_IRAM1_start__ = 0x0000;
define symbol __ICFEDIT_region_IRAM1_end__ = 0x3FFF;
define symbol __ICFEDIT_size_cstack__ = 0x0400;
define symbol __ICFEDIT_size_svcstack__ = 0x400;
define symbol __ICFEDIT_size_irqstack__ = 0x400;
上面这个是使用内部SRAM需要修改的地方,最底部3个就是堆栈大小,根据需要设置。
.icf文件修改好后,在设置里面 linker->config 里面勾选 Override default 然后添加刚刚那个icf文件。
实现一个简单的main函数,即可开始裸机运行了。
CPU配置选择Cortex A7,这里开启了浮点运算VFP,需要在ARM中使用汇编开启,上面的启动文件中有个SystemInit()函数,先实现一个空的,后面例程里面会提供这个SystemInit(),这个主要用来初始化VFP,关闭MMU,开启cache等操作,开始时不要用浮点运算就行。
最后
以上就是妩媚紫菜为你收集整理的全志V3S裸机启动的全部内容,希望文章能够帮你解决全志V3S裸机启动所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复