/*************************************************************************\ * Copyright (c) 2023 Paul Scherrer Institute * ecmc is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. * * ecmcPluginSafety.c * * Created on: jan 29, 2024 * Author: anderssandstrom * * Instructions: * - IMPORTANT: Add "USR_CFLAGS +=-DECMC_PLUGIN_MODULE_NAME=${MODULE}" to GNUMakefile * - All functions and ecmcPluginData struct must be declared static \*************************************************************************/ // Needed to get headers in ecmc right... #define ECMC_IS_PLUGIN #define ECMC_PLUGIN_VERSION 1 #ifdef __cplusplus extern "C" { #endif // ifdef __cplusplus #include #include #include #include "ecmcPluginDefs.h" #include "ecmcSafetyPlgDefs.h" #include "ecmcSafetyPlgWrap.h" static int lastEcmcError = 0; static int alreadyLoaded = 0; static int destructs_ = 0; /** Optional. * Will be called once after successful load into ecmc. * Return value other than 0 will be considered error. * configStr can be used for configuration parameters. **/ static int construct(char *configStr) { if(alreadyLoaded) { return ECMC_PLUGIN_ALREADY_LOADED_ERROR_CODE; } alreadyLoaded = 1; return setCfgString(configStr); } /** Optional function. * Will be called once at unload. **/ static void safetyDestruct(void) { destructs_ = 1; deleteAllSafetyGroups(); } /** Optional function. * Will be called each realtime cycle if defined * ecmcError: Error code of ecmc. Makes it possible for * this plugin to react on ecmc errors * Return value other than 0 will be considered to be an error code in ecmc. **/ static int safetyRealtime(int ecmcError) { if(destructs_) return 0; executeSafetyGroups(); lastEcmcError = ecmcError; return 0; } /** Link to data source here since all sources should be available at this stage * (for example ecmc PLC variables are defined only at enter of realtime) **/ static int safetyEnterRT(){ return validate(); } /** Optional function. * Will be called once just before leaving realtime mode * Return value other than 0 will be considered error. **/ static int safetyExitRT(void){ return 0; } // Register data for plugin so ecmc know what to use static struct ecmcPluginData pluginDataDef = { // Allways use ECMC_PLUG_VERSION_MAGIC .ifVersion = ECMC_PLUG_VERSION_MAGIC, // Name .name = "ecmc_plugin_safety", // Description .desc = "Safety plugin.", // Option description .optionDesc = "\n "ECMC_PLUGIN_DBG_PRINT_OPTION_CMD"<1/0> : Enables/disables printouts from plugin, default = disabled.\n" , // Plugin version .version = ECMC_PLUGIN_VERSION, // Optional construct func, called once at load. NULL if not defined. .constructFnc = construct, // Optional destruct func, called once at unload. NULL if not defined. .destructFnc = safetyDestruct, // Optional func that will be called each rt cycle. NULL if not defined. .realtimeFnc = safetyRealtime, // Optional func that will be called once just before enter realtime mode .realtimeEnterFnc = safetyEnterRT, // Optional func that will be called once just before exit realtime mode .realtimeExitFnc = safetyExitRT, // PLC funcs .funcs[0] = {0}, // last element set all to zero.. // PLC consts .consts[0] = {0}, // last element set all to zero.. }; ecmc_plugin_register(pluginDataDef); # ifdef __cplusplus } # endif // ifdef __cplusplus