×
单片机 > 单片机程序设计 > 详情

LPC1788做U盘的时候对命令的响应

发布时间:2020-06-06 发布时间:
|

首先是对于端点的数据处理

#ifndef __USBEP2_H_

#define __USBEP2_H_

 

#include "usb.h"

#include "usbhw.h"

#include "msc.h"

#include "mscuser.h"

 

void usb_ep2_in_process(void);

 

 

void usb_ep2_out_process(void);

 

#endif

 

#include "usbep2.h"

 

 

 

//批量输入事件

void usb_ep2_in_process(void)

{

    switch (BulkStage)

    {

       

    case MSC_BS_DATA_IN:

      switch (CBW.CB[0])

      {

        case SCSI_READ10:

          MSC_MemoryRead();//读取数据并等待下一次传输

          break;

      }

      break;

     

    case MSC_BS_DATA_IN_LAST:

      MSC_SetCSW();//上一次传输并且传输已经完成

      break;

     

    case MSC_BS_DATA_IN_LAST_STALL:

      USB_SetStallEP(MSC_EP_IN);

      MSC_SetCSW();

      break;

     

    case MSC_BS_CSW:

      BulkStage = MSC_BS_CBW;//简单的进行状态切换

      break;

  }

   

}

 

//批量输出事件

void usb_ep2_out_process(void)

{

    BulkLen = USB_ReadEP(MSC_EP_OUT, BulkBuf);//读取缓存

    switch (BulkStage)//根据阶段判定

    {

        case MSC_BS_CBW://最开始的阶段必然是命令阶段

            MSC_GetCBW();//获取并处理cbw命令

            break;

        case MSC_BS_DATA_OUT://数据输出阶段

            switch (CBW.CB[0]) //分辨写入指令

            {

            case SCSI_WRITE10:

                MSC_MemoryWrite();

                break;

            case SCSI_VERIFY10:

                MSC_MemoryVerify();

                break;

            }

        break;

        default://不支持的状态

        USB_SetStallEP(MSC_EP_OUT);

        CSW.bStatus = CSW_PHASE_ERROR;

        MSC_SetCSW();

        break;

    }

}

 

 

 

然后再在子程序中对命令详细分析

 

 

#ifndef __MSCUSER_H_

#define __MSCUSER_H_

#include "msc.h"

#include "usbhw.h"

#include "memory.h"

 

 

 

//批量传输节点的最大包长度

#define MSC_MAX_PACKET  64

 

//批量传输节点地址

#define MSC_EP_IN       0x82

#define MSC_EP_OUT      0x02

 

extern uint8_t  BulkStage;               //传输状态,指明下一次如何传输

extern uint8_t  BulkLen;                 //输出接点,主机输出的数据长度

extern uint8_t  BulkBuf[MSC_MAX_PACKET]; //数据缓存中心

 

extern MSC_CBW CBW;                     //cbw块

extern MSC_CSW CSW;                     //csw块

 

extern uint32_t  MemOK;                   /* 测试mem是否完好 */

 

 

 

#define MSC_DEBUG   0

 

#if MSC_DEBUG

#define msc_debug_printf(format,args...)    printf(format,##args)       //变参宏定义

#else

#define  msc_debug_printf(x,...)  while(0);

#endif

 

 

 

 

//枚举过程中的重要节点

extern uint32_t MSC_Reset     (void);

extern uint32_t MSC_GetMaxLUN (void);

 

//msc设备的方法

extern void MSC_GetCBW (void);

 

extern void MSC_SetCSW (void);

 

void MSC_MemoryRead (void) ;

 

void MSC_MemoryWrite(void);

 

void MSC_MemoryVerify(void);

 

 

#endif

 

 

 

#include "mscuser.h"

 

 

uint32_t  MemOK = __TRUE;                   /* 测试mem是否完好 */

 

uint32_t Offset;                  /* 读取写入的定位 */

uint32_t Length;                  /* 读取写入的长度 */

 

uint8_t  BulkStage;               /* 批量传输的阶段, 数据阶段 命令阶段 状态阶段 */

 

uint8_t  BulkBuf[MSC_MAX_PACKET]; /* 读取批量端点传输来的数据 */

uint8_t  BulkLen;                 /* 传输长度 */

 

MSC_CBW CBW;                   /*CBW结构体 */

MSC_CSW CSW;                   /*CSW结构体 */

 

 

#if NORFLASH

u8 usb_mac_global_buffer[MSC_MAX_PACKET];

#endif

 

#if NANDFLASH

u8 usb_mac_global_buffer[MSC_MAX_PACKET];

#endif

 

 

//msc设备复位

uint32_t MSC_Reset (void)

{

    BulkStage = MSC_BS_CBW;

    return (__TRUE);

}

 

//获取标号

uint32_t MSC_GetMaxLUN (void)

{

    EP0Buf[0] = 0;    //0为一个设备

    return (__TRUE);

}

 

 

//设备读取数据,在in阶段发送出去

void MSC_MemoryRead (void)

{

    uint32_t n;

    if (Length > MSC_MAX_PACKET) //根据长度来计算,不能大于包长度

    {

        n = MSC_MAX_PACKET;

    }

    else

    {

        n = Length;

    }

 

    if ((Offset + n) > MSC_MemorySize) //缓冲区最大长度

    {

        n = MSC_MemorySize - Offset;

        BulkStage = MSC_BS_DATA_IN_LAST_STALL;//传输失败的发送

    }

   

    #if NORFLASH

    NOR_FLASH_Read_Buffer_Mal(Offset,usb_mac_global_buffer,n);//读取数据

    USB_WriteEP(MSC_EP_IN, (u8*)usb_mac_global_buffer, n);

    #endif

   

    #if NANDFLASH

    while(nandReady == 0);

    nandReady = 0;

    NAND_Read_Addr_Mal(Offset,usb_mac_global_buffer,n);

    USB_WriteEP(MSC_EP_IN, (u8*)usb_mac_global_buffer, n);

    nandReady = 1;

    #endif

   

    Offset += n;

    Length -= n;//传输完成后对指针进行相应的处理

 

    CSW.dDataResidue -= n;

 

    if (Length == 0)

    {

        BulkStage = MSC_BS_DATA_IN_LAST;//数据传输成功

    }

 

    if (BulkStage != MSC_BS_DATA_IN) //上一次传输为0 ,命令通过

    {

        CSW.bStatus = CSW_CMD_PASSED;

    }

}

 

u8 norflash_buffer[2048] = {0};

 

//写入数据到设备

void MSC_MemoryWrite (void)

{

    if ((Offset + BulkLen) > MSC_MemorySize) //防止超界

    {

        BulkLen = MSC_MemorySize - Offset;

        BulkStage = MSC_BS_CSW;

        USB_SetStallEP(MSC_EP_OUT);

    }

   

    #if NORFLASH

    NOR_FLASH_Write_Mal(Offset,BulkBuf,BulkLen);   

    msc_idle_time_count = 0;//发生写入时,空闲时间设置为0

    #endif

   

    #if NANDFLASH

    while(nandReady == 0);

    nandReady = 0;

    NAND_Write_Addr_Mal(Offset,BulkBuf,BulkLen);

    nandReady = 1;

    msc_idle_time_count = 0;

    #endif

   

 

    Offset += BulkLen;//指针变换(写入和删除都有相应的执指针变化,自动切换位置)

    Length -= BulkLen;

 

    CSW.dDataResidue -= BulkLen;

 

    if ((Length == 0) || (BulkStage == MSC_BS_CSW))

    {

        CSW.bStatus = CSW_CMD_PASSED;

        MSC_SetCSW();//指令通过

    }

}

 

 

//数据校验

void MSC_MemoryVerify (void)

{

    uint32_t n;

 

    if ((Offset + BulkLen) > MSC_MemorySize)  //防止超界

    {

        BulkLen = MSC_MemorySize - Offset;

        BulkStage = MSC_BS_CSW;

        USB_SetStallEP(MSC_EP_OUT);

    }

   

    #if NORFLASH

    NOR_FLASH_Read_Buffer_Mal(Offset,usb_mac_global_buffer,BulkLen);

    for(n = 0; n 

    {

        if(usb_mac_global_buffer[n] != BulkBuf[n])

        {

            MemOK = __FALSE;

            break;

        }

    }

    #endif

   

    #if NANDFLASH

    while(nandReady == 0);

    nandReady = 0;

    NAND_Read_Addr_Mal(Offset,usb_mac_global_buffer,BulkLen);

    nandReady = 1;

    for(n = 0; n 

    {

        if(usb_mac_global_buffer[n] != BulkBuf[n])

        {

            MemOK = __FALSE;

            break;

        }

    }

    #endif

   

 

    Offset += BulkLen;

    Length -= BulkLen;

 

    CSW.dDataResidue -= BulkLen;

 

    if ((Length == 0) || (BulkStage == MSC_BS_CSW))

    {

        CSW.bStatus = (MemOK) ? CSW_CMD_PASSED : CSW_CMD_FAILED;//根据校验的最终状态,选择返回命令失败或者成功

        MSC_SetCSW();

    }

}

 

 

//usb实际与数据相关的处理工作

uint32_t MSC_RWSetup (void)

{

    uint32_t n;

 

    //首先获得逻辑地址对应的物理地址,主机发送下来的block地址,我们要转换成响应的nand block和nand page

    n = (CBW.CB[2] <

 

    Offset = n * MSC_BlockSize;//定位逻辑位置

 

    //需要传输的块数量

    n = (CBW.CB[7] <

        (CBW.CB[8] <

 

    //要传输的数据总长度

    Length = n * MSC_BlockSize;

 

    if (CBW.dDataLength != Length) //接受长度必须和发送的要读取长度计算一致,否则不能起作用

    {

        USB_SetStallEP(MSC_EP_IN);

        USB_SetStallEP(MSC_EP_OUT);

        CSW.bStatus = CSW_PHASE_ERROR;

        MSC_SetCSW();

        return (__FALSE);

    }

   

    return (__TRUE);//算好了,核心是offect 和length

}

 

 

//检测数据是否符合规则

uint32_t DataInFormat (void)

{

 

    if (CBW.dDataLength == 0) //检测数据长度

    {

        CSW.bStatus = CSW_PHASE_ERROR;

        MSC_SetCSW();

        return (__FALSE);

    }

    if ((CBW.bmFlags & 0x80) == 0) //检测数据方向

    {

        USB_SetStallEP(MSC_EP_OUT);

        CSW.bStatus = CSW_PHASE_ERROR;

        MSC_SetCSW();

        return (__FALSE);

    }

    return (__TRUE);//数据ok

}

 

 

void DataInTransfer (void)

{

 

    if (BulkLen > CBW.dDataLength) {

        BulkLen = CBW.dDataLength;

    }

 

    USB_WriteEP(MSC_EP_IN, BulkBuf, BulkLen);

    BulkStage = MSC_BS_DATA_IN_LAST;

 

    CSW.dDataResidue -= BulkLen;

    CSW.bStatus = CSW_CMD_PASSED;

}

 

 

//scsi指明测试存储单元是否准备好

void MSC_TestUnitReady (void)

{

 

    if (CBW.dDataLength != 0) //发送来的cbw不带数据就准备好了

    {

        if ((CBW.bmFlags & 0x80) != 0)

        {

            USB_SetStallEP(MSC_EP_IN);//设置断点暂停

        } else

        {

            USB_SetStallEP(MSC_EP_OUT);

        }

    }

    #if NANDFLASH

    if(nandReady == 0)MemOK = __FALSE;

    else MemOK = __TRUE;

    #endif

   

    if(MemOK == __TRUE)

    {

        CSW.bStatus = CSW_CMD_PASSED;//准备好存储空间

        MSC_SetCSW();

    }

    else

    {

        CSW.bStatus = CSW_CMD_FAILED;//还没准备好存储空间

        MSC_SetCSW();

    }

   

    #if NORFLASH

    if(msc_idle_time_count 

    else NOR_FLASH_Flush();

    #endif

   

    #if NANDFLASH

    if(msc_idle_time_count 

    else Nand_Flush();

    #endif

}

 

 

//检测上一次传输失败的原因 返回失败原因代码

void MSC_RequestSense (void)

{

 

    if (!DataInFormat()) return;

 

    BulkBuf[ 0] = 0x70;          //错误代码,固定为0x70

    BulkBuf[ 1] = 0x00;         //保留

    BulkBuf[ 2] = 0x00;         //Sense Key为0x05,表示无效请求(ILLEGAL REQUEST)

    BulkBuf[ 3] = 0x00;         //Information为0 四个字节

    BulkBuf[ 4] = 0x00;

    BulkBuf[ 5] = 0x00;

    BulkBuf[ 6] = 0x00;

    BulkBuf[ 7] = 0x0A;          //附加数据长度为10字节

    BulkBuf[ 8] = 0x00;          //保留 四字节

    BulkBuf[ 9] = 0x00;

    BulkBuf[10] = 0x00;

    BulkBuf[11] = 0x00;

    BulkBuf[12] = 0x00;          //Additional Sense Code(ASC)为0x20,表示无效命令操作码(INVALID COMMAND OPERATION CODE)

    BulkBuf[13] = 0x00;          //Additional Sense Code Qualifier(ASCQ)为0

    BulkBuf[14] = 0x00;          //保留 四字节

    BulkBuf[15] = 0x00;

    BulkBuf[16] = 0x00;

    BulkBuf[17] = 0x00;

 

    if (CBW.CB[4] <= 18)

    {

        BulkLen = CBW.CB[4];

    }

    else

    {

        BulkLen = 18;

    }

    DataInTransfer();

}

 

void MSC_Inquiry (void)

{

 

    if (!DataInFormat()) return;

 

    BulkBuf[ 0] = 0x00;          //磁盘设备

    BulkBuf[ 1] = 0x80;          //其中最高位D7为RMB。RMB=0,表示不可移除设备。如果RMB=1,则为可移除设备。

    BulkBuf[ 2] = 0x00;          //各种版本号0

    BulkBuf[ 3] = 0x01;          //数据响应格式

 

    BulkBuf[ 4] = 36-4;          //附加数据长度,为32字节

    BulkBuf[ 5] = 0x80;          /* SCCS = 1: Storage Controller Component */

    BulkBuf[ 6] = 0x00;          //保留

    BulkBuf[ 7] = 0x00;          //保留

 

    BulkBuf[ 8] = 'D';           //厂商标识

    BulkBuf[ 9] = 'I';

    BulkBuf[10] = 'N';

    BulkBuf[11] = 'K';

    BulkBuf[12] = ' ';

    BulkBuf[13] = ' ';

    BulkBuf[14] = ' ';

    BulkBuf[15] = ' ';

 

    BulkBuf[16] = 'D';           //产品标识,

    BulkBuf[17] = 'E';

    BulkBuf[18] = 'N';

    BulkBuf[19] = 'G';

    BulkBuf[20] = 'X';

    BulkBuf[21] = 'I';

    BulkBuf[22] = 'A';

    BulkBuf[23] = 'O';

    BulkBuf[24] = 'J';

    BulkBuf[25] = 'U';

    BulkBuf[26] = 'N';

    BulkBuf[27] = 'D';

    BulkBuf[28] = 'I';

    BulkBuf[29] = 'S';

    BulkBuf[30] = 'K';

    BulkBuf[31] = ' ';

 

    BulkBuf[32] = '1';           //产品版本号

    BulkBuf[33] = '.';

    BulkBuf[34] = '0';

    BulkBuf[35] = ' ';

 

    BulkLen = 36;

    DataInTransfer();

}

 

//scsi响应函数

void MSC_ModeSense6 (void)

{

 

    if (!DataInFormat()) return;

 

    BulkBuf[ 0] = 0x03;

    BulkBuf[ 1] = 0x00;

    BulkBuf[ 2] = 0x00;

    BulkBuf[ 3] = 0x00;

 

    BulkLen = 4;

    DataInTransfer();

}

 

void MSC_ModeSense10 (void) {

 

    if (!DataInFormat()) return;

 

    BulkBuf[ 0] = 0x00;

    BulkBuf[ 1] = 0x06;

    BulkBuf[ 2] = 0x00;

    BulkBuf[ 3] = 0x00;

    BulkBuf[ 4] = 0x00;

    BulkBuf[ 5] = 0x00;

    BulkBuf[ 6] = 0x00;

    BulkBuf[ 7] = 0x00;

 

    BulkLen = 8;

    DataInTransfer();

}

 

//读取设备的实际容量

void MSC_ReadCapacity (void)

{

 

    if (!DataInFormat()) return;

 

    //最大逻辑块大小 因为逻辑块从0开始,所以需要-1

    BulkBuf[ 0] = ((MSC_BlockCount - 1) >> 24) & 0xFF;

    BulkBuf[ 1] = ((MSC_BlockCount - 1) >> 16) & 0xFF;

    BulkBuf[ 2] = ((MSC_BlockCount - 1) >>  8) & 0xFF;

    BulkBuf[ 3] = ((MSC_BlockCount - 1) >>  0) & 0xFF;

 

    //逻辑块长度

    BulkBuf[ 4] = (MSC_BlockSize >> 24) & 0xFF;

    BulkBuf[ 5] = (MSC_BlockSize >> 16) & 0xFF;

    BulkBuf[ 6] = (MSC_BlockSize >>  8) & 0xFF;

    BulkBuf[ 7] = (MSC_BlockSize >>  0) & 0xFF;

 

    BulkLen = 8;

    DataInTransfer();

}

 

//读格式化容量信息,返回最大能格式化的数据信息

void MSC_ReadFormatCapacity (void)

{

 

    if (!DataInFormat()) return;

 

    BulkBuf[ 0] = 0x00;

    BulkBuf[ 1] = 0x00;

    BulkBuf[ 2] = 0x00;

    BulkBuf[ 3] = 0x08;          //容量列表描述符长度

 

    //设备块数量 正对于不同的介质这里可以有不同的设置

    BulkBuf[ 4] = (MSC_BlockCount >> 24) & 0xFF;

    BulkBuf[ 5] = (MSC_BlockCount >> 16) & 0xFF;

    BulkBuf[ 6] = (MSC_BlockCount >>  8) & 0xFF;

    BulkBuf[ 7] = (MSC_BlockCount >>  0) & 0xFF;

 

    //每一块的长度

    BulkBuf[ 8] = 0x02;                     /* Descriptor Code: Formatted Media */

    BulkBuf[ 9] = (MSC_BlockSize >> 16) & 0xFF;

    BulkBuf[10] = (MSC_BlockSize >>  8) & 0xFF;

    BulkBuf[11] = (MSC_BlockSize >>  0) & 0xFF;

 

    BulkLen = 12;

    DataInTransfer();

}

 

void MSC_GetCBW (void)

{

    uint32_t n;//将buf数据拷贝入cbw结构体,便于下一次处理

    for (n = 0; n 

    {

        *((uint8_t *)&CBW + n) = BulkBuf[n];

    }

    if ((BulkLen == sizeof(CBW)) && (CBW.dSignature == MSC_CBW_Signature)) //检测命令长度以及命令头 usbc

    {

        //完整有效地cbw

        CSW.dTag = CBW.dTag;//发送来的cbw需要csw返回,csw的tag必须对应发送来的cbw tag

        CSW.dDataResidue = CBW.dDataLength;//需要传输的数据长度

        if ((CBW.bLUN != 0) || (CBW.bCBLength  16) //目标逻辑单元不对或者长度不对都会导致命令失败

        {

fail: CSW.bStatus = CSW_CMD_FAILED;//命令失败,0x01

            MSC_SetCSW();//返回失败csw

        }

        else

        {

            switch (CBW.CB[0]) //检测命令代码,进行散转处理

            {

            case SCSI_TEST_UNIT_READY://测试设备是否准备好

                MSC_TestUnitReady();

                msc_debug_printf("SCSI_TEST_UNIT_READY\r\n");

                break;

            case SCSI_REQUEST_SENSE://检测上一次传输失败的原因

                MSC_RequestSense();

                msc_debug_printf("SCSI_REQUEST_SENSE\r\n");

                break;

            case SCSI_FORMAT_UNIT:  //格式化单元,不支持

                msc_debug_printf("SCSI_FORMAT_UNIT\r\n");

                goto fail;

            case SCSI_INQUIRY: 

                MSC_Inquiry();      //查询设备的基本信息

                msc_debug_printf("SCSI_INQUIRY\r\n");

                break;

            case SCSI_START_STOP_UNIT://不支持

                msc_debug_printf("SCSI_START_STOP_UNIT\r\n");

                goto fail;

            case SCSI_MEDIA_REMOVAL:

                CSW.bStatus = CSW_CMD_PASSED;

                MSC_SetCSW();//返回失败csw

                msc_debug_printf("SCSI_MEDIA_REMOVAL\r\n");

                //goto fail;

                break;

            case SCSI_MODE_SELECT6://不支持

                msc_debug_printf("SCSI_MODE_SELECT6\r\n");

                goto fail;

            case SCSI_MODE_SENSE6://不知干嘛的

                MSC_ModeSense6();

                msc_debug_printf("SCSI_MODE_SENSE6\r\n");

                break;

            case SCSI_MODE_SELECT10:

                msc_debug_printf("SCSI_MODE_SELECT10\r\n");

                goto fail;

            case SCSI_MODE_SENSE10:

                MSC_ModeSense10();

                msc_debug_printf("SCSI_MODE_SENSE10\r\n");

                break;

            case SCSI_READ_FORMAT_CAPACITIES://读格式化容量信息

                MSC_ReadFormatCapacity();

                msc_debug_printf("SCSI_READ_FORMAT_CAPACITIES\r\n");

                break;

            case SCSI_READ_CAPACITY://读容量信息

                MSC_ReadCapacity();

                msc_debug_printf("SCSI_READ_CAPACITY\r\n");

                break;

            case SCSI_READ10://读取实际的磁盘数据

                if (MSC_RWSetup())

                {

                    if ((CBW.bmFlags & 0x80) != 0) //方向没有错误

                    {

                        BulkStage = MSC_BS_DATA_IN;//数据输入状态,下次in事件来的时候就能传输正确数据

                        MSC_MemoryRead();

                        msc_debug_printf("SCSI_READ10 right\r\n");

                    }

                    else

                    {

                        USB_SetStallEP(MSC_EP_OUT);//方向错误,暂停端点

                        CSW.bStatus = CSW_CMD_FAILED;

                        MSC_SetCSW();

                        msc_debug_printf("SCSI_READ10 error\r\n");

                    }

                }

                break;

            case SCSI_WRITE10://写入实际磁盘数据

                if (MSC_RWSetup())

                {

                    if ((CBW.bmFlags & 0x80) == 0) //检查方向

                    {

                        BulkStage = MSC_BS_DATA_OUT;//说明下一次out带来就是要写入数据,修改设备的状态

                        msc_debug_printf("SCSI_WRITE10 right\r\n");

                    }

                    else

                    {

                        USB_SetStallEP(MSC_EP_IN);//命令不支持(核心思想状态机)

                        CSW.bStatus = CSW_PHASE_ERROR;

                        MSC_SetCSW();

                        msc_debug_printf("SCSI_WRITE10 error\r\n");

                    }

                }

                msc_debug_printf("SCSI_WRITE10\r\n");

                break;

            case SCSI_VERIFY10://校验数据

                if (MSC_RWSetup())

                {

                    if ((CBW.bmFlags & 0x80) == 0)

                    {

                        BulkStage = MSC_BS_DATA_OUT;

                        MemOK = __TRUE;//直接返回数据校验ok

                    }

                    else

                    {

                        USB_SetStallEP(MSC_EP_IN);

                        CSW.bStatus = CSW_PHASE_ERROR;//方向不对,命令错误

                        MSC_SetCSW();

                    }

                }

                msc_debug_printf("SCSI_VERIFY10\r\n");

                break;

            default:

                goto fail;

                }

        }

    }

    else

    {//无效的cbw指令,直接禁用全部端点,等待usb重新设置端点 从错误中恢复

        USB_SetStallEP(MSC_EP_IN);

        USB_SetStallEP(MSC_EP_OUT);

        BulkStage = MSC_BS_ERROR;

        msc_debug_printf("无效的cbw指令\r\n");

    }

}

 

 

//设备返回的状态封包

void MSC_SetCSW (void) {

 

    CSW.dSignature = MSC_CSW_Signature;

    USB_WriteEP(MSC_EP_IN, (uint8_t *)&CSW, sizeof(CSW));

    BulkStage = MSC_BS_CSW;

}

 

 

Usb大容量存储器的宏如下

 

#ifndef __MSC_H__

#define __MSC_H__

#include "sys.h"

 

/* MSC Subclass Codes */

#define MSC_SUBCLASS_RBC                0x01

#define MSC_SUBCLASS_SFF8020I_MMC2      0x02

#define MSC_SUBCLASS_QIC157             0x03

#define MSC_SUBCLASS_UFI                0x04

#define MSC_SUBCLASS_SFF8070I           0x05

#define MSC_SUBCLASS_SCSI               0x06

 

/* MSC Protocol Codes */

#define MSC_PROTOCOL_CBI_INT            0x00

#define MSC_PROTOCOL_CBI_NOINT          0x01

#define MSC_PROTOCOL_BULK_ONLY          0x50

 

 

/* MSC Request Codes */

#define MSC_REQUEST_RESET               0xFF

#define MSC_REQUEST_GET_MAX_LUN         0xFE

 

 

/* MSC Bulk-only Stage */

#define MSC_BS_CBW                      0       /* Command Block Wrapper */

#define MSC_BS_DATA_OUT                 1       /* Data Out Phase */

#define MSC_BS_DATA_IN                  2       /* Data In Phase */

#define MSC_BS_DATA_IN_LAST             3       /* Data In Last Phase */

#define MSC_BS_DATA_IN_LAST_STALL       4       /* Data In Last Phase with Stall */

#define MSC_BS_CSW                      5       /* Command Status Wrapper */

#define MSC_BS_ERROR                    6       /* Error */

 

 

typedef __packed struct _MSC_CBW {

  uint32_t dSignature;  //cbw标志  为USBC四个字符

  uint32_t dTag;        //cbw标签,返回csw的时候需要添加

  uint32_t dDataLength; //需要在数据阶段传送的字节数,低字节在前

  uint8_t  bmFlags;     //cbw标志,最高位标识数据方向

  uint8_t  bLUN;        //目标逻辑单元编号,仅仅使用低四位

  uint8_t  bCBLength;   //cbw cb的长度,使用低五位

  uint8_t  CB[16];      //选择执行的命令,由选择的子类决定使用的命令,(一般是scsi命令集)

} MSC_CBW;

 

typedef __packed struct _MSC_CSW {

  uint32_t dSignature;  //csw标志,为字符 usbs

  uint32_t dTag;    //命令状态标签,从cbw的标签中来

  uint32_t dDataResidue;    //命令完成时的完成字节数

  uint8_t  bStatus; //命令执行状态 00代表执行成功

} MSC_CSW;

 

#define MSC_CBW_Signature               0x43425355  //usbc

#define MSC_CSW_Signature               0x53425355  //usbs

 

 

/* CSW Status Definitions */

#define CSW_CMD_PASSED                  0x00

#define CSW_CMD_FAILED                  0x01

#define CSW_PHASE_ERROR                 0x02

 

 

/* SCSI Commands */

#define SCSI_TEST_UNIT_READY            0x00

#define SCSI_REQUEST_SENSE              0x03

#define SCSI_FORMAT_UNIT                0x04

#define SCSI_INQUIRY                    0x12

#define SCSI_MODE_SELECT6               0x15

#define SCSI_MODE_SENSE6                0x1A

#define SCSI_START_STOP_UNIT            0x1B

#define SCSI_MEDIA_REMOVAL              0x1E

#define SCSI_READ_FORMAT_CAPACITIES     0x23

#define SCSI_READ_CAPACITY              0x25

#define SCSI_READ10                     0x28

#define SCSI_WRITE10                    0x2A

#define SCSI_VERIFY10                   0x2F

#define SCSI_MODE_SELECT10              0x55

#define SCSI_MODE_SENSE10               0x5A

 

 

#endif 

 

 

 

在之前的代码中会调用两个存储设备读写命令,如下

 

#ifndef __MEMORY_H_

#define __MEMORY_H_

#include "sst39vf32.h"

#include "k9f1g08.h"

#include "hy57v256.h"

 

#define NORFLASH    0

#define NANDFLASH   1

 

 

 

#if NORFLASH

 

#define MSC_MemorySize  NOR_FLASH_SIZE  //norflash大小

#define MSC_BlockSize   SECTOR_SIZE     //norflash扇区大小

#define MSC_BlockCount  SECTOR_COUNT    //norflash扇区总数

 

extern u8 msc_idle_time_count;

 

#define MSC_IDLE_TIME_LIMIT     90

 

#endif

 

 

 

#if NANDFLASH

 

#define MSC_MemorySize  NAND_USE_NUMOF_BLOCK*NAND_PAGE_NUM*NAND_SERECT_SIZE //nand flash大小

#define MSC_BlockSize   NAND_SERECT_SIZE            //nand flash扇区大小

#define MSC_BlockCount  NAND_USE_NUMOF_BLOCK*NAND_PAGE_NUM  //nand flash扇区数量

 

extern u8 msc_idle_time_count;

 

#define MSC_IDLE_TIME_LIMIT     90

 

#endif

 

#endif

 

 

#include "memory.h"

 

#if NORFLASH

 

u8 msc_idle_time_count; //岣дȫĿՏЊ䍊

#endif

 

 

#if NANDFLASH

 

u8 msc_idle_time_count;

 

#endif



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
TQ210天嵌开发板S5PV210 LED闪烁程序C语言代码记录