0

私は STM32F401VCT6U 「ディスカバリー」ボードを使用しており、ユーザーが実行時にメモリにアドレスを書き込む方法を提供する必要があります。

次の関数に簡略化できるものを書きました。

uint8_t Write(uint32_t address, uint8_t* values, uint8_t count) 
{
    uint8_t index;
    for (index = 0; index < count; ++index) {
        if (IS_FLASH_ADDRESS(address+index)) {
            /* flash write */
            FLASH_Unlock();
            if (FLASH_ProgramByte(address+index, values[index]) != FLASH_COMPLETE) {
                  return FLASH_ERROR;
            }
            FLASH_Lock();
        } else {
            /* ram write */
            ((uint8_t*)address)[index] = values[index]
        }
    }
    return NO_ERROR;
}

上記で、addressはベースアドレス、valuesは少なくともcountメモリに書き込むバイトと書き込むバイト数を含むサイズのバッファですcount

さて、私の問題は次のとおりです。上記の関数がaddressフラッシュ内のベースで呼び出されcount=100、最初の数回は正常に動作し、渡されたvaluesバッファがフラッシュに書き込まれます。ただし、これらの最初の数回の呼​​び出しの後、私はもう値を書き込むことはできません: フラッシュの値のビットをリセットすることしかできません。任意の値への 0x00 は成功します (ただし、後でアドレスに他の値を書き込むことはできません)。

base を変更することで、フラッシュ内の他のアドレスに正常に書き込むことができますがaddress、これも数回 ( を使用して 2 回または 3 回呼び出しますcount=100) だけです。

この動作は、フラッシュの最大書き込み回数に達したことを示唆していますが、それほど高速になるとは思えません。枯渇する前に、少なくとも10,000回の書き込みが予想されます。それで、私は何を間違っていますか?

4

3 に答える 3

5

フラッシュがどのように機能するかを誤解しています。たとえば、EEPROM への書き込みほど簡単ではありません。あなたが説明している動作は、フラッシュの正常な動作です。
フラッシュの同じアドレスを繰り返し書き込むには、最初に FLASH_EraseSector を使用してセクタ全体を消去する必要があります。通常、この消去中に保持する必要があるデータは、RAM または別のフラッシュ セクターにバッファリングする必要があります。
データの小さなブロックを繰り返し書き込んでいて、フラッシュのバーンアウトが心配な場合は、多くの消去書き込みサイクルを行う必要があります。書き込みのたびにデータをフラッシュ セクターに沿って未書き込みのフラッシュに移動するフラッシュへのインターフェイスを書き込み、追跡します。セクターの開始からの現在のオフセット。その場合にのみ、セクター内のバイトがなくなったときに、セクターの先頭から消去してやり直す必要があります。

于 2015-06-11T08:21:47.920 に答える
0

私は実用的でテスト済みのソリューションを持っていますが、@Ricibobの回答とはかなり異なるため、これを回答にすることにしました。

ユーザーは選択したフラッシュ セクタのどこにでも書き込むことができるため、保持する必要があるデータのみを RAM にバッファリングしながら、必要に応じてセクタを消去する責任をアプリケーションが処理できません。

その結果、セクターへの書き込みが機能しない場合にセクターを消去する責任をユーザーに移しました (この方法では、ユーザーはセクター内の別のアドレスを自由に使用して、書き込みと消去のサイクルが多すぎるのを回避できます)。

解決

基本的に、リターン コードと失敗した場合のwrite(uint32_t startAddress, uint8_t count, uint8_t* values)関数を公開します。また、パラメーターとして渡されたアドレスに対応するセクターの ID、開始アドレス、および終了アドレスを返す関数をユーザーに提供します。このようにして、ユーザーは消去操作によってどの範囲のアドレスが影響を受けるかを知ることができます。最後に、ID がパラメーターとして渡されたフラッシュ セクターを消去する関数を公開します。WRITE_SUCCESSFULCANNOT_WRITE_FLASHgetSector(uint32_t address)eraseSector(uint8_t sectorID)

ポリシーの消去

失敗した書き込みのポリシーは、「フラッシュの値が FF と異なる場合は消去する」という @Ricibob の提案とは異なります。これは、ビットリセットのみである限り書き込みが成功することがフラッシュプログラミングマニュアルに記載されているためです (これは一致します)。質問で観察した動作):

注: ビットを「1」から「0」に変更する場合、消去操作を必要とせずに、連続した書き込み操作が可能です。「1」を書き込むには、フラッシュ メモリの消去操作が必要です。消去とプログラム動作が同時に要求された場合、消去動作が最初に実行されます。

そこで、マクロを使用します。CAN_WRITE(a,b)ここaで、 はフラッシュの元の値でありb、目的の値です。マクロは次のように定義されます。

!(~a & b)

これは次の理由で機能します。

  • 論理 not( !) は 0 を に変換し、trueそれ以外はすべてに変換するため、マクロを 0 に等しくする必要があります。false~a & btrue
  • 1 in の任意のビットaは 0 in~aであるため、 in の値に関係なく 0 になりますb( 1 in 1 または 0 を変換できます)。
  • のビットが 0 の場合aは の 1 で~aあり、bが 1の場合~a & b != 0は書き込みができず、b0 の場合は問題ありません ( 0 を 1 ではなく 0 にのみ変換できます)。

STM32F4 のフラッシュ セクタのリスト

最後に、今後の参考のために (見つけるのは簡単ではないため)、STM32 のフラッシュ セクタのリストは、フラッシュ プログラミング マニュアルの 7 ページにあります。

于 2015-07-10T12:26:39.673 に答える