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