Chinaunix首页 | 论坛 | 博客
  • 博客访问: 535853
  • 博文数量: 86
  • 博客积分: 1076
  • 博客等级: 准尉
  • 技术积分: 1018
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-02 19:15
文章分类

全部博文(86)

文章存档

2013年(15)

2012年(69)

2011年(2)

分类: LINUX

2012-05-14 19:03:52

     今天调试音频应用程序的时候,出了个很诡异的问题,之前的环境是音频ALSA和SD-WIFI一起工作,现在产品样板回来了,换成了音频ALSA和SPI转USB的WIFI,本以为不需要任何改动,谁知道一放音乐只会响那么一声内核就死掉了,一直重复刚才播出的那一小段声音。
     刚一开始,真没想出来什么问题,怀疑过应用程序死锁,怀疑过电压不稳定,毕竟是新的板子。后来将内核恢复到之前的版本(不带SPI的),就是可以的。那问题肯定出在SPI上,是电压吗?还是别的?
     经同事指点,问题很可能出在DMA的中断上面。我们的SoC总共有两个DMA控制器,各8通道,之前SD和ALSA(I2S的控制器DMA中断)分别挂载DMA1和DMA2上面,而SPI和I2S一同挂在DMA2上,也就是申请DMA中断的时候,是同一个中断号,所以这个就要涉及到中断申请的注意点了。
    有关中断申请的基础知识。


  1. IRQ注册函数:(头文件在:<include/linux/interrupt.h>)

  2. int request_irq(unsigned int irqirq_handler_t handler, unsigned long flags, const char *dev_name, void *dev_id);


     其中:

  •  irq:要申请的硬件中断号
  •  handler:向系统登记的中断处理函数(是个回调函数,中断发生时系统调用它)
  •  dev_id:设备的ID
  •  flags:中断处理的属性,可以指定中断的触发方式以及处理方式(着重处理方面)
    • 设置为IRQF_DISABLED:表明中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有的中断,慢速处理程序则不会屏蔽其他设备的驱动。
    • 设置为IRQF_SHARED:表明多个设备共享中断,dev_id在中断共享的时候会用到,一般设置为这个设备的结构体或者NULL。

        (对于触发方式,可以指定为:IRQ_TRIGGER_RISING、IRQ_TRIGGER_FALLING、IRQ_TRIGGER_HIGH、IRQ_TRIGGER_LOW)

  •  dev_name定义传递给request_irq的字符串,用来在/proe/interrupts中显示中断拥有者

       IRQ释放函数:

             

  1. void free_irq(unsigned int irq,void *dev_id);(一般在退出设备或关闭设备时调用)


       打开一个IRQ:


  1. void enable_irq(unsigned int irq);(允许该IRQ产生中断)


       关闭一个IRQ:

  1. void disable_irq(unsigned int irq);(禁止该IRQ产生中断)

 

     那么,很自然的去查了下SPI申请的DMA中断,果然那边申请的时候设置的参数为IRQF_DISABLED。所以将其改为共享中断,然后再各自的中断函数当中通过读取DMA的中断标志位,去判断是否是自己模块的中断,如果不是,则立即返回IRQ_HANDLED。


 

阅读(1601) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

JGFNTU2013-05-03 21:38:56

中断到来时,会遍历执行共享此中断的所有中断处理程序,直到某一函数返回IRQ_HANDLED

JGFNTU2013-05-03 21:36:12

勘误:“所以将其改为共享中断,然后再各自的中断函数当中通过读取DMA的中断标志位,去判断是否是自己模块的中断,如果不是,则立即返回IRQ_HANDLED。”
应该改为“。。。如果不是,则立即返回IRQ_NONE”