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

时间:2021-04-21 12:20:53

 

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

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

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

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

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

外部中断组2   EINT2  GPC0---GPC7

外部中断组3   EINT3  GPD0---GPD5

外部中断组4   EINT4  GPF0---GPF14

外部中断组5   EINT5  GPG0---GPG7

外部中断组6   EINT6  GPH0---GPH9

外部中断组7   EINT7  GPO0---GPO15

外部中断组8   EINT8  GPP0---GPP14

外部中断组9   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口为中断模式

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

EINTxCONx

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

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

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

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

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

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

2、VIC配置

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

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

VICxINTENCLEAR       1 DISABLE

VICxINTSELECT           0=IRQ         1=FIQ

VICxADDRESS              矢量地址寄存器清零

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

VICxVECTADDR[x]

D、使能中断

VICxINTENABLE   1=ENABLE0无效,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 .
   
  
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; 
}