第九章 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(看上去 ...
随机推荐
- 一般处理程序生成简单的图片验证码并通过html验证用户输入的验证码是否正确
一般处理程序生成简单的图片验证码并通过html验证用户输入的验证码是否正确 最近没事研究了下验证码的的动态生成及通过cookie实现HTML页面对用户输入的验证码的校验,简要如下: 1.写 ...
- .Net 组件技术概述
1. 基本原理 组件是组件系统中功能的表现,没有组件就没有功能.特定接口是用于给组件管理程序来操纵.管理该组件,特定功能是组件需要完成的任务.在一个使用组件建立的产品中会随着功能数目的多少而会有多个组 ...
- vJine.Core 0.3.0.49 正式发布
nuget: https://www.nuget.org/packages/vJine.Core/ oschina: http://git.oschina.net/vjine/vJine.Core/a ...
- 理解css 中的position五个属性
在实际开发页面布局时,运用position,对定位的块级元素的嵌套的效果总是不太理解,这里做了几个测试 一般的在w3c中我们可以很容易的获取定义: static : 默认值.没有定位,元素出现在正常的 ...
- CSU-ACM2016暑期集训训练4-BFS(F - Oil Deposits)
F - Oil Deposits Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u De ...
- hanoi双塔
汉诺塔,经典的递归. 经典的汉诺塔游戏相信很多同学都会玩的,规则就不用赘述,百科一下就OK.有三个柱子A,B,C,A柱子上套有n个大小不等的盘子,任意两个盘子,上面的盘子一定小于下面的盘子.现在请你编 ...
- mysql学习笔记6——用phpmyadmin和在腾讯微云中创建数据库
安装phpmyadmin就不多说了,对于新手,推荐使用wamp(windows系统),傻瓜式安装,很好用.安装完后在浏览器栏输入localhost
- TimesTen ODBC 链接库差异及相关命令行工具的使用注意事项
1. TimesTen有两种访问模式:Direct模式和Client/Server模式,以下为来自Operations Guide 的描述 Connecting using TimesTen ODBC ...
- ajax、json一些整理(2)
<script type="text/javascript"> $(document).ready(function(){ $("#btn").cl ...
- JS 页面打印
var hkey_root, hkey_path, hkey_key hkey_root = "HKEY_CURRENT_USER" hkey_path = "\\Sof ...