s5pv210的外部中断

  中断,在学单片机的时候就没有学好,这次接触到210的中断体系,直接蒙圈了。。前天下午老师简单的讲了一下,他的每句话拆开都可以听得懂,联系起来就傻了,,而且懂了与会写差距还远着呢。当天下午所有人都是萎靡的状态(不懂,不会写极其郁闷),以为参照裸机开发指南可以边写会慢慢理解,结果越写越是打击。晚上没有回去,一直想体验下在教室通宵的感觉,除了蚊子比较多、床不好睡、网速依旧渣、睡得太累,好吧,好像并没有什么优点。

  虽然说是通宵了,但是几乎什么都没有学到,反而把自己搞得劳累。得不偿失!早上去领了免费包子,吃完回教室,大家在吐槽寝室那边“习俗”的事和程序的事,得到老师的承诺说下午会带着写程序,整个早上也没有怎么瞎折腾了,随便看看。

  前几天写好的makefile今天打开居然无法使用,编译到最后连接的时候有段错误!!(致命一击),重新把程序审视了一遍,什么都没有发现。请教老师也没有找出来,可能是ld程序出错了,后来重启了几次依旧如此,不想再纠结了,直接做中断了。

  6410和210的中断体系增加了向量中断的概念,相比2440,复杂程度乘法增加的。部分理解如下:

  四个向量中断:每个分别存放32个中断源,注意是中断”源“,不是单个中断,理解这点很重要,因为每个中断“源”里面包含了若干中断

          其中外部中断全部在第一个中断向量中,中断“源”是16,,,16中断“源”包含了EXT_INT[16] ~ [31]号中断,这里主要讨论16--19和24--28号的外部按键中断

          由于存在中断“源”和具体中断的区别,所以分别有两套寄存器控制着,这一点也是非常重要的,操作“源”就可以操作里面的中断,里面具体的哪一号中断还要          另外控制。呵呵,现在只能理解部分,以后要好好加深。

  中断处理函数和中断服务程序:(起这样两个名字的人有没有考虑过初学者的感受。。。)处理一个中断需要两级跳转,首先是跳转到中断处理函数(irq_handle和irq_handler          这两个函数真心不晓得是哪个),中断处理函数负责入栈、出栈等操作外,还负责跳转到中断服务程序(isr_key),在中断服务函数判断产生了具体哪个中断          (不是哪个中断“源”),然后执行相应的操作。

  关于注册地址:中断处理函数需要注册到异常向量表的中断异常地址上,实现中断异常的跳转。

         中断服务程序需要注册到相应的中断“源”地址上,

         因为两者都是通过注册地址来调用的,所以都不需要直接动手调用函数

 /******************************************************************************************************************************************************************************************************************/      具体程序如下: 

#include "stdio.h"

// 1.设置按键
#define GPH2CON     *((volatile unsigned int *)0xE0200C40)
#define GPH3CON      *((volatile unsigned int *)0xE0200C60)

//中断状态寄存器,可以通过该寄存器知道中断是否发生
#define VIC0IRQSTATUS     *((volatile unsigned int *)0xF2000000)
//中断选择
#define VIC0INTSELECT     *((volatile unsigned int *)0xF200000C)
//中断使能寄存器
#define VIC0INTENABLE      *((volatile unsigned int *)0xF2000010)
//禁止所有中断
#define VIC0INTENCLEAR    *((volatile unsigned int *)0xF2000014)

//存放中断处理函数的地址
//VICAddress:向量地址寄存器.当IRQ中断产生时,
//此寄存器保存当前激活的中断向量的地址.
#define VIC0ADDR       *((volatile unsigned int *)0xF2000F00)
//存放中断服务程序的地址
#define VIC0VECTADDR16   *((volatile unsigned int *)0xF2000140)
//#define VIC0_BASE (0xF2000000)
//#define VIC0EINT16ADDR    ( *((volatile unsigned long *)(VIC0_BASE + 0x100 + 64)) )

//设置中断为下降沿触发
#define EXT_INT_2_CON *((volatile unsigned int *)0xE0200E08)
#define EXT_INT_3_CON *((volatile unsigned int *)0xE0200E0C)
//不屏蔽中断
#define EXT_INT_2_MASK   *((volatile unsigned int *)0xE0200F08)
#define EXT_INT_3_MASK   *((volatile unsigned int *)0xE0200F0C)
//记录中断,有中断发生相应位就会置1,初始化时相应位清零
//可以用来检测具体哪一个中断是否发生
//VIC0IRQSTATUS是检测是否有中断产生(总体与个体的关系)
#define EXT_INT_2_PEND   *((volatile unsigned int *)0xE0200F48)
#define EXT_INT_3_PEND    *((volatile unsigned int *)0xE0200F4C)

//中断向量表
#define _Exception_Vector 0xD0037400
#define pExceptionRESET      ( *((volatile unsigned long *)(_Exception_Vector + 0x0)) )
#define pExceptionUNDEF     ( *((volatile unsigned long *)(_Exception_Vector + 0x4)) )
#define pExceptionSWI          ( *((volatile unsigned long *)(_Exception_Vector + 0x8)) )
#define pExceptionPABORT       ( *((volatile unsigned long *)(_Exception_Vector + 0xc)) )
#define pExceptionDABORT       ( *((volatile unsigned long *)(_Exception_Vector + 0x10)) )
#define pExceptionRESERVED       ( *((volatile unsigned long *)(_Exception_Vector + 0x14)) )
#define pExceptionIRQ          ( *((volatile unsigned long *)(_Exception_Vector + 0x18)) )
#define pExceptionFIQ       ( *((volatile unsigned long *)(_Exception_Vector + 0x1c)) )

void IRQ_handle(void); //用来现场保护和恢复,并且跳转到中断处理函数,不用调用

void enable_irq(void); //使能cpsr的总中断
void disable_irq(void); //关闭cpsr的总中断

void key_isq(void);
void delay(void);
/************************************************************************************************/
int init_interrupt_reg()
{

    //printf("here1\r\n");
  //禁止所有中断
  VIC0INTENCLEAR = 0xffffffff;

   //设置成普通中断模式
  VIC0INTSELECT = 0x0;

  //清除中断地址
  VIC0ADDR = 0x0;
  return 0;
}

int init_gpio(void)
{
//printf("here3\r\n");
//设置GPH2 0~3为中断方式
//GPH2CON &= 0xffff0000;
GPH2CON |= 0x0000ffff;
GPH3CON |= 0x0000ffff;

//设置外部中断为下降沿触发
EXT_INT_2_CON &= 0xffff8888; //保留位不清零
EXT_INT_2_CON |= 0x00002222;

EXT_INT_3_CON &= 0xffff8888; //保留位不清零
EXT_INT_3_CON |= 0x00002222;

//打开外部中断16--19
EXT_INT_2_MASK &= 0xfffffff0;
//打开外部中断24--27
EXT_INT_3_MASK &= 0xfffffff0;

//通过清除中断记录,清除外部中断,写1清零
EXT_INT_2_PEND = 0xff;
EXT_INT_3_PEND = 0xff;

//使能16号外部中断源

VIC0INTENABLE |= (0x1<<16);
return 0;
}

int set_isr_addr(void)
{
//printf("here2\r\n");

//注册中断服务子函数到相应的中断响应地址
//每个源都有一个特有的地址,16号中断源
VIC0VECTADDR16 = (unsigned long)key_isq;

//注册中断处理函数到中断异常
pExceptionIRQ = (unsigned long)IRQ_handle;

return 0;
}

//编写中断服务子函数
void key_isq(void)
{
//printf("here6\r\n");
delay();//消抖

unsigned int reg = 0;
unsigned int reg1 = 0;
reg = EXT_INT_2_PEND;//有中断产生时相应位就会有记录为1
reg1 = EXT_INT_3_PEND; // 25--28的中断记录

//判断16--19号外部中断产生 了哪一个
if((reg & 0x01)==0x01)
{
//记录位为1,有中断,为EINT16
printf("key1(EINT16) down\r\n");
}
else if(reg & (0x01<<1))
{
//记录位为1,有中断,为EINT17
printf("key2(EINT17) down\r\n");
}
else if(reg & (0x01<<2))
{
//记录位为1,有中断,为EINT18
printf("key3(EINT18) down\r\n");
}
else if(reg & (0x01<<3))

{
//记录位为1,有中断,为EINT19
printf("key4(EINT19) down\r\n");
}

//判断25--28号外部中断产生 了哪一个
if((reg1 & 0x01)==0x01)
{
//记录位为1,有中断,为EINT19
printf("key5(EINT24) down\r\n");
}
else if(reg1 & (0x01<<1))
{
//记录位为1,有中断,为EINT19
printf("key6(EINT25) down\r\n");
}
else if(reg1 & (0x01<<2))
{
//记录位为1,有中断,为EINT19
printf("key7(EINT26) down\r\n");
}
else if(reg1 & (0x01<<3))
{
//记录位为1,有中断,为EINT19
printf("key8(EINT27) down\r\n");
}

VIC0ADDR =0x0; //随便写入一个值表示中断服务子函数结束

EXT_INT_2_PEND = 0xf; //通过写1去清零16--19相应的记录位
EXT_INT_3_PEND = 0xf; //通过写1去清零25--28相应的记录位

}

typedef void funp(void);//定义了funp的函数类型,记得加;号
//中断处理函数
void irq_handler(void)
{
//printf("here5\r\n");

unsigned int reg = 0;

void (*isr)(void);

reg = VIC0IRQSTATUS;

if(reg !=0)
{
//有中断产生
isr = (funp*)VIC0ADDR;//类型强转,读取中断向量的地址执行中断服务子程序
}
(*isr)();
}
/**************************************************************************************/
void init_exint(void)
{
disable_irq();
init_interrupt_reg();

set_isr_addr();

//irq_handler(void);由IRQ_handle()函数调用到

//中断处理函数和中断服务程序不用注册,
//key_isq(void);由于已经安装了地址,有中断产生时自然会调用

init_gpio();

enable_irq();
}

、*********************************************************************************************************************************************************************/

  吐槽下博客园的程序文本格式。。。

  虽然说程序写完了,准确的说是抄完了,现在让我一个写还是没有把握写出来,毕竟那么多寄存器不是那么好找的,更别说用了。在老师程序的基础上,完成了全部八个外部按键中断,

  还有一点是要注意的是,由于裸机是没有标准库的,所以要想很好的调试程序,在裸机上面移植了网上的printf函数,只要把自己写的程序最后组装成一个函数,然后直接把组装好的函数扔进printf的主函数即可。

  记得要把源代码赋值到printf的目录,直接加到项目工程是不能编译的,,,加进去之后还有把目录里面的加载到工程里面,否则修改不到。。。(这种错误,智商捉急啊。。)

时间: 2024-10-05 12:54:15

s5pv210的外部中断的相关文章

嵌入式外部中断控制编程方法论—比較CC2541(51核)和S5PV210(ARM核)

这是一篇阐述怎样对嵌入式SOC外部中断进行控制编程的方法论文章.希望读者理解本篇文章后.能够具备对市场上全部已经面世和将来面世的嵌入式芯片的外部中断进行控制编程的能力. 笔者原创的技术分享一直都恪守下面原则: 从需求的角度去理解嵌入式各种软件和硬件模块的作用和组成.并从芯片系统设计的角度去阐述怎样进行控制编程. 前者对于理解复杂的系统(如linux的各个子系统)是非常有效的:后者所讲的是代表一个芯片设计project师的视觉,芯片模块由他负责设计,他对于该模块的控制编程自然是最有发言权的. 笔者

《零死角玩转STM32》-17-EXTI外部中断/事件控制器

/* * 本文中的相关图片来自火哥的教程,只作为随笔记录,无侵权之意 * 21:25:46, 2017-04-08 */ EXTI:外部中断/事件控制器.STM32F429共有23根,其中EXTI0~EXTI15,分别对应GPIO中的PX0 ~ PX15,另外7根线有如下用途: (中间省略了EXTI1 ~ EXTI15) EXTI功能框图如下所示: 按照图中的序号标识,可以清晰的看出外部GPIO引脚上的电平变化是如何传递到内核,即GPIO -> EXTI -> NVIC,并触发相应的中断/事件

掌握所有IO口的外部中断

外部中断配置流程 1.初始化IO口工作在普通IO.上拉输入状态. 2.首先开IO口组中断(P0IE=1.P1IE=1.P2IE=1): 3.开组内对应的具体某IO口中断(P0IEM.P1IEM.P2IEM该寄存器里面的对应位对应相应的IO口): 4.上升沿还是下降沿触发(PICTL寄存器): 5.开CPU总中断EA=1; #include <cc2530.h> void main() { //步骤1 P0SEL &=0xDF;//P05口表示为普通IO口 P0DIR &=0xD

STM32外部中断

0.STM32F103上测试 #include <stm32f10x.h> void GPIO_Config(void); void NVIC_Config(void); void EXTI_Config(void); int main(void) { GPIO_Config(); NVIC_Config(); EXTI_Config(); while(1): } void GPIO_Config(void) { /*定义一个GPIO_InitTypeDef类型的结构体,本类型在stm32f1

[ZYNQ-7]PS处理PL外部中断的简单实例的剖析 (参考米联miz702n)

Zynq的ARM通过GIC中断控制器来接收核仲裁所有的中断.由于中断向量表只有4Bytes大小,仅仅正好存放一条跳转语句,因此当产生一个外部中断时,中断处理的大致过程:PC内容保存到LR_IRQ用于中断返回,拷贝CPSR到SPSR_IRQ以反应中断模式,屏蔽其他中断,紧接着将PC设置为中断向量表入口.CPU完成现场保护.确认中断源,并调用相关的中断处理函数.恢复CPSR,恢复CPU现场,中断返回. main.c of simplified Interrupt instance (from miz

STM32F4——NVIC中断优先级及外部中断

NVIC中断优先级 一.简介: CM4内核可以支持256个中断,包括16个内核中断和240个外部中断,256级的可编程中断设置.对于STM32F4没有用到CM4内核的所有东西,只是用到了一部分,对于STM32F40和41系列共有92个中断,其中有10个内核中断和82个可屏蔽中断,常用的为82个可屏蔽中断. 二.相关寄存器: ISER[8]-中断使能寄存器组,用来使能中断,每一位控制一个中断,由于上面已经说明了控制82个可屏蔽的中断,因此利用ISER[0~2]这三个32位寄存器就够了.一下的几个寄

LPC1768外部中断与GPIO中断

LPC1768的外部中断严格来说只有四个,分别是EINT0,EINT1,EINT2,EINT3,技术手册上有如下说明 控制这四个外部中断靠以下寄存器 这三个寄存器的0 1 2 3位分别代表中断的0 1 2 3,EXTINT寄存器表示中断是否发生,在发生中断的时候该寄存器会置位,可以通过写1清零,EXTMODE寄存器表示触发模式,有电平触发和变化沿触发两种,EXTPOLAR与EXTMODE,在电平触发模式下,决定高电平还是低电平触发,在变化沿触发的情况下决定上升沿还是下降沿触发 这三个中断分别相关

CC2540开发板学习笔记(三)&mdash;&mdash;外部中断

一.实验内容 通过外部中断方式依次按下按键S1控制LED1的亮灭 二.实验过程 1.电路原理图同上 2.中断的概念 比如说我们在执行main函数时,突然来了个指令.优先级比现在执行的main还高,那我们便选择跳过去执行优先级高的,完了之后再执行main函数,中断就类似这样一个概念,使用中断可以减少CPU的无效浪费,降低能耗. 3.寄存器调度 (1)LED1的初始化..同前两节,就是SEL,DIR,INP三个,还有附初始状态. (2)外部中断初始化(S1的外部中断初始化) 按键S1外部中断初始化方

中断之外部中断

. ARM Cortex M3共有256个中断. STM32F103CB共有43个外部中断和16个内部中断. 具有相同数值编号的IO口被分配为同一组,共用一条中断请求线,如下图: 所以共有15条中断线,另外 ●EXTI线16连接到PVD输出●EXTI线17连接到RTC闹钟事件●EXTI线18连接到USB唤醒事件 寄存器:1.外部中断配置寄存器    AFIO_EXTxCR1------->用于选择输入中断源  Pin 0..3 AFIO_EXTxCR2------->用于选择输入中断源  Pi