バックナンバーはこちら。
https://www.simulationroom999.com/blog/In-vehicle-external-storage-backnumber/
はじめに
FatFs WinシミュレーションでSDカードに直接制御する話。
今回は「FatFs改造」の話。
登場人物
博識フクロウのフクさん
イラストACにて公開の「kino_k」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=iKciwKA9&area=1
エンジニア歴8年の太郎くん
イラストACにて公開の「しのみ」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=uCKphAW2&area=1
実験手順
フクさん
想定実験手順は以下。
今回は「FatFs改造」の話。
- FatFs改造方針を考える
- FatFs改造 ← これの1回目/全3回
- FatFsでSDカードのFAT認識
- FatFsでファイル書き込みとWindowsでの認識
- FatFsでFAT32フォーマットしてWindowsで認識
フクさん
そして、全体構成
太郎くん
たしか、大体改造したソースコードを見るんだよね?
フクさん
そうそう。
とりあえず、差分は以下だ。
FatFs改造差分コード
diff U3B win32/diskio.c win32/diskio.c
--- win32/diskio.c Thu Dec 3 23:18:14 2020
+++ win32/diskio.c Mon Jan 4 02:16:08 2021
@@ -14,8 +14,8 @@
#define SZ_RAMDISK 135 /* Size of drive 0 (RAM disk) [MiB] */
#define SS_RAMDISK 512 /* Initial sector size of drive 0 (RAM disk) [byte] */
-#define MIN_READ_ONLY 1 /* Read-only drive from */
-#define MAX_READ_ONLY 1 /* Read-only drive to */
+#define MIN_READ_ONLY 5 /* Read-only drive from */
+#define MAX_READ_ONLY 5 /* Read-only drive to */
@@ -55,7 +55,7 @@
DWORD dw;
int drv;
-
+#if 0
for (;;) {
Sleep(100);
for (drv = 1; drv < Drives; drv++) {
@@ -69,6 +69,7 @@
}
}
}
+#endif
}
@@ -92,6 +93,12 @@
return 1;
}
+ if (pdrv > 3) {
+ stat->n_sectors = 1024 * 1024;
+ stat->sz_sector = 512;
+ stat->status = 0;
+ }
+
/* Get drive size */
if (!DeviceIoControl(h, IOCTL_STORAGE_CHECK_VERIFY, 0, 0, 0, 0, &rb, 0)) return 0;
if (DeviceIoControl(h, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, 0, 0, &parms_ex, sizeof parms_ex, &rb, 0)) {
@@ -119,6 +125,29 @@
Public Functions
---------------------------------------------------------------------------*/
+static HANDLE hSD[10];
+
+void dismount_volume(const TCHAR drvlet[])
+{
+ int i;
+ DWORD dummy;
+ for (i = 0; i < 10; i++) {
+ HANDLE *pSD = &hSD[i];
+ WCHAR szlogicalDrvName[10] = L"\\\\.\\d:";
+ if (drvlet[i] == '\0') {
+ break;
+ }
+ szlogicalDrvName[4] = drvlet[i];
+ if ((*pSD != 0)) {
+ DeviceIoControl(*pSD, FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0, &dummy, 0);
+ CloseHandle(*pSD);
+ *pSD = 0;
+ }
+ *pSD = CreateFileW(szlogicalDrvName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
+ DeviceIoControl(*pSD, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &dummy, 0);
+ DeviceIoControl(*pSD, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, &dummy, 0);
+ }
+}
/*-----------------------------------------------------------------------*/
@@ -143,17 +172,29 @@
if (!RamDisk) return 0;
Stat[0].sz_sector = SS_RAMDISK;
- if (GetVersionEx(&vinfo) == FALSE) return 0;
- ndrv = vinfo.dwMajorVersion > 5 ? 1 : MAX_DRIVES;
+ //if (GetVersionEx(&vinfo) == FALSE) return 0;
+ //ndrv = vinfo.dwMajorVersion > 5 ? 1 : MAX_DRIVES;
+ ndrv = MAX_DRIVES;
for (pdrv = 0; pdrv < ndrv; pdrv++) {
if (pdrv == 0) { /* \\.\PhysicalDrive0 is never mapped to disk function, but RAM disk is mapped to pd#0 instead. */
swprintf(str, 50, L"RAM Disk");
- } else { /* \\.\PhysicalDrive<n> (n=1..) are mapped to disk funtion pd#<n>. */
+ } else if(pdrv <= 3){ /* \\.\PhysicalDrive<n> (n=1..) are mapped to disk funtion pd#<n>. */
swprintf(str, 50, L"\\\\.\\PhysicalDrive%u", pdrv);
- h = CreateFileW(str, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
- if (h == INVALID_HANDLE_VALUE) break;
- Stat[pdrv].h_drive = h;
+ if (Stat[pdrv].h_drive != 0) {
+ CloseHandle(Stat[pdrv].h_drive);
+ }
+ h = CreateFileW(str, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
+ if (h != INVALID_HANDLE_VALUE)
+ Stat[pdrv].h_drive = h;
+ }else {
+ swprintf(str, 50, L"PhysicalDrive%u", pdrv);
+ if (Stat[pdrv].h_drive != 0) {
+ CloseHandle(Stat[pdrv].h_drive);
+ }
+ h = CreateFileW(str, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
+ if (h != INVALID_HANDLE_VALUE)
+ Stat[pdrv].h_drive = h;
}
wprintf(L"PD#%u <== %s", pdrv, str);
if (get_status(pdrv)) {
@@ -321,9 +362,35 @@
res = RES_ERROR;
} else {
memcpy(Buffer, buff, nc);
- if (!WriteFile(Stat[pdrv].h_drive, Buffer, nc, &rnc, 0) || nc != rnc) {
- res = RES_ERROR;
+ {
+ int i;
+ //DWORD dummy;
+ //DeviceIoControl( Stat[pdrv].h_drive, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &dummy, 0 );
+ //DeviceIoControl( Stat[pdrv].h_drive, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, &dummy, 0 );
+ for (i = 0; i < 10; i++) {
+ if (!WriteFile(Stat[pdrv].h_drive, Buffer, nc, &rnc, 0) || nc != rnc) {
+ LPVOID lpMsgBuf;
+ res = RES_ERROR;
+
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER // テキストのメモリ割り当てを要求する
+ | FORMAT_MESSAGE_FROM_SYSTEM // エラーメッセージはWindowsが用意しているものを使用
+ | FORMAT_MESSAGE_IGNORE_INSERTS,// 次の引数を無視してエラーコードに対するエラーメッセージを作成する
+ NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),// 言語を指定
+ (LPTSTR)&lpMsgBuf, // メッセージテキストが保存されるバッファへのポインタ
+ 0,
+ NULL);
+ printf((char*)lpMsgBuf);
+
+ }
+ else {
+ res = RES_OK;
+ break;
+ }
+ }
+ //DeviceIoControl( Stat[pdrv].h_drive, FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0, &dummy, 0 );
}
+ FlushFileBuffers(Stat[pdrv].h_drive);
}
}
} else { /* RAM disk */
diff U3B win32/main.c win32/main.c
--- win32/main.c Thu Dec 3 23:18:14 2020
+++ win32/main.c Sun May 2 02:48:11 2021
@@ -26,8 +26,8 @@
/* This is an example of volume - partition mapping table */
PARTITION VolToPart[FF_VOLUMES] = {
{0, 1}, /* "0:" ==> 1st partition on PD#0 */
- {0, 2}, /* "1:" ==> 2nd partition on PD#0 */
- {0, 3}, /* "2:" ==> 3rd partition on PD#0 */
+// {0, 2}, /* "1:" ==> 2nd partition on PD#0 */
+// {0, 3}, /* "2:" ==> 3rd partition on PD#0 */
{1, 0}, /* "1:" ==> PD#1 */
{2, 0}, /* "2:" ==> PD#2 */
{3, 0}, /* "3:" ==> PD#3 */
@@ -559,6 +559,12 @@
zprintf(L"FatFs module test monitor (%s, CP%u, %s)\n\n", FF_USE_LFN ? L"LFN" : L"SFN", FF_CODE_PAGE, uni[FF_LFN_UNICODE]);
assign_drives(); /* Find physical drives on the PC */
+ {
+ extern void dismount_volume(const TCHAR drvlet[]);
+ const TCHAR drvlet[10] = { 'd','e','f','g','\0' };
+ dismount_volume(drvlet);
+ }
+
#if FF_MULTI_PARTITION
zprintf(L"\nMultiple partition is enabled. Logical drives are associated with the patitions as follows:\n");
for (cnt = 0; cnt < sizeof VolToPart / sizeof (PARTITION); cnt++) {
差分コードの解説
フクさん
コードの解説は次回かなー。
太郎くん
とりあえず、気になるポイントは以下かな。
- dismount_volume関数
- main.cのVolToPart配列
フクさん
じゃ、そこに注力して解説しよう。
まとめ
フクさん
まとめだよ。
- FatFs改造のソースコード差分提示。
- 次回から以下に注力する形で開設予定。
- dismount_volume関数。
- DeviceIoControlがポイントとなる。
- main.cのVolToPart配列。
- 論理ドライブと物理ドライブ関連。
- dismount_volume関数。
バックナンバーはこちら。
コメント