title: 16-驱动调试(六)利用中断打印
date: 2019/1/15 23:35:14
toc: true
---
原理
这一章节也没啥新知识,原理就是利用系统时钟的中断,去打印一些信息.
在进入中断之前,会保存现场,包括
LR
,可以打印这个LR
就能看到,定时器中断是普通中断,保存现场的时候已经将返回地址+4到LR寄存器,这个是硬件决定的,所以我们查找这个返回地址的时候减去4.
保护现场
- 硬件自动保存
- 保存当前的
cpsr
到中断下的scpsr
- 保存返回地址到LR寄存器,(某种异常模式的LR等于被中断的下一条指令的地址)它有可能是PC + 4有可能是PC + 8,到底是那种取决于不同的情况
- 保存当前的
软件需要做的
stmdb sp!, {r0-r12, lr}
保存
R0~R12
寄存器保存
LR
寄存器,注意这个保存之后是退出中断的返回地址,因为ARM
架构的原因,不同的中断异常有不同的返回地址,所以需要对这个LR
先进行一些运算再保存.偏移地址如下:举个例子比如UDEF
异常,只需要直接复制,而FIQ
则需要保存LR+4
BL MOV PC, R14 SWI MOVS PC, R14_svc UDEF MOVS PC, R14_und FIQ SUBS PC, R14_fiq, #4 IRQ SUBS PC, R14_irq, #4 PABT SUBS PC, R14_abt, #4 DABT SUBS PC, R14_abt, #8
死循环判断流程
记录pid,如果pid一直是同一个并且大于10s,打印这个pid和LR
asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
struct irq_desc *desc = irq_desc + irq;
/*
* Some hardware gives randomly wrong interrupts. Rather
* than crashing, do something sensible.
*/
if (irq >= NR_IRQS)
desc = &bad_irq_desc;
#ifdef 1
static pid_t pre_pid; //进程号
static int cnt=0; //计数值
if(irq==30) //判断irq中断号,是否等于系统时钟
{
if(pre_pid==current->pid)
{
cnt++;
}
else
{
cnt=0;
pre_pid=current->pid;
}
if(cnt==10*HZ) //超时10s
{
cnt=0;
printk("s3c2410_timer_interrupt : pid = %d, task_name = %s\n",current->pid,current->comm);
printk("pc = %08x\n",regs->ARM_pc);
}
}
#endif
irq_enter();
desc_handle_irq(irq, desc);
/* AT91 specific workaround */
irq_finish(irq);
irq_exit();
set_irq_regs(old_regs);
}
代码简单解释
中断号是30,在
include\asm-arm\arch-s3c2410\Irqs.h
,或者使用cat /proc/interrupt
查看current->pid:
当前进程的PID号current->com
表示当前进程的nameHZ
也是一个宏,代表每S的频率,比如每隔10ms加1,那么HZ就等于100参数的
regs
表示原有的寄存器,用他来查看进来之前普通函数的lr