当前位置:首页 > 嵌入式培训 > 嵌入式学习 > 讲师博文 > FS4412 开发板 中断分析

FS4412 开发板 中断分析 时间:2018-09-28      来源:未知

一:框图

       这里通过按下按键,触发中断的例子,分析FS4412开发板 中断的原理机制。

按下k2会触发中断信号 --->  GPIO管脚控制器  ---> 中断使能 -->  分发使能 --> 接口使能  -->  优先级门槛 ---> ARM core。 

      FS4412开发板使用的CPU是exynos4412 ,它的中断相对复杂,关键的是如何使得中断信号如何通过重重关口,后到达 cpu核心。 这里有五个关口分别对应 GPIO管脚控制器(寄存器是EXT_INT41_MASK), 中断使能(寄存器是ICDISER), 分发使能(ICDDCR),接口使能,

优先级门槛(ICCICR). 要在程序中分别打开这五个关口对应的寄存器位,过五关斩六将,才能把信号送入ARM 核心。

 

二. 代码分析

1. Main.c  (c语言主程序)

/*

  功能:   按键K2按下后能触发中断输出字符

 

 作业:  实现K3 按下后能触发中断输出字符

*/

 

//----------------uart

#define  GPA1CON    (*(volatile unsigned int *)0x11400020)

#define  ULCON2     (*(volatile unsigned int *)0x13820000) 

#define  UCON2      (*(volatile unsigned int *)0x13820004) 

#define  UBRp2    (*(volatile unsigned int *)0x13820028) 

#define  UFRACVAL2  (*(volatile unsigned int *)0x1382002C) 

#define  UTXH2      (*(volatile unsigned int *)0x13820020) 

#define  UTRSTAT2   (*(volatile unsigned int *)0x13820010) 

 

 

//---------------interrupt

#define  GPX1CON        (*(volatile unsigned int *)0x11000c20)

#define  EXT_INT41CON   (*(volatile  int *)0x11000E04)

#define  EXT_INT41_MASK (*(volatile  int *)0x11000F04)

#define ICDISER1_CPU0  (*(volatile  int *)0x10490104)

#define ICDIPTR14_CPU0 (*(volatile  int *)0x10490838)

#define ICDDCR (*(volatile  int *)0x10490000)

#define ICCICR_CPU0  (*(volatile  int *)0x10480000)

#define ICCPMR_CPU0  (*(volatile  int *)0x10480004)

#define EXT_INT41_PEND (*(volatile  int *)0x11000f44)

#define ICCIAR_CPU0  (*(volatile  int *)0x1048000C)

#define ICCEOIR_CPU0 (*(volatile  int *)0x10480010)

#define ICDICPR1_CPU0 (*(volatile  int *)0x10490284)

 

void interrupt_init(void)

{

//-----外: 配置管脚的工作模式

GPX1CON = (GPX1CON & ~(0xF<<4))|(0xF<<4);  //配置 GPX1_1为中断模式

 

EXT_INT41CON = (EXT_INT41CON & ~(0x7<<4))|(0x2<<4);  //设置GPX1_1的触发方式为 下降沿触发

EXT_INT41_MASK = EXT_INT41_MASK & (~0x02); //GPX1_1 中断使能

 

 

 

//-----内: 功能块设置

ICDISER1_CPU0 = ICDISER1_CPU0 | (1<<25); //EINT9 (GPX1_1)  GIC中断使能

ICDIPTR14_CPU0 = 0x01010101;   //参考例子背景,用默认设置 

ICDDCR = ICDDCR|1; //GIC 分发总使能

ICCICR_CPU0 = 1;  // CPU0  中断使能

ICCPMR_CPU0 = 0XFF;   //设置CPU0的优先级门槛为低

 

//KEY3

//外

GPX1CON = (GPX1CON & ~(0xF<<8))|(0xF<<8);  //配置 GPX1_2为中断模式

EXT_INT41CON = (EXT_INT41CON & ~(0x7<<8))|(0x2<<8);  //设置GPX1_2的触发方式未 下降沿触发

EXT_INT41_MASK = EXT_INT41_MASK & (~0x04); //GPX1_2 中断使能

 

//内

ICDISER1_CPU0 = ICDISER1_CPU0 | (1<<26); //EINT9 (GPX1_2)  GIC中断使能

}

 

 

 

void uart_init(void)

{

  //-----外: 配置管脚的工作模式

  GPA1CON = 0x22;  //配置GPA1_1 GPA10 为uart串口模式

  

  //-----内: 功能块设置

  //1.  uart 通讯协议格式的设置

  ULCON2 = 0x03;  //设置协议格式(  无校验位  1个停止位 8个数据位)

  UCON2 = 0x05;   //设置串口发送接收模式为polling模式

  

  /*2.  设置uart 的速度为115200

  p_VAL = (100000000/(115200 *16)) - 1 = 53.253

  UBRpn =  53

  UFRACVALn/16 = 0.253

  Therefore, UFRACVALn = 4

  */

  UBRp2 = 53;

  UFRACVAL2 = 4;

    

}

 

 

 

void putc(char c)

{

   while(1)

   {

      if(UTRSTAT2&0x02)  //检测发送是否为空

      {

         break;

      }

   }

   

   UTXH2 = c;  //发送字符

}

 

 

void do_irq(void )

{

 

  int irq_num;

 

   irq_num = ICCIAR_CPU0&0x3ff; ////中断ID号

 

   switch(irq_num)

   {

   case 57:

       putc('k');

       putc('2');

      EXT_INT41_PEND = EXT_INT41_PEND|(1<<1);  //清GPX1_1中断标志    

      ICDICPR1_CPU0 = ICDICPR1_CPU0|(1<<25);    //清GIC GPX1_1中断标志

       break;

case 58:

       putc('k');

       putc('3');

      EXT_INT41_PEND = EXT_INT41_PEND|(1<<2);  //清GPX1_2中断标志    

      ICDICPR1_CPU0 = ICDICPR1_CPU0|(1<<26);    //清GIC GPX1_2中断标志

       break;

   default:

       putc('e');

       break;

   }

    ICCEOIR_CPU0 = (ICCEOIR_CPU0&0x3FF)|irq_num;    //结束中断 将处理完成的中断ID号写入该寄存器,则表示相应的中断处理完成

}

 

int main(void) 

{

    uart_init();

    interrupt_init();

 

while(1)

{

      putc('f');

 delay1s();

}

return 0;

}

 

2. Start.s    汇编程序(程序运行的第一条指令在该位置)

    .global  delay1s 

    .text     

    .global _start

_start:

b reset                          @0x00

ldr pc,_undefined_instruction    @0x04

ldr pc,_software_interrupt     

ldr pc,_prefetch_abort

ldr pc,_data_abort

ldr pc,_not_used

ldr pc,_irq                      @0x18

ldr pc,_fiq

 

_undefined_instruction: .word  _undefined_instruction

_software_interrupt: .word  _software_interrupt

_prefetch_abort: .word  _prefetch_abort

_data_abort: .word  _data_abort

_not_used: .word  _not_used

_irq: .word  irq_handler 

_fiq: .word  _fiq

 

 

irq_handler:

    sub  lr,lr,#4

    stmfd  sp!,{r0-r12,lr} @进栈保存现场 

    bl   do_irq

irq_handler_end:

    ldmfd  sp!,{r0-r12,pc}^ @出栈恢复现场

 

 

 

reset: 

ldr r0,=0x40008000      @设置异常向量表的启始地址为 0x40008000

mcr p15,0,r0,c12,c0,0 @ Vector Base Address Register

 

init_stack:

ldr r0,stacktop         /*get stack top pointer*/

 

/********svc mode stack********/

mov sp,r0

sub r0,#128*4          /*512 byte  for irq mode of stack*/

/****irq mode stack**/

msr cpsr,#0xd2

mov sp,r0

sub r0,#128*4          /*512 byte  for irq mode of stack*/

/***fiq mode stack***/

msr  cpsr,#0xd1

mov sp,r0

sub r0,#0

/***abort mode stack***/

msr cpsr,#0xd7

mov sp,r0

sub r0,#0

/***undefine mode stack***/

msr cpsr,#0xdb

mov sp,r0

sub r0,#0

   /*** sys mode and usr mode stack ***/

msr cpsr,#0x10

mov sp,r0             /*1024 byte  for user mode of stack*/

 

b main

 

delay1s:

     ldr      r4,=0xfffffff   

delay1s_loop:

     sub    r4,r4,#1

     cmp   r4,#0         

     bne    delay1s_loop

     mov   pc,lr

 

 

.align 4

 

/****  swi_interrupt handler  ****/

 

 

stacktop:    .word  stack+4*512

 

.data

 

stack:

  .space  4*512

.end

 

3.map.lds   链接脚本

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

OUTPUT_ARCH(arm)

ENTRY(_start)

SECTIONS

{

. = 0x40008000;  /*指定链接的起始地址   */

. = ALIGN(4);

.text      :

{

start.o(.text)

*(.text)

}

. = ALIGN(4);

    .data : 

{ *(.data) }

    . = ALIGN(4);

    .bss :

     { *(.bss) }

}

4. Makefile   编译

all:

arm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o start.o start.S

arm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o main.o main.c

arm-none-linux-gnueabi-ld start.o main.o -Tmap.lds -o uart.elf

arm-none-linux-gnueabi-objcopy -O binary  uart.elf uart.bin

arm-none-linux-gnueabi-objdump -D uart.elf > uart.dis

clean:

rm -rf *.bak start.o main.o uart.elf uart.bin uart.dis

上一篇:TN0015_fork函数替换为SylixOS进程

下一篇:信号量的pv操作

热点文章推荐
华清学员就业榜单
高薪学员经验分享
热点新闻推荐
前台专线:010-82525158 企业培训洽谈专线:010-82525379 院校合作洽谈专线:010-82525379 Copyright © 2004-2022 北京华清远见科技集团有限公司 版权所有 ,京ICP备16055225号-5京公海网安备11010802025203号

回到顶部