etisserant@52: etisserant@52: #include "canfestival.h" etisserant@52: etisserant@178: /* CanFestival nodes generated OD headers*/ etisserant@52: %(nodes_includes)s etisserant@52: etisserant@52: #define BOARD_DECL(nodename, busname, baudrate)\ etisserant@52: s_BOARD nodename##Board = {busname, baudrate}; etisserant@52: etisserant@178: /* CAN channels declaration */ etisserant@52: %(board_decls)s etisserant@52: etisserant@178: /* Keep track of init level to cleanup correctly */ etisserant@52: static int init_level=0; etisserant@178: /* Retrieve PLC cycle time */ etisserant@57: extern int common_ticktime__; etisserant@52: etisserant@178: /* Called once all NetworkEdit declares slaves have booted*/ greg@160: static void Master_post_SlaveBootup(CO_Data* d, UNS8 nodeId) etisserant@59: { etisserant@59: /* Put the master in operational mode */ etisserant@59: setState(d, Operational); etisserant@59: etisserant@59: /* Ask slave node to go in operational mode */ etisserant@59: masterSendNMTstateChange (d, 0, NMT_Start_Node); etisserant@59: } etisserant@59: etisserant@178: /* Per master node slavebootup callbacks. Checks that etisserant@178: * every node have booted before calling Master_post_SlaveBootup */ etisserant@169: %(slavebootups)s etisserant@169: etisserant@178: /* One slave node post_sync callback. etisserant@178: * Used to align PLC tick-time on CANopen SYNC etisserant@178: */ etisserant@178: %(post_sync)s etisserant@178: etisserant@178: #define NODE_FORCE_SYNC(nodename) \ etisserant@57: /* Artificially force sync state to 1 so that it is not started */\ etisserant@57: nodename##_Data.CurrentCommunicationState.csSYNC = -1;\ etisserant@57: /* Force sync period to common_ticktime__ so that other node can read it*/\ etisserant@57: *nodename##_Data.COB_ID_Sync = 0x40000080;\ etisserant@178: *nodename##_Data.Sync_Cycle_Period = common_ticktime__ * 1000; etisserant@178: etisserant@178: #define NODE_INIT(nodename, nodeid) \ etisserant@52: /* Defining the node Id */\ etisserant@52: setNodeId(&nodename##_Data, nodeid);\ etisserant@52: /* init */\ etisserant@52: setState(&nodename##_Data, Initialisation); etisserant@52: etisserant@178: #define NODE_MASTER_INIT(nodename, nodeid) \ etisserant@178: NODE_FORCE_SYNC(nodename) \ etisserant@178: NODE_INIT(nodename, nodeid) etisserant@178: etisserant@178: #define NODE_SLAVE_INIT(nodename, nodeid) \ etisserant@178: NODE_INIT(nodename, nodeid) etisserant@178: etisserant@52: void InitNodes(CO_Data* d, UNS32 id) etisserant@52: { etisserant@178: %(slavebootup_register)s etisserant@178: %(post_sync_register)s etisserant@52: %(nodes_init)s etisserant@52: } etisserant@52: greg@144: void Exit(CO_Data* d, UNS32 id) greg@144: { greg@144: } greg@144: etisserant@52: #define NODE_CLOSE(nodename) \ etisserant@57: if(init_level-- > 0)\ etisserant@52: {\ etisserant@52: EnterMutex();\ greg@160: masterSendNMTstateChange(&nodename##_Data, 0, NMT_Reset_Node);\ etisserant@52: setState(&nodename##_Data, Stopped);\ etisserant@52: LeaveMutex();\ etisserant@52: canClose(&nodename##_Data);\ etisserant@52: } etisserant@52: etisserant@52: void __cleanup_%(locstr)s() etisserant@52: { etisserant@52: // Stop timer thread etisserant@203: if(init_level-- > 0){ greg@144: StopTimerLoop(&Exit); etisserant@203: %(nodes_close)s etisserant@203: } etisserant@156: #if !defined(WIN32) || defined(__CYGWIN__) etisserant@156: TimerCleanup(); etisserant@156: #endif etisserant@52: } etisserant@52: etisserant@52: #define NODE_OPEN(nodename)\ etisserant@52: if(!canOpen(&nodename##Board,&nodename##_Data)){\ etisserant@52: printf("Cannot open " #nodename " Board (%%s,%%s)\n",nodename##Board.busname, nodename##Board.baudrate);\ etisserant@52: return -1;\ etisserant@52: }\ etisserant@52: init_level++; etisserant@52: etisserant@52: /*************************** INIT *****************************************/ etisserant@52: int __init_%(locstr)s(int argc,char **argv) etisserant@52: { etisserant@57: #ifndef NOT_USE_DYNAMIC_LOADING etisserant@75: if( !LoadCanDriver("%(candriver)s") ){ etisserant@57: fprintf(stderr, "Cannot load CAN interface library for CanFestival (%(candriver)s)\n");\ etisserant@57: return -1; etisserant@57: } etisserant@57: #endif etisserant@156: #if !defined(WIN32) || defined(__CYGWIN__) etisserant@156: TimerInit(); etisserant@156: #endif etisserant@156: etisserant@52: %(nodes_open)s etisserant@52: etisserant@52: // Start timer thread etisserant@52: StartTimerLoop(&InitNodes); etisserant@57: init_level++; etisserant@52: return 0; etisserant@52: } etisserant@52: etisserant@57: #define NODE_SEND_SYNC(nodename)\ etisserant@57: sendSYNCMessage(&nodename##_Data); etisserant@57: lbessard@137: void __retrieve_%(locstr)s() etisserant@52: { etisserant@57: /* Locks the stack, so that no changes occurs while PLC access variables etisserant@57: * TODO : implement buffers to avoid such a big lock etisserant@57: * */ etisserant@52: EnterMutex(); etisserant@178: /* Send Sync */ etisserant@57: %(nodes_send_sync)s etisserant@52: } etisserant@52: etisserant@57: #define NODE_PROCEED_SYNC(nodename)\ etisserant@57: proceedSYNC(&nodename##_Data); etisserant@57: etisserant@52: void __publish_%(locstr)s() etisserant@52: { etisserant@178: /* Process sync event */ etisserant@57: %(nodes_proceed_sync)s etisserant@52: LeaveMutex(); etisserant@52: } etisserant@52: