.

     

MPI Application Template
template.c
 

syncInterrupt.c -- Configure board to interrupt host every N samples.
/* syncInterrupt.c */

/* Copyright(c) 1991-2006 by Motion Engineering, Inc.  All rights reserved.
 *
 * This software  contains proprietary and  confidential information  of
 * Motion Engineering Inc., and its suppliers.  Except as may be set forth
 * in the license agreement under which  this software is supplied, use,
 * disclosure, or  reproduction is prohibited without the prior express
 * written consent of Motion Engineering, Inc.
 */

/*

: Configure board to interrupt host every N samples.

This program configures the board to interrupt the host every N (SYNC_PERIOD) samples.  
It also will spawn a task that will wake up every time the interrupt occurs and check 
to see if the interrupt sent was the sync interrupt.
If HOST_PROCESS_FLAG is defined, the program will set the HostProcessFlag in the firmware
at the beginning of the task.  When the task is complete, it will clear the HostProcessFlag.
If the HostProcessFlag is still set when the firmware starts SynqNet transmission, a status
bit in the Control Status word is set.  This code also will look to see if that bit gets set.
The bit indicates that the host's process did not complete before SynqNet transmission.  This 
should be used if the host is trying to (for example) process feedback and calculate a new DAC
command.  HOST_PROCESS_FLAG should only be defined if the SYNC_PERIOD is 1 (interrupt every
sample).

Warning!  This is a sample program to assist in the integration of an
 MEI motion controller with your application.  It may not contain all
 of the logic and safety features that your application requires.

The msgCHECK(...) macros used in the following sample code are intended
 to convey our strong belief that ALL error return codes should be checked.
 Actual application code should use specific error handling techniques (other
 than msgCHECKs) best suited to your internal error recovery methods.

*/

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <windows.h>

#include "stdmpi.h"
#include "stdmei.h"

#include "apputil.h"

#define SYNC_PERIOD  (1)   /* sync interrupt every sample */
#define HOST_PROCESS_FLAG (1)

long syncDone = 0;
long syncStop = 0;

/* Perform basic command line parsing. (-control -server -port -trace) */
void basicParsing(int                    argc,
                  char                  *argv[],
                  MPIControlType        *controlType,
                  MPIControlAddress     *controlAddress)
{
    long argIndex;

    /* Parse command line for Control type and address */
    argIndex = argControl(argc, argv, controlType, controlAddress);

    /* Check for unknown/invalid command line arguments */
    if (argIndex < argc) {
        fprintf(stderr,"usage: %s %s\n", argv[0], ArgUSAGE);
        exit(MPIMessageARG_INVALID);
    }
}

/* Perform certain cleanup actions and delete MPI objects */
void programCleanup(MPIControl *control)
{
    long    returnValue;

    /* Delete control handle */
    returnValue =
        mpiControlDelete(*control);
    msgCHECK(returnValue);

    *control = MPIHandleVOID;
}

static long syncInterruptFunction(MPIControl *control)
{
   long             returnValue;
   MPIXmpData       *firmware;
   MPIControlConfig mpiConfig;
   MPIControlConfig mpiConfig;
   MPI_BOOL         interrupted;
   long sampleCounter, oldSampleCounter, syncFlag;

   returnValue = mpiControlMemory(*control,
                           &firmware,
                           NULL);

   /* Enable interrupts */
   if (returnValue == MPIMessageOK) {
      MPIPlatform platform = mpiControlPlatform(*control);
      returnValue = mpiPlatformValidate(platform);

      if (returnValue == MPIMessageOK) {
         returnValue = mpiPlatformInterruptEnable(platform,
                                       TRUE);
      }
   }

   /* Configure sync interrupt */
   if (returnValue == MPIMessageOK) {
      returnValue = mpiControlConfigGet(*control,
                                 &mpiConfig,
                                 &mpiConfig);

      if (returnValue == MPIMessageOK) {
         mpiConfig.syncInterruptPeriod = SYNC_PERIOD;

         returnValue = mpiControlConfigSet(*control,
                                    &mpiConfig,
                                    &mpiConfig);
      }
   }

   if (returnValue == MPIMessageOK) {
      returnValue = mpiControlMemoryGet(*control,
                              &oldSampleCounter,
                              &firmware->SystemData.SampleCounter,
                              sizeof(oldSampleCounter));

      if (returnValue == MPIMessageOK) {
         while (!syncStop) {
            returnValue = mpiControlInterruptWait(*control,
                                          &interrupted,
                                          MPIWaitFOREVER);


            /* check to see if this is really a SyncInterrupt */
            if (returnValue == MPIMessageOK) {
               returnValue = mpiControlMemoryGet(*control,
                                       &syncFlag,
                                       &firmware->SystemData.SyncInterrupt.Flag,
                                       sizeof(syncFlag));

               if ((returnValue == MPIMessageOK) && (syncFlag)) {
#if HOST_PROCESS_FLAG
                  /* Set Host Process Flag */
                  /* WARNING: Do Not leave the Host Process Flag set for longer than 1 sample.  The foreground 
                     task in the firmware will consider this an error and will set a warning bit.

                     The Host Process Flag is not necessary if the SYNC_PERIOD is greater than 1 sample/interrupt.
                     It is there if the Host wants to know if the Host Process has compleated before the 
                     SynqNet DMA occurs in the firmware's foreground task.
                  */
                  long hostProcessFlag = 1;
                  returnValue = mpiControlMemorySet(*control,
                                          &firmware->SystemData.SyncInterrupt.HostProcessFlag,
                                          &hostProcessFlag,
                                          sizeof(hostProcessFlag));
#endif
                  /* Host Process Start */
                  if (returnValue == MPIMessageOK) {
                     returnValue = mpiControlMemoryGet(*control,
                                             &sampleCounter,
                                             &firmware->SystemData.SampleCounter,
                                             sizeof(sampleCounter));
#if 0             
                     if (returnValue == MPIMessageOK) {
                        mpiPlatformConsole("SampleCounter: 0x%d\n", sampleCounter);

                        if ((sampleCounter - SYNC_PERIOD) != oldSampleCounter) {
                           mpiPlatformConsole("Error %d samples\nsampleCounter %d\noldSampleCounter %d\nperiod %d\n",
                              (sampleCounter - oldSampleCounter), sampleCounter, oldSampleCounter, SYNC_PERIOD);
                        }

                        oldSampleCounter = sampleCounter;
                     }
#endif
                  }
                  /* Host Process End */

#if HOST_PROCESS_FLAG
                  if (returnValue == MPIMessageOK) {
                     /* Clear Host Process Flag */
                     hostProcessFlag = 0;
                     returnValue = mpiControlMemorySet(*control,
                                             &firmware->SystemData.SyncInterrupt.HostProcessFlag,
                                             &hostProcessFlag,
                                             sizeof(hostProcessFlag));
                  }
#endif
               }
            }
         }
      }
   }

   /* Disable sync interrupt */
   if (returnValue == MPIMessageOK) {
      mpiConfig.syncInterruptPeriod = 0;

      returnValue = mpiControlConfigSet(*control,
                                 &mpiConfig,
                                 &mpiConfig);
   }

   syncDone = 1;

   return returnValue;
}

int main(int     argc,
         char   *argv[])
{
    long          returnValue;
    MPIControl          control;
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;
   Thread            thread;
   long           threadPriority;
   ThreadStatus      status;

#if HOST_PROCESS_FLAG
    MPINotify        notify;         /* event notification object */
    MPIEventMgr         eventMgr;       /* event manager handle */
    MPIEventMask     eventMask;
    Service          service;
   MPIEventStatus    eventStatus;
#endif

    /* Perform basic command line parsing. (-control -server -port -trace) */
    basicParsing(argc,
                 argv,
                 &controlType,
                 &controlAddress);

    /* Obtain a control handle */
    control = mpiControlCreate(controlType, &controlAddress);
    msgCHECK(mpiControlValidate(control));

    /* Initialize the controller */
    returnValue = mpiControlInit(control);
    msgCHECK(returnValue);


   thread = threadCreate(NULL);
   returnValue = threadValidate(thread);
    msgCHECK(returnValue);

   returnValue = threadStart(thread,
                     (THREAD_FUNCTION)syncInterruptFunction,
                     &control);
    msgCHECK(returnValue);

   returnValue = threadStatus(thread,
                        &status);
    msgCHECK(returnValue);

   if (status.active != FALSE) {
      returnValue = threadPriorityGet(thread,
                           &threadPriority);
      msgCHECK(returnValue);

      threadPriority = THREAD_PRIORITY_TIME_CRITICAL;


      returnValue = threadPrioritySet(thread,
                              threadPriority);
       msgCHECK(returnValue);
   }
   else {
      printf("could not activate thread\n");
      syncDone = 1;
   }

#if HOST_PROCESS_FLAG
    /* Request notification of control events */
    mpiEventMaskCLEAR(eventMask);
    mpiEventMaskCONTROL(eventMask);
    returnValue =
        mpiControlEventNotifySet(control,
                                eventMask,
                                NULL);
    msgCHECK(returnValue);

    /* Create event notification object for motion */
    notify =
        mpiNotifyCreate(eventMask,
                        control);
    msgCHECK(mpiNotifyValidate(notify));

    /* Create event manager object */
    eventMgr = mpiEventMgrCreate(control);
    msgCHECK(mpiEventMgrValidate(eventMgr));

    /* Add notify to event manager's list */
    returnValue =
        mpiEventMgrNotifyAppend(eventMgr,
                                notify);
    msgCHECK(returnValue);

    /* Create service thread */
    service =
        serviceCreate(eventMgr,
                      -1,   /* default (max) priority */
                      -1);  /* -1 => enable interrupts */
    mpiAssert(service != NULL);
#endif

   while(!syncDone) {
      if(kbhit()) {
         syncStop = 1;
      }

#if HOST_PROCESS_FLAG
      /* Wait for motion event */
      returnValue =
         mpiNotifyEventWait(notify,
                        &eventStatus,
                        MPIWaitPOLL);

      if (returnValue == MPIMessageOK) {
         if (eventStatus.type == MPIEventTypeCONTROL_HOST_PROCESS_TIME_EXCEEDED) {
            mpiPlatformConsole("Host Process Time Exceeded\n");
            mpiPlatformConsole("mpiNotifyEventWait(0x%x, 0x%x, %d) returns 0x%x\n"
               "\teventStatus: type %d source 0x%x info 0x%x\n",
               notify,
               &eventStatus,
               MPIWaitFOREVER,
               returnValue,
               eventStatus.type,
               eventStatus.source,
               eventStatus.info[0]);


               returnValue = mpiControlEventReset(control,
                                          eventMask);
                msgCHECK(returnValue);
         }
      }
      if (returnValue == MPIMessageTIMEOUT) {
         returnValue = MPIMessageOK;
      }
#endif
   }

#if HOST_PROCESS_FLAG
    /* Perform certain cleanup actions and delete MPI objects */
    returnValue = serviceDelete(service);
    msgCHECK(returnValue);

    returnValue = mpiEventMgrDelete(eventMgr);
    msgCHECK(returnValue);

    returnValue = mpiNotifyDelete(notify);
    msgCHECK(returnValue);

   returnValue = threadDelete(thread);
    msgCHECK(returnValue);
#endif

    programCleanup(&control);


    return MPIMessageOK;
}


          
       Legal Notice  |  Tech Email  |  Feedback
      
Copyright ©
2001-2009 Motion Engineering