web-dev-qa-db-ja.com

STM32 USBデバイスライブラリを使用した大容量記憶装置としてのフラッシュメモリ

ボードにこのフラッシュメモリICがあり、これはSTM32F04に接続されていますARM=プロセッサ。ユーザーのプロセッサのUSBポートが利用可能です。フラッシュメモリがストレージデバイスとして検出されるようにしたいUSB経由でPCに接続した場合。

最初のステップとして、私は自分のUSBクラスをMSCとしてプログラムで正常に動作するように定義しました。ボードをPCに接続すると、接続されている大容量記憶装置を検出するため、 "You使用する前にディスクをフォーマットする必要があります。」.

ここで問題は、フラッシュをプロセッサの「ストレージ」として定義する方法です。以下はおそらくあなたの答えの一部です:-usbd_msc_storage_template.c -FAT file system

STM32F446プロセッサを使用しています。 FREERTOSおよびFATFS。私のPC上のWindows 10。

前もって感謝します :)

7
Ehsan Norouzi

まず第一に、大容量記憶装置としてPCに表示されるのがフラッシュメモリだけでよい場合は、MCUからファイルごとにストレージにアクセスするために使用されるため、FatFSは必要ありません。 PCがストレージデバイスにアクセスすると、PCはそれ自体でファイルシステムを管理し、ドライブのフォーマット時に使用するファイルシステムの種類を選択できます。ストレージ自体と通信するときに低レベルでダウンするのは、ストレージに「YアドレスからXバイトの読み取り/書き込み」を指示することだけです。デバイスが行う必要があるのは、特定のデータの書き込みまたは読み取りを行い、操作の結果を返すことだけです。

SBマスストレージデバイスクラス

このUSBクラスは、ストレージデバイスとしてホストにデバイスを公開し、指定されたアドレスから指定されたバイト数のデータを読み書きできるようにします。あなたが言及したSTM32F4の場合、実装する必要がある関数は次のとおりです(STM32Cubeライブラリに基づく)。

typedef struct _USBD_STORAGE
{
  int8_t (* Init) (uint8_t lun);
  int8_t (* GetCapacity) (uint8_t lun, uint32_t *block_num, uint16_t *block_size);
  int8_t (* IsReady) (uint8_t lun);
  int8_t (* IsWriteProtected) (uint8_t lun);
  int8_t (* Read) (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
  int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
  int8_t (* GetMaxLun)(void);
  int8_t *pInquiry;
}USBD_StorageTypeDef;

あなたが言及したように、実装するサンプルの空のテンプレートを提供するUSBD_MSC_Template_fops.c / .hファイルがあり、最も重要な関数はReadWriteであり、実際の「作業」終わらせる。デバイスをPCホストに接続したときにUSBマスストレージデバイスとして表示されるように初期化するには、USB自体を初期化(USBD_Init)して、MSCデバイスクラス( USBD_RegisterClass)、前述の構造をドライバーに登録(USBD_MSC_RegisterStorage)、ホストへの接続が検出されたときにドライバーのUSBデバイスプロセスを開始(USBD_Start)。多くの例があります。それを実行します-ディスカバリボードまたは評価ボードのリファレンス実装を参照してください。ホストプロパティがデバイスをUSB MSCデバイスとして検出し、フォーマットされていないと報告したため、正しく実行したようです。

ドライブがフォーマットされていないというシステムの理由は、usbd_msc_storage_template.cファイルの空の実装がSTORAGE_Read関数の実行に成功(戻りコード0)を返しますが、実際には読み取りを実行しないためです-データなし返送されます。これはオペレーティングシステムによってホストごとに異なる場合がありますが、最も可能性の高いシナリオは、ストレージがフォーマットされていないか、データが破損しているというメッセージが表示されることです。

SBマスストレージデバイスのコールバックと物理メモリのインターフェイス

上記のように、USBD_MSC_RegisterStorageを呼び出すと、構造体がUSBに登録されますMSCデバイスクラスドライバー。この時点で、ドライバー自体は、適切なタイミングで、提供された関数を呼び出します。ホスト。ターゲットメモリがSDカードの場合、自然な手順は、最初にSDカードにアクセスする機能を実装することです。これらの機能がテストされ、機能することが証明されたら、残りの機能をUSB内に配置するだけですMSCデバイスReadおよびWrite関数および-正しい割り込み優先度を前提として-通常は「箱から出して」機能します。システムはカードをフォーマットして後で読み取ることができ、 MCUを介してファイルを書き込みます。

選択したどのタイプのメモリでも同じように機能します。唯一の要件は、USBD_StorageTypeDefコールバック関数を正確に実装することです。これは、ホストが、報告されたアドレス空間内の任意のアドレスに任意の数のランダムなバイトを書き込むことを選択し、完全に従う(そのまますべてのデータを書き込む)か、「成功した実行」を返すか、エラーを返すことを意味します。つまり、ドライブがアンマウントされ、ユーザーにエラーメッセージが表示されます。読み取りの場合、これは、ホストがYアドレスからX数のバイトを要求した場合、デバイスが正確にその量のデータを返す必要があることを意味します。これは、メモリの種類がこの種のアクセスに完全に適していない場合、USBに準拠するために物理メモリにアクセスするレイヤーで実行する必要のある作業が増えることを意味しますMSC =インターフェースすべてが自然に以下の最後のポイントにつながります。

ファイルシステムストレージとしてのフラッシュメモリ

生データに直接アクセスするフラッシュメモリの場合、ファイルシステムアプリケーションに完全に適さない特定の欠点があります。それらはこれらの記憶が構築される方法から来ます。達成可能ですが、これらの欠陥を隠すために実行する必要がある追加の手順があります。

  1. 「1」を個別に書き込む-フラッシュメモリに直接アクセスすると、指定されたアドレスの下に「0」ビットのみを書き込むことができます。特定のビットを「0」にフリップすると、個別に「1」に戻すことはできなくなります。これを行うには、データのブロック全体を最初に消去する必要があります。フラッシュメモリのパーツにもよりますが、これは通常512、4096バイトなどの領域になります。つまり、特定のバイトを1(バイナリ0000 0001)から4(バイナリ0000 0100)に変更する場合は、セクター全体の読み取り/消去/書き込みを行う必要があります。これは、ホストが書き込みを要求するビットの1つでも「0」から「1」にフリップする必要がある場合、まずその領域を消去する必要があることを意味します。

  2. ランダムアクセス-メモリの種類(NOR/NAND)によって、ランダムにデータにアクセスできる場合とできない場合があります。特に、NORフラッシュの場合、データを個別に読み取りまたは書き込みできますが、NANDメモリの場合、セルの相互接続方法により、ページアクセスのみが許可されます。つまり、読み取りまたは書き込みが必要になる場合があります。必要以上のデータ。

  3. 書き込み耐久性-フラッシュメモリには、セルごとに特定の数の書き込みサイクルがあります。つまり、常に同じアドレスにデータを書き込むと、すぐにこの制限を超える可能性があります。これは、FAT領域が常に書き込まれるFATのようなファイルシステムでは特に重要です。これは、物理セクターの書き込みが均等に分散されるウェアレベリングの形式を実装することによって解決されます。アプリケーションで可能な場合は、IsWriteProtectedからtrueを返すことで、読み取り専用にすることもできます。

現在のSDカードがこれをすべて実現する方法については、私が認識している今日のすべてのSDカードには、上記すべてに加えてSDプロトコルを実装する単純なマイクロコントローラー(8081、ARM7などの一種)が含まれています。カードと話すとき、実際には生のメモリと話すのではなく、あなたとあなたのデータの間にあるMCUと通信します。その役割は、完璧な連続データの錯覚をユーザーに提示することです。

12
Jacek Ślimok