原文地址http://qiita.com/mt08/items/fcc925fa47726bfc6c74

概要

  • STM32CubeMXを使って、USB MassStorageを使ってみる。
  • USBを使うときは、外付けのOscillator/Xtalが必要。(48MHzを作るのに、内部のやつは精度がでない?)
  • usbd_storage_if.cだけ変更. 今回は、ReadOnly.

環境

  • STM32L1系
  • ビルド環境
    • Windows7 64bit
    • MDK-ARM Lite v5.20
    • STM32CubeMX v4.18.0
      • ボードが動くくらいの設定(クロックとか、GPIOとか)
      • FreeRTOS : [v] Enabled (Lチカにつかった程度)
      • USB_DEVICE : Class for FS IP Mass Storage Class
      • USB : [v] Device (FS)
        => コード生成
    • Firmware Package for Family STM32L1 v1.6.0

大体の説明

  • コールバック
    ホストに接続すると、コールバックが呼ばれるので、うまく応答すればよい。

    usbd_storage_if.c
    ...
    USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
    {
    STORAGE_Init_FS,
    STORAGE_GetCapacity_FS,
    STORAGE_IsReady_FS,
    STORAGE_IsWriteProtected_FS,
    STORAGE_Read_FS,
    STORAGE_Write_FS,
    STORAGE_GetMaxLun_FS,
    (int8_t *)STORAGE_Inquirydata_FS,
    };
    ...
  • ディスクの容量は、STORAGE_BLK_NBRにセクタ数定義する。
    今回、#define STORAGE_BLK_NBR 0x81000としたので、
    => 0x81000 * 512bytes/sector = 258MBくらいのディスク

  • コールバックは、だいたい、STORAGE_Read_FSで、セクタのデータを要求してくるので、そいつをかえせばいい。

    • ↓の実装では、_ReadSector()に飛ばしている。
    • _ReadSector()で、要求されたセクタ番号で、MBR, PBR, FAT, ROOT_DIR, DATAの領域で、処理を分けている。
      • MBR,PBRは、固定値を用意して、memcpy
      • FAT, ROOTDIR, DATAは、Offsetを引いて、処理関数(handleFatClusterChain,handleRoot,handleData)へ飛ばして、うまくデータを詰める

実際のコード

  • もともとのコードの変更箇所

    usbd_storage_if.c
    ...
    #define STORAGE_LUN_NBR 1
    #define STORAGE_BLK_NBR 0x81000 //##mt08
    #define STORAGE_BLK_SIZ ... int8_t STORAGE_IsWriteProtected_FS (uint8_t lun)
    {
    /* USER CODE BEGIN 5 */
    return (USBD_FAIL); //##mt08: Read Only
    /* USER CODE END 5 */
    } ...
    int8_t STORAGE_Read_FS (uint8_t lun,
    uint8_t *buf,
    uint32_t blk_addr,
    uint16_t blk_len)
    {
    /* USER CODE BEGIN 6 */
    _ReadSector(buf, blk_addr, blk_len); //##mt08
    return (USBD_OK);
    /* USER CODE END 6 */
    }

追加コード

  • 型宣言

    #include <stdint.h>
    typedef uint8_t Byte;
    typedef struct MasterBootRecord {
    Byte checkRoutionOnx86[446];
    struct {
    Byte bootDescriptor; /* 0x80: bootable device, 0x00: non-bootable */
    Byte firstPartitionSector[3]; /* 1st sector number */
    Byte fileSystemDescriptor; /* 1:FAT12, 4:FAT16(less than 32MB), 5:Extended-DOS Partition,
    6:FAT16(more 32MB), 0xb:FAT32(more 2GB),
    0xc:FAT32 Int32h, 0xe:FAT16 Int32h,
    0xf:5:Extended-DOS Partition Int32h */
    Byte lastPartitionSector[3];
    Byte firstSectorNumbers[4]; /* first sector number (link to BPB sector) */
    Byte numberOfSectors[4];
    } partitionTable[4];
    Byte sig[2]; /* 0x55, 0xaa */
    } MBRecord; typedef struct FAT16BPB_t {
    /* FAT16 or FAT12 BPB */
    Byte jmpOpeCode[3]; /* 0xeb ?? 0x90 */
    Byte OEMName[8];
    /* FAT16 */
    Byte bytesPerSector[2]; /* bytes/sector */
    Byte sectorsPerCluster; /* sectors/cluster */
    Byte reservedSectors[2]; /* reserved sector, beginning with sector 0 */
    Byte numberOfFATs; /* file allocation table */
    Byte rootEntries[2]; /* root entry (512) */
    Byte totalSectors[2]; /* partion total secter */
    Byte mediaDescriptor; /* 0xf8: Hard Disk */
    Byte sectorsPerFAT[2]; /* sector/FAT (FAT32 always zero: see bigSectorsPerFAT) */
    Byte sectorsPerTrack[2]; /* sector/track (not use) */
    Byte heads[2]; /* heads number (not use) */
    Byte hiddenSectors[4]; /* hidden sector number */
    Byte bigTotalSectors[4]; /* total sector number */
    /* info */
    Byte driveNumber;
    Byte unused;
    Byte extBootSignature;
    Byte serialNumber[4];
    Byte volumeLabel[11];
    Byte fileSystemType[8]; /* "FAT16 " */
    Byte loadProgramCode[448];
    Byte sig[2]; /* 0x55, 0xaa */
    } BPBlock; // BIOS Parameter Block typedef struct DirEntry_t {
    Byte name[8]; /* file name */
    Byte extension[3]; /* file name extension */
    Byte attribute; /* file attribute
    bit 4 directory flag
    bit 3 volume flag
    bit 2 hidden flag
    bit 1 system flag
    bit 0 read only flag */
    Byte reserved; /* use NT or same OS */
    Byte createTimeMs; /* VFAT 10millsec (0   199) */
    Byte createTime[2]; /* VFAT */
    Byte createDate[2]; /* VFAT */
    Byte accessDate[2]; /* VFAT */
    Byte clusterHighWord[2]; /* FAT32 MSB 16 bits */
    Byte updateTime[2];
    Byte updateDate[2];
    Byte cluster[2]; /* start cluster number */
    Byte fileSize[4]; /* file size in bytes (directory is always zero) */
    } DirEntry; #pragma anon_unions
    typedef struct _DirEntTime {
    union {
    uint16_t W;
    struct {
    uint16_t second : 5;
    uint16_t minutes : 6;
    uint16_t hour : 5;
    } B;
    };
    } DirEntTime; typedef struct _DirEntDate {
    union {
    uint16_t W;
    struct {
    uint16_t day : 5;
    uint16_t month : 4;
    uint16_t year : 7;
    } B;
    };
    } DirEntDate;
    #pragma no_anon_unions
  • 固定値: MBRとか、PBSとか。
    (てきとうなUSBフラッシュメモリで、パーティション切って、フォーマットして、ダンプして、必要なとこを入力)

    const MBRecord sectMBR = {
    .checkRoutionOnx86 = { 0x00 },
    .partitionTable = {
    {
    .bootDescriptor = 0x00,
    .firstPartitionSector = { 0x02, 0x21, 0x00 },
    .fileSystemDescriptor = 0x06, //FAT16
    .lastPartitionSector = { 0xC2, 0x22, 0x20 },
    .firstSectorNumbers = { 0x00, 0x08, 0x00, 0x00 },
    .numberOfSectors = { 0x00, 0x00, 0x08, 0x00 },
    },//[0]
    { 0 },//[1]
    { 0 },//[2]
    { 0 },//[3]
    },
    .sig = { 0x55, 0xAA },
    };
    const BPBlock sectBPB = {
    .jmpOpeCode = { 0xEB, 0x00, 0x90 },
    .OEMName = { ' ',' ',' ',' ',' ',' ',' ',' ' },
    .bytesPerSector = { 0x00, 0x02 },
    .sectorsPerCluster = 0x08, // 4KB/sectors
    .reservedSectors = { 0x08, 0x00 },
    .numberOfFATs = 0x02,
    .rootEntries = { 0x00, 0x02 },
    .totalSectors = { 0x00, 0x00 },
    .mediaDescriptor = 0xF8, // HDD
    .sectorsPerFAT = { 0x00, 0x01 },
    .sectorsPerTrack = { 0x3F,0x00 },
    .heads = { 0xFF,0x00 },
    .hiddenSectors = { 0x00, 0x08, 0x00, 0x00 },
    .bigTotalSectors = { 0x00,0x00,0x08, 0x00 },
    .driveNumber = 0x80,
    .unused = 0,
    .extBootSignature = 0x29,
    .serialNumber = { 0x78,0x56,0x34,0x12 },
    .volumeLabel = { 'N','O',' ','N','A','M','E',' ',' ',' ',' ' },
    .fileSystemType = { 'F','A','T','1','6',' ',' ',' ' },
    .loadProgramCode = { 0 },
    .sig = { 0x55, 0xAA },
    }; #define SECTOR_MBR (0x0000)
    #define SECTOR_PBR (0x0800)
    #define SECTOR_FAT1 (0x0808)
    #define SECTOR_FAT2 (0x0908)
    #define SECTOR_ROOT (0x0A08)
    #define SECTOR_DATA (0x0A28)
  • セクタ読み出しで、それっぽいデータをわたすとこ。

    void _handleFatClusterChain(uint32_t sect_offset, uint8_t *buf)
{
uint16_t *bufW = (uint16_t *)&buf[0];
if (sect_offset == 0)
{
bufW[0] = 0xfff8;
bufW[1] = 0xffff;
bufW[2] = 0xffff; //最初のファイル. 1クラスタでおわり.
}
} void _handleRoot(uint32_t sect_offset, uint8_t *buf)
{
// 1 sector(512bytes) has 16 entries
DirEntry *pDir = (DirEntry *)buf;
if (sect_offset == 0)
{
memset(pDir, 0x00, sizeof(DirEntry));
sprintf((char *)pDir->name, "TEXT_123");
pDir->extension[0] = 'T';
pDir->extension[1] = 'X';
pDir->extension[2] = 'T';
pDir->attribute = 0x00;
{
DirEntTime *pT = (DirEntTime *)&pDir->updateTime[0];
DirEntDate *pD = (DirEntDate *)&pDir->updateDate[0];
pT->B.hour = 12;
pT->B.minutes = 34;
pT->B.second = 56 / 2;
pD->B.year = 2017 - 1980;
pD->B.month = 1;
pD->B.day = 12;
} *(uint16_t*)&pDir->cluster = 0x0002;
*(uint32_t*)&pDir->fileSize = 123;
}
} void _handleData(uint32_t sect_offset, uint8_t *buf)
{
memset(buf, 'A', 512);
sprintf((char *)buf, "Hello World!\r\n");
buf[14]='>';
} uint32_t _ReadSector(uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
switch (blk_addr)
{
case SECTOR_MBR:
memcpy(buf, (const void *)&sectMBR, 512);
break;
case SECTOR_PBR:
memcpy(buf, (const void *)&sectBPB, 512);
break;
default:
memset(buf, 0x00, 512);
//FAT cluster chain
if ((SECTOR_FAT1 <= blk_addr) && (blk_addr < SECTOR_ROOT))
{
if (blk_addr >= SECTOR_FAT2) { blk_addr -= (SECTOR_FAT2 - SECTOR_FAT1); }
_handleFatClusterChain(blk_addr - SECTOR_FAT1, buf); }
else if ((SECTOR_ROOT <= blk_addr) && (blk_addr < SECTOR_DATA))
{
_handleRoot(blk_addr - SECTOR_ROOT, buf); }
else if (SECTOR_DATA <= blk_addr)
{
_handleData(blk_addr - SECTOR_DATA, buf); }
break;
}
return 0;
}

その他

    • 4KB/clusterにしてるのは、STM32の内蔵FLASHが4KB/sectorなので。
      で、256MBくらいのパーティションで、FAT16フォーマットすると、4KB/clusterになる。
      (ファイルシステムのクラスタサイズと、フラッシュメモリの物理セクタサイズがちがうと、管理が大変だよね...;_;)
    • EEPROMにファイル情報(ROOTDIRに入るような情報=>FATチェーン生成)、FLASHにデータのみ、という感じで使用しようかと。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

好了现在我们动手吧。现在只要修改usbd_storage_if.C文件

/**
******************************************************************************
* @file : usbd_storage_if.c
* @brief : Memory management layer
******************************************************************************
* This notice applies to any and all portions of this file
* that are not between comment pairs USER CODE BEGIN and
* USER CODE END. Other portions of this file, whether
* inserted by the user or by software development tools
* are owned by their respective copyright owners.
*
* Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/ /* Includes ------------------------------------------------------------------*/
#include "usbd_storage_if.h"
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */ /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/ /** @defgroup USBD_STORAGE
* @brief usbd core module
* @{
*/ /** @defgroup USBD_STORAGE_Private_TypesDefinitions
* @{
*/
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */
/**
* @}
*/ /** @defgroup USBD_STORAGE_Private_Defines
* @{
*/
#define STORAGE_LUN_NBR 1
#define STORAGE_BLK_NBR 0x81000
#define STORAGE_BLK_SIZ 0x200 /* USER CODE BEGIN PRIVATE_DEFINES */
/* USER CODE END PRIVATE_DEFINES */ /**
* @}
*/ /** @defgroup USBD_STORAGE_Private_Macros
* @{
*/
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */ /**
* @}
*/ /** @defgroup USBD_STORAGE_IF_Private_Variables
* @{
*/
/* USER CODE BEGIN INQUIRY_DATA_FS */
/* USB Mass storage Standard Inquiry Data */
const int8_t STORAGE_Inquirydata_FS[] = /* 36 */
{ /* LUN 0 */
0x00,
0x80,
0x02,
0x02,
(STANDARD_INQUIRY_DATA_LEN - ),
0x00,
0x00,
0x00,
'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
'', '.', '' ,'', /* Version : 4 Bytes */
};
/* USER CODE END INQUIRY_DATA_FS */ /* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */ /**
* @}
*/ /** @defgroup USBD_STORAGE_IF_Exported_Variables
* @{
*/
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */ /**
* @}
*/ /** @defgroup USBD_STORAGE_Private_FunctionPrototypes
* @{
*/
static int8_t STORAGE_Init_FS (uint8_t lun);
static int8_t STORAGE_GetCapacity_FS (uint8_t lun,
uint32_t *block_num,
uint16_t *block_size);
static int8_t STORAGE_IsReady_FS (uint8_t lun);
static int8_t STORAGE_IsWriteProtected_FS (uint8_t lun);
static int8_t STORAGE_Read_FS (uint8_t lun,
uint8_t *buf,
uint32_t blk_addr,
uint16_t blk_len);
static int8_t STORAGE_Write_FS (uint8_t lun,
uint8_t *buf,
uint32_t blk_addr,
uint16_t blk_len);
static int8_t STORAGE_GetMaxLun_FS (void); /* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
#include <stdint.h>
typedef uint8_t Byte;
typedef struct MasterBootRecord
{
Byte checkRoutionOnx86[];
struct
{
Byte bootDescriptor; /* 0x80: bootable device, 0x00: non-bootable */
Byte firstPartitionSector[]; /* 1st sector number */
Byte fileSystemDescriptor; /* 1:FAT12, 4:FAT16(less than 32MB), 5:Extended-DOS Partition,
6:FAT16(more 32MB), 0xb:FAT32(more 2GB),
0xc:FAT32 Int32h, 0xe:FAT16 Int32h,
0xf:5:Extended-DOS Partition Int32h */
Byte lastPartitionSector[];
Byte firstSectorNumbers[]; /* first sector number (link to BPB sector) */
Byte numberOfSectors[];
} partitionTable[];
Byte sig[]; /* 0x55, 0xaa */
} MBRecord; typedef struct FAT16BPB_t
{
/* FAT16 or FAT12 BPB */
Byte jmpOpeCode[]; /* 0xeb ?? 0x90 */
Byte OEMName[];
/* FAT16 */
Byte bytesPerSector[]; /* bytes/sector */
Byte sectorsPerCluster; /* sectors/cluster */
Byte reservedSectors[]; /* reserved sector, beginning with sector 0 */
Byte numberOfFATs; /* file allocation table */
Byte rootEntries[]; /* root entry (512) */
Byte totalSectors[]; /* partion total secter */
Byte mediaDescriptor; /* 0xf8: Hard Disk */
Byte sectorsPerFAT[]; /* sector/FAT (FAT32 always zero: see bigSectorsPerFAT) */
Byte sectorsPerTrack[]; /* sector/track (not use) */
Byte heads[]; /* heads number (not use) */
Byte hiddenSectors[]; /* hidden sector number */
Byte bigTotalSectors[]; /* total sector number */
/* info */
Byte driveNumber;
Byte unused;
Byte extBootSignature;
Byte serialNumber[];
Byte volumeLabel[];
Byte fileSystemType[]; /* "FAT16 " */
Byte loadProgramCode[];
Byte sig[]; /* 0x55, 0xaa */
} BPBlock; // BIOS Parameter Block typedef struct DirEntry_t
{
Byte name[]; /* file name */
Byte extension[]; /* file name extension */
Byte attribute; /* file attribute
bit 4 directory flag
bit 3 volume flag
bit 2 hidden flag
bit 1 system flag
bit 0 read only flag */
Byte reserved; /* use NT or same OS */
Byte createTimeMs; /* VFAT 10millsec (0 199) */
Byte createTime[]; /* VFAT */
Byte createDate[]; /* VFAT */
Byte accessDate[]; /* VFAT */
Byte clusterHighWord[]; /* FAT32 MSB 16 bits */
Byte updateTime[];
Byte updateDate[];
Byte cluster[]; /* start cluster number */
Byte fileSize[]; /* file size in bytes (directory is always zero) */
} DirEntry; #pragma anon_unions
typedef struct _DirEntTime
{
union
{
uint16_t W;
struct
{
uint16_t second : ;
uint16_t minutes : ;
uint16_t hour : ;
} B;
};
} DirEntTime; typedef struct _DirEntDate
{
union
{
uint16_t W;
struct
{
uint16_t day : ;
uint16_t month : ;
uint16_t year : ;
} B;
};
} DirEntDate;
#pragma no_anon_unions const MBRecord sectMBR =
{
.checkRoutionOnx86 = { 0x00 },
.partitionTable = {
{
.bootDescriptor = 0x00,
.firstPartitionSector = { 0x02, 0x21, 0x00 },
.fileSystemDescriptor = 0x06, //FAT16
.lastPartitionSector = { 0xC2, 0x22, 0x20 },
.firstSectorNumbers = { 0x00, 0x08, 0x00, 0x00 },
.numberOfSectors = { 0x00, 0x00, 0x08, 0x00 },
},//[0]
{ },//[1]
{ },//[2]
{ },//[3]
},
.sig = { 0x55, 0xAA },
};
const BPBlock sectBPB =
{
.jmpOpeCode = { 0xEB, 0x00, 0x90 },
.OEMName = { ' ',' ',' ',' ',' ',' ',' ',' ' },
.bytesPerSector = { 0x00, 0x02 },
.sectorsPerCluster = 0x08, // 4KB/sectors
.reservedSectors = { 0x08, 0x00 },
.numberOfFATs = 0x02,
.rootEntries = { 0x00, 0x02 },
.totalSectors = { 0x00, 0x00 },
.mediaDescriptor = 0xF8, // HDD
.sectorsPerFAT = { 0x00, 0x01 },
.sectorsPerTrack = { 0x3F,0x00 },
.heads = { 0xFF,0x00 },
.hiddenSectors = { 0x00, 0x08, 0x00, 0x00 },
.bigTotalSectors = { 0x00,0x00,0x08, 0x00 },
.driveNumber = 0x80,
.unused = ,
.extBootSignature = 0x29,
.serialNumber = { 0x78,0x56,0x34,0x12 },
.volumeLabel = { 'N','O',' ','N','A','M','E',' ',' ',' ',' ' },
.fileSystemType = { 'F','A','T','','',' ',' ',' ' },
.loadProgramCode = { },
.sig = { 0x55, 0xAA },
}; #define SECTOR_MBR (0x0000)
#define SECTOR_PBR (0x0800)
#define SECTOR_FAT1 (0x0808)
#define SECTOR_FAT2 (0x0908)
#define SECTOR_ROOT (0x0A08)
#define SECTOR_DATA (0x0A28) void _handleFatClusterChain(uint32_t sect_offset, uint8_t *buf)
{
uint16_t *bufW = (uint16_t *)&buf[];
if (sect_offset == )
{
bufW[] = 0xfff8;
bufW[] = 0xffff;
bufW[] = 0xffff; //结束第一个文件。1簇。
}
} void _handleRoot(uint32_t sect_offset, uint8_t *buf)
{
// 1 sector(512bytes) has 16 entries
DirEntry *pDir = (DirEntry *)buf;
if (sect_offset == )
{
memset(pDir, 0x00, sizeof(DirEntry));
sprintf((char *)pDir->name, "TEXT_123");
pDir->extension[] = 'T';
pDir->extension[] = 'X';
pDir->extension[] = 'T';
pDir->attribute = 0x00;
{
DirEntTime *pT = (DirEntTime *)&pDir->updateTime[];
DirEntDate *pD = (DirEntDate *)&pDir->updateDate[];
pT->B.hour = ;
pT->B.minutes = ;
pT->B.second = / ;
pD->B.year = - ;
pD->B.month = ;
pD->B.day = ;
} *(uint16_t*)&pDir->cluster = 0x0002;
*(uint32_t*)&pDir->fileSize = ;
}
} void _handleData(uint32_t sect_offset, uint8_t *buf)
{
memset(buf, 'A', );
sprintf((char *)buf, "Hello World!\r\n");
buf[]='>';
} uint32_t _ReadSector(uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
switch (blk_addr)
{
case SECTOR_MBR:
memcpy(buf, (const void *)&sectMBR, );
break;
case SECTOR_PBR:
memcpy(buf, (const void *)&sectBPB, );
break;
default:
memset(buf, 0x00, );
//FAT cluster chain
if ((SECTOR_FAT1 <= blk_addr) && (blk_addr < SECTOR_ROOT))
{
if (blk_addr >= SECTOR_FAT2)
{
blk_addr -= (SECTOR_FAT2 - SECTOR_FAT1);
}
_handleFatClusterChain(blk_addr - SECTOR_FAT1, buf); }
else if ((SECTOR_ROOT <= blk_addr) && (blk_addr < SECTOR_DATA))
{
_handleRoot(blk_addr - SECTOR_ROOT, buf); }
else if (SECTOR_DATA <= blk_addr)
{
_handleData(blk_addr - SECTOR_DATA, buf); }
break;
}
return ;
}
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */ /**
* @}
*/ USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
{
STORAGE_Init_FS,
STORAGE_GetCapacity_FS,
STORAGE_IsReady_FS,
STORAGE_IsWriteProtected_FS,
STORAGE_Read_FS,
STORAGE_Write_FS,
STORAGE_GetMaxLun_FS,
(int8_t *)STORAGE_Inquirydata_FS,
}; /* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name : STORAGE_Init_FS
* Description :
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
int8_t STORAGE_Init_FS (uint8_t lun)
{
/* USER CODE BEGIN 2 */
return (USBD_OK);
/* USER CODE END 2 */
} /*******************************************************************************
* Function Name : STORAGE_GetCapacity_FS
* Description :
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
int8_t STORAGE_GetCapacity_FS (uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
/* USER CODE BEGIN 3 */
*block_num = STORAGE_BLK_NBR;
*block_size = STORAGE_BLK_SIZ;
return (USBD_OK);
/* USER CODE END 3 */
} /*******************************************************************************
* Function Name : STORAGE_IsReady_FS
* Description :
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
int8_t STORAGE_IsReady_FS (uint8_t lun)
{
/* USER CODE BEGIN 4 */
return (USBD_OK);
/* USER CODE END 4 */
} /*******************************************************************************
* Function Name : STORAGE_IsWriteProtected_FS
* Description :
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
int8_t STORAGE_IsWriteProtected_FS (uint8_t lun)
{
/* USER CODE BEGIN 5 */
return (USBD_OK);
/* USER CODE END 5 */
} /*******************************************************************************
* Function Name : STORAGE_Read_FS
* Description :
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
int8_t STORAGE_Read_FS (uint8_t lun,
uint8_t *buf,
uint32_t blk_addr,
uint16_t blk_len)
{
/* USER CODE BEGIN 6 */
_ReadSector(buf, blk_addr, blk_len);
return (USBD_OK);
/* USER CODE END 6 */
} /*******************************************************************************
* Function Name : STORAGE_Write_FS
* Description :
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
int8_t STORAGE_Write_FS (uint8_t lun,
uint8_t *buf,
uint32_t blk_addr,
uint16_t blk_len)
{
/* USER CODE BEGIN 7 */
return (USBD_OK);
/* USER CODE END 7 */
} /*******************************************************************************
* Function Name : STORAGE_GetMaxLun_FS
* Description :
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
int8_t STORAGE_GetMaxLun_FS (void)
{
/* USER CODE BEGIN 8 */
return (STORAGE_LUN_NBR - );
/* USER CODE END 8 */
} /* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */ /**
* @}
*/ /**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

[转]使用STM32CubeMX:USB大容量存储设备的更多相关文章

  1. 控制器没有足够的带宽可利用为USB大容量存储设备的解决方法

    伴随网盘时代的没落,最近刚入手了一个移动硬盘.现在的移动硬盘都是USB3.0,传输速度比USB2.0要快很多.但是链接笔记本电脑后发现传输速度在20MB/s左右,跟USB2.0速度差不多,并不能达到传 ...

  2. 弹出USB大容量存储设备时出问题的解决方法

    我的计算机->管理->系统工具->事件查看器->自定义视图->Kernel-Pnp->详情->进程ID 然后在任务管理器里找到该进程(任务管理器->查看 ...

  3. win10突然不能使用usb大容量存储设备(移动硬盘)的解决方法

    昨天开始使用usb硬盘,发现一块无法识别,一块识别好了以后不能打开. 可能是之前一次系统更新有bug,但是一直也没有用移动硬盘,所以没有发现. 开始尝试各种方案,已经尝试过并且无效的有以下几个: 1, ...

  4. [未完] Linux 4.4 USB —— spiflash模拟usb大容量存储设备 调试记录 Gadget Mass Stroage

    linux 4.4 USB Gadget Mass Stroage 硬件平台: licheepi nano衍生 调试记录 驱动信息 │ This driver is a replacement for ...

  5. 【转】弹出USB大容量存储设备时出问题的解决方法

    原文链接 如下图所示,这个问题,相信很多人都有遇到过,而且经常难以解决,试了很多方法都无效.到最后,只能抱着侥幸的心理直接拔出,如果运气好,可能没有事,如果运气不好,你的U盘或者移动硬盘就要从此报废了 ...

  6. 教你开启红米的USB大容量存储选项,全网首发哦

    教你开启红米的USB大容量存储选项,全网首发哦 http://bbs.7to.cn/thread-10732-1-1.html 发表于 2014-4-29 110643 红米note入手也有两天了.各 ...

  7. 如何查找Mac上的USB存储设备使用痕迹

    最近刚好有个案子的证物主机是MBP, OS X版本为El Capitan,案况与营业秘密外泄有关,当中要找有关USB存储设备的使用痕迹. 要提醒大家的是,不同版本的OS X,各种迹证的存放文件名称及路 ...

  8. C# 访问USB(HID)设备

    原文:C# 访问USB(HID)设备 二话不说,直接给代码,如果您真想做这方面的东西,还是稍微研究下,没有现成的好类用,就需要自己了解其原理 //引用空间 using System; using Sy ...

  9. android usb Host模式下与usb Hid 设备的通信

    做android 与USB HID设备的通信有段时间了,总结一下遇到的问题和解决方法: 1,第一次遇到的问题:android 版本低不支持usb hid, 被要求做相关项目的时候,就从mUsbMana ...

随机推荐

  1. T-SQL select语句连接两个表

    当一个表中按条件出现多个记录时,会按照匹配条件生成多个结果记录.left out 和right out 是对不能匹配的记录发生作用.

  2. C++进阶--编译器自动生成的类函数

    //############################################################################ /* 在C++ 03标准下 在没有显式定义 ...

  3. Elasticsearch Internals: Networking Introduction An Overview of the Network Topology

    This article introduces the networking part of Elasticsearch. We look at the network topology of an ...

  4. 51nod 1132 覆盖数字的数量 V2

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1132 题意是给定a,b,l,r求[l,r]内有几个整数可以表示成ax+b ...

  5. bzoj4937: [Ceoi2016]popeala

    Description 你办了一场比赛,有n给人参加,只有一道题,有m个数据点,标号为1~m,每个测试点都有一个分数a[i].现在所 有选手已经提交了程序并且测评完了,你知道每个人都能通过哪些测试点. ...

  6. [转]FTP命令字和响应码解释

    FTP命令 命令  描述  ABOR 中断数据连接程序 ACCT <account> 系统特权帐号 ALLO <bytes>  为服务器上的文件存储器分配字节 APPE < ...

  7. 配置Flink依赖的pom文件时报错:flink-clients_2.11 & flink-streaming-java_2.11

    在配置eclipse上的pom文件时,在配置到flink-clients_2.11 和 flink-streaming-java_2.11这两个jar包的时候不管怎么弄都报错而且包一大堆错. 最难受的 ...

  8. 纯MATLAB版本 SIFT代码

    先贴几个链接: http://blog.csdn.net/abcjennifer/article/details/7639681  Rachel-Zhang的 http://blog.csdn.net ...

  9. 保存chrome主题背景的图片

    chrome主题背景的图怎样可以保存下来? 在chrome地址栏中输入: chrome://theme/IDR_THEME_NTP_BACKGROUND?npebkpkiddfadallfhefpip ...

  10. Jmeter(十)检查点

    检查点又名断言,我们在手工测试过程中肉眼以及自己的逻辑思维对实际结果进行判断是否与预期结果一致,但是工具是死的,没有眼睛,没有思维,并不知道需要判断的信息在哪块,或者是来判断什么东西,我们需要让工具更 ...