原文地址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
    1. ...
    2. USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
    3. {
    4. STORAGE_Init_FS,
    5. STORAGE_GetCapacity_FS,
    6. STORAGE_IsReady_FS,
    7. STORAGE_IsWriteProtected_FS,
    8. STORAGE_Read_FS,
    9. STORAGE_Write_FS,
    10. STORAGE_GetMaxLun_FS,
    11. (int8_t *)STORAGE_Inquirydata_FS,
    12. };
    13. ...
  • ディスクの容量は、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
    1. ...
    2. #define STORAGE_LUN_NBR 1
    3. #define STORAGE_BLK_NBR 0x81000 //##mt08
    4. #define STORAGE_BLK_SIZ
    5.  
    6. ...
    7.  
    8. int8_t STORAGE_IsWriteProtected_FS (uint8_t lun)
    9. {
    10. /* USER CODE BEGIN 5 */
    11. return (USBD_FAIL); //##mt08: Read Only
    12. /* USER CODE END 5 */
    13. }
    14.  
    15. ...
    16. int8_t STORAGE_Read_FS (uint8_t lun,
    17. uint8_t *buf,
    18. uint32_t blk_addr,
    19. uint16_t blk_len)
    20. {
    21. /* USER CODE BEGIN 6 */
    22. _ReadSector(buf, blk_addr, blk_len); //##mt08
    23. return (USBD_OK);
    24. /* USER CODE END 6 */
    25. }

追加コード

  • 型宣言

    1. #include <stdint.h>
    2. typedef uint8_t Byte;
    3. typedef struct MasterBootRecord {
    4. Byte checkRoutionOnx86[446];
    5. struct {
    6. Byte bootDescriptor; /* 0x80: bootable device, 0x00: non-bootable */
    7. Byte firstPartitionSector[3]; /* 1st sector number */
    8. Byte fileSystemDescriptor; /* 1:FAT12, 4:FAT16(less than 32MB), 5:Extended-DOS Partition,
    9. 6:FAT16(more 32MB), 0xb:FAT32(more 2GB),
    10. 0xc:FAT32 Int32h, 0xe:FAT16 Int32h,
    11. 0xf:5:Extended-DOS Partition Int32h */
    12. Byte lastPartitionSector[3];
    13. Byte firstSectorNumbers[4]; /* first sector number (link to BPB sector) */
    14. Byte numberOfSectors[4];
    15. } partitionTable[4];
    16. Byte sig[2]; /* 0x55, 0xaa */
    17. } MBRecord;
    18.  
    19. typedef struct FAT16BPB_t {
    20. /* FAT16 or FAT12 BPB */
    21. Byte jmpOpeCode[3]; /* 0xeb ?? 0x90 */
    22. Byte OEMName[8];
    23. /* FAT16 */
    24. Byte bytesPerSector[2]; /* bytes/sector */
    25. Byte sectorsPerCluster; /* sectors/cluster */
    26. Byte reservedSectors[2]; /* reserved sector, beginning with sector 0 */
    27. Byte numberOfFATs; /* file allocation table */
    28. Byte rootEntries[2]; /* root entry (512) */
    29. Byte totalSectors[2]; /* partion total secter */
    30. Byte mediaDescriptor; /* 0xf8: Hard Disk */
    31. Byte sectorsPerFAT[2]; /* sector/FAT (FAT32 always zero: see bigSectorsPerFAT) */
    32. Byte sectorsPerTrack[2]; /* sector/track (not use) */
    33. Byte heads[2]; /* heads number (not use) */
    34. Byte hiddenSectors[4]; /* hidden sector number */
    35. Byte bigTotalSectors[4]; /* total sector number */
    36. /* info */
    37. Byte driveNumber;
    38. Byte unused;
    39. Byte extBootSignature;
    40. Byte serialNumber[4];
    41. Byte volumeLabel[11];
    42. Byte fileSystemType[8]; /* "FAT16 " */
    43. Byte loadProgramCode[448];
    44. Byte sig[2]; /* 0x55, 0xaa */
    45. } BPBlock; // BIOS Parameter Block
    46.  
    47. typedef struct DirEntry_t {
    48. Byte name[8]; /* file name */
    49. Byte extension[3]; /* file name extension */
    50. Byte attribute; /* file attribute
    51. bit 4 directory flag
    52. bit 3 volume flag
    53. bit 2 hidden flag
    54. bit 1 system flag
    55. bit 0 read only flag */
    56. Byte reserved; /* use NT or same OS */
    57. Byte createTimeMs; /* VFAT 10millsec (0   199) */
    58. Byte createTime[2]; /* VFAT */
    59. Byte createDate[2]; /* VFAT */
    60. Byte accessDate[2]; /* VFAT */
    61. Byte clusterHighWord[2]; /* FAT32 MSB 16 bits */
    62. Byte updateTime[2];
    63. Byte updateDate[2];
    64. Byte cluster[2]; /* start cluster number */
    65. Byte fileSize[4]; /* file size in bytes (directory is always zero) */
    66. } DirEntry;
    67.  
    68. #pragma anon_unions
    69. typedef struct _DirEntTime {
    70. union {
    71. uint16_t W;
    72. struct {
    73. uint16_t second : 5;
    74. uint16_t minutes : 6;
    75. uint16_t hour : 5;
    76. } B;
    77. };
    78. } DirEntTime;
    79.  
    80. typedef struct _DirEntDate {
    81. union {
    82. uint16_t W;
    83. struct {
    84. uint16_t day : 5;
    85. uint16_t month : 4;
    86. uint16_t year : 7;
    87. } B;
    88. };
    89. } DirEntDate;
    90. #pragma no_anon_unions
  • 固定値: MBRとか、PBSとか。
    (てきとうなUSBフラッシュメモリで、パーティション切って、フォーマットして、ダンプして、必要なとこを入力)

    1. const MBRecord sectMBR = {
    2. .checkRoutionOnx86 = { 0x00 },
    3. .partitionTable = {
    4. {
    5. .bootDescriptor = 0x00,
    6. .firstPartitionSector = { 0x02, 0x21, 0x00 },
    7. .fileSystemDescriptor = 0x06, //FAT16
    8. .lastPartitionSector = { 0xC2, 0x22, 0x20 },
    9. .firstSectorNumbers = { 0x00, 0x08, 0x00, 0x00 },
    10. .numberOfSectors = { 0x00, 0x00, 0x08, 0x00 },
    11. },//[0]
    12. { 0 },//[1]
    13. { 0 },//[2]
    14. { 0 },//[3]
    15. },
    16. .sig = { 0x55, 0xAA },
    17. };
    18. const BPBlock sectBPB = {
    19. .jmpOpeCode = { 0xEB, 0x00, 0x90 },
    20. .OEMName = { ' ',' ',' ',' ',' ',' ',' ',' ' },
    21. .bytesPerSector = { 0x00, 0x02 },
    22. .sectorsPerCluster = 0x08, // 4KB/sectors
    23. .reservedSectors = { 0x08, 0x00 },
    24. .numberOfFATs = 0x02,
    25. .rootEntries = { 0x00, 0x02 },
    26. .totalSectors = { 0x00, 0x00 },
    27. .mediaDescriptor = 0xF8, // HDD
    28. .sectorsPerFAT = { 0x00, 0x01 },
    29. .sectorsPerTrack = { 0x3F,0x00 },
    30. .heads = { 0xFF,0x00 },
    31. .hiddenSectors = { 0x00, 0x08, 0x00, 0x00 },
    32. .bigTotalSectors = { 0x00,0x00,0x08, 0x00 },
    33. .driveNumber = 0x80,
    34. .unused = 0,
    35. .extBootSignature = 0x29,
    36. .serialNumber = { 0x78,0x56,0x34,0x12 },
    37. .volumeLabel = { 'N','O',' ','N','A','M','E',' ',' ',' ',' ' },
    38. .fileSystemType = { 'F','A','T','1','6',' ',' ',' ' },
    39. .loadProgramCode = { 0 },
    40. .sig = { 0x55, 0xAA },
    41. };
    42.  
    43. #define SECTOR_MBR (0x0000)
    44. #define SECTOR_PBR (0x0800)
    45. #define SECTOR_FAT1 (0x0808)
    46. #define SECTOR_FAT2 (0x0908)
    47. #define SECTOR_ROOT (0x0A08)
    48. #define SECTOR_DATA (0x0A28)
  • セクタ読み出しで、それっぽいデータをわたすとこ。

  1. void _handleFatClusterChain(uint32_t sect_offset, uint8_t *buf)
  2. {
  3. uint16_t *bufW = (uint16_t *)&buf[0];
  4. if (sect_offset == 0)
  5. {
  6. bufW[0] = 0xfff8;
  7. bufW[1] = 0xffff;
  8. bufW[2] = 0xffff; //最初のファイル. 1クラスタでおわり.
  9. }
  10. }
  11.  
  12. void _handleRoot(uint32_t sect_offset, uint8_t *buf)
  13. {
  14. // 1 sector(512bytes) has 16 entries
  15. DirEntry *pDir = (DirEntry *)buf;
  16. if (sect_offset == 0)
  17. {
  18. memset(pDir, 0x00, sizeof(DirEntry));
  19. sprintf((char *)pDir->name, "TEXT_123");
  20. pDir->extension[0] = 'T';
  21. pDir->extension[1] = 'X';
  22. pDir->extension[2] = 'T';
  23. pDir->attribute = 0x00;
  24. {
  25. DirEntTime *pT = (DirEntTime *)&pDir->updateTime[0];
  26. DirEntDate *pD = (DirEntDate *)&pDir->updateDate[0];
  27. pT->B.hour = 12;
  28. pT->B.minutes = 34;
  29. pT->B.second = 56 / 2;
  30. pD->B.year = 2017 - 1980;
  31. pD->B.month = 1;
  32. pD->B.day = 12;
  33. }
  34.  
  35. *(uint16_t*)&pDir->cluster = 0x0002;
  36. *(uint32_t*)&pDir->fileSize = 123;
  37. }
  38. }
  39.  
  40. void _handleData(uint32_t sect_offset, uint8_t *buf)
  41. {
  42. memset(buf, 'A', 512);
  43. sprintf((char *)buf, "Hello World!\r\n");
  44. buf[14]='>';
  45. }
  46.  
  47. uint32_t _ReadSector(uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
  48. {
  49. switch (blk_addr)
  50. {
  51. case SECTOR_MBR:
  52. memcpy(buf, (const void *)&sectMBR, 512);
  53. break;
  54. case SECTOR_PBR:
  55. memcpy(buf, (const void *)&sectBPB, 512);
  56. break;
  57. default:
  58. memset(buf, 0x00, 512);
  59. //FAT cluster chain
  60. if ((SECTOR_FAT1 <= blk_addr) && (blk_addr < SECTOR_ROOT))
  61. {
  62. if (blk_addr >= SECTOR_FAT2) { blk_addr -= (SECTOR_FAT2 - SECTOR_FAT1); }
  63. _handleFatClusterChain(blk_addr - SECTOR_FAT1, buf);
  64.  
  65. }
  66. else if ((SECTOR_ROOT <= blk_addr) && (blk_addr < SECTOR_DATA))
  67. {
  68. _handleRoot(blk_addr - SECTOR_ROOT, buf);
  69.  
  70. }
  71. else if (SECTOR_DATA <= blk_addr)
  72. {
  73. _handleData(blk_addr - SECTOR_DATA, buf);
  74.  
  75. }
  76. break;
  77. }
  78. return 0;
  79. }

その他

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

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

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

  1. /**
  2. ******************************************************************************
  3. * @file : usbd_storage_if.c
  4. * @brief : Memory management layer
  5. ******************************************************************************
  6. * This notice applies to any and all portions of this file
  7. * that are not between comment pairs USER CODE BEGIN and
  8. * USER CODE END. Other portions of this file, whether
  9. * inserted by the user or by software development tools
  10. * are owned by their respective copyright owners.
  11. *
  12. * Copyright (c) 2017 STMicroelectronics International N.V.
  13. * All rights reserved.
  14. *
  15. * Redistribution and use in source and binary forms, with or without
  16. * modification, are permitted, provided that the following conditions are met:
  17. *
  18. * 1. Redistribution of source code must retain the above copyright notice,
  19. * this list of conditions and the following disclaimer.
  20. * 2. Redistributions in binary form must reproduce the above copyright notice,
  21. * this list of conditions and the following disclaimer in the documentation
  22. * and/or other materials provided with the distribution.
  23. * 3. Neither the name of STMicroelectronics nor the names of other
  24. * contributors to this software may be used to endorse or promote products
  25. * derived from this software without specific written permission.
  26. * 4. This software, including modifications and/or derivative works of this
  27. * software, must execute solely and exclusively on microcontroller or
  28. * microprocessor devices manufactured by or for STMicroelectronics.
  29. * 5. Redistribution and use of this software other than as permitted under
  30. * this license is void and will automatically terminate your rights under
  31. * this license.
  32. *
  33. * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
  34. * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
  35. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  36. * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
  37. * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
  38. * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  39. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  40. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  41. * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  42. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  43. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  44. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  45. *
  46. ******************************************************************************
  47. */
  48.  
  49. /* Includes ------------------------------------------------------------------*/
  50. #include "usbd_storage_if.h"
  51. /* USER CODE BEGIN INCLUDE */
  52. /* USER CODE END INCLUDE */
  53.  
  54. /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
  55. * @{
  56. */
  57.  
  58. /** @defgroup USBD_STORAGE
  59. * @brief usbd core module
  60. * @{
  61. */
  62.  
  63. /** @defgroup USBD_STORAGE_Private_TypesDefinitions
  64. * @{
  65. */
  66. /* USER CODE BEGIN PRIVATE_TYPES */
  67. /* USER CODE END PRIVATE_TYPES */
  68. /**
  69. * @}
  70. */
  71.  
  72. /** @defgroup USBD_STORAGE_Private_Defines
  73. * @{
  74. */
  75. #define STORAGE_LUN_NBR 1
  76. #define STORAGE_BLK_NBR 0x81000
  77. #define STORAGE_BLK_SIZ 0x200
  78.  
  79. /* USER CODE BEGIN PRIVATE_DEFINES */
  80. /* USER CODE END PRIVATE_DEFINES */
  81.  
  82. /**
  83. * @}
  84. */
  85.  
  86. /** @defgroup USBD_STORAGE_Private_Macros
  87. * @{
  88. */
  89. /* USER CODE BEGIN PRIVATE_MACRO */
  90. /* USER CODE END PRIVATE_MACRO */
  91.  
  92. /**
  93. * @}
  94. */
  95.  
  96. /** @defgroup USBD_STORAGE_IF_Private_Variables
  97. * @{
  98. */
  99. /* USER CODE BEGIN INQUIRY_DATA_FS */
  100. /* USB Mass storage Standard Inquiry Data */
  101. const int8_t STORAGE_Inquirydata_FS[] = /* 36 */
  102. {
  103.  
  104. /* LUN 0 */
  105. 0x00,
  106. 0x80,
  107. 0x02,
  108. 0x02,
  109. (STANDARD_INQUIRY_DATA_LEN - ),
  110. 0x00,
  111. 0x00,
  112. 0x00,
  113. 'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
  114. 'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */
  115. ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
  116. '', '.', '' ,'', /* Version : 4 Bytes */
  117. };
  118. /* USER CODE END INQUIRY_DATA_FS */
  119.  
  120. /* USER CODE BEGIN PRIVATE_VARIABLES */
  121. /* USER CODE END PRIVATE_VARIABLES */
  122.  
  123. /**
  124. * @}
  125. */
  126.  
  127. /** @defgroup USBD_STORAGE_IF_Exported_Variables
  128. * @{
  129. */
  130. extern USBD_HandleTypeDef hUsbDeviceFS;
  131. /* USER CODE BEGIN EXPORTED_VARIABLES */
  132. /* USER CODE END EXPORTED_VARIABLES */
  133.  
  134. /**
  135. * @}
  136. */
  137.  
  138. /** @defgroup USBD_STORAGE_Private_FunctionPrototypes
  139. * @{
  140. */
  141. static int8_t STORAGE_Init_FS (uint8_t lun);
  142. static int8_t STORAGE_GetCapacity_FS (uint8_t lun,
  143. uint32_t *block_num,
  144. uint16_t *block_size);
  145. static int8_t STORAGE_IsReady_FS (uint8_t lun);
  146. static int8_t STORAGE_IsWriteProtected_FS (uint8_t lun);
  147. static int8_t STORAGE_Read_FS (uint8_t lun,
  148. uint8_t *buf,
  149. uint32_t blk_addr,
  150. uint16_t blk_len);
  151. static int8_t STORAGE_Write_FS (uint8_t lun,
  152. uint8_t *buf,
  153. uint32_t blk_addr,
  154. uint16_t blk_len);
  155. static int8_t STORAGE_GetMaxLun_FS (void);
  156.  
  157. /* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
  158. #include <stdint.h>
  159. typedef uint8_t Byte;
  160. typedef struct MasterBootRecord
  161. {
  162. Byte checkRoutionOnx86[];
  163. struct
  164. {
  165. Byte bootDescriptor; /* 0x80: bootable device, 0x00: non-bootable */
  166. Byte firstPartitionSector[]; /* 1st sector number */
  167. Byte fileSystemDescriptor; /* 1:FAT12, 4:FAT16(less than 32MB), 5:Extended-DOS Partition,
  168. 6:FAT16(more 32MB), 0xb:FAT32(more 2GB),
  169. 0xc:FAT32 Int32h, 0xe:FAT16 Int32h,
  170. 0xf:5:Extended-DOS Partition Int32h */
  171. Byte lastPartitionSector[];
  172. Byte firstSectorNumbers[]; /* first sector number (link to BPB sector) */
  173. Byte numberOfSectors[];
  174. } partitionTable[];
  175. Byte sig[]; /* 0x55, 0xaa */
  176. } MBRecord;
  177.  
  178. typedef struct FAT16BPB_t
  179. {
  180. /* FAT16 or FAT12 BPB */
  181. Byte jmpOpeCode[]; /* 0xeb ?? 0x90 */
  182. Byte OEMName[];
  183. /* FAT16 */
  184. Byte bytesPerSector[]; /* bytes/sector */
  185. Byte sectorsPerCluster; /* sectors/cluster */
  186. Byte reservedSectors[]; /* reserved sector, beginning with sector 0 */
  187. Byte numberOfFATs; /* file allocation table */
  188. Byte rootEntries[]; /* root entry (512) */
  189. Byte totalSectors[]; /* partion total secter */
  190. Byte mediaDescriptor; /* 0xf8: Hard Disk */
  191. Byte sectorsPerFAT[]; /* sector/FAT (FAT32 always zero: see bigSectorsPerFAT) */
  192. Byte sectorsPerTrack[]; /* sector/track (not use) */
  193. Byte heads[]; /* heads number (not use) */
  194. Byte hiddenSectors[]; /* hidden sector number */
  195. Byte bigTotalSectors[]; /* total sector number */
  196. /* info */
  197. Byte driveNumber;
  198. Byte unused;
  199. Byte extBootSignature;
  200. Byte serialNumber[];
  201. Byte volumeLabel[];
  202. Byte fileSystemType[]; /* "FAT16 " */
  203. Byte loadProgramCode[];
  204. Byte sig[]; /* 0x55, 0xaa */
  205. } BPBlock; // BIOS Parameter Block
  206.  
  207. typedef struct DirEntry_t
  208. {
  209. Byte name[]; /* file name */
  210. Byte extension[]; /* file name extension */
  211. Byte attribute; /* file attribute
  212. bit 4 directory flag
  213. bit 3 volume flag
  214. bit 2 hidden flag
  215. bit 1 system flag
  216. bit 0 read only flag */
  217. Byte reserved; /* use NT or same OS */
  218. Byte createTimeMs; /* VFAT 10millsec (0 199) */
  219. Byte createTime[]; /* VFAT */
  220. Byte createDate[]; /* VFAT */
  221. Byte accessDate[]; /* VFAT */
  222. Byte clusterHighWord[]; /* FAT32 MSB 16 bits */
  223. Byte updateTime[];
  224. Byte updateDate[];
  225. Byte cluster[]; /* start cluster number */
  226. Byte fileSize[]; /* file size in bytes (directory is always zero) */
  227. } DirEntry;
  228.  
  229. #pragma anon_unions
  230. typedef struct _DirEntTime
  231. {
  232. union
  233. {
  234. uint16_t W;
  235. struct
  236. {
  237. uint16_t second : ;
  238. uint16_t minutes : ;
  239. uint16_t hour : ;
  240. } B;
  241. };
  242. } DirEntTime;
  243.  
  244. typedef struct _DirEntDate
  245. {
  246. union
  247. {
  248. uint16_t W;
  249. struct
  250. {
  251. uint16_t day : ;
  252. uint16_t month : ;
  253. uint16_t year : ;
  254. } B;
  255. };
  256. } DirEntDate;
  257. #pragma no_anon_unions
  258.  
  259. const MBRecord sectMBR =
  260. {
  261. .checkRoutionOnx86 = { 0x00 },
  262. .partitionTable = {
  263. {
  264. .bootDescriptor = 0x00,
  265. .firstPartitionSector = { 0x02, 0x21, 0x00 },
  266. .fileSystemDescriptor = 0x06, //FAT16
  267. .lastPartitionSector = { 0xC2, 0x22, 0x20 },
  268. .firstSectorNumbers = { 0x00, 0x08, 0x00, 0x00 },
  269. .numberOfSectors = { 0x00, 0x00, 0x08, 0x00 },
  270. },//[0]
  271. { },//[1]
  272. { },//[2]
  273. { },//[3]
  274. },
  275. .sig = { 0x55, 0xAA },
  276. };
  277. const BPBlock sectBPB =
  278. {
  279. .jmpOpeCode = { 0xEB, 0x00, 0x90 },
  280. .OEMName = { ' ',' ',' ',' ',' ',' ',' ',' ' },
  281. .bytesPerSector = { 0x00, 0x02 },
  282. .sectorsPerCluster = 0x08, // 4KB/sectors
  283. .reservedSectors = { 0x08, 0x00 },
  284. .numberOfFATs = 0x02,
  285. .rootEntries = { 0x00, 0x02 },
  286. .totalSectors = { 0x00, 0x00 },
  287. .mediaDescriptor = 0xF8, // HDD
  288. .sectorsPerFAT = { 0x00, 0x01 },
  289. .sectorsPerTrack = { 0x3F,0x00 },
  290. .heads = { 0xFF,0x00 },
  291. .hiddenSectors = { 0x00, 0x08, 0x00, 0x00 },
  292. .bigTotalSectors = { 0x00,0x00,0x08, 0x00 },
  293. .driveNumber = 0x80,
  294. .unused = ,
  295. .extBootSignature = 0x29,
  296. .serialNumber = { 0x78,0x56,0x34,0x12 },
  297. .volumeLabel = { 'N','O',' ','N','A','M','E',' ',' ',' ',' ' },
  298. .fileSystemType = { 'F','A','T','','',' ',' ',' ' },
  299. .loadProgramCode = { },
  300. .sig = { 0x55, 0xAA },
  301. };
  302.  
  303. #define SECTOR_MBR (0x0000)
  304. #define SECTOR_PBR (0x0800)
  305. #define SECTOR_FAT1 (0x0808)
  306. #define SECTOR_FAT2 (0x0908)
  307. #define SECTOR_ROOT (0x0A08)
  308. #define SECTOR_DATA (0x0A28)
  309.  
  310. void _handleFatClusterChain(uint32_t sect_offset, uint8_t *buf)
  311. {
  312. uint16_t *bufW = (uint16_t *)&buf[];
  313. if (sect_offset == )
  314. {
  315. bufW[] = 0xfff8;
  316. bufW[] = 0xffff;
  317. bufW[] = 0xffff; //结束第一个文件。1簇。
  318. }
  319. }
  320.  
  321. void _handleRoot(uint32_t sect_offset, uint8_t *buf)
  322. {
  323. // 1 sector(512bytes) has 16 entries
  324. DirEntry *pDir = (DirEntry *)buf;
  325. if (sect_offset == )
  326. {
  327. memset(pDir, 0x00, sizeof(DirEntry));
  328. sprintf((char *)pDir->name, "TEXT_123");
  329. pDir->extension[] = 'T';
  330. pDir->extension[] = 'X';
  331. pDir->extension[] = 'T';
  332. pDir->attribute = 0x00;
  333. {
  334. DirEntTime *pT = (DirEntTime *)&pDir->updateTime[];
  335. DirEntDate *pD = (DirEntDate *)&pDir->updateDate[];
  336. pT->B.hour = ;
  337. pT->B.minutes = ;
  338. pT->B.second = / ;
  339. pD->B.year = - ;
  340. pD->B.month = ;
  341. pD->B.day = ;
  342. }
  343.  
  344. *(uint16_t*)&pDir->cluster = 0x0002;
  345. *(uint32_t*)&pDir->fileSize = ;
  346. }
  347. }
  348.  
  349. void _handleData(uint32_t sect_offset, uint8_t *buf)
  350. {
  351. memset(buf, 'A', );
  352. sprintf((char *)buf, "Hello World!\r\n");
  353. buf[]='>';
  354. }
  355.  
  356. uint32_t _ReadSector(uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
  357. {
  358. switch (blk_addr)
  359. {
  360. case SECTOR_MBR:
  361. memcpy(buf, (const void *)&sectMBR, );
  362. break;
  363. case SECTOR_PBR:
  364. memcpy(buf, (const void *)&sectBPB, );
  365. break;
  366. default:
  367. memset(buf, 0x00, );
  368. //FAT cluster chain
  369. if ((SECTOR_FAT1 <= blk_addr) && (blk_addr < SECTOR_ROOT))
  370. {
  371. if (blk_addr >= SECTOR_FAT2)
  372. {
  373. blk_addr -= (SECTOR_FAT2 - SECTOR_FAT1);
  374. }
  375. _handleFatClusterChain(blk_addr - SECTOR_FAT1, buf);
  376.  
  377. }
  378. else if ((SECTOR_ROOT <= blk_addr) && (blk_addr < SECTOR_DATA))
  379. {
  380. _handleRoot(blk_addr - SECTOR_ROOT, buf);
  381.  
  382. }
  383. else if (SECTOR_DATA <= blk_addr)
  384. {
  385. _handleData(blk_addr - SECTOR_DATA, buf);
  386.  
  387. }
  388. break;
  389. }
  390. return ;
  391. }
  392. /* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
  393.  
  394. /**
  395. * @}
  396. */
  397.  
  398. USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
  399. {
  400. STORAGE_Init_FS,
  401. STORAGE_GetCapacity_FS,
  402. STORAGE_IsReady_FS,
  403. STORAGE_IsWriteProtected_FS,
  404. STORAGE_Read_FS,
  405. STORAGE_Write_FS,
  406. STORAGE_GetMaxLun_FS,
  407. (int8_t *)STORAGE_Inquirydata_FS,
  408. };
  409.  
  410. /* Private functions ---------------------------------------------------------*/
  411. /*******************************************************************************
  412. * Function Name : STORAGE_Init_FS
  413. * Description :
  414. * Input : None.
  415. * Output : None.
  416. * Return : None.
  417. *******************************************************************************/
  418. int8_t STORAGE_Init_FS (uint8_t lun)
  419. {
  420. /* USER CODE BEGIN 2 */
  421. return (USBD_OK);
  422. /* USER CODE END 2 */
  423. }
  424.  
  425. /*******************************************************************************
  426. * Function Name : STORAGE_GetCapacity_FS
  427. * Description :
  428. * Input : None.
  429. * Output : None.
  430. * Return : None.
  431. *******************************************************************************/
  432. int8_t STORAGE_GetCapacity_FS (uint8_t lun, uint32_t *block_num, uint16_t *block_size)
  433. {
  434. /* USER CODE BEGIN 3 */
  435. *block_num = STORAGE_BLK_NBR;
  436. *block_size = STORAGE_BLK_SIZ;
  437. return (USBD_OK);
  438. /* USER CODE END 3 */
  439. }
  440.  
  441. /*******************************************************************************
  442. * Function Name : STORAGE_IsReady_FS
  443. * Description :
  444. * Input : None.
  445. * Output : None.
  446. * Return : None.
  447. *******************************************************************************/
  448. int8_t STORAGE_IsReady_FS (uint8_t lun)
  449. {
  450. /* USER CODE BEGIN 4 */
  451. return (USBD_OK);
  452. /* USER CODE END 4 */
  453. }
  454.  
  455. /*******************************************************************************
  456. * Function Name : STORAGE_IsWriteProtected_FS
  457. * Description :
  458. * Input : None.
  459. * Output : None.
  460. * Return : None.
  461. *******************************************************************************/
  462. int8_t STORAGE_IsWriteProtected_FS (uint8_t lun)
  463. {
  464. /* USER CODE BEGIN 5 */
  465. return (USBD_OK);
  466. /* USER CODE END 5 */
  467. }
  468.  
  469. /*******************************************************************************
  470. * Function Name : STORAGE_Read_FS
  471. * Description :
  472. * Input : None.
  473. * Output : None.
  474. * Return : None.
  475. *******************************************************************************/
  476. int8_t STORAGE_Read_FS (uint8_t lun,
  477. uint8_t *buf,
  478. uint32_t blk_addr,
  479. uint16_t blk_len)
  480. {
  481. /* USER CODE BEGIN 6 */
  482. _ReadSector(buf, blk_addr, blk_len);
  483. return (USBD_OK);
  484. /* USER CODE END 6 */
  485. }
  486.  
  487. /*******************************************************************************
  488. * Function Name : STORAGE_Write_FS
  489. * Description :
  490. * Input : None.
  491. * Output : None.
  492. * Return : None.
  493. *******************************************************************************/
  494. int8_t STORAGE_Write_FS (uint8_t lun,
  495. uint8_t *buf,
  496. uint32_t blk_addr,
  497. uint16_t blk_len)
  498. {
  499. /* USER CODE BEGIN 7 */
  500. return (USBD_OK);
  501. /* USER CODE END 7 */
  502. }
  503.  
  504. /*******************************************************************************
  505. * Function Name : STORAGE_GetMaxLun_FS
  506. * Description :
  507. * Input : None.
  508. * Output : None.
  509. * Return : None.
  510. *******************************************************************************/
  511. int8_t STORAGE_GetMaxLun_FS (void)
  512. {
  513. /* USER CODE BEGIN 8 */
  514. return (STORAGE_LUN_NBR - );
  515. /* USER CODE END 8 */
  516. }
  517.  
  518. /* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
  519. /* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
  520.  
  521. /**
  522. * @}
  523. */
  524.  
  525. /**
  526. * @}
  527. */
  528. /************************ (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. 【springboot】之整合ActiveMQ

    1.引入依赖的jar <parent> <groupId>org.springframework.boot</groupId> <artifactId> ...

  2. HEAD插件安装

    简介 是一个HTML5编写的集群操作和管理工具,可以对集群进行傻瓜式操作,Head插件中可以显示集群的拓扑结构,执行索引和节点级别等操作,同时也可以输入RESTful命令和Elasticsearch交 ...

  3. MySQL mysqlbinlog企业案例

    内容待补充 案例文字说明: 7.3 故障时间点: 周四上午10点,开发人员误删除了一个表,如何恢复? 7.4 思路: 1.停业务,避免数据的二次伤害 2.找一个临时库,恢复周三23:00全备 3.截取 ...

  4. scheduler定时器相关

    定时器官网: http://www.quartz-scheduler.org/

  5. ~Vue实现简单答题功能,主要包含单选框和复选框

    内容 实现简单答题效果 环境 Vue,webpack(自行安装) 实现方式 页面将答题列表传递给调用组件,组件将结果返回给调用页面(其它模式也ok,这只是例子) ------------------- ...

  6. linux命令之vi文本编辑器

    vi filename :打开或新建文件,并将光标置于第一行首 按i,开始输入(insert) d删除整行 u   撤销上一步的操作Ctrl+r 恢复上一步被撤销的操作 ESC退出输入 按ESC键 跳 ...

  7. angular的常见问题

    ng-if 跟 ng-show/hide 的区别有哪些? 第一点区别是,ng-if 在后面表达式为 true 的时候才创建这个 dom 节点,ng-show 是初始时就创建了,用 display:bl ...

  8. 《C++数据结构-快速拾遗》 基础常识

    1.命名空间函数 namespace wjy { void print() { cout<<"; } int load(int num) { return num; } } us ...

  9. install

    程序包:GNU coreutils 语法: 类似于“cp”,复制文件后默认具有执行权限(755). 选项:  包含公共选项 -d,创建目录. -m,指定复制后的权限设定(默认设定755). -o,指定 ...

  10. Webpack配置及使用

    ##如何将js模块化 ### module.exports() ### module.require() ### 自定义文件,进入时需要./ ### npm下载得到文件,不需要./ ##如果使用第三方 ...