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设备的更多相关文章

  1. 利用mass storage class 做免驱动usb设备.

    当需要使用usb bulk传输,想让设备像串口通讯那样和PC主机通信, 通常需要自己做一个PC端的驱动,比较麻烦. 为避免在pc上编写usb设备驱动的麻烦,可以将设备做成mass storage 类的 ...

  2. USB mass storage协议

    这一节主要把在实现“linux模拟U盘功能”过程中的一些调试过程记录下来,并加以解析. 一.背景知识     1.USB Mass Storage类规范概述        USB 组织在univers ...

  3. USB Mass Storage学习笔记-STM32+FLASH实现U盘

    一.内容概述  采用STM32内部自带USB控制器外加大页NAND FLASH K9F1G08U0A实现一个128M的U盘. 1.STM32的USB控制器 STM32F103的MCU自带USB从控制器 ...

  4. USB Mass Storage协议分析

    目录 简介 指令数据和状态协议 CBW指令格式 CSWCommand Status Wrapper状态格式 SCSI命令集 Format Unit Inquiry MODE SELECT 简介 USB ...

  5. 精通Web Analytics 2.0 (11) 第九章: 新兴分析—社交,移动和视频

    精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第九章: 新兴分析-社交,移动和视频 网络在过去几年中发生了不可思议的发展变化:从单向对话到双向对话的转变; 由视频,Ajax和 ...

  6. 第九章:四大组件之Broadcast Receiver

    第九章:四大组件之Broadcast Receiver   一.广播的功能和特征 广播的生命周期很短,经过调用对象-->实现onReceive-->结束,整个过程就结束了.从实现的复杂度和 ...

  7. 第九章 C语言在嵌入式中的应用

    上章回顾 编码的规范和程序版式 版权管理和申明 头文件结构和作用 程序命名 程序注释和代码布局规范 assert断言函数的应用 与0或NULL值的比较 内存的分配和释放细节,避免内存泄露 常量特性 g ...

  8. Laxcus大数据管理系统2.0(11)- 第九章 容错

    第九章 容错 在当前,由于集群庞大的组织体系和复杂性,以及用户普遍要求低成本硬件,使得集群在运行过程中发生的错误概率,远远高于单一且性能稳定的小型机服务器,并且集群在运行过程中几乎是不允许停止的,这就 ...

  9. [转]Windows Shell 编程 第九章 【来源:http://blog.csdn.net/wangqiulin123456/article/details/7987969】

    第九章 图标与Windows任务条 如果问一个非程序人员Windows最好的特色是什么,得到的答案应该是系统最有吸引力的图标.无论是Windows98现在支持的通用串行总线(USB)还是WDM(看上去 ...

随机推荐

  1. 一般处理程序生成简单的图片验证码并通过html验证用户输入的验证码是否正确

    一般处理程序生成简单的图片验证码并通过html验证用户输入的验证码是否正确       最近没事研究了下验证码的的动态生成及通过cookie实现HTML页面对用户输入的验证码的校验,简要如下: 1.写 ...

  2. .Net 组件技术概述

    1. 基本原理 组件是组件系统中功能的表现,没有组件就没有功能.特定接口是用于给组件管理程序来操纵.管理该组件,特定功能是组件需要完成的任务.在一个使用组件建立的产品中会随着功能数目的多少而会有多个组 ...

  3. vJine.Core 0.3.0.49 正式发布

    nuget: https://www.nuget.org/packages/vJine.Core/ oschina: http://git.oschina.net/vjine/vJine.Core/a ...

  4. 理解css 中的position五个属性

    在实际开发页面布局时,运用position,对定位的块级元素的嵌套的效果总是不太理解,这里做了几个测试 一般的在w3c中我们可以很容易的获取定义: static : 默认值.没有定位,元素出现在正常的 ...

  5. CSU-ACM2016暑期集训训练4-BFS(F - Oil Deposits)

    F - Oil Deposits Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u De ...

  6. hanoi双塔

    汉诺塔,经典的递归. 经典的汉诺塔游戏相信很多同学都会玩的,规则就不用赘述,百科一下就OK.有三个柱子A,B,C,A柱子上套有n个大小不等的盘子,任意两个盘子,上面的盘子一定小于下面的盘子.现在请你编 ...

  7. mysql学习笔记6——用phpmyadmin和在腾讯微云中创建数据库

    安装phpmyadmin就不多说了,对于新手,推荐使用wamp(windows系统),傻瓜式安装,很好用.安装完后在浏览器栏输入localhost

  8. TimesTen ODBC 链接库差异及相关命令行工具的使用注意事项

    1. TimesTen有两种访问模式:Direct模式和Client/Server模式,以下为来自Operations Guide 的描述 Connecting using TimesTen ODBC ...

  9. ajax、json一些整理(2)

    <script type="text/javascript"> $(document).ready(function(){ $("#btn").cl ...

  10. JS 页面打印

    var hkey_root, hkey_path, hkey_key hkey_root = "HKEY_CURRENT_USER" hkey_path = "\\Sof ...