S3C2440 USB 设备控制器

发布者:创客1992最新更新时间:2022-10-12 来源: csdn关键字:S3C2440  USB  设备控制器 手机看文章 扫描二维码
随时随地手机看文章

s3c2440 soc集成了一个usb1.1设备控制器,可以进行全速/低速的控制,中断与批量传输。除了端点0,具有四个端点,每个端点都可以作为中断与批量的端点,每个端点具有128 byte的FIFO,所以端点最大packet可以设置成128byte。并且支持DMA传输。任何一种设备控制器对于软件来说都是一组寄存器:数据,状态,控制。usb 设备控制器也不例外。设置好相应的控制寄存器,并且在数据来时读取数据寄存器,需要发送数据的时候将数据写入输出寄存器。而这种数据的通信建立在对状态寄存器的读取上,往往还会有中断与DMA的操作。s3c2440 usb设备控制器的寄存器分为以下几组:


(1):电源管理寄存器

        PWR_REG 负责USB设备挂起等电源设置

(2):地址寄存器

        存储USB设备的地址,当主机枚举设备设备的时候设置

(3):中断控制寄存器

        EP_INT_REG    端点中断状态寄存器,每当一个端点事件发生的时候,相应的位就会置1

        USB_INT_REG   设备中断状态寄存器,主要有三个中断:唤醒,复位,挂起

        EP_INT_EN_REG  端点中断使能寄存器

        EP_INT_EN_REG  设备中断使能寄存器

(4):编号寄存器


因为USB 设备控制器有五个端点,并且五个端点寄存器大同小异,所以硬件设计上使用了编号寄存器:名字相同但物理寄存器不同。有一个INDEX_REG寄存器,它里面的值指示了具体的哪组物理寄存器。这样的寄存器有七个分别是:

        MAXP_REG: 端点最大信息包大小

        IN_CSR1_REG

        IN_CSR2_REG

        OUT_CSR1_REG

        OUT_CSR2_REG

        OUT_FIFO_CNT1_REG

        OUT_FIFO_CNT2_REG

(5):FIFO寄存器

        EPO_FIFO_REG

        EP1_FIFO_REG

        EP2_FIFO_REG

        EP3_FIFO_REG

        EP4_FIFO_REG

(6):DMA寄存器

        端点1~4,每个端点六个,用于设置端点的DMA传输。


USB设备控制器处理了大部分的USB传输细节,并产生相应的中断。所以对USB设备控制器的编程,最关键的部分就是中断处理的部分。比如端点每收到一个token以及后面的数据包,就会产生相应的中断。软件只需要在中断处理程序中读取数据,并且清除中断标志。USB设备控制器就会自动发送应答包。现在网上比较流行的操作s3c2440 usb 设备控制器的程序就是移植到u-boot里面的usb下载程序。因为在u-boot的环境下所以调试起来没有在裸机上来的方便,所以我将这个程序移植到了裸机上,编译环境arm-linux-gcc。下面大体介绍以下这个程序的流程:


这个程序主要是完成了USB设备的枚举,与批量OUT传输,并且开启了DMA,OUT传输用的端点是端点3。这个程序首先从init_usb_slave() 开始:这个函数主要是设置usb slave的引脚以及控制寄存器,设置中断处理程序的入口,以及开启中断。


void usb_init_slave(void)

{

        struct s3c24x0_gpio * const gpioregs = s3c24x0_get_base_gpio();

        char *mode;

 

        Delay(10);

 

        Usb_Isr_Init();  

      //设置中断处理程序的入口,需要两个中断USBD与DMA2,USBD用于处理USB事务,DMA2用于处理DMA传输

         writel((readl(&gpioregs->MISCCR) & ~((1<<3) | (1<<13))), &gpioregs->MISCCR);

// USBD is selected instead of USBH1 

// USB port 1 is enabled.

//

//  USBD should be initialized first of all.

//

        isUsbdSetConfiguration=0;

 

        UsbdMain(); //主要配置函数

        Delay(10);

 

        writel((readl(&gpioregs->GPCDAT) | (1<<5)), &gpioregs->GPCDAT);

        //这个操作和Mini2440开发板有关,在USB 设备的信号线上D+上接上了一个GPC5的一个上拉电阻,当GPC5输出高电平的时候,主机的集线器才能检测到设备,从而给复位信号

 

 /* enable USB Device, thisway.diy */

#if USBDMA

        mode="DMA";   

#else

        mode="Int";

#endif

        download_run=0; //The default menu is the Download & Run mode.

        printk("USB slave is enable!n");

        //printk是我自己编写的打印函数

}

在配置完设备后,给GPC5一个高电平,主机就开始枚举设备的过程了。能不能开始这个过程关键是看设备是否配置正确。这就是要看UsbMain()这个函数了。他在usbmain.c中,如下:

void UsbdMain(void)

{

    InitDescriptorTable();

    ConfigUsbd(); 

    PrepareEp1Fifo(); 

}


这个函数挺简单,但是调用了三个函数可不简单。第一个就是初始化一些USB描述符,比如设备描述符,配置描述符等,在usb控制传输的时候返回给设备。这个函数在usbsetup.c中。PrepareEp1Fifo()是配置端点1的,这里没有用到。关键的是ConfigUsbd()函数,这个函数是最主要的配置函数。在usblib.c中:

void ConfigUsbd(void)

{

        struct s3c24x0_interrupt * intregs = s3c24x0_get_base_interrupt();

        ReconfigUsbd();

        writel((readl(&intregs->INTMSK) & ~(BIT_USBD)), &intregs->INTMSK);

}


这个函数是个封装函数,第一次配置调用他,并且开启中断。在重置USB的过程中调用的是ReconfigUsbd(),这个函数也在usblib.c中:

void ReconfigUsbd(void)

{

// *** End point information ***

//   EP0: control

//   EP1: bulk in end point

//   EP2: not used

//   EP3: bulk out end point

//   EP4: not used

struct s3c24x0_usb_device * const usbdevregs = s3c24x0_get_base_usb_device();   

 

writeb(PWR_REG_DEFAULT_VALUE, &usbdevregs->PWR_REG); //disable suspend mode

writeb(0, &usbdevregs->INDEX_REG); 

writeb(FIFO_SIZE_8, &usbdevregs->MAXP_REG); //EP0 max packit size = 8 

writeb((EP0_SERVICED_OUT_PKT_RDY | EP0_SERVICED_SETUP_END), & usbdevregs->EP0_CSR_IN_CSR1_REG); //EP0:clear OUT_PKT_RDY & SETUP_END

writeb(1, &usbdevregs->INDEX_REG); 

 

#if (EP1_PKT_SIZE==32)

writeb(FIFO_SIZE_32, &usbdevregs->MAXP_REG); //EP1:max packit size = 32

#else

writeb(FIFO_SIZE_64, &usbdevregs->MAXP_REG); //EP1:max packit size = 64

#endif

writeb((EPI_FIFO_FLUSH | EPI_CDT), &usbdevregs->EP0_CSR_IN_CSR1_REG); 

writeb((EPI_MODE_IN | EPI_IN_DMA_INT_MASK | EPI_BULK), &usbdevregs->IN_CSR2_REG);  //IN mode, IN_DMA_INT=masked    

writeb(EPO_CDT, &usbdevregs->OUT_CSR1_REG); 

writeb((EPO_BULK | EPO_OUT_DMA_INT_MASK), &usbdevregs->OUT_CSR2_REG); 

 

writeb(2, &usbdevregs->INDEX_REG); 

writeb(FIFO_SIZE_64, &usbdevregs->MAXP_REG); //EP2:max packit size = 64

writeb((EPI_FIFO_FLUSH | EPI_CDT | EPI_BULK), &usbdevregs->EP0_CSR_IN_CSR1_REG); 

writeb((EPI_MODE_IN | EPI_IN_DMA_INT_MASK), &usbdevregs->IN_CSR2_REG);  //IN mode, IN_DMA_INT=masked    

writeb(EPO_CDT, &usbdevregs->OUT_CSR1_REG); 

writeb((EPO_BULK | EPO_OUT_DMA_INT_MASK), &usbdevregs->OUT_CSR2_REG); 

 

writeb(3, &usbdevregs->INDEX_REG); 

    #if (EP3_PKT_SIZE==32)

writeb(FIFO_SIZE_32, &usbdevregs->MAXP_REG); //EP3:max packit size = 32

    #else

writeb(FIFO_SIZE_64, &usbdevregs->MAXP_REG); //EP3:max packit size = 64

    #endif

writeb((EPI_FIFO_FLUSH | EPI_CDT | EPI_BULK), &usbdevregs->EP0_CSR_IN_CSR1_REG);

writeb((EPI_MODE_OUT | EPI_IN_DMA_INT_MASK), &usbdevregs->IN_CSR2_REG); //OUT mode, IN_DMA_INT=masked    

writeb(EPO_CDT, &usbdevregs->OUT_CSR1_REG); 

    //clear OUT_PKT_RDY, data_toggle_bit.

//The data toggle bit should be cleared when initialization.

writeb((EPO_BULK | EPO_OUT_DMA_INT_MASK), &usbdevregs->OUT_CSR2_REG); 

 

writeb(4, &usbdevregs->INDEX_REG); 

writeb(FIFO_SIZE_64, &usbdevregs->MAXP_REG); //EP4:max packit size = 64

writeb((EPI_FIFO_FLUSH | EPI_CDT | EPI_BULK), &usbdevregs->EP0_CSR_IN_CSR1_REG); 

writeb((EPI_MODE_OUT | EPI_IN_DMA_INT_MASK), &usbdevregs->IN_CSR2_REG); //OUT mode, IN_DMA_INT=masked    

writeb(EPO_CDT, &usbdevregs->OUT_CSR1_REG); 

    //clear OUT_PKT_RDY, data_toggle_bit.

//The data toggle bit should be cleared when initialization.

writeb((EPO_BULK | EPO_OUT_DMA_INT_MASK), &usbdevregs->OUT_CSR2_REG); 

    

writeb((EP0_INT | EP1_INT | EP2_INT | EP3_INT | EP4_INT), &usbdevregs->EP_INT_REG); 

writeb((RESET_INT | SUSPEND_INT | RESUME_INT), &usbdevregs->USB_INT_REG); 

    //Clear all usbd pending bits

   

writeb((EP0_INT | EP1_INT | EP3_INT), &usbdevregs->EP_INT_EN_REG); 

writeb(RESET_INT, &usbdevregs->USB_INT_EN_REG); 

        ep0State = EP0_STATE_INIT;

    

}


可以看出首先是操作电源管理寄存器关闭自动挂起功能,然后就是针对每个端点来配置,主要设置端点的最大信息包的大小,端点类型,传输方向。以及是否支持DMA。最主要的是端点0与端点3因为其他三个端点没有用到。最后清除所有的中断状态寄存器的标志。


usb 设备控制器最主要的部分就是中断处理程序,本程序中的USB中断处理程序是void IsrUsbd(void),在usbmain.c中:

void IsrUsbd(void)

{

    struct s3c24x0_usb_device * const usbdevregs = s3c24x0_get_base_usb_device();

    U8 usbdIntpnd,epIntpnd;

    U8 saveIndexReg = readb(&usbdevregs->INDEX_REG);

 

    usbdIntpnd = readb(&usbdevregs->USB_INT_REG);

    epIntpnd = readb(&usbdevregs->EP_INT_REG);

//    printk( "[INT:EP_I=%x,USBI=%x]",epIntpnd,usbdIntpnd );

    if(usbdIntpnd&SUSPEND_INT)

    {

writeb(SUSPEND_INT, &usbdevregs->USB_INT_REG);

    // printk( "    }

    if(usbdIntpnd&RESUME_INT)

    {

writeb(RESUME_INT, &usbdevregs->USB_INT_REG);

    // printk("    }

    if(usbdIntpnd&RESET_INT)

    {

    // printk( "   

    //ResetUsbd();

    ReconfigUsbd();

writeb(RESET_INT, &usbdevregs->USB_INT_REG); //RESET_INT should be cleared after ResetUsbd().   

        PrepareEp1Fifo(); 

    }

    //以上三个是USB设备中断,主要用到的是复位中断,当GPC5引脚为高时,USB 插入主机,就会产生这个中断

    if(epIntpnd&EP0_INT)

    {

writeb(EP0_INT, &usbdevregs->EP_INT_REG);

    Ep0Handler();

    }

    //对于每个端点中断都有不同的处理程序,这个是端点0的处理程序。在设备枚举的过程中使用。

    if(epIntpnd&EP1_INT)

    {

writeb(EP1_INT, &usbdevregs->EP_INT_REG);

    Ep1Handler();

    }

    

    if(epIntpnd&EP2_INT)

    {

writeb(EP2_INT, &usbdevregs->EP_INT_REG);

    // printk("<2:TBD]n");   //not implemented yet

    //Ep2Handler();

    }

 

    if(epIntpnd&EP3_INT)

    {

writeb(EP3_INT, &usbdevregs->EP_INT_REG);

printk("Ep3handern");

    Ep3Handler();

    }

 

    if(epIntpnd&EP4_INT)

    {

writeb(EP4_INT, &usbdevregs->EP_INT_REG);

  //  printk("<4:TBD]n");   //not implemented yet

    //Ep4Handler();

    }

 

    ClearPending_my((int)BIT_USBD);  

writeb(saveIndexReg, &usbdevregs->INDEX_REG);    

[1] [2] [3]
关键字:S3C2440  USB  设备控制器 引用地址:S3C2440 USB 设备控制器

上一篇:基于mini2440的USB视频采集
下一篇:mini2440 IIC 裸机程序记录

推荐阅读最新更新时间:2024-11-19 23:59

s3c2440 移值u-boot-2016.03 第3篇 支持Nor flash 识别
当选择,NOR flash 启用时,才可以访问 NOR FLASH 。 /common/board_r.c 364 line: initr_flash() flash_size = flash_init(); /drivers/mtd/cfi_flash.c 想要打开调试的话, 就定义这个 #define DEBUG flash_init() debug( JEDEC PROBE: ID %x %x %xn , info- manufacturer_id, info- device_id, info- device_id2); if (jedec_flash_match(info, info- start )) break; /d
[单片机]
<font color='red'>s3c2440</font> 移值u-boot-2016.03 第3篇 支持Nor flash 识别
USB总线在光栅位移传感器检测系统中的应用
  由于光栅传感器测量精度高、动态测量范围广、可进行无接触测量、易实现系统的自动化和数字化,因而在机械工业中得到了广泛的应用。   特别是在量具、数控机床的闭环反馈控制、工作母机的坐标测量等方面,光栅传感器起着重要作用。   目前,USB端口已成为微机主板的标准端口,利用USB总线技术,开发适用于科学研究和工业生产的各种仪器仪表设备,借以取代传统计算机测 控系统中采用的串行RS232、并行接口以及ISA或PCI总线的仪器仪表设备,不仅可使计算机测控系统更加高效实时、方便灵活,而且可满足高质量、高可 靠性、低成本计算机测控系统的要求。本文以光栅位移传感器检测系统的设计背景,详细介绍了系统的硬件、软件设计方法。 光栅位移传感
[单片机]
安捷伦推出业界最低价位的USB 2.0 信号质量测试选件
北京,2013 年 2 月4 日——安捷伦科技有限公司(NYSE: A)日前宣布推出业内最低价位的 USB 2.0 信号质量测试选件。适用于 InfiniiVision 4000 X 系列示波器,支持低速、全速和高速的 USB2.0 应用。USB2.0 接口目前已广泛用于计算机和嵌入式电子产品中。 长期以来,示波器一直是电气工程师验证USB2.0设计信号完整性的主要工具。在 Agilent InfiniiVision 4000 X 系列示波器上安装新的 DSOX4USBSQ 信号质量测试选件后,您可以根据USB-IF标准来快速验证 USB 的信号质量,不管它是集线器、主机还是器件。 嵌入式电子产品工程师一般不会进行正式的 US
[测试测量]
TransferJet恐冲击USB地位
Sony于2008年和Panasonic、日立和三星电子等国际知名厂商共组「TransferJet Consortium」,以藉此共同确立「TransferJet」的相互连接规格,并以「TransferJet」的普及化为其目标。日前Sony也发表了内建TransferJet技术的笔电与数位相机等产品,试图藉此向消费大众叩关。未来如果TransferJet技术逐渐普及,最大受害者可能是消费市场短距有线传输第一把交椅的USB。 TransferJet为一种可将影像内容或音乐档,进行高速传输的无线传输技术,其资料传输速度最高可达560Mbps。且TransferJet有别于现行一般无线传输技术,在进行传输时无须繁复的连接设定也
[嵌入式]
S3C2440驱动篇—Linux平台设备驱动
在设备驱动程序中经常会见到和platform相关的字段,分布在驱动程序的多个角落,这也是2.6内核中比较重要的一种机制,把它原理弄懂,对以后分析驱动程序很有帮助:在linux2.6设备模型中,关心总线,设备,驱动这三个实体,总线将设备和驱动绑定,在系统每注册一个设备的时候,会寻找与之匹配的驱动。相反,在系统每注册一个驱动的时候,寻找与之匹配的设备,匹配是由总线来完成的。 一个现实的Linux 设备和驱动通常都需要挂接在一种总线上,对于本身依附于PCI、USB、I2C、SPI 等的设备而言,这自然不是问题,但是在嵌入式系统里面,SoC 系统中集成的独立的外设控制器、挂接在SoC 内存空间的外设等确不依附于此类总线。基于这一背景,Li
[单片机]
USB技术在可穿戴计算机中的应用
1 引言 在网络计算机已经开始逐步取代了个人计算机的二十世纪末期,新一代的可穿戴计算机(Wearable Computers)又悄然来到我们周围。可穿戴计算概念的提出为人与计算机的有机结合开创了一条新途径,是实现更加友好的人机交互的新技术之一。尽管可穿戴计算机的体积很小,但却具备了PC机的所有功能,例如语音输入与输出功能、视频输出功能、图像采集功能和无线通讯功能等等。这些功能不但需要各种不同的外围设备,而且要求外设接口的数据传输速度也要快,这无疑加重了外设接口设计的困难,也成为了可穿戴计算机设计中的瓶颈和关键技术之一。通用串行总线USB(Universal Serial Bus)是应用在PC领域的新型接口技术,是Intel、Comp
[嵌入式]
爆料:三星给Note10研发USB Type-C降噪耳机
IT之家7月11日消息 根据Sammobile的报道,三星Note10和Note10+的USB Type-C接口将兼作耳机接口,另据爆料人士Roland Quandt称,三星正在为下一代旗舰产品开发一种新的降噪USB Type-C耳机。不过,Quandt并未透露这款耳机是否会进行Akg调优,或是否会与Galaxy Note 10一同发售。   近日,新一批三星Galaxy Note10手机的渲染图也公布了,图片显示三星Note10将采用新的后置摄像头布局,三摄从中间移到了左上角,并且手机底部有单个扬声器,还有一个S Pen孔,没有3.5毫米耳机插孔。 据悉,三星已经正式宣布将于美国东部时间8月7日下午4点(北京
[手机便携]
首款10Gbps USB-C™ Re-Timer 投入量产,可用于PC、智能手机和VR
硅谷数模日前宣布,它的ANX74xx系列产品投入量产。该产品提供USB-C re-timer解决方案,可用于笔记本、平板电脑、台式机、智能手机和VR应用。硅谷数模的ANX74xx系列是首款通过了USB-IF和VESA plug测试的USB-C re-timer,这标志着它能够满足PC界的严苛要求。 ANX74xx系列产品能够在PC主板和USB/DisplayPort 线缆提供高信号吞吐能力,不受平台性能影响,确保信号完整,是第一款投入量产的USB-C re-timer,能够满足PC和配件市场需求。根据IHS的预测,2018年,PC市场USB-C端口数将达到5.14亿,到2019年,这一数字将增长为6.22亿。IHS还预测,一半
[半导体设计/制造]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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