- 论坛徽章:
- 0
|
本帖最后由 testh 于 2012-12-13 14:17 编辑
感谢版主支持。
先说下我的疑问吧,有很多,一个一个的说,先说第1个。
目前使用的是alsa-driver-1.0.24版。
目标为core/pcm_lib.c中的snd_pcm_update_hw_ptr0()这个函数。
这个函数在两个地方会被调用:
(1)在DMA的中断中会被调用。当DMA完成一次中断传输后,就会调用snd_pcm_period_elapsed(),然后再调用snd_pcm_update_hw_ptr0(),参数in_interrupt=1,是从中断中调用的;
(2)snd_pcm_update_hw_ptr()中调用,但参数in_interrupt=0,告诉snd_pcm_update_hw_ptr0()是在软件传输中调用的,非中断调用;
下图为借用的网上资料说明的alsa的buffer框架图。
资料链接地址为: http://blog.csdn.net/droidphone/article/details/7316061
结合此图,我理解的是图中的DMA Buffer即为 用户驱动中.pcm_new那里分配出来的dma缓冲区,开始我以为整个dma缓冲区就简单的映射为boundary,但是后来看代码越发的不对劲,现在理解为dma的缓冲区只能完整的映射为buffer那么大,就dma的size与buffer_size相同,这样的话,一个boundary里面就包含有若干个buffer,一个buffer即为一个dma缓冲区大小,它们之间的关系有点像虚拟内存的关系,实际的物理储存空间只有dma-buffer那么大,但是虚拟扩展出来的却有boundary那么大,因此在使用boundary的时候需要dma-buffer一步一步的向前移动。在一个buffer这么大的空间中又包含period个小块,一个小块表示dma中断一次完成的数据传输量,大小为period_size。
上面这段是我能够理解的,理解错误的地方烦请指针一下,下面是我结合snd_pcm_update_hw_ptr0()比较疑惑的地方:
(1)- jdelta = jiffies - runtime->hw_ptr_jiffies;
- if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) {
- delta = jdelta /
- (((runtime->period_size * HZ) / runtime->rate) + HZ/100);
- /* move new_hw_ptr according jiffies not pos variable */
- new_hw_ptr = old_hw_ptr;
- hw_base = delta;
- /* use loop to avoid checks for delta overflows */
- /* the delta value is small or zero in most cases */
- while (delta > 0) {
- new_hw_ptr += runtime->period_size;
- if (new_hw_ptr >= runtime->boundary)
- new_hw_ptr -= runtime->boundary;
- delta--;
- }
- /* align hw_base to buffer_size */
- hw_ptr_error(substream,
- "hw_ptr skipping! %s"
- "(pos=%ld, delta=%ld, period=%ld, "
- "jdelta=%lu/%lu/%lu, hw_ptr=%ld/%ld)\n",
- in_interrupt ? "[Q] " : "",
- (long)pos, (long)hdelta,
- (long)runtime->period_size, jdelta,
- ((hdelta * HZ) / runtime->rate), hw_base,
- (unsigned long)old_hw_ptr,
- (unsigned long)new_hw_ptr);
- /* reset values to proper state */
- delta = 0;
- hw_base = new_hw_ptr - (new_hw_ptr % runtime->buffer_size);
复制代码 这段是jiffies check的部分,我不太明白为什么使用 (hdelta * HZ) / runtime->rate) 的值 和 jdelta + HZ/100 的值来作比较。前者表示传输 hdelta这些数据所用的jiffies数,后者表示本次进入snd_pcm_update_hw_ptr0()和上次进入之间的时间差。根据这个推断,如果这个判断条件为真就认为硬件中断已经发生很多次了,通过他们的判断可以判断出来吗? 或者是我对(hdelta * HZ) / runtime->rate)的含义理解有误?另外不太明白为什么 jdelta还要再单独加上 HZ/100,是作为一个额外的时间补偿吗?
|
|