2440 USB Gadget 存储设备的调试
众所周知,USB Gadget 的源代码,在 内核目录 driver->usb->gadget 目录下,gadget 能实现的功能有很多,可以让嵌入式设备,在PC 上实现一个存储磁盘,虚拟成一个网络设备还有, zero 设备,今天,我主要记录一下,自己,在调试SD 卡过程,碰到的问题,哎,发现,自己弄这个arm 开发板,一路碰到的都是很经典的问题,先讲一下,自己碰到的问题吧。
linux ,对gadget的支持,已经,有方案了,自己用的是2440,自然,选中内核的选项,就可以把2440 的udc ,编译进内核了,但是,都必须是 模块的形式,编译,才行,找到Device drivers–>USb support –> <M> usb gadget support –> <M> File backed Storage gadget
[*]File-backed Storage gadget testing version , 直接编译
sudo make ,这样它就会把模块也编译出来。
插入相应的模块
insmod /etc/modules/s3c2410_udc.ko insmod /etc/modules/g_file_storage.ko file=/dev/sdcard stall=0 removable=1
这里的驱动,涉及的文件是s3c2410_udc.c 和 file_storage.c
接上USB 线以后,就可以,识别成存储器,但是 这样的做法,只能,拷贝小文件,大文件往往会出各种问题,
别想了,问题没出在file_storage.c,这是Linux内核社区写的 ,肯定是棒子给的文件有问题,
自己的不是大牛,这两文件的分析,就算了,主要,还是讲一下,自己无所不能的搜索技术,google ,找答案,
嘿嘿,自己的问题,网上的哥们分析,还真不少,但大部分,都是,讲协议的,什么协议? 这个都是内核里写好的
看大牛的分析,还不如拿着RFC,看源代码,总的来说是不管的事。 突然google 发力,追踪到了这里 ,http://www./forum/printthread.php?Cat=&Board=embedded&main=725335&type=thread
网上牛人真多啊, 这种微妙的东西都能发现,他妈的是吃什么长大的,总之一个字,就是牛。
以防链接消失,我把关键复制下来,
tengel,我是这样加的again: static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep, struct s3c2410_request *req) { u8 *buf; u32 ep_csr; unsigned bufferspace; int is_last = 1; unsigned avail; int fifo_count = 0; u32 idx; int fifo_reg; int again_num = 0; struct timeval time;
idx = ep->bEndpointAddress & 0x7F; switch (idx) { default: idx = 0; case 0: fifo_reg = S3C2410_UDC_EP0_FIFO_REG; break; case 1: fifo_reg = S3C2410_UDC_EP1_FIFO_REG; break; case 2: fifo_reg = S3C2410_UDC_EP2_FIFO_REG; break; case 3: fifo_reg = S3C2410_UDC_EP3_FIFO_REG; break; case 4: fifo_reg = S3C2410_UDC_EP4_FIFO_REG; break; }
if (!req->req.length) { return 1; }
do_gettimeofday(&time); if(( time.tv_sec – o_tick ) >= 10){ dprintk(DEBUG_WATCH, “last data, actual:%d, length:%d, count:%d\n”, o_actual, o_length, o_x_count); } o_tick = time.tv_sec;
again: buf = req->req.buf + req->req.actual; bufferspace = req->req.length – req->req.actual; if (!bufferspace) { dprintk(DEBUG_WATCH/*DEBUG_NORMAL*/, “%s: buffer full!\n”, __func__); return -1; }
udc_write(idx, S3C2410_UDC_INDEX_REG); fifo_count = s3c2410_udc_fifo_count_out(); //dprintk(DEBUG_WATCH/*DEBUG_VERBOSE*/, “%s fifo count : %d\n”, __func__, fifo_count);
if (fifo_count > ep->ep.maxpacket) { avail = ep->ep.maxpacket; } else { avail = fifo_count; }
fifo_count = s3c2410_udc_read_packet(fifo_reg, buf, req, avail);
// checking this with ep0 is not accurate as we already read a control request if (idx != 0 && fifo_count < ep->ep.maxpacket) { is_last = 1; // overflowed this request? flush extra data if (fifo_count != avail) { req->req.status = -EOVERFLOW; } } else { is_last = (req->req.length <= req->req.actual) ? 1 : 0; }
udc_write(idx, S3C2410_UDC_INDEX_REG); fifo_count = s3c2410_udc_fifo_count_out();
// Only ep0 debug messages are interesting if (idx == 0) { dprintk(DEBUG_WATCH/*DEBUG_VERBOSE*/, “%s fifo count : %d [last %d]\n”, __func__, fifo_count,is_last); }
if (is_last) { if (idx == 0) { s3c2410_udc_set_ep0_de_out(base_addr); ep->dev->ep0state = EP0_IDLE; } else { udc_write(idx, S3C2410_UDC_INDEX_REG); ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG); udc_write(idx, S3C2410_UDC_INDEX_REG); udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY, S3C2410_UDC_OUT_CSR1_REG); s3c2410_udc_done(ep, req, 0); } } else { if (idx == 0) { s3c2410_udc_clear_ep0_opr(base_addr); } else { udc_write(idx, S3C2410_UDC_INDEX_REG); ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG); udc_write(idx, S3C2410_UDC_INDEX_REG); udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY, S3C2410_UDC_OUT_CSR1_REG); } } }
/**/ //udc_write(idx, S3C2410_UDC_INDEX_REG); fifo_count = s3c2410_udc_fifo_count_out(); if( (( EP_FIFO_SIZE == fifo_count) || ((req->req.length – req->req.actual) == fifo_count) ) && (!is_last) ){ dprintk(DEBUG_NORMAL, “goto again”); goto again; }
return is_last; }
分析这位仁兄的做法,对照,内核代码,发现,这哥们就是,把数据多读了几遍,哎,在这,我又得概叹几句了,
“为什么国人这么聪明,还得用棒子设计的CPU呢?”,真想不通。
瞬间,改过以后,就好使多了。
转载:http://www./?p=264
|