OK6410裸机之中断向量控制器

发布者:Yuexiang最新更新时间:2018-10-11 来源: eefocus关键字:OK6410  裸机  中断  向量控制器 手机看文章 扫描二维码
随时随地手机看文章

statr.S文件:

.globl _start

_start:

    // 0 地址 

    b reset                                                  // 复位时,cpu跳到0地址 

    ldr pc, =undefined_instruction          // cpu遇到不能识别的指令时 

    ldr pc, _vector_swi                               // 当执行swi指令时, 进入swi模 式 

    b halt     @ldr    pc, _prefetch_abort  // 预取中止异常 

    b halt     @ldr    pc, _data_abort        // 数据访问异常 

    b halt     @ldr    pc, _not_used           // 没用到 

    ldr    pc, _irq                                        // 0x18 中断异常 

    b halt     @ldr    pc, _fiq                     // 快中断异常 

_irq :

    .word vector_irq

_vector_swi:

    .word vector_swi

vector_swi:

    // 1. 保存现场 

    ldr sp, =0x56000000

    stmdb sp!, {r0-r12, lr}  // lr就是swi的下一条指令地址 

    // 2. 处理异常 

    mrs r0, cpsr

    ldr r1, =swi_str

    bl print_cpsr

    // 3. 恢复现场 

    ldmia sp!, {r0-r12, pc}^ // ^表示把spsr恢复到cpsr 

    

swi_str:

    .word 0x00697773         // swi 

    

undefined_instruction:

    // 1. 保存现场 

    ldr sp, =0x55000000

    stmdb sp!, {r0-r12, lr}

    // 2. 处理异常 

    mrs r0, cpsr

    ldr r1, =und_str

    bl print_cpsr

    // 3. 恢复现场 

    ldmia sp!, {r0-r12, pc}^  // ^表示把spsr恢复到cpsr 

und_str:

    .word 0x00646e75         // und 

usr_str:

    .word 0x00727375         // usr 

vector_irq:

    // 1. 保存现场 

    ldr sp, =0x54000000

    sub lr, lr, #4               //只有swi和und异常lr指向下一条指令,其他异常发生的时候lr都是指向下两条指令

    stmdb sp!, {r0-r12, lr}  // lr就是swi的下一条指令地址 

    // 2. 处理异常 

    bl do_irq

    

    // 3. 恢复现场 

    ldmia sp!, {r0-r12, pc}^  // ^表示把spsr恢复到cpsr 

reset:

// 硬件相关的设置 

    // Peri port setup 

    ldr r0, =0x70000000

    orr r0, r0, #0x13

    mcr p15,0,r0,c15,c2,4       @ 256M(0x70000000-0x7fffffff)

    

// 关看门狗 

    // 往WTCON(0x7E004000)写0 

    ldr r0, =0x7E004000

    mov r1, #0

    str r1, [r0]

    

    // 设置栈 

    ldr sp, =8*1024

    // 设置时钟 

    bl clock_init

    bl ddr_init

    bl init_uart

// 把程序的代码段、数据段复制到它的链接地址去     

    adr r0, _start             // 获得_start指令当前所在的地址 : 0

    ldr r1, =_start           // _start的链接地址 0x51000000 

    

    ldr r2, =bss_start      // bss段的起始链接地址 

    

    sub r2, r2, r1

    

    cmp r0,r1

    beq clean_bss

    

    bl copy2ddr

    cmp r0, #0

    bne halt

        

// 清BSS 

// 把BSS段对应的内存清零 

clean_bss:

    ldr r0, =bss_start

    ldr r1, =bss_end

    mov r3, #0

    cmp r0, r1

    ldreq pc, =on_ddr

clean_loop:

    str r3, [r0], #4

    cmp r0, r1    

    bne clean_loop        

    ldr pc, =on_ddr

on_ddr:

    bl irq_init

    mrs r0, cpsr

    bic    r0,r0,#0x9f  // 清cpsr的I位,M4~M0 

    orr    r0,r0,#0x10

    msr    cpsr,r0       // 进入user mode 

    ldr sp, =0x57000000

    ldr r1, =usr_str

    bl print_cpsr

    

    swi 0

    // cpu进入svc模式

    // 把之前的cpsr保存到spsr_svc 

    // 切换到r13_svc, r14_svc

    // 把swi的下一条指令存到r14(lr)_svc

    // 跳到地址8

              

    bl hello

undef:

    .word 0xff000000

    // cpu进入Undefined模式

    // 把之前的cpsr保存到spsr_und 

    // 切换到r13_und, r14_und

    // 把下一条指令存到r14(lr)_und

    // 跳到地址4

swi_ret:

    bl main

halt:

    b halt    

=====================================================================

irq.c文件:

#define GPNCON     (*((volatile unsigned long *)0x7F008830))

#define GPNDAT     (*((volatile unsigned long *)0x7F008834))

#define EINT0CON0  (*((volatile unsigned long *)0x7F008900))

#define EINT0MASK  (*((volatile unsigned long *)0x7F008920))

#define EINT0PEND  (*((volatile unsigned long *)0x7F008924))

#define PRIORITY    (*((volatile unsigned long *)0x7F008280))

#define SERVICE     (*((volatile unsigned long *)0x7F008284))

#define SERVICEPEND (*((volatile unsigned long *)0x7F008288))

#define VIC0IRQSTATUS  (*((volatile unsigned long *)0x71200000))

#define VIC0FIQSTATUS  (*((volatile unsigned long *)0x71200004))

#define VIC0RAWINTR    (*((volatile unsigned long *)0x71200008))

#define VIC0INTSELECT  (*((volatile unsigned long *)0x7120000c))

#define VIC0INTENABLE  (*((volatile unsigned long *)0x71200010))

#define VIC0INTENCLEAR (*((volatile unsigned long *)0x71200014))

#define VIC0PROTECTION (*((volatile unsigned long *)0x71200020))

#define VIC0SWPRIORITYMASK (*((volatile unsigned long *)0x71200024))

#define VIC0PRIORITYDAISY  (*((volatile unsigned long *)0x71200028))

#define VIC0VECTADDR0      (*((volatile unsigned long *)0x71200100))

#define VIC0VECTADDR1      (*((volatile unsigned long *)0x71200104))

#define VIC0ADDRESS           (*((volatile unsigned long *)0x71200f00))

void eint0_3_irq(void)

{

    int i;

    

    printf("eint0_3_irq\n\r");  // K1~K4 

    for (i = 0; i < 4; i ++)

    {

        if (EINT0PEND & (1<

        {

            if (GPNDAT & (1<

            {

                printf("K%d released\n\r", i+1);

            }

            else

            {

                printf("K%d pressed\n\r", i+1);

            }

        }

    }

}

void eint4_11_irq(void)

{

    int i;

    printf("eint4_11_irq\n\r"); // K5~K6 

    for (i = 4; i < 6; i ++)

    {

        if (EINT0PEND & (1<

        {

            if (GPNDAT & (1<

            {

                printf("K%d released\n\r", i+1);

            }

            else

            {

                printf("K%d pressed\n\r", i+1);

            }

        }

    }

}

void irq_init(void)

{

    // 配置GPIO引脚为中断引脚 

    // GPN0~5 设为中断引脚 

    GPNCON &= ~(0xfff);

    GPNCON |= 0xaaa;

    // 设置中断触发方式为: 双边沿触发 

    EINT0CON0 &= ~(0xfff);

    EINT0CON0 |= 0x777;

    // 使能中断 

    EINT0MASK &= ~(0x3f);

    // 在中断控制器里使能这些中断 

    VIC0INTENABLE |= (0x3); // bit0: eint0~3, bit1: eint4~11  

//发生中断时硬件会把VIC0VECTADDR0赋给VIC0ADDRESS(第一组为VIC0ADDRESS,第二组为VIC1ADDRESS)

    VIC0VECTADDR0 = eint0_3_irq;  

    

//发生中断时硬件会把VIC0VECTADDR1赋给VIC0ADDRESS(第一组为VIC0ADDRESS,第二组为VIC1ADDRESS)

    VIC0VECTADDR1 = eint4_11_irq; 

    // 设置优先级 

}

//在中断向量控制器中有两个中断组,每一组有32个中断,在第一组中断发生时硬件会自动把VIC0VECTADDR

//寄存器的值给VIC0ADDRESS,在第二组中断发生时硬件会自动把VIC1VECTADDR寄存器的值给

//VIC1ADDRESS,只要提前把中断服务函数的地址赋给对应的寄存器,在发生中断的时候就会在do_irq函数中

//把VIC0ADDRESS或则VIC1ADDRESS值给函数指针执行就可以运行中断服务函数

void do_irq(void)

{

    int i = 0;

    void (*the_isr)(void);

    //第一组的32个中断对应为VIC0ADDRESS,第二组的32个中断对应为VIC1ADDRESS

    the_isr = VIC0ADDRESS; 

        

    // 2.1 分辨是哪个中断 

    // 2.2 调用它的处理函数     

    // 2.3 清中断     

    the_isr();

    

    EINT0PEND   = 0x3f;  // 清中断 

    VIC0ADDRESS = 0;

}

=====================================================================

Makefile文件:

CC      = arm-linux-gcc

LD      = arm-linux-ld

AR      = arm-linux-ar

OBJCOPY = arm-linux-objcopy

OBJDUMP = arm-linux-objdump

INCLUDEDIR     := $(shell pwd)/include

CFLAGS             := -Wall -Os -fno-builtin-printf 

CPPFLAGS        := -nostdinc -I$(INCLUDEDIR)

export     CC AR LD OBJCOPY OBJDUMP INCLUDEDIR CFLAGS CPPFLAGS 

objs := start.o sdram.o nand.o clock.o uart.o irq.o  main.o lib/libc.a

uart.bin: $(objs)

    ${LD} -Tuart.lds -o uart.elf $^

    ${OBJCOPY} -O binary -S uart.elf $@

    ${OBJDUMP} -D uart.elf > uart.dis

.PHONY : lib/libc.a

lib/libc.a:

    cd lib; make; cd ..

    

%.o:%.c

    ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

%.o:%.S

    ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

clean:

    make  clean -C lib

    rm -f uart.bin uart.elf uart.dis *.o

    

=====================================================================

uart.lds链接文件:

SECTIONS {

    . = 0x50000000;

    

    .text : {

            start.o

            clock.o

            sdram.o

            nand.o

            * (.text)

    }

    . = ALIGN(4);

    .rodata : {

            * (.rodata)

    }

    . = ALIGN(4);

    .data : {

            * (.data)

    }

    . = ALIGN(4);

    bss_start = .;

    .bss  : { *(.bss)  *(COMMON) }

    bss_end = .;

}

OK6410裸机之中断向量控制器


关键字:OK6410  裸机  中断  向量控制器 引用地址:OK6410裸机之中断向量控制器

上一篇:OK6410裸机之串口发送中断
下一篇:OK6410裸机之中断处理过程

推荐阅读最新更新时间:2024-03-16 16:15

msp430 按键 中断 轮询
msp430 数码管 key 中断 轮询 仿真见我的上传资源 /****************************************************************** * 实验名称:IO特性(MSP430F249) * * 实验说明: * 通设置系统主时钟(MCLK=8Mhz ) 、辅助时钟(ACLK=8Mhz )、 * 子系统时钟(SMCLK=8Mhz ) * 编译软件:Embedded Workbench 5.3 ******************************************************************/ #include MSP43
[单片机]
sdcc 中断使用中的一个问题
在sdcc中,中断处理函数使用关键字__interrupt标识,后面跟上中断号,8051中断号列表如下: Interrupt # Description Vector Address 0 External 0 0x0003 1 Timer 0 0x000b 2 External 1 0x0013 3 Timer 1 0x001b 4 Serial 0x0023 5 Timer 2 (8052) 0x002b 虽然看上去很简单,但是在使用过程中还出现了一个小问题,由于我将程序分成了两个部分,main.c和t
[单片机]
S3C6410 裸机DMA
/************************************************************************************************************* * 文件名: dma.c * 功能: S3C6410 DMA底层驱动函数 * 作者: cp1300@139.com * 创建时间: 2013年01月23日21:06 * 最后修改时间:2013年01月23日 * 详细: DMA控制器底层驱动 *****************************************************************
[单片机]
STM32学习笔记(2)外部中断
一、中断 1.什么是中断 操作系统需要管理外设,但是外设的速度远远低于CPU的速度,所以我们需要一种机制来弥补这种速度鸿沟,提高CPU的效率。 为此我们引入了中断机制,让外设在需要操作系统处理外设相关事件的时候,能够主动通知操作系统,即当CPU收到中断或者异常的事件时,打断操作系统和应用的正常执行,暂停执行当前的程序或任务,让操作系统完成外设的相关处理,在完成对这个事件的处理后,再恢复操作系统和应用的正常执行。 举个栗子,当你在读文章时忽然来了一个电话,你会先去接电话,等电话挂断后你又接着回来读文章,接电话这一过程就是执行中断。 正是由于中断机制,计算机系统才能有条不紊地“同时”完成多个任务,中断机制实质上帮助提高了并
[单片机]
STM32学习笔记(2)外部<font color='red'>中断</font>
PIC读书笔记4:中断函数注意事项
1:中断名称 例如Timer1中断: void __attribute__ ((interrupt)) _T1Interrupt (void) { //interrupt service roution code here.. } 函数名_T1Interrupt并不是随意选择的,她是中断向量表中预先定义的Timer1中断标志符,并且在连接器脚本中需要加载代码,加载的是 .gld 文件。 C30编译器中用到的__attribute__(())机制是用于说明特殊功能的C语言扩展功能。个人认为这种语法又长又难读。推荐使用include文(.h)件里的宏定义,这样可以大大提高代码的可读性。下面代码与上面功能一样。使用宏_ISR
[单片机]
STM32F103做从机SPI通信SPI3中断异常
在做AM335D板子与STM32F103使用SPI通信时,需要用到STM32的从机模式,所以特别对于ST的从机模式进行了研究,由于硬件上使用的是STM32F103的SPI3,所以过程中遇到了一点麻烦,这里记录一下过程,以备查阅: 使用SPI3通信时,从机时钟产生不了中断,经过查阅资料,是因为spi3的nss口与JTAG有共用引脚,所以配置错误会导致SPI3无法使用。需要注意以下两点就可以了: 1.开启GPIO时钟的同时,开启AFIO时钟,如下: RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE ); 2.关闭JTAG功能,
[单片机]
STM8的TIM4定时器1ms进入中断
TIM4 — 8位基本定时器 ● 8位自动装载可调整的预分频器,比例可选为1~128之间任意的2的幂 ● 时钟源: CPU时钟 ● 中断源: 1个溢出/更新中断 需要实现1ms进入一次中断,可作为系统定时器 TIM4初始化 void Tim4_Init(void) { TIM4_DeInit(); TIM4_TimeBaseInit(TIM4_PRESCALER_64,250-1);//64分频,向上计数,16M/64/250 = 1ms计数完了触发中断 TIM4_ARRPreloadConfig(ENABLE);//使能自动重装 TIM4_ITConfig(TIM4_IT_UPDATE , ENABLE);/
[单片机]
嵌入式系统离线测试
  引言   随着嵌入式系统的发展,迫切需要在嵌入式系统开发阶段对嵌入式系统进行离线测试与分析,以保证系统的软件应用程序、硬件具有兼容性、高可靠性和高可用性,迅速发现并准确定位系统中存在的问题。本文结合上海贝尔阿尔卡特股份有限公司开发的宽带交换系统,讨论离线单板硬件测试方法和系统测试方法。   离线单板硬件测试概述   在宽带交换机系统中,离线测试包括自检测试和一般的离线测试。自检测试是单板初始化完成后为了保证板子的正确运转进行的测试。它主要包括看门狗测试、快速硬件器件测试和下载通路测试。  快速硬件测试完成寄存器测试和单板上单个硬件设备测试,其中又包括许多测试项。如果某一测试项测试失败,整个测试就会停止直到看门狗超
[测试测量]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
发布文章
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved