这篇文章原来放在CU上的,现在挪过来了。CU上设置不可见了。
1. 目标
这里主要是实验一下uclinux的系统调用。
2. 环境
OS :vmware + redhat 9
编译器 :arm-elf-gcc 2.95
ARM7模拟器:skyeye
3. 源文件
1个汇编(init.s),3个C文件(main.c, print.c, syscall.c),1个C头文件(unistd.h),1个Makefile,1个链接文件(syscall.lds),1个skyeye的配置文件(skyeye.conf),共8个文件
init.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,#'S'
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 ldr sp, =0x0c600000 mov r0,#'\n'
ldr r1,=UTXH0 @ print 'A'
str r0,[r1] b Main HandlerSWI:
stmfd sp!,{r0-r12,lr} stmfd sp!,{r0-r2} @ in this example, we use only three paramters at most ldr r0,[lr,#-4] @ lr is "swi #x" address, get swi instruction code
bic r0,r0,#0xff000000 @ get #x ldmfd sp!, {r1-r3} bl swi_c_handler @ c function use r0,r1 as parameter, and return result with r0 @ ldr r1,=UTXH0 @ print 'B'
@ str r0,[r1] str r0,[sp] @ change r0 to true result ldmfd sp!, {r0-r12,pc}^ @ ^,不能在用户模式使用 作用: 1.如果寄存器列表有pc, 还要把spsr复制到cpsr, 2.如果没有pc, 那么这些寄存器指的是用户寄存器,而不是当前模式的寄存器
main.c
#include "unistd.h" static inline __syscall0(void,hello);
static inline __syscall2(int,add,int,a,int,b);
static inline __syscall2(int,sub,int,a,int,b);
static inline __syscall2(int,sum,int *,p,int,count);
static inline __syscall3(int,sub3,int,a,int,b,int,c); int swi_c_handler(int sys_call_num,int param1,int param2,int param3){
int result=; switch(sys_call_num){ case __NR_hello:
sys_hello();
break; case __NR_add:
result = sys_add(param1,param2);
break; case __NR_sub:
result = sys_sub(param1,param2);
break; case __NR_sub3:
result = sys_sub3(param1,param2,param3);
break; case __NR_sum:
result = sys_sum((int *)param1,param2);
break; default:
print("no such call number: %d\n",sys_call_num);
result = -;
} return result;
} void Main(){
char *s="hello,world";
int num[]={,,,,}; // print("%s\n",s); hello();
print("5+8=%d\n",add(,));
print("28-13=%d\n",sub(,));
print("39-13-2=%d\n",sub3(,,));
print("4+7+10+3+8=%d\n",sum(num,)); while();
}
print.c
#include void print_char(char c){
__asm__ __volatile__ (
"mov r0,%0 \n\t"
"ldr r1,=0x01d00020 \n\t"
"str r0,[r1] \n\t"
:
:"r"((long)(c))
:"r0","r1");
} int itoa(char * buf,int num){
int i=,a=num,b; while(){
b = a % ;
a = a / ;
buf[i++]=b+'';
if(a==) break;
} return i;
} void print(char * fmt, ...){
char out_buf[],itoa_buf[],*s;
int n,i,index=,itoa_len; va_list args;
va_start(args,fmt); for(;*fmt;++fmt){
if(*fmt!='%'){
out_buf[index++]=*fmt;
continue;
}
fmt++;
switch(*fmt){
case 'd':
n = (int)va_arg(args,int);
itoa_len = itoa(itoa_buf,n);
for(i=itoa_len-;i>=;i--){
out_buf[index++]=itoa_buf[i];
}
break;
case 's':
s = (char *)va_arg(args,char *);
for(;*s;s++){
out_buf[index++]=*s;
}
break;
default:
out_buf[index++]=' ';
}
} out_buf[index]=; // NULL for(s=out_buf;*s;s++){
print_char(*s);
} va_end(args);
}
syscall.c
void sys_hello(){
print("hello, S3C44B0X!\n");
} int sys_add(int a,int b){
return a+b;
} int sys_sub(int a,int b){
return a-b;
} int sys_sub3(int a,int b,int c){
return a-b-c;
} int sys_sum(int * pnum, int count){
int sum=,i;
for(i=;i sum+=pnum[i];
}
return sum;
}
unistd.h
#ifndef __UNISTD_H_
#define __UNISTD_H_ #define __NR_SYSCALL_BASE 0X900000 #define __NR_hello (__NR_SYSCALL_BASE + 1)
#define __NR_add (__NR_SYSCALL_BASE + 2)
#define __NR_sub (__NR_SYSCALL_BASE + 3)
#define __NR_sub3 (__NR_SYSCALL_BASE + 4)
#define __NR_sum (__NR_SYSCALL_BASE + 5) #define __sys1(x) #x
#define __sys2(x) __sys1(x) #define __syscall(name) "swi " __sys2(__NR_##name) "\n\t" #define __syscall0(type,name) \
type name(){ \
long __res; \
__asm__ __volatile__ ( \
__syscall(name) \
"mov %0, r0 \n\t" \
:"=r"(__res) \
: \
:"r0","lr"); \
return (type)(__res); \
} #define __syscall1(type,name,type1,arg1){ \
type name(type1 arg1){ \
long __res; \
__asm__ __volatile ( \
"mov r0,%1 \n\t" \
__syscall(name) \
"mov %0,r0 \n\t" \
:"=r"((long)__res) \
:"r"((long)(arg1)) \
:"r0","lr"); \
} #define __syscall2(type,name,type1,arg1,type2,arg2) \
type name(type1 arg1,type2 arg2){ \
long __res; \
__asm__ __volatile ( \
"mov r0,%1 \n\t" \
"mov r1,%2 \n\t" \
__syscall(name) \
"mov %0,r0 \n\t" \
:"=r"((long)__res) \
:"r"((long)(arg1)),"r"((long)(arg2)) \
:"r0","r1","lr"); \
} #define __syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
type name(type1 arg1,type2 arg2,type3 arg3){ \
long __res; \
__asm__ __volatile ( \
"mov r0,%1 \n\t" \
"mov r1,%2 \n\t" \
"mov r2,%3 \n\t" \
__syscall(name) \
"mov %0,r0 \n\t" \
:"=r"((long)__res) \
:"r"((long)(arg1)),"r"((long)(arg2)),"r"((long)(arg3)) \
:"r0","r1","r2","lr"); \
} #endif
syscall.lds
OUTPUT_FORMAT("elf32-littlearm","elf32-littlearm","elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000; .text :
{
init.o (.text)
main.o (.text)
print.o (.text)
syscall.o (.text)
} . = ALIGN(); .data :
{
*(.data)
} . = ALIGN(); .bss :
{
*(.bss)
*(.rodata)
} }
Makefile
all: syscall syscall: init.o main.o print.o syscall.o
arm-elf-ld -T syscall.lds -o syscall init.o main.o print.o syscall.o
arm-elf-objcopy -O binary syscall syscall.bin init.o: init.s
arm-elf-as --gstabs -o init.o init.s main.o: main.c unistd.h
arm-elf-gcc -gstabs -c main.c print.o: print.c
arm-elf-gcc -gstabs -c print.c syscall.o: syscall.c
arm-elf-gcc -gstabs -c syscall.c .PHONY: clean
clean:
rm -f *.o syscall syscall.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=syscall.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
uart: mod=stdio
4. 运行
# skyeye -e syscall