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

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

#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 < BulkLen;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 < BulkLen;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] << 24) |(CBW.CB[3] << 16) |(CBW.CB[4] <<  8) | (CBW.CB[5] <<  0);

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

//需要传输的块数量

n = (CBW.CB[7] <<  8) |

(CBW.CB[8] <<  0);

//要传输的数据总长度

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 < MSC_IDLE_TIME_LIMIT)msc_idle_time_count++;//设备空闲时间(没发生写入的时间)

else NOR_FLASH_Flush();

#endif

#if NANDFLASH

if(msc_idle_time_count < MSC_IDLE_TIME_LIMIT)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 < BulkLen; 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 < 1) || 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

时间: 2024-10-05 23:37:47

LPC1788做U盘的时候对命令的响应的相关文章

网盘的倒掉是不可避免的,因为做网盘的成本是非常巨大的(国内几大网盘就剩百度云、天翼云、和彩云),中国的独服太贵

作者:冯硕链接:http://www.zhihu.com/question/51803053/answer/127549782来源:知乎著作权归作者所有,转载请联系作者获得授权. 很正常的情况.目前全国所有的网盘商均处于巨亏的状态,撤退是非常正确的选择.我在这个回答下新浪微盘为什么要停止个人免费服务?有什么影响? - 冯硕的回答 就说过这个问题了.网盘的倒掉是不可避免的,因为做网盘的成本是非常巨大的.现在活着的网盘,大家且用且珍惜.当时新浪微盘倒掉的时候,我的确准考虑做网盘方面的业务.当时我不仅

做网盘难啊

做网盘难啊要养一堆客户端研发,界面丑要被骂要养一堆服务端研发,不稳定丢了文件要被骂要养一堆安全人员,泄露隐私要被骂要养一堆机器学习的人做反黄,做得差会被喝茶,做得好会被骂还有带宽费用,限速了也要被骂而且还没什么人愿意付费,做网盘的老板心里苦啊 有些人说你弄到大数据了也赚了,只有你心里知道,狗屁的大数据. 作者:王码修链接:http://www.zhihu.com/question/51803053/answer/127582337来源:知乎著作权归作者所有,转载请联系作者获得授权.

使用USBWriter做U盘启动盘后容量变小的解决办法

环境windows10 , 以administrator登录: 1. 按下windows键盘上的Win+R键, 输入cmd 2. 输入DiskPart, 回车,  然后弹出新的命令行窗口 3. 在弹出的新的命令行窗口继续输入: Microsoft DiskPart 版本 10.0.14393.0 Copyright (C) 1999-2013 Microsoft Corporation.在计算机上: LG DISKPART> list disk     #列出当前系统上所有磁盘 磁盘 ### 

为什么用U盘做启动盘

U盘做为电子时代的产物,从1.44M的软盘到最初的32M.256M,直到现在的8G.16G,甚至容量更大的U盘.是移动存储的变革,更是电子技术发展的见证. 操作系统是计算机的灵魂,他能使电子器件灵动起来.但是安装OS曾经也是一件技术活.以前还得用系统光盘,没有半天是完不成的.但现在Ghost的出现,使系统安装变成了非常快捷的事.随着光驱的退去,U盘做为读取速度快,容量大,即插即用的特点,被广泛的应用起来.U盘容量的增大,为之配套的系统安装软件也来了.成为各商家和店家的首选了.U盘做为启动盘要利用

NotifyIcon - 做拖 盘图标的

属性:Text - 拖盘文字Icon - 拖盘图标ContextMenuStrip - 右击时候的菜单. 右键菜单.ContextMenuStrip1.学会编辑菜单项. - 是分隔线.2.如何设置热键 &字母3.如何设快捷键.右击菜单项,在属性中选择ShortCutKey中的组合键即可4.如何给菜单项加图标?5.右击菜单项,选择属性,设置Image 把右键菜单挂到拖盘图标上.右击NotifyIcon1,选择属性.设置ContextMenuStrip 工具条:1.会加按钮并设置按钮的图像及文字2.

QT 做软件盘

最近搞了一个组织细胞脱水机项目,当然,对于国内的项目都是仿来仿去的,我们也不例外,开启被仿机器后,第一个看到的界面就是用户登录界面,需要输入中文,作为一个程序员,我的第一反应就是我需要采用什么用的框架来做这个界面,方向是多方面的,肯定会选择自己熟悉的一个,自然而然,我选择了QT来做界面,但是QT并没有像安卓,iOS,C#等支持得那么完美,毕竟做的人不是那么多,所以相对不是那么完美.我们没有鼠标键盘这样的外设,所有的用户交互都是通过触摸显示屏.这里碰到的第一个问题就是:QT软键盘制作.下面进入正题

实习先做一点事——菜鸟学习常用命令

一些简单常用的命令实习的时候也需要使用,书到用时方恨少~赶紧补习一下吧 1.ls  当前目录的清单 2.cd 切换目录 现在在根目录下,如果不在根目录可以使用cd ..逐步退回到根目录 跳转到指定目录,从根目录开始,目录名称前加 / ,当前目录内的子目录直接写名称即可(注意cd后面一个空格) 以上,进入根目录下users/kiki 以下从根目录进入到users/kiki/kikis 进入当前用户主目录(当前用户主目录与根目录不是同一个概念) cd ~ 返回进入此目录之前所在的目录  cd - 3

(4)分布式下的爬虫Scrapy应该如何做-规则自动爬取及命令行下传参

本次探讨的主题是规则爬取的实现及命令行下的自定义参数的传递,规则下的爬虫在我看来才是真正意义上的爬虫. 我们选从逻辑上来看,这种爬虫是如何工作的: 我们给定一个起点的url link ,进入页面之后提取所有的ur 链接,我们定义一个规则,根据规则(用正则表达式来限制)来提取我们想要的连接形式,然后爬取这些页面,进行一步的处理(数据提取或者其它动作),然后循环上述操作,直到停止,这个时候有一个潜在的问题,就是重复爬取,在scrapy 的框架下已经着手处理了这些问题,一般来说,对于爬取过滤的问题,通

三层交换机做DHCP详细教程及步骤命令

实验名称:3层交换机开启DHCP功能实验目的:实现实现环境: 终端设备:PC0:192.168.10.0/24 vlan10PC1:192.168.20.0/24 vlan20PC2:192.168.30.0/24 vlan30PC3:192.168.40.0/24 vlan40 交换机:SW2/SW3/SW0/SW1多层交换机MSW0 实验思路交换机:1为4台交换机创建VLAN10-40,并为其对应接口配置access或trunk链路多层交换机1开启路由转发功能2为其配置与2层交换机连接端口的