专题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\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

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

转载于:https://www.cnblogs.com/free-1122/p/11452179.html

第二季-专题12-通过按键玩中断相关推荐

  1. 专题2-通过按键玩中断\第1课-中断处理流程深度剖析-lesson1

    中断概念 1.中断生命周期 串口先产生一个事件,该事件传送到中断控制器里面,中断控制器会进行相应过滤,能通过过滤,那么就交给CPU去处理. 2.中断源 2440芯片手册 6410芯片手册 3.中断过滤 ...

  2. 越狱第一和第二季(免费在线视频)

    在网上发现的资源,经过测试,是可以看的,而且是SWF文件,所以看起来还算是比较舒服的(对网速不太快的人来讲).最近听说这个电影是相当的流行的啊!所以,大家都赶紧来看哦~ 第一季第1集:[url]htt ...

  3. Python可以这样学(第二季:tkinter案例精选)-董付国-专题视频课程

    Python可以这样学(第二季:tkinter案例精选)-3592人已学习 课程介绍         董付国老师系列教材<Python程序设计基础>(ISBN:9787302410584) ...

  4. 火星人敏捷开发1001问(第二季)-陈勇-专题视频课程

    火星人敏捷开发1001问(第二季)-17497人已学习 课程介绍         此课程为敏捷开发的课程,聚焦于敏捷开发中似是而非的各种问题.每个问题都会有分析与解决的环节,从而令学员不但得到可行的答 ...

  5. 跟着王进老师学开发C#篇第二季:面向对象-王进-专题视频课程

    跟着王进老师学开发C#篇第二季:面向对象-9471人已学习 课程介绍         面向对象的思想在现在程序开发中非常重要,很多刚入门的程序员没有真正理解面向对象的思想而被挡在在软件开发的门外,本次 ...

  6. 血腥大地-第二季(资源破解与管理)-张立铜-专题视频课程

    血腥大地-第二季(资源破解与管理)-2426人已学习 课程介绍         课程继承<血腥大地>游戏内容 1.主要完成游戏资源的获取,从原血腥大地游戏中获取(不涉及任何商业利益,不能将 ...

  7. Android自动化测试第二季(提高篇)-金阳光-专题视频课程

    Android自动化测试第二季(提高篇)-17804人已学习 课程介绍         [金阳光测试]是由金阳光等创办的国内个人免费培训测试.欢迎喜欢测试的朋友来观看学习,提意见. 课程收益      ...

  8. 新星计划第二季|量身打造、全新互动,快来报名

    活动官网: https://marketing.csdn.net/p/1d9bedb178313a415dfd4b5839766206 <新星计划>第一季,我们汇集了各大领域的优秀新人,在 ...

  9. ARM之S5pv210的按键和中断部分

    一.按键和中断分析 要使用中断,首先要做好两个部分的工作:CPU中断的初始化和相应器件的中断的初始化. CPU中断初始化:就是要设置号CPU有关中断的东西. 相关器件的中断初始化:例如按键,就要设置好 ...

  10. 嵌入式-ARM-学习总结(7):按键与中断

    嵌入式-ARM-学习总结(7):按键与中断 一.按键 1.S5PV210的按键 2.按键的2中相应方法:轮询方式和中断方式 3.按键对应的GPIO模式设置 4.轮询方式处理按键的程序流程 5.代码编写 ...

最新文章

  1. “男医生,女护士?”消除偏见,Google有大招
  2. Jupyter Notebook各种使用方法记录
  3. 2021年,自动驾驶将我们带到何处去?
  4. 成功之路该如何走--工作半年的思考
  5. TCP/IP详解--第一章
  6. ASP.NET MVC分页实现
  7. spring+springMvc+struts的SSH框架整合
  8. E-triples II_2019牛客暑期多校训练营(第四场)
  9. 如何判断脸型测试软件,【图】脸型判断 教你非常准确的测试方法_脸型_伊秀美容网|yxlady.com...
  10. MySQL安装配置详解(5.5 For Windows)
  11. cxf 服务器响应超时时间,CXF日志响应时间
  12. Java Swing开发 Label标签 界面中文出现乱码解决方案
  13. 登录双token方案
  14. 【PTA~L1-080 乘法口诀数列】
  15. Win10台式电脑网线正常但连不上网。
  16. 获取IFeatureWorkspace所有要素类、表
  17. 超全!Tkinter 使用教程!4000字!
  18. NTP时间同步服务器客户端、服务端的安装以及配置文件的配置
  19. 使用Python Openssl库解析X509证书信息
  20. 学习linux压缩命令压缩文档

热门文章

  1. 二级分类php代码,php smarty 二级分类代码和模版循环例子
  2. lisp取消选集选中状态_为什么对话框创建后是隐藏状态的
  3. 实习成长之路:面试官说的MySQL高可用-------主备一致到底是什么?
  4. Picasso,Glide,Fresco对比分析
  5. springcloud 微服务鉴权_推荐 1w+ 星标的 SpringCloud 微服务项目,开发脚手架
  6. html盒子中盒子排列,解析CSS的box model盒模型及其内的子元素布局控制
  7. python---python实现快速排序
  8. python调用matlab函数_python调用matlab的m自定义函数方法
  9. hadoop合并日志_Hadoop深入学习:HDFS主要流程——SNN合并fsimage和编辑日志
  10. 帆软9.0动态列之解决动态列的分组统计问题