📄 massstorage.c
字号:
/*---------------------------------------------------------------------------------------------------------*/
/* */
/* Copyright (c) Nuvoton Technology Corp. All rights reserved. */
/* */
/*---------------------------------------------------------------------------------------------------------*/
#include <string.h>
#include "Driver\DrvUSB.h"
#include "USB\UDC.h"
#define VENDER_CMD 0x61
//#define TEST_DATA_FLASH
#define DATA_FLASH_STORAGE_SIZE (64*1024) /* Configure the DATA FLASH storage size */
#define MASS_BUFFER_SIZE 48 /* Mass Storage command buffer size */
#define STORAGE_BUFFER_SIZE 512 /* Data transfer buffer size in 512 bytes alignment */
#define UDC_SECTOR_SIZE 512 /* logic sector size */
#define VENDOR_ID 0x0416
#define PRODUCT_ID 0x501E
int32_t gTotalSectors = 0;
int32_t g_dataFlashTotalSectors = 0;
uint8_t volatile MassLUN=0;
uint8_t volatile F_DATA_FLASH_LUN = 0xFF;
/* DATA Flash Programming API */
extern void DataFlashRead(uint32_t addr, uint32_t size, uint32_t buffer);
extern void DataFlashWrite(uint32_t addr, uint32_t size, uint32_t buffer);
/* USB flow control variables */
uint8_t g_u8UsbState;
uint8_t g_u8Address;
uint8_t g_u8Config;
uint8_t g_u8Flag;
uint8_t g_u8BulkState;
uint8_t g_au8SenseKey[4];
uint32_t g_u32DataFlashStartAddr;
uint32_t g_u32Address;
uint32_t g_u32Length;
uint32_t g_u32LbaAddress;
uint32_t g_u32BytesInStorageBuf;
uint32_t g_u32OutToggle; // for Error Detection
uint8_t preventflag=0;
uint8_t g_u8Size;
int32_t g_bCBWInvalid;
int32_t udcOnLine = 0;
/* CBW/CSW variables */
struct CBW g_sCBW;
struct CSW g_sCSW;
uint32_t MassBlock[MASS_BUFFER_SIZE / 4];
uint32_t Storage_Block[STORAGE_BUFFER_SIZE / 4];
#define MassCMD_BUF ((uint32_t)&MassBlock[0])
#define STORAGE_DATA_BUF ((uint32_t)&Storage_Block[0])
// code = 5Ah, Mode Sense
static uint8_t ModePage_01[12] = {
0x01, 0x0A, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00 };
static uint8_t ModePage_05[32] = {
0x05, 0x1E, 0x13, 0x88, 0x08, 0x20, 0x02, 0x00,
0x01, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05, 0x1E, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00 };
static uint8_t ModePage_1B[12] = {
0x1B, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
static uint8_t ModePage_1C[8] = {
0x1C, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00 };
//======================================================
const uint8_t MassDeviceDescriptor[LEN_DEVICE] =
{
LEN_DEVICE, // bLength
DESC_DEVICE, // bDescriptorType
0x10, 0x01, // bcdUSB
0x00, // bDeviceClass
0x00, // bDeviceSubClass
0x00, // bDeviceProtocol
MAX_PACKET_SIZE0, // bMaxPacketSize0
(VENDOR_ID & 0xFF),
(VENDOR_ID >> 8), // idVendor
(PRODUCT_ID & 0xFF),
(PRODUCT_ID >> 8), // idProduct
0x00, 0x00, // bcdDevice
0x01, // iManufacture
0x02, // iProduct
0x01, // iSerialNumber
0x01 // bNumConfigurations
};
const uint8_t MassConfigurationBlock[LEN_CONFIG+LEN_INTERFACE+LEN_ENDPOINT*2] =
{
LEN_CONFIG, // bLength
DESC_CONFIG, // bDescriptorType
(LEN_CONFIG+LEN_INTERFACE+LEN_ENDPOINT*2), 0x00, // wTotalLength
0x01, // bNumInterfaces
0x01, // bConfigurationValue
0x00, // iConfiguration
0xC0, // bmAttributes
0x32, // MaxPower
/* const BYTE cbyInterfaceDescriptor[LEN_INTERFACE] = */
LEN_INTERFACE, // bLength
DESC_INTERFACE, // bDescriptorType
0x00, // bInterfaceNumber
0x00, // bAlternateSetting
0x02, // bNumEndpoints
0x08, // bInterfaceClass
0x05, // bInterfaceSubClass
0x50, // bInterfaceProtocol
0x00, // iInterface
/* const BYTE cbyEndpointDescriptor1[LEN_ENDPOINT] = */
LEN_ENDPOINT, // bLength
DESC_ENDPOINT, // bDescriptorType
0x82, // bEndpointAddress
EP_BULK, // bmAttributes
MAX_PACKET_SIZE, 0x00, // wMaxPacketSize
0x00, // bInterval
/* const BYTE cbyEndpointDescriptor2[LEN_ENDPOINT] = */
LEN_ENDPOINT, // bLength
DESC_ENDPOINT, // bDescriptorType
0x03, // bEndpointAddress
EP_BULK, // bmAttributes
MAX_PACKET_SIZE, 0x00, // wMaxPacketSize
0x00 // bInterval
};
const uint8_t MassStringDescriptor0[4] =
{
4, // bLength
DESC_STRING, // bDescriptorType
0x09, 0x04
};
const uint8_t MassStringDescriptor1[16] =
{
16, // bLength
DESC_STRING, // bDescriptorType
'N', 0, 'u', 0, 'v', 0, 'o', 0, 't', 0, 'o', 0, 'n', 0
};
const uint8_t InquiryID[36] =
{
0x00, // Peripheral Device Type
0x80, // RMB
0x00, // ISO/ECMA, ANSI Version
0x00, // Response Data Format
0x1F, 0x00, 0x00, 0x00, // Additional Length
/* Vendor Identification */
'N', 'u', 'v', 'o', 't', 'o', 'n', ' ',
/* Product Identification */
'1', '0', '0', ' ', 'M', 'a', 's', 's', ' ', 'S', 't', 'o', 'r', 'a', 'g', 'e',
/* Product Revision */
'1', '.', '0', '0'
};
static __INLINE uint32_t get_be32(uint8_t *buf)
{
return ((uint32_t) buf[0] << 24) | ((uint32_t) buf[1] << 16) |
((uint32_t) buf[2] << 8) | ((uint32_t) buf[3]);
}
void RoughDelay(uint32_t t)
{
volatile int32_t delay;
delay = t;
while(delay-- >= 0);
}
void my_memcpy(void *dest, void *src, int32_t size)
{
int32_t i;
for (i = 0; i < size; i++)
*((uint8_t *)dest + i) = *((uint8_t *)src + i);
}
void ModeSenseCommand(void)
{
uint8_t i,j;
uint8_t NumHead,NumSector;
uint16_t NumCyl;
/* Clear the command buffer */
*((uint32_t *)MassCMD_BUF ) = 0;
*((uint32_t *)MassCMD_BUF+1) = 0;
switch (g_sCBW.au8Data[0])
{
case 0x01:
{
outpb(MassCMD_BUF, 19);
i = 8;
for (j = 0; j<12; j++, i++)
outpb(MassCMD_BUF+i, ModePage_01[j]);
break;
}
case 0x05:
{
outpb(MassCMD_BUF, 39);
i = 8;
for (j = 0; j<32; j++, i++)
outpb(MassCMD_BUF+i, ModePage_05[j]);
NumHead = 2;
NumSector = 64;
if (g_sCBW.bCBWLUN==F_DATA_FLASH_LUN)
NumCyl = g_dataFlashTotalSectors/128;
outpb(MassCMD_BUF+12, NumHead);
outpb(MassCMD_BUF+13, NumSector);
outpb(MassCMD_BUF+16, (uint8_t)(NumCyl >> 8));
outpb(MassCMD_BUF+17, (uint8_t)(NumCyl & 0x00ff));
break;
}
case 0x1B:
{
outpb(MassCMD_BUF, 19);
i = 8;
for (j = 0; j<12; j++, i++)
outpb(MassCMD_BUF+i, ModePage_1B[j]);
break;
}
case 0x1C:
{
outpb(MassCMD_BUF, 15);
i = 8;
for (j = 0; j<8; j++, i++)
outpb(MassCMD_BUF+i, ModePage_1C[j]);
break;
}
case 0x3F:
{
outpb(MassCMD_BUF, 0x47);
i = 8;
for (j = 0; j<12; j++, i++)
outpb(MassCMD_BUF+i, ModePage_01[j]);
for (j = 0; j<32; j++, i++)
outpb(MassCMD_BUF+i, ModePage_05[j]);
for (j = 0; j<12; j++, i++)
outpb(MassCMD_BUF+i, ModePage_1B[j]);
for (j = 0; j<8; j++, i++)
outpb(MassCMD_BUF+i, ModePage_1C[j]);
NumHead = 2;
NumSector = 64;
if (g_sCBW.bCBWLUN==F_DATA_FLASH_LUN)
NumCyl = g_dataFlashTotalSectors/128;
outpb(MassCMD_BUF+24, NumHead);
outpb(MassCMD_BUF+25, NumSector);
outpb(MassCMD_BUF+28, (uint8_t)(NumCyl >> 8));
outpb(MassCMD_BUF+29, (uint8_t)(NumCyl & 0x00ff));
break;
}
default:
g_au8SenseKey[0] = 0x05;
g_au8SenseKey[1] = 0x24;
g_au8SenseKey[2] = 0x00;
}
}
void ReqSenCommand(void)
{
uint8_t tmp[20];
if (preventflag==1)
{
preventflag=0;
tmp[0] = 0x70;
}
else
tmp[0] = 0xf0;
tmp[1] = 0;
tmp[3] = 0;
tmp[4] = 0;
tmp[5] = 0;
tmp[6] = 0;
tmp[7] = 0x0A;
tmp[8] = 0;
tmp[9] = 0;
tmp[10] = 0;
tmp[11] = 0;
tmp[14] = 0;
tmp[15] = 0;
tmp[16] = 0;
tmp[17] = 0;
tmp[2] = g_au8SenseKey[0];
tmp[12] = g_au8SenseKey[1];
tmp[13] = g_au8SenseKey[2];
my_memcpy(g_au8UsbBulk1, tmp, 20);
// Sense Key
g_au8SenseKey[0] = 0x00;
g_au8SenseKey[1] = 0x00;
g_au8SenseKey[2] = 0x00;
}
void RdFmtCapCommand(void)
{
uint32_t i;
uint32_t TotalSectors = 0;
for (i = 0; i < 36; i++)
outpb(MassCMD_BUF+i, 0);
outpb(MassCMD_BUF+3, 0x10);
if (g_sCBW.bCBWLUN==F_DATA_FLASH_LUN)
TotalSectors = g_dataFlashTotalSectors;
outpb(MassCMD_BUF+4, *((uint8_t *)&TotalSectors+3));
outpb(MassCMD_BUF+5, *((uint8_t *)&TotalSectors+2));
outpb(MassCMD_BUF+6, *((uint8_t *)&TotalSectors+1));
outpb(MassCMD_BUF+7, *((uint8_t *)&TotalSectors+0));
outpb(MassCMD_BUF+8, 0x02);
outpb(MassCMD_BUF+10, 0x02);
outpb(MassCMD_BUF+12, *((uint8_t *)&TotalSectors+3));
outpb(MassCMD_BUF+13, *((uint8_t *)&TotalSectors+2));
outpb(MassCMD_BUF+14, *((uint8_t *)&TotalSectors+3));
outpb(MassCMD_BUF+15, *((uint8_t *)&TotalSectors+0));
outpb(MassCMD_BUF+18, 0x02);
}
void RdCurCapCommand(void)
{
int i;
uint32_t temp;
for (i = 0; i < 36; i++)
outpb(MassCMD_BUF+i, 0);
if (g_sCBW.bCBWLUN==F_DATA_FLASH_LUN)
temp = g_dataFlashTotalSectors - 1;
outpb(MassCMD_BUF+0, *((uint8_t *)&temp+3));
outpb(MassCMD_BUF+1, *((uint8_t *)&temp+2));
outpb(MassCMD_BUF+2, *((uint8_t *)&temp+1));
outpb(MassCMD_BUF+3, *((uint8_t *)&temp+0));
outpb(MassCMD_BUF+6, 0x02);
}
//======================================================
// USB Configuration
//======================================================
void UsbCfg(void)
{
/* Init the USB device address to 0x0 */
_DRVUSB_SET_FADDR(0x00);
/* Init control end point */
USBD->STBUFSEG.STBUFSEG = 0x1F; /* Buffer for setup packet */
_DRVUSB_SET_CFG_EP0(EPT_CFGP); /* Clear EP0 CTRL IN Ready Flag */
_DRVUSB_SET_CFG(0, CFG0_SETTING); /* EP0 ==> control IN end point, address 0 */
_DRVUSB_SET_EP_BUF(0, USB_SRAM_BASE + BUF0_SETTING); /* Buffer for EP0 */
_DRVUSB_SET_CFG_EP1(EPT_CFGP); /* Clear EP1 CTRL OUT Ready Flag */
_DRVUSB_SET_CFG(1, CFG1_SETTING); /* EP1 ==> control OUT end point, address 0 */
_DRVUSB_SET_EP_BUF(1, USB_SRAM_BASE + BUF1_SETTING); /* Buffer for EP1 */
/* Init Bulk IN end point */
_DRVUSB_SET_CFG_EP2(EPT_CFGP); /* Clear EP2 BULK IN Ready Flag */
_DRVUSB_SET_CFG(2, CFG2_SETTING); /* EP2 ==> Bulk IN end point, address 2 */
_DRVUSB_SET_EP_BUF(2, USB_SRAM_BASE + BUF_BULK1); /* Buffer for EP2 (Bulk IN) */
/* Init Bulk OUT end point */
_DRVUSB_SET_CFG_EP3(EPT_CFGP); /* Clear EP3 BULK OUT Ready Flag */
_DRVUSB_SET_CFG(3, CFG3_SETTING); /* EP3 ==> Bulk OUT end point, address 3 */
_DRVUSB_SET_EP_BUF(3, USB_SRAM_BASE + BUF_BULK0); /* Buffer for EP3 (Bulk OUT) */
g_u8Address = 0; /* Device address */
g_u8Config = 0;
g_u8Flag = 0; /* Flag to record the USB request */
g_u8BulkState = BULK_CBW;
g_au8SenseKey[0] = 0;
g_au8SenseKey[1] = 0;
g_au8SenseKey[2] = 0;
g_bCBWInvalid = FALSE;
g_u32Address = 0;
g_u32Length = 0;
g_u8Size = 0;
g_sCSW.dCSWSignature = CSW_SIGNATURE;
udcOnLine = 0;
g_u32OutToggle = 0; // for Error Detection
}
//======================================================
// USB Floating Detect
//======================================================
void UsbFdt(void)
{
uint8_t u8FLDET = USBD->FLDET.FLDET;
_DRVUSB_SET_EVENT_FLAG(INTSTS_FLDET);
if (u8FLDET)
{
/* USB Plug In */
if(g_u8UsbState & USB_STATE_ATTACHED)
{
/* Do nothing if it is already attached */
return;
}
/* Update USB state */
g_u8UsbState = USB_STATE_ATTACHED;
/* Init the end points */
UsbCfg();
/* Enable USB and enable PHY */
_DRVUSB_ENABLE_USB();
}
else
{
/* USB Un-plug */
/* Update USB state */
g_u8UsbState = USB_STATE_DETACHED;
udcOnLine = 0;
/* Disable USB, Disable remote weak up, and disable PHY */
_DRVUSB_DISABLE_USB();
}
}
//======================================================
// USB Bus Event
//======================================================
void UsbBus(void)
{
uint8_t u8ATTR = *((__IO uint32_t *)(&USBD->ATTR)) & 0xFF;
/* Clear event flag */
_DRVUSB_SET_EVENT_FLAG(INTSTS_BUS);
/* Just return if USB detached. */
if (g_u8UsbState == USB_STATE_DETACHED)
return;
/* Process USB bus command if USB is attached. */
if (u8ATTR & ATTR_USBRST)
{
/* Enable USB and enable PHY */
_DRVUSB_ENABLE_USB();
/* Enter default state */
g_u8UsbState = USB_STATE_DEFAULT;
/* Configure the end-points */
UsbCfg();
}
else if (u8ATTR & ATTR_SUSPEND)
{
/* Enable USB but disable PHY */
_DRVUSB_DISABLE_PHY();
/* Update the USB state */
g_u8UsbState |= USB_STATE_FLAG_SUSPENDED;
}
else if (u8ATTR & ATTR_RESUME)
{
/* Enable USB and enable PHY */
_DRVUSB_ENABLE_USB();
/* Clear the suspend state */
g_u8UsbState &= ~USB_STATE_FLAG_SUSPENDED;
}
}
//======================================================
int32_t UsbStdReq(void)
{
int volatile len, idx;
uint8_t tmp[8];
my_memcpy(tmp, g_au8UsbSetup, 8);
/* check if after DEFAULT state (RESET) */
if ((g_u8UsbState & USB_STATE_FLAG_DEFAULT) == 0x00)
return FALSE;
/* parse the request in setup packet */
switch (tmp[1])
{
case GET_DESCRIPTOR:
{
len = tmp[6] + ((uint32_t)tmp[7] << 8);
switch (tmp[3])
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -