平成26年10月 9日
MPLAB Harmonyの使い方(4)
前回の変更でライブラリ機能の追加方法は概ね見当がつきますが、Device Control System Serviceのみでは周辺機能との連携が殆ど無いのでもう少し複雑な機能を実装してみます。
とはいえ、いきなりUSBのような巨大なモジュールを実装しても、上手く行かないときの対処方法の検討が大変です。
ここは少しずつ機能を増やしていきます。
ライブラリの中からタイマ機能を使用することにします。
タイマ機能なら機能的にあまり複雑にはならないし、一般的な周辺機能と同じく割り込み駆動を行えます。
これでタイマ機能と割り込み関連のライブラリを使用できることになります。
再び先のプロジェクトを変更して、ライブラリ機能を追加します。
前回同様、最初にプロジェクトのバックアップコピーをとっておきます。
次に下図のように、タイマ機能の設定を追加します。
なお、タイマ機能にはCHを関数に固定したSTATIC仕様と引数で渡すDYNAMIC仕様があるようです。
ここでは扱いが簡単と思われるSTATIC仕様で動作検証を行います。
この設定ではタイマが30,000カウント(1ms)毎に割り込みを発生させます。
前回と同じくGenerateボタンを押して設定をプログラムに反映させます。
画面左側のProjectウインドウのようにファイルが追加されます。
ここではCソースファイル/Framework/systemの下にclk, intのライブラリが追加されています。タイマ用のライブラリソースは特に無いようで、割り込み処理ルーチンがsystem_interrupt.c内に追加されています。
ここでintライブラリはグローバル割り込みフラグを含む割り込み機能を管理するライブラリです。
clkライブラリは主として発信回路からCPUへクロックを供給するまでの、発信器の選択やPLL機能・分周期の設定などを管理しているライブラリのようです。
これら2つのライブラリはタイマ機能を割り込み駆動で追加すると自動的に追加されるようです。本来ならclkライブラリは追加の必要は無いと思うのですが。
動作検証のために必要なファイルの変更箇所を示します。追加部分は太字部分です。
まず、SYS_Initialize()関数内でSYS_CLK_Initialize()関数が呼ばれていますが、これをコメントアウトします。
この関数内部で呼び出しているPLIB関連の関数で無意味なワーニングが多数発生します。
ここではタイマ動作に対してclkライブラリは無関係なので、削除しても問題ありません。
(H26/10/9追記)
ワーニングをなくすには、これだけでは不十分でした。Projectウインドウのframework/system/clk/src/ディレクトリにあるsys_clk.cおよびsys_clk_pic32mx.cの各々を選択して右クリックしpropertiesを選択すると、以下の画面が表示されます。ここで”Exclude
forom build”にチェックを入れることで、これらのファイルをビルド対象から外します。

(追記ここまで)
system_init.c
#include "system_config.h"
#include "app.h"
#include "system_definitions.h"
/*** DEVCFG0 ***/
#pragma config DEBUG = ON
#pragma config ICESEL = ICS_PGx2
#pragma config PWP = 0xff
#pragma config BWP = OFF
#pragma config CP = OFF
/*** DEVCFG1 ***/
#pragma config FNOSC = PRIPLL
#pragma config FSOSCEN = OFF
#pragma config IESO = OFF
#pragma config POSCMOD = HS
#pragma config OSCIOFNC = OFF
#pragma config FPBDIV = DIV_1
#pragma config FCKSM = CSDCMD
#pragma config WDTPS = PS1048576
#pragma config FWDTEN = OFF
/*** DEVCFG2 ***/
#pragma config FPLLIDIV = DIV_4
#pragma config FPLLMUL = MUL_15
#pragma config FPLLODIV = DIV_2
#pragma config UPLLIDIV = DIV_12
#pragma config UPLLEN = OFF
/*** DEVCFG3 ***/
#pragma config USERID = 0xffff
#pragma config FSRSSEL = PRIORITY_7
#pragma config FMIIEN = OFF
#pragma config FETHIO = OFF
#pragma config FCANIO = OFF
#pragma config FUSBIDIO = OFF
#pragma config FVBUSONIO = OFF
// *****************************************************************************
// Section: Library/Stack Initialization Data
// *****************************************************************************/
// *****************************************************************************
// Section: Driver Initialization Data
// *****************************************************************************
// *****************************************************************************
// Section: System Data
// *****************************************************************************
/* Structure to hold the object handles for the modules in the system. */
SYSTEM_OBJECTS sysObj;
// *****************************************************************************
// Section: Module Initialization Data
// *****************************************************************************
const SYS_DEVCON_INIT sysDevconInit =
{
.moduleInit = {0},
};
// *****************************************************************************
// Section: Static Initialization Functions
// *****************************************************************************
// *****************************************************************************
// Section: System Initialization
// *****************************************************************************
void SYS_Initialize ( void* data )
{
/* Core Processor Initialization */
//SYS_CLK_Initialize(&sysClkInit);//コメントアウトに変更が必要
sysObj.sysDevcon = SYS_DEVCON_Initialize(SYS_DEVCON_INDEX_0, (SYS_MODULE_INIT*)&sysDevconInit);
SYS_DEVCON_PerformanceConfig(SYS_DEVCON_SYSTEM_CLOCK);
/* System Services Initialization */
SYS_INT_Initialize();
/* Initialize Drivers */
/* Timer Instanace 0 Call */
DRV_TMR0_Initialize();
/* Initialize System Services */
/* Initialize Middleware */
/* Enable Global Interrupts */
SYS_INT_Enable();
/* Initialize the Application */
APP_Initialize();
}
app.cファイルでは初期化関数にタイマの開始を追加します。また、動作確認用のIOポート操作はAPP_Tasks()関数から割り込み処理ルーチンに移動させます。
app.c
<一部省略>
void APP_Initialize ( void )
{
/* Place the App state machine in its initial state. */
appData.state = APP_STATE_INIT;
/* TODO: Initialize your application's state machine and other
* parameters.
*/
LATD=0;
TRISD=0;
PLIB_TMR_Start(TMR_ID_1);
}
void APP_Tasks ( void )
{
/* Check the application's current state. */
switch ( appData.state )
{
/* Application's initial state. */
case APP_STATE_INIT:
{
//LATD=0xFFFF; //削除する
//LATD=0;
break;
}
/* TODO: implement your application state machine.*/
/* The default state should never be executed. */
default:
{
/* TODO: Handle error in application's state machine. */
break;
}
}
}
system_interrupt.c
#include <xc.h>
#include <sys/attribs.h>
#include "app.h"
#include "system_definitions.h"
#include "xc.h"
// *****************************************************************************
// *****************************************************************************
// Section: System Interrupt Vector Functions
// *****************************************************************************
// *****************************************************************************
void __ISR(_TIMER_1_VECTOR, ipl1) _IntHandlerDrvTmrInstance0(void)
{
PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_TIMER_1);
LATD ^=0xffff;
}
これで割り込み駆動による周辺機能動作の雛形が出来ました。
動作確認の結果を示します。
少しピンボケ気味ですが、期待通りに1ms周期で出力値が変化しています。
同じ手法でUARTやSPIなどの周辺機能ライブラリを動作させられます。