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. shell中if判断一个变量为空

    1.最直接简单的判断 [ ! $a ] && echo "a is null" 不用那些if语句了,直接缩短代码量. 2. 变量通过" "引号引 ...

  2. C#定义自定义类型转换

    类型转换不限于单一继承链中的类型(派生类转换为基类或者基类转换为派生类),完全不相关的类型之间也能进行转换.关键在于在两个类型之间提供转型操作符. 在下面这样的情况下应该定义显式转型操作符: 在转型有 ...

  3. 性能更好的js动画实现方式——requestAnimationFrame

    本文转载,原文地址:http://www.cnblogs.com/2050/p/3871517.html 用js来实现动画,我们一般是借助setTimeout或setInterval这两个函数,css ...

  4. Centos7安装并配置mysql5.6完美教程

    Centos7安装并配置mysql5.6完美教程 Centos7将默认数据库mysql替换成了Mariadb,对于我们这些还想使用mysql的开发人员来说并不是一个好消息.然而,网上关于Linux安装 ...

  5. extern int a[] VS extern int *a

    array VS pointer 参考: 1.Extern using pointer instead of array array is not pointer 2.extern array que ...

  6. 暑假集训(2)第七弹 -----今年暑假不AC(hdu2037)

    J - 今年暑假不AC Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:32768KB     64 ...

  7. Window_Open详解

    Window_Open详解    引:Window_Open详解一.window.open()支持环境:JavaScript1.0+/JScript1.0+/Nav2+/IE3+/Opera3+ 二. ...

  8. 自制3D打印机---挤出头

    计划准备自己制作一台3D打印机,故将制作过程记录在此方便以后查阅. 计划首先制作加热头部件,此部件的主要功能是通过加热棒加热挤出头,然后从送料管道将ABS或者PLA材料线材送入后融化成为液体后,从挤出 ...

  9. linux点滴:NFS

    介绍 NFS,Network File System,网络文件系统.主要功能是通过网络让不同的主机系统间共享资源,类似于windows下的文件共享.适用于互联网中小型企业. 工作原理 客户端发送请求 ...

  10. hdu 4746 Mophues 莫比乌斯反演+前缀和优化

    Mophues 题意:给出n, m, p,求有多少对a, b满足gcd(a, b)的素因子个数<=p,(其中1<=a<=n, 1<=b<=m) 有Q组数据:(n, m, ...