想研究一下ARM体系,决定裸奔,到了swi这一部分的时候,每次一执行swi指令,6410总是进入指令预取终止异常中,困扰了好久,求大家不吝指点
代码如下
start.s
Mode_USR EQU 0x10
Mode_FIQ EQU 0x11
Mode_IRQ EQU 0x12
Mode_SVC EQU 0x13
Mode_ABT EQU 0x17
Mode_UND EQU 0x1B
Mode_SYS EQU 0x1F
UND_Stack_Size EQU 0x00000400
SVC_Stack_Size EQU 0x00001000
ABT_Stack_Size EQU 0x00000400
FIQ_Stack_Size EQU 0x00000400
IRQ_Stack_Size EQU 0x00001000
USR_Stack_Size EQU 0x00001000
Heap_Size EQU 0x00010000
I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled
F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled
Stack_Top EQU 0x52000000
WATCHDOG EQU 0x7E004000
IMPORT Main
; IMPORT swi_service_func
; IMPORT __use_no_semihosting_swi
EXPORT SWI_Handler
IMPORT C_SWI_Handler
PRESERVE8
AREA |startup|,CODE,READONLY
ENTRY
Vector_Table
LDR PC, Reset_Addr
LDR PC, Undefined_Addr
LDR PC, SWI_Addr
LDR PC, Prefetch_Addr
LDR PC, Abort_Addr
NOP ; Reserved vector must be remained
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr
Vector_Addr_Table
Reset_Addr DCD Reset_Handler
Undefined_Addr DCD Undefined_Handler
SWI_Addr DCD SWI_Handler
Prefetch_Addr DCD Prefetch_Handler
Abort_Addr DCD Abort_Handler
IRQ_Addr DCD IRQ_Handler
FIQ_Addr DCD FIQ_Handler
FUN_SWI DCD C_SWI_Handler
; 复位地址入口
Reset_Handler
; mrc p15,0,r0,c1,c0,0 ;使能VIC PORT功能
; orr r0,r0,#(1<<24)
; mcr p15,0,r0,c1,c0,0
LDR R0,=0x7E004000 ; WATCHDOG寄存器地址
MOV R1,#0x0
STR R1,[R0] ; 写入0,禁止WATCHDOG,否则CPU会不断重启
b clk_init ;时钟初始化好
LDR R0, =Stack_Top
MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
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
MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size
MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB SL, SP, #SVC_Stack_Size
MSR CPSR_c, #Mode_USR
MOV SP, R0
SUB SL, SP, #USR_Stack_Size
;使能IQR中断
;MRS R0,CPSR
; BIC R0,R0,#0x80
;MSR CPSR_c,R0
MSR CPSR_c, #Mode_USR ;intel user mode
STMFD sp!,{r0-r3, r12, lr} ;
bl Main ;uboot将CPU控制权交给main
LDMFD sp!,{r0-r3, r12, pc}^ ;main退出后,uboot重新获取CPU控制权
Undefined_Handler
B Undefined_Handler
T_bit EQU 0x20
SWI_Handler
STMFD sp!,{r0-r3, r12, lr} ; Store registers
MOV r1, sp ; Set pointer to parameters
MRS r0, spsr ; Get spsr
STMFD sp!,{r0} ; Store spsr onto stack
TST r0, #T_bit ; Occurred in Thumb state?
LDRNEH r0, [lr,#-2] ; Yes: Load halfword and...
BICNE r0, r0, #0xFF00 ; ...extract comment field
LDREQ r0, [lr,#-4] ; No: Load word and...
BICEQ r0, r0, #0xFF000000 ; ...extract comment field ; r0 now contains SWI number ; r1 now contains pointer to stacked registers
LDR PC, FUN_SWI ; Call main part of handler
LDMFD sp!,{r0} ; Get spsr from stack
MSR spsr_cf, r0 ; Restore spsr
LDMFD sp!,{r0-r3, r12, pc}^ ; Restore registers and return
Prefetch_Handler
B Prefetch_Handler
Abort_Handler
B Abort_Handler
IRQ_Handler
B IRQ_Handler
FIQ_Handler
B FIQ_Handler
;clock
ELFIN_WATCHDOG_BASE EQU 0x7e004000
ELFIN_CLOCK_POWER_BASE EQU 0x7e00f000
OTHERS_OFFSET EQU 0x900
APLL_LOCK_OFFSET EQU 0x00
MPLL_LOCK_OFFSET EQU 0x04
EPLL_LOCK_OFFSET EQU 0x08
CLK_DIV2_OFFSET EQU 0x28
CLK_DIV0_OFFSET EQU 0x20
Startup_PCLKdiv EQU 3
Startup_HCLKx2div EQU 1
Startup_HCLKdiv EQU 1
Startup_MPLLdiv EQU 1
Startup_APLLdiv EQU 1
CLK_DIV_VAL EQU ((Startup_PCLKdiv<<12)|(Startup_HCLKx2div<<9)|(Startup_HCLKdiv<<8)|(Startup_MPLLdiv<<4)|Startup_APLLdiv)
APLL_MDIV EQU 266
APLL_PDIV EQU 3
APLL_SDIV EQU 1
APLL_VAL EQU ((1<<31 | APLL_MDIV<<16 | APLL_PDIV<<8 | APLL_SDIV))
APLL_CON_OFFSET EQU 0x0c
MPLL_CON_OFFSET EQU 0x10
EPLL_CON0_OFFSET EQU 0x14
EPLL_CON1_OFFSET EQU 0x18
CLK_SRC_OFFSET EQU 0x1c
MPLL_MDIV EQU 266
MPLL_PDIV EQU 3
MPLL_SDIV EQU 1
MPLL_VAL EQU ((1<<31 | MPLL_MDIV<<16 | MPLL_PDIV<<8 | MPLL_SDIV))
clk_init
ldr r0, =ELFIN_CLOCK_POWER_BASE ;0x7e00f000
ldr r1, [r0, #OTHERS_OFFSET]
mov r2, #0x40
orr r1, r1, r2
str r1, [r0, #OTHERS_OFFSET]
nop
nop
nop
nop
nop
ldr r2, =0x80
orr r1, r1, r2
str r1, [r0, #OTHERS_OFFSET]
check_syncack
ldr r1, [r0, #OTHERS_OFFSET]
ldr r2, =0xf00
and r1, r1, r2
cmp r1, #0xf00
bne check_syncack
mov r1, #0xff00
orr r1, r1, #0xff
str r1, [r0, #APLL_LOCK_OFFSET]
str r1, [r0, #MPLL_LOCK_OFFSET]
str r1, [r0, #EPLL_LOCK_OFFSET]
ldr r1, [r0, #CLK_DIV2_OFFSET]
bic r1, r1, #0x70000
orr r1, r1, #0x30000
str r1, [r0, #CLK_DIV2_OFFSET]
ldr r1, [r0, #CLK_DIV0_OFFSET] ;Set Clock Divider
bic r1, r1, #0x30000
bic r1, r1, #0xff00
bic r1, r1, #0xff
ldr r2, =CLK_DIV_VAL
orr r1, r1, r2
str r1, [r0, #CLK_DIV0_OFFSET]
ldr r1, =APLL_VAL
str r1, [r0, #APLL_CON_OFFSET]
ldr r1, =MPLL_VAL
str r1, [r0, #MPLL_CON_OFFSET]
ldr r1, =0x80200203 ;FOUT of EPLL is 96MHz
str r1, [r0, #EPLL_CON0_OFFSET]
ldr r1, =0x0
str r1, [r0, #EPLL_CON1_OFFSET]
ldr r1, [r0, #CLK_SRC_OFFSET] ;APLL, MPLL, EPLL select to Fout
ldr r2, =0x2007
orr r1, r1, r2
str r1, [r0, #CLK_SRC_OFFSET]
;wait at least 200us to stablize all clock
mov r1, #0x10000
1
subs r1, r1, #1
bne %B1
;Synchronization for VIC port
ldr r1, [r0, #OTHERS_OFFSET]
orr r1, r1, #0x20
str r1, [r0, #OTHERS_OFFSET]
mov pc,lr
END
main.c
//#include <uboot.h>
#include <printf.h>
#define rGPMCON (*(volatile unsigned *)(0x7F008820))
#define rGPMDAT (*(volatile unsigned *)(0x7F008824))
#define rGPMPUD (*(volatile unsigned *)(0x7F008828))
struct four_results
{
int a;
int b;
int c;
int d;
};
__swi(0) int multiply_two(int, int);
__swi(1) int add_two(int, int);
__swi(2) int add_multiply_two(int, int, int, int);
__swi(3) __value_in_regs struct four_results many_operations(int, int, int, int);
void msDelay(int time)
{
volatile unsigned int i,j;
for(i = 0; i < 200000; i++)
for(j=0; j<time; j++);
}
void GPIO_Init(void)
{
rGPMCON = 0x11111;
rGPMPUD = 0x00;
rGPMDAT = 0X1F;
}
void LedTest(void)
{
volatile unsigned int i;
unsigned char count=0;
while (1)
{
for(i=0; i<4; i++)
{
rGPMDAT = ~(1<<i);
msDelay(10);
}
count++;
if(count>3)
return;
}
}
unsigned Install_Handler( unsigned routine, unsigned *vector )
{
unsigned vec, old_vec;
vec = (routine - (unsigned)vector - 8) >> 2;
if (vec & 0xff000000)
{
printf("Handler greater than 32MBytes from vector");
}
vec = 0xea000000 | vec; /**//* OR in 'branch always' code */
old_vec = *vector;
*vector = vec;
return (old_vec);
}
/***********************/
unsigned *swi_vec = (unsigned *)0x08;
extern void SWI_Handler(void);
void C_SWI_Handler( int swi_num, int *regs )
{
switch( swi_num )
{
case 0:
regs[0] = regs[0] * regs[1]; break;
case 1:
regs[0] = regs[0] + regs[1]; break;
case 2:
regs[0] = (regs[0] * regs[1]) + (regs[2] * regs[3]); break;
case 3:
{
int w, x, y, z;
w = regs[0];
x = regs[1];
y = regs[2];
z = regs[3];
regs[0] = w + x + y + z;
regs[1] = w - x - y - z;
regs[2] = w * x * y * z;
regs[3] =(w + x) * (y - z);
}
break;
}
}
void Main(void)
{
/* int result1, result2;
struct four_results res_3;
Install_Handler( (unsigned) SWI_Handler, swi_vec );
printf("result1 = multiply_two( 2, 4 ) = %d ", result1 = multiply_two( 2, 4 ));
printf("result2 = multiply_two( 3, 6 ) = %d ", result2 = multiply_two( 3, 6 ));
printf("add_two( result1, result2 ) = %d ", add_two( result1, result2 ));
printf("add_multiply_two( 2, 4, 3, 6 ) = %d ", add_multiply_two( 2, 4, 3, 6 ));
res_3 = many_operations( 12, 4, 3, 1 );
printf("res_3.a = %d ", res_3.a );
printf("res_3.b = %d ", res_3.b );
printf("res_3.c = %d ", res_3.c );
printf("res_3.d = %d ", res_3.d );
GPIO_Init();
printf("hello world\n");
LedTest();*/
__asm("swi 0");
}
开发环境本来是arm-linux-gcc的,后来linux下不好调试,转到了RVDS 2.2,**费了好大的劲,请大家指点…… |