打印

OK6410裸奔swi问题

[复制链接]
2036|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
nickyhzp|  楼主 | 2013-7-4 15:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
想研究一下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,**费了好大的劲,请大家指点……

相关帖子

沙发
nickyhzp|  楼主 | 2013-7-4 15:35 | 只看该作者
执行swi之后,总是进入Abort_Handler这个模式,uboot那里是以前在linux上用的,转移到RVDS 2.2后,代码没清理,一直保留了

使用特权

评论回复
板凳
幻影长矛手| | 2013-7-4 15:40 | 只看该作者
这么专业的问题问问飞凌的技术服务比较好。

使用特权

评论回复
地板
nickyhzp|  楼主 | 2013-7-5 08:31 | 只看该作者
幻影长矛手 发表于 2013-7-4 15:40
这么专业的问题问问飞凌的技术服务比较好。

飞凌迟迟不给回复,总感觉他们好像把板子卖出去后就事不关己似的

使用特权

评论回复
5
and| | 2013-7-5 10:09 | 只看该作者
LDR    PC, FUN_SWI          ; Call main part of handler   
这一句的LDR,是不是应该改用 BL或者BLX 什么的?

使用特权

评论回复
6
nickyhzp|  楼主 | 2013-7-8 09:49 | 只看该作者
and 发表于 2013-7-5 10:09
LDR    PC, FUN_SWI          ; Call main part of handler   
这一句的LDR,是不是应该改用 BL或者BLX 什 ...

bl跳转指令有空间限制,ldr也可以跳转,并且没有空间限制!现在的问题是执行 swi之后,根本就没进入swi中断向量中,直接进入的数据预取错误里面

使用特权

评论回复
7
群龙舞十方| | 2013-7-10 09:01 | 只看该作者
去飞凌技术论坛上问问,让他们给段可运行的代码先试试。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

29

帖子

0

粉丝