发新帖我要提问
12
返回列表
打印
[ARM程序分析与设计]

从头开始一个arm程序

[复制链接]
楼主: ruchong001
手机看帖
扫描二维码
随时随地手机跟帖
21
itelectron| | 2009-11-14 15:21 | 只看该作者 回帖奖励 |倒序浏览
#ifndef __OPTION_H__
#define __OPTION_H__

#define FCLK 296352000
#define HCLK (FCLK/3)
#define PCLK (HCLK/2)
//#define PCLK (HCLK)
#define UCLK 48000000

// for uart Baud rate.
//rUBRDIV0=( (int)(pclk/16./baud+0.5) -1 )
#define UBRDIV0_VAL        ((int)(PCLK/16./115200+0.5)-1)

// BUSWIDTH : 16,32
#define BUSWIDTH    (32)

//64MB
// 0x30000000 ~ 0x30ffffff : Download Area (16MB) Cacheable
// 0x31000000 ~ 0x33feffff : Non-Cacheable Area
// 0x33ff0000 ~ 0x33ff47ff : Heap & RW Area
// 0x33ff4800 ~ 0x33ff7fff : FIQ ~ User Stack Area
// 0x33ff8000 ~ 0x33fffeff : Not Useed Area
// 0x33ffff00 ~ 0x33ffffff : Exception & ISR Vector Table

#define _RAM_STARTADDRESS         0x30000000
#define _ISR_STARTADDRESS         0x33ffff00     
#define _MMUTT_STARTADDRESS        0x33ff8000
#define _STACK_BASEADDRESS        0x33ff8000
#define HEAPEND                          0x33ff0000
#define _NONCACHE_STARTADDRESS        0x31000000

//If you use ADS1.x, please define ADS10
#define ADS10 1


// note: makefile,option.a should be changed

#endif

使用特权

评论回复
22
itelectron| | 2009-11-14 15:22 | 只看该作者
#include "2440addr.h"                    /* S3C2440 definitions               */

使用特权

评论回复
23
itelectron| | 2009-11-14 15:23 | 只看该作者
/*********************************************************************
sub sp,sp,#4  ; 计算返回地址
//进入中断后,它的返回地址该怎么计算呢,可以这样来理解,因为它的指令流水线是3级的,
//即执行进入中断函数时,PC已经指向欲取值的指令即当前执行的地址+8;当已进入中断时,
LR里面装的是PC,所以要想中断返回到正确的地址处,就必须把LR-4。
【galaxy9229 发表于www.21ic 2008-9-25 16:51 ARM程序分析与设计】
/**********************************************************************/
IRQ_Entry
                sub    sp,sp,#4       ;//保留PC值//; 计算返回地址//SP=SP-4;
                stmfd    sp!,{r8-r9}  ;//将R8~R9 入栈。满递减堆栈。
               
                ldr    r9,=INTOFFSET  
                ldr    r9,[r9]
                ldr    r8,=HandleEINT0 ;读入中断偏移码
                add    r8,r8,r9,lsl #2 ;二级跳转表的首地址
                ldr    r8,[r8]
                str    r8,[sp,#8]                ;//中断入口地址送进SP(第一个代码留出的4字节空间)
                ldmfd    sp!,{r8-r9,pc}  ;//数据出栈,放入R8~R9,PC 寄存器。满递减堆栈。              
               
                ENDIF

Reset_Addr      DCD     Reset_Handler ;定义中断的入口地址
Undef_Addr      DCD     Undef_Handler        ;//DCD 用于分配一段字内存单元,并用伪指令中的expr 初始化
SWI_Addr        DCD     SWI_Handler
PAbt_Addr       DCD     PAbt_Handler
DAbt_Addr       DCD     DAbt_Handler
                DCD     0              ;//保留地址
IRQ_Addr        DCD     IRQ_Handler
FIQ_Addr        DCD     FIQ_Handler

Undef_Handler   B       Undef_Handler ;中断处理程序的入口地址//B为跳转指令|| ??自己跳转到自己??
SWI_Handler     B       SWI_Handler
PAbt_Handler    B       PAbt_Handler
DAbt_Handler    B       DAbt_Handler
               
                IF      IntVT_SETUP <> 1
IRQ_Handler     B       IRQ_Handler
                ENDIF
               
                IF      IntVT_SETUP <> 0
IRQ_Handler     B       IRQ_Entry
                ENDIF
               
FIQ_Handler     B       FIQ_Handler


;//存储控制器配制
                IF      MC_SETUP <> 0
MC_CFG
                DCD     BWSCON_Val
                DCD     BANKCON0_Val
                DCD     BANKCON1_Val
                DCD     BANKCON2_Val
                DCD     BANKCON3_Val
                DCD     BANKCON4_Val
                DCD     BANKCON5_Val
                DCD     BANKCON6_Val
                DCD     BANKCON7_Val
                DCD     REFRESH_Val
                DCD     BANKSIZE_Val
                DCD     MRSRB6_Val
                DCD     MRSRB7_Val
                ENDIF


;//时钟管理配置
                IF      CLOCK_SETUP <> 0
CLK_CFG
                DCD     LOCKTIME_Val     
                DCD     CLKDIVN_Val
                DCD     UPLLCON_Val
                DCD     MPLLCON_Val
                DCD     CLKSLOW_Val
                DCD     CLKCON_Val
                DCD     CAMDIVN_Val
                ENDIF

            
;//I/O 配置
               
                IF      PIO_SETUP <> 0
PIOA_CFG     
                DCD     PCONA_Val
PIOB_CFG        DCD     PCONB_Val
                DCD     PUPB_Val
PIOC_CFG        DCD     PCONC_Val
                DCD     PUPC_Val
PIOD_CFG        DCD     PCOND_Val
                DCD     PUPD_Val
PIOE_CFG        DCD     PCONE_Val
                DCD     PUPE_Val
PIOF_CFG        DCD     PCONF_Val
                DCD     PUPF_Val
PIOG_CFG        DCD     PCONG_Val
                DCD     PUPG_Val
PIOH_CFG        DCD     PCONH_Val
                DCD     PUPH_Val
PIOJ_CFG        DCD     PCONJ_Val
                DCD     PUPJ_Val
                ENDIF

; //复位处理模块
                                ;//下面是重起时的中断处理函数
                EXPORT  Reset_Handler  ;//定义一个全局函数名变量
Reset_Handler   

                IF      WT_SETUP <> 0                        ;//看门狗处理;若WT_SETUP为1,则执行下一个语句
                LDR     R0, =WT_BASE                        ;//ldr r0,0x12345678  是将内存0x12345678地址中存储的数据搬到r0寄存器中
                LDR     R1, =WTCON_Val                        ;//ldr r0,=0x12345678 可以理解为:将立即数0x12345678放到r0寄存器中
                LDR     R2, =WTDAT_Val
                STR     R2, [R0, #WTCNT_OFS]                ;//将R2 的数据存储到R0+WTCNT_OFS 存储单元,R0 值不变
                STR     R2, [R0, #WTDAT_OFS]
                STR     R1, [R0, #WTCON_OFS]                ;//看门狗禁止
                ENDIF
               
               
                IF      CLOCK_SETUP <> 0                        ;//时钟处理;若CLOCK_SETUP为1,则执行下一个语句        
                LDR     R0, =CLK_BASE            
                ADR     R8, CLK_CFG                                ;//将CLK_CFG 的地址放入R8
                LDMIA   R8, {R1-R7}                            ;//将CLK_CFG起始地址的8地址装载到R1-R7
                STR     R1, [R0, #LOCKTIME_OFS]
                STR     R2, [R0, #CLKDIVN_OFS]  
                STR     R3, [R0, #UPLLCON_OFS]
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                STR     R4, [R0, #MPLLCON_OFS]  
                STR     R5, [R0, #CLKSLOW_OFS]
                STR     R6, [R0, #CLKCON_OFS]
                STR     R7, [R0, #CAMDIVN_OFS]
                ENDIF                          
                                    
                IF      MC_SETUP <> 0                        ;//存储控制器处理;若MC_SETUP为1,则执行下一个语句
                ADR     R13, MC_CFG                       
                LDMIA   R13, {R0-R12}
                LDR     R13, =MC_BASE
                STMIA   R13, {R0-R12}                        ;//将R0-R12中的地址的数据装载到MC_BASE起始的13个寄存器。
                ENDIF                           
                                
                IF      PIO_SETUP <> 0                        ;//IO处理;若PIO_SETUP为1,则执行下一个语句
                LDR     R13, =PIO_BASE

                IF      PIOA_SETUP <> 0                        ;//端口A处理;若PIOA_SETUP为1,则执行下一个语句               
                ADR     R0, PIOA_CFG
                STR     R0, [R13, #PCONA_OFS]
                ENDIF

                IF      PIOB_SETUP <> 0                        ;//端口B处理               
                ADR     R0, PIOB_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCONB_OFS]
                STR     R1, [R13, #PUPB_OFS]
                ENDIF

                IF      PIOC_SETUP <> 0                        ;//端口C处理
                ADR     R0, PIOC_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCONC_OFS]
                STR     R1, [R13, #PUPC_OFS]
                ENDIF

                IF      PIOD_SETUP <> 0                        ;//端口D处理
                ADR     R0, PIOD_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCOND_OFS]
                STR     R1, [R13, #PUPD_OFS]
                ENDIF

                IF      PIOE_SETUP <> 0                          ;//端口E处理
                ADR     R0, PIOE_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCONE_OFS]
                STR     R1, [R13, #PUPE_OFS]
                ENDIF

                IF      PIOF_SETUP <> 0                          ;//端口F处理
                ADR     R0, PIOF_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCONF_OFS]
                STR     R1, [R13, #PUPF_OFS]
                ENDIF

                IF      PIOG_SETUP <> 0                          ;//端口G处理
                ADR     R0, PIOG_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCONG_OFS]
                STR     R1, [R13, #PUPG_OFS]
                ENDIF
  
                IF      PIOH_SETUP <> 0                         ;//端口H处理
                ADR     R0, PIOH_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCONH_OFS]
                STR     R1, [R13, #PUPH_OFS]
                ENDIF
               
                IF      PIOJ_SETUP <> 0                        ;//端口J处理
                ADR     R0, PIOJ_CFG
                LDR     R1, [R0,#4]
                STR     R0, [R13, #PCONJ_OFS]
                STR     R1, [R13, #PUPJ_OFS]
                ENDIF

                ENDIF

使用特权

评论回复
24
itelectron| | 2009-11-14 15:23 | 只看该作者
;;以下函数为进入相应的模式,并定义相应模式的端栈大小
;//为每个模式设置栈
                LDR     R0, =Stack_Top

;//进入未定义指令模式并设定其栈指针
                MSR     CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit                 ;//写状态寄存器指令ARM中只有MSR 指令可以直接设置状态寄存器CPSR或SPSR
                MOV     SP, R0                                                  ;//切换到未定义模式
                SUB     R0, R0, #UND_Stack_Size

;//进入异常中断模式,并设定其栈指针
                MSR     CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #ABT_Stack_Size

;//进入 FIQ 模式,并设定其栈指针
                MSR     CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #FIQ_Stack_Size

;//进入 IRQ 模式,并设定其栈指针
                MSR     CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #IRQ_Stack_Size

;//进入 Supervisor 模式,并设定其栈指针
                MSR     CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #SVC_Stack_Size
;                IMPORT MMU_EnableICache
;                bl     MMU_EnableICache


;//进入 用户 模式,并设定其栈指针  //;最后进入用户模式
                MSR     CPSR_c, #Mode_USR
                MOV     SP, R0
                SUB     SL, SP, #USR_Stack_Size


;//进入C代码
                                            ;
                IMPORT  __main
                LDR     R0, =__main
                BX      R0


;//用护初始堆与栈 ;//用户设置堆栈程序(C外部接口:用于动态申请内存使用)

                AREA    |.text|, CODE, READONLY

               ; IMPORT  __use_two_region_memory

                EXPORT  __user_initial_stackheap
__user_initial_stackheap  
/**********************************************************************
//__user_initial_stackheap 库函数用法翻译
用法:
        __user_initial_stackheap 返回这些值:
                1. 堆基址(heap base)                          ---> RO
                2. 栈基址(stack base,一般为栈的最高地址)       ---> R1
                3. 堆顶(heap limit)                           ---> R2
                4. 栈顶(stack limit)                          ---> R3
***********************************************************************/

                LDR     R0, =  Heap_Mem
                LDR     R1, =(Stack_Mem + USR_Stack_Size)
                LDR     R2, = (Heap_Mem +      Heap_Size)
                LDR     R3, = Stack_Mem
                BX      LR

                END

使用特权

评论回复
25
大碗拉面| | 2009-11-15 21:36 | 只看该作者
此贴很火~~

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则