Chinaunix首页 | 论坛 | 博客
  • 博客访问: 850815
  • 博文数量: 213
  • 博客积分: 5048
  • 博客等级: 大校
  • 技术积分: 1883
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-14 10:14
文章分类

全部博文(213)

文章存档

2011年(4)

2010年(55)

2009年(47)

2008年(107)

我的朋友

分类: 嵌入式

2009-12-19 13:40:18

    公司还在用IAR4.30的,我想反正之前我都没用,不如用最新的。。我装了IAR5.40试了下,IAR5.X跟IAR4.X最大的差别我觉得就是连接器了,4系列用的Xlink,5系列用的Ilink。还有一些小差别,如汇编文件可以s结尾了,取消了4系列的s79结尾。在细节的我也不是很清楚。
    不过感肯定的是高版本的确实比以前更加人性化了,IAR5.40对ATMEL的支持更多更全面了,example很不错,对samsung片子的支持还是一如既往的差,我自己总结就是:ARM7不用OS或者用ucos的片子可能用IAR,这样开发更加方便,而像arm9那种需要linux的片子,一般都不用IAR,他们用gcc可能更多些,最多也就是bootstrap用IAR开发一下。

    言归正传,IAR5.40的example里面有对AT91SAM7S-EK的工程,和启动部分有关系也就下面几个文件:
at91lib/board_cstartup_iar.s //启动部分汇编代码
at91lib/board_lowlevel.c   //启动阶段的cpu的有关初始化
at91lib/board_memories.c  //remap部分
at91lib/board.h
at91lib/board_memories.h
还有一个icf文件,和ilink有关的文件,在4系列xlink的时候是xcl文件

board_cstartup_iar.s
主要做了这样几件事:
中断向量表
IRQ,FIQ中断的函数
定义reset的标记resetHandler
lowinit(调用board_lowlevel.c,间接调用board_memories.c)
初始化几个mode的sp
跳转到main

MODULE ?cstartup

        ;; Forward declaration of sections.
        SECTION IRQ_STACK:DATA:NOROOT(2)
        SECTION CSTACK:DATA:NOROOT(3)

//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------

#define __ASSEMBLY__
#include "board.h"

//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------

#define ARM_MODE_ABT 0x17
#define ARM_MODE_FIQ 0x11
#define ARM_MODE_IRQ 0x12
#define ARM_MODE_SVC 0x13
#define ARM_MODE_SYS 0x1F

#define I_BIT 0x80
#define F_BIT 0x40

//------------------------------------------------------------------------------
// Startup routine
//------------------------------------------------------------------------------

/*
   Exception vectors
 */
        SECTION .vectors:CODE:NOROOT(2)

        PUBLIC resetVector
        PUBLIC irqHandler

        EXTERN Undefined_Handler
        EXTERN SWI_Handler
        EXTERN Prefetch_Handler
        EXTERN Abort_Handler
        EXTERN FIQ_Handler

        ARM

__iar_init$$done: ; The interrupt vector is not needed
                                ; until after copy initialization is done

resetVector:
        ; All default exception handlers (except reset) are
        ; defined as weak symbol definitions.
        ; If a handler is defined by the application it will take precedence.
        LDR pc, =resetHandler ; Reset
        LDR pc, Undefined_Addr ; Undefined instructions
        LDR pc, SWI_Addr ; Software interrupt (SWI/SYS)
        LDR pc, Prefetch_Addr ; Prefetch abort
        LDR pc, Abort_Addr ; Data abort
        B . ; RESERVED
        LDR pc, =irqHandler ; IRQ
        LDR pc, FIQ_Addr ; FIQ

Undefined_Addr: DCD Undefined_Handler
SWI_Addr: DCD SWI_Handler
Prefetch_Addr: DCD Prefetch_Handler
Abort_Addr: DCD Abort_Handler
FIQ_Addr: DCD FIQ_Handler
    
/*
   Handles incoming interrupt requests by branching to the corresponding
   handler, as defined in the AIC. Supports interrupt nesting.
 */
irqHandler:
        /* Save interrupt context on the stack to allow nesting */
        SUB lr, lr, #4
        STMFD {lr}
        MRS lr, SPSR
        STMFD {r0, lr}

        /* Write in the IVR to support Protect Mode */
        LDR lr, =AT91C_BASE_AIC
        LDR r0, [r14, #AIC_IVR]
        STR lr, [r14, #AIC_IVR]

        /* Branch to interrupt handler in Supervisor mode */
        MSR CPSR_c, #ARM_MODE_SYS
        STMFD {r1-r3, r4, r12, lr}
        MOV lr, pc
        BX r0
        LDMIA {r1-r3, r4, r12, lr}
        MSR CPSR_c, #ARM_MODE_IRQ | I_BIT

        /* Acknowledge interrupt */
        LDR lr, =AT91C_BASE_AIC
        STR lr, [r14, #AIC_EOICR]

        /* Restore interrupt context and branch back to calling code */
        LDMIA {r0, lr}
        MSR SPSR_cxsf, lr
        LDMIA {pc}^


/*
   After a reset, execution starts here, the mode is ARM, supervisor
   with interrupts disabled.
   Initializes the chip and branches to the main() function.
 */
        SECTION .cstartup:CODE:NOROOT(2)

        PUBLIC resetHandler
        EXTERN LowLevelInit
        EXTERN ?main
        REQUIRE resetVector
        ARM

resetHandler:

        /* Set pc to actual code location (i.e. not in remap zone) */
     LDR pc, =label

        /* Perform low-level initialization of the chip using LowLevelInit() */
label:
     LDR r0, =LowLevelInit
        LDR r4, =SFE(CSTACK)
        MOV sp, r4
        MOV lr, pc
        BX r0

        /* Set up the interrupt stack pointer. */
        MSR cpsr_c, #ARM_MODE_IRQ | I_BIT | F_BIT ; Change the mode
        LDR sp, =SFE(IRQ_STACK)

        /* Set up the SYS stack pointer. */
        MSR cpsr_c, #ARM_MODE_SYS | F_BIT ; Change the mode
        LDR sp, =SFE(CSTACK)

        /* Branch to main() */
        LDR r0, =?main
        MOV lr, pc
        BX r0

        /* Loop indefinitely when program is finished */
loop4:
        B loop4

        END

board_lowlevel.c主要做的就是系统时钟的初始化和中断地址的赋值。最后做remap。
对比之前版本的cstartup,我感到最大的方便就是remap的实现,现在的remap放在board_memories.c中实现了,而且有ilink的原因,remap吧中断向量表copy那部分也自动实现了。
initialize by copy { section .vectors };

在remap的过程中我觉得有两点重点需要理解一下:
1、LDR pc, =label
这句话是标记label的地址+rom的start地址赋值给pc,这里rom的start值为0x00100000。reset刚开始是从基地址0运行的。这是ld部分的知识,运行地址和装载地址不相同的情况,具体我就不多说了。
2、第二个就是解释为什么可以直接从基地址0,直接跳到基地址0x00100000.这是因为at91的芯片内部flash,首先可以通过首地址0x00100000访问,内部ram可以通过0x00200000。0x00000000-0x000FFFFF是remap区域,这块区域在remap前映射的是flash的空间,remap后映射的是ram的空间。所以remap之前我们通过基地址0和基地址0x0010000来访问flash,remap之后我们可以通过基地址0和基地址0x00200000访问。
阅读(4193) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~