Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: set programming language to c in src code macros

...

The block MCTC SPI Header contains the following elements:

Code Block
languagec
/**< SPI cyclic data header */
typedef struct {
    uint16_t crc_le16;                          /**< checksum */
    uint8_t seq;                                /**< sequence number */
    uint8_t lenData;                            /**< data length */
} GOAL_MI_MCTC_SPI_CYCLIC_T;

...

For uGOAL this is determined within the SAPI module:

Code Block
languagec
/****************************************************************************/
/** Basic cyclic communication function
 *
 * This function initiates SPI transfer and dispatches received data to
 * upper layers data callback and RPC handling.
 *
 */
void sapi_loop(
        void
)
{
    /* update frame header */
    sapi_pdUpdateHeader(sendData, GOAL_MI_MCTC_LEN - sizeof(GOAL_MI_MCTC_SPI_CYCLIC_T));

    /* transfer data via SPI */
    plat_spiTransfer((const char *) &sendData[0], (char *) receiveData, BUF_LENGTH);

    /* control LED if Connection valid or Wink active */
    if (true == sapi_pdCheckHeader(receiveData, GOAL_MI_MCTC_LEN - sizeof(GOAL_MI_MCTC_SPI_CYCLIC_T))) {

        /* inform application */
        som_dataCb(&receiveData[0], &sendData[0]);

        /* trigger RPC */
        goal_miMctcDmCbRead();
   }
}

...

For GOAL based applications this can be determined in the function goal_miMctcSpiProcessTask within the goal_mi_mctc_spi.c module:

Code Block
languagec
        do {

            /* check frame CRC */
            res = goal_miMctcCrc(&pBufSpi[sizeof(GOAL_MI_MCTC_SPI_CYCLIC_T)], pHdr->lenData, GOAL_le16toh_p(&pHdr->crc_le16));
            if (GOAL_RES_ERR(res)) {
                break;
            }

            /* check sequence counter */
            if (pMiMctcSpi->seqCyclicRem != pHdr->seq) {

                /* inform MI MCTC that connection is running */
                goal_miMctcMonitorRx(pMiMctc, GOAL_TRUE);

                /* re-arm watchdog */
                pMiMctcSpi->tsTout = tsNow + pMiMctc->cfgToutValue;

                /* update seen sequence */
                pMiMctcSpi->seqCyclicRem = pHdr->seq;
            }

            if (pHdr->lenData) {
                /* process MI DM incoming data */
                goal_miDmReadSync(pMiMctcSpi->pMiDmRead, &pBufSpi[sizeof(GOAL_MI_MCTC_SPI_CYCLIC_T)]);
            }
        } while (0);

...

Following code shows the state machine in exceprts:

Code Block
languagec
/****************************************************************************/
/** MCTC MI - RPC Sync Loop
 */
void goal_miMctcRpcSyncLoop(
    MCTC_INST_T *pMiMctc                        /**< MI MCTC handle */
)
{
    GOAL_STATUS_T res = GOAL_OK;                /* result */
    GOAL_BOOL_T flgSetupLocal = GOAL_FALSE;     /* local setup done flag */
    GOAL_BOOL_T flgSetupRemote = GOAL_FALSE;    /* remote setup done flag */
    GOAL_MCTC_T *pHdlMctcTx = NULL;             /* call handle */

    /* leave if not in sync-mode */
    if ((GOAL_MI_MCTC_RPC_STATE_RUN == pMiMctc->stateRpc)
        || (GOAL_MI_MCTC_RPC_STATE_STOP == pMiMctc->stateRpc)) {
        return;
    }

    /* check if send is permitted */
    if (GOAL_TRUE != goal_miMctcRpcSendAllow(pMiMctc)) {
        return;
    }

    /* handle state machine */
    switch (pMiMctc->stateRpc) {

        case GOAL_MI_MCTC_RPC_STATE_RUN_ONCE:

            /* .... */
            
            break;

        /* initialize synchronisation */
        case GOAL_MI_MCTC_RPC_STATE_SYNC_INIT:

            goal_logDbg("state: SYNC_INIT");

            /* reset sync state */
            GOAL_MASK_SET(pMiMctc->flgRpc, GOAL_MI_MCTC_RPC_FLG_SYNC_REQ);
            GOAL_MASK_CLR(pMiMctc->flgRpc, GOAL_MI_MCTC_RPC_FLG_SYNC_ACK);
            pMiMctc->seqRpcLocal = 0;
            pMiMctc->seqRpcLocalAck = 0;
            pMiMctc->seqRpcRemoteAck = 0;
            pMiMctc->stateRpc = GOAL_MI_MCTC_RPC_STATE_SYNC_REQ;

            /* intended fallthrough */
            GOAL_TARGET_FALLTHROUGH;

        /* request synchronisation from partner */
        case GOAL_MI_MCTC_RPC_STATE_SYNC_REQ:

            goal_logDbg("state: SYNC_REQ");

            /* send RPC sync frame until ACK is received */
            if (!(GOAL_MI_MCTC_RPC_FLG_SYNC_ACK & pMiMctc->flgRpcRemote)) {

                /* send sync request frame */
                goal_miMctcRpcSend(pMiMctc, NULL, 0);

                break;
            }

            /* request acknowledge of first sequence */
            GOAL_MASK_CLR(pMiMctc->flgRpc, GOAL_MI_MCTC_RPC_FLG_SYNC_REQ);
            GOAL_MASK_SET(pMiMctc->flgRpc, GOAL_MI_MCTC_RPC_FLG_REQ_ACK);
            pMiMctc->seqRpcLocal = 1;
            pMiMctc->stateRpc = GOAL_MI_MCTC_RPC_STATE_SYNC_ACK_LOCAL;

            /* intended fallthrough */
            GOAL_TARGET_FALLTHROUGH;

        case GOAL_MI_MCTC_RPC_STATE_SYNC_ACK_LOCAL:

            goal_logDbg("state: SYNC_ACK_LOCAL");

            /* send empty sequence 1 until ACK is received and we confirmed remote sequence */
            if (1 != pMiMctc->seqRpcLocalAck) {

                /* send empty RPC request */
                goal_miMctcRpcSend(pMiMctc, NULL, 0);

                break;
            }

            /* wait for remote sync */
            pMiMctc->stateRpc = GOAL_MI_MCTC_RPC_STATE_SYNC_ACK_REMOTE;

            break;

        case GOAL_MI_MCTC_RPC_STATE_SYNC_ACK_REMOTE:

            goal_logDbg("state: SYNC_ACK_REMOTE");

            if (0 == pMiMctc->seqRpcRemoteAck) {

                /* send empty RPC request */
                goal_miMctcRpcSend(pMiMctc, NULL, 0);

                break;
            }

            /* enter run mode */
            GOAL_MASK_CLR(pMiMctc->flgRpc, GOAL_MI_MCTC_RPC_FLG_REQ_ACK);
            pMiMctc->stateRpc = GOAL_MI_MCTC_RPC_STATE_RUN_ONCE;

            break;
    }
}

...

For uGOAL application, the following defines need to be set in goal_config.h:

Code Block
languagec
/* for debugging purpose disable any timeout detection on the peer */
#define CONFIG_UGOAL_TIMEOUT_RPC 0
#define CONFIG_UGOAL_TIMEOUT_MEDIA 0

...

For GOAL based application, following code needs to be called before any other functions. So best place the following calls in appl_init():

Code Block
languagec
#include <goal_media/goal_mi_mctc_spi.h>


/****************************************************************************/
/** Application Init
 *
 * Build up the device structure and initialize the Profinet stack.
 */
GOAL_STATUS_T appl_init(
    void
)
{
    GOAL_STATUS_T res = GOAL_OK;                /* result */

    /* disable media and RPC timeout */
    goal_miMctcCfgTout(0);
    goal_miMctcSpiCfgTout(0);

    /* initialize DD */
    res = goal_ddInit();
    if (GOAL_RES_ERR(res)) {
        goal_logErr("Initialization of DD failed");
    }

    /* ..... */
}

...