目的
32ビットマイコン用のMCC Harmonyを使ってベアメタル環境でLチカを行い、基本的な開発環境の使い方とマイコンの動作を確認する
ハードウェア実装
PIC32MX210F016BはDIP基板なのでブレッドボードに実装しました。図1に回路図を示します。今回のマイコンは動作電圧が2.3 V~3.6 Vなので5 Vを加えると壊れるので注意してください。

Vcapにはコンデンサを、AVddとAVssにはVddとGNDを接続しておかないとプログラムの書き込みがうまくいきませんでした。またデータシート上ではコンデンサを置く推奨箇所があったり使わない端子の処理をする様に指示がありますが最低限VcapとAVdd、AVss、Vdd、Vssだけ接続しておけばとりあえず動作します。誤動作だったり外来ノイズに対して弱くなるのできちんとした設計(処理)をするに越したことは無いと思います。
また図のPICの端子は記載以外にもピンの割り当て可能な機能がいくつもあるので詳しくはデータシートを参照してください。今回は表記を省略しています。
MCCで基本設定
Harmonyの使い勝手がさっぱりわからなかったためまずは簡単にタイマー割り込みを使ったLチカを作って試してみました。
MCC Harmonyは32ビットマイコン用のコードコンフィグレータでアプリケーション層(ソフトウェア的な処理)、ドライバー層(I2CとかUARTの制御群)、ペリフェラル層(UART、I2C、タイマーとかのハードウェア)を連携させて開発しやすくする便利ツールです。(私個人の雑な理解です)
16ビットマイコンと同じ様に32ビットマイコン(今回はPIC32MX210F016B)でプロジェクトを作成して、MCCが開いたら、Device Resourceをクリックして図の様にTMR1を追加します。Harmonyのシステムサービスを利用して便利な?(慣れないとタイマー割り込みで直接動作させる方がわかりやすいと思うこととシステムサービスを使うためにもいろいろと苦戦したため)開発を試してみようと思います。


追加されたTMR1をクリックすると下図のようにペリフェラルのタイマー1が追加されます。次にSystemのTimeサービスも追加します。

そうすると下図の様にHarmony CoreとFreeRTOSを追加するかを順番に聞かれるのでCoreサービスはYesでFreeRTOSはNoを選択します。ちなみに余談ですが私の技量ではこのマイコンにFreeRTOSを組み込めませんでした。機能を削ってもコンパイラの最適化レベルを変更してもヒープメモリやスタックサイズを変えてビルドしてもスタックメモリが足りないかヒープメモリが足りないと怒られてうまくいきませんでした。このマイコンにはSRAMが4 kBあるのですがMCC Harmonyで提供されるFreeRTOSだと難しいのかもしれません。


次に追加されたTimeサービスのTMRにTMR1を接続します。ひし形のポートをドラッグすれば接続できます。その次にピン設定をするためにPluginsからPin Configurationをクリックします。

PinTable(図3)、PinDiagram(図4)、PinSettings(図5)の三つが開くと思います。Diagramで視覚的にピンを割り当てもできればPinTableでピンごとに割り当て可能な機能を見ながら決めていくこともできます。PinTableでパッケージを変えるとピンの割り当て可能な箇所が変わるようです。また入出力やプルアップ、プルダウンはPinSettingsのみでできる様です。今回は手順4に示すようにRA2にGPIOピンを割り当ててDirectionをOutにしています。




ピン設定からMCCのタブに切り替えてGenerateボタンを押します。そうすればMCCでコードが生成されます。

main.cやapp.cなどのプログラムを変更すると次回生成時にそのコードがそのまま出てきます。再利用可能なアプリケーションモジュールとして使っていくからそういった作りになっているのかなとは思っています。(アプリケーション名が過去に作ったものと一致するとその時のcファイルが開かれるみたいです)
MCCのデフォルト設定でコードを生成するとmain.cとapp.cファイルが生成されます。またmain.cにはSYS_TasksとSYS_Initialaize関数が、APP.CにはAPP_Initialize()とAPP_Tasks()が生成されるようです。(MCCの内容によって変わります。) APP.Cにはユーザー(開発者)がステートマシンで状態を管理するプログラムを書いていくみたいです。
※MCCでHarmony Core Serviceが読み込まれているとデフォルトでAPP.C(設定変更できます。)が生成されます。
アプリケーション名の変更方法

上図の様にCoreサービスをクリックすると右側に設定画面が表示されます。Generation Harmony Application Files内のApplication NameをAPPから好きな名前に変えることで変更できます。また複数のアプリケーションを作りたい場合はNumber of Applicationsを1から好きな数に変更すればその個数分のCファイルが生成されるようです。2個目、3個目も同様に名前も変更できます。また生成しない設定も可能でその際はGenerate Harmony Application Filesのチェックを外します。
Projectツリーから生成されたmain.cを開いて一度クリーンビルドを実行し、ビルドが成功することを確認します。

app.hとapp.cに下のコードを書いて、Runしました。使い方がわからない関数とか変数があればその参照しているヘッダファイルとかcファイルとかを読んでみると関数の使い方や定義などの説明が丁寧に書いてあったので、時間はかかるかもしれませんが、理解の助けになるかもしれません。
ちなみにヘッダーファイルは手順6の左上あたりにあるHeader Files内にアプリケーション名のファイルがあると思います。
下のコードは行数を抑えるために一部コメントを削除しています。またあまり良い書き方ではないかもしれないので参考程度にお願いします。
#include "app.h" //ヘッダファイルにappData(任意の名称で良い)の構造体やステート名称の定義などをする今回はapp.hだがMCC上で名称変更できます
#include "system/time/sys_time.h" //システムサービスのコールバック関数を利用するのに必要なので追記
APP_DATA appData;
// *****************************************************************************
// ****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************
/*******************************************************************************
Function:
void APP_Initialize ( void )
//時間経過フラグ
void TimeExpired(){
appData.tmrexpired = true;
}
//初期化処理
void APP_Initialize ( void )
{
appData.state = APP_STATE_INIT;
appData.tmrexpired = false;
}
void APP_Tasks ( void )
//主な処理内容
void APP_Tasks ( void )
{
switch ( appData.state )
{
/* Application's initial state. */
case APP_STATE_INIT:
{
SYS_TIME_CallbackRegisterMS(TimeExpired, 0, 1000, SYS_TIME_PERIODIC); //1000ミリ秒でTimeExpired関数を呼び出す
bool appInitialized = true;
if (appInitialized)
{
appData.state = APP_STATE_SERVICE_TASKS;
}
break;
}
case APP_STATE_SERVICE_TASKS:
{
if(appData.tmrexpired == true){
appData.tmrexpired = false; //時間のフラグが立った後は再度フラグをリセットしておく
PORTAbits.RA2 = !PORTAbits.RA2;
}
break;
}
default:
{
break;
}
}
}
//APP.hの内容
#ifndef _APP_H
#define _APP_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include "configuration.h"
typedef enum
{
/* Application's state machine's initial state. */
APP_STATE_INIT=0,
APP_STATE_SERVICE_TASKS,
/* TODO: Define states used by the application state machine. */
} APP_STATES;
typedef struct
{
/* The application's current state */
APP_STATES state;
bool tmrexpired; //追加
/* TODO: Define any additional data used by the application. */
} APP_DATA;
void APP_Initialize ( void );
void APP_Tasks( void );
#endif /* _APP_H */
プログラムを書き込む前にPICKIT5のPower設定で3.25 Vの電圧を出力するようにしておきます。(デフォルトで3.25 Vになっているとは思いますが念のため)
実行結果
プログラムを実行すると動画のようになりました。
デバッグについて
今回、思ったような動作をしなかった時があったので原因を探るのにデバッグ機能を重宝しました。デバッグはPICKIT5のPGDとPGCをマイコン側のPGDx・PGCx(xは任意の番号)端子に接続してMCCで設定を行えばプログラムと本体の動作の確認ができました。書き込みはPGDx・PGCxの好きなポートにつなげばできるのですがデバッグは設定が必要です。図6のようにSystemをクリックしてDEVCFG0内のIn-Circuit Emmulator..(緑色のマーカー表示の箇所)をデバッグに使いたいポートに設定します。はじめはPGx1になっていてMCLRの隣にデバッグポートも持っていきたかったのでPGx3に変更しました。

図7の様に赤丸をクリックするとPICに書き込みをした後にそのままデバッグが始まります。

図8の様に赤丸の部分でコードを1行ずつ進めたりデバッグを停止したり、最初からやり直したりできます。左の赤いボタンはデバッグ停止でその隣の黄色のボタン(灰色になっていますが…)は一時停止です。一時停止ボタンを押すことで紫色のリセットや緑のContinue、他ステップ実行やカーソル箇所でのプログラム実行を行えます。変数の状態は画面下側のVariablesタブなどを開くと確認することができます。

終わりに
今回は32ビットマイコンでLチカを通してMPLAB Xのツールの使い方やプログラミング方法を確認しました。いろいろな試行錯誤を行って開発環境の使い方が多少なりともわかってきたように感じます。
32ビットマイコンになると16ビットマイコンよりも複雑でとっつきにくいですが、用途や実現したい内容によって選択ができるものが増えることは良いことだと思います。今回はLチカの動作確認だけですが、かなり苦戦したので(自分の技量の問題もありますが…)誰かの役に立てれば幸いです。ここまで読んでいただきありがとうございました。























