Using the MPLAB® Harmony v2 System Service to Control Timers

This page shows how to set up theMPLAB® Harmony Timer System Service to trigger two interrupts, each operating at different intervals, from one timer. Both of the Interrupt Service Routines (ISRs) are programmed for the simplistic task of toggling an I/O pin.

Steps demonstrated on this page include:

  1. Using MPLAB Harmony Configurator (MHC) to enable the Timer System Service.
  2. Verifying timer and system service initialization parameters.
  3. Writing the two ISRs.
  4. Registering the ISRs with the Timer System Service.
  5. Initializing application code which starts the timer.

Using the MHC to enable the Timer System Service

  • The MHC is used to establish the system clock.
  • To configure a system timer with the MHC, check theUse Timer System Service box and theInterrupt Notification Enabled box.
  • You will be asked to select theTimer Driver Instance to use as the system clock, as well as the desired frequency of the system clock.
    • The MHC will create a Timer Driver Instance for you using default values. It's likely you will need to modify these timer driver selections.
  • The field labeled Maximum Timer Clientsndetermines the number of separate ISRs that can be triggered by the system clock.
  • Enabling the Timer System Service creates the data structuresSysTmrObject to hold the data for the system timer.
  • When created, the content ofsSysTmrObject is left blank. The status fieldsSysTmrObject.status is set toSYS_STATUS_UNINITIALIZED ( 0x0000).
mhc-tmr-system-services.png
Click to enlarge.

PlacingsSysTmrObject.status (or the entire structure) into the debugger Watch Window can be very useful in tracking down problems with initializing the system timer.

watch-window.png

Initializing Timer System Service

  • The MHC places calls to the functionsDRV_TMR_Initialize andSYS_TMR_Initialize into the system initialization functionSYS_Initialize.
  • After both the timer and the system service initialization functions successfully execute,sSysTmrObject will contain the data for the system timer withsSysTmrObject.status set toSYS_STATUS_BUSY ( 0x0001).

system-init.c

void SYS_Initialize (void* data)
{



/* Initialize Timer Driver */
sysObj.drvTmr0 =DRV_TMR_Initialize(DRV_TMR_INDEX_0,(SYS_MODULE_INIT *)&drvTmr0InitData);

/* Initialize System Services */
SYS_INT_Initialize();

/* TMR Service Initialization Code */
sysObj.sysTmr =SYS_TMR_Initialize(SYS_TMR_INDEX_0,(constSYS_MODULE_INIT *const)&sysTmrInitData);



}

  • The MHC inserts callsDRV_TMR_Tasks(SysObj.drvTMR0) andSYS_TMR_Tasks(SysObj.sysTmr) into the functionSYS_Tasks(). These functions will maintain the state machines for the hardware timer and for the Timer System Service.

system-init.c

void SYS_Tasks (void)
{
/* Maintain the state machines of all library modules executing polled in
the system. */


/* Maintain system services */
SYS_DEVCON_Tasks(sysObj.sysDevcon);
SYS_TMR_Tasks(sysObj.sysTmr);

/* Maintain Device Drivers */
DRV_TMR_Tasks(sysObj.drvTmr0);

/* Maintain the application's state machine. */
APP_Tasks();

}

  • The structuresdrvTmr0InitData andsysTmrInitData contain the parameters needed to configure the timer driver and the Timer System Service. These structures are created by the MHC and placed in the filesystem-init.c.

system-init.c

void SYS_Tasks (void)
{
/* Maintain the state machines of all library modules executing polled in
the system. */


/* Maintain system services */
SYS_DEVCON_Tasks(sysObj.sysDevcon);
SYS_TMR_Tasks(sysObj.sysTmr);

/* Maintain Device Drivers */
DRV_TMR_Tasks(sysObj.drvTmr0);

/* Maintain the application's state machine. */
APP_Tasks();

}

Writing the Interrupt Service Routines (ISRs)

  • You will write an ISR for each task sharing the system timer. In this example we have two ISRsISR_Callback1 andISR_CallBack2. These are very simple routines which simply toggle an I/O pin when they are executed.

app.c



/* ISR to Toggle PIN RF0 when called */
void ISR_Callback_1 (uintptr_tcontext,uint32_tcurrTick )
{
PLIB_PORTS_PinToggle(PORTS_ID_0, PORT_CHANNEL_F, PORTS_BIT_POS_0);
}

/* ISR to Toggle pin RA0 when called*/
void ISR_Callback_2 (uintptr_tcontext,uint32_tcurrTick )
{
PLIB_PORTS_PinToggle(PORTS_ID_0, PORT_CHANNEL_A, PORTS_BIT_POS_0);
}

Registering the ISR with the Timer System Service

  • Your ISRs are registered as System Service Callbacks by the functionSYS_TMR_CallbackPeriodic. In this example, the ISRs are registered when your application is first executed. The code below registersISR_Callback1 to run every 400 milliseconds, andISR_Callback2 to run every 200 milliseconds.

app.c

void APP_Tasks (void )
{
/* Check the application's current state. */
switch ( appData.state )
{
/* Application's initial state. */
case APP_STATE_INIT:
{
PLIB_PORTS_PinDirectionOutputSet(PORTS_ID_0, PORT_CHANNEL_F, PORTS_BIT_POS_0);
PLIB_PORTS_PinDirectionOutputSet(PORTS_ID_0, PORT_CHANNEL_A, PORTS_BIT_POS_0);

SYS_TMR_CallbackPeriodic ( 400, 0, ISR_Callback_1 );
SYS_TMR_CallbackPeriodic ( 200, 0, ISR_Callback_2 );

appData.state=APP_STATE_RUN ;
break;
}

case APP_STATE_RUN:
{
break;
}

}
}

Initializing the Application

  • SYS_TMR_CallbackPeriodic must be called after the Timer System Service is initialized. This only needs to be called once. Repeated calls toSYS_TMR_CallbackPeriodic can disrupt the interrupt process. To avoid this function from being called multiple times, the code below inserts the stateAPP-STATE-RUN.
  • The code also shows how to set the desired output pins as output.

app.c

void APP_Tasks (void )
{
/* Check the application's current state. */
switch ( appData.state )
{
/* Application's initial state. */
case APP_STATE_INIT:
{
PLIB_PORTS_PinDirectionOutputSet(PORTS_ID_0, PORT_CHANNEL_F, PORTS_BIT_POS_0);
PLIB_PORTS_PinDirectionOutputSet(PORTS_ID_0, PORT_CHANNEL_A, PORTS_BIT_POS_0);

SYS_TMR_CallbackPeriodic ( 400, 0, ISR_Callback_1 );
SYS_TMR_CallbackPeriodic ( 200, 0, ISR_Callback_2 );

appData.state=APP_STATE_RUN ;
break;
}

case APP_STATE_RUN:
{
break;
}

}
}

 Learn More

 
Harmony Timer Tutorial
Learn more >
 
Example Code and Projects
Learn more >
 
Entire Timer System Service Interface
Learn more >
 
PIC32 Timer Hardware Description
Learn more >