这篇文章原来放在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,#' ' 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=0; 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 ",sys_call_num); result = -1; } return result; } void Main(){ char *s="hello,world"; int num[5]={4,7,10,3,8}; //32 print("%s ",s); hello(); print("5+8=%d ",add(5,8)); print("28-13=%d ",sub(28,13)); print("39-13-2=%d ",sub3(39,13,2)); print("4+7+10+3+8=%d ",sum(num,5)); while(1); }
print.c
#include void print_char(char c){ __asm__ __volatile__ ( "mov r0,%0 " "ldr r1,=0x01d00020 " "str r0,[r1] " : :"r"((long)(c)) :"r0","r1"); } int itoa(char * buf,int num){ int i=0,a=num,b; while(1){ b = a % 10; a = a / 10; buf[i++]=b+'0'; if(a==0) break; } return i; } void print(char * fmt, ...){ char out_buf[128],itoa_buf[10],*s; int n,i,index=0,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-1;i>=0;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]=0; // NULL for(s=out_buf;*s;s++){ print_char(*s); } va_end(args); }
syscall.c
void sys_hello(){ print("hello, S3C44B0X! "); } 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=0,i; for(i=0;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) " " #define __syscall0(type,name) type name(){ long __res; __asm__ __volatile__ ( __syscall(name) "mov %0, r0 " :"=r"(__res) : :"r0","lr"); return (type)(__res); } #define __syscall1(type,name,type1,arg1){ type name(type1 arg1){ long __res; __asm__ __volatile ( "mov r0,%1 " __syscall(name) "mov %0,r0 " :"=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 " "mov r1,%2 " __syscall(name) "mov %0,r0 " :"=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 " "mov r1,%2 " "mov r2,%3 " __syscall(name) "mov %0,r0 " :"=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(32); .data : { *(.data) } . = ALIGN(32); .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 0 uart: mod=stdio
4. 运行
# skyeye -e syscall