RXマイコン C++ フレームワークでデータフラッシュを読み書き

## RXマイコンのデータフラッシュ

RXマイコンには、データフラュシュメモリを搭載しているデバイスがあります。

- 比較的低価格で、コードメモリが少ないデバイスでは、搭載していません
- 通常、100,000 回の書き換えが可能で、電源を切ってもデータが保持されます
- 一般的な EEPROM と違って、独自の管理や操作を行う必要があります
- 搭載しているデータフラュシュメモリにはいくつかのグループ（３種類以上）があります
- 各グループで、微妙に操作や特性が異なります
- データフラュシュメモリの消去や書き込みには、一定の時間を要します
- 消去は、ブロック単位で行われ、ワード単位で書き込みを行う事が出来ます
- C++フレームワークでは、それらを一般化して、同じように扱えるよう工夫しています

|RXマイコン|データフラュシュ操作クラス|動作確認|
|---|---|:-:|
|[RX111](https://github.com/hirakuni45/RX/tree/master/RX110)|[RX24T/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX24T/flash_io.hpp?ts=4)||
|[RX113](https://github.com/hirakuni45/RX/tree/master/RX113)|[RX24T/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX24T/flash_io.hpp?ts=4)||
|[RX130](https://github.com/hirakuni45/RX/tree/master/RX130)|[RX24T/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX24T/flash_io.hpp?ts=4)||
|[RX140](https://github.com/hirakuni45/RX/tree/master/RX140)|[RX24T/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX24T/flash_io.hpp?ts=4)|〇|
|[RX220](https://github.com/hirakuni45/RX/tree/master/RX220)|[RX62x/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX62x/flash_io.hpp?ts=4)|〇|
|[RX231](https://github.com/hirakuni45/RX/tree/master/RX231)|[RX24T/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX24T/flash_io.hpp?ts=4)|〇|
|[RX24T](https://github.com/hirakuni45/RX/tree/master/RX24T)|[RX24T/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX24T/flash_io.hpp?ts=4)|〇|
|[RX261](https://github.com/hirakuni45/RX/tree/master/RX261)|[RX24T/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX24T/flash_io.hpp?ts=4)||
|[RX26T](https://github.com/hirakuni45/RX/tree/master/RX26T)|[RX62x/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX62x/flash_io.hpp?ts=4)|〇|
|[RX62N](https://github.com/hirakuni45/RX/tree/master/RX62x)|[RX62x/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX62x/flash_io.hpp?ts=4)|〇|
|[RX631](https://github.com/hirakuni45/RX/tree/master/RX63x)|[RX62x/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX62x/flash_io.hpp?ts=4)|〇|
|[RX63T](https://github.com/hirakuni45/RX/tree/master/RX63x)|[RX62x/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX62x/flash_io.hpp?ts=4)||
|[RX64M](https://github.com/hirakuni45/RX/tree/master/RX64M)|[RX600/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX600/flash_io.hpp?ts=4)|〇|
|[RX71M](https://github.com/hirakuni45/RX/tree/master/RX71M)|[RX600/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX600/flash_io.hpp?ts=4)|〇|
|[RX65N](https://github.com/hirakuni45/RX/tree/master/RX65x)|[RX600/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX600/flash_io.hpp?ts=4)|〇|
|[RX660](https://github.com/hirakuni45/RX/tree/master/RX660)|[RX600/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX600/flash_io.hpp?ts=4)||
|[RX66N](https://github.com/hirakuni45/RX/tree/master/RX66N)|[RX600/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX600/flash_io.hpp?ts=4)||
|[RX671](https://github.com/hirakuni45/RX/tree/master/RX671)|[RX600/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX600/flash_io.hpp?ts=4)||
|[RX72N](https://github.com/hirakuni45/RX/tree/master/RX72N)|[RX600/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX600/flash_io.hpp?ts=4)|〇|
|[RX72M](https://github.com/hirakuni45/RX/tree/master/RX72M)|[RX600/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX600/flash_io.hpp?ts=4)||
|[RX66T](https://github.com/hirakuni45/RX/tree/master/RX66T)|[RX600/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX600/flash_io.hpp?ts=4)|〇|
|[RX72T](https://github.com/hirakuni45/RX/tree/master/RX72T)|[RX600/flash_io.hpp](https://github.com/hirakuni45/RX/blob/master/RX600/flash_io.hpp?ts=4)|〇|

以下の表は、主なRXマイコンにおけるデータフラュシュメモリの性質などです。

|CPU|容量|バンクサイズ|書き込み単位|消去後の値|ユニーク ID 数 (32bits)|
|---|:--:|:-:|:-:|:-:|:-:|
|RX110|0K|-|-|-|4|
|RX111|8K|1024|1|0xFF|4|
|RX113|8K|1024|1|0xFF|4|
|RX130|8K|1024|1|0xFF|4|
|RX13T|0K|-|-|-|4|
|RX140|4K|256|1|0xFF|4|
|RX220|8K|128|2|0x??|4|
|RX23[01]|8K|1024|1|0xFF|4|
|RX23T|0K|-|-|-|4|
|RX24T|8K|1024|1|0xFF|4|
|RX26[01]|8K|256|1|0xFF|4|
|RX26T|16K|64|4|0x??|3|
|RX62[1N]|32K|2048|8|0x??|0|
|RX63[1N]|32K|2048|4|0x??|4|
|RX63T|8K|2048|4|0x??|4|
|RX64M|64K|64|4|0x??|3|
|RX71M|64K|64|4|0x??|3|
|RX65[1N]|32K|64|4|0x??|4|
|RX660|32K|64|4|0x??|4|
|RX66N|32K|64|4|0x??|4|
|RX671|8K|64|4|0x??|4|
|RX72N|32K|64|4|0x??|4|
|RX66T|32K|64|4|0x??|3|
|RX72T|32K|64|4|0x??|3|

- 大きく分けて、２つのグループがあります
- 消去後の値が「0xFF」又は「未定」の場合、２種別
- バンクサイズは、消去を行うブロックです
- 書き込み単位は、１バイト～８バイトまで、色々あります
- ユニークIDも、無い場合と、３～４ワードの場合があります
- ブロックを消去すれば、ワード単位で書き込みが出来ます
- １度書き込むと、ブロックを消去するまで書き換えが出来ません
- ブロック単位、ワード単位で、消去検査が出来ます

---

## flash_io クラスの使い方

flash_io クラスには、以下の API があります。

```C++
	/*!
		@brief	FCU を初期化して開始する
		@return 正常なら「true」
	 */
	bool start() noexcept;
```

```C++
	/*!
		@brief  読み出し
		@param[in]	org	開始アドレス
		@return データ
	*/
	uint8_t read(uint32_t org) noexcept;
```

```C++
	/*!
		@brief  読み出し
		@param[in]	org	開始アドレス
		@param[in]	len	バイト数
		@param[out]	dst	先
		@return 読出しサイズ
	*/
	uint32_t read(uint32_t org, uint32_t len, void* dst) noexcept;
```

```C++
	/*!
		@brief  消去チェック（ワード単位）
		@param[in]	adrs	アドレス
		@return エラーがあれば「false」
	*/
	bool erase_check_w(uint32_t adrs) noexcept;
```

```C++
	/*!
		@brief  消去チェック（バンク単位）
		@param[in]	bank	バンク
		@return エラーがあれば「false」
	*/
	bool erase_check(uint32_t bank) noexcept;
```

```C++
	/*!
		@brief  消去（バンク単位）
		@param[in]	bank	バンク
		@return エラーがあれば「false」
	*/
	bool erase(uint32_t bank) noexcept;
```

```C++
	/*!
		@brief  書き込み
		@param[in]	src ソース
		@param[in]	org	開始オフセット
		@param[in]	len	バイト数
		@return エラーがあれば「false」
	*/
	bool write(uint32_t org, const void* src, uint32_t len) noexcept;
```

```C++
	/*!
		@brief  エラー型
	*/
	enum class ERROR : uint8_t {
		NONE,		///< エラー無し
		START,		///< 開始不良
		CLOCK,		///< クロック設定不良
		NOS,		///< 未サポート
		ADDRESS,	///< アドレス不良
		LENGTH,		///< 長さ不良
		BANK,		///< バンク数不良
		TIMEOUT,	///< タイムアウト
		WRITE,		///< 書き込みエラー
		LOCK,		///< Lock エラー
		ST_ILGL,	///< ILGL ステータス検出
		ST_ERS,		///< ERS ステータス検出
		ST_PRG,		///< PRG ステータス検出
	};


	/*!
		@brief	最終エラー型を取得
		@return 最終エラー型
	 */
	auto get_last_error() const noexcept { return error_; }
```

```C++
	/*!
		@brief  ユニーク ID 数を取得 @n
				ユニーク ID をサポートしない場合は「０」が返る。
		@return ユニーク ID 数
	*/
	static uint32_t get_uid_num() noexcept;


	/*!
		@brief  ユニーク ID の取得 @n
				ユニーク ID をサポートしない場合、特定の ROM 領域を返す。 @n
				各マイコン「flash.hpp」を参照 
		@param[in]	idx		ID 番号（０～３）
		@return ID 値
	*/
	static uint32_t get_uid(uint32_t idx) noexcept;
```

- 「start()」関数を呼んで、各 API を呼べば、機能にアクセスできます
- シンプルな構造です
- 消去「erase」、書き込み「write」、消去検査「erase_check」では、一定の時間が必要で、ブロックされます

---

## サンプル・アプリケーション

上記 API を使った、[サンプルアプリケーション](https://github.com/hirakuni45/RX/tree/master/FLASH_sample)があります。
ターミナルとのシリアル接続で、対話形式で、データフラッシュメモリの操作が行えます。

- シリアルポートなど、ハードウェアー起因の設定は、各マイコンのルートディレクトリにある「board_profile.hpp」に定義があります
- 自分のシステムに合わせるには、このプロファイルを修正してコンパイルすれば良いかと思います

RX65N Envision Kit の [board_profile.hpp](https://github.com/hirakuni45/RX/blob/master/RX65x/board_profile.hpp?ts=4) (参考)：

```C++
	// 基板シグネチュア
	static const char system_str_[] = "RX65N Envision Kit";

	/// LED インジケーター
	static constexpr bool LED_ACTIVE = 0;
	typedef device::PORT<device::PORT7, device::bitpos::B0, LED_ACTIVE> LED;

	// SCI ポートの定義
	typedef device::SCI9 SCI_CH;
	static constexpr auto SCI_ORDER = device::port_map::ORDER::FIRST;
```

アプリケーションの動作：

RX62N の場合：

```sh
Start Data Flash sample for 'RX62N FRK-RX62N' 96 [MHz]
Flash drive clock: 48 [MHz]
Data Flash total size: 0x00008000
Data Flash block size: 2048 bytes
Data Flash word size: 8 byte
# check 2
Erase check: bank 2: 0x1000 to 0x17FF OK
# write 1000 123456789abcdef0 fa926534bcdea021
# r 1000 100f
0x1000: 123456789ABCDEF0 FA926534BCDEA021
# check 2
Erase check: bank 2: 0x1000 to 0x17FF NG
# erase 2
Erase OK: bank 2, 0x1000 to 0x17FF
# check 2
Erase check: bank 2: 0x1000 to 0x17FF OK
# r 1000 100f
0x1000: 1274567892BCDEF0 FA926514BCDEA021
```

RX24T の場合：

```sh
Start Data Flash sample for 'RX24T DIY' 80 [MHz]
Flash drive clock: 20 [MHz]
Data Flash total size: 0x00002000
Data Flash block size: 1024 bytes
Data Flash word size: 1 byte
# help
Data Flash Size: 8192, Block Num: 8, Block Size: 1024, Word: 1
erase [bank] (erase 0 to 7)
check [bank] (erase check 0 to 7)
checkw org (erase check word data)
r[ead] org [end] (read)
write org data... (write)
uid (unique ID list)
# check 0
Erase check: bank 0: 0x0000 to 0x03FF OK
# check 1
Erase check: bank 1: 0x0400 to 0x07FF OK
# r 400 40f
0x0400: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
# write 400 1 2 3 4 5 6 7 8 9 a b c d e f
# r 400 40f
0x0400: 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F FF
# checkw 410
Erase check word: 0x0410 OK
# write 410 a5
# r 410
0x0410: A5
# checkw 410
Erase check word: 0x0410 NG
# erase 1
Erase OK: bank 1, 0x0400 to 0x07FF
# r 400 41f
0x0400: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0x0410: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
```

RX64M の場合：

```sh
Start Data Flash sample for 'RX64M LFQFP 176 DIY' 120 [MHz]
Flash drive clock: 60 [MHz]
Data Flash total size: 0x00010000
Data Flash block size: 64 bytes
Data Flash word size: 4 byte
FCLK base: 60 MHz
# help
Data Flash Size: 65536, Block Num: 1024, Block Size: 64, Word: 4
erase [bank] (erase 0 to 1023)
check [bank] (erase check 0 to 1023)
checkw org (erase check word data)
r[ead] org [end] (read)
write org data... (write)
uid (unique ID list)
# check 10
Erase check: bank 10: 0x0280 to 0x02BF OK
# write 280 abcd 1234 ef01 5678
# r 280 28f
0x0280: 0000ABCD 00001234 0000EF01 00005678
# r 290 29f
0x0290: 00000480 00034400 00001008 00080000
# checkw 290
Erase check word: 0x0290 OK
# write 290 8901
# r 290
0x0290: 00008901
# checkw 290
Erase check word: 0x0290 NG
# write 294 abcdef01
# r 290 29f
0x0290: 00008901 ABCDEF01 08001008 00080000
# check 10
Erase check: bank 10: 0x0280 to 0x02BF NG
# check 9
Erase check: bank 9: 0x0240 to 0x027F OK
# check 11
Erase check: bank 11: 0x02C0 to 0x02FF OK
# erase 10
Erase OK: bank 10, 0x0280 to 0x02BF
# r 280 28f
0x0280: 9009EFCD C590F634 508AEF03 14025E78
```

---

## まとめ

- RXマイコンC++フレームワークの取得、アプリケーションのビルド方法などは、以下のリンクを参照して下さい
[gcc、g++を使ったルネサスＲＸマイコン開発](https://qiita.com/hira_kuni_45/items/a890e9ec613b88ca9a5f)
- RXマイコンC++フレームワークなど、ソースコード一式は、MIT ライセンスで公開しています
- データフラュシュに関する、詳細は、各RXマイコンのハードウェアーマニュアルを参照して下さい
- データフラュシュへの書き込み時間等に対する情報は、ハードウェアーマニュアルの電気的特性に載っています