1122 lines
39 KiB
C
1122 lines
39 KiB
C
/*
|
|
* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
|
|
* The corresponding license agreement applies. This hint shall not be removed.
|
|
*/
|
|
|
|
/**
|
|
\addtogroup EcatAppl EtherCAT application
|
|
@{
|
|
*/
|
|
|
|
|
|
/**
|
|
\file ecatappl.c
|
|
\author EthercatSSC@beckhoff.com
|
|
\brief Implementation
|
|
This file contains the Process Data interface
|
|
|
|
\version 5.12
|
|
|
|
<br>Changes to version V5.11:<br>
|
|
V5.12 APPL1: add optional application function called from the main loop (after mbx and esm are executed)<br>
|
|
V5.12 BOOT1: add a bootloader sample application (only the ESM and FoE is supported)<br>
|
|
V5.12 COE4: add timestamp object (0x10F8) and update diagnosis handling<br>
|
|
V5.12 ECAT1: update SM Parameter measurement (based on the system time), enhancement for input only devices and no mailbox support, use only 16Bit pointer in process data length caluclation<br>
|
|
V5.12 ECAT3: update PD monitoring variables even if the slave is not in OP, disable all interrupts in case that the pd handling is called from the mainloop<br>
|
|
V5.12 ECAT5: update Sync error counter/flag handling,check enum memory alignment depending on the processor,in case of a polled timer disable ESC interrupts during DC_CheckWatchdog<br>
|
|
V5.12 ECAT8: reset appl function pointer on startup, update timeout calculation during eeprom access<br>
|
|
V5.12 EEPROM1: get read size from register 0x502.6<br>
|
|
V5.12 EEPROM2: clear CRC Error bit only in case of a valid reload, write station alias only in case of an successful reload,handle full eeprom emlation relaod commands<br>
|
|
V5.12 EEPROM3: implement a store EEPROM timeout handler<br>
|
|
<br>Changes to version V5.10.1:<br>
|
|
V5.11 COE3: change 0x10F3.2 (Sync Error limit) from UINT32 to UINT16 (according to the ETG.1020)<br>
|
|
V5.11 ECAT1: update EEPROM access reset operation<br>
|
|
V5.11 ECAT10: change PROTO handling to prevent compiler errors<br>
|
|
V5.11 ECAT11: create application interface function pointer, add eeprom emulation interface functions<br>
|
|
V5.11 ECAT2: update EEPROM access retry cycle (add 10ms delay between two retry cycles)<br>
|
|
V5.11 ECAT3: handle bus cycle calculation for input/output only devices and create warning diag message only if calculation failed<br>
|
|
V5.11 ECAT4: enhance SM/Sync monitoring for input/output only slaves<br>
|
|
V5.11 ECAT6: add function to calculate bus cycle time<br>
|
|
V5.11 ECAT8: call PDO_InputMapping only once if DC is enabled and COE is not supported<br>
|
|
V5.11 EEPROM1: fix compiler error during pEEPROM pointer initialization<br>
|
|
V5.11 EEPROM2: write Station alias value to EEPROM data register on EEPROM reload command<br>
|
|
V5.11 EEPROM3: clear EEPROM error bits<br>
|
|
V5.11 EEPROM4: prevent the variable in the EEPROM busy loop to be removed by the compiler<br>
|
|
V5.11 ESM7: "add Sync define for 0x22 (""SYNCTYPE_SM2_SYNCHRON""), support value 0x22 for 0x1C33.1 (SM2 sync)"<br>
|
|
<br>Changes to version V5.01:<br>
|
|
V5.10 COE1: Define one entry description for all 0x1C3x objects and change data type of SI11,12,13 to UINT16 (according ETG.1020)<br>
|
|
V5.10 ECAT1: Correct calculation of blinking and flashing sequence<br>
|
|
V5.10 ECAT13: Update Synchronisation handling (FreeRun,SM Sync, Sync0, Sync1)<br>
|
|
Compare DC UINT configuration (by ESC Config data) vs. DC activation register settings<br>
|
|
Update 0x1C3x entries<br>
|
|
V5.10 ECAT2: Prevent EEPROM data null pointer access (if the pointer is null an command error is set)<br>
|
|
EEPROM emulation return command error if unknown command was received<br>
|
|
V5.10 ECAT4: Update alignment marco for 8 to 15 bit alignments (16 and 32 Bit controllers)<br>
|
|
Bugfix calculate LED blink frequency<br>
|
|
V5.10 ECAT7: Add "bInitFinished" to indicate if the initialization is complete<br>
|
|
V5.10 HW2: Change HW_GetTimer return value to UINT32<br>
|
|
<br>Changes to version V5.0:<br>
|
|
V5.01 APPL3: Include library demo application<br>
|
|
V5.01 ESC1: Change ESC access function (if EEPROM Emulation is active)<br>
|
|
V5.01 ESC2: Add missed value swapping<br>
|
|
<br>Changes to version V4.40:<br>
|
|
V5.0 TEST1: Add test application. See Application Note ET9300 for more details.<br>
|
|
V5.0 ECAT2: Application specific functions are moved to application files.<br>
|
|
V5.0 ECAT3: Global dummy variables used for dummy ESC operations.<br>
|
|
V5.0 ESC1: ESC 32Bit Access added.<br>
|
|
V5.0 ESC3: Add EEPROM emulation support.<br>
|
|
V5.0 ESM3: Handling pending ESM transitions.<br>
|
|
V5.0 ESC5: Enhance EEPROM access handling.<br>
|
|
V5.0 PDO1: AL Event flags are not rechecked in PDO_OutputMappping(). (Already checked before call function)<br>
|
|
V5.0 SYNC1: Add missed SM event indication (0x1C32/0x1C33 SI11).<br>
|
|
<br>Changes to version V4.30:<br>
|
|
V4.40 DIAG1: add diagnosis message support<br>
|
|
V4.40 PDO1: merge content of HW_InputMapping (spihw.c/mcihw.c) to PDO_InputMapping. merge content of HW_OutputMapping (spihw.c/mcihw.c) to PDO_OutputMapping.<br>
|
|
V4.40 PDO2: Generic process data length calculation<br>
|
|
V4.40 ECAT2: call cyclic CheckIfLocalError() to check the local flags<br>
|
|
V4.40 HW0: Generic hardware access functions. Add Function (PDI_Isr()), content merged from spihw.c and mcihw.c.<br>
|
|
V4.40 WD1: define (ESC_SM_WD_SUPPORTED) to choose ESC SyncManager watchdog or local watchdog<br>
|
|
V4.40 ESM2: Change state transition behaviour from SafeOP to OP<br>
|
|
V4.40 TIMER1: Change bus cycle time calculation and trigger of ECAT_CheckTimer() if ECAT_TIMER_INT is reset<br>
|
|
V4.40 HW1: Add support for fc1100 hardware<br>
|
|
<br>Changes to version V4.20:<br>
|
|
V4.30 EL9800: EL9800_x cyclic application is moved to el9800.c<br>
|
|
V4.30 OBJ 3: add object dictionary initialization<br>
|
|
V4.30 SYNC: add CalcSMCycleTime() (calculation of bus cycle time); change synchronisation control functions<br>
|
|
V4.30 PDO: include PDO specific functions (moved from coeappl.c).<br>
|
|
xxx_InputMapping(); xxx_OutputMapping(); xxx_ReadInputs(); xxx_ResetOutputs(); xxx_Application()<br>
|
|
V4.30 CiA402: Add CiA402_StateMachine() and CiA402_Application() call<br>
|
|
V4.20 DC 1: Add DC pending Statemachine handling<br>
|
|
V4.20 PIC24: Add EL9800_4 (PIC24) required source code<br>
|
|
V4.20 LED 1: Modified LED Handling<br>
|
|
V4.11 APPL 1: The checkWatchdog() function should not called in checkTimer() if this function is triggered by an Interrupt<br>
|
|
<br>Changes to version V4.08:<br>
|
|
V4.10 LED 1: The handling of the EtherCAT-Error-LED was added<br>
|
|
V4.10 AOE 3: The AoE fragment size has to be initialized during the state transition<br>
|
|
from INIT to PREOP<br>
|
|
<br>Changes to version V4.07:<br>
|
|
V4.08 LED 1: The handling of the EtherCAT-LED can be (de-)selected by the switch LEDS_SUPPORTED<br>
|
|
because the ET1100 and ET1200 have an output port which could be connected directly.<br>
|
|
<br>Changes to version V4.01:<br>
|
|
V4.02 ECAT 1: The watchdog timer variables shall be initialized.<br>
|
|
<br>Changes to version V4.00:<br>
|
|
V4.01 APPL 1: If the application is running in synchron mode and no SM event<br>
|
|
is received, the application should be called from the main loop<br>
|
|
V4.01 APPL 2: In FreeRun mode the output should only be copied if the slave is in OP<br>
|
|
<br>Changes to version V3.20:<br>
|
|
V4.00 APPL 1: The watchdog checking should be done by a microcontroller<br>
|
|
timer because the watchdog trigger of the ESC will be reset too<br>
|
|
if only a part of the sync manager data is written<br>
|
|
V4.00 APPL 2: The setting of EtherCAT state LEDs were included<br>
|
|
V4.00 APPL 3: The outputs should be reset to a safe state,<br>
|
|
when the state OP is left<br>
|
|
V4.00 APPL 4: An example for the EEPROM access through the ESC is shown in<br>
|
|
the function APPL_StartMailboxHandler<br>
|
|
V4.00 APPL 5: The inputs should be read once when the state transition<br>
|
|
from PREOP to SAFEOP is made<br>
|
|
V4.00 APPL 6: The main function was split in MainInit and MainLoop
|
|
*/
|
|
|
|
|
|
/*-----------------------------------------------------------------------------------------
|
|
------
|
|
------ Includes
|
|
------
|
|
-----------------------------------------------------------------------------------------*/
|
|
#include "ecatslv.h"
|
|
|
|
#define _ECATAPPL_ 1
|
|
#include "ecatappl.h"
|
|
#undef _ECATAPPL_
|
|
/*remove definition of _ECATAPPL_ (#ifdef is used in ecatappl.h)*/
|
|
|
|
#include "coeappl.h"
|
|
|
|
|
|
|
|
#define _APPL_INTERFACE_ 1
|
|
#include "applInterface.h"
|
|
#undef _APPL_INTERFACE_
|
|
|
|
#include "cia402appl.h"
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------------------------------
|
|
------
|
|
------ local Types and Defines
|
|
------
|
|
--------------------------------------------------------------------------------------*/
|
|
|
|
|
|
#ifndef ECAT_TIMER_INC_P_MS
|
|
/**
|
|
* \todo Define the timer ticks per ms
|
|
*/
|
|
#warning "Define the timer ticks per ms"
|
|
#endif /* #ifndef ECAT_TIMER_INC_P_MS */
|
|
|
|
|
|
|
|
/*ECATCHANGE_START(V5.12) ECAT1*/
|
|
#define MEASUREMENT_ACTIVE (((sSyncManOutPar.u16GetCycleTime & 0x1) == 0x1) || ((sSyncManInPar.u16GetCycleTime & 0x1) == 0x1))
|
|
/*ECATCHANGE_END(V5.12) ECAT1*/
|
|
|
|
/*-----------------------------------------------------------------------------------------
|
|
------
|
|
------ local variables and constants
|
|
------
|
|
-----------------------------------------------------------------------------------------*/
|
|
/*ECATCHANGE_START(V5.12) ECAT1*/
|
|
/*variables required to calculate values for SM Synchronisation objects (0x1C3x)*/
|
|
|
|
UINT32 u32CycleTimeStartValue; /** <\brief contains the timer start value to measure the application cycle (used in freerun and SM2 sync)*/
|
|
|
|
UINT32 u32MinCycleTimeStartValue; /** <\brief timeout counter in ms to measure the process timings (stored in 0x1C3x)*/
|
|
|
|
UINT32 u32SystemTimeReadFailure; /** <\brief System time measurement failure (the value is calculated on main init)*/
|
|
|
|
BOOL bMinCycleTimeMeasurementStarted; /** <\brief Indicates if the min cycle measurement is started*/
|
|
|
|
UINT32 u32MinCycleTimeValue; /** <\brief tmp value of the min cycle time during measurement*/
|
|
|
|
/*ECATCHANGE_END(V5.12) ECAT1*/
|
|
|
|
|
|
|
|
|
|
UINT16 aPdOutputData[(MAX_PD_OUTPUT_SIZE>>1)];
|
|
UINT16 aPdInputData[(MAX_PD_INPUT_SIZE>>1)];
|
|
|
|
/*variables are declared in ecatslv.c*/
|
|
extern VARVOLATILE UINT8 u8dummy;
|
|
|
|
BOOL bInitFinished = FALSE; /** < \brief indicates if the initialization is finished*/
|
|
|
|
/*-----------------------------------------------------------------------------------------
|
|
------
|
|
------ local functions
|
|
------
|
|
-----------------------------------------------------------------------------------------*/
|
|
/*ECATCHANGE_START(V5.12) ECAT1*/
|
|
UINT32 GetSystemTimeDelay(UINT32 u32StartTime);
|
|
void HandleCycleTimeMeasurement(void);
|
|
/*ECATCHANGE_END(V5.12) ECAT1*/
|
|
|
|
/*-----------------------------------------------------------------------------------------
|
|
------
|
|
------ Functions
|
|
------
|
|
-----------------------------------------------------------------------------------------*/
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
\brief This function will copies the inputs from the local memory to the ESC memory
|
|
*////////////////////////////////////////////////////////////////////////////////////////
|
|
void PDO_InputMapping(void)
|
|
{
|
|
|
|
#if ((MIN_PD_CYCLE_TIME == 0) || (PD_INPUT_CALC_AND_COPY_TIME == 0))
|
|
/*ECATCHANGE_START(V5.12) ECAT1*/
|
|
UINT32 u32TimeValue = 0;
|
|
UINT16 ALEvent = HW_GetALEventRegister_Isr();
|
|
ALEvent = SWAPWORD(ALEvent);
|
|
|
|
|
|
if (MEASUREMENT_ACTIVE)
|
|
{
|
|
u32TimeValue = GetSystemTimeDelay(0);
|
|
}
|
|
/*ECATCHANGE_END(V5.12) ECAT1*/
|
|
#endif /* ((MIN_PD_CYCLE_TIME == 0) || (PD_INPUT_CALC_AND_COPY_TIME == 0)) */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
APPL_InputMapping((UINT16*)aPdInputData);
|
|
HW_EscWriteIsr(((MEM_ADDR *) aPdInputData), nEscAddrInputData, nPdInputSize );
|
|
|
|
|
|
|
|
#if ((MIN_PD_CYCLE_TIME == 0) || (PD_INPUT_CALC_AND_COPY_TIME == 0))
|
|
/*ECATCHANGE_START(V5.12) ECAT1*/
|
|
|
|
if (MEASUREMENT_ACTIVE)
|
|
{
|
|
u32TimeValue = GetSystemTimeDelay(u32TimeValue);
|
|
|
|
#if (PD_INPUT_CALC_AND_COPY_TIME == 0)
|
|
if (sSyncManInPar.u32CalcAndCopyTime < u32TimeValue)
|
|
{
|
|
sSyncManInPar.u32CalcAndCopyTime = u32TimeValue;
|
|
}
|
|
#endif
|
|
|
|
#if (MIN_PD_CYCLE_TIME == 0)
|
|
/* handle the min cycle time measurement only if a new cycle was started (prevent measurement failures if the get cycle time bit is set within a process data cycle)*/
|
|
if (bMinCycleTimeMeasurementStarted == TRUE)
|
|
{
|
|
|
|
/* add input mapping time to the min cycle time*/
|
|
u32MinCycleTimeValue = u32MinCycleTimeValue + u32TimeValue;
|
|
|
|
|
|
if (sSyncManOutPar.u32MinCycleTime < u32MinCycleTimeValue)
|
|
{
|
|
sSyncManOutPar.u32MinCycleTime = u32MinCycleTimeValue;
|
|
}
|
|
|
|
if (sSyncManInPar.u32MinCycleTime < u32MinCycleTimeValue)
|
|
{
|
|
sSyncManInPar.u32MinCycleTime = u32MinCycleTimeValue;
|
|
}
|
|
|
|
bMinCycleTimeMeasurementStarted = FALSE;
|
|
}
|
|
#endif /* (MIN_PD_CYCLE_TIME == 0) */
|
|
}
|
|
|
|
/*ECATCHANGE_END(V5.12) ECAT1*/
|
|
#endif /* ((MIN_PD_CYCLE_TIME == 0) || (PD_INPUT_CALC_AND_COPY_TIME == 0)) */
|
|
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
\brief This function will copies the outputs from the ESC memory to the local memory.
|
|
This function is only called in case of an SM2 (output process data) event.
|
|
*////////////////////////////////////////////////////////////////////////////////////////
|
|
void PDO_OutputMapping(void)
|
|
{
|
|
/*ECATCHANGE_START(V5.12) ECAT1*/
|
|
UINT32 u32TimeValue = 0;
|
|
if (MEASUREMENT_ACTIVE)
|
|
{
|
|
#if ((MIN_PD_CYCLE_TIME == 0) || (PD_OUTPUT_CALC_AND_COPY_TIME == 0))
|
|
u32TimeValue = GetSystemTimeDelay(0);
|
|
u32MinCycleTimeStartValue = u32TimeValue;
|
|
|
|
bMinCycleTimeMeasurementStarted = TRUE;
|
|
u32MinCycleTimeValue = 0;
|
|
|
|
#endif /* ((MIN_PD_CYCLE_TIME == 0) || (PD_OUTPUT_CALC_AND_COPY_TIME == 0)) */
|
|
|
|
HandleCycleTimeMeasurement();
|
|
|
|
}
|
|
/*ECATCHANGE_END(V5.12) ECAT1*/
|
|
|
|
HW_EscReadIsr(((MEM_ADDR *)aPdOutputData), nEscAddrOutputData, nPdOutputSize );
|
|
APPL_OutputMapping((UINT16*) aPdOutputData);
|
|
|
|
|
|
/*ECATCHANGE_START(V5.12) ECAT1*/
|
|
#if ((MIN_PD_CYCLE_TIME == 0) || (PD_OUTPUT_CALC_AND_COPY_TIME == 0))
|
|
if (MEASUREMENT_ACTIVE)
|
|
{
|
|
u32TimeValue = GetSystemTimeDelay(u32TimeValue);
|
|
|
|
#if (PD_OUTPUT_CALC_AND_COPY_TIME == 0)
|
|
if (sSyncManOutPar.u32CalcAndCopyTime < u32TimeValue)
|
|
{
|
|
sSyncManOutPar.u32CalcAndCopyTime = u32TimeValue;
|
|
}
|
|
#endif
|
|
|
|
#if (MIN_PD_CYCLE_TIME == 0)
|
|
/* add the first part of the min cycle time */
|
|
u32MinCycleTimeValue = u32TimeValue;
|
|
#endif
|
|
}
|
|
#endif /* #if ((MIN_PD_CYCLE_TIME == 0) || (PD_OUTPUT_CALC_AND_COPY_TIME == 0)) */
|
|
/*ECATCHANGE_END(V5.12) ECAT1*/
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
\brief This function shall be called every 1ms.
|
|
\brief If the switch ECAT_TIMER_INT is 0, the watchdog control is implemented without using
|
|
\brief interrupts. In this case a local timer register is checked every ECAT_Main cycle
|
|
\brief and the function is triggered if 1 ms is elapsed
|
|
*////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ECAT_CheckTimer(void)
|
|
{
|
|
|
|
/*decrement the state transition timeout counter*/
|
|
if(bEcatWaitForAlControlRes && (EsmTimeoutCounter > 0))
|
|
{
|
|
EsmTimeoutCounter--;
|
|
}
|
|
|
|
|
|
ECAT_SetLedIndication();
|
|
|
|
DC_CheckWatchdog();
|
|
|
|
|
|
/*ECATCHANGE_START(V5.12) COE4*/
|
|
|
|
/* Increment the counter every ms between two updates based on the system time (32Bit overrun is handled in COE_SyncTimeStamp) */
|
|
if (!b32BitDc || ((u64Timestamp & 0xFFFFFFFF) <= 4293000000))
|
|
{
|
|
|
|
/* the timestamp is stored in ns */
|
|
u64Timestamp = u64Timestamp + 1000000;
|
|
|
|
}
|
|
else if(b32BitDc)
|
|
{
|
|
/* in case of a 32Bit DC and almost expired time stamp check for a DC overrun*/
|
|
u32CheckForDcOverrunCnt = CHECK_DC_OVERRUN_IN_MS;
|
|
}
|
|
|
|
u32CheckForDcOverrunCnt++;
|
|
/*ECATCHANGE_END(V5.12) COE4*/
|
|
}
|
|
|
|
/*ECATCHANGE_START(V5.12) ECAT1*/
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
\brief In case of non DC synchronization the cycle time measurement is started and 0x1C3.2 (Cycle time) is updated
|
|
*////////////////////////////////////////////////////////////////////////////////////////
|
|
void HandleCycleTimeMeasurement(void)
|
|
{
|
|
if (!bDcSyncActive) //no DC sync configured (cycle time measurement 0x1C3x.2 is only available in no DC sync modes)
|
|
{
|
|
if (u32CycleTimeStartValue > 0)
|
|
{
|
|
/* bus cycle completed*/
|
|
u32CycleTimeStartValue = GetSystemTimeDelay(u32CycleTimeStartValue);
|
|
|
|
if ((sSyncManOutPar.u32CycleTime == 0) || (sSyncManOutPar.u32CycleTime > u32CycleTimeStartValue))
|
|
{
|
|
sSyncManOutPar.u32CycleTime = u32CycleTimeStartValue;
|
|
}
|
|
|
|
if ((sSyncManInPar.u32CycleTime == 0) || (sSyncManInPar.u32CycleTime > u32CycleTimeStartValue))
|
|
{
|
|
sSyncManInPar.u32CycleTime = u32CycleTimeStartValue;
|
|
}
|
|
}
|
|
/* get next start value */
|
|
u32CycleTimeStartValue = GetSystemTimeDelay(0);
|
|
|
|
}/* No DC sync configured */
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
\param u32StartTime Old system time (0x910:0x913) value
|
|
|
|
\return System time delta in ns
|
|
|
|
\brief Calculates the difference between the old and current system time value in ns.
|
|
NOTE: This function only handles a 32Bit system time values (therefore the maximum delay about 4sec).
|
|
*////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
UINT32 GetSystemTimeDelay(UINT32 u32StartTime)
|
|
{
|
|
UINT32 u32CurValue = 0;
|
|
UINT32 u32Delta = 0;
|
|
|
|
|
|
HW_EscReadDWordIsr(u32CurValue, ESC_SYSTEMTIME_OFFSET);
|
|
|
|
if (u32CurValue > 0)
|
|
{
|
|
if (u32StartTime <= u32CurValue)
|
|
{
|
|
u32Delta = u32CurValue - u32StartTime;
|
|
}
|
|
else
|
|
{
|
|
//The 32Bit timer is wrapped around
|
|
u32Delta = u32CurValue + (0xFFFFFFFF - u32StartTime);
|
|
}
|
|
}// current value successfully read out
|
|
|
|
if (u32StartTime > 0)
|
|
{
|
|
|
|
/*the difference between two timestamps are calculated => subtract measurement failure*/
|
|
if (u32SystemTimeReadFailure < u32Delta)
|
|
{
|
|
u32Delta = u32Delta - u32SystemTimeReadFailure;
|
|
}
|
|
else
|
|
{
|
|
/*set the delta to 0 if the measurement failure is greater than the calculated difference*/
|
|
u32Delta = 0;
|
|
}
|
|
}
|
|
return u32Delta;
|
|
}
|
|
/*ECATCHANGE_END(V5.12) ECAT1*/
|
|
|
|
void PDI_Isr(void)
|
|
{
|
|
if(bEscIntEnabled)
|
|
{
|
|
/* get the AL event register */
|
|
UINT16 ALEvent = HW_GetALEventRegister_Isr();
|
|
ALEvent = SWAPWORD(ALEvent);
|
|
|
|
if ( ALEvent & PROCESS_OUTPUT_EVENT )
|
|
{
|
|
if(bDcRunning && bDcSyncActive)
|
|
{
|
|
/* Reset SM/Sync0 counter. Will be incremented on every Sync0 event*/
|
|
u16SmSync0Counter = 0;
|
|
}
|
|
if(sSyncManOutPar.u16SmEventMissedCounter > 0)
|
|
{
|
|
sSyncManOutPar.u16SmEventMissedCounter--;
|
|
}
|
|
|
|
/*ECATCHANGE_START(V5.12) ECAT5*/
|
|
sSyncManInPar.u16SmEventMissedCounter = sSyncManOutPar.u16SmEventMissedCounter;
|
|
/*ECATCHANGE_END(V5.12) ECAT5*/
|
|
|
|
|
|
|
|
/* Outputs were updated, set flag for watchdog monitoring */
|
|
bEcatFirstOutputsReceived = TRUE;
|
|
|
|
|
|
/*
|
|
handle output process data event
|
|
*/
|
|
if ( bEcatOutputUpdateRunning )
|
|
{
|
|
/* slave is in OP, update the outputs */
|
|
PDO_OutputMapping();
|
|
}
|
|
else
|
|
{
|
|
/* Just acknowledge the process data event in the INIT,PreOP and SafeOP state */
|
|
HW_EscReadByteIsr(u8dummy,nEscAddrOutputData);
|
|
HW_EscReadByteIsr(u8dummy,(nEscAddrOutputData+nPdOutputSize-1));
|
|
}
|
|
}
|
|
|
|
/*
|
|
Call ECAT_Application() in SM Sync mode
|
|
*/
|
|
if (sSyncManOutPar.u16SyncType == SYNCTYPE_SM_SYNCHRON)
|
|
{
|
|
/* The Application is synchronized to process data Sync Manager event*/
|
|
ECAT_Application();
|
|
}
|
|
|
|
if ( bEcatInputUpdateRunning
|
|
&& ((sSyncManInPar.u16SyncType == SYNCTYPE_SM_SYNCHRON) || (sSyncManInPar.u16SyncType == SYNCTYPE_SM2_SYNCHRON))
|
|
)
|
|
{
|
|
/* EtherCAT slave is at least in SAFE-OPERATIONAL, update inputs */
|
|
PDO_InputMapping();
|
|
}
|
|
|
|
/*
|
|
Check if cycle exceed
|
|
*/
|
|
/*if next SM event was triggered during runtime increment cycle exceed counter*/
|
|
ALEvent = HW_GetALEventRegister_Isr();
|
|
ALEvent = SWAPWORD(ALEvent);
|
|
|
|
if ( ALEvent & PROCESS_OUTPUT_EVENT )
|
|
{
|
|
sSyncManOutPar.u16CycleExceededCounter++;
|
|
sSyncManInPar.u16CycleExceededCounter = sSyncManOutPar.u16CycleExceededCounter;
|
|
|
|
/* Acknowledge the process data event*/
|
|
HW_EscReadByteIsr(u8dummy,nEscAddrOutputData);
|
|
HW_EscReadByteIsr(u8dummy,(nEscAddrOutputData+nPdOutputSize-1));
|
|
}
|
|
} //if(bEscIntEnabled)
|
|
|
|
/*ECATCHANGE_START(V5.12) ECAT5*/
|
|
COE_UpdateSyncErrorStatus();
|
|
/*ECATCHANGE_END(V5.12) ECAT5*/
|
|
|
|
}
|
|
|
|
void Sync0_Isr(void)
|
|
{
|
|
Sync0WdCounter = 0;
|
|
|
|
if(bDcSyncActive)
|
|
{
|
|
|
|
if ( bEcatInputUpdateRunning )
|
|
{
|
|
LatchInputSync0Counter++;
|
|
}
|
|
|
|
if(u16SmSync0Value > 0)
|
|
{
|
|
/* Check if Sm-Sync sequence is invalid */
|
|
if (u16SmSync0Counter > u16SmSync0Value)
|
|
{
|
|
if ((nPdOutputSize > 0) && (sSyncManOutPar.u16SmEventMissedCounter <= sErrorSettings.u16SyncErrorCounterLimit))
|
|
{
|
|
sSyncManOutPar.u16SmEventMissedCounter = sSyncManOutPar.u16SmEventMissedCounter + 3;
|
|
}
|
|
|
|
if ((nPdInputSize > 0) && (nPdOutputSize == 0) && (sSyncManInPar.u16SmEventMissedCounter <= sErrorSettings.u16SyncErrorCounterLimit))
|
|
{
|
|
sSyncManInPar.u16SmEventMissedCounter = sSyncManInPar.u16SmEventMissedCounter + 3;
|
|
}
|
|
|
|
} // if (u16SmSync0Counter > u16SmSync0Value)
|
|
|
|
|
|
if ((nPdOutputSize == 0) && (nPdInputSize > 0))
|
|
{
|
|
/* Input only with DC, check if the last input data was read*/
|
|
UINT16 ALEvent = HW_GetALEventRegister_Isr();
|
|
ALEvent = SWAPWORD(ALEvent);
|
|
|
|
if ((ALEvent & PROCESS_INPUT_EVENT) == 0)
|
|
{
|
|
|
|
/* no input data was read by the master, increment the sm missed counter*/
|
|
if (u16SmSync0Counter <= u16SmSync0Value)
|
|
{
|
|
u16SmSync0Counter++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Reset SM/Sync0 counter*/
|
|
u16SmSync0Counter = 0;
|
|
|
|
sSyncManInPar.u16SmEventMissedCounter = 0;
|
|
|
|
}
|
|
}
|
|
else if (u16SmSync0Counter <= u16SmSync0Value)
|
|
{
|
|
|
|
u16SmSync0Counter++;
|
|
}
|
|
}//SM -Sync monitoring enabled
|
|
|
|
|
|
/* Application is synchronized to SYNC0 event*/
|
|
ECAT_Application();
|
|
|
|
if ( bEcatInputUpdateRunning
|
|
&& (LatchInputSync0Value > 0) && (LatchInputSync0Value == LatchInputSync0Counter) ) /* Inputs shall be latched on a specific Sync0 event */
|
|
{
|
|
/* EtherCAT slave is at least in SAFE-OPERATIONAL, update inputs */
|
|
PDO_InputMapping();
|
|
|
|
if(LatchInputSync0Value == 1)
|
|
{
|
|
/* if inputs are latched on every Sync0 event (otherwise the counter is reset on the next Sync1 event) */
|
|
LatchInputSync0Counter = 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*ECATCHANGE_START(V5.12) ECAT5*/
|
|
COE_UpdateSyncErrorStatus();
|
|
/*ECATCHANGE_END(V5.12) ECAT5*/
|
|
|
|
}
|
|
|
|
void Sync1_Isr(void)
|
|
{
|
|
Sync1WdCounter = 0;
|
|
|
|
if ( bEcatInputUpdateRunning
|
|
&& (sSyncManInPar.u16SyncType == SYNCTYPE_DCSYNC1)
|
|
&& (LatchInputSync0Value == 0)) /* Inputs are latched on Sync1 (LatchInputSync0Value == 0), if LatchInputSync0Value > 0 inputs are latched with Sync0 */
|
|
{
|
|
/* EtherCAT slave is at least in SAFE-OPERATIONAL, update inputs */
|
|
PDO_InputMapping();
|
|
}
|
|
|
|
/* Reset Sync0 latch counter (to start next Sync0 latch cycle) */
|
|
LatchInputSync0Counter = 0;
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
|
|
\brief This function shall called within a 1ms cycle.
|
|
Set Run and Error Led depending on the Led state
|
|
|
|
*////////////////////////////////////////////////////////////////////////////////////////
|
|
void ECAT_SetLedIndication(void)
|
|
{
|
|
static UINT16 ms = 0;
|
|
static UINT16 RunCounter = 0;
|
|
static UINT16 ErrorCounter = 0;
|
|
|
|
static UINT8 u8PrevErrorLed = LED_OFF ;
|
|
static UINT8 u8PrevRunLed = LED_OFF ;
|
|
|
|
// this code should be called every ms in average
|
|
if ( bEcatOutputUpdateRunning )
|
|
{
|
|
// in OP the EtherCAT state LED is always 1 and ErrorLED is 0
|
|
bEtherCATRunLed = TRUE;
|
|
bEtherCATErrorLed = FALSE;
|
|
}
|
|
else
|
|
{
|
|
ms++;
|
|
if(ms == 50 || ms == 100 ||ms == 150 ||ms == 200) //set flickering LED if required
|
|
{
|
|
/*Set run Led State*/
|
|
switch ( nAlStatus & STATE_MASK)
|
|
{
|
|
case STATE_INIT:
|
|
// in INIT the EtherCAT state LED is off
|
|
u8EcatRunLed = LED_OFF;
|
|
break;
|
|
case STATE_PREOP:
|
|
// in PREOP the EtherCAT state LED toggles every 200 ms
|
|
u8EcatRunLed = LED_BLINKING;
|
|
break;
|
|
case STATE_SAFEOP:
|
|
// in SAFEOP the EtherCAT state LED is 200 ms on and 1s off
|
|
u8EcatRunLed = LED_SINGLEFLASH;
|
|
break;
|
|
case STATE_OP:
|
|
u8EcatRunLed = LED_ON;
|
|
break;
|
|
case STATE_BOOT:
|
|
u8EcatRunLed = LED_FLICKERING;
|
|
break;
|
|
default:
|
|
u8EcatRunLed = LED_OFF;
|
|
break;
|
|
}//switch nAlStatus
|
|
|
|
/*Calculate current Run LED state*/
|
|
if((u8EcatRunLed & 0x20) || ms == 200) //if fast flag or slow cycle event
|
|
{
|
|
UINT8 NumFlashes = 0;
|
|
if ((u8EcatRunLed & 0x1F) > 0)
|
|
{
|
|
NumFlashes = (u8EcatRunLed & 0x1F)+((u8EcatRunLed & 0x1F)-1); //total number
|
|
}
|
|
|
|
/*generate LED code*/
|
|
if(u8EcatRunLed != u8PrevRunLed) //state changed start with active LED
|
|
{
|
|
if(u8EcatRunLed & 0x80) //invert flag enable?
|
|
{
|
|
bEtherCATRunLed = FALSE;
|
|
}
|
|
else
|
|
{
|
|
bEtherCATRunLed = TRUE;
|
|
}
|
|
|
|
RunCounter = 1;
|
|
}
|
|
else //second and following LED cycle
|
|
{
|
|
if(u8EcatRunLed & 0x40) //toggle LED bit on
|
|
{
|
|
bEtherCATRunLed = !bEtherCATRunLed;
|
|
|
|
if(NumFlashes) //NumFlashes defined => limited LED toggle
|
|
{
|
|
RunCounter++;
|
|
|
|
if(RunCounter > NumFlashes) //toggle led finished
|
|
{
|
|
if(u8EcatRunLed & 0x80) //invert flag enable?
|
|
{
|
|
bEtherCATRunLed = TRUE;
|
|
}
|
|
else
|
|
{
|
|
bEtherCATRunLed = FALSE;
|
|
}
|
|
|
|
if(RunCounter >= (NumFlashes+5)) //toggle time + 5 cycles low
|
|
{
|
|
RunCounter = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bEtherCATRunLed = (u8EcatRunLed & 0x01);
|
|
}
|
|
}
|
|
u8PrevRunLed = u8EcatRunLed;
|
|
}
|
|
|
|
/*Calculate current Error LED state*/
|
|
if((u8EcatErrorLed & 0x20) || ms == 200) //if fast flag or slow cycle event
|
|
{
|
|
UINT8 NumFlashes = 0;
|
|
if ((u8EcatErrorLed & 0x1F) > 0)
|
|
{
|
|
NumFlashes = (u8EcatErrorLed & 0x1F)+((u8EcatErrorLed & 0x1F)-1); //total number
|
|
}
|
|
|
|
/*generate LED code*/
|
|
if(u8EcatErrorLed != u8PrevErrorLed) //state changed start with active LED
|
|
{
|
|
if(u8EcatErrorLed & 0x80) //invert flag enable?
|
|
{
|
|
bEtherCATErrorLed = FALSE;
|
|
}
|
|
else
|
|
{
|
|
bEtherCATErrorLed = TRUE;
|
|
}
|
|
|
|
ErrorCounter = 1;
|
|
}
|
|
else //second and following LED cycle
|
|
{
|
|
if(u8EcatErrorLed & 0x40) //toggle LED bit on
|
|
{
|
|
bEtherCATErrorLed = !bEtherCATErrorLed;
|
|
|
|
if(NumFlashes) //NumFlashes defined => limited LED toggle
|
|
{
|
|
ErrorCounter++;
|
|
|
|
if(ErrorCounter > NumFlashes) //toggle led finished
|
|
{
|
|
if(u8EcatErrorLed & 0x80) //invert flag enable?
|
|
{
|
|
bEtherCATErrorLed = TRUE;
|
|
}
|
|
else
|
|
{
|
|
bEtherCATErrorLed = FALSE;
|
|
}
|
|
|
|
if(ErrorCounter >= (NumFlashes+5)) //toggle time + 5 cycles low
|
|
{
|
|
ErrorCounter = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bEtherCATErrorLed = (u8EcatErrorLed & 0x01);
|
|
}
|
|
}
|
|
|
|
u8PrevErrorLed = u8EcatErrorLed;
|
|
}
|
|
|
|
if(ms == 200)
|
|
{
|
|
ms = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* set the EtherCAT-LED */
|
|
HW_SetLed(((UINT8)bEtherCATRunLed),((UINT8)bEtherCATErrorLed));
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
\param pObjectDictionary Pointer to application specific object dictionary.
|
|
NULL if no specific object are available.
|
|
\return 0 if initialization was successful
|
|
|
|
\brief This function initialize the EtherCAT Sample Code
|
|
|
|
*////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
UINT16 MainInit(void)
|
|
{
|
|
UINT16 Error = 0;
|
|
/*Hardware init function need to be called from the application layer*/
|
|
|
|
#ifdef SET_EEPROM_PTR
|
|
SET_EEPROM_PTR
|
|
#endif
|
|
|
|
|
|
/*ECATCHANGE_START(V5.12) ECAT8*/
|
|
/* Reset application function pointer*/
|
|
|
|
|
|
|
|
|
|
pAPPL_MainLoop = NULL;
|
|
/*ECATCHANGE_END(V5.12) ECAT8*/
|
|
|
|
/* initialize the EtherCAT Slave Interface */
|
|
ECAT_Init();
|
|
/* initialize the objects */
|
|
COE_ObjInit();
|
|
|
|
|
|
/*indicate that the slave stack initialization finished*/
|
|
bInitFinished = TRUE;
|
|
|
|
/*ECATCHANGE_START(V5.12) ECAT1*/
|
|
|
|
bMinCycleTimeMeasurementStarted = FALSE;
|
|
u32CycleTimeStartValue = 0;
|
|
u32MinCycleTimeStartValue = 0;
|
|
|
|
u32SystemTimeReadFailure = 0;
|
|
|
|
/* Get the System Time read failure */
|
|
{
|
|
UINT32 u32TimeValue = 0;
|
|
UINT32 u32Cnt = 0;
|
|
UINT32 u32Delta = 0;
|
|
|
|
while (u32Cnt < 1000)
|
|
{
|
|
HW_EscReadDWordIsr(u32TimeValue, ESC_SYSTEMTIME_OFFSET);
|
|
HW_EscReadDWordIsr(u32Delta, ESC_SYSTEMTIME_OFFSET);
|
|
|
|
if (u32TimeValue <= u32Delta)
|
|
{
|
|
u32Delta = u32Delta - u32TimeValue;
|
|
}
|
|
else
|
|
{
|
|
//The 32Bit timer is wrapped around
|
|
u32Delta = u32Delta + (0xFFFFFFFF - u32TimeValue);
|
|
}
|
|
|
|
|
|
if (u32SystemTimeReadFailure == 0)
|
|
{
|
|
u32SystemTimeReadFailure = u32Delta;
|
|
}
|
|
else if (u32SystemTimeReadFailure > u32Delta)
|
|
{
|
|
u32SystemTimeReadFailure = u32Delta;
|
|
}
|
|
|
|
u32Cnt++;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*ECATCHANGE_END(V5.12) ECAT1*/
|
|
|
|
|
|
/*Application Init need to be called from the application layer*/
|
|
return Error;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
|
|
\brief This function shall be called cyclically from main
|
|
|
|
*////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void MainLoop(void)
|
|
{
|
|
|
|
/*return if initialization not finished */
|
|
if(bInitFinished == FALSE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* FreeRun-Mode: bEscIntEnabled = FALSE, bDcSyncActive = FALSE
|
|
Synchron-Mode: bEscIntEnabled = TRUE, bDcSyncActive = FALSE
|
|
DC-Mode: bEscIntEnabled = TRUE, bDcSyncActive = TRUE */
|
|
if (
|
|
(!bEscIntEnabled || !bEcatFirstOutputsReceived) /* SM-Synchronous, but not SM-event received */
|
|
&& !bDcSyncActive /* DC-Synchronous */
|
|
)
|
|
{
|
|
/* if the application is running in ECAT Synchron Mode the function ECAT_Application is called
|
|
from the ESC interrupt routine (in mcihw.c or spihw.c),
|
|
in ECAT Synchron Mode it should be additionally checked, if the SM-event is received
|
|
at least once (bEcatFirstOutputsReceived = 1), otherwise no interrupt is generated
|
|
and the function ECAT_Application has to be called here (with interrupts disabled,
|
|
because the SM-event could be generated while executing ECAT_Application) */
|
|
if ( !bEscIntEnabled )
|
|
{
|
|
/* application is running in ECAT FreeRun Mode,
|
|
first we have to check, if outputs were received */
|
|
UINT16 ALEvent = HW_GetALEventRegister();
|
|
ALEvent = SWAPWORD(ALEvent);
|
|
|
|
if ( ALEvent & PROCESS_OUTPUT_EVENT )
|
|
{
|
|
/* set the flag for the state machine behavior */
|
|
bEcatFirstOutputsReceived = TRUE;
|
|
if ( bEcatOutputUpdateRunning )
|
|
{
|
|
/* update the outputs */
|
|
PDO_OutputMapping();
|
|
}
|
|
}
|
|
else if ( nPdOutputSize == 0 )
|
|
{
|
|
/* if no outputs are transmitted, the watchdog must be reset, when the inputs were read */
|
|
if ( ALEvent & PROCESS_INPUT_EVENT )
|
|
{
|
|
/* Outputs were updated, set flag for watchdog monitoring */
|
|
bEcatFirstOutputsReceived = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*ECATCHANGE_START(V5.12) ECAT3*/
|
|
DISABLE_ESC_INT();
|
|
/*ECATCHANGE_END(V5.12) ECAT3*/
|
|
ECAT_Application();
|
|
|
|
if ( bEcatInputUpdateRunning )
|
|
{
|
|
/* EtherCAT slave is at least in SAFE-OPERATIONAL, update inputs */
|
|
PDO_InputMapping();
|
|
}
|
|
/*ECATCHANGE_START(V5.12) ECAT3*/
|
|
ENABLE_ESC_INT();
|
|
/*ECATCHANGE_END(V5.12) ECAT3*/
|
|
}
|
|
|
|
/* there is no interrupt routine for the hardware timer so check the timer register if the desired cycle elapsed*/
|
|
{
|
|
UINT32 CurTimer = (UINT32)HW_GetTimer();
|
|
|
|
if(CurTimer>= ECAT_TIMER_INC_P_MS)
|
|
{
|
|
ECAT_CheckTimer();
|
|
|
|
HW_ClearTimer();
|
|
}
|
|
}
|
|
|
|
/*ECATCHANGE_START(V5.12) COE4*/
|
|
if (u32CheckForDcOverrunCnt >= CHECK_DC_OVERRUN_IN_MS)
|
|
{
|
|
COE_SyncTimeStamp();
|
|
}
|
|
/*ECATCHANGE_END(V5.12) COE4*/
|
|
|
|
/* call EtherCAT functions */
|
|
ECAT_Main();
|
|
|
|
/* call lower prior application part */
|
|
COE_Main();
|
|
CheckIfEcatError();
|
|
|
|
if(bEcatInputUpdateRunning)
|
|
{
|
|
CiA402_StateMachine();
|
|
}
|
|
|
|
/*ECATCHANGE_START(V5.12) APPL1*/
|
|
if (pAPPL_MainLoop != NULL)
|
|
{
|
|
pAPPL_MainLoop();
|
|
}
|
|
/*ECATCHANGE_END(V5.12) APPL1*/
|
|
}
|
|
|
|
/*The main function was moved to the application files.*/
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
\brief ECAT_Application (prev. SSC versions "COE_Application")
|
|
this function calculates and the physical process signals and triggers the input mapping
|
|
*////////////////////////////////////////////////////////////////////////////////////////
|
|
void ECAT_Application(void)
|
|
{
|
|
#if (MIN_PD_CYCLE_TIME == 0)
|
|
/*ECATCHANGE_START(V5.12) ECAT1*/
|
|
UINT32 u32TimeValue = 0;
|
|
|
|
if (MEASUREMENT_ACTIVE)
|
|
{
|
|
u32TimeValue = GetSystemTimeDelay(0);
|
|
|
|
if (nPdOutputSize == 0)
|
|
{
|
|
/* in case of an input only device the cycle starts with an ECAT_Application call*/
|
|
|
|
u32MinCycleTimeStartValue = u32TimeValue;
|
|
bMinCycleTimeMeasurementStarted = TRUE;
|
|
u32MinCycleTimeValue = 0;
|
|
}
|
|
} /* measurement started*/
|
|
/*ECATCHANGE_END(V5.12) ECAT1*/
|
|
#endif /* (MIN_PD_CYCLE_TIME == 0)*/
|
|
|
|
if (MEASUREMENT_ACTIVE)
|
|
{
|
|
if (nPdOutputSize == 0)
|
|
{
|
|
/* in case of an input only device the cycle starts with an ECAT_Application call*/
|
|
HandleCycleTimeMeasurement();
|
|
}
|
|
}
|
|
|
|
/*Axis configuration is written in state change from PREOP to SAFEOP
|
|
=> trigger CiA402 Application if device is in SAFEOP or OP
|
|
(Motion Controller function is only triggered if DC Synchronisation is active and valid mode of operation is set)*/
|
|
if(bEcatInputUpdateRunning)
|
|
{
|
|
APPL_Application();
|
|
}
|
|
/* PDO Input mapping is called from the specific trigger ISR */
|
|
|
|
#if (MIN_PD_CYCLE_TIME == 0)
|
|
/*ECATCHANGE_START(V5.12) ECAT1*/
|
|
|
|
if (MEASUREMENT_ACTIVE)
|
|
{
|
|
u32TimeValue = GetSystemTimeDelay(u32TimeValue);
|
|
|
|
|
|
/* handle the min cycle time measurement only if a new cycle was started (prevent measurement failures if the get cycle time bit is set within a process data cycle)*/
|
|
if (bMinCycleTimeMeasurementStarted == TRUE)
|
|
{
|
|
|
|
/* add application execution time to the min cycle time*/
|
|
u32MinCycleTimeValue = u32MinCycleTimeValue + u32TimeValue;
|
|
|
|
if (nPdInputSize == 0)
|
|
{
|
|
/* In case of an output only device the cycle ends with an ECAT_Application call*/
|
|
|
|
|
|
if (sSyncManOutPar.u32MinCycleTime < u32MinCycleTimeValue)
|
|
{
|
|
sSyncManOutPar.u32MinCycleTime = u32MinCycleTimeValue;
|
|
}
|
|
|
|
if (sSyncManInPar.u32MinCycleTime < u32MinCycleTimeValue)
|
|
{
|
|
sSyncManInPar.u32MinCycleTime = u32MinCycleTimeValue;
|
|
}
|
|
|
|
bMinCycleTimeMeasurementStarted = FALSE;
|
|
}
|
|
}
|
|
|
|
}/* measurement started*/
|
|
/*ECATCHANGE_END(V5.12) ECAT1*/
|
|
#endif /* #if MIN_PD_CYCLE_TIME == 0 */
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @} */
|
|
|