当前位置:首页 > > 充电吧
[导读]如果想弄懂看门狗定时器中断,要掌握下面两个知识点:1 懂寄存器Cortex A9采用的是ARM官方规定的中断处理机制有两大类寄存器决定了中断工作状态1) exynos 4412 特有的寄存器(在第26

如果想弄懂看门狗定时器中断,要掌握下面两个知识点:

1 懂寄存器

Cortex A9采用的是ARM官方规定的中断处理机制

有两大类寄存器决定了中断工作状态

1) exynos 4412 特有的寄存器(在第26章)

2) Cortex A9 规定的工作寄存器(在第9章和第10章)

2 懂中断处理过程

1) Arm启动先执行一段启动代码(start.S),这段代码是用汇编写的

2) 然后,汇编代码再执行到c的main函数

start.S讲解

.text

.global _start @@@@ _start 是一个全局标号 (表示在其他函数可以调用_start)

_start: @@@@ 通常被指定为0x0000 0000地址

b reset @@@@ 此段代码放在0x0000 0000地址处 ,命令功能是跳转到reset处去执行

ldr pc,_undefined_instruction

ldr pc,_software_interrupt

ldr pc,_prefetch_abort

ldr pc,_data_abort

ldr pc,_not_used

ldr pc,_irq @@@@ 将_irq地址处的指令地址给PC ,相当于一条跳转命令,这条指令回放在0x0000 0018处

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 @@@@ .word 是一条伪指令,相当于定义一个4字节的变量_irq,值为irq_handler

@@@@ 等价于 int _irq = irq_handler

_fiq: .word _fiq

@@@@ 伪指令:不是一条实际的汇编指令,变量定义,宏定义,数组定义

reset:

@@@@ 初始化 协处理器

ldr r0,=0x40008000

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

@@@@ 设置cpsr的值,为0xd3

mrs r0,cpsr

bic r0,r0,#0x1f

orr r0,r0,#0xd3 @@@@ 0xd3 1101 0011 禁止FIQ, IRQ, 处于ARM状态 ,模式为管理模式 SVC

msr cpsr,r0 @ Enable svc mode of cpu

init_stack: @@@@初始化堆栈, svc, irq, fiq.... 每种模式的堆栈大小为512字节

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 @@@@ 跳转到main函数,不会回来了

.align 4

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

/**** irq_handler ****/

irq_handler: @@@@ 一旦IRQ中断会跳转到这

sub lr,lr,#4

stmfd sp!,{r0-r12,lr} @@@@ 将r0-r12, lr寄存器入栈,,,,保护现场

bl do_irq @@@@ 跳转到中断服务程序do_irq, 执行完再回来

ldmfd sp!,{r0-r12,pc}^ @@@@ 将栈中数据出栈,给r0-r12, lr寄存器,,,,恢复现场

stacktop: .word stack+4*512

.data

stack: .space 4*512

//////////////////////////////////下面是C代码//////////////////////////////

void do_irq(void ) //C语言的中断服务程序代码,这段程序是程序员需要重点完成的

{

int irq_num;

irq_num = (CPU0.ICCIAR & 0x1FF);

switch (irq_num) {

case 58: //turn on LED2; turn off LED3

GPX2.GPX2DAT = 0x1 << 7;

GPX1.GPX1DAT &= ~0x1;

printf("IRQ interrupt !! turn on LED2; turn off LED3n");

//Clear Pend

EXT_INT41_PEND |= 0x1 << 2;

ICDICPR.ICDICPR1 |= 0x1 << 26;

break;

}

// End of interrupt

CPU0.ICCEOIR = (CPU0.ICCEOIR & ~(0x1FF)) | irq_num;

}

int main(void)

{

//.....

}

二:GIC控制器初始化, ARM提供(Generic Interrupt Controller)

////////4412 的中断控制其部分,采用了ARM公司的GIC中断控制器架构

GIC中断共152个, 分为三部分

SGI 16个 Software Generated Interrupt (SGI)

PPI 8个 Private Peripheral Interrupt (PPI)

SPI 128 Shared Peripheral Interrupt (SPI)

每个中断都被编了一个ID

可以根据GIC Interrupt Table 来查找

SPI Port No SPI中断源编号

ID 总的中断源编号

exynos4412 已经连接了两个外部中断

中断源 SPI Port No ID

EINT[9] 25 57

GIC 设置流程:

1 设置GIC中的某个SPI 中断允许还是禁止

////////////////

ICDISER(n) ICDISER1, ICDISER2, ICDISER3, ICDISER4

SPI中断共128个,分成了4组

ICDISER1 ---- > 控制 0-31 (第1组) (控制此中断编号是否可以产生中断 1 允许,0 禁止)

ICDISER2 ---- > 控制 32-63 (第2组)

ICDISER3 ---- > 控制 64-95 (第3组)

ICDISER4 ---- > 控制 96-127 (第4组)

INT9 ---- 25号 INT10 ---- 26号

ICDISER1 (GIC的通道号0-31) 如果某一位为1 那么中断允许

允许INT9 产生中断

ICDISER.ICDISER1 |= (0x1 << 25); //中断使能寄存器

允许INT10 产生中断

ICDISER.ICDISER1 |= (0x1 << 26); //中断使能寄存器

练习:

允许WDT产生中断(43)

ICDISER2 |= 0x1 << 11; (43 % 32)

2 设置 某个CPU是否允许响应中断(默认情况,4个CPU都不响应中断)

ICCICR: 对应于每个CPU,都有一个ICCICR,他的功能是 控制这个CPU的总的中断开关,1表示这个CPU响应中断, 0表示不响应中断

CPU0.ICCICR |= 0x1; (把它值1,表明CPU0响应中断)

3 设置 某个CPU响应的中断的最高优先级

CPU0.ICCPMR = 0xFF; //上面允许了中断,ICCPMR中断优先级低于设置值的中断允许进入 0xFF最高,如果设置成0,

4 设置 中断产生时是否影响中断标志位, 具体中断标志在哪参照ICDICPR

ICDDCR

ICDDCR = 1; //总的中断标志置位允许位

5 设置某个中断是由哪个CPU来响应

ICDIPTR 有很多组:4个中断为1组(中断ID号最大159, 160 / 4 = 40, ICDIPTR 有40个 )

如果设置EINT9由CPU0来响应(EINT9 是57号,所以在编号14的寄存器中(56, 57, 58, 59))

ICDIPTR.ICDIPTR14 = 0x00000100; //表示总中断号为 57的中断由CPU0来处理

如果设置EINT9由CPU1来响应

ICDIPTR.ICDIPTR14 = 0x00000200; //表示总中断号为 57的中断由CPU1来处理

如果设置EINT9由CPU2来响应

ICDIPTR.ICDIPTR14 = 0x00000400; //表示总中断号为 57的中断由CPU2来处理

如果设置EINT9由CPU3来响应

ICDIPTR.ICDIPTR14 = 0x00000800; //表示总中断号为 57的中断由CPU3来处理

如果设置EINT9由CPU4来响应

ICDIPTR.ICDIPTR14 = 0x00001000; //表示总中断号为 57的中断由CPU4来处理

//上面的寄存器设置我的中断由哪个CPU来处理

ICDIPTR 有很多(设置某个中断由哪个CPU来执行)

ICDIPTR1 ICDIPTR1 ICDIPTR2 ICDIPTR3 ICDIPTR4 ICDIPTR5........

有 160 / 4 个, 共40个, 每个寄存器控制4个中断

每个寄存器是32位的,8位为1组, 每组代表某种中断由哪个CPU来执行

0000 0001 表示由 CPU0来处理

0000 0010 表示由 CPU1来处理

0000 0100 表示由 CPU2来处理

0000 1000 表示由 CPU3来处理

0001 0000 表示由 CPU4来处理

0010 0000 表示由 CPU5来处理

0100 0000 表示由 CPU6来处理

1000 0000 表示由 CPU7来处理

一个32位寄存器可以分四组

ICDIPTR.ICDIPTR14 = 0x01010101; //编号56,57,58,59四个中断,由CPU0来处理

14 是 总的中断编号 / 4

如果设置EINT9 (57) 中断优先级10

ICDIPR14 = 0x00000A00;

下面是看门狗定时器中断示例

#include

* @brief IRQ Interrupt Service Routine program body

* @param[in] None

* @return None

int flag = 0;

void do_irq(void)

{

int irq_num;

irq_num = (CPU0.ICCIAR & 0x1FF); //获取中断编号

printf("n ******* WDT interrupt !!********n");

if(flag == 0)

{

//点亮

flag = 1;

}

else

{

//点灭

flag = 0;

}

//换成点亮或点灭LED3 GPX1_0

WDT.WTCLRINT = 1; //清exynos4412中断标志位

// End of interrupt

CPU0.ICCEOIR = (CPU0.ICCEOIR & ~(0x1FF)) | irq_num; //清cpu0中断标志位

}

void wdt_init()

{

WDT.WTCNT = 6000; //initial value ,, 延时大概有两秒

WDT.WTDAT = 6000; //initial value ,, 延时大概有两秒

WDT.WTCON = 0xff<<8 | 1<<5 | 3<<3 | 1<<2 ;

}

void mydelay_ms(int time)

{

int i, j;

while(time--)

{

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

for (j = 0; j < 514; j++);

}

}

int main(void)

{

/*

* GIC interrupt controller:

* */

// Enables the corresponding interrupt SPI43, WDT

ICDISER.ICDISER2 |= 1<<11; //ICDISER2:spi 32[bit0] ~ 63[bit31], 43 - 32 = [bit11]

CPU0.ICCICR |= 0x1; //Global enable for signaling of interrupts

CPU0.ICCPMR = 0xFF; //The priority mask level.Priority filter. threshold

ICDDCR = 1; //Bit1: GIC monitors the peripheral interrupt signals and

// forwards pending interrupts to the CPU interfaces2

//ICDIPTR18:SPI40~SPI43; SPI43 interrupts are sent to processor 0

ICDIPTR.ICDIPTR18 = (ICDIPTR.ICDIPTR18 & ~(0xFF<<24)) | 1<<24;

wdt_init();

printf("n****************WDT Interrupt test!!***************n");

while(1)

{

mydelay_ms(200);

mydelay_ms(200);

printf("working...n");

}

return 0;

}

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭