zoukankan      html  css  js  c++  java
  • 第二季-专题12-通过按键玩中断

    专题2-通过按键玩中断

    第1课-中断处理流程深度剖析

     

    一. 中断概念

    CPU在工作的过程中,经常需要与外设进行交互,交互的方式包括“轮询方式”,“中断方式”。

    1. 轮询方式:

    CPU不断地查询设备的状态。该方式实现比较简单,但是CPU利用率很低,不适合多任务的系统。

    1. 中断方式

    CPU在告知硬件开始一项工作后,就去做别的事去了,当硬件完成了该项工作后,向CPU发送一个信号,告知CPU它已经完成了这项工作。这种方式就是我们所说的中断。

    1. 中断生命周期

    串口控制器——中断控制器——CPU核

    串口产生了事件,但是事件并不是直接送到CPU,而是送到中断处理器,进行判断是否适合CPU来处理,若是适合CPU的处理,就将事件传送给CPU。具体的流程可以变成如下的方式:

    中断信号产生(中断源)——中断信号过滤(中断控制器)——中断信号处理(CPU)

    二. 中断源

    在中断的生命周期中,中断源的作用是负责产生中断信号。(芯片手册浏览中断源)

    S3C2440支持60个中断源;S3C6410支持64中断源;S5PV210支持93个中断源。

     

    第一关卡:

    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对应GPF1、GPF4、GPF2、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、EINT1、EINT2、EINT4_7使能

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

       

        __asm__(

        /*开中断*/ 

        "mrs r0,cpsr "

        "bic r0, r0, #0x80 "

        "msr cpsr_c, r0 "           

        :

        :

      );

    }

    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 "                 

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

       

        /*不进行权限检查*/

        "mvn    r0, #0 "                  

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

       

       /*使能MMU*/

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

        "orr    r0, r0, #0x0001 "         

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

        :

        :

      );          

    }

    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

    当完成所有的程序编程后,我们要不一些过滤用的寄存器清零。

  • 相关阅读:
    微信小程序 登录
    小程序验证码输入框 连续输入 自动跳到下一个input
    微信小程序支付方法
    判断屏幕是否过大 或国小 进行 缩放达到自适应
    reactnative 启动
    第二届中国云计算应用论坛圆满闭幕 北达软
    什么是EA? 北达软
    第二届中国云计算应用论坛2012.01.08北京大学隆重揭幕 北达软
    北达软主办的企业架构与数据规划培训圆满结束 北达软
    北达软主办的“第九期中国EA沙龙”圆满举行 北达软
  • 原文地址:https://www.cnblogs.com/free-1122/p/11452179.html
Copyright © 2011-2022 走看看