RL78マイコンの開発をMac版e2studioでやってみる！

## 背景
私は組み込みマイコンの開発をMacでやっています。
主にSTマイクロ、NXPで、これらの開発環境にはeclipseが使われています。
eclipseが使われる利点は、MacでもWindowsと同じように開発できることです。

長年、ルネサスのマイコンはWindowsでしか開発ができませんでした。
しかし、やっと**eclipseを利用したMac版e2studioがリリースされました！**

そこで、RL78の開発をMac版e2studioでやろうと意気込んでいたのですが、**周辺機能の設定をGUIでやる機能が提供されていません!**

私も年齢的には古い人間なので(笑)、そういう設定はマニュアルを調べて、ソースコードで記述するもんだと言いたいところですが、STマイクロやNXPのGUIによる周辺機能の設定を体験すると、もう戻れません...

## 方針
Windows版e2studioには、GUIによる周辺機能の設定が提供されています。
ただし**CC-RLでの開発に限定**されます。

そこで、最初の周辺機能の設定はWindows版e2studioに任せるしかありません。
出力されたソースコードをMac版e2studioに持っていくことを考えます。

そこで、方針としては
* Windows版e2studioでCC-RLのC言語プロジェクトを作る
* 周辺機能の設定をGUIでやる
* 周辺機能設定のソースコードを生成する
* Mac版e2studioでLLVMのC言語プロジェクトを作る
* Windows版e2studioのソースコードをMac版e2studioのプロジェクトにコピーする
* LLVM開発に合わせた修正を行う
* メインアプリケーションのプログラム開発をする

という感じになります。
アセンブラにも少しだけ踏み込んで、起動プロセスなども確認してみます。

## Windows版e2studioでプロジェクトを作る
### 新規Cプロジェクト
![スクリーンショット 2025-03-28 9.12.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/ba89e389-3e6a-4ebb-b7a7-069372f125fa.png)
```Renesas CC-RL C/C++ Executable Project```を選びます。
プロジェクト名を決めて、ターゲットデバイスなどの設定に移ります。

今手掛けている開発のマイコンはRL78/G10で、ターゲット・デバイスは```R5F10Y16```です。秋月電子で入手できます。
ちなみに、Hardware Debugの構成を生成のポップアップですが、
WindowsではE1も選択肢に現れますが、MacではE2/E2 Liteしかサポートしてません。

![スクリーンショット 2025-03-28 9.22.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/ce574af1-e326-4613-91db-3314867d7bc3.png)


次に進んだら、```Use 周辺コード生成```にチェックを入れます。
これをチェックすることで、GUIによる周辺機能の設定ができます。
![スクリーンショット 2025-03-28 9.26.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/5d76ed76-0543-4653-a573-f844a0edc326.png)

このように、古いルネサスの開発環境で利用していたGUI設定が使えます。
ここで周辺機能の設定をし、C言語のソースコードを生成します。

![スクリーンショット 2025-03-28 9.30.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/c1af0c0a-56b7-456c-9776-1d8d799b4c4b.png)

```コードを生成する```ボタンをクリックすると、cg_srcフォルダの中に周辺機能の設定を記述したソースコードが生成されます。
このソースコードを、Mac版e2studioでうまく利用します。

![スクリーンショット 2025-03-28 9.37.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/8cc59f55-87b3-4556-a13d-7ead126f81d1.png)

## Mac版e2studioでプロジェクトを作る

![スクリーンショット 2025-03-28 9.44.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/b16011b2-f068-4c81-a2c8-496cea61db71.png)

```LLVM for Renesas RL78 C/C++ Executable Project```を選びます。
Windows版e2studioと同じように、プロジェクト名を決めて、ターゲットデバイスなどの設定に移ります。
先ほど記載した通り、デバッガはE2/E2 Liteしか選択肢がありません。

![スクリーンショット 2025-03-28 9.48.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/faa7fb7d-3236-4c8d-b0e2-871a73057039.png)

この後、適宜設定をしてプロジェクトを作成します。
基本的には何も変更せず、次々進んでいけばいいです。

このように、最低限のソースコードが作成されます。
割り込み処理の入り口なども用意されていますね。

![スクリーンショット 2025-03-28 9.50.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/2055fa5a-8443-4dab-bc8c-45e26199a79e.png)

## CC-RLでの起動の流れ
アセンブラ```generate/cstart.asm```の中を見てみます。
76行で```hdwinit```をコールしています。

![スクリーンショット 2025-03-28 10.00.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/74cac808-e137-436d-99da-a07228ada738.png)

```hdwinit```は```src/cg_src/r_cg_systeminit.c```の中に記述されています。
さらにその中で```R_Systeminit()```がコールされ、その中でクロック、I/Oポート、タイマーの設定がされています。

![スクリーンショット 2025-03-28 10.04.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/fb3e4404-593b-4255-98c6-4e009a8da620.png)

アセンブラにもどり、メモリの0フィルや初期値代入を経て、199行で```main()```をコールしています。

![スクリーンショット 2025-03-28 10.08.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/8d476cb8-0062-4b5f-91fb-99cce2a62ce9.png)

main()ではまず```R_MAIN_UserInit()```がコールされ、この中でユーザーが必要とする初期設定をする感じです。
main()で無限ループへ入るまでをシンプルにしたいという意図でしょうね。

![スクリーンショット 2025-03-28 10.20.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/00b4ef50-cc6e-4f42-8429-43dd864638fd.png)


## LLVMでの起動の流れ
アセンブラ```start.S```の中を見てみます。
153行で```HardwareSetup```をコールしています。

![スクリーンショット 2025-03-28 10.15.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/37f10076-2abf-4c55-b75e-d48940bce181.png)

```HardwareSetup```は```generate/hwinit.c```の中に記述されています。
中身は空っぽです。
![スクリーンショット 2025-03-28 10.16.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/be680b93-f6c8-4643-9bc3-2c38173db7e2.png)

そして、```main()```は161行でコールされています。
![スクリーンショット 2025-03-28 10.17.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/d3644bb1-7892-48af-8f16-d4ef6c125a99.png)

main()は空っぽで、無限ループのみ用意されています。

![スクリーンショット 2025-03-28 10.24.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/c31f3a96-25f9-41cb-b340-9d64f462f246.png)

見た感じでは、CC-RLとLLVMの流れは変わりません。
CC-RLの```hdwinit```と```R_MAIN_UserInit```内でやっている処理をLLVMの```HardwareSetup```でやれば良さそうです。

では、移植作業をやってみましょう。

## 移植作業
### CC-RLのcg_srcフォルダをMac版e2studioにコピーする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/099c961b-2750-429f-8473-907aff43dcde.png)

中身はC言語なので、互換性は問題ありません。
ヘッダの定義に差があるため、また、CC-RLでのmainループも含まれているため、コンパイルするとエラーが出ます。

![スクリーンショット 2025-03-28 10.44.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/2a96c491-3f68-4852-b87d-b8d46ddfc867.png)

### ヘッダ定義エラーの解消
r_cg_port.cのエラーを見てみます。

![スクリーンショット 2025-03-28 10.46.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/56ddba43-80e8-4939-8ddc-9291fc41dd17.png)

PMC0の定義がないためエラーになっています。
これはヘッダ内の定義の違いによって発生しています。
今回は、CC-RLで生成したハードウェア情報を利用するため、レジスタのアドレスマッピングなどはCC-RLのものに置き換えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/a1cf1a89-079e-4e5a-bedd-efa454598fc9.png)

Windows版e2studioの```generate/iodefine.h```の中身をクリップボードにコピーします。
Mac版e2studioのIntrinsic Functionの定義は念のため残しておき、それ以降をクリップボードのWindows版e2studio```generate/iodefine.h```で置き換えます。

定義に関するエラーは消え、残るエラーは1つになりました。

![スクリーンショット 2025-03-28 10.57.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/101dfd6c-585d-44ab-b3be-a7b785a94de3.png)

### main重複の解消
最後の一つのエラーはmainが二つあるためです。
Windows版e2studioからコピーしてきた```cg_src/r_cg_main.c```が原因です。

![スクリーンショット 2025-03-28 11.01.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/0c93ef6d-9fc5-44a4-9351-10e7a413150a.png)

中を見てみると、ヘッダのインクルードと無限ループ前の初期化の定義があります。
処理としては実質空っぽなので、なくなっても大丈夫です。
```cg_src/r_cg_main.c```をMac版e2studioのプロジェクトから削除しましょう。

![スクリーンショット 2025-03-28 11.03.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/1f4628c9-3d60-4c0b-bfd7-a4acf7ab3216.png)

これでコンパイルは通りました！

### Warningの解消
放っておいてもいいかなぁとは思います。
Warningの内容を確認してみます。

![スクリーンショット 2025-03-28 11.05.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/9681059d-6889-45ca-8935-d971ecaa6aaf.png)

```c:cg_src/r_cg_cgc_user.c
uint8_t reset_flag = RESF;
```
定義したけど使ってないということですね。
リセット要因を調べる処理ですが、必要ないなら削除すればいいと思います。
将来使うかもしれないから、取っておきたい気もします。
対処はその日の気分で(笑)

![スクリーンショット 2025-03-28 11.05.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/82ffb49d-a751-46cb-9c17-56f5be63c100.png)

```c:cg_src/r_cg_tau_user.c
#pragma interrupt r_tau0_channel0_interrupt(vect=INTTM00)
static void __near r_tau0_channel0_interrupt(void)
```
CC-RLでの#pragma定義、実際の割り込み処理の定義がLLVMでは使えないということです。
割り込み処理ベクタ番号の情報なども付記されているので、このまま残しておきましょう。

最後に、重複定義になっている```r_cg_macrodriver.h```の一部をコメントアウトします。
```c:cg_src/r_cg_macrodriver.h
//#define DI      __DI
//#define EI      __EI
//#define HALT    __halt
//#define NOP     __nop
//#define STOP    __stop
```
LLVMでの定義を利用するので、CC-RLの定義はコメントアウト、または削除します。
### ハードウェアのセットアップ
```generate/hwinit.c```にハードウェアの設定を記述します。
ハードウェアの設定はCC-RLで生成された```xxx_Create()```を利用します。
そのために必要なヘッダファイルをインクルードします。
```c:generate/hwinit.c(1)
/************************************************************************/
/*    File Version: V1.00                                               */
/*    Date Generated: 10/09/2013                                        */
/************************************************************************/

#ifdef __cplusplus
extern "C" {
#endif
extern void HardwareSetup(void);
#ifdef __cplusplus
}
#endif

#include "iodefine.h"
#include "r_cg_macrodriver.h"
#include "r_cg_cgc.h"
#include "r_cg_port.h"
#include "r_cg_tau.h"
#include "r_cg_intp.h"
#include "r_cg_userdefine.h"
```

アセンブラからコールされる```HardwareSetup```の中身を書きます。
必要なハードウェアの```Create()```関数をCC-RLの```r_cg_systeminit.c```から探して記述します。

```c:generate/hwinit.c(2)
void HardwareSetup(void)
{
    DI();
    PIOR = 0x05U;
    R_CGC_Get_ResetSource();
    R_PORT_Create();
    R_CGC_Create();
    R_TAU0_Create();
    R_INTC_Create();
}
```
### オプション・バイト
RL78マイコンは、起動時に

* ウォッチドッグタイマの設定
* 電圧検出設定
* リセット端子の設定
* 高速オンチップ・オシレータの周波数設定
* オンチップ・デバッグのオプション

をROMから読み出します。
CC-RLではハードウェアのGUIで設定すると、オプションバイトの値が生成されます。
そして、ROMの書き込みファイルにオプションバイトが配置されます。

LLVMの場合は、generate/vects.cの中にオプションバイトを記述します。
すでに初期値が用意されていますので、適宜書き換えます。
```Option_Bytes[]```が```option_bytes```セクションに配置されます。
```c:generate/vects.c
const unsigned char Option_Bytes[]  __attribute__ ((section (".option_bytes"))) = {
		0xef, 0xff, 0xe8, 0x85
};

```



### 割り込み処理
```generate/inthandler.c```に割り込み処理の関数が用意されています。
中身は空っぽです。
関数の名前は割り込み処理の内容がわかるように付けられています。
また、ベクタアドレスがコメントで書かれているので、```iodefine.h```の記述と見比べて探すこともできます。

### main
ヘッダを適切にインクルードし、CC-RLの```R_MAIN_UserInit()```でやっていた処理を無限ループの前に記載すればいいでしょう。
R_MAIN_UserInit()と同じような関数を作って、無限ループの前にコールする方法でもいいでしょう。
通常は```EI()```だけが記載されています。
個人的には、なんちゃってオブジェクト指向の自作フレームワークを組み込んでいるので、その初期化とかをここでやってます。

```c:r_cg_main.c
/***********************************************************************************************************************
* Function Name: R_MAIN_UserInit
* Description  : This function adds user code before implementing main function.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
static void R_MAIN_UserInit(void)
{
    /* Start user code. Do not edit comment generated here */
    EI();
    /* End user code. Do not edit comment generated here */
}
```

さぁ、これでアプリケーションは動作します！

コンパイルして、デバッグしてみます。

![スクリーンショット 2025-03-31 10.19.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202602/7d5350d5-fb27-44ed-be01-52d6810b33a9.png)

ちゃんと動きますね。
ブレークポイント、変数表示、レジスタ編集もWindows版と同じようにできます。

## 最後に
MacでもRL78の開発ができるようになりました。
これは私にとっては超効率アップです。
ただ、周辺機能の設定を楽にやりたい場合、現状はWondows版e2studio、あるいはCS+の併用は避けられません。
しかし、周辺機能の設定が最初にがっちり決まっていれば、これ以降はMacだけで開発できます。

今回の移植方法では、Windows版e2studio、CS+のCソースコードの修正は行わないので、途中で周辺機能を変更しても、ソースコードを入れ替えるだけでOKです。

Macで組み込み開発をされている方々の助けになれば幸いです。

## 参考情報
Mac版e2studioでRL78マイコンの開発をする際、統合開発環境のインストールについては、下記サイトが役に立ちます。

[e² studio クイックスタートガイド - macOS環境にe² studioとLLVM for RL78ツールチェーンをインストールする方法](https://www.renesas.com/ja/video/e-studio-quick-start-guide-install-e-studio-and-llvm-rl78-toolchain-macos)

上記だけではダメで、実はE2 / E2 Liteを使うためにはPythonのインストールが必要です。
リリースノートの7ページ目に注意書きがありました。
[e² studio 2025-01 Release Documentation ](https://www.renesas.com/ja/document/rln/e-studio-2025-01-release-note#page=7)
```
Note:
The GDB included in the e² studio installation for debugging has a requirement on Python 3.10.
This will need to be installed on your machine for the debugging to work correctly. 
If not installed the debugger will not launch.
```

Python 3.10 macOS版をダウンロード、インストールしなくてはいけません。
[こちら](https://www.python.org/ftp/python/3.10.11/python-3.10.11-macos11.pkg)からダウンロードできます。