How to enable a callback for cyclic IO - data

Caution: using that callback routine can have a massiv influence to the realtime behavior of the stack!

This feature is unavailable for multicore projects until GOAL v2.23.0.

The example below shows the use of the callback function:

  • create the following local prototype and variables

  • Add the callback function to the callback handler

/****************************************************************************/ /* Local Prototypes */ /****************************************************************************/ static GOAL_STATUS_T appl_pnioCb( GOAL_PNIO_T *pHdlPnio, /**< PROFINET instance */ GOAL_PNIO_CB_ID_T id, /**< callback id */ GOAL_PNIO_CB_DATA_T *pCb /**< callback parameters */ ); /****************************************************************************/ /* Local Variables */ /****************************************************************************/ static GOAL_BOOL_T flgAppReady = GOAL_FALSE; /**< app ready flag */ static GOAL_PNIO_AR_ID_T idAr = 0; /**< AR ID */ static GOAL_PNIO_T *pPnio; /**< PROFINET instance */ static char targetData[APPL_MOD_SIZE]; /**< dummy where data is copied to */ /****************************************************************************/ /** Profinet Callback Handler * * This function collects all callbacks from the stack and decides if the * callback must be handled. */ static GOAL_STATUS_T appl_pnioCb( GOAL_PNIO_T *pHdlPnio, /**< PROFINET instance */ GOAL_PNIO_CB_ID_T id, /**< callback id */ GOAL_PNIO_CB_DATA_T *pCb /**< callback parameters */ ) { GOAL_STATUS_T res = GOAL_OK; /* return value */ UNUSEDARG(pHdlPnio); /* handle callback IDs */ switch (id) { case GOAL_PNIO_CB_ID_APPL_READY: /* application ready was confirmed, start data handling if not * already running */ if (GOAL_TRUE != flgAppReady) { flgAppReady = GOAL_TRUE; idAr = pCb->data[0].idAr; } break; case GOAL_PNIO_CB_ID_RELEASE_AR: /* AR was released, stop data handling if it was the first AR */ if (idAr == pCb->data[0].idAr) { flgAppReady = GOAL_FALSE; idAr = 0; } break; case GOAL_PNIO_CB_ID_BLINK: goal_targetSetLeds((pCb->data[1].stateDcpLight) ? UINT32_MAX : 0); break; case GOAL_PNIO_CB_ID_NEW_IO_DATA: /* New I/O data received. * Be careful: this call will block the PNIO stack * so just do the copying here and nothing else. * If not fast enough, just set a flag and retrieve the data * later in appl_loop if required. **/ memcpy(targetData, pCb->data[2].pCu8, pCb->data[1].u16); break; default: break; } return res; }

To use the cb function GOAL_PNIO_CB_ID_NEW_IO_DATA the following functions have to be called exactly in the order described below before and after function goal_pnioNew(...):

  • goal_pnioCfgNewIoDataCbSet(GOAL_TRUE); → configure stack to feature the GOAL_PNIO_CB_ID_NEW_IO_DATA callback

  • goal_pnioCyclicCtrl(pPnio,GOAL_TRUE); → enable GOAL_PNIO_CB_ID_NEW_IO_DATA callback for each arrived cyclic frame

/****************************************************************************/ /** Application Setup * * Setup the application. */ GOAL_STATUS_T appl_setup( void ) { GOAL_STATUS_T res; /* result */ /* configure stack to feature the GOAL_PNIO_CB_ID_NEW_IO_DATA callback */ goal_pnioCfgNewIoDataCbSet(GOAL_TRUE); /* create new PROFINET instance */ res = goal_pnioNew(&pPnio, APPL_PNIO_ID, appl_pnioCb); if (GOAL_RES_ERR(res)) { goal_logErr("failed to create a new PROFINET instance"); return res; } /* enable GOAL_PNIO_CB_ID_NEW_IO_DATA callback for each arrived cyclic frame */ goal_pnioCyclicCtrl(pPnio,GOAL_TRUE); goal_logInfo("Initializing device structure"); /* from here create the device configuration */ ... /* PROFINET configuration succesful */ goal_logInfo("PROFINET ready"); return GOAL_OK; }