データフラッシュ関係更新
今まで、RX72Nなどで、データフラッシュに対するアクセスが正しく動作していなかった。
原因が判らず、放置してあったが、思い出したように取り組んでみた。
device::FLASH::FENTRYR = 0xAA80;
if(device::FLASH::FENTRYR() == 0x0080) {
mode_ = mode::PE;
return true;
} else {
debug_format("FACI 'P/E' not ready: 'turn_pe_'\n");
return false;
}
上記の部分で、Program/Erase モードに移行しない状況となっていた・・
※ハードウェアーマニュアルでは、0xAA80 を書き込んで、0x0080 が読める事を確認する事になっている。
クロック設定や、シーケンサに設定するクロックなど確認したが問題無かった。
※RX72N には、「データフラッシュメモリアクセス周波数設定レジスタ (EEPFCLK)」があり、注意書きとして、
FCLK の周波数を変更する場合、以下の手順に従い、変更前後で遅い方の周波数で動作している状態で
データフラッシュメモリアクセス周波数設定レジスタ (EEPFCLK) を変更してください。
なので、system_io クラス内の FCLK 設定クラス内に移動した。
又、「フラッシュシーケンサ処理クロック周波数通知レジスタ (FPCKAR)」があり(RX64、RX71、RX72 共通)
起動時に設定している。
色々デバッグする過程で、直ぐに読み出すと正しく読めないような状況だと判った。
そこで、とりあえず、10 マイクロ秒の遅延を間に入れた。
static constexpr uint32_t MODE_CHANGE_DELAY = 10; ///< モード変更における遅延
device::FLASH::FENTRYR = 0xAA80;
utils::delay::micro_second(MODE_CHANGE_DELAY);
if(device::FLASH::FENTRYR() == 0x0080) {
mode_ = mode::PE;
return true;
} else {
debug_format("FACI 'P/E' not ready: 'turn_pe_'\n");
return false;
}
これで正しく動作する事が判った。
※ハードウェアーマニュアルを良く調べたが、この「遅延」に関する記述は見つけられなかった・・・
その他:
- 「イレースチェック」コマンドを追加。
- バンク指定の不具合修正。
- メッセージの見直しなど色々追加した。
RX24T のデータフラッシュでは、1バイト単位で書き込めるが、RX6x 系では、4 バイト単位での書き込みとなっており、この辺りも管理を考え直す必要性がある。
また、RX64M にはあるが、RX72N には無いレジスタとか、細かい違い吸収するスマートな方法を考えないとならないと思っている。
※現状では、「#iddef」等で、分岐している。
対話形式のデータフラッシュ操作の様子
Flash drive clock: 60 [MHz]
Data Flash total size: 0x00008000
Data Flash block size: 64 bytes
Data Flash word size: 4 byte
FCLK base: 60 MHz
# ?
Data Flash Size: 32768, Bank: 512, Block: 64, Word: 4
erase [bank] (erase 0 to 512)
check [bank] (erase check 0 to 512)
r[ead] org [end] (read)
write org data... (write)
uid (unique ID list)
# check 5
Erase check: bank 5: 0x0140 to 0x017F NG
# erase 5
Erase OK: bank 5, 0x0140 to 0x017F
# write 140 aaa bbbb ccccc dddddd
# r 140 10
0x0140: 00000AAA 0000BBBB 000CCCCC 00DDDDDD
# check 6
Erase check: bank 6: 0x0180 to 0x01BF NG
# write 180 abcd
FACI 'write32_' write error: 0x0180
Write error: 0x0180: 0x0000ABCD
# erase 6
Erase OK: bank 6, 0x0180 to 0x01BF
# write 180 abcd
# r 180 10
0x0180: 0000ABCD 00000000 00000000 00000000
#
enum class を活用
組み込みのプログラミングでは、内部レジスタにマジックワードを書き込む事が多い。
仕様書には詳しく書いてあるものの、プログラムを観た場合に非常に判り難い。
最近、それを少しででも改善するような試みをしている。
今回、フラッシュの FACI シーケンサコマンドを「enum class」で定義して、専用のコマンドとした。
/// FACI シーケンサ・コマンド
enum class FACI : uint8_t {
WRITE_TOP = 0xE8, ///< プログラム(データフラッシュメモリ) 4バイトプログラム
WRITE_FIN = 0xD0, ///< プログラム(データフラッシュメモリ) 4バイトプログラム 最終コマンド
ERASE1 = 0x20, ///< 1st ブロックイレーズ (データフラッシュメモリ 64バイト)
ERASE2 = 0xD0, ///< 2nd ブロックイレーズ (データフラッシュメモリ 64バイト)
CLEAR_STATUS = 0x50, ///< ステータスクリア
BREAK = 0xB3, ///< 強制終了
CHECK_BLANK1 = 0x71, ///< 1st ブランクチェック
CHECK_BLANK2 = 0xD0, ///< 2nd ブランクチェック
};
inline void faci_cmd_(FACI cmd) const noexcept
{
FLASH::FACI_CMD_AREA = static_cast<uint8_t>(cmd);
}
inline void faci_cmd_(FACI cmd1, FACI cmd2) noexcept
{
FLASH::FACI_CMD_AREA = static_cast<uint8_t>(cmd1);
FLASH::FACI_CMD_AREA = static_cast<uint8_t>(cmd2);
}
※ FACI コマンドでは、コマンドによっては 2 バイト長もあるので、xxxx1、xxxx2 に別けてあるのが多少痛いのだけど・・・
faci_cmd_(FACI::WRITE_TOP);
FLASH::FACI_CMD_AREA = 0x02; // 書き込み数
...
faci_cmd_(FACI::WRITE_FIN);
faci_cmd_(FACI::CHECK_BLANK1, FACI::CHECK_BLANK2);
このような試みで、多少判りやすくなっていると思う。
まとめ
今回は、放置してあったデータフラッシュアクセスを何とか動作するようにしたが、何故「遅延」を入れる必要があるのか不明だ・・・
※RX64M、RX71M などでは、遅延は必要無い。
怪しいのは、動作速度を設定するレジスタ関係などだが、何回確認しても、問題無いと思える。
もしかしたら、順番があるのかもしれないが、それは試していない、現状、遅延を入れて動いているので、「良し」としている。