第九章 Mass Storage设备
9.1 Mass Storage设备介绍
USB的Mass Storage类是USB大容量储存设备类(Mass Storage Device Class)。专门用于大容量存储设备,比如U盘、移动硬盘、USB CD-ROM、读卡器等。在日常生活中经常用到。USB Mass Storage设备开发相对简单。
9.2 MSC数据类型
usbdmsc.h中已经定义好MSC设备类中使用的所有数据类型和函数。下面介绍MSC设备类使用的数据类型。
typedef enum
{
//设备加入
USBDMSC_MEDIA_PRESENT,
//设备移出
USBDMSC_MEDIA_NOTPRESENT,
//设备未知
USBDMSC_MEDIA_UNKNOWN
}
tUSBDMSCMediaStatus;
tUSBDMSCMediaStatus,定义存储设备状态。定义在usbdmsc.h。USBDMSCMediaChange()函数用手修改此状态。
typedef struct
{
//open函数指针,用户自己完成该函数编写
void *(* Open)(unsigned long ulDrive);
//Close函数指针,用户自己完成该函数编
void (* Close)(void * pvDrive);
// BlockRead函数指针,用于读取存储设备,用户自己完成该函数编
unsigned long (* BlockRead)(void * pvDrive, unsigned char *pucData,
unsigned long ulSector,
unsigned long ulNumBlocks);
// BlockWrite函数指针,用于写入存储设备,用户自己完成该函数编
unsigned long (* BlockWrite)(void * pvDrive, unsigned char *pucData,
unsigned long ulSector,
unsigned long ulNumBlocks);
// 读取当前扇区数
unsigned long (* NumBlocks)(void * pvDrive);
}
tMSCDMedia;
tMSCDMedia,存储设备底层操作驱动。用于MSC设备对存储设备操作。
typedef struct
{
unsigned long ulUSBBase;
tDeviceInfo *psDevInfo;
tConfigDescriptor *psConfDescriptor;
unsigned char ucErrorCode;
unsigned char ucSenseKey;
unsigned short usAddSenseCode;
void *pvMedia;
volatile tBoolean bConnected;
unsigned long ulFlags;
tUSBDMSCMediaStatus eMediaStatus;
unsigned long pulBuffer[DEVICE_BLOCK_SIZE>>2];
unsigned long ulBytesToTransfer;
unsigned long ulCurrentLBA;
unsigned char ucINEndpoint;
unsigned char ucINDMA;
unsigned char ucOUTEndpoint;
unsigned char ucOUTDMA;
unsigned char ucInterface;
unsigned char ucSCSIState;
}
tMSCInstance;
tMSCInstance,MSC设备类实例。定义了MSC设备类的USB基地址、设备信息、IN端点、OUT端点等信息。
typedef struct
{
unsigned short usVID;
unsigned short usPID;
unsigned char pucVendor[8];
unsigned char pucProduct[16];
unsigned char pucVersion[4];
unsigned short usMaxPowermA;
unsigned char ucPwrAttributes;
const unsigned char * const *ppStringDescriptors;
unsigned long ulNumStringDescriptors;
tMSCDMedia sMediaFunctions;
tUSBCallback pfnEventCallback;
tMSCInstance *psPrivateData;
}
tUSBDMSCDevice;
tUSBDMSCDevice,MSC设备类,定义了VID、PID、电源属性、字符串描述符等,还包括了一个MSC设备类实例。其它设备描述符、配置信息通过API函数储入tMSCInstance定义的MSC设备实例中。
9.3 API函数
在MSC设备类API库中定义了4个函数,完成USB MSC设备初始化、配置及数据处理。下面为usbdMSC.h中定义的API函数:
void *USBDMSCInit(unsigned long ulIndex,
const tUSBDMSCDevice *psMSCDevice);
void *USBDMSCCompositeInit(unsigned long ulIndex,
const tUSBDMSCDevice *psMSCDevice);
void USBDMSCTerm(void *pvInstance);
void USBDMSCMediaChange(void *pvInstance,
tUSBDMSCMediaStatus eMediaStatus);
void *USBDMSCInit(unsigned long ulIndex,
const tUSBDMSCDevice *psMSCDevice);
作用:初始化MSC设备硬件、协议,把其它配置参数填入psMSCDevice实例中。
参数:ulIndex,USB模块代码,固定值:USB_BASE0。psMSCDevice,MSC设备类。
返回:指向配置后的tUSBDMSCDevice。
void *USBDMSCCompositeInit(unsigned long ulIndex,
const tUSBDMSCDevice *psMSCDevice);
作用:初始化MSC设备协议,本函数在USBDMSCInit中已经调用。
参数:ulIndex,USB模块代码,固定值:USB_BASE0。psMSCDevice,MSC设备类。
返回:指向配置后的tUSBDMSCDevice。
void USBDMSCTerm(void *pvInstance);
作用:结束MSC设备。
参数:pvInstance,指向tUSBDMSCDevice。
返回:无。
void USBDMSCMediaChange(void *pvInstance,
tUSBDMSCMediaStatus eMediaStatus);
作用:存储设备状态改变。
参数:pvInstance,指向tUSBDMSCDevice。
返回:无。
在这些函数中USBDMSCInit函数最重要并且使用最多,USBDMSCInit第一次使用MSC设备时,用于初始化MSC设备的配置与控制。其它数据访问、控制处理由中断直接调用tMSCDMedia定义的5个底层驱动函数完成。
9.4 MSC设备开发
MSC设备开发只需要5步就能完成。如图2所示,MSC设备配置(主要是字符串描述符)、callback函数编写、存储设备底层驱动编写、USB处理器初始化、数据处理。
<ignore_js_op>



图2
下面以“USB转UART”实例说明使用USB库开发USB MSC类过程:
第一步:MSC设备配置(主要是字符串描述符),按字符串描述符标准完成串描述符配置,进而完成MSC设备配置。
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_gpio.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/rom.h"
#include "driverlib/systick.h"
#include "driverlib/usb.h"
#include "driverlib/udma.h"
#include "usblib/usblib.h"
#include "usblib/usb-ids.h"
#include "usblib/device/usbdevice.h"
#include "usblib/device/usbdmsc.h"
#include "diskio.h"
#include "usbdsdcard.h"
//声明函数原型
unsigned long USBDMSCEventCallback(void *pvCBData, unsigned long ulEvent,
unsigned long ulMsgParam,
void *pvMsgData);
const tUSBDMSCDevice g_sMSCDevice;
//msc状态
volatile enum
{
MSC_DEV_DISCONNECTED,
MSC_DEV_CONNECTED,
MSC_DEV_IDLE,
MSC_DEV_READ,
MSC_DEV_WRITE,
}
g_eMSCState;
//全局标志
#define FLAG_UPDATE_STATUS 1
static unsigned long g_ulFlags;
//DMA
tDMAControlTable sDMAControlTable[64] __attribute__ ((aligned(1024)));
//****************************************************************************
// 语言描述符
//****************************************************************************
const unsigned char g_pLangDescriptor[] =
{
4,
USB_DTYPE_STRING,
USBShort(USB_LANG_EN_US)
};
//****************************************************************************
// 制造商 字符串 描述符
//****************************************************************************
const unsigned char g_pManufacturerString[] =
{
(17 + 1) * 2,
USB_DTYPE_STRING,
'T', 0, 'e', 0, 'x', 0, 'a', 0, 's', 0, ' ', 0, 'I', 0, 'n', 0, 's', 0,
't', 0, 'r', 0, 'u', 0, 'm', 0, 'e', 0, 'n', 0, 't', 0, 's', 0,
};
//****************************************************************************
//产品 字符串 描述符
//****************************************************************************
const unsigned char g_pProductString[] =
{
(19 + 1) * 2,
USB_DTYPE_STRING,
'M', 0, 'a', 0, 's', 0, 's', 0, ' ', 0, 'S', 0, 't', 0, 'o', 0, 'r', 0,
'a', 0, 'g', 0, 'e', 0, ' ', 0, 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0,
'e', 0
};
//****************************************************************************
// 产品 序列号 描述符
//****************************************************************************
const unsigned char g_pSerialNumberString[] =
{
(8 + 1) * 2,
USB_DTYPE_STRING,
'1', 0, '2', 0, '3', 0, '4', 0, '5', 0, '6', 0, '7', 0, '8', 0
};
//*****************************************************************************
// 设备接口字符串描述符
//*****************************************************************************
const unsigned char g_pDataInterfaceString[] =
{
(19 + 1) * 2,
USB_DTYPE_STRING,
'B', 0, 'u', 0, 'l', 0, 'k', 0, ' ', 0, 'D', 0, 'a', 0, 't', 0,
'a', 0, ' ', 0, 'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0,
'a', 0, 'c', 0, 'e', 0
};
//*****************************************************************************
// 设备配置字符串描述符
//*****************************************************************************
const unsigned char g_pConfigString[] =
{
(23 + 1) * 2,
USB_DTYPE_STRING,
'B', 0, 'u', 0, 'l', 0, 'k', 0, ' ', 0, 'D', 0, 'a', 0, 't', 0,
'a', 0, ' ', 0, 'C', 0, 'o', 0, 'n', 0, 'f', 0, 'i', 0, 'g', 0,
'u', 0, 'r', 0, 'a', 0, 't', 0, 'i', 0, 'o', 0, 'n', 0
};
//*****************************************************************************
// 字符串描述符集合
//*****************************************************************************
const unsigned char * const g_pStringDescriptors[] =
{
g_pLangDescriptor,
g_pManufacturerString,
g_pProductString,
g_pSerialNumberString,
g_pDataInterfaceString,
g_pConfigString
};
#define NUM_STRING_DESCRIPTORS (sizeof(g_pStringDescriptors) / \
sizeof(unsigned char *))
//*****************************************************************************
//MSC实例,配置并为设备信息提供空间
//*****************************************************************************
tMSCInstance g_sMSCInstance;
//*****************************************************************************
//设备配置
//*****************************************************************************
const tUSBDMSCDevice g_sMSCDevice =
{
USB_VID_STELLARIS,
USB_PID_MSC,
"TI ",
"Mass Storage ",
"1.00",
500,
USB_CONF_ATTR_SELF_PWR,
g_pStringDescriptors,
NUM_STRING_DESCRIPTORS,
{
USBDMSCStorageOpen,
USBDMSCStorageClose,
USBDMSCStorageRead,
USBDMSCStorageWrite,
USBDMSCStorageNumBlocks
},
USBDMSCEventCallback,
&g_sMSCInstance
};
#define MSC_BUFFER_SIZE 512
第二步:完成Callback函数。Callback函数用于返回数据处理状态:
//*****************************************************************************
//callback函数
//*****************************************************************************
unsigned long USBDMSCEventCallback(void *pvCBData, unsigned long ulEvent,
unsigned long ulMsgParam, void *pvMsgData)
{
switch(ulEvent)
{
// 正在写数据到存储设备.
case USBD_MSC_EVENT_WRITING:
{
if(g_eMSCState != MSC_DEV_WRITE)
{
g_eMSCState = MSC_DEV_WRITE;
g_ulFlags |= FLAG_UPDATE_STATUS;
}
break;
}
//读取数据.
case USBD_MSC_EVENT_READING:
{
if(g_eMSCState != MSC_DEV_READ)
{
g_eMSCState = MSC_DEV_READ;
g_ulFlags |= FLAG_UPDATE_STATUS;
}
break;
}
//空闲
case USBD_MSC_EVENT_IDLE:
default:
{
break;
}
}
return(0);
}
第三步:完成接口函数编写:
#define SDCARD_PRESENT 0x00000001
#define SDCARD_IN_USE 0x00000002
struct
{
unsigned long ulFlags;
}
g_sDriveInformation;
//*****************************************************************************
// 打开存储设备
//*****************************************************************************
void * USBDMSCStorageOpen(unsigned long ulDrive)
{
unsigned char ucPower;
unsigned long ulTemp;
// 检查是否在使用.
if(g_sDriveInformation.ulFlags & SDCARD_IN_USE)
{
return(0);
}
// 初始化存储设备.
ulTemp = disk_initialize(0);
if(ulTemp == RES_OK)
{
//打开电源
ucPower = 1;
disk_ioctl(0, CTRL_POWER, &ucPower);
//设置标志.
g_sDriveInformation.ulFlags = SDCARD_PRESENT | SDCARD_IN_USE;
}
else if(ulTemp == STA_NODISK)
{
// 没有存储设备.
g_sDriveInformation.ulFlags = SDCARD_IN_USE;
}
else
{
return(0);
}
return((void *)&g_sDriveInformation);
}
//*****************************************************************************
// 关闭存储设备
//*****************************************************************************
void USBDMSCStorageClose(void * pvDrive)
{
unsigned char ucPower;
g_sDriveInformation.ulFlags = 0;
ucPower = 0;
disk_ioctl(0, CTRL_POWER, &ucPower);
}
//*****************************************************************************
// 读取扇区数据
//*****************************************************************************
unsigned long USBDMSCStorageRead(void * pvDrive,
unsigned char *pucData,
unsigned long ulSector,
unsigned long ulNumBlocks)
{
if(disk_read (0, pucData, ulSector, ulNumBlocks) == RES_OK)
{
return(ulNumBlocks * 512);
}
return(0);
}
//*****************************************************************************
// 写数据到扇区
//*****************************************************************************
unsigned long USBDMSCStorageWrite(void * pvDrive,
unsigned char *pucData,
unsigned long ulSector,
unsigned long ulNumBlocks)
{
if(disk_write(0, pucData, ulSector, ulNumBlocks) == RES_OK)
{
return(ulNumBlocks * 512);
}
return(0);
}
//*****************************************************************************
// 获取当前扇区
//*****************************************************************************
unsigned long USBDMSCStorageNumBlocks(void * pvDrive)
{
unsigned long ulSectorCount;
disk_ioctl(0, GET_SECTOR_COUNT, &ulSectorCount);
return(ulSectorCount);
}
#define USBDMSC_IDLE 0x00000000
#define USBDMSC_NOT_PRESENT 0x00000001
//*****************************************************************************
// 存储设备当前状态
//*****************************************************************************
unsigned long USBDMSCStorageStatus(void * pvDrive);
第四步:系统初始化,配置内核电压、系统主频、使能端口、等。系统初始化:
//系统初始化。
SysCtlLDOSet(SYSCTL_LDO_2_75V);
SysCtlClockSet(SYSCTL_XTAL_8MHZ | SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN );
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,0xf0);
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE,0x0f);
HWREG(GPIO_PORTF_BASE+GPIO_O_PUR) |= 0x0f;
// ucDMA配置
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
SysCtlDelay(10);
uDMAControlBaseSet(&sDMAControlTable[0]);
uDMAEnable();
g_ulFlags = 0;
g_eMSCState = MSC_DEV_IDLE;
//msc设备初始化
USBDMSCInit(0, (tUSBDMSCDevice *)&g_sMSCDevice);
//初始化存储设备
disk_initialize(0);
第五步:状态处理,其它控制。
while(1)
{
switch(g_eMSCState)
{
case MSC_DEV_READ:
{
if(g_ulFlags & FLAG_UPDATE_STATUS)
{
g_ulFlags &= ~FLAG_UPDATE_STATUS;
}
break;
}
case MSC_DEV_WRITE:
{
if(g_ulFlags & FLAG_UPDATE_STATUS)
{
g_ulFlags &= ~FLAG_UPDATE_STATUS;
}
break;
}
case MSC_DEV_IDLE:
default:
{
break;
}
}
}
使用上面五步就完成MSC设备开发。MSC设备开发时要加入两个lib库函数: usblib.lib和DriverLib.lib,在启动代码中加入USB0DeviceIntHandler中断服务函数。以上MSC设备开发完成,在Win xp下运行效果如下图所示:
<ignore_js_op>
在枚举过程中可以看出,在电脑右下脚可以看到“Mass Storage Device”字样,标示正在进行枚举,并手手动安装驱动。枚举成功后,在“设备管理器”的“通用串行总线控制器”中看到“USB Mass Storage Device”设备,如下图。现在MSC设备可以正式使用。
<ignore_js_op>
MSC设备可以在“我的电脑”中“有可移动存储的设备”找到:
<ignore_js_op>
MSC设备开发源码较多,下面只列出一部分如下:
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_gpio.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/rom.h"
#include "driverlib/systick.h"
#include "driverlib/usb.h"
#include "driverlib/udma.h"
#include "usblib/usblib.h"
#include "usblib/usb-ids.h"
#include "usblib/device/usbdevice.h"
#include "usblib/device/usbdmsc.h"
#include "diskio.h"
#include "usbdsdcard.h"
//声明函数原型
unsigned long USBDMSCEventCallback(void *pvCBData, unsigned long ulEvent,
unsigned long ulMsgParam,
void *pvMsgData);
const tUSBDMSCDevice g_sMSCDevice;
//msc状态
volatile enum
{
MSC_DEV_DISCONNECTED,
MSC_DEV_CONNECTED,
MSC_DEV_IDLE,
MSC_DEV_READ,
MSC_DEV_WRITE,
}
g_eMSCState;
//全局标志
#define FLAG_UPDATE_STATUS 1
static unsigned long g_ulFlags;
//DMA
tDMAControlTable sDMAControlTable[64] __attribute__ ((aligned(1024)));
//****************************************************************************
// 语言描述符
//****************************************************************************
const unsigned char g_pLangDescriptor[] =
{
4,
USB_DTYPE_STRING,
USBShort(USB_LANG_EN_US)
};
//****************************************************************************
// 制造商 字符串 描述符
//****************************************************************************
const unsigned char g_pManufacturerString[] =
{
(17 + 1) * 2,
USB_DTYPE_STRING,
'T', 0, 'e', 0, 'x', 0, 'a', 0, 's', 0, ' ', 0, 'I', 0, 'n', 0, 's', 0,
't', 0, 'r', 0, 'u', 0, 'm', 0, 'e', 0, 'n', 0, 't', 0, 's', 0,
};
//****************************************************************************
//产品 字符串 描述符
//****************************************************************************
const unsigned char g_pProductString[] =
{
(19 + 1) * 2,
USB_DTYPE_STRING,
'M', 0, 'a', 0, 's', 0, 's', 0, ' ', 0, 'S', 0, 't', 0, 'o', 0, 'r', 0,
'a', 0, 'g', 0, 'e', 0, ' ', 0, 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0,
'e', 0
};
//****************************************************************************
// 产品 序列号 描述符
//****************************************************************************
const unsigned char g_pSerialNumberString[] =
{
(8 + 1) * 2,
USB_DTYPE_STRING,
'1', 0, '2', 0, '3', 0, '4', 0, '5', 0, '6', 0, '7', 0, '8', 0
};
//*****************************************************************************
// 设备接口字符串描述符
//*****************************************************************************
const unsigned char g_pDataInterfaceString[] =
{
(19 + 1) * 2,
USB_DTYPE_STRING,
'B', 0, 'u', 0, 'l', 0, 'k', 0, ' ', 0, 'D', 0, 'a', 0, 't', 0,
'a', 0, ' ', 0, 'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0,
'a', 0, 'c', 0, 'e', 0
};
//*****************************************************************************
// 设备配置字符串描述符
//*****************************************************************************
const unsigned char g_pConfigString[] =
{
(23 + 1) * 2,
USB_DTYPE_STRING,
'B', 0, 'u', 0, 'l', 0, 'k', 0, ' ', 0, 'D', 0, 'a', 0, 't', 0,
'a', 0, ' ', 0, 'C', 0, 'o', 0, 'n', 0, 'f', 0, 'i', 0, 'g', 0,
'u', 0, 'r', 0, 'a', 0, 't', 0, 'i', 0, 'o', 0, 'n', 0
};
//*****************************************************************************
// 字符串描述符集合
//*****************************************************************************
const unsigned char * const g_pStringDescriptors[] =
{
g_pLangDescriptor,
g_pManufacturerString,
g_pProductString,
g_pSerialNumberString,
g_pDataInterfaceString,
g_pConfigString
};
#define NUM_STRING_DESCRIPTORS (sizeof(g_pStringDescriptors) / \
sizeof(unsigned char *))
//*****************************************************************************
//MSC实例,配置并为设备信息提供空间
//*****************************************************************************
tMSCInstance g_sMSCInstance;
//*****************************************************************************
//设备配置
//*****************************************************************************
const tUSBDMSCDevice g_sMSCDevice =
{
USB_VID_STELLARIS,
USB_PID_MSC,
"TI ",
"Mass Storage ",
"1.00",
500,
USB_CONF_ATTR_SELF_PWR,
g_pStringDescriptors,
NUM_STRING_DESCRIPTORS,
{
USBDMSCStorageOpen,
USBDMSCStorageClose,
USBDMSCStorageRead,
USBDMSCStorageWrite,
USBDMSCStorageNumBlocks
},
USBDMSCEventCallback,
&g_sMSCInstance
};
#define MSC_BUFFER_SIZE 512
//*****************************************************************************
//callback函数
//*****************************************************************************
unsigned long USBDMSCEventCallback(void *pvCBData, unsigned long ulEvent,
unsigned long ulMsgParam, void *pvMsgData)
{
switch(ulEvent)
{
// 正在写数据到存储设备.
case USBD_MSC_EVENT_WRITING:
{
if(g_eMSCState != MSC_DEV_WRITE)
{
g_eMSCState = MSC_DEV_WRITE;
g_ulFlags |= FLAG_UPDATE_STATUS;
}
break;
}
//读取数据.
case USBD_MSC_EVENT_READING:
{
if(g_eMSCState != MSC_DEV_READ)
{
g_eMSCState = MSC_DEV_READ;
g_ulFlags |= FLAG_UPDATE_STATUS;
}
break;
}
//空闲
case USBD_MSC_EVENT_IDLE:
default:
{
break;
}
}
return(0);
}
//*****************************************************************************
//主函数
//*****************************************************************************
int main(void)
{
//系统初始化。
SysCtlLDOSet(SYSCTL_LDO_2_75V);
SysCtlClockSet(SYSCTL_XTAL_8MHZ | SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN );
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,0xf0);
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE,0x0f);
HWREG(GPIO_PORTF_BASE+GPIO_O_PUR) |= 0x0f;
// ucDMA配置
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
SysCtlDelay(10);
uDMAControlBaseSet(&sDMAControlTable[0]);
uDMAEnable();
g_ulFlags = 0;
g_eMSCState = MSC_DEV_IDLE;
//msc设备初始化
USBDMSCInit(0, (tUSBDMSCDevice *)&g_sMSCDevice);
//初始化存储设备
disk_initialize(0);
while(1)
{
switch(g_eMSCState)
{
case MSC_DEV_READ:
{
if(g_ulFlags & FLAG_UPDATE_STATUS)
{
g_ulFlags &= ~FLAG_UPDATE_STATUS;
}
break;
}
case MSC_DEV_WRITE:
{
if(g_ulFlags & FLAG_UPDATE_STATUS)
{
g_ulFlags &= ~FLAG_UPDATE_STATUS;
}
break;
}
case MSC_DEV_IDLE:
default:
{
break;
}
}
}
}
第九章 Mass Storage设备的更多相关文章
- 利用mass storage class 做免驱动usb设备.
当需要使用usb bulk传输,想让设备像串口通讯那样和PC主机通信, 通常需要自己做一个PC端的驱动,比较麻烦. 为避免在pc上编写usb设备驱动的麻烦,可以将设备做成mass storage 类的 ...
- USB mass storage协议
这一节主要把在实现“linux模拟U盘功能”过程中的一些调试过程记录下来,并加以解析. 一.背景知识 1.USB Mass Storage类规范概述 USB 组织在univers ...
- USB Mass Storage学习笔记-STM32+FLASH实现U盘
一.内容概述 采用STM32内部自带USB控制器外加大页NAND FLASH K9F1G08U0A实现一个128M的U盘. 1.STM32的USB控制器 STM32F103的MCU自带USB从控制器 ...
- USB Mass Storage协议分析
目录 简介 指令数据和状态协议 CBW指令格式 CSWCommand Status Wrapper状态格式 SCSI命令集 Format Unit Inquiry MODE SELECT 简介 USB ...
- 精通Web Analytics 2.0 (11) 第九章: 新兴分析—社交,移动和视频
精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第九章: 新兴分析-社交,移动和视频 网络在过去几年中发生了不可思议的发展变化:从单向对话到双向对话的转变; 由视频,Ajax和 ...
- 第九章:四大组件之Broadcast Receiver
第九章:四大组件之Broadcast Receiver 一.广播的功能和特征 广播的生命周期很短,经过调用对象-->实现onReceive-->结束,整个过程就结束了.从实现的复杂度和 ...
- 第九章 C语言在嵌入式中的应用
上章回顾 编码的规范和程序版式 版权管理和申明 头文件结构和作用 程序命名 程序注释和代码布局规范 assert断言函数的应用 与0或NULL值的比较 内存的分配和释放细节,避免内存泄露 常量特性 g ...
- Laxcus大数据管理系统2.0(11)- 第九章 容错
第九章 容错 在当前,由于集群庞大的组织体系和复杂性,以及用户普遍要求低成本硬件,使得集群在运行过程中发生的错误概率,远远高于单一且性能稳定的小型机服务器,并且集群在运行过程中几乎是不允许停止的,这就 ...
- [转]Windows Shell 编程 第九章 【来源:http://blog.csdn.net/wangqiulin123456/article/details/7987969】
第九章 图标与Windows任务条 如果问一个非程序人员Windows最好的特色是什么,得到的答案应该是系统最有吸引力的图标.无论是Windows98现在支持的通用串行总线(USB)还是WDM(看上去 ...
随机推荐
- 第二十七篇、使用MVVM布局页面
思路:架构的设计模式主要有这么两种 >MVC :这种方式用得很多,也很是常见,不在过多的介绍 >MVVM:使用这种 常常需要导入第三方框架,常见的是响应式框架 >主要讲一下ViewM ...
- java中实现多态的机制是什么?
多态性是面向对象程序设计代码重用的一个重要机制,我们曾不只一次的提到Java多态性.在Java运行时多态性:继承和接口的实现一文中,我们曾详细介绍了Java实现运行时多态性的动态方法调度:今天我们再次 ...
- File Operation using SHFileOperation
SHFILEOPSTRUCT Original link: http://winapi.freetechsecrets.com/win32/WIN32SHFILEOPSTRUCT.htm Refere ...
- think完全还原原形的 SQL
$dd = Db::getInstance(); //实例连接数据库$sql = "SELECT * FROM `yezi_friendlinks`"; // SQL$ ...
- div之间有间隙以及img和div之间有间隙的原因及解决方法
原因: div 中 存在 img标签,由于img标签的 display:inline-block 属性. display:inline-block布局的元素在chrome下会出现几像素的间隙,原因是因 ...
- 最完美解决Nginx部署ThinkPHP项目的办法
网上通用解决方法的配置如下: server { ... location / { index index.htm index.html index.php; #访问路径的文件不存在则重写URL转交给T ...
- Python 基础篇:字符串、列表操作
字符串操作 判断是否为数字 string = "200" string.isdigit() >>false 待完善.. 列表操作 列表是我们最以后最常用的数据类型之一, ...
- ORA-12012 error on auto execute of job 8887
*** ACTION NAME:(AUTO_SPACE_ADVISOR_JOB) -- ::58.046 *** MODULE NAME:(DBMS_SCHEDULER) -- ::58.046 ** ...
- RHEL 6.4 64bit kettle5.01导入xlsx格式的excel时报错
环境:RHEL 6.4 64bit : kettle5.01:xlsx格式的excel 创建的job,在spoon里面运行都没有问题(Linux和windows) 在windows的命令行运行也没有问 ...
- Python多线程启动http.server
OS: Windows 8.1 with update 关键字:Python3.4, http.server, Thread 例子代码如下: import os from threading impo ...