BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / embedded-system / #7412同步于 2010/1/22
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Embedded_System机器人发帖

2440DMA求教!

nyp1984
2010/1/22镜像同步2 回复
小弟在把网上的uda1341驱动改成了adv212的驱动,adv212用的是DCS dma mode,但在2440的dma部分遇到了问题(2.6.29的内核): 1、在分配dma buffer时如果小于我请求read的大小就会不停的请求中断; 2、dma完成一buffer传输后再次enqueue时出错,出错原因是等待load buffer timeout; 3、我看到网上总有人说dma的驱动有问题,还说物理通道和映射通道什么的,但在看源码后还是不能理解,求正解;如果有需要改正的bug望告知小弟。 以上问题我都在debug的情况下走了遍源代码,会出现这样的问题完全符合设计者的思路,但关键是我不能理解…… 如果有用过adv202 or adv212+2440 的有更好的数据传输方法也望赐教。 这是我第一次在这里发请教贴,希望能感受到byr的热情,谢谢~ 关于dma初始化部分的源代码: static int __init adv212_init_dma(audio_stream_t * s) { int ret ; int dmacount; enum s3c2410_dmasrc source; int hwcfg; unsigned long devaddr; int dcon = 0; unsigned int flags = 0; devaddr = ADV212_BASE_PHYS+ ADV212_DIRECT_REG_CODE; if(s->dmach == DMACH_XD0) { source =S3C2410_DMASRC_HW; hwcfg =1 ; dmacount = 0; dcon=S3C2410_DCON_HANDSHAKE|S3C2410_DCON_SYNC_HCLK|S3C2410_DCON_INTREQ|S3C2410_DCON_WHOLE_SERVICE|S3C2410_DCON_INTREQ|S3C2410_DCON_AUTORELOAD|S3C2410_DCON_HWTRIG|S3C2410_DCON_WORD|dmacount; flags = S3C2410_DMAF_AUTOSTART; ret = s3c2410_dma_request(s->dmach, &s3c2440adv212_dma_in, NULL); s3c2410_dma_devconfig(s->dmach, source, hwcfg, devaddr);//write source addr, srrc ctl,dist ctl s3c2410_dma_config(s->dmach, 4, dcon); //wsh wrire dcon, change xferunit from 2 to 4 s3c2410_dma_set_buffdone_fn(s->dmach, adv212_dmain_done_callback); s3c2410_dma_setflags(s->dmach, flags); return 0 ; } else return 1; } 关于read部分的源代码: static ssize_t smdk2440_adv212_read(struct file *file, char *buffer, size_t count, loff_t * ppos) { /*nyp*/ const char *buffer0 = buffer; audio_stream_t *s = &input_stream; int chunksize, ret = 0; unsigned short value16; int jp2_size,i,size_tmp; if (!s->buffers) { int i; if (adv212_setup_buf(s)) //alloc DMA buffers return -ENOMEM; for (i = 0; i < s->nbfrags; i++) { audio_buf_t *b = s->buf; printk("s->buf_idx = %u\n", s->buf_idx); down(&b->sem); printk("s->dmach = %d\n",s->dmach); s3c2410_dma_enqueue(s->dmach, (void *) b, b->dma_addr, s->fragsize); NEXT_BUF(s, buf); } } if(start_flag == 0) { printk("\nstart output\n"); reg16_adv212_eirqflg =0xFFFF;//start compress and make adv212 can output printk("\n***nyp3 : eirqflg=0x%x***\n",reg16_adv212_eirqflg); value16 = s3c2410_gpio_getpin(S3C2410_GPB10); while(value16 != 0) value16 = s3c2410_gpio_getpin(S3C2410_GPB10); start_flag = 1; printk("lalala\n"); } while (count > 0) { audio_buf_t *b = s->buf; // Wait for a buffer to become full if (file->f_flags & O_NONBLOCK) { ret = -EAGAIN; if (down_trylock(&b->sem)) break; } else { ret = -ERESTARTSYS; if (down_interruptible(&b->sem)) break; } chunksize = b->size; if (chunksize > count) // we required less than buffer size chunksize = count; if (copy_to_user(buffer, b->start + s->fragsize - b->size, chunksize)) { up(&b->sem); return -EFAULT; } b->size -= chunksize; buffer += chunksize; count -= chunksize; if (b->size > 0) { up(&b->sem); break; } //Make current buffer available for DMA again printk("in the while s->buf_idx = %u\n", s->buf_idx); s3c2410_dma_enqueue(s->dmach, (void *) b, b->dma_addr, s->fragsize); NEXT_BUF(s, buf); } if ((buffer - buffer0)) ret = buffer - buffer0; printk("adv212_read: return=%d bytes!\n", ret); return ret; }
订阅后,新回复会通过你的通知中心匿名送达。
2 条回复
nyp1984机器人#1 · 2010/1/22
自己顶
nyp1984机器人#2 · 2010/1/22
zbd