第二季-專題12-經過按鍵玩中斷

專題2-經過按鍵玩中斷

第1課-中斷處理流程深度剖析

 

一. 中斷概念編程

CPU在工做的過程當中,常常須要與外設進行交互,交互的方式包括「輪詢方式」,「中斷方式」。oop

  1. 輪詢方式:

CPU不斷地查詢設備的狀態。該方式實現比較簡單,可是CPU利用率很低,不適合多任務的系統。字體

  1. 中斷方式

CPU在告知硬件開始一項工做後,就去作別的事去了,當硬件完成了該項工做後,向CPU發送一個信號,告知CPU它已經完成了這項工做。這種方式就是咱們所說的中斷。fetch

  1. 中斷生命週期

串口控制器——中斷控制器——CPU核優化

串口產生了事件,可是事件並非直接送到CPU,而是送到中斷處理器,進行判斷是否適合CPU來處理,如果適合CPU的處理,就將事件傳送給CPU。具體的流程能夠變成以下的方式:生命週期

中斷信號產生(中斷源)——中斷信號過濾(中斷控制器)——中斷信號處理(CPU)事件

二. 中斷源it

在中斷的生命週期中,中斷源的做用是負責產生中斷信號。(芯片手冊瀏覽中斷源)io

S3C2440支持60箇中斷源;S3C6410支持64中斷源;S5PV210支持93箇中斷源。asm

 

第一關卡:

SUBSRCPND:當外界來了中斷的時候,對應的只中斷就會被置1。裏面的每一個位對應一個只中斷。

SUBMASK:進行第一重過濾,每一位對應着一個只中斷,咱們把相應的位設置爲1,就是把該位屏蔽了。0表示容許經過。

第二關卡:

SRCPND:進行中斷的斷定。

MASK:中斷的過濾。

Mode:判斷中斷是優先的仍是普通的

Priority:判斷多箇中斷的優先級別

S3C2440支持60箇中斷源;

S3C6410支持64箇中斷源;

S5PV210支持93箇中斷源。(經過芯片手冊瀏覽中斷源)

  1. 中斷過濾

中斷信號產生(中斷源)——中斷信號過濾(中斷控制器)——中斷信號處理(CPU)

(1)非向量方式(2440)

(2)向量方式(6410/210)

中斷程序總入口——保存環境——判斷中斷源——調用對應該中斷源的中斷處理程序——回覆環境

當中斷產生時CPU直接調轉到用戶設置好的中斷處理程序處——保存環境——設備的中斷處理——恢復環境

 

以上紅色的字體表示咱們須要用軟件來實現的操做。

 

 

第2課-2440按鍵中斷編程

 

一.程序結構優化

將完整的程序劃分爲多個曉得程序。

二.中斷編程

l  Botton

#define GPFCON  (volatile unsigned long *)0x56000050

 

/*

 * K1,K2,K3,K4對應GPF一、GPF四、GPF二、GPF0

 */

#define GPF0_int     (0x2<<(0*2))

#define GPF1_int     (0x2<<(1*2))

#define GPF2_int     (0x2<<(2*2))

#define GPF4_int     (0x2<<(4*2))

 

#define GPF0_msk    (3<<(0*2))

#define GPF1_msk    (3<<(1*2))

#define GPF2_msk    (3<<(2*2))

#define GPF4_msk    (3<<(4*2))

 

void button_init()

{  

             *(GPFCON) &= ~(GPF0_msk | GPF1_msk | GPF2_msk | GPF4_msk);

         *(GPFCON) |= GPF0_int | GPF1_int | GPF2_int | GPF4_int;

}

 

l  Interrupt

/*interrupt registes*/

#define SRCPND              (volatile unsigned long *)0x4A000000

#define INTMOD              (volatile unsigned long *)0x4A000004

#define INTMSK              (volatile unsigned long *)0x4A000008

#define PRIORITY            (volatile unsigned long *)0x4A00000c

#define INTPND              (volatile unsigned long *)0x4A000010

#define INTOFFSET           (volatile unsigned long *)0x4A000014

#define SUBSRCPND           (volatile unsigned long *)0x4A000018

#define INTSUBMSK           (volatile unsigned long *)0x4A00001c

 

#define EINTMASK            (volatile unsigned long *)0x560000a4

#define EINTPEND            (volatile unsigned long *)0x560000a8

 

void init_irq()

{

 

    // 對於EINT4,須要在EINTMASK寄存器中使能它

    *(EINTMASK) &= ~(1<<4);

           

 

    // EINT0、EINT一、EINT二、EINT4_7使能

    *(INTMSK)   &= (~(1<<0)) & (~(1<<1)) & (~(1<<2)) & (~(1<<4));

   

    __asm__(

    /*開中斷*/ 

    "mrs r0,cpsr\n"

    "bic r0, r0, #0x80\n"

    "msr cpsr_c, r0\n"           

    :

    :

  );

}

 

void handle_int()

{

         /*讀取產生中斷的源*/

         unsigned long value = *(INTOFFSET);

        

         switch(value)

         {

                   case 0: //EINT0~K4

                            led_on();

                       break;

                  

                   case 1: //EINT1~K1

                            led_off();

                       break;

                  

                   case 2: //EINT2~K3

                       led_on();

                       break;

                  

                   case 4: //EINT4~K2

                       led_off();

                       break;

                  

                   default:

                       break;

         }

        

         /* 中斷清除 */

         if(value == 4)

         *(EINTPEND) = (1 << 4);

         *(SRCPND) = 1 << value;

         *(INTPND) = 1 << value;

}

 

l  Led

#define GPBCON (volatile unsigned long*)0x56000010

#define GPBDAT (volatile unsigned long*)0x56000014

 

#define     GPB5_out         (1<<(5*2))

#define     GPB6_out         (1<<(6*2))

#define     GPB7_out         (1<<(7*2))

#define     GPB8_out         (1<<(8*2))

 

void led_init()

{  

    *(GPBCON) = GPB5_out | GPB6_out | GPB7_out | GPB8_out;

}

 

void led_off()

{

    *(GPBDAT) = 0x7ff;

}

 

void led_on()

{

    *(GPBDAT) = 0x61f;

}

 

l  Main

int gboot_main()

{

#ifdef MMU_ON

    mmu_init();

#endif

    led_init();

    button_init();

    init_irq();

   

    while(1);

   

    return 0;   

}

 

 

l  MMU

/*

 * 用於段描述符的一些宏定義

 */

#define MMU_FULL_ACCESS     (3 << 10)   /* 訪問權限 */

#define MMU_DOMAIN          (0 << 5)    /* 屬於哪一個域 */

#define MMU_SPECIAL         (1 << 4)    /* 必須是1 */

#define MMU_CACHEABLE       (1 << 3)    /* cacheable */

#define MMU_BUFFERABLE      (1 << 2)    /* bufferable */

#define MMU_SECTION         (2 << 0)         /* 段描述符 */

#define MMU_SECDESC         (MMU_FULL_ACCESS | MMU_DOMAIN | MMU_SPECIAL | MMU_SECTION)

#define MMU_SECDESC_WB      (MMU_FULL_ACCESS | MMU_DOMAIN | MMU_SPECIAL | MMU_CACHEABLE | MMU_BUFFERABLE | MMU_SECTION)

 

 

void create_page_table(void)

{

    unsigned long *ttb = (unsigned long *)0x31000000;

    unsigned long vaddr, paddr;

   

    vaddr = 0x00000000;

    paddr = 0x30000000;

    *(ttb + (vaddr >> 20))= (paddr & 0xfff00000) | MMU_SECDESC_WB;

 

    vaddr = 0x56000000;

    paddr = 0x56000000;

    *(ttb + (vaddr >> 20)) = (paddr & 0xFFF00000) | MMU_SECDESC;

   

    vaddr = 0x4A000000;

    paddr = 0x4A000000;

    *(ttb + (vaddr >> 20)) = (paddr & 0xfff00000) | MMU_SECDESC;

 

    vaddr = 0x30000000;

    paddr = 0x30000000;

    while (vaddr < 0x34000000)

    {

        *(ttb + (vaddr >> 20)) = (paddr & 0xFFF00000) | MMU_SECDESC_WB;

        vaddr += 0x100000;

        paddr += 0x100000;

    }

}

 

void mmu_enable()

{

   __asm__(

   

    /*設置TTB*/

    "ldr    r0, =0x31000000\n"                 

    "mcr    p15, 0, r0, c2, c0, 0\n" 

   

    /*不進行權限檢查*/

    "mvn    r0, #0\n"                  

    "mcr    p15, 0, r0, c3, c0, 0\n"  

   

   /*使能MMU*/

    "mrc    p15, 0, r0, c1, c0, 0\n"   

    "orr    r0, r0, #0x0001\n"         

    "mcr    p15, 0, r0, c1, c0, 0\n"   

    :

    :

  );          

}

 

void mmu_init()

{

    create_page_table();

    mmu_enable();

}

 

 

l  Start.s

.text

.global _start

_start:

         b reset

         ldr pc, _undifined_instruction

         ldr pc, _software_interrupt

         ldr pc, _prefetch_abort

         ldr pc, _data_abort

         ldr pc, _not_used

         ldr pc, _irq

         ldr pc, _fiq

        

 

_undifined_instruction: .word undifined_instruction

_software_interrupt: .word software_interrupt

_prefetch_abort: .word prefetch_abort

_data_abort: .word data_abort

_not_used: .word not_used

_irq: .word irq

_fiq: .word reset

 

undifined_instruction:

         nop

 

software_interrupt:

         nop

        

prefetch_abort:

         nop

        

data_abort:

         nop

 

not_used:

         nop

 

irq:

         sub lr, lr, #4 

         stmfd sp!, {r0-r12, lr}     /* 保護現場 */ 

         bl handle_int              

         ldmfd sp!, {r0-r12, pc}^    /* 恢復現場,^表示把spsr恢復到cpsr */ 

        

fiq:  

         nop

 

reset:

         bl set_svc

         bl disable_watchdog

         bl disable_interrupt

         bl disable_mmu

         bl init_clock

         bl init_sdram

         bl copy_to_ram

         bl init_stack

         bl clean_bss

         ldr pc, =gboot_main

@     bl light_led

 

set_svc:

         mrs r0, cpsr

         bic r0, r0,#0x1f

         orr r0, r0,#0xd3

         msr cpsr, r0

         mov pc, lr

 

#define pWTCON 0x53000000

disable_watchdog:

         ldr r0, =pWTCON

         mov r1, #0x0

         str r1, [r0]

         mov pc, lr

 

disable_interrupt:

         mvn r1, #0x0

         ldr r0, =0x4a000008

         str r1, [r0]

         mov pc, lr

        

disable_mmu:

         mcr p15,0,r0,c7,c7,0

         mrc p15,0,r0,c1,c0,0

         bic r0, r0, #0x00000007

         mcr p15,0,r0,c1,c0,0

         mov pc, lr

 

#define CLKDIVN 0x4c000014

#define MPLLCON 0x4c000008

#define MPLL_405MHZ ((127<<12)|(2<<4)|(1<<0))

 

init_clock:

         ldr r0, =CLKDIVN

         mov r1, #0x5

         str r1, [r0]

        

         mcr p15,0,r0,c1,c0,0

         orr r0,r0,#0xc0000000

         mcr p15,0,r0,c1,c0,0

        

         ldr r0, =MPLLCON

         ldr r1, =MPLL_405MHZ

         str r1, [r0]

         mov pc, lr

        

#define mem_contrl 0x48000000

init_sdram:

         ldr r0, =mem_contrl

         add r3, r0, #4*13

         adrl r1, mem_data

 

0:

         ldr r2, [r1], #4

         str r2, [r0], #4

         cmp r0, r3

         bne 0b

         mov pc, lr

        

copy_to_ram:

         ldr r0, =0x0

         ldr r1, =0x30008000

         add r3, r0, #1024*4

 

copy_loop:

         ldr r2, [r0], #4

         str r2, [r1], #4

         cmp r0, r3

         bne copy_loop

         mov pc, lr

        

init_stack:

         msr cpsr_c, #0xd2

         ldr sp, =0x33000000         @此處實際設置的是r13_irq                           

         msr cpsr_c, #0xd3

         ldr sp, =0x34000000         @此處實際設置的是r13_svc

         mov pc, lr

 

clean_bss:

         ldr r0, =bss_start

         ldr r1, =bss_end

         cmp r0, r1

         moveq pc, lr

 

clean_loop:

         mov r2, #0

         str r2, [r0], #4

         cmp r0, r1

         bne clean_loop

         mov pc, lr

 

mem_data:

         .long 0x22000000

         .long 0x00000700

         .long 0x00000700

         .long 0x00000700

         .long 0x00000700

         .long 0x00000700

         .long 0x00000700

         .long 0x00018001

         .long 0x00018001

         .long 0x008c04f5

         .long 0x000000b1

         .long 0x00000030

         .long 0x00000030

 

#define GPBCON 0x56000010

#define GPBDAT 0x56000014

light_led:

         ldr r0, =GPBCON

         ldr r1,=0x15400

         str r1, [r0]

        

         ldr r0, =GPBDAT

         ldr r1,=0x6BF

         str r1, [r0]

         mov pc, lr

 

當完成全部的程序編程後,咱們要不一些過濾用的寄存器清零。

相關文章
相關標籤/搜索