Zynq cap 调试总结
遇到的问题和解决方法
1、ramdisk 启动之后,必须先ls一下,才能open文件。
问题定位方法:gdb,显示栈。
问题定位:open函数会调用到内核中的kunmap函数,而kumap函数不能在中断上下文
中调用(在kunmap函数中有BUG_ON(in_interrupt());),而我们filp_open正是在中断
上下文中调用的,因此出错。
解决方法:启动内核线程,来open文件。
2、结构体的地址被莫名其妙地修改了。
问题定位方法:打印
问题定位:结构体的地址保存在一个局部变量中(在内核栈),当在内核中定义个大的局部
变量时,就有可能把内核栈堆满,从而冲掉到栈上其它变量。
解决方法:将数组换成指针。
总结:内核栈有限,不要过分的去用,这是常识。
3、内核死在synchronize_irq 函数中。
问题定位方法:gdb,打印栈。
问题定位:synchronize_irq会被disalbe_irq调用,通常情况下会在驱动注册的中断处理
函数中调用disalbe_irq 来使中断处理能嵌套。问题出在,在synchronize_irq 中会判断
IRQD_IRQ_INPROGRESS标志,而IRQD_IRQ_INPROGRESS会在调用驱动注册的中断处理
函数之前的中断处理流程中(handle_irq_event函数中)设置,因此造成死锁。
解决方法:把disalbe_irq 换成disable_irq_nosync。
总结:以后还是使用disable_irq_nosync 比较靠谱。
4、timer 中断
问题描述:想在内核中写一个timer 的驱动,中断通过setup_irq 来建立,一打开timer
的中断,内核就死掉。
问题定位:代码逻辑上捋中断处理流程,发现在zynq平台,这个timer的中断处理和普通
的驱动中断处理不相同。其中断处理必须在arch
/arm/include/asm/entry-macro-multi.S中加入,不能使用setup_irq 函数来建立。当
然不要忘记在init 函数中,使能中断。
问题解决:在arch/arm/include/asm/entry-macro-multi.S加入如下代码:
36 ____test_for_gtirq r0, r6, r5, lr
37 ____movne___r0, sp
38 ____adrne___lr, BSYM(1b)
39 ____bne_internal_timer2_int
其中test_for_gtirq 为:
76 ____.macro test_for_gtirq, irqnr, irqstat, base, tmp
77 ____bic_\irqnr, \irqstat, #0x1c00
78 ____mov ____\tmp, #0
79 ____cmp_\irqnr, #27
80 ____moveq___\tmp, #1
81 ____streq___\irqstat, [\base, #GIC_CPU_EOI]
82 ____cmp_\tmp, #0
5、记住一点,现在的串口驱动都是使用的定时器轮寻收发数据,而非中断方式。
6、内核启动死在挂载系统时
问题定位:用的是ramdisk,Uboot会把zImage和ramdisk.image.gz分别加载到内存的不同地址,当我们某模块直接编译到内核中时,在内核运行时,有些全局变量会占用ramdisk在内存的空间,冲掉的ramdisk自然起不来文件系统。
备注:虽然单独观察zimage的大小并没有增加多少,但是BSS段在二进制文件中没有占据空间,即磁盘上二进制文件的大小比较小,但是加载到内存后,需要为BSS段分配内存空间。
阅读(3063) | 评论(0) | 转发(0) |