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. Android之 Fragment

    什么是Fragment: Android是在Android 3.0 (API level 11)开始引入Fragment的. 可以把Fragment想成Activity中的模块,这个模块有自己的布局, ...

  2. 【HTTPS】Https和SSL学习笔记(一)

    1. 什么是HTTPS 在说HTTPS之前必须要先说一下HTTP.我们平常浏览网页用的就是HTTP协议,HTTP协议之间传输的数据都是明文,这样对于一些敏感信息传输其实是不安全的,很容易被恶意窃取.应 ...

  3. ASP.NET生成日历

    public string GetDayList(DateTime? date) { ; var minDate = Convert.ToDateTime(((DateTime)(date ?? Da ...

  4. Ext.Net学习笔记21:Ext.Net FormPanel 字段验证(validation)

    Ext.Net学习笔记21:Ext.Net FormPanel 字段验证(validation) 作为表单,字段验证当然是不能少的,今天我们来一起看看Ext.Net FormPanel的字段验证功能. ...

  5. 第五篇、常用的SQL语句和函数介绍

    简介: 在使用到sqlite3的时候,常常需要写一些SQL语句,现将常用到的部分语句稍微总结以下,由于个人习惯,关键字用大写. 附: /*简单约束*/ CREATE TABLE IF NOT EXIS ...

  6. C# 并行开发总结

    本文内容 均参考自 <C#并行高级编程> TPL 支持 数据并行(有大量数据要处理,必须对每个数据执行同样的操作, 任务并行(有好多可以并发运行的操作),流水线(任务并行和数据并行的结合体 ...

  7. html元素类型 块级元素、内联元素(又叫行内元素)和内联块级元素。

    html中的标签元素大体被分为三种不同的类型:块级元素.内联元素(又叫行内元素)和内联块级元素. 块级元素特点: 1.每个块级元素都从新的一行开始,并且其后的元素也另起一行.(霸道,一个块级元素独占一 ...

  8. C语言 宏/macor/#define/

    C语言 宏/macor/#define 高级技巧 1.在进行调试的时候,需要进行打印/PRINT,可以通过define进行自定义.例如,自己最常用的DEBUG_PRINT() #define DEBU ...

  9. java nio使用方法(转)

    最近由于工作关系要做一些Java方面的开发,其中最重要的一块就是Java NIO(New I/O),尽管很早以前了解过一些,但并没有认真去看过它的实现原理,也没有机会在工作中使用,这次也好重新研究一下 ...

  10. mysql常见的hint(转载的)

    mysql常用的hint对于经常使用oracle的朋友可能知道,oracle的hint功能种类很多,对于优化sql语句提供了很多方法.同样,在mysql里,也有类似的hint功能.下面介绍一些常用的. ...