MIMXRT1180-EVK LittleFS サンプルは、DCache が無効になっていない限り、外部フラッシュで失敗します。こんにちは、
Zephyr LittleFS サンプル ( https://github.com/zephyrproject-rtos/zephyr/tree/main/samples/subsys/fs/littlefs ) を実行しようとしています。CM33コアを使用して外部フラッシュ(W25Q128JWSIQ)に書き込んでいますが、問題が発生しています。
サンプルをデフォルト設定で実行しようとすると、約90%の確率で失敗します。フラッシュメモリを消去してファイルシステムを再構築するオプションをオンにすると、ほぼ毎回失敗するようです。
失敗するタイミングは様々ですが、ログは通常次のような内容になります。
ネタバレ*** Zephyr OSビルドv4.3.0-6239-g28cd602a81eaを起動しています***
littlefs上のファイルを読み書きするためのサンプルプログラム
w25q128jw@0 の 0xe20000 にある領域 3、1966080 バイト
[00:00:00.022,000] main: フラッシュ領域を消去しています... 0
[00:00:00.028,000] littlefs: LittleFS バージョン 2.11、ディスクバージョン 2.1
[00:00:00.037,000] littlefs: w25q128jw@0:0xe20000 の FS は 480 個の 0x1000 バイトのブロックで、512 サイクルです
[00:00:00.047,000] littlefs: パーティションサイズ: rd 16 ; pr 16 ; ca 64 ; la 32
[00:00:00.055,000] littlefs: WEST_TOPDIR/modules/fs/littlefs/lfs.c:1386:{0x0, 0x1} のディレクトリペアが破損しています
[00:00:00.066,000]littlefs: マウントできません (LFS -84);
フォーマット[00:00:00.118,000] littlefs: /lfs がマウントされました
/lfs マウント: 0
/lfs: bsize = 16 ; frsize = 4096 ; blocks = 480 ; bfree = 478
ディレクトリ /lfs を一覧表示しています...
[00:00:00.150,000] littlefs: WEST_TOPDIR/modules/fs/littlefs/lfs.c:2109:スーパーブロック0x0は書き込み不能になりました
[00:00:00.161,000] fs: ファイルオープンエラー (-5)
[00:00:00.167,000] main: 失敗: /lfs/boot_count を開けません: -5
[00:00:00.174,000] littlefs: /lfs がマウントされていません
/lfs アンマウント: 0
ある時点で「スーパーブロック0x0が書き込み不能になりました」というエラーが発生し、サンプルが失敗します。
Kconfigオプション「CONFIG_DCACHE=n」でDCacheを無効にするとサンプルが確実に動作することがわかったので、これはキャッシュの問題だと考えています。
ネタバレ*** Zephyr OSビルドv4.3.0-6239-g28cd602a81eaを起動しています***
littlefs上のファイルを読み書きするためのサンプルプログラム
w25q128jw@0 の 0xe20000 にある領域 3、1966080 バイト
[00:00:00.060,000] main: フラッシュ領域を消去しています... 0
[00:00:00.069,000] littlefs: LittleFS バージョン 2.11、ディスクバージョン 2.1
[00:00:00.127,000] littlefs: w25q128jw@0:0xe20000 の FS は 480 個の 0x1000 バイトのブロックで、512 サイクルです
[00:00:00.139,000] littlefs: パーティションサイズ: rd 16 ; pr 16 ; ca 64 ; la 32
[00:00:00.151,000] littlefs: WEST_TOPDIR/modules/fs/littlefs/lfs.c:1386:{0x0, 0x1} のディレクトリペアが破損しています
[00:00:00.164,000]littlefs: マウントできません (LFS -84);
フォーマット[00:00:00.235,000] littlefs: /lfs がマウントされました
/lfs マウント: 0
/lfs: bsize = 16 ; frsize = 4096 ; blocks = 480 ; bfree = 478
ディレクトリ /lfs を一覧表示しています...
/lfs/boot_count 読み取り回数:0 (バイト数: 0)
/lfs/boot_count に新しいブートカウント 1 を書き込みます: [wr:1]
[00:00:00.297,000] main: テストファイル: /lfs/pattern.bin が見つかりません。作成してください。
------ ファイル: /lfs/pattern.bin ------
01 55 55 55 55 55 55 55 02 55 55 55 55 55 55 55
03 55 55 55 55 55 55 55 04 55 55 55 55 55 55 55
05 55 55 55 55 55 55 55 06 55 55 55 55 55 55 55
07 55 55 55 55 55 55 55 08 55 55 55 55 55 55 55
09 55 55 55 55 55 55 55 0a 55 55 55 55 55 55 55
0b 55 55 55 55 55 55 55 0c 55 55 55 55 55 55 55
0d 55 55 55 55 55 55 55 0e 55 55 55 55 55 55 55
0/55 55 55 55 55 55 55 10 55 55 55 55 55 55 55
11 55 55 55 55 55 55 55 12 55 55 55 55 55 55 55
13 55 55 55 55 55 55 55 14 55 55 55 55 55 55 55
15 55 55 55 55 55 55 55 16 55 55 55 55 55 55 55
17 55 55 55 55 55 55 55 18 55 55 55 55 55 55 55
19 55 55 55 55 55 55 55 1a 55 55 55 55 55 55 55
1b 55 55 55 55 55 55 55 1c 55 55 55 55 55 55 55
1d 55 55 55 55 55 55 55 1e 55 55 55 55 55 55 55
1f 55 55 55 55 55 55 55 20 55 55 55 55 55 55 55
21 55 55 55 55 55 55 55 22 55 55 55 55 55 55 55
23 55 55 55 55 55 55 55 24 55 55 55 55 55 55 55
25 55 55 55 55 55 55 55 26 55 55 55 55 55 55 55
27 55 55 55 55 55 55 55 28 55 55 55 55 55 55 55
29 55 55 55 55 55 55 55 2a 55 55 55 55 55 55 55
2b 55 55 55 55 55 55 55 2c 55 55 55 55 55 55 55
2d 55 55 55 55 55 55 55 2e 55 55 55 55 55 55 55
2f 55 55 55 55 55 55 55 30 55 55 55 55 55 55 55
31 55 55 55 55 55 55 55 32 55 55 55 55 55 55 55
33 55 55 55 55 55 55 55 34 55 55 55 55 55 55 55
35 55 55 55 55 55 55 55 36 55 55 55 55 55 55 55
37 55 55 55 55 55 55 55 38 55 55 55 55 55 55 55
39 55 55 55 55 55 55 55 3a 55 55 55 55 55 55 55
3b 55 55 55 55 55 55 55 3c 55 55 55 55 55 55 55
3d 55 55 55 55 55 55 55 3e 55 55 55 55 55 55 55
3f 55 55 55 55 55 55 55 40 55 55 55 55 55 55 55
41 55 55 55 55 55 55 55 42 55 55 55 55 55 55 55
43 55 55 55 55 55 55 55 44 55 55 55 55 55 55 55
45 55 aa
[00:00:00.659,000] littlefs: /lfs がマウントされていません
/lfs アンマウント: 0
しかし、DCache を有効にしたまま、フラッシュの変更 (書き込みと消去、ドライバレベルではなくサンプルレベル) のたびに "sys_cache_data_flush_and_invd_all()" を使用して DCache をフラッシュおよび無効化し、割り込みを "irq_lock()" でロックしても、やはり動作しません。
DCacheを無効にすることは一時的な回避策としては有効ですが、本番システムには理想的ではありません。動作させるために何か見落としている点があるのでしょうか?
MCUXpresso SDKに付属しているフラッシュメモリにアクセスするサンプルは正常に動作するため、おそらくZephyrまたはその設定に問題があると考えられます。
フラッシュにアクセスする他のZephyrサンプルでも同様の挙動が見られ、DCacheを無効にした場合のみ安定したアクセスが可能になりますが、それらについては徹底的なテストは行っていません。
技術情報:
ボード:NXP MIMXRT1180-EVK(CM33コア)をマイクロUSB経由でWindows PCからパススルーしてUbuntu VMに接続
OS: Zephyr v4.3.0-6239-g28cd602a81ea
IDE: Ubuntu上のVS Code用MCUXpresso 26.3.72(Zephyr開発者ソフトウェアキット4.3付き)
プロジェクトKconfig:
ネタバレ#
# 著作権 (c) 2019 Peter Bigot Consulting, LLC
#
# SPDX-License-Identifier: Apache-2.0
#
# オプションでファイルシステムの再作成を強制する
CONFIG_APP_WIPE_STORAGE=y
CONFIG_DEBUG=y
CONFIG_NO_OPTIMIZATIONS=y
CONFIG_LOG=y
CONFIG_PRINTK=y
CONFIG_SHELL=y
CONFIG_LOG_DEFAULT_LEVEL=3
CONFIG_LOG_BACKEND_UART=y
CONFIG_LOG_MODE_IMMEDIATE=y
CONFIG_UART_CONSOLE=y
CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_LITTLEFS=y
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
# フラッシュメモリを確実に動作させるために必要な回避策
CONFIG_DCACHE=n
どんなご協力でもありがたいです。
よろしくお願いします、
ジェイソン
Re: MIMXRT1180-EVK LittleFS sample fails on external flash unless DCache is disabledこんにちは、エドウィンさん。
この問題解決にご協力いただきありがとうございます。しかし、ご提案いただいた解決策がよく理解できません。同じ例はFreeRTOSでも動作し、LWIPスタックやミドルウェアは一切関与していません。Zephyrでは動作せず、FreeRTOSでは動作する、単純なLittleFSフラッシュの読み書きの例です。
重要なバッファデータはキャッシュ不可能なメモリに格納する必要があることは理解していますが、Zephyrが提供するもの以外に、そのようなサブシステムやソフトウェアは存在しません。つまり、Zephyrドライバまたはサブシステム内で問題の原因となっている可能性のあるバッファを特定し、それらをキャッシュ不可能なメモリに移動させることを提案しているのですか?
どのバッファーがよくある原因なのか、ご説明いただき、ご経験を共有していただけると幸いです。
よろしくお願いいたします
トーマス
Re: MIMXRT1180-EVK LittleFS sample fails on external flash unless DCache is disabledこんにちは、 @JasonPD さん。
この問題の原因は間違いなくキャッシュ関連であり、具体的には、以下の記事で説明されている内容です。 「i.MXRT でキャッシュされていないメモリを使用する」
前述のとおり、この問題はLwIPのようなミドルウェアを使用している場合に最も顕著に現れ、Dキャッシュを完全に無効にするのではなく、重要なデータをキャッシュ不可能なメモリ領域に配置することで解決できます。
問題の本質をより深く理解するために、その投稿と参照されているアプリケーションノート( i.MXRT L1キャッシュの使用)を確認し、記事の推奨事項に従ってLwIPミドルウェアが正しく機能するようにしてください。
BR、
エドウィン。
Re: MIMXRT1180-EVK LittleFS sample fails on external flash unless DCache is disabledさらに調べて、フラッシュドライバ「flash_mcux_flexspi_nor.c」を見てみました。その中に、書き込みと消去後に現金が無効化される仕組みが定義ガードによって保護されているのを見つけました。
#ifdef CONFIG_HAS_MCUX_CACHE
現在当社が独占的に使用しているCM33の場合、KConfファイルには次のように記載されています。
config SOC_MIMXRT1189_CM33
HAS_MCUX_XCACHE を選択してください
CM7の場合は次のようになります。
config SOC_MIMXRT1189_CM7
HAS_MCUX_CACHE を選択します。
フラッシュドライバの定義ガードを次のように調整しました。
#if defined(CONFIG_HAS_MCUX_CACHE) || defined(CONFIG_HAS_MCUX_XCACHE)
この変更により、フラッシュメモリへの書き込みと消去がエラーなく行えるようになりました。XIPとDCacheを再度有効にし、すべてのIRQ無効化を解除しました。今のところはうまくいっているようです。
NXPの視点から見て、この解決策は理にかなっているかどうか、ご意見をいただけますか?フラッシュメモリにアクセスする際、依然としてIRQを無効にする必要がありますか?
よろしくお願いいたします
トーマス