jz2440的外部中断(按键+串口)

代码进行模块化编程

启动文件

start.S
.text
.global _start

_start:
   b  Reset
@ 0x04: 未定义指令中止模式的向量地址
HandleUndef:
    b   HandleUndef
 
@ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
HandleSWI:
    b   HandleSWI

@ 0x0c: 指令预取终止导致的异常的向量地址
HandlePrefetchAbort:
    b   HandlePrefetchAbort

@ 0x10: 数据访问终止导致的异常的向量地址
HandleDataAbort:
    b   HandleDataAbort

@ 0x14: 保留
HandleNotUsed:
    b   HandleNotUsed

@ 0x18: 中断模式的向量地址
    b    HandleIRQ  

@ 0x1c: 快中断模式的向量地址
HandleFIQ:
    b   HandleFIQ

Reset:
    /* 关闭看门狗 */
    ldr r0, =0x53000000
    ldr r1, =0
    str r1, [r0]

    /* 设置MPLL, FCLK : HCLK : PCLK = 400m : 100m : 50m */
    /* LOCKTIME(0x4C000000) = 0xFFFFFFFF */
    ldr r0, =0x4C000000
    ldr r1, =0xFFFFFFFF
    str r1, [r0]

    /* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8  */
    ldr r0, =0x4C000014
    ldr r1, =0x5
    str r1, [r0]

    /* 设置CPU工作于异步模式 */
    mrc p15,0,r0,c1,c0,0
    orr r0,r0,#0xc0000000   //R1_nF:OR:R1_iA
    mcr p15,0,r0,c1,c0,0

    /* 设置MPLLCON(0x4C000004) = (92<<12)|(1<<4)|(1<<0)
     *  m = MDIV+8 = 92+8=100
     *  p = PDIV+2 = 1+2 = 3
     *  s = SDIV = 1
     *  FCLK = 2*m*Fin/(p*2^s) = 2*100*12/(3*2^1)=400M
     */
    ldr r0, =0x4C000004
    ldr r1, =(92<<12)|(1<<4)|(1<<0)
    str r1, [r0]

    /* 一旦设置PLL, 就会锁定lock time直到PLL输出稳定
     * 然后CPU工作于新的频率FCLK
     */
    
    

    /* 设置内存: sp 栈 */
    /* 分辨是nor/nand启动
     * 写0到0地址, 再读出来
     * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
     * 否则就是nor启动
     */
    mov r1, #0
    ldr r0, [r1] /* 读出原来的值备份 */
    str r1, [r1] /* 0->[0] */
    ldr r2, [r1] /* r2=[0] */
    cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */
    ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
    moveq sp, #4096  /* nand启动 */
    streq r0, [r1]   /* 恢复原来的值 */
    
    
    bl  uart0_init
    
    mrs r0, cpsr         /* 读出cpsr */
    bic r0, r0, #0xf     /* 修改M4-M0为0b10000, 进入usr模式 */
    bic r0, r0, #(1<<7)  /* 清除I位, 使能中断 */
    msr cpsr, r0
    
    ldr lr, =halt_loop      @ 设置返回地址
    ldr pc, =main           @ 调用main函数
halt_loop:
    b   halt_loop
    
HandleIRQ :
       ldr  sp,=4096
       sub  lr ,lr,#4   /*计算返回地址*/
       stmdb   sp!,    { r0-r12,lr } /*保存使用的寄存器*/
         ldr  lr ,=return_halt
       ldr  pc ,=handle_irq_c   /*调用中断服务程序*/
return_halt:
         ldmia   sp!,    { r0-r12,pc }^  /*^表示将spsr的值复制到cpsr */   

makefile

objs:=start.o  uart.o interrupt.o  init.o  main.o
key.bin:$(objs)
    arm-linux-ld   -Ttext   0x00000000  -o  key_elf  $^
    arm-linux-objcopy  -O  binary -S   key_elf  $@
    arm-linux-objdump  -D  -m  arm     key_elf>key.dis
%.o:%.c
    arm-linux-gcc  -Wall -O2  -c  -o   $@   $<
%.o:%.S
    arm-linux-gcc  -Wall  -O2 -c  -o   $@  $<
.PHONY:clean
clean:
    rm  -f  timer_elf   key.bin   key.dis  *.o

 外部中断初始化代码

init.c

#include "s3c2440_soc.h"#include"s3c24xx.h"


#define GPF4_out    (1<<(4*2))
#define GPF5_out    (1<<(5*2))
#define GPF6_out    (1<<(6*2))

void led_init()
{
     GPFCON&=~(GPF4_out| GPF5_out|GPF6_out);
     GPFCON|=(GPF4_out| GPF5_out|GPF6_out);
}
void  init_irq () /*中断的初始化*/
{
     /*将引脚设置为输出模式*/
     GPFCON&=~(3<<0|3<<4);
     GPFCON|=(2<<0|2<<4);
    
     GPGCON&=~(3<<6);
     GPGCON|=(2<<6);
    
     // 对于EINT11,需要在EINTMASK寄存器中使能它
     EINTMASK &= ~(1<<11);
     //设定优先级
     PRIORITY = (PRIORITY & ((~0x01) | (0x3<<7))) | (0x0 << 7) ;
     //进行使能
     INTMSK&=~(1<<0|1<<2|1<<5);
         
}

串口初始化

uart.c
#include "s3c2440_soc.h"


/* 115200,8n1 */
void uart0_init()
{
    /* 设置引脚用于串口 */
    /* GPH2,3用于TxD0, RxD0 */
    GPHCON &= ~((3<<4) | (3<<6));
    GPHCON |= ((2<<4) | (2<<6));

    GPHUP &= ~((1<<2) | (1<<3));  /* 使能内部上拉 */
    

    /* 设置波特率 */
    /* UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1
     *  UART clock = 50M
     *  UBRDIVn = (int)( 50000000 / ( 115200 x 16) ) –1 = 26
     */
    UCON0 = 0x00000005; /* PCLK,中断/查询模式 */
    UBRDIV0 = 26;

    /* 设置数据格式 */
    ULCON0 = 0x00000003; /* 8n1: 8个数据位, 无较验位, 1个停止位 */

    /*  */

}

int putchar(int c)
{
    /* UTRSTAT0 */
    /* UTXH0 */

    while (!(UTRSTAT0 & (1<<2)));
    UTXH0 = (unsigned char)c;
    
}

int getchar(void)
{
    while (!(UTRSTAT0 & (1<<0)));
    return URXH0;
}

int puts(const char *s)
{
    while (*s)
    {
        putchar(*s);
        s++;
    }
}

中断代码

interrupt.c

#include "s3c2440_soc.h"
#include "uart.h"
void handle_irq_c()
{
    unsigned long oft = INTOFFSET;
    //判断的中断源
    switch( oft)
    {  
        case 0:
        {
             GPFDAT |= (0x7<<4);  // 所有LED熄灭
             GPFDAT &= ~(1<<4);   // LED1点亮
             puts("hello world\n\r");
             break;
         }
         case 2:
         {   
                GPFDAT |= (0x7<<4); // 所有LED熄灭  
                GPFDAT &= ~(1<<5);  // LED2点亮
                break;
         }
         case 5:
         {  
                 GPFDAT |= (0x7<<4); // 所有LED熄灭
                 GPFDAT &= ~(1<<6); // LED4点亮               
                 break;                
        }
        default: break;
    }
    
    //清中断
    if( oft == 5 )
        EINTPEND = (1<<11);   // EINT8_23合用IRQ5
 
    SRCPND=1<<oft;
    INTPND=1<<oft;

}

主函数


#include "s3c2440_soc.h"
#include "uart.h"
#include "init.h"
int main(void)
{
    led_init();
    init_irq ();
    while(1);
    return 0;
}

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值