我是靠谱客的博主 妩媚紫菜,最近开发中收集的这篇文章主要介绍全志V3S裸机启动,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

全志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裸机启动所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部