免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1220 | 回复: 0
打印 上一主题 下一主题

5.2 裸机底层驱动设计方法 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-11-01 19:33 |只看该作者 |倒序浏览

5.2  裸机底层驱动设计方法
所谓裸机在这里主要是指系统软件平台没有用到操作系统。在基于ARM处理器平台的软件设计中,如果整个系统只需要完成一个相对简单而且独立的任务,那么可以不使用操作系统,只需要考虑在平台上如何正确地执行这个单任务程序。不过,在这种方式下同样需要一个Boot Loader,这个时候的Boot Loader一般是自己写的一个简单的启动代码加载程序。大家所熟悉的各种Boot Loader下的设备驱动,其实就是很好的裸机驱动程序。比如说U-Boot下的网卡驱动、串口驱动、LCD驱动等。
在裸机方式下,ARM的软件集成开发环境就显得极为重要,因为在这种方式下可以把所有代码都放在这个环境里面编写、编译和调试。在这种方式下测试驱动程序,首先要完成CPU的初始化,然后把需要测试的程序装载到系统的RAM区/或者SDRAM中。当然,如果需要处理一些复杂的中断处理的话,最好也把CPU的复位向量表放到RAM区中。把所有程序都调试好之后,再把最后的程序烧写到Flash里面去执行。
5.2.1  复位向量表
所谓复位向量表,其实就是一些跳转指令表,这些跳转指令就是针对ARM处理器的多种异常处理的,有关处理器的工作模式及异常处理的介绍,读者可以回顾本书1.4的介绍。复位向量表通常是放在CPU复位执行的第一块内存地址空间中,一般来说都是0x00000000这个地址。
在32位ARM系统中,都是在中断向量表中放置一条分支指令或PC寄存器加载指令,来实现程序跳转到中断服务例程的功能。例如:
     IRQEntry    B  HandleIRQ                     ;跳转范围较小一般在64KB之内
                    B  HandleFIQ                        ;
    或
     IRQEntry    LDR  PC,HandleIRQ ;跳转的范围是任意32位地址空间
                    LDR PC,HandleFIQ
LDR伪指令等效于生成一条存储读取指令和一条32位常数定义指令。32位常数存储在LDR指令附近的存储单元中,相对偏移小于4KB。该32位数据就是要跳转到中断服务程序的入口地址。之所以使用LDR伪指令,是因为ARM的RISC指令为单字指令,不能装载32位的立即数(常数),无法直接把一个32位常数数据或地址数据装载到寄存器中。下面一段程序与上述伪指令功能等效,但中断向量表描述得更为清晰。其中VectorTable为相对LDR指令的偏移量。
IRQEntry  LDR PC,VectorTable+0  ;与LDR PC,=HandleIRQ 等效
          LDR PC,VectorTable+4 ;与LDR PC,=HandleFIQ 等效
                   ……
VectorTable  DCD HandleIRQ
            DCD HandleFIQ
            ……
HandleIRQ
……
HandleFIQ
一个典型的复位向量表的例子(Nucleus系统中比较常用)如例程5-2所示。
例程5‑2  典型复位向量表
;**********************************
;* VECTOR TABLE                 *
;**********************************
    .sect   "vectors"
    .def    INT_Vectors
INT_Vectors
     LDR    pc, INT_Initialize_Addr                     ; 复位异常中断地址
     LDR    pc, INT_Undef_Inst_Addr                         ; 未定义指令异常中断地址
     LDR    pc, INT_Software_Addr                          ; 软件异常中断地址
     LDR    pc, INT_Data_Abort_Addr                         ; 取数据错误异常中断地址
     LDR    pc, INT_Reserved_Addr                        ; 保留
     LDR    pc, INT_IRQ_Addr                         ; IRQ异常中断地址
     LDR    pc, INT_FIQ_Addr                         ;  快速IRQ异常中断地址
INT_Initialize_Addr
        .word   _INT_Initialize
INT_Undef_Inst_Addr
        .word   _INT_Undef_Inst
INT_Software_Addr
        .word   _INT_Software
INT_Prefetch_Abort_Addr
        .word   _INT_Prefetch_Abort
INT_Data_Abort_Addr
        .word   _INT_Data_Abort
INT_Reserved_Addr
        .word   _INT_Reserved
INT_IRQ_Addr
        .word   _INT_IRQ
INT_FIQ_Addr
        .word   _INT_FIQ
从上面的复位向量程序可以看出,CPU判断如果是复位异常则会跳转到_INT_Initialize执行,如果是未定义指令异常则跳转到_INT_Undef_Inst执行程序,其他几个异常也是同样的处理方式。
一般ARM嵌入式系统的程序都是固化在从0x00000000开始的低端ROM空间中,中断向量表VectorTable也固化在ROM中,所以上述两种方法都无法在程序运行时动态、随机地修改中断向量表。不论对于初学ARM处理器的程序员还是有经验的程序员,设置中断向量都相当烦琐,必须修改ARM的C程序启动代码。
还有一点需要指出的是,如果CPU有REMAP功能的话,一定要在初始化程序的结尾把整个程序包含复位向量表一起复制到RAM中,然后执行REMAP,如果没有REMAP功能,则需要把复位向量表单独转移到RAM中去。
5.2.2  中断服务程序
ARM处理器的中断处理程序实际可以称为对于处理器的异常处理程序。在对这些异常进行处理时就需要一定的中断服务程序。一般在进入中断服务程序之前,都要完成对程序现场和一定数据、堆栈的保护,然后跳转到中断服务程序执行中断服务,完成中断服务之后,在退出中断服务程序之前恢复保存的数据、堆栈信息等。在ARM处理器设计中通常把复位初始化程序也算到异常中断处理程序中。对应处理器的8个异常,分别有如下8个处理程序。
n  _INTCPU_Initialize:用来处理CPU复位初始化异常中断;
n  _INT_Undef_Inst:用来处理未定义指令异常中断;
n  _INT_Software:用来处理软件异常中断;
n  _INT_Prefetch_Abort:用来处理取指溢出异常中断;
n  _INT_Data_Abort:用来处理数据溢出异常中断;
n  _INT_Reserved:保留异常中断;
n  _INT_FIQ:用来处理FIQ异常中断;
n  _INT_IRQ:用来处理IRQ异常中断。
在8个异常中断处理函数里面,常用的主要是处理器复位异常中断、软件异常中断、常规异常中断(IRQ)、快速异常中断(FIQ)4个。
下面结合实际的异常处理源码来具体分析这8个异常中断程序。这些代码针对的ARM处理器是OMAP5910。
1)CPU复位初始化异常中断处理INTCPU_Initialize,该异常中断处理的主要功能有:
(1)初始化处理器系统控制寄存器。
(2)初始化中断向量表。
(3)初始化系统堆栈指针。
(4)跳转到高级初始化函数,进行高级初始化。
该异常处理函数的具体代码通常如例程5-3所示。
例程5‑3  INTCPU_Initialize
    .def    _c_int00
_c_int00
.def  _INTCPU_Initialize
_INTCPU_Initialize:
    ; //确保处理器进入Super模式
    MRS     r0,CPSR                              ; 获取当前CPSR值
    BIC      r0,r0,#MODE_MASK                    ; 清除CPSR中对应的CPU模式位
    ORR     r0,r0,#SUP_MODE             ; 设置supervisor模式位
    ORR     r0,r0,#LOCKOUT              ; 确保 IRQ/FIQ 中断被禁止
    MSR     CPSR,r0                               ; 设置新的CPSR参数值
    ;//清除未初始化的BSS区域
    LDR     r0,BSS_Start                     ; 获取BSS段的起始地址
    MOV    r2,#0                                  ; 清除r2寄存器值
    LDR     r1,BSS_End                    ; 获取BSS段的结束地址
INT_BSS_Clear_Loop:        
    STR     r2,[r0],#4                         ; 进入循环清空BSS段数据
INT_BSS_Clear_Check:        
    CMP     r0,r1                                 ; 与BSS结束地址比较
    BNE     INT_BSS_Clear_Loop               ; 如果相等,表示BSS段清空了
    ; 判断C运行段是否需要自动初始化.  
    LDR     r0, c_cinit
    CMN     r0, #1
    BLNE    _auto_init
    ; 打开I-Cache (针对 TI 925T 处理器)
    MRC     p15,#0,r1,C1,C0,#0                  ; 获取CP15 协处理器中寄存器的值
    ORR     r1,r1,#0x1000                     ; 使能指令cache I-cache
    NOP
    MCR     p15,#0,r1,C1,C0,#0                  ; 写CP15协处理器的寄存器.
; 建立向量表装载标识位,主要是为让系统中的其他调用了解默认的向量表是否已经装载了。
; 如果INT_Loaded_Flag 为1, 表示所有的默认的向量表已经装载
; 否则, 如果INT_Loaded_Flag 为 0, 可以通过登记一个LISR来使得默认的向量被装载
; 在 ARM60系统应用中,这个变量总是为1
; 所有的向量必须通过这个函数建立
;    INT_Loaded_Flag =  0;
    MOV     r0,#1                        ; 设定所有的向量被装载(通过设置Loaded_Flag=1)
    LDR      r1,Loaded_Flag                   ;
    STR      r0,[r1,#0]                        ; 初始化Loaded_Flag
; 初始化系统堆栈指针。  通常在BSS段清空之后完成这个初始化,
; 原因是TCD_System_Stack也是一个BSS段里的变量。
; 这里定义在BSS段之后的ram空间为可以使用的堆栈空间。
;
    LDR    r10,System_Stk_Limit            
    LDR    r3,System_Limit                     ; 获取系统堆栈Limit地址
    STR    r10,[r3, #0]                          ; 保存该地址
    LDR    sp,System_Stack_SP                  ; 建立系统堆栈指针
    LDR    r3,System_Stack                     ; 获取系统堆栈地址
    STR    sp,[r3, #0]                          ; 保存堆栈指针
    MRS    r0,CPSR                                ; 获取当前的CPSR
    BIC     r0,r0,#MODE_MASK                     ; 清除模式位
    ORR    r0,r0,#IRQ_MODE              ; 设置IRQ_mode位
    MSR    CPSR,r0                                ;
    LDR    sp,IRQ_Stack_SP                  ; 建立IRQ堆栈指针
    MRS    r0,CPSR                               ; 获取当前的CPSR
    BIC     r0,r0,#MODE_MASK                     ; 清除模式位
    ORR    r0,r0,#FIQ_MODE                ; 设置FIQ_mode位
    MSR    CPSR,r0                               ;
    LDR     sp,FIQ_Stack_SP                  ; 建立FIQ堆栈指针
    MRS     r0,CPSR                              ; 获取当前的CPSR
    BIC      r0,r0,#MODE_MASK                    ; 清除模式位
    ORR     r0,r0,#SUP_MODE             ; 设置supervisor模式位
    MSR     CPSR,r0                              ; 建立了所有异常的堆栈之后
                                                 ;  返回supervisor模式
; 定义全局数据结构
; 初始化该数据结构。
;
;    TMD_HISR_Stack_Ptr =        (VOID *) r2;
;    TMD_HISR_Stack_Size =       TIMER_SIZE;
;    TMD_HISR_Priority =         TIMER_PRIORITY;
    LDR     r2,HISR_Stack_Mem               ; 获取HISR_Stack_Mem变量地址
    LDR     r3,HISR_Stack_Ptr                  ; 获取HISR_Stack_Ptr变量地址
    STR      r2,[r3, #0]                         ; 建立timer HISR堆栈指针
    MOV     r1,#HISR_STACK_SIZE        ; 获取HISR_STACK_SIZE参数值
    LDR      r3,HISR_Stack_Size                ; 获取HISR_Stack_Size变量地址
    STR      r1,[r3, #0]                         ; 设置timer HISR 堆栈大小
    MOV     r1,#HISR_PRIORITY           ; 获取HISR 优先级参数
                                                 ; HISR_PRIORITY的值(0-2)
    LDR      r3,HISR_Priority                   ; 获取HISR_Priority变量地址
    STR      r1,[r3, #0]                         ; 设置HISR 优先级
/*BL调用中断向量表建立函数*/
/*BL调用初始化Timer函数*/
    BL      _INT_Install_Vector_Table        ; 调用装载向量表子函数
    BL      _INT_Timer_Initialize           ; 调用初始化Timer函数
;
;
;   调用INC_Initialize分配第一个可用的ram地址,通常都是上层来进行调用的
;     INC_Initialize(first_available_memory);
    LDR     r0,First_Avail_Mem           ; 获取First_Avail_Mem地址
/*跳转到_INC_Initialze高级初始化部分*/
    B       _INC_Initialize                ; 跳转到高级初始化部分,注意使用B指令
复位异常处理是CPU上电复位之后第一个执行代码。复位异常中断处理不论是在裸机设计方式中,还是基于操作系统的软件设计方式中,都是最重要的异常处理程序之一。上述程序完成CPU的初始化,堆栈空间的初始化等工作。那么下面再看看其他几个异常处理函数的定义部分。
2)未定义指令异常服务程序
未定义指令异常在通常的系统设计中都不做深入处理,在完成对现场的保护后,在服务程序中打印出相关的提示信息。其服务程序通常如下:
.def _INT_Undef_Inst
_INT_Undef_Inst
    STMDB   sp!,{r0-r3,lr}
    LDMIA   sp!,{r0-r3,lr}                       ;保存寄存器组
    BX       LR
B        _INT_Undef_Inst
3)软件中断服务程序
这是一个由用户定义的中断指令,可用于用户模式下的程序调用特权操作。软件中断服务程序在基于操作系统的嵌入式系统设计中十分重要,可以通过该机制实现系统功能调用。软件中断服务程序的常规流程一般是先得到软件中断号,然后根据中断号执行不同的代码。常规的处理方式如下。
; The CPSR Register is not accessible User mode, so a switch to the
; privileged mode is done by the assembly instruction SWI.
.state32      
; 使能异常,建立堆栈
; Works only if called from 16-bit (THUMB) mode
;/-------------------------------------------------------------------
    .def _INT_Software
_INT_Software:
         LDRH  r4, [LR, #-2]                 ;得到软件中断指令
           AND          r4, r4, #0xFF                        ;把中断号放到寄存器R4中
/*对R4 进行判别,从而进入不同的处理,一系列的CMP和BEQ指令*/
           CMP    r4, #0xF6
         BEQ    SetFIQIRQBit
         …
         …  /*类似的CMP和BEQ指令*/
           CMP r4, #0xF3
           BEQ ClearFIQBit
           B       ExitSwi           ;
SetSupervisor:      //切换CPU模式到Supervisor模式
           MRS r7, SPSR                        ; 保存SPSR副本
           BIC   r7,r7,#MODE_MASK           ; 清除模式位
           ORR r7,r7,#SUP_MODE          ; 设置Supervisor模式位
           MSR SPSR, r7                        ; 写回SPSR参数
           B       ExitSwi                           ;
SetUser:         //切换CPU模式到User模式
           MRS r7, SPSR                               ; 保存SPSR副本
           BIC   r7, r7, #MODE_MASK          ; 清除模式位     
           ORR r7, r7, #USR_MODE         ; 设置User模式位
           MSR SPSR, r7                               ; 写回SPSR参数
           B       ExitSwi                               ;
EnableIRQ://使能IRQ
         MOV   r5, #IRQ_MODE
         MOV   r6, #IRQ_MASK
         B      DoIt
EnableFIQ://使能FIQ
         MOV   r5, #FIQ_MODE
         MOV   r6, #FIQ_MASK
      B      DoIt
Set_SVC_Stack://建立Supervisor模式下的堆栈               
           ;STACK  MANIPULATION
         MOV    SP, r0                          ; 堆栈地址
      MOV      r1,r1,lsl #2                    ; 转换字地址到字节地址
         ADD    SP, r1, SP                         ; 在初始化SP上累加
      B    ExitSwi
Set_Abort_or_Udef_Stack:
           MRS r2, CPSR
           BIC   r2, r2, #MODE_MASK
           ORR r2, r2, r5
           MSR CPSR, r2                                   ; 设置Udef模式位
         MOV   SP, r0                          ; 堆栈地址
           MOV         r1,r1,lsl #2                     ; 转换字地址到字节地址
         ADD   SP, r1, SP                         ; 在初始化SP上累加
           BIC   r2, r2, #MODE_MASK
           ORR r2, r2, #SUP_MODE
           MSR CPSR, r2                            ; 保存Supervisor模式位
           B       ExitSwi
SetIRQBit:
           MOV   r5, #IRQ_MASK
         MOV   r6, #SET_BIT
           B      SetClearFIQIRQ
ClearIRQBit:
           MOV   r5, #IRQ_MASK
         MOV   r6, #CLEAR_BIT
           B      SetClearFIQIRQ
SetFIQBit:
           MOV   r5, #FIQ_MASK
         MOV   r6, #SET_BIT
           B      SetClearFIQIRQ
ClearFIQBit:
           MOV   r5, #FIQ_MASK
         MOV   r6, #CLEAR_BIT
           B      SetClearFIQIRQ      
SetFIQIRQBit:
           MOV   r5, #FIQ_IRQ_MASK
         B      SetFIQIRQ
RestoreFIQIRQBit:
           MOV   r5, #FIQ_IRQ_MASK
         B      RestoreFIQIRQ
SetFIQIRQ:
           MRS   r7, SPSR                         ; 读取保存的SPSR
           ;
           AND          r0, r7, #0xC0                     ; 屏蔽FIQ、IRQ位,写入r0寄存器.
           ORR    r7, r7, r5                           ; 设置FIQ、IRQ位,保存SPSR
         B            STORE_SPSR
RestoreFIQIRQ:
           MRS    r7, SPSR                       ; 读取保存的SPSR值
           BIC   r7, r7, r5
           ORR    r7, r7, r0                           ; 设置FIQ、IRQ位,保存SPSR
           B                STORE_SPSR
SetClearFIQIRQ:
           MRS    r7, SPSR                        ; 读取保存的SPSR值
           BIC     r7, r7, r5                           ; 清除FIQ、IRQ位
           CMP r6, #CLEAR_BIT              ; 判断是否等于 #CLEAR_BIT
           BEQ STORE_SPSR                       ; 相等的话,调到STORE_SPSR
         ORR    r7, r7, r5                    ; 不相等,则设置FIQ、IRQ位,保存SPSR
STORE_SPSR:
         MSR    SPSR, r7                          ;保存SPSR
           B                ExitSwi
DoIt:
           ;
         MRS    r4, CPSR                         ; 读取保存的SPSR值
         BIC     r4,r4,#MODE_MASK  ; 清除所有的模式位
         ORR    r4,r4,r5                    ;
         MSR    CPSR, r4                ;
           ;STACK  MANIPULATION
         MOV    SP, r0                            ; 堆栈地址
MOV          r1,r1,lsl #2            ;
         ADD     SP, r1, SP               ;
           BIC      r4,r4,#MODE_MASK ;
         ORR     r4,r4,#SUP_MODE         
         MSR     CPSR, r4              ;
         MRS     r4,SPSR              ;
         BIC      r4,r4,r6                 ;
         MSR     SPSR,r4              ;        
                    
ExitSwi:
           MOVS    PC, R14                              ; 从SWI返回
取指异常、数据异常、保留异常中断处理函数都是比较简单的,通常都不做详细地处理,具体代码如4)、5)、6)所示。
4)取指异常中断服务程序如下所示
;********************************************************************
    .def _INT_Prefetch_Abort
_INT_Prefetch_Abort
    MOV     r0, lr
B       _INT_Prefetch_Abort
5)数据异常中断服务程序如下所示
;********************************************************************
    .def _INT_Data_Abort
_INT_Data_Abort:
    STMDB   sp!,{r0-r3,lr}
    LDMIA   sp!,{r0-r3,lr}               
    BX      LR                           
B       _INT_Data_Abort
6)保留异常中断服务程序如下所示
;********************************************************************
    .def _INT_Reserved
_INT_Reserved:
    MOV     r0, lr
    B       _INT_Reserved
7)IRQ中断服务程序
当ARM处理器的外部中断请求有效,而且CPSR寄存器的I控制位被清除时,ARM处理器产生外部中断请求IRQ异常中断。一般来说系统中的各个外设通常都是通过该异常中断请求ARM处理器服务的。IRQ中断服务程序如下所示。
;********************************************************************
        .def    _INT_IRQ
_INT_IRQ:
; ARM Core Check
    STMDB   sp!, {r1}
    MRS     r1, SPSR
    TST     r1, #IRQ_BIT
    LDMIA   sp!, {r1}
    SUBNES  pc,lr,#4
    STMDB   sp!,{r0-r4}                     ; 保存R0~R4到当前的IRQ堆栈空间中
    SUB     lr,lr,#4                          ; 调整IRQ返回地址
;********************************
;* Begin Hardware Specific Code *
;********************************
    LDR     r3, INT_CNTRL_BASE_1            ;
    LDR     r4, [r3,#INT_CNTRL_MIR]         ;
;******************************
;* End Hardware Specific Code *  
;******************************
    STMDB   sp!,{r4}  ;
    MVN     r4,#0       ;
;********************************
;* Begin Hardware Specific Code *
;********************************
    LDR     r2, [r3,#INT_CNTRL_ITR]         ;
;******************************
;* End Hardware Specific Code *
;******************************
LDR     r3, IRQ_Priority                ;
;以下流程在向量表里面进行优先级识别
IRQ_VECTOR_LOOP
    LDR     r0, [r3,#0]                    ; 从优先级表里面检查装载的第一个向量表
    MOV     r1, #1                           ;
    MOV     r1, r1, LSL r0                    ;
    TST     r1, r2                           ;
    BNE     IRQ_VECTOR_FOUND             ;
    BIC     r4,r4,r1                        ; 清除屏蔽位保证高级优先级
    ADD     r3, r3, #4                     ;
    ADR     r0, Priority_End          ;
    CMP     r0, r3   ;
    BNE     IRQ_VECTOR_LOOP        ;
    ;
    ADD     sp,sp,#4                                          ;
    LDMIA   sp!,{r0-r4}                                         ; 保存r0-r4
    STMDB   sp!,{lr}                                          ; 保存返回值
    LDMIA   sp!,{pc}^                               ; 保存SPSR等参数,返回
IRQ_VECTOR_FOUND
;********************************
;* Begin Hardware Specific Code *
;********************************
   LDR    r3, INT_CNTRL_BASE_1        
   MVN    r2, r1                       
   STR    r2, [r3,#INT_CNTRL_ITR]
   LDR    r2, [r3,#INT_CNTRL_MIR]         
   ORR    r4, r2, r4
   STR     r4, [r3,#INT_CNTRL_MIR]         ; 屏蔽所有低优先级中断
   MOV     r1, #1                                ; 清除pending中断
   STR     r1, [r3,#INT_CNTRL_CONTROL_REG]       ;
;******************************
;* End Hardware Specific Code *
;******************************
   LDR     r3, IRQ_Vectors                  ; 获取IRQ向量地址
   MOV     r2, r0, LSL #2        
    ADD     r3, r3, r2                                 ; 调整向量表地址到当前偏移量
   LDR     r2, [r3,#0]                       ; 从向量表转载跳转地址
   MOV     PC, r2                               ; 修改PC,进行跳转
; END: INT_IRQ
8)FIQ中断服务程序
当ARM处理器的快速中断请求有效,并且CPSR寄存器的F控制位被清除时,ARM处理器产生FIQ异常中断。FIQ中断服务程序如下所示。
;*************************************************************
    .def _INT_FIQ
_INT_FIQ
    .if $$isdefed("NU_FIQ_DEMO")
    STMDB   sp!, {r1}
    MRS     r1, SPSR
    TST     r1, #FIQ_BIT                        ;
    LDMIA   sp!, {r1}
    SUBNES  pc, lr, #4
    SUB     lr,lr,#4                                 ; 调整返回地址
    STMDB   sp!,{r0-r7,lr}                              ; 保存寄存器等到当前的FIQ堆栈空间
    LDR     r3, INT_CNTRL_BASE              ; 装载INT_CNTRL_BASE
    MOV     r1, #2                                          ; 清除pending中断
    STR     r1,[r3,#INT_CNTRL_CTRL_REG]  ;
    BL      _FIQ_LISR                                   ; 跳转到FIQ中断服务程序
    LDMIA   sp!,{r0-r7,pc}^                           ;
    .else
    B    _INT_FIQ
.endif
当然如果系统中很多中断没有用,那么对应的中断处理函数可以写得较为简单一些,甚至一条空语句就可以表示。主要的中断处理函数是IRQ和FIQ两个,在两个服务程序里面来判断中断状态寄存器,得到中断的产生源,然后分发出去。
在介绍了ARM处理器的复位向量表,以及相关的8个异常中断处理机制之后,接下来探讨一下在裸机方式下的常用程序调试方式。
5.2.3  程序调试方式
最常用的也是最方便的一种程序调试方式就是把程序加载到RAM区中去调试,在ADS集成开发环境下实现通常都需要一个入口函数。一个简单的例子程序代码如下。
    IMPORT  C_Entry
AREA    Init,CODE,READONLY
ENTRY
LDR R0,=0x3FF0000        ;初始化系统配置寄存器,它的地址为0X3FF0000
LDR R1,=0xE7FFFF80     ; Start_addr = 0x3FF00000
STR  R1,[R0]                   ; 4KB Cache,4KB SRAM,WB disable
   LDR      SP,=0x3FE1000      ;初始化用户堆栈,
BL    C_Entry                   ;跳转到函数C_Entry()处执行的C/C++代码
B.
END                                ;标识汇编代码的结束
在ADS下可以通过“Debug Settings”窗口设置RO Base(程序段的起始地址)和RW Base(数据段的起始地址),在“Options”选项卡中要注意指定程序实体entry(调试入口)的地址和“Equivalent Command Line”里面的组合语句的产生。在如图5-1所示的Debug Settings界面中,Image Entry point是0x40010000。注意一下图中红色圈里面的地址,这些地址都是在RAM区里面的。如果有多个程序时,可以在“Layout”选项卡里面指定第一个程序模块.o和第一个段名(Section)。通常填中断向量所在的模块。

图5‑1  Debug Settings界面
通过上面的介绍,现在就可以开始裸机驱动程序的设计了,不过要注意,主程序的入口函数一定是C_Entry()函数。裸机串口驱动的代码可以参考本书7.3介绍的代码例子。


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/83842/showart_1356829.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP