tiny6410異常處理例程分析

/*本文中部分程序省略,只分析異常處理部分*/

.globl _start

_start:


/* 0 地址 */
b reset                 /* 復位時,cpu跳到0地址 */
ldr pc, =undefined_instruction  /* cpu遇到不能識別的指令時 */
ldr pc, _vector_swi             /* 當執行swi指令時, 進入SVC模 式 */
@ldr pc, _prefetch_abort /* 預取中止異常 */
@ldr pc, _data_abort     /* 數據訪問異常 */
@ldr pc, _not_used       /* 沒用到 */
@ldr pc, _irq            /* 中斷異常 */
@ldr pc, _fiq            /* 快中斷異常 */


/*當發生中斷時,
       1.cpu進入IRQ模式
       2.r13,r14切換到IRQ模式下的R13_irq,R14_irq
       3.程序跳到0x18處執行,即執行ldr pc,_irq,程序跳轉
*/
    /*當cpu碰到一條自己不認識的指令時
       1.cpu進入Undefine模式
       2.r13,r14切換到R13_und,R14_und
       3.程序跳到0x04處執行,即執行ldr pc, =undefined_instruction
   
*/
/*當執行到swi ,*/
_vector_swi:
.word vector_swi

vector_swi:
/* 1. 保存現場 */
ldr sp, =0x56000000 /* sp,r13, r13_svc */
stmdb sp!, {r0-r12, lr}  /*把,r0-r12,lr都入棧*/


/* 2. 處理異常 */
mrs r0, cpsr
ldr r1, =swi_str
bl print_cpsr


/* 3. 恢復現場 */
ldmia sp!, {r0-r12, pc}^ /* ^表示把spsr恢復到cpsr ,r0-r12出棧,lr也出棧,把lr的值賦給pc,程序執行bl hello*/

swi_str:
.word 0x00697773  /* swi */

undefined_instruction:
/* 1. 保存現場 */
ldr sp, =0x55000000
stmdb sp!, {r0-r12, lr}


/* 2. 處理異常 */
mrs r0, cpsr
ldr r1, =und_str
bl print_cpsr


/* 3. 恢復現場 */
ldmia sp!, {r0-r12, pc}^  /* ^表示把spsr恢復到cpsr,出棧,把lr的值賦給pc,lr也出棧,把lr的值賦給pc,程序跳到swi_ret處繼續執行 */


und_str:
.word 0x00646e75  /* und */


usr_str:
.word 0x00727375  /* usr */


reset:
/* 硬件相關的設置 */
    /* Peri port setup */
    ldr r0, =0x70000000
    orr r0, r0, #0x13
    mcr p15,0,r0,c15,c2,4       @ 256M(0x70000000-0x7fffffff)
    
/* 關看門狗 */
/* 往WTCON(0x7E004000)寫0 */

ldr r0, =0x7E004000
mov r1, #0
str r1, [r0]

/* 設置棧 */
ldr sp, =8*1024


/* 設置時鐘 */
bl clock_init
bl ddr_init
bl init_uart


/* 把程序的代碼段、數據段複製到它的鏈接地址去 */
adr r0, _start   /* 獲得_start指令當前所在的地址 : 0*/
ldr r1, =_start  /* _start的鏈接地址 0x51000000 */

ldr r2, =bss_start      /* bss段的起始鏈接地址 */

sub r2, r2, r1

cmp r0,r1
beq clean_bss

bl copy2ddr      /*r0作爲函數copy2ddr的第一個參數,r1作爲第二個參數,r2作爲第三個參數*/
cmp r0, #0       /*返回結果存在r0中*/
bne halt

/* 清BSS */
/* 把BSS段對應的內存清零 */
clean_bss:
ldr r0, =bss_start
ldr r1, =bss_end
mov r3, #0
cmp r0, r1
ldreq pc, =on_ddr
clean_loop:
str r3, [r0], #4
cmp r0, r1
bne clean_loop
ldr pc, =on_ddr       /*代碼已經都複製到了ddr中,從片內內存跳到ddr中的on ddr處執行*/


on_ddr:


mrs r0, cpsr         /*mov register,r0*/
bic r0,r0,#0x1f
orr r0,r0,#0x10
msr cpsr,r0      /* 進入user mode */


ldr sp, =0x57000000


ldr r1, =usr_str   
bl print_cpsr

swi 0    /*
         * cpu進入svc模式
         * 把之前的cpsr保存到spsr_svc 
         * 切換到r13_svc, r14_svc
         * 把swi的下一條指令(即bl hello)的地址存到r14(lr)_svc
         * 跳到地址8
         * 以上幾條都是系統自己做的事
         */
bl hello
undef:
.word 0xff000000 /*
         * cpu進入Undefined模式
         * 把之前的cpsr保存到spsr_und 
         * 切換到r13_und, r14_und
         * 把下一條指令(即swi_ret)的地址存到r14(lr)_und
         * 跳到地址4
         */

swi_ret:
bl main



halt:

b halt

/*小結:

  在實際開發中,通常用未定義指令來做調試,開發者可以在程序中加入未定義指令,在未定義指令的異常處理部分通過串口輸出些字符,從而跟蹤程序的運行

*/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章