Mini2440 USB gadget --使用与测试

发布者:RainbowMelody最新更新时间:2024-06-21 来源: elecfans关键字:Mini2440  USB  gadget 手机看文章 扫描二维码
随时随地手机看文章

USB Gadget驱动又称USB器件驱动。主要用于运行linux的嵌入式系统中,使得系统拥有普通USB设备的功能。mini2440具有USB1.1设备控制器,所以可以使用USB Gadget功能。但是linux2.6.32.2内核对于mini2440的支持不是很完全。开启USB Gadget功能之后,不能使得主机发现USB硬件。这个问题主要是USB接口上拉电阻的问题,mini2440使用GPC5来上拉USB,使得主机集线器发现有USB设备链接从而枚举设备。但是在linux2.6.32.2内核中,没有设置GPC5的代码。所以导致不能使用Gadget功能。解决办法网上也有一些,就是增加额外的模块置位GPC5,但是我认为这样不是最好的办法。认真分析s3c2410_udc.c以及g_zero.c的代码后,发现在注册Gadget功能驱动的时候会调用s3c2410_udc.c提供的usb_gadget_register_driver函数,而这个函数最后会调用s3c2410_udc_enable。这个函数就是使能UDC的。代码如下:

  1. static void s3c2410_udc_enable(struct s3c2410_udc *dev)  

  2. {  

  3.     int i;  

  4.   

  5.     dprintk(DEBUG_NORMAL, 's3c2410_udc_enable calledn');  

  6.   

  7.     /* dev->gadget.speed = USB_SPEED_UNKNOWN; */  

  8.     dev->gadget.speed = USB_SPEED_FULL;  

  9.   

  10.     /* Set MAXP for all endpoints */  

  11.     for (i = 0; i < S3C2410_ENDPOINTS; i++) {  

  12.         udc_write(i, S3C2410_UDC_INDEX_REG);  

  13.         udc_write((dev->ep[i].ep.maxpacket & 0x7ff) >> 3,  

  14.                 S3C2410_UDC_MAXP_REG);  

  15.     }  

  16.   

  17.     /* Set default power state */  

  18.     udc_write(DEFAULT_POWER_STATE, S3C2410_UDC_PWR_REG);  

  19.   

  20.     /* Enable reset and suspend interrupt interrupts */  

  21.     udc_write(S3C2410_UDC_USBINT_RESET | S3C2410_UDC_USBINT_SUSPEND,  

  22.             S3C2410_UDC_USB_INT_EN_REG);  

  23.   

  24.     /* Enable ep0 interrupt */  

  25.     udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_EN_REG);  

  26.   

  27.     /* time to say 'hello, world' */  

  28.   

  29.     if (udc_info && udc_info->udc_command) {  

  30.         udc_info->udc_command(S3C2410_UDC_P_ENABLE);  

  31.     }  

  32. }  

        我们发现这个函数除了前面使能中断的操作后,最后有个判断语句,判断udc_info以及udc_info->command是否有值。然后调用udc_command,这个函数的调用参数为S3C2410_UDC_P_ENABLE。很显然这个就是使能UDC的关键操作。我们看一下udc_info又是什么,在s3c2410_udc.c的最开始有这样的定义:


        static struct s3c2410_udc_mach_info *udc_info;

        说明这是一个指向s3c2410_udc_mach_info结构的指针。s3c2410_udc_mach_info结构在udc.h中定义:

  1. struct s3c2410_udc_mach_info {  

  2.     void    (*udc_command)(enum s3c2410_udc_cmd_e);  

  3.     void    (*vbus_draw)(unsigned int ma);  

  4.     unsigned int vbus_pin;  

  5.     unsigned char vbus_pin_inverted;  

  6. };  

        那么这个指针又是什么时候赋值的,是在s3c2410_udc_probe函数中。这就说明在注册s3c2410_udc驱动的时候,由platform总线找到相应的设备匹配后,调用的。如下:
udc_info = pdev->dev.platform_data;
        那么什么又是platfom_data呢,这个又是在什么时候赋值的呢。要理解这个还得需要平台驱动的只是,也就是platform driver的知识。s3c2410的udc驱动是一个platform驱动,所以USB设备控制器是platform device。那么这个platform_data又是在哪赋的值。一般而言platform device在系统板级初始化的时候初始化的。也就是板级初始化的时候赋值。但是用Kscope怎么也找不到给他赋值的语句。说明根本就没人给他赋值。所以在注册g_zero功能驱动的时候udc_info是空的,没有执行udc_info->udc_command()。我们要做的就是给usb gadget platform device的platform_data初始化。在mach-mini2440.c中增加如下代码:

  1. static void s3c2410_udc_pullup(enum s3c2410_udc_cmd_e cmd)  

  2. {  

  3.     switch (cmd) {  

  4.     case S3C2410_UDC_P_ENABLE :  

  5.         s3c2410_gpio_setpin(S3C2410_GPC(5), 1);  

  6.         break;  

  7.     case S3C2410_UDC_P_DISABLE :  

  8.         s3c2410_gpio_setpin(S3C2410_GPC(5), 0);  

  9.         break;  

  10.     case S3C2410_UDC_P_RESET :  

  11.         break;  

  12.     default:  

  13.         break;  

  14.     }  

  15. }  

        这个函数就是udc_info->udc_command()执行的函数,在这里使得GPC5为高电平,使能USB设备。

  1. static struct s3c2410_udc_mach_info s3c2410_udc_cfg __initdata = {  

  2.     .udc_command        = s3c2410_udc_pullup,  

  3. };  

        这个结构体定义了platform_data的初始值。


        修改mini2440_machine_init函数,增加s3c24xx_udc_set_platdata(&s3c2410_udc_cfg);如下

  1. static void __init mini2440_machine_init(void)  

  2. {  

  3. #if defined (LCD_WIDTH)   

  4.     s3c24xx_fb_set_platdata(&mini2440_fb_info);  

  5. #endif   

  6.     s3c_i2c0_set_platdata(NULL);  

  7.   

  8.     s3c2410_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);  

  9.   

  10.     s3c_device_nand.dev.platform_data = &friendly_arm_nand_info;  

  11.     s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg;  

  12.     s3c24xx_udc_set_platdata(&s3c2410_udc_cfg); //增加的代码   

  13.     platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));  

  14.     s3c_pm_init();  

  15. }  

        s3c24xx_udc_set_platdata()这个函数定义与devs.c,如下:

  1. void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)  

  2. {  

  3.     struct s3c2410_udc_mach_info *npd;  

  4.   

  5.     npd = kmalloc(sizeof(*npd), GFP_KERNEL);  

  6.     if (npd) {  

  7.         memcpy(npd, pd, sizeof(*npd));  

  8.         s3c_device_usbgadget.dev.platform_data = npd;  

  9.     } else {  

  10.         printk(KERN_ERR 'no memory for udc platform datan');  

  11.     }  

  12. }  

        最后还要在头文件中包含plat/udc.h。这样我们注册Gadget功能驱动的时候自动使能了USB设备功能。但是在卸载驱动的时候发生了问题,内核打印出一大堆调试信息。问题出在composite.c中的composite_unbind函数中。这个函数开头有一行代码WARN_ON(cdev->config);就是如果cdev-config不为0,那么内核就会打印出调试信息。上面还给了注释
/* composite_disconnect() must already have been called
* by the underlying peripheral controller driver!
* so there's no i/o concurrency that could affect the
* state protected by cdev->lock.
*/
        这个composite_unbind是在卸载udc功能驱动的时候调用的,调用关系如下:usb_composite_unregister 调用 usb_gadget_unregister_driver而usb_gadget_unregister_driver如下定义:

  1. int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)  

  2. {  

  3.     struct s3c2410_udc *udc = the_controller;  

  4.   

  5.     if (!udc)  

  6.         return -ENODEV;  

  7.   

  8.     if (!driver || driver != udc->driver || !driver->unbind)  

  9.         return -EINVAL;  

  10.   

  11.     dprintk(DEBUG_NORMAL,'usb_gadget_register_driver() '%s'n',  

  12.         driver->driver.name);  

  13.   

  14.     driver->disconnect(&udc->gadget);  

  15. //此处为新加语句,这条语句调用 composite_disconnect,然后使得cdev->config为NULL   

  16.     driver->unbind(&udc->gadget);  

  17. //这里就是composite_unbind   

  18.   

  19.   

  20.     device_del(&udc->gadget.dev);  

  21.     udc->driver = NULL;  

  22.   

  23.     /* Disable udc */  

  24.     s3c2410_udc_disable(udc);  

  25.   

  26.     return 0;  

  27. }  

        从注释上可以看出调用composite_unbind的前提是要首先保证composite_disconnect被调用。这样才不会出现警告的内核信息。在增加上面的代码后重新编译内核,将USB Gadget设置称为模块。然后make modules 在通过ftp将s3c2410_udc.ko与g_zero.ko传入开发板,先后加载这两个模块。在主机上lsusb会发现出现新设备
Bus 005 Device 023: ID 0525:a4a0 Netchip Technology, Inc. Linux-USB 'Gadget Zero'
        卸载g_zero.ko后,新设备就会消失。这样基本的USB Gadget驱动功能就开启了。类似的还可以测试其他的USB Gagget。


关键字:Mini2440  USB  gadget 引用地址:Mini2440 USB gadget --使用与测试

上一篇:Ubuntu 11.10 下移植 madplay 到 mini2440
下一篇:Mini2440 Linux 内存布局

推荐阅读最新更新时间:2026-03-25 04:43

linux-2.6.32在mini2440开发板上移植 配置USB外设
编者:因为LINUX内核对S3C2440的Host驱动的已经支持,而且支持的外设相当的丰富,所以这一部分只是进行配置就可以使用。因为配置的东西较多,没有给出详细的截图,看手册上介绍的就很明白。需要手册的请留下邮箱索取。 1 配置和测试USB 键盘、扫描器和鼠标 在内核源代码目录的终端输入:make menuconfig,依次选择如下子菜单项: Device Drivers --- HID Devices --- 按空格键选中“USB Human Interface Device (full HID) support”,这样就配置好了USB键盘和鼠标项。 提示:这里的配置选项对应的内核源代码目录是:
[单片机]
使用USB无线网卡和USB摄像头打造mini2440无线监控系统
一、我的mini2440开发板上使用的网卡设备为水星MERCURY54M无线USB网卡 MW54U ver:7.0,其内部芯片型号为ATHEROS的ar9271。mini2440的自带linux系统里面是没有这个驱动程序的,但是在官网上usb-wifi-kits-for-mini2440-linux-2.6.32.2-20100728.tar.gz这个安装包里面是有ar9271这个驱动的。 所以首先就得,先把usb-wifi-kits-for-mini2440-linux-2.6.32.2-20100728.tar.gz这个压缩包拷贝到mini2440的linux系统中,然后直接在根系统下面解压缩,使用以下命令: #tar -xz
[单片机]
s3c6410 linux gadget hid驱动
我用的内核是linux2.6.38的,最开始的时候开发板是可以当U盘用的,而使用hid功能的时候出现如下问题: g_hid gadget: hid_setup crtl_request : bRequestType:0x21 bRequest:0xa Value:0x0 g_hid gadget: Unknown request 0xa s3c-hsotg s3c-hsotg: writen DxEPCTL=0x04228000 to 00000900 (DxEPCTL=0x00208000) s3c-hsotg s3c-hsotg: s3c_hsotg_rx_data: FIFO 8 bytes on ep0 but no
[单片机]
MIC Gadget发售兼容iPad的CF读卡器
     Hybrid tech网站以及MIC Gadget网店本周悄然推出一款适配器产品,提供iPad和iPad 2用户所渴望的储存卡读取支持。这款CF Card Reader for iPad可让拥有高端单反以及老式CF卡相机的摄影者直接将图片和视频上传至任意一代iPad中。目前苹果平板机提供的格式支持非常有限,RAW以及一些视频格式被排除在外,主要原因是它们超出苹果官方的720p、30FPS限定。      这款读卡器支持UDMA标准的储存卡,尽管会受限于USB 2.0的速度瓶颈。产品整合一个标准USB接口,可接驳工作电流20mA以下的设备。      iPad用户现在可花费$30购买CF Card Reader。该公司
[手机便携]
mini2440串口设置
在这里有必要先了解一下底层串口的知识, 在这里用到的关于串口的分别是:termios,tcgetattr,tcsetattr,tcsendbreak,tcdrain,tcflush,tcflow,cfmakeraw, cfgetospeed,cfgetispeed,cfsetispeed,cfsetospeed。 分别对其进行分析: 其原型为: int tcgetattr(int fd, struct termios *termios_p); int tcsetattr(int fd, int optional_actions, struct termios *termios_p); int tcsendbreak(int fd,
[单片机]
mini2440使用J-LINK 直接下载到NOR-FLASH
J-Flash ARM的配置。 一般说来file-- open project里面会找到一些*.jflash的配置文件,加载他们就行了,但是没找到适合S3C2440的。所以自己建了一个MINI2440.jflash,手动进行配置: j-link设置 1. 打开J-Flash ARM,并进入菜单:Options-- Project settings 2.主要设置CPU选项和Flash选项 CPU : Core -- ARM9, Little endian Use target RAM(faster)-- Addr:40000000 4KB(不选很慢;从Nor flash启动时内部Boot SRAM的地址和大小,参考S3C2
[单片机]
linux-3.0内核移植到fl2440开发板(以MINI2440为模板)
我们的fl2440开发板使用的是s3c2440的芯片,与MINI2440十分相似,因此需要改动的地方不多,移植也比较容易。 1. $ sudo tar -xjf linux-3.0.tar.bz2 2. 进入 linux-3.0,修改顶层Makefile 配置CPU类型和交叉编译器(195,196行) ARCH ?= arm CROSS_COMPILE ?= /opt/buildroot-2011.11/arm920t/usr/bin/arm-linux- 添加zImage头制作(559行后面) cp arch/arm/boot/zImage . -f /home/weishusheng/kernel/linux-3
[单片机]
Qemu Mini2440 的 Linux Fedora 下网络配置
最近应朋友的要求,研究一下QEMU MINI2440下的仿真。本来我以为这个过程没什么的,这一研究还真发现不少问题,写出来与大家分享。 我使用的系统环境: 1.使用VMware 6.5,宿主机使用 win 7 2.VMWare 6.5上的系统是 Linux Fedora 8 3.RTEMS 的编译环境 4.9 首先我从以下网站获取源代码: 1.获取QEMU的源代码:git clone git://repo.or.cz/qemu/mini2440.git qemu 2.获取UBOOT的源代码git clone git://repo.or.cz/u-boot-openmoko/mini2440.git uboot
[单片机]
Qemu <font color='red'>Mini2440</font> 的 Linux Fedora 下网络配置
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved