S3C2440 之USB设备篇

来源:互联网 发布:卷皮淘宝客 编辑:程序博客网 时间:2024/05/22 16:44

S3C2440 之USB 设备篇

S3C2440 有2 个USB 主机接口和1 个USB 设备接口, 本篇讲述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 个端点,EP0 ,EP1 ,EP2 ,EP3 ,EP4, 。

   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 使能,表示全速设备,然后设置USBD1 为USB 设备,禁止USB 挂起,这样调用 UsbdMain(); 进行必要的初始化,这样就准备完成了。

当我们把2440 的USB 口插入到电脑主机的时候,会产生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 0