S3C2440 之USB设备篇

    技术2024-08-12  64

                  S3C2440 USB 设备篇

    S3C2440 2USB 主机接口和1USB 设备接口, 本篇讲述USB 设备接口。

    1 USB 的分类及主机接口和设备接口的区别

    1.1USB2.0 按照速度分为以下三类

    High-speed USB2.0 :理论速度480Mbps ,对应之前的USB2.0 Full-speed USB2.0 :理论速度12Mbps ,也就是过去的USB1.1 Low-speed USB2.0 :理论速度1.5Mbps ,这个一般用于鼠标、键盘等对速度要求不高的外部设备。

     

    1.2 低速USB  全速USB 硬件设备接口的区别

    USB 通过D-,D+ 信号的状态判断设备的插入,如下图所示,D+ 接上拉电阻为全速设备,D- 接下拉为低速设备。

     

    1.3 MINI2440USB 设备接口的区别

          Mini2440 开发板只有一个USB 主机接口和一个USB 设备接口,均为USB 全速接口。Mini2440 USB 设备的D+ 是由GPC5 来控制的,如果GPC5 输出高电平,则D+ 上相当于通过上拉电阻接到+5V ,则设备启用;如果GPC5 输出低电平,则D+ 上相当于通过下拉电阻接到GND ,则设备禁用。

     

    2 S3C2440USB 设备的固件枚举过程分析

    2.1 S3C2440 USB 设备的端点

       2440 5 个端点,EP0EP1EP2EP3EP4,

       EP0 是用于USB 设备枚举,传输方式为control 方式。EP1 EP4 用于数据传输。端点的传输方向有两种,IN OUT ,这个由 IN_CSR2_REG 来配置。

      端点的传输方式,批量(bulk ),中断(interrupt )也是由 IN_CSR2_REG 来配置。

    由上图看到,BIT6 用于配置是 批量模式,BIT5 用于配置传输方向。

     

    2.2 S3C2440 USB 程序分析

          整个USB 枚举过程其实是很简单的,首先进行USB 时钟的初始化,设置为48MHz ;然后GPC5 使能,表示全速设备,然后设置USBD1USB 设备,禁止USB 挂起,这样调用 UsbdMain(); 进行必要的初始化,这样就准备完成了。

    当我们把2440USB 口插入到电脑主机的时候,会产生USB 设备复位中断,我们在设备复位中断中进行一些初始化,整个枚举就进入到一个状态机中,一步一步直到枚举完成。

     

    // 初始化USB 设备时钟 48MHZ

           ChangeUPllValue(0x38,2,2); // UCLK=48Mhz

     

           // GPC5 使能, 输出为高电平, 表示全速设备

           rGPCCON &= ~(3<<10);

           rGPCCON |=  (1<<10); // output

           rGPCUP  |=  (1<<5);  // pullup disable

           rGPCDAT |=  (1<<5);  // ourtput 

     

           rMISCCR=rMISCCR&~(1<<3);  // USBD1 设置为设备( 不是主机)

           rMISCCR=rMISCCR&~(1<<13); // USBD1 设置为普通模式( 不是挂起模式)

           UsbdMain();

        while(1)

           {

    delay();

    }

     

    我们看下函数UsbdMain 的定义

    void UsbdMain(void)

    {

        InitDescriptorTable();   // 初始化设备描述符

     

        ConfigUsbd();          // USB 配置

     

        PrepareEp1Fifo();       // 端点1 初始化

    }

     

    我们看下函数ConfigUsbd

    void ConfigUsbd(void)

    {

        ReconfigUsbd();       // 重新配置USB

     

        pISR_USBD =(unsigned)IsrUsbd;  // 安装中断函数

        ClearPending(BIT_USBD);        // 清除USB 中断挂起标记

        rINTMSK&=~(BIT_USBD);       // 允许USB 中断

    }

     

    void ReconfigUsbd(void)

    {

    // *** End point information ***

    //   EP0: control

    //   EP1: bulk in end point

    //   EP2: not used

    //   EP3: bulk out end point

    //   EP4: not used

     

    // 禁止设备进入挂起模式( 正常模式)

    rPWR_REG=PWR_REG_DEFAULT_VALUE;   

     

        rINDEX_REG=0;

    //EP0 max packit size = 8         最大数据包

        rMAXP_REG=FIFO_SIZE_8;       

    //EP0:clear OUT_PKT_RDY & SETUP_END

    rEP0_CSR=EP0_SERVICED_OUT_PKT_RDY|EP0_SERVICED_SETUP_END;  

         

        rINDEX_REG=1;

        #if (EP1_PKT_SIZE==32)

    //EP1:max packit size = 32

            rMAXP_REG=FIFO_SIZE_32;

        #else

    //EP1:max packit size = 64

          rMAXP_REG=FIFO_SIZE_64;  

        #endif

     

        rIN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT;

    //IN mode, IN_DMA_INT=masked, 端点方向为IN, 批量传输模式, 中断禁止.

        rIN_CSR2_REG=EPI_MODE_IN|EPI_IN_DMA_INT_MASK|EPI_BULK;

     

        rOUT_CSR1_REG=EPO_CDT;    

        rOUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;    

     

        rINDEX_REG=2;

    //EP2:max packit size = 64

        rMAXP_REG=FIFO_SIZE_64; 

        rIN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;

    //IN mode, IN_DMA_INT=masked   

        rIN_CSR2_REG=EPI_MODE_IN|EPI_IN_DMA_INT_MASK;

        rOUT_CSR1_REG=EPO_CDT;    

        rOUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;    

                                                                                        

        rINDEX_REG=3;

         #if (EP3_PKT_SIZE==32)

    //EP3:max packit size = 32

            rMAXP_REG=FIFO_SIZE_32;

         #else

    //EP3:max packit size = 64

           rMAXP_REG=FIFO_SIZE_64;   

        #endif

           //OUT mode, IN_DMA_INT=masked   

        rIN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;

     

        rIN_CSR2_REG=EPI_MODE_OUT|EPI_IN_DMA_INT_MASK;

        rOUT_CSR1_REG=EPO_CDT;    

         //clear OUT_PKT_RDY, data_toggle_bit.

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

        rOUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;    

     

        rINDEX_REG=4;

        rMAXP_REG=FIFO_SIZE_64;  //EP4:max packit size = 64

        rIN_CSR1_REG=EPI_FIFO_FLUSH|EPI_CDT|EPI_BULK;

    //OUT mode, IN_DMA_INT=masked    

        rIN_CSR2_REG=EPI_MODE_OUT|EPI_IN_DMA_INT_MASK;

    //clear OUT_PKT_RDY, data_toggle_bit.

        rOUT_CSR1_REG=EPO_CDT;    

            

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

        rOUT_CSR2_REG=EPO_BULK|EPO_OUT_DMA_INT_MASK;    

       

    // 清除中断标记位

        rEP_INT_REG=EP0_INT|EP1_INT|EP2_INT|EP3_INT|EP4_INT;

    //Clear all usbd pending bits

        rUSB_INT_REG=RESET_INT|SUSPEND_INT|RESUME_INT;        

            

            

        //EP0,1,3 & reset interrupt are enabled

    // 中断使能寄存器

        rEP_INT_EN_REG=EP0_INT|EP1_INT|EP3_INT;      

    // USB 复位中断使能

        rUSB_INT_EN_REG=RESET_INT;                               

    // 端点0 状态设置为初始化

        ep0State=EP0_STATE_INIT;                                

    }

     

    void IsrUsbd(void)

    {

        U8 usbdIntpnd,epIntpnd;

        U8 saveIndexReg=rINDEX_REG;

        usbdIntpnd=rUSB_INT_REG;   // 读取USB 中断寄存器

        epIntpnd=rEP_INT_REG;       // 读取断点中断寄存器

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

     

        if(usbdIntpnd&SUSPEND_INT)

        {

               rUSB_INT_REG=SUSPEND_INT;

               DbgPrintf( "<SUS]");

        }

        if(usbdIntpnd&RESUME_INT)

        {

               rUSB_INT_REG=RESUME_INT;

               DbgPrintf("<RSM]");

        }

        if(usbdIntpnd&RESET_INT)   // 收到复位信号, 重新配置USB 设备配置

        {

               DbgPrintf( "<RST]"); 

              

                  // 中断标记清零

               rUSB_INT_REG = RESET_INT;  //RESET_INT should be cleared after ResetUsbd().     

     

                  //ResetUsbd();

               ReconfigUsbd();

     

                  Test();  //PrepareEp1Fifo();

           

        }

     

        if(epIntpnd&EP0_INT)

        {

               rEP_INT_REG=EP0_INT; 

               Ep0Handler();

        }

        if(epIntpnd&EP1_INT)

        {

              rEP_INT_REG=EP1_INT; 

               Ep1Handler();

        }

     

        if(epIntpnd&EP2_INT)

        {

               rEP_INT_REG=EP2_INT; 

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

               //Ep2Handler();

        }

     

        if(epIntpnd&EP3_INT)

        {

               rEP_INT_REG=EP3_INT;

               Ep3Handler();

        }

     

        if(epIntpnd&EP4_INT)

        {

               rEP_INT_REG=EP4_INT;

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

               //Ep4Handler();

        }

     

        ClearPending(BIT_USBD);   

       

        rINDEX_REG=saveIndexReg;

    }

     

    void Test()

    {

        U8 in_csr1;

        rINDEX_REG=1;

        in_csr1=rIN_CSR1_REG;

        SET_EP1_IN_PKT_READY();

    }

    最新回复(0)