S3C2440定时器4中断测试程序

转自:http://blog.sina.com.cn/s/blog_63e0ea870100v06z.html

__irq为一个标识,用来表示一个函数是否为中断函数。对于不同的编译器,__irq在函数名中的位置不一样,例如:
ADS编译器中 : void __irq IRQ_Eint0(void);
Keil编译器中 : void IRQ_Eint0(void) __irq;
但是其意义一样,它所完成的任务是标识该函数为中断函数,在编译器编译是调用此函数时,先保护函数入口现场,然后执行中断函数,函数执行完毕,恢复中断现场,这整个过程不需要用户重新编写代码来完成,由编译器自动完成。因而这也给不具备中断嵌套功能的ARM系统带来了问题,若使用 __irq 时有中断嵌套产生,这现场保护就会混乱。中断嵌套处理可以自己编写中断入口现场保护代码,并不使用 __irq 标识符号。(小呆:具体如何编写可以嵌套的中断这里暂时不做研究。
总结如下
1、若不想自己编写中断入口现场保护代码,而且使用中无中断嵌套,在中断函数中用 __irq 来标识我们的中断函数,否则出错;
2、若程序中要使用中断嵌套,对于无中断嵌套功能的ARM来说,一定要自己编写中断入口现场保护代码,而且不能用 __irq 标识我们的中断函数,否则出错。
__irq关键字
在ADS编译器中,“__irq”专门用来声明IRQ中断服务程序,如果用“__irq”来声明一个函数,那么该函数表示一个IRQ中断服务程序,编译器便会自动在该函数内部增加中断现场保护的代码。同样一个函数,如果将关键字“__irq”去掉,那么编译器便不会增加现场保护的代码,而只是作为一个普通函数来处理。
现在大家应该对“__irq”关键字有了一定的了解,那么,是不是所有的IRQ中断服务程序都需要使用“__irq”关键字声明呢?其实,这取决于获取“中断服务程序地址”的方法:
如果在执行中断服务函数之前没有对中断现场进行保护,那么中断服务函数必须要使用“__irq”关键字进行声明。例如,在0x0000 0018处执行指令“LDR PC, [PC, #-0xff0]”,此时对应的中断服务函数必须要使用“__irq”关键字进行声明;如果在执行中断服务函数之前已经对中断现场进行了保护,那么中断服务函数不能使用“__irq”关键字进行声明。

 

//=========================================
// NAME: main.c
// DESC: 内部定时器4LED灯延时
//=========================================

#define U32 unsigned int


#define _ISR_STARTADDRESS 0x33ffff00

#define pISR_TIMER4     (*(unsigned *)(_ISR_STARTADDRESS+0x58))

#define rSRCPND      (*(volatile unsigned *)0x4a000000)  //Interrupt request status 源挂起寄存器
#define rINTMSK      (*(volatile unsigned *)0x4a000008)  //Interrupt mask control   中断屏蔽寄存器
#define rINTPND      (*(volatile unsigned *)0x4a000010)  //Interrupt request status 中断挂起寄存器

#define rTCFG0    (*(volatile unsigned *)0x51000000)  //Timer 0 configuration
#define rTCFG1    (*(volatile unsigned *)0x51000004)  //Timer 1 configuration
#define rTCON     (*(volatile unsigned *)0x51000008)  //Timer control
#define rTCNTB4   (*(volatile unsigned *)0x5100003c)  //Timer count buffer 4

#define rGPBCON      (*(volatile unsigned *)0x56000010)  //Port B control
#define rGPBDAT      (*(volatile unsigned *)0x56000014)  //Port B data
#define rGPBUP       (*(volatile unsigned *)0x56000018)  //Pull-up control B

void led_init(void)
{
 //板载LED为GPB[5:8]
 rGPBCON = (rGPBCON & ~(0xff<<10)) | (0x55<<10);  //rGPBCON为01 配置为输出
 rGPBUP  = rGPBUP  | (0xf<<5); //rGPBUP为1   禁止上拉
 rGPBDAT = rGPBDAT | (0xf<<5); //LED灯全关
}

void led_display(unsigned char data)
{
 //0x0全灭 0xf全亮 0x01 0x02 0x04 0x80 各自灯亮
 rGPBDAT = (rGPBDAT & ~(0xf<<5)) | ((~data) <<5);
}

void timer4_init(void)
{
 rSRCPND = rSRCPND | (0x1<<14);   //清空定时器4源请求
    rINTPND = rINTPND | (0x1<<14);    //清空定时器4中断请求
    rINTMSK =  rINTMSK & ~(0x1<<14);//打开定时器4中断    
    //定时器配制寄存器0 
    //定时器输入时钟频率 = PCLK / {预分频值+1} / {分频值}
    //{预分频值} = 0~255 {分频值} = 2, 4, 8, 16 
    //25KHz:50MHz/(250*8)=50MHz/(2000)
    rTCFG0 = (rTCFG0 & ~(0xff<<8)) | (249<<8); // prescaler1:249
    rTCFG1 = (rTCFG1 & ~(0xf<<16)) | (0x2<<16); //divider:8,0b0010
    
    rTCNTB4 = 25000;  //让定时器4每隔1秒中断一次 25000=1*25000
    rTCON = (rTCON & ~(0x7<<20)) | (0x7<<20); //自动重载、手动更新、启动定时器4
    rTCON = (rTCON & ~(0x2<<20));    //关闭手动更新
}

void __irq timer4_ISR(void)
{
 static int count;
 rSRCPND = rSRCPND | (0x1<<14);
 rINTPND = rINTPND | (0x1<<14);
 //每隔0.5秒LED灯亮一次
 if (count == 0)
 {
  led_display(0xf);       //LED亮
  count = 1;
 }
 else if (count == 1)
 {
    led_display(0x0);       //LED灭
    count = 0;
 
}

void Main(void)
{
 led_init();
 timer4_init();
 
    pISR_TIMER4 = (U32)timer4_ISR;  
 while(1); 
}

-------------------------------------

pISR_UNDEF=(unsigned)HaltUndef;

任何地址都可以看作变量的指针. pISR_UNDEF就相当于一个指针变量. pISR_UNDEF=(unsigned)HaltUndef; 等于把函数HaltUndef的地址存到这个指针变量里. 也就是说_ISR_STARTADDRESS+0x4这个地址里存放着 HaltUndef的地址. 这段代码的目的是给中断函数赋值. 当发生中断时,系统会去pISR_UNDEF定义的地址里取出中断函数的地址也就是HaltUndef的地址,然后执行. 就相当于当发生中断时,执行HaltUndef函数. 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
2022 / 01/ 30: 新版esptool 刷micropython固件指令不是 esptool.py cmd... 而是 esptool cmd... 即可;另外rshell 在 >= python 3.10 的时候出错解决方法可以查看:  已于2022年发布的: 第二章:修复rshell在python3.10出错 免费内容: https://edu.csdn.net/course/detail/29666 micropython语法和python3一样,编写起来非常方便。如果你快速入门单片机玩物联网而且像轻松实现各种功能,那绝力推荐使用micropython。方便易懂易学。 同时如果你懂C语音,也可以用C写好函数并编译进micropython固件里然后进入micropython调用(非必须)。 能通过WIFI联网(2.1章),也能通过sim卡使用2G/3G/4G/5G联网(4.5章)。 为实现语音控制,本教程会教大家使用tensorflow利用神经网络训练自己的语音模型并应用。为实现通过网页控制,本教程会教大家linux(debian10 nginx->uwsgi->python3->postgresql)网站前后台入门。为记录单片机传输过来的数据, 本教程会教大家入门数据库。  本教程会通过通俗易懂的比喻来讲解各种原理与思路,并手把手编写程序来实现各项功能。 本教程micropython版本是 2019年6月发布的1.11; 更多内容请看视频列表。  学习这门课程之前你需要至少掌握: 1: python3基础(变量, 循环, 函数, 常用库, 常用方法)。 本视频使用到的零件与淘宝上大致价格:     1: 超声波传感器(3)     2: MAX9814麦克风放大模块(8)     3: DHT22(15)     4: LED(0.1)     5: 8路5V低电平触发继电器(12)     6: HX1838红外接收模块(2)     7:红外发射管(0.1),HX1838红外接收板(1)     other: 电表, 排线, 面包板(2)*2,ESP32(28)  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值