arm swi 软中断 一例

原文在CU,挪过来了。

1. 目标

    本文单纯验证swi指令相关功能

2. 环境

    vmware + redhat 9 + arm-elf-gcc 2.95 + skyeye-1.2.6_rc1(模拟s3c44b0x)

3. 功能详述

     1). 调用swi前,关IRQ,FIQ,INTMSK,改变CPU模式为用户模式0x10000

     2). 指令的功能号由swi指令码的低24位传输,通过
           ldr r4,[lr,#-4]
           bic r4,r4,#0xff000000
          得到它的功能号,这样就可以根据功能号来进行相关功能的调用,
          本例只使用了两个功能号:
         

           swi #1   1 表示两个数的加法
           swi #2   2 表示两个数的减法
           加法和减法的函数在.c文件中定义

     3). 在swi的处理程序中,对于c函数int add(int a,int b)的参数传递是通过
           r0,r1进行的, add(),sub()的结果通过r0返回给swi的处理程序
                           
     4). swi的处理流程:  swi #x --> 0x00000008 --> HandlerSWI --> C函数, 仅此而已

4. 运行:

            #  skyeye 
    调试

           # skyeye -d

     不用再加文件名,文件写在skyeye.conf里了, 当然还得用arm-elf-gdb.

 

5. 文件清单(5个文件)

swi.s

.equ INTCON,   0x01e00000
.equ INTMSK,   0x01e0000c
.equ LOCKTIME, 0x01d8000c
.equ PLLCON,   0x01d80000
.equ CLKCON,   0x01d80004
.equ WTCON,    0x01d30000
.equ I_ISPR,   0x01e00020
.equ I_ISPC,   0x01e00024
.equ TCFG0,    0x01d50000
.equ TCFG1,    0x01d50004
.equ TCON,     0x01d50008
.equ TCNTB5,   0X01d50048
.equ UTXH0,    0x01d00020
.equ UFCON0,   0x01d00008
.equ ULCON0,   0x01d00000
.equ UCON0,    0x01d00004
.equ UBRDIV0,  0x01d00028


.globl _start
_start:
    b reset
    b .
    b HandlerSWI
    b .
    b .
    b .
    b .
    b .


reset:
    mov r0,#0x80 | 0x40 | 0x13  @ svc, disable irq,fiq
    msr cpsr_c,r0

    ldr sp, =0x0c700000

    ldr r0,=WTCON        @ disable watch dog
    ldr r1, =0x0
    str r1, [r0]

    ldr r0, =INTCON      @ non-vector mode, disable irq, disable fiq
    ldr r1, =0x7
    str r1, [r0]

    ldr r0, =LOCKTIME
    ldrb r1, =800
    strb r1, [r0]

    ldr r0, =PLLCON
    ldr r1, =0x34031
    str r1,[r0]
    
    ldr r0, =CLKCON
    ldr r1, =0x7ff8
    str r1, [r0]

    @ UART 0
    ldr r0,=UFCON0
    mov r1,#0x0
    str r1,[r0]

    ldr r0,=ULCON0
    mov r1,#0x03
    str r1,[r0]
    
    ldr r0,=UCON0
    mov r1,#0x05
    str r1,[r0]

    ldr r0,=UBRDIV0
    mov r1,#32
    str r1,[r0]

    ldr r0,=UTXH0        @ print 'C'
    mov r1,#'C'
    str r1,[r0]
    
    @ sp_svc
    ldr sp,=0x0c700000
    
    ldr r0, =INTMSK
    ldr r1, =0x03ffffff  @ disable all irq.
    str r1, [r0]
    
    @ move to user mode

    mov r0, #0x80 | 0x40 | 0x10  @ svc, disable irq,fiq
    msr cpsr_c,r0

    mov r0, #'A'
    mov r1, #0x1
    swi #1              @ add('A',1), print 'B'

    ldr r1,=UTXH0       @ print 'A'
    str r0,[r1]

    mov r0, #'H'        @ subtract
    mov r1, #0x1        @
    swi #2              @ sub('H',1), print 'G'

    ldr r1,=UTXH0       @ print 'H'
    str r0,[r1]
    
    ldr r1,=UTXH0       @ print 'S' -- STOP
    mov r0,#'S'
    str r0,[r1]

stop:    b stop              @ while(1);


HandlerSWI:       
    stmfd sp!,{r0-r12,lr}   

    ldr r4,[lr,#-4]         @ lr is "swi #x" address, get swi instruction code
    bic r4,r4,#0xff000000   @ get #x

    cmp r4,#1               @ 1 -- add(a,b)
    bne next

    bl add                  @ c function use r0,r1 as parameter, and return result with r0
    ldr r1,=UTXH0           @ print 'B'
    str r0,[r1]

next:
    cmp r4,#2               @ 2 -- sub(a,b)
    bne swi_return

    bl sub
    ldr r1,=UTXH0           @ print 'G'
    str r0,[r1]

swi_return:
    ldmfd sp!, {r0-r12,pc}^

c_fun.c

int add(int a,int b){
    return a + b;
}

int sub(int a,int b){
    return a - b;
}

 

swi.lds

OUTPUT_FORMAT("elf32-littlearm","elf32-littlearm","elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
    . = 0x00000000;

    .text :
    {
            swi.o (.text)
    }
    
    . = ALIGN(4);
    .data :
    {
       *(.data)
    }

}

Makefile

all: swi

swi: swi.o c_fun.o
    arm-elf-ld -T swi.lds -o swi swi.o c_fun.o
    arm-elf-objcopy -O binary -S swi swi.bin

swi.o: swi.s
    arm-elf-as --gstabs -o swi.o swi.s

c_fun.o: c_fun.c
    arm-elf-gcc -gstabs -c c_fun.c

.PHONY: clean
clean:    
    rm -f swi.o c_fun.o swi swi.bin

 

skyeye.conf

#skyeye config file for S3C44B0X
cpu: arm7tdmi
mach: s3c44b0x

# physical memory
mem_bank: map=M, type=RW, addr=0x00000000, size=0x00200000, file=swi.bin
mem_bank: map=M, type=RW, addr=0x0c000000, size=0x00800000

# peripherals I/O mapping area
mem_bank: map=I, type=RW, addr=0x01c00000, size=0x00400000

# uart 0
uart: mod=stdio

 

posted @ 2018-01-04 22:34  北极熊129  阅读(1377)  评论(0编辑  收藏  举报