转:S3C6410外部中断裸机学习笔记(VIC模式)

一、           关于外部中断的一些基础知识

 

S3C6410共有127个外部中断,其外接I/O引脚及分组如下:

 

外部中断组    EINT0   GPN0---GPN15  GPL8---GPL14   GPM0---GPM4

外部中断组    EINT1   GPA0---GPA7    GPB0---GPB6

外部中断组    EINT2   GPC0---GPC7

外部中断组    EINT3   GPD0---GPD5

外部中断组    EINT4   GPF0---GPF14

外部中断组    EINT5   GPG0---GPG7

外部中断组    EINT6   GPH0---GPH9

外部中断组    EINT7   GPO0---GPO15

外部中断组    EINT8   GPP0---GPP14

外部中断组    EINT9   GPQ0---GPQ9

 

以上127个引脚每个引脚都可以产生一个外部中断

 

2127个外部中断在VIC里的中断号

       NO.                中断源                          说明                                         GROUP

       0            INT_EINT0        外部中断组0引脚号0-3                     VIC0

       1            INT_EINT1        外部中断组0引脚号4-11                   VIC0

       32          INT_EINT2        外部中断组0引脚号12-19                 VIC1

       33          INT_EINT3        外部中断组0引脚号20-27                 VIC1

       53          INT_EINT4        外部中断组1-9                                     VIC1

 

以上属于外部中断组027个中断占用了VIC里的4个中断号,外部中断组1-9只占用了1个中断号

 

二、           外部中断响应流程

 

外部中断从外设到CPU的具体流程如下: 

外设 àGPIO à VIC à ARM1117

 

那么我们编写关于中断的程序流程也应该是这个过程:

 

配置外设 à 配置GPIO à 配置VIC à 配置ARM协处理器等

 

三、           配置过程

 

1、配置GPIO

GPxCON:配置相应的I/O口为中断模式

 

图片

 

EINTxCONx

图片

 

外部中断屏蔽 EINTxMASK          屏蔽某个外部中断, 0=发生中断   1=不发生中断  默认是

全屏蔽的。图片

外部中断悬挂寄存器EINTxPEND       中断标志位

图片

过滤控制寄存器 EINTxFLTCONx       设置滤波方式,         延迟滤波 或数字滤波

 

VIC配置

A、在协处理器中开启VIC,在协处理器里设置VE位。

B、 关中断,清矢量地址寄存器并配置中断类型

VICxINTENCLEAR        1 DISABLE

VICxINTSELECT            0=IRQ          1=FIQ

VICxADDRESS               矢量地址寄存器清零

C、 配置中断函数入口地址

VICxVECTADDR[x]

D、使能中断

VICxINTENABLE    1=ENABLE 0无效,DISABLE只能通过VICxINTENCLEAR1更改

   E、总中断使能                 CPSR Bit 8I1 ENABLE

 

完整的代码如下,其于RVDS2.2环境,AXD调试

startup.s

-----------------------------------------------------------------------------------------------------------------------
 INCLUDE s3c6410.inc
;----------------------------------------------------------------
 IMPORT main   ;C Entry Point for Steppingstone Loader
;----------------------------------------------------------------
 
 EXPORT ENTRY
 AREA Init,CODE,READONLY
;----------------------------------------------------------------

ENTRY
  b ResetHandler
  b .
  b .
  b .
  b .
  b .
  b .
  b .
   
  
ResetHandler
;----------------------------------------
; Disable WatchDog Timer
;----------------------------------------  
  ldr r0,=WTCON
  ldr r1,=0x00
  str r1,[r0]
  
;----------------------------------------
; Enable VIC 
;---------------------------------------- 
  mrc p15,0,r0,c1,c0,0
  orr r0,r0,#(1<<24) ;Enable VE bit
  mcr p15,0,r0,c1,c0,0 
    
;SetBit C1 Register VE位(BIT24)则中断向量地址由VIC决定
;ClrBit C1 Register VE位(BIT24)则中断向量地址是固定地址

;  总中断ENABLE

  mrs r0,cpsr
  bic r0,r0,#0x80
  msr cpsr_c,r0

;DEBUG  
  mrs r0,cpsr

  b main

  END  -----------------------------------------------------------------------------------------------------------------------
main.c

void main(void)
{

 Led_Init(); 
 
 INTC_Init();
 
 Key_IO_Init();
  
 Key_Int_Config();

 while(1);
}

 -----------------------------------------------------------------------------------------------------------------------
led.c

#include "s3c6410_addr.h"

void Led_Init(void)
{
 // GPK4 5 6 7 接LED,I/O设置为输出
 rGPKCON0 = (rGPKCON0 & (~(0xFFFF << 16))) | (0x1111 << 16);
 
 // GPK4 5 6 7 设置为上拉
 rGPKPUD = (rGPKPUD & (~(0xFF << 8))) | (0xAA << 8);
 
 // 初始化时LED OFF
 rGPKDAT |= 0x00F0;
}

-----------------------------------------------------------------------------------------------------------------------
key.c

#include "s3c6410_addr.h"
#include "interrupt.h"

void Key_ISR(void) __irq;

void Key_IO_Init(void)
{
 // GPN0 1 2 3 接按键K1 K2 K3 K4 配置按键为中断E_INT 
 rGPNCON = rGPNCON & 0xFFFFFFAA; 
 rGPNDAT = rGPNDAT | 0x000F;
 
}


// KEY Interrupt configuration
void Key_Int_Config(void)
{
 // Configurate the Key I/O for Interrupt Mode 0x10
 rGPNCON = rGPNCON & 0xFFFFFF00 | 0x00AA; 
 
 // Configurate the EINT0 EINT1 EINT2 EINT3 Trigger of Flowing Type 01x
 rEINT0CON0 = (rEINT0CON0 & 0xFFFFFF22);
 
 // Disable Interrupt MASK EINT0 ENIT1 EINT2 EINT3
 rEINT0MASK &= 0xFFFFFFF0;
 
 //Clear EINT Flag
 rEINT0PEND |= 0x0000000F;
 
 // Select External Interrupt Mode IRQ
 rVIC0INTSELECT = 0x0;
 rVIC1INTSELECT = 0x0;
 
 // Set the Entry Address of External Interrupt Group 0 ISR
 VIC0VECTADDR[0] = (unsigned int)Key_ISR;
 
 // Enable the External Interrupt Group 0
 rVIC0INTENABLE |= 0x01; 
  
}


void Key_ISR(void) __irq
{
 int temp;
 // KEY 1
 if(rEINT0PEND & 0x01)
 {
  temp = ~(rGPKDAT & (0x01 << 4));
  rGPKDAT = rGPKDAT & ~(0x01 << 4) | temp;
   
  // Clear Interrupt Pend
  rEINT0PEND |= 0x01; 
 }
 // KEY2
 if(rEINT0PEND & 0x02)
 {
  temp = ~(rGPKDAT & (0x01 << 5));
  rGPKDAT = rGPKDAT & ~(0x01 << 5) | temp;
  
  // Clear Interrupt Pend
  rEINT0PEND |= 0x02;  
 }
 // KEY3
 if(rEINT0PEND & 0x04)
 {
  temp = ~(rGPKDAT & (0x01 << 6));
  rGPKDAT = rGPKDAT & ~(0x01 << 6) | temp;
  
  // Clear Interrupt Pend
  rEINT0PEND |= 0x04;  
 }
 // KEY4
 if(rEINT0PEND & 0x08)
 {
  temp = ~(rGPKDAT & (0x01 << 7));
  rGPKDAT = rGPKDAT & ~(0x01 << 7) | temp;
  
  // Clear Interrupt Pend
  rEINT0PEND |= 0x08;  
 }
 rVIC0ADDR = 0x00000000;  
}

-----------------------------------------------------------------------------------------------------------------------

interrupt.c

#include "s3c6410_addr.h"
#include "interrupt.h"


void INTC_Init(void)
{
 // Disable All Interrupt
 rVIC0INTENCLEAR = 0xFFFFFFFF;
 rVIC1INTENCLEAR = 0xFFFFFFFF; 
 
 // Clear VECT Address
 rVIC0ADDR = 0x0;
 rVIC1ADDR = 0x0; 
}

原文:http://user.qzone.qq.com/39458645/infocenter#!app=2&via=QZ.HashRefresh&pos=1331913255

posted @ 2013-03-15 11:14  heyb7  阅读(42)  评论(0)    收藏  举报