ImageVerifierCode 换一换
格式:DOCX , 页数:24 ,大小:32.48KB ,
资源ID:9684328      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/9684328.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(USB OTG驱动分析.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

USB OTG驱动分析.docx

1、USB OTG驱动分析前一段时间弄了 2 个礼拜的 OTG 驱动调试,感觉精神疲惫啊。主要原因还是自己对 OTG 功能不了解造成的。现在终于完成但是对实质原理还有些模糊。所以 自己重新总结一下。因为自己是菜鸟,所以用菜鸟的白话方式分析。高手滤过吧。 所谓 OTG 功能 就是具备该功能的设备即可当主设备 (host) 去轮询别人,也可以当从设备 (device) 去被别人轮(双性人?)。正所谓所有的产品和功能都是因为需求 存在的,举个最简单的需求,原来 MP3 想传送一个歌曲都得通过电脑。现在只要两个 MP3 链接,其中一个 MP3 有 OTG 功能作为主设备(相当于电脑主机),然后另外一个是从

2、设备就可以 实现数据的传送了。 那么话说回来,具有 OTG 功能的设备如何确定自己是主还是从设备那。原来原来 USB 接口上有 4 个管脚, OTG 功能有 5 个。原来 4 个分别是电 D+ D- 地。 现在增加了一个 ID 。这个 ID 线就决定了自己做主设备还是从设备。如果 ID 线是高则自己是从设备,反之是主设备。 下面开始分析代码。向平时一样定义platform_device资源等信息。 定义platform_device结构 static struct platform_device _maybe_unused dr_otg_device = . name = fsl-usb2-o

3、tg , /设备的名称 日后匹配用 . id = - 1, /只有一个这样的设备 . dev = . release = dr_otg_release, . dma_mask = & dr_otg_dmamask, . coherent_dma_mask = 0xffffffff, , . resource = otg_resources, /设备的资源 看下面. num_resources = ARRAY_SIZE( otg_resources) , ; 定义platform_device下的struct resource设备资源结构static struct resource otg_re

4、sources = 0 = . start = ( u32) ( USB_OTGREGS_BASE) , /描述设备实体在cpu总线上的线 性起始物理地址. end = ( u32) ( USB_OTGREGS_BASE + 0x1ff) , /描述设备实体在cpu总线上的线性结尾物理地址 . flags = IORESOURCE_MEM, , 1 = . start = MXC_INT_USB_OTG, /中断号 . flags = IORESOURCE_IRQ, , ; 定义平台设备私 有数据,以后驱动要使用 static struct fsl_usb2_platform_data _ma

5、ybe_unused dr_utmi_config = . name = DR , . platform_init = usbotg_init, . platform_uninit = usbotg_uninit, . phy_mode = FSL_USB2_PHY_UTMI_WIDE, . power_budget = 500, /* via RT9706 */ . gpio_usb_active = gpio_usbotg_utmi_active, . gpio_usb_inactive = gpio_usbotg_utmi_inactive, . transceiver = utmi ,

6、 . wake_up_enable = _wake_up_enable, ; # define PDATA ( & dr_utmi_config) 定义platform_device下的DEV设备下的平台私有数据(就是该设备私有的数据) static inline void dr_register_otg( void ) PDATA- operating_mode = FSL_USB2_DR_OTG; /将模式更改(上面定义的时候定义的是FSL_USB2_PHY_UTMI_WIDE,不知道为什么开始不定义这个,可能是为了兼 容) dr_otg_device. dev. platform_dat

7、a = PDATA; /该设备的私有数据赋值,就 是上面定义的dr_utmi_config if ( platform_device_register( & dr_otg_device) ) printk( KERN_ERR usb: cant register otg device/n ) ; else printk( KERN_INFO usb: DR OTG registered/n ) ; 上面几个过程主要是完成了设备的注册。这个过程是: 1. 定 义platform_device结构。 2. 定义 platform_device下的struct resource设备资源结构 3. 定

8、义platform_device下的DEV设备下的平台私有数据(就是该设备私有的数据) 4. 调用platform_device_register将 platform_device结构注册上面4个过程调用结束后,设备的信息就被注册到系统中,等待驱动的使用下 面分析驱动和设备的链接过程 定义platform_driver结构 struct platform_driver fsl_otg_driver = . probe = fsl_otg_probe, /定义处理函数,该函数在设备名字匹配到后调用,也就是发现该驱动 对应的设备在系统中注册过。 . remove = fsl_otg_remove,

9、 . driver = . name = fsl-usb2-otg , /通过该名字匹配开始注册进系统的设备 . owner = THIS_MODULE, , ; 将platform_driver结构注册进系统,系统通 过注册名字匹配该设备是否已经在系统中,如果在调用注册的probe = fsl_otg_probe函数 static int _init fsl_usb_otg_init( void ) printk( KERN_INFO DRIVER_DESC loaded, %s/n , DRIVER_VERSION) ; return platform_driver_register( &

10、 fsl_otg_driver) ; 调用 fsl_otg_probe 函数,函数参数 platform_device *pdev ,就是我们上面注册进系统 的 platform_device 结构,现在由系统赋值调用 fsl_otg_probe static int _init fsl_otg_probe( struct platform_device * pdev) int status; struct fsl_usb2_platform_data * pdata; DBG( pdev=0x%p/n , pdev) ; if ( ! pdev) return - ENODEV; /* 判断

11、是否有设备自己的数据,就是检查我们上面定义的 3 的过程*/ if ( ! pdev- dev. platform_data) return - ENOMEM; pdata = pdev- dev. platform_data; /* configure the OTG */ status = fsl_otg_conf( pdev) ; if ( status) printk( KERN_INFO Couldnt init OTG module/n ) ; return - status; /* start OTG */ status = usb_otg_start( pdev) ; if (

12、 register_chrdev( FSL_OTG_MAJOR, FSL_OTG_NAME, & otg_fops) ) printk( KERN_WARNING FSL_OTG_NAME : unable to register FSL OTG device/n ) ; return - EIO; create_proc_file( ) ; return status; 上面函数中调用了 fsl_otg_conf ,我们来看看他干了什么。 static int fsl_otg_conf( struct platform_device * pdev) int status; struct fs

13、l_otg * fsl_otg_tc; struct fsl_usb2_platform_data * pdata; pdata = pdev- dev. platform_data; DBG( ) ; /*/ struct fsl_otg struct otg_transceiver otg;struct otg_fsm fsm;struct usb_dr_mmap *dr_mem_map;struct delayed_work otg_event; /*used for usb host */struct work_struct work_wq;u8host_working; int ir

14、q; /*/ if ( fsl_otg_dev) return 0; /* allocate space to fsl otg device */ fsl_otg_tc = kzalloc( sizeof ( struct fsl_otg) , GFP_KERNEL) ; if ( ! fsl_otg_tc) return - ENODEV; INIT_DELAYED_WORK( & fsl_otg_tc- otg_event, fsl_otg_event) ; INIT_LIST_HEAD( & active_timers) ; status = fsl_otg_init_timers( &

15、 fsl_otg_tc- fsm) ; if ( status) printk( KERN_INFO Couldnt init OTG timers/n ) ; fsl_otg_uninit_timers( ) ; kfree( fsl_otg_tc) ; return status; spin_lock_init( & fsl_otg_tc- fsm. lock) ; /* Set OTG state machine operations */ /*/ static struct otg_fsm_ops fsl_otg_ops = .chrg_vbus = fsl_otg_chrg_vbus

16、,.drv_vbus = fsl_otg_drv_vbus,.loc_conn = fsl_otg_loc_conn,.loc_sof = fsl_otg_loc_sof,.start_pulse = fsl_otg_start_pulse, .add_timer = fsl_otg_add_timer,.del_timer = fsl_otg_del_timer, .start_host = fsl_otg_start_host,.start_gadget = fsl_otg_start_gadget,; /*/ fsl_otg_tc- fsm. ops = & fsl_otg_ops; /

17、* initialize the otg structure */ fsl_otg_tc- otg. label = DRIVER_DESC; fsl_otg_tc- otg. set_host = fsl_otg_set_host; fsl_otg_tc- otg. set_peripheral = fsl_otg_set_peripheral; fsl_otg_tc- otg. set_power = fsl_otg_set_power; fsl_otg_tc- otg. start_hnp = fsl_otg_start_hnp; fsl_otg_tc- otg. start_srp =

18、 fsl_otg_start_srp; fsl_otg_dev = fsl_otg_tc; /* Store the otg transceiver */ /*/ int otg_set_transceiver(struct otg_transceiver *x)if (xceiv & x)return -EBUSY;xceiv = x;return 0; 该函数就是将struct otg_transceiver结构副给一个全局变量保存,供以后使用,以后会通过调用下面函数得到该结构 struct otg_transceiver *otg_get_transceiver(void)if (xce

19、iv)get_device(xceiv-dev);return xceiv; /*/ status = otg_set_transceiver( & fsl_otg_tc- otg) ; if ( status) printk( KERN_WARNING : unable to register OTG transceiver./n ) ; return status; return 0; int usb_otg_start( struct platform_device * pdev) struct fsl_otg * p_otg; /*获得otg_transceiver结构 */ stru

20、ct otg_transceiver * otg_trans = otg_get_transceiver( ) ; struct otg_fsm * fsm; volatile unsigned long * p; int status; struct resource * res; u32 temp; /*获得设备的私有数据*/ struct fsl_usb2_platform_data * pdata = pdev- dev. platform_data; /* 使用container_of宏定义可以通过结构中一个变量的指针获得该结构首地址 */p_otg = container_of(

21、otg_trans, struct fsl_otg, otg) ; fsm = & p_otg- fsm; /* Initialize the state machine structure with default values */ SET_OTG_STATE( otg_trans, OTG_STATE_UNDEFINED) ; fsm- transceiver = & p_otg- otg; /* We dont require predefined MEM/IRQ resource index */ /*获得设备的资源,是在设备注册时结构体里面的内容*/ res = platform_

22、get_resource( pdev, IORESOURCE_MEM, 0) ; if ( ! res) return - ENXIO; /* We dont request_mem_region here to enable resource sharing * with host/device */ /*通过资源中 获得的物理地址映射一个可以被驱动访问的虚拟地址指针*/usb_dr_regs = ioremap( res- start, sizeof ( struct usb_dr_mmap) ) ; /*将该指针保存到p_otg - dr_mem_map中 */ p_otg- dr_me

23、m_map = ( struct usb_dr_mmap * ) usb_dr_regs; pdata- regs = ( void * ) usb_dr_regs; /* request irq */ /*获得设备注册时候的中断并注册,在 OTG ID发生变化时触发中断,然后调用注册的中断例程函数,函数后面分析*/ p_otg- irq = platform_get_irq( pdev, 0) ; status = request_irq( p_otg- irq, fsl_otg_isr, IRQF_SHARED, driver_name, p_otg) ; if ( status) dev

24、_dbg( p_otg- otg. dev, cant get IRQ %d, error %d/n , p_otg- irq, status) ; iounmap( p_otg- dr_mem_map) ; kfree( p_otg) ; return status; if ( pdata- platform_init & & pdata- platform_init( pdev) ! = 0) return - EINVAL; /* Export DR controller resources */ /*/ int otg_set_resources(struct resource *re

25、sources)otg_resources = resources;return 0; 和otg_set_transceiver功能类似将设备资源保存到一个全局变量中 /*/ otg_set_resources( pdev- resource) ; /*开始配置USB寄存器*/* stop the controller */ temp = readl( & p_otg- dr_mem_map- usbcmd) ; temp & = USB_CMD_RUN_STOP; writel( temp, & p_otg- dr_mem_map- usbcmd) ; /* reset the contro

26、ller */ temp = readl( & p_otg- dr_mem_map- usbcmd) ; temp | = USB_CMD_CTRL_RESET; writel( temp, & p_otg- dr_mem_map- usbcmd) ; /* wait reset completed */ while ( readl( & p_otg- dr_mem_map- usbcmd) & USB_CMD_CTRL_RESET) ; /* configure the VBUSHS as IDLE(both host and device) */ temp = USB_MODE_STREAM_DISABLE | ( pdata- es ? USB_MODE_ES : 0) ; writel( temp, & p_otg- dr_mem_map- usbmode) ; /* configure PHY interface */ temp = readl( & p_otg- dr_mem_map- portsc) ; temp & = ( PORTSC_PHY_TYPE_SEL | PORTSC_PTW) ; switch ( pdata- phy_mode) case FSL_USB2_PHY_ULPI:

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1