本コラムでは、TOPPERS/ATK2(以下、ATK2)のマイコン依存部処理であるクロック初期化処理を、ルネサス製Mcuに置き換える事例を紹介します。また、PCとのシリアル通信処理で使用しているUART(RLIN3)のポート初期化処理もルネサス製Portに置き換えます。
ルネサス製MCALに関する基本情報や開発環境については「ルネサスエレクトロニクス社製MCALの使用方法」をご参照ください。
※本コラムは、ルネサスエレクトロニクス社の許可を得て公開しています。
クロック設定
HSBRH850F1K100には、16MHzの水晶振動子が搭載されています。ATK2のHSBRH850F1K100向けコードでは、初期化時に以下のクロック設定を行っています。
対象クロック | 周波数 | 備考 |
---|---|---|
MainOSC | 16MHz | 水晶振動子から供給 |
CPLLOUT | 120MHz | PLL出力 |
CPUCLK | 120MHz | CPLLOUTをそのまま使用 |
C_AWO_TAUJ(タイマ用) | 16MHz | MainOSCをそのまま使用 |
C_ISO_LIN(UART用) | 16MHz | MainOSCをそのまま使用 |
※対象クロックの名称/意味については「RH850/F1K ユーザーズマニュアル ハードウェア編」をご参照ください。
Mcuによるクロック設定の振舞いを確認するために、ATK2のソースコードから上記の初期化処理を削除もしくはコメントアウトする必要があります。具体的には、target_config.cに実装されている関数target_clock_initializeが該当します。同ファイルの関数target_hardware_initializeから、target_clock_initializeを呼び出している行を削除/コメントアウトすればOKです。
Mcu
コンフィギュレーション
McuのEcucDefsは、<インストールフォルダ>\X1X\F1x\modules\mcu\definition\4.2.2\F1K\R422_MCU_F1K.arxmlに定義されています。ルネサス製McuのEcucDefsでは、/AUTOSAR/EcucDefs/Mcu/McuModuleConfiguration/McuClockSettingConfigの下に、RH850/F1K向けのクロック設定を行うコンテナを独自に規定しています。RH850/F1Kのクロックコントローラ仕様を知っていれば、直感的に設定することが可能です。具体的に、前述のクロック設定を行うためのコンフィギュレーションをYAML形式(※1)で記載すると以下のようになります。(該当パラメータの抜粋となります)Mcu: McuModuleConfiguration: McuClockSettingConfig: McuClockSettingId: 0 McuClkModeSelect: MCU_CPLLCLK_ID_3 # CPUCLKにCPLLOUTを選択 McuCpuClockDivider: DIVBY_1_ID_1 # CPLLOUTを分周しない McuCpuMainSysClk: 120000000 # CPUCLK:120MHz McuMainOscSetting: McuMainOscAmplificationGain: LOW_ID_2 # MainOSC:16MHz McuMainOsciFrequency: 16000000 # MainOSC:16MHz McuPllSetting: McuCpllDivider: P_VALUE_4 # CPLLOUT:120MHz McuCpllClk: 120000000 # CPLLOUT:120MHz McuPllInputClockSelection: MCU_SELECT_MOSC # PLLCLKINにMainOSCを選択 McuPllMrValue: 2 # PLLC.M(Mr):2 McuPllNrValue: 60 # PLLC.N(Nr):60 McuAwoTauj: McuSrcClockSel: FX_ID_2 # C_AWO_TAUJにMainOSCを選択 McuDivClockSel: DIVBY_1_ID_1 # MainOSCを分周しない McuPeripheralClock: 16000000 # C_AWO_TAUJ:16MHz McuIsoLin: McuSrcClockSel: FX_ID_2 # C_ISO_LINにMainOSCを選択 McuPeripheralClock: 16000000 # C_ISO_LIN:16MHz McuIsoLin3: McuDivClockSel: DIVBY_1_ID_1 # MainOSCを分周しない McuPeripheralClock: 16000000 # RLIN3への供給クロック:16MHz※1 YAML形式によるEcucValsの表記については「ABREXの使い方」をご参照ください。
ジェネレータ実行
Port同様、Mcuのジェネレータ実行時も、入力情報として以下の4つが必要となります。※入力情報の詳細な説明はPortの説明をご参照ください。
- [1] ECU Configuration Description File
- Mcu向けのEcucValsを指定します。
- 複数モジュール向けのEcucValsを1つのarxmlで定義しても問題ありません。
- [2] Translation XML File
- ジェネレータを実行するフォルダからの相対パスが同じであれば、Portのジェネレータで使用したものと同じファイルを使用できます。
- [3] BSWMDT File
- Mcu用のBSWMDT Fileは、以下に用意されています。
- <インストールフォルダ>\X1X\F1x\modules\mcu\generator\R422_MCU_F1x_BSWMDT.arxml
- Mcu用のBSWMDT Fileは、以下に用意されています。
- Port同様、省略可能です。
実装
クロックを設定するのみであれば、Mcuは初期化処理を行うのみとなります。ただし、Mcu_Init以外にも初期化処理が必要となるので注意が必要です。まず、Mcu_Initの引数は、ハードウェアやMCAL実装に依存して定義される構造体型であるMcu_ConfigTypeへのポインタとなります。ルネサス製MCALでは、ジェネレータで生成したMcu_PBcfg.cに対象の構造体が生成されます。また、Mcu_Cfg.hに以下のマクロが定義されますので、こちらをMcu_Initの引数として使用することができます。
/* Configuration Set Handles */ #define McuModuleConfiguration (&Mcu_GstConfiguration[0])
そして、Mcu_InitClockによりクロックの初期化を行い、今回はPLLを使用するのでMcu_DistributePllClockによりPLLからのクロック供給を有効にします。具体的には、以下のようなコードとなります。
#include "Mcu.h" : sint32 main(void) { : /* Mcu初期化 */ Mcu_Init(McuModuleConfiguration); /* クロック初期化 */ (void) Mcu_InitClock(McuConf_McuClockSettingConfig_McuClockSettingConfig); /* PLL起動 */ while (Mcu_GetPllStatus() != MCU_PLL_LOCKED); (void) Mcu_DistributePllClock(); : }
Mcu_InitClockの引数は、McuClockSettingIdで設定したクロック設定の識別子です。McuClockSettingConfigコンテナは、複数設定することができますので、複数のクロック設定を用意しておき、Mcu_InitClock呼出し時にどのクロック設定とするか選択できるわけです。なお、McuClockSettingIdには、SymbolicNameValue属性が付いていますので、上記のように引数をマクロで指定することも可能です。Dioの識別子用パラメータとは異なり、McuClockSettingIdは0からの連番でしか設定不可となっているため、設定値を直接書いても問題ありません。クロック初期化後、Mcu_GetPllStatusによりPLLがロックされるのを待ちます。PLLがロックされたことを確認した上で、Mcu_DistributePllClockにより、PLLからのクロック供給を有効にします。
上記例では、Mcu_InitClockとMcu_DistributePllClockの返り値を読み捨てていますが、何らかのエラーが発生することを考慮する場合は、返り値に応じた処理が必要となります。
なお、Mcuのソースコードには、アセンブリ言語で実装されたMcu_RRamCopy_asm.850が存在しますが、これは次バージョンで削除されるとのことです。現バージョンにおいても、Mcu_RRamCopy_asm.850をリンクしなくてもビルドは可能で、クロックの初期化も問題ありませんでした。
Port
ルネサス製Portの使用方法については、既に「ルネサス製MCALのPortとDioを使ってみた」で説明していますので、ここではATK2で行っているUART(RLIN3)のポート初期化処理に対応するコンフィギュレーションについてのみ説明します。
HSBRH850F1K100では、ポートP10_11、P10_12に、USBシリアル変換ICのRXD、TXDが接続されています。RH850/F1Kのマニュアル(右図)に書かれているように、P10_11、P10_12は、第2兼用モードとすることで、RLIN31RX、RLIN31TXとして使用することができます。このコンフィギュレーションをYAML形式(※2)で記載すると以下のようになります。(該当パラメータの抜粋となります)
Port: PortConfigSet: PortGroup10: PortPin11: PortPinDirection: PORT_PIN_IN # 入力モード PortPinInitialMode: RLIN31RX_AT2IN # 第2兼用モード(RLIN31RX) PortInputBufferControl: true # 入力バッファ許可 PortPin12: PortPinDirection: PORT_PIN_OUT # 出力モード PortPinInitialMode: RLIN31TX_AT2OUT_PFC_PFCE_PMCSR # 第2兼用モード(RLIN31TX) PortInputBufferControl: false # 入力バッファ禁止※2 YAML形式によるEcucValsの表記については「ABREXの使い方」をご参照ください。
HSBRH850F1K100向けコードでは、上記のポートの初期化処理が含まれてしまっているので、Portによるポート設定の振舞いを確認するために、ATK2を使用する場合は削除もしくはコメントアウトする必要があります。具体的には、target_config.cに実装されている関数target_port_initializeの後半の処理(PFC10/PMC10/PM10/PIBC10の設定)が該当します。 なお、ルネサス製Linでは、RLIN3をUARTモードで使用するための設定はできないようです。ですので、RLIN3の初期化処理はATK2のマイコン依存部処理をそのまま使用しました。
動作確認
ルネサス製Mcu、Portを用いて初期化を行い、ATK2付属のサンプルプログラム(sample1)を使って動作確認を行いました。以下の通り、UARTによるシリアル通信ができていること(ボーレート等の設定が合っていること)、TAUJを使用したアラームの1秒周期(16MHz)が実時間で1秒となっていることを確認できました。