S5PV210裸机(四):按键中断

news2024/11/25 16:25:02

本文主要探讨轮询按键和中断安按键的相关知识。

按键
        无按下,GPIO引脚处高电平,电路断开
        按下,GPIO引脚接低电平,电路导通
        SoC内部通过检测GPIO电平高低判断按键作为SoC的输入信号

 按键响应
        轮询方式:SoC每隔一段时间读取GPIO电平获取按键信息,影响CPU处理其他事务
        中断方式:设定GPIO触发中断处理程序ISR,按键触发GPIO外部中断,ISR程序处理按键信息

轮询处理按键

        按键

                SW5:GPH0_2

                SW6:GPH0_3

                SW7:GPH2_0

                SW8:GPH2_1

                SW9:GPH2_2

                SW10:GPH2_3

                

                初始化GPIO模式为input,循环读取GPIO的电平值,判断按键,并串口输出

 

 

按键消抖
        电平高到低(按键按下)或电平低到高(按键弹起)电平变化不是瞬时变化,是有短暂的稳定后变化
        触发按键按下/弹起,延时时间(10~20ms)再次获取按键信息和上次对比,若相同则认为弹起或按下

demo1:

        轮询按键延时监测,不同led灯亮表示不同按键按下

start.S

#define WTCON           0xE2700000
#define SVC_STACK       0xd0037d80

.global _start
_start:
        //关看门狗
        ldr r0, =WTCON
        ldr r1, =0x0
        str r1, [r0]

        //设置SVC栈
        ldr sp, =SVC_STACK

        //开/关icache
        mrc p15,0,r0,c1,c0,0;                   // 读出cp15的c1到r0中
        orr r0, r0, #(1<<12)                    // bit12 置1  开icache
        mcr p15,0,r0,c1,c0,0;


        bl key_init
        bl key_polling

        b .

key.c

#define GPH0CON         0xE0200C00
#define GPH0DAT         0xE0200C04
#define GPH2CON         0xE0200C40
#define GPH2DAT         0xE0200C44

#define rGPH0CON        (*(volatile unsigned int *)GPH0CON)
#define rGPH0DAT        (*(volatile unsigned int *)GPH0DAT)
#define rGPH2CON        (*(volatile unsigned int *)GPH2CON)
#define rGPH2DAT        (*(volatile unsigned int *)GPH2DAT)

void key_init(void)
{
        // 设置GPHxCON寄存器,设置为输入模式
        rGPH0CON &= ~(0xFF<<8);
        rGPH2CON &= ~(0xFFFF<<0);
}

void key_polling(void)
{
        while (1)
        {
                if (rGPH0DAT & (1<<2))
                {
                        //按键未按下
                        led_off();
                }
                else
                {
                        //LEFT按键按下
                        delay_time();
                        led1();
                }

                if (rGPH0DAT & (1<<3))
                {
                        //按键未按下
                        led_off();
                }
                else
                {
                        //DOWN按键按下
                        delay_time();
                        led2();
                }

                if (rGPH2DAT & (1<<0))
                {
                        //按键未按下
                        led_off();
                }
                else
                {
                        //UP按键按下
                        delay_time();
                        led3();
                }
        }
}

led.c

#define GPJ0CON         0xE0200240
#define GPJ0DAT         0xE0200244
#define rGPJ0CON        *((volatile unsigned int *)GPJ0CON)
#define rGPJ0DAT        *((volatile unsigned int *)GPJ0DAT)

//亮1个led
void led1()
{
        rGPJ0CON = 0x11111111;
        rGPJ0DAT = ((0<<3) | (1<<4) | (1<<5));
}

//亮2个led
void led2()
{
        rGPJ0CON = 0x11111111;
        rGPJ0DAT = ((0<<3) | (0<<4) | (1<<5));
}

//亮3个led
void led3()
{
        rGPJ0CON = 0x11111111;
        rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));
}

//led灭
void led_off()
{
        rGPJ0CON = 0x11111111;
        rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));
}

//延时

void delay_time()
{
        unsigned volatile int i = 900000;
        while(i--);
}

Makefile

key.bin: start.o led.o key.o
        arm-linux-ld -Ttext 0x0 -o key.elf $^
        arm-linux-objcopy -O binary key.elf key.bin
        arm-linux-objdump -D key.elf > key.dis
        gcc mkv210_image.c -o mkx210
        ./mkx210 key.bin 210.bin

%.o : %.S
        arm-linux-gcc -o $@ $< -c -nostdlib

%.o : %.c
        arm-linux-gcc -o $@ $< -c -nostdlib

clean:
        rm *.o *.elf *.bin *.dis mkx210 -f

210外部中断

        外部中断是SoC外部设备通过GPIO引脚产生的中断,GPIO配置为外部中断模式,按键触发电压高低会触发外部中断通过引脚传给CPU处理
        电平触发分为高电平触发和低电平触发,GPIO上电平会不停触发中断。
        边沿触发分为上升沿触发、下降沿触发和双边沿触发,边沿触发即为电平变化的瞬间触发

        按键

                同上

        GPIO

                同上

        外部中断关键寄存器:EXT_CON、EXT_PEND、EXT_MASK


                EXT_INT_n_CON配置外部中断触发方式


                EXT_INT_n_PEND是中断挂起,中断触发设置1,若为处理则一直为1直至处理


                EXT_INT_n_MASK中断使能或禁止禁止开关。

EINT2、EINT3、EINT16_19(VIC0)

   

中断
        单核CPU不能并行执行事务,需要中断机制,断开在执行事务处理中断,结束后返回继续执行事务
        异常处理程序和异常向量表绑定,异常触发后cpu跳转到异常向量表执行绑定的处理程序
中断处理使用汇编实现跳转和返回
        跳转到IRQ,保存SVC下寄存器(保存r0~r12(scv),保存运行地址(svc)到lr(irq),保存cpsr(svc)到spsr(irq))

210中断
       异常向量表跳转
                    保存现场:
                                跳转到IRQ
                                保存SVC下寄存器(保存r0~r12(scv)
                                保存运行地址(svc)到lr(irq)
                                保存cpsr(svc)到spsr(irq))
        执行异常处理程序irq_handler
                210有4个中断寄存器,每位对应一个中断源
                中断发生irq_handler查询置1位,判断中断编号和寄存器

   210中断寄存器    

         VICnINTENABLE和VICnINTENCLEAR
                VICnINTENABLE     中断使能
                INTENCLEAR         中断禁止
                使能VICnINTENABLE对应位写1
                禁止INTENCLEAR对应位写1
                不存在同为1或0冲突,使能或禁止时另一寄存器会被自发修改

        VICnINTSELECT
                设置对应位中断模式为irq或fiq
                fiq模式有专有的r8~r12

 

        VICnIRQSTATUS和VICnFIQSTATUS
                中断状态寄存器且只读,发生中断,对应位自发置1,由此获得中断编号

 

        VICnVECTPRIORITY0~VICnVECTPRIORITY31
                中断优先级设置

        

         

         

        VICnVECTADDR0~VICnVECTADDR31、VICnADDRESS
                VICnVECTADDR存放各中断isr函数地址

        

        

        
                VICnADDRESS发生中断,自动识别中断编号并且会自动找到对应VECnTADDR,复制isr函数地址到VICADDRESS

        

demo2:

        按键中断监测,printf串口打印哪个按键被按下

start.S

#define WTCON           0xE2700000
#define SVC_STACK       0xd0037d80
#define IRQ_STACK       0xd0037f80

.global IRQ_handle
.global _start

_start:
        //关看门狗
        ldr r0, =WTCON
        ldr r1, =0x0
        str r1, [r0]

        //设置SVC栈
        ldr sp, =SVC_STACK

        //开/关icache
        mrc p15,0,r0,c1,c0,0;                   // 读出cp15的c1到r0中
        orr r0, r0, #(1<<12)                    // bit12 置1  开icache
        mcr p15,0,r0,c1,c0,0;

        bl main
        b .

//现场保护和恢复,调用中断处理程序
IRQ_handle:
        //设置IRQ模式下的栈
        ldr sp, =IRQ_STACK
        // 保存LR
        sub lr, lr, #4
        //保存r0-r12和lr到irq模式下的栈
        stmfd sp!, {r0-r12, lr}
        //调用isr处理程序
        bl irq_handler
        //恢复现场
        ldmfd sp!, {r0-r12, pc}^

main.c

#include "stdio.h"
#include "uart.h"
#include "key.h"
#include "interrupt.h"

#define KEY_EINT2               NUM_EINT2               //left
#define KEY_EINT3               NUM_EINT3               //down
#define KEY_EINT16_19   NUM_EINT16_31                   //else

void dealy_time()
{
        unsigned int i = 900000;
        while(i--);
}

int main()
{
        //初始化串口
        init_uart();

        //初始化按键
        key_init_interrupt();

        //初始化中断控制器
        system_init_exception();

        //绑定isr到中断控制器硬件
        intc_setvectaddr(KEY_EINT2, isr_eint2);
        intc_setvectaddr(KEY_EINT3, isr_eint3);
        intc_setvectaddr(KEY_EINT16_19, isr_eint16_19);

        //使能中断
        intc_enable(KEY_EINT2);
        intc_enable(KEY_EINT3);
        intc_enable(KEY_EINT16_19);

        //延时
        while (1)
        {
                dealy_time();
        }

        return 0;
}

uart.c

#define  GPA0CON0       0xE0200000
#define  UCON0          0xE2900004
#define  ULCON0         0xE2900000
#define  UMCON0         0xE290000C
#define  UFCON0         0xE2900008
#define  UBRDIV0        0xE2900028
#define  UDIVSLOT0      0xE290002C
#define UTRSTAT0        0xE2900010
#define UTXH0           0xE2900020
#define URXH0           0xE2900024

#define rGPA0CON0       (*(volatile unsigned int *)GPA0CON0)
#define rUCON0          (*(volatile unsigned int *)UCON0)
#define rULCON0         (*(volatile unsigned int *)ULCON0)
#define rUMCON0         (*(volatile unsigned int *)UMCON0)
#define rUFCON0         (*(volatile unsigned int *)UFCON0)
#define rUBRDIV0        (*(volatile unsigned int *)UBRDIV0)
#define rUDIVSLOT0      (*(volatile unsigned int *)UDIVSLOT0)
#define rUTRSTAT0       (*(volatile unsigned int *)UTRSTAT0)
#define rUTXH0          (*(volatile unsigned int *)UTXH0)
#define rURXH0          (*(volatile unsigned int *)URXH0)

void init_uart()
{
  //set GPIO uart mode(TX,RX)
  rGPA0CON0 &= ~(0xff); 
  rGPA0CON0 |= ((1 << 2) | (1<< 6));
  //set uart polling mode
  rUCON0 = 0x5;
  //set uart,prohibit afc 
  rUMCON0 = 0x0;
  //set uart,prohibit fifo
  rUFCON0 = 0x0;
  //set clock device frequence
  //DIV_VAL = (PCLK / (bps x 16)) -1
  //DIV_VAL = (66000000 / (115200*16)) -1 = 34.8
  rUBRDIV0 = 34;
  //0.8 * 16 = 13,check 210 table
  rUDIVSLOT0 = 0xdfdd;
}

void putc(char cdata)
{
  //judge send buff is'not or is empty,then send data 
  while (!(rUTRSTAT0 & (1 << 1)));
  rUTXH0 = cdata;
}

char getc()
{
  //judge get buff is'not or is empty,then get data
  while (!(rUTRSTAT0 & 1));
  return (rURXH0 & 0x0f);
}

uart.h

void init_uart();

void send_data(char cdata);

char get_data();

key.c

#include "stdio.h"
#include "interrupt.h"

#define GPH0CON         0xE0200C00
#define GPH0DAT         0xE0200C04
#define GPH2CON         0xE0200C40
#define GPH2DAT         0xE0200C44

#define rGPH0CON        (*(volatile unsigned int *)GPH0CON)
#define rGPH0DAT        (*(volatile unsigned int *)GPH0DAT)
#define rGPH2CON        (*(volatile unsigned int *)GPH2CON)
#define rGPH2DAT        (*(volatile unsigned int *)GPH2DAT)

#define EXT_INT_0_CON   0xE0200E00
#define EXT_INT_2_CON   0xE0200E08
#define EXT_INT_0_PEND  0xE0200F40
#define EXT_INT_2_PEND  0xE0200F48
#define EXT_INT_0_MASK  0xE0200F00
#define EXT_INT_2_MASK  0xE0200F08

#define rEXT_INT_0_CON  (*(volatile unsigned int *)EXT_INT_0_CON)
#define rEXT_INT_2_CON  (*(volatile unsigned int *)EXT_INT_2_CON)
#define rEXT_INT_0_PEND (*(volatile unsigned int *)EXT_INT_0_PEND)
#define rEXT_INT_2_PEND (*(volatile unsigned int *)EXT_INT_2_PEND)
#define rEXT_INT_0_MASK (*(volatile unsigned int *)EXT_INT_0_MASK)
#define rEXT_INT_2_MASK (*(volatile unsigned int *)EXT_INT_2_MASK)

//按键初始化
void key_init_interrupt()
{
        //GPIO模式设置为外部中断模式
        rGPH0CON |= 0xFF<<8;
        rGPH2CON |= 0xFFFF<<0;

        //中断触发模式设置
        rEXT_INT_0_CON &= ~(0xFF<<8);
        rEXT_INT_0_CON |= ((2<<8)|(2<<12));                     //EXT_INT2和EXT_INT3设置为下降沿触发
        rEXT_INT_2_CON &= ~(0xFFFF<<0);
        rEXT_INT_2_CON |= ((2<<0)|(2<<4)|(2<<8)|(2<<12));       //EXT_INT16_19设置为下降沿触发

        //中断允许
        rEXT_INT_0_MASK &= ~(3<<2);
        rEXT_INT_2_MASK &= ~(0x0f<<0);

        //清挂起,清除是写1
        rEXT_INT_0_PEND |= (3<<2);
        rEXT_INT_2_PEND |= (0x0F<<0);
}

//EINT2按键<==>GPH0_2引脚<==>LEFT按键,处理程序
void isr_eint2()
{
        printf("isr_eint2_LEFT.\n");
        //清除中断挂起
        rEXT_INT_0_PEND |= (1<<2);
        intc_clearvectaddr();
}

//EINT3按键<==>GPH0_3引脚<==>DOWN按键,处理程序
void isr_eint3()
{
        printf("isr_eint3_DOWN.\n");
        //清除中断挂起
        rEXT_INT_0_PEND |= (1<<3);
        intc_clearvectaddr();
}

void isr_eint16_19()
{
        if (rEXT_INT_2_PEND & (1<<0))
        {
                printf("eint16\n");
        }
        if (rEXT_INT_2_PEND & (1<<1))
        {
                printf("eint17\n");
        }
        if (rEXT_INT_2_PEND & (1<<2))
        {
                printf("eint18\n");
        }
        if (rEXT_INT_2_PEND & (1<<3))
        {
                printf("eint19\n");
        }

        //清除中断挂起
        rEXT_INT_2_PEND |= (0x0f<<0);
        intc_clearvectaddr();
}

key.h

void key_init_interrupt();

void isr_eint2();

void isr_eint3();

void isr_eint16_19();

interrupt.c

#include "stdio.h"
#include "interrupt.h"

void reset_exception()
{
        printf("reset_exception.\n");
}

void undef_exception()
{
        printf("undef_exception.\n");
}

void sotf_int_exception()
{
        printf("sotf_int_exception.\n");
}

void prefetch_exception()
{
        printf("prefetch_exception.\n");
}

void data_exception()
{
        printf("data_exception.\n");
}

//绑定异常向量表;禁止所有中断;选择中断类型为IRQ;清除VICnADDR为0
void system_init_exception()
{
        //绑定异常向量表
        r_exception_reset = (unsigned int)reset_exception;
        r_exception_undef = (unsigned int)undef_exception;
        r_exception_sotf_int = (unsigned int)sotf_int_exception;
        r_exception_prefetch = (unsigned int)prefetch_exception;
        r_exception_data = (unsigned int)data_exception;
        r_exception_irq = (unsigned int)IRQ_handle;
        //r_exception_fiq = (unsigned int)FIQ_handle;

        //初始化中断控制器的基本寄存器
        intc_init();
}

//清除中断处理函数地址
void intc_clearvectaddr()
{
    // VICxADDR:当前正在处理的中断的中断处理函数的地址
    VIC0ADDR = 0;
    VIC1ADDR = 0;
    VIC2ADDR = 0;
    VIC3ADDR = 0;
}

//初始化中断控制器
void intc_init()
{
    //禁止所有中断
    VIC0INTENCLEAR = 0xffffffff;
    VIC1INTENCLEAR = 0xffffffff;
    VIC2INTENCLEAR = 0xffffffff;
    VIC3INTENCLEAR = 0xffffffff;

    //选择中断类型为IRQ
    VIC0INTSELECT = 0x0;
    VIC1INTSELECT = 0x0;
    VIC2INTSELECT = 0x0;
    VIC3INTSELECT = 0x0;

    //清VICnADDR
    intc_clearvectaddr();
}


//绑定我们写的isr到VICnVECTADDR寄存器
void intc_setvectaddr(unsigned long intnum, void (*handler)(void))
{
    //VIC0
    if(intnum<32)
    {
        *( (volatile unsigned long *)(VIC0VECTADDR + 4*(intnum-0)) ) = (unsigned)handler;
    }
    //VIC1
    else if(intnum<64)
    {
        *( (volatile unsigned long *)(VIC1VECTADDR + 4*(intnum-32)) ) = (unsigned)handler;
    }
    //VIC2
    else if(intnum<96)
    {
        *( (volatile unsigned long *)(VIC2VECTADDR + 4*(intnum-64)) ) = (unsigned)handler;
    }
    //VIC3
    else
    {
        *( (volatile unsigned long *)(VIC3VECTADDR + 4*(intnum-96)) ) = (unsigned)handler;
    }
}


//使能中断
void intc_enable(unsigned long intnum)
{
    unsigned long temp;
   //确定intnum
    if(intnum<32)
    {
        temp = VIC0INTENABLE;
        temp |= (1<<intnum);
        VIC0INTENABLE = temp;
    }
    else if(intnum<64)
    {
        temp = VIC1INTENABLE;
        temp |= (1<<(intnum-32));
        VIC1INTENABLE = temp;
    }
    else if(intnum<96)
    {
        temp = VIC2INTENABLE;
        temp |= (1<<(intnum-64));
        VIC2INTENABLE = temp;
    }
    else if(intnum<NUM_ALL)
    {
        temp = VIC3INTENABLE;
        temp |= (1<<(intnum-96));
        VIC3INTENABLE = temp;
    }
    else
    {
        VIC0INTENABLE = 0xFFFFFFFF;
        VIC1INTENABLE = 0xFFFFFFFF;
        VIC2INTENABLE = 0xFFFFFFFF;
        VIC3INTENABLE = 0xFFFFFFFF;
    }

}

//禁止中断
void intc_disable(unsigned long intnum)
{
    unsigned long temp;

    if(intnum<32)
    {
        temp = VIC0INTENCLEAR;
        temp |= (1<<intnum);
        VIC0INTENCLEAR = temp;
    }
    else if(intnum<64)
    {
        temp = VIC1INTENCLEAR;
        temp |= (1<<(intnum-32));
        VIC1INTENCLEAR = temp;
    }
    else if(intnum<96)
    {
        temp = VIC2INTENCLEAR;
        temp |= (1<<(intnum-64));
        VIC2INTENCLEAR = temp;
    }
    else if(intnum<NUM_ALL)
    {
        temp = VIC3INTENCLEAR;
        temp |= (1<<(intnum-96));
        VIC3INTENCLEAR = temp;
    }
    else
    {
        VIC0INTENCLEAR = 0xFFFFFFFF;
        VIC1INTENCLEAR = 0xFFFFFFFF;
        VIC2INTENCLEAR = 0xFFFFFFFF;
        VIC3INTENCLEAR = 0xFFFFFFFF;
    }
}


//读取VICnIRQSTATUS判断具体VIC中断
unsigned long intc_getvicirqstatus(unsigned long ucontroller)
{
    if(ucontroller == 0)
        return  VIC0IRQSTATUS;
    else if(ucontroller == 1)
        return  VIC1IRQSTATUS;
    else if(ucontroller == 2)
        return  VIC2IRQSTATUS;
    else if(ucontroller == 3)
        return  VIC3IRQSTATUS;
    else
    {

    }
    return 0;
}


//中断处理
void irq_handler(void)
{
    unsigned long vicaddr[4] = {VIC0ADDR,VIC1ADDR,VIC2ADDR,VIC3ADDR};
    int i=0;
    void (*isr)(void) = NULL;

    for(i=0; i<4; i++)
    {
        if(intc_getvicirqstatus(i) != 0)
        {
            isr = (void (*)(void)) vicaddr[i];
            break;
        }
    }
    (*isr)();           //调用函数
}

interrupt.h

#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__


#define VIC0_BASE                                       (0xF2000000)
#define VIC1_BASE                                       (0xF2100000)
#define VIC2_BASE                                       (0xF2200000)
#define VIC3_BASE                                       (0xF2300000)

//VIC0
#define         VIC0IRQSTATUS                   ( *((volatile unsigned long *)(VIC0_BASE + 0x00)) )
#define         VIC0FIQSTATUS                   ( *((volatile unsigned long *)(VIC0_BASE + 0x04)) )
#define         VIC0INTSELECT                   ( *((volatile unsigned long *)(VIC0_BASE + 0x0c)) )
#define         VIC0INTENABLE                   ( *((volatile unsigned long *)(VIC0_BASE + 0x10)) )
#define         VIC0INTENCLEAR                  ( *((volatile unsigned long *)(VIC0_BASE + 0x14)) )
#define         VIC0VECTADDR                    (VIC0_BASE + 0x100)
#define         VIC0ADDR                        ( *((volatile unsigned long *)(VIC0_BASE + 0xf00)) )

//VIC1
#define         VIC1IRQSTATUS                   ( *((volatile unsigned long *)(VIC1_BASE + 0x00)) )
#define         VIC1FIQSTATUS                   ( *((volatile unsigned long *)(VIC1_BASE + 0x04)) )
#define         VIC1INTSELECT                   ( *((volatile unsigned long *)(VIC1_BASE + 0x0c)) )
#define         VIC1INTENABLE                   ( *((volatile unsigned long *)(VIC1_BASE + 0x10)) )
#define         VIC1INTENCLEAR                  ( *((volatile unsigned long *)(VIC1_BASE + 0x14)) )
#define         VIC1VECTADDR                    (VIC1_BASE + 0x100)
#define         VIC1ADDR                        ( *((volatile unsigned long *)(VIC1_BASE + 0xf00)) )

//VIC2
#define         VIC2IRQSTATUS                   ( *((volatile unsigned long *)(VIC2_BASE + 0x00)) )
#define         VIC2FIQSTATUS                   ( *((volatile unsigned long *)(VIC2_BASE + 0x04)) )
#define         VIC2INTSELECT                   ( *((volatile unsigned long *)(VIC2_BASE + 0x0c)) )
#define         VIC2INTENABLE                   ( *((volatile unsigned long *)(VIC2_BASE + 0x10)) )
#define         VIC2INTENCLEAR                  ( *((volatile unsigned long *)(VIC2_BASE + 0x14)) )
#define         VIC2VECTADDR                    (VIC2_BASE + 0x100)
#define         VIC2ADDR                        ( *((volatile unsigned long *)(VIC2_BASE + 0xf00)) )

// VIC3
#define         VIC3IRQSTATUS                   ( *((volatile unsigned long *)(VIC3_BASE + 0x00)) )
#define         VIC3FIQSTATUS                   ( *((volatile unsigned long *)(VIC3_BASE + 0x04)) )
#define         VIC3INTSELECT                   ( *((volatile unsigned long *)(VIC3_BASE + 0x0c)) )
#define         VIC3INTENABLE                   ( *((volatile unsigned long *)(VIC3_BASE + 0x10)) )
#define         VIC3INTENCLEAR                  ( *((volatile unsigned long *)(VIC3_BASE + 0x14)) )
#define         VIC3VECTADDR                    (VIC3_BASE + 0x100)
#define         VIC3ADDR                        ( *((volatile unsigned long *)(VIC3_BASE + 0xf00)) )


#define exception_vector_table_base             0xD0037400
#define exception_reset                         (exception_vector_table_base + 0x00)
#define exception_undef                         (exception_vector_table_base + 0x04)
#define exception_sotf_int                      (exception_vector_table_base + 0x08)
#define exception_prefetch                      (exception_vector_table_base + 0x0C)
#define exception_data                          (exception_vector_table_base + 0x10)
#define exception_irq                           (exception_vector_table_base + 0x18)
#define exception_fiq                           (exception_vector_table_base + 0x1C)

#define r_exception_reset                       (*(volatile unsigned int *)exception_reset)
#define r_exception_undef                       (*(volatile unsigned int *)exception_undef)
#define r_exception_sotf_int                    (*(volatile unsigned int *)exception_sotf_int)
#define r_exception_prefetch                    (*(volatile unsigned int *)exception_prefetch)
#define r_exception_data                        (*(volatile unsigned int *)exception_data)
#define r_exception_irq                         (*(volatile unsigned int *)exception_irq)
#define r_exception_fiq                         (*(volatile unsigned int *)exception_fiq)

//中断源编号
#define INT_LIMIT                               (96)

//INT NUM - VIC0
#define NUM_EINT0                               (0)
#define NUM_EINT1                               (1)
#define NUM_EINT2                               (2)
#define NUM_EINT3                               (3)
#define NUM_EINT4                               (4)
#define NUM_EINT5                               (5)
#define NUM_EINT6                               (6)
#define NUM_EINT7                               (7)
#define NUM_EINT8                               (8)
#define NUM_EINT9                               (9)
#define NUM_EINT10                              (10)
#define NUM_EINT11                              (11)
#define NUM_EINT12                              (12)
#define NUM_EINT13                              (13)
#define NUM_EINT14                              (14)
#define NUM_EINT15                              (15)
#define NUM_EINT16_31                           (16)
#define NUM_Reserved17                          (17) 
#define NUM_MDMA                                (18)
#define NUM_PDMA0                               (19)
#define NUM_PDMA1                               (20)
#define NUM_TIMER0                              (21)
#define NUM_TIMER1                              (22)
#define NUM_TIMER2                              (23)
#define NUM_TIMER3                              (24)
#define NUM_TIMER4                              (25)
#define NUM_SYSTIMER                            (26)
#define NUM_WDT                                 (27)
#define NUM_RTC_ALARM                           (28)
#define NUM_RTC_TICK                            (29)
#define NUM_GPIOINT                             (30)
#define NUM_FIMC3                               (31)

//INT NUM - VIC1
#define NUM_CORTEX0                             (32+0)
#define NUM_CORTEX1                             (32+1)
#define NUM_CORTEX2                             (32+2)
#define NUM_CORTEX3                             (32+3)
#define NUM_CORTEX4                             (32+4)
#define NUM_IEM_APC                             (32+5)
#define NUM_IEM_IEC                             (32+6)
#define NUM_Reserved39                          (32+7)
#define NUM_NFC                                 (32+8)
#define NUM_CFC                                 (32+9)
#define NUM_UART0                               (32+10)
#define NUM_UART1                               (32+11)
#define NUM_UART2                               (32+12)
#define NUM_UART3                               (32+13)
#define NUM_I2C                                 (32+14)
#define NUM_SPI0                                (32+15)
#define NUM_SPI1                                (32+16)
#define NUM_SPI2                                (32+17)
#define NUM_AUDIO                               (32+18)
#define NUM_I2C_PMIC                            (32+19)
#define NUM_I2C_HDMI                            (32+20)
#define NUM_HSIRX                               (32+21)
#define NUM_HSITX                               (32+22)
#define NUM_UHOST                               (32+23)
#define NUM_OTG                                 (32+24)
#define NUM_MSM                                 (32+25)
#define NUM_HSMMC0                              (32+26)
#define NUM_HSMMC1                              (32+27)
#define NUM_HSMMC2                              (32+28)
#define NUM_MIPI_CSI                            (32+29)
#define NUM_MIPI_DSI                            (32+30)
#define NUM_ONENAND_AUDI                        (32+31)

//INT NUM - VIC2
#define NUM_LCD0                                (64+0)
#define NUM_LCD1                                (64+1)
#define NUM_LCD2                                (64+2)
#define NUM_LCD3                                (64+3)
#define NUM_ROTATOR                             (64+4)
#define NUM_FIMC_A                              (64+5)
#define NUM_FIMC_B                              (64+6)
#define NUM_FIMC_C                              (64+7)
#define NUM_JPEG                                (64+8)
#define NUM_2D                                  (64+9)
#define NUM_3D                                  (64+10)
#define NUM_MIXER                               (64+11)
#define NUM_HDMI                                (64+12)
#define NUM_HDMI_I2C                            (64+13)
#define NUM_MFC                                 (64+14)
#define NUM_TVENC                               (64+15)
#define NUM_I2S0                                (64+16)
#define NUM_I2S1                                (64+17)
#define NUM_I2S2                                (64+18)
#define NUM_AC97                                (64+19)
#define NUM_PCM0                                (64+20)
#define NUM_PCM1                                (64+21)
#define NUM_SPDIF                               (64+22)
#define NUM_ADC                                 (64+23)
#define NUM_PENDN                               (64+24)
#define NUM_KEYPAD                              (64+25)
#define NUM_Reserved90                          (64+26) 
#define NUM_HASH                                (64+27) 
#define NUM_FEEDCTRL                            (64+28) 
#define NUM_PCM2                                (64+29)
#define NUM_SDM_IRQ                             (64+30)
#define NUM_SMD_FIQ                             (64+31)

//INT NUM - VIC3
#define NUM_IPC                                 (96+0)
#define NUM_HOSTIF                              (96+1)
#define NUM_HSMMC3                              (96+2)
#define NUM_CEC                                 (96+3)
#define NUM_TSI                                 (96+4)
#define NUM_MDNIE0                              (96+5)
#define NUM_MDNIE1                              (96+6)
#define NUM_MDNIE2                              (96+7)
#define NUM_MDNIE3                              (96+8)
#define NUM_ADC1                                (96+9)
#define NUM_PENDN1                              (96+10)
#define NUM_ALL                                 (200)

void system_init_exception();

void intc_clearvectaddr();

void intc_init();

void intc_setvectaddr(unsigned long intnum, void (*handler)(void));

void intc_enable(unsigned long intnum);

void intc_disable(unsigned long intnum);

unsigned long intc_getvicirqstatus(unsigned long ucontroller);

void irq_handler(void);

void IRQ_handle();

#endif

Makefile

CC              = arm-linux-gcc
LD              = arm-linux-ld
OBJCOPY = arm-linux-objcopy
OBJDUMP = arm-linux-objdump
AR              = arm-linux-ar

INCDIR  := $(shell pwd)
# C预处理器的flag,flag就是编译器可选的选项
CPPFLAGS        := -nostdlib -nostdinc -I$(INCDIR)/include
# C编译器的flag
CFLAGS          := -Wall -O2 -fno-builtin

#导出这些变量到全局,其实就是给子文件夹下面的Makefile使用
export CC LD OBJCOPY OBJDUMP AR CPPFLAGS CFLAGS


objs := start.o uart.o main.o key.o interrupt.o 
objs += lib/libc.a

uart.bin: $(objs)
        $(LD) -Ttext 0x0 -o interrupt.elf $^
        $(OBJCOPY) -O binary interrupt.elf interrupt.bin
        $(OBJDUMP) -D interrupt.elf > interrupt.dis
        gcc mkv210_image.c -o mkx210
        ./mkx210 interrupt.bin 210.bin
lib/libc.a:
        cd lib; make; cd ..

%.o : %.S
        $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c

%.o : %.c
        $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c

clean:
        rm *.o *.elf *.bin *.dis mkx210 -f
        cd lib; make clean; cd ..

printf

​​​​​​​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1070994.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IPETRONIK数据采集设备携手Softing Q-Vision软件致力于ADAS测试方案

一 背景 汽车ADAS技术是当下国内外的重点研究方向&#xff0c;且ADAS的发展水平和市场竞争力紧密相关&#xff0c;因此一套完善的ADAS测试方案对各整车厂而言非常重要。然而&#xff0c;国内ADAS测试却面临着很多阻碍&#xff0c;主要原因在于&#xff1a;相关测试设备昂贵&am…

关于LinkedBlockingQueue的offer的正确用法,如何保证阻塞

我们在做一些并发操作时&#xff0c;常常会使用到LinkedBlockingQueue 也会使用offer方法来往队列中插入数据 我们一直觉得使用offer后&#xff0c;当队列满了&#xff0c;新增加的元素会阻塞插入线程&#xff0c;然后一直等待到队列有空间后再插入。然而测试后发现并不是这样。…

7. Java本项目知识基础---上篇

Java本项目知识快速入门 1. idea项目打开、关闭、复制 正常关闭&#xff1a; 正常打开&#xff1a; 正常复制&#xff1a; 2. idea快捷键 保存&#xff1a;ctrls 撤销&#xff1a;ctrlz 还原&#xff1a;ctrlshiftz 复制:ctrlc 粘贴:ctrlv 快速复制粘贴:ctrld 删除行:c…

MySQL MVCC多版本并发控制机制原理详解

目录 一、前言二、MVCC解决了什么问题三、MVCC核心 Undo Log 和 Read View 介绍3.1、Undo Log&#xff08;日志版本链&#xff09;3.2、Read View&#xff08;一致性视图&#xff09;3.2.1、设计思路3.2.2、ReadView判断规则 四、数据准备五、举例探究MVCC机制5.1、例子执行流程…

直流负载箱的维护和保养方法有哪些?

直流负载箱的维护和保养方法主要包括以下几个方面&#xff1a; 日常要定期清洁负载箱的外壳和散热器&#xff0c;确保散热良好&#xff0c;避免灰尘积累影响散热效果。还要定期检查负载箱的连接器&#xff0c;确保连接良好&#xff0c;避免接触不良或松动导致故障。根据使用要求…

信创之国产浪潮电脑+统信UOS操作系统体验3:使用 visual studio code搭建Python开发环境

☞ ░ 前往老猿Python博客 ░ https://blog.csdn.net/LaoYuanPython 一、引言 老猿原来在windows下开发python程序&#xff0c;要么使用python自带的IDLE&#xff0c;要么使用pycharm&#xff0c;IDLE用来开发很不方便&#xff0c;而pycharm对开发支持比较好&#xff0c;换成…

我做了一个简易P图(参数图)分析软件

P图(即参数图&#xff0c;Parameter Diagram)&#xff0c;是一个结构化的工具&#xff0c;帮助大家对产品更好地进行分析。 典型P图格式 P图最好是和FMEA软件联动起来&#xff0c;如国可工软的FMEA软件有P图分析这个功能。 单纯的P图分析软件很少&#xff0c;为了方便做P图分…

vue-1

一、为什么要学习Vue 1.前端必备技能 2.岗位多&#xff0c;绝大互联网公司都在使用Vue 3.提高开发效率 4.高薪必备技能&#xff08;Vue2Vue3&#xff09; 二、什么是Vue 概念&#xff1a;Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套 构建用户界面 的 渐进式 框架 …

检验样品数量

声明 本文是学习GB-T 586-2015 船用法兰铸钢止回阀. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 4 要求 4.1 材料 止回阀的主要零件材料见表4。 表4 止回阀的主要零件材料 零 件 名 称 材 料 名 称 牌 号 标 准 编 号 阀体 阀体 铸钢 ZG275-485…

使用docker-compose部署Redis(单机部署)

目录 一、查看Redis镜像版本二、拉取自己需要的镜像版本三、创建挂载目录四、添加配置文件五、编写 docker-compose.yml 文件六、启动容器七、连接测试 一、查看Redis镜像版本 先去Docker Hub查看Redis镜像有那些版本&#xff0c;我部署的时候Redis最新已经到7.x的版本了&…

23.4 Bootstrap 框架5

1. 背景颜色 1.1 背景颜色样式 在Bootstrap 5中, 可以使用以下类来设置背景颜色: * 1. .bg-primary: 设置为主要的背景颜色(#007bff, 深蓝色). * 2. .bg-secondary: 设置为次要的背景颜色(#6c757d, 灰色). * 3. .bg-success: 设置为成功的背景颜色(#28a745, 绿色). * 4. …

[yolo系列:yolov7添加可变形卷积Deformable Conv V2]

yolo系列文章目录 文章目录 yolo系列文章目录一、可变形卷积是什么&#xff1f;二、使用步骤1.在models/common.py文件添加2.然后再yolo.py里面添加DCNv23.修改yolov7的yaml 总结参考文章 一、可变形卷积是什么&#xff1f; 可变形卷积即DCN&#xff08;缩写取自Deformable Con…

uniapp:swiper-demo效果

单元格轮播 <swiper class"swiper1" :circular"true" :autoplay"true" interval"3000" previous-margin"195rpx" next-margin"195rpx"><swiper-item v-for"(item,index) in 5" :key"inde…

平凡工作也能创造卓越:学习公文写作的逻辑与技巧

平凡工作也能创造卓越&#xff1a;学习公文写作的逻辑与技巧 前言如何把平凡的工作写出光环1.个人不能超越集体2.工作成果的概括要准确3.描写平凡工作的难点痛点 书籍介绍关键点关键词 书籍亮点内容简介购买链接参与方式往期赠书回顾 前言 如何把平凡的工作写出光环 &#x1…

C语言字符串查找函数和错误信息报告函数(strstr、strtok,strerror)

文章目录 摘要1 strstr1.1 函数使用1.2 模拟实现 2. strtok2.1 函数介绍 3. strerror3.1 函数介绍3.2 strerror 与 perror 摘要 本篇文章介绍了C语言中常用的字符串处理函数&#xff0c;包括字符串查找函数 strstr 和字符串分割函数 strtok&#xff0c;以及错误信息报告函数 s…

2023旅游产业内容营销洞察报告:如何升级经营模式,适配社媒新链路

2023年我国旅游业强劲复苏&#xff0c;上半年旅游消费增长显著&#xff0c;政府出台一系列文旅扶持政策后&#xff0c;旅游业也在积极寻求数字化转型的升级方式。 上半年以旅游消费为代表的服务业对经济的增长贡献率超过60%&#xff0c;旅游企业普遍实现经营好转&#xff0c;企…

Windows 10下安装运行ROS

Windows 10下安装运行ROS 官方教程 ROS on Windows installation 1 系统要求 Windows ROS需要64位的Windows 10 Desktop或Windows 10 IoT Enterprise。 请确保您已安装Powershell并在系统路径中 从实时病毒扫描程序中排除c:\opt(以及稍后的工作空间文件夹)&#xff0c;因为…

KALI 各种工具的使用与介绍

KALI 各种工具的使用与介绍 一、工具介绍 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关…

Linux CentOS7 yum仓库

在windows下安装一个软件很轻松&#xff0c;只要双击setup或者.exe的文件&#xff0c;安装提示连续“下一步”即可&#xff0c;然而linux系统下安装一个软件似乎并不那么轻松&#xff0c;因为我们不是在图形界面下。 本文我们将讨论如何在linux下安装一个软件。 一、linux软件…