examples/AppliSlave_Linux/appli.c
changeset 93 16c8ceea8f18
parent 92 0d84d95790d9
child 94 bdf4c86be6b2
equal deleted inserted replaced
92:0d84d95790d9 93:16c8ceea8f18
     1 /*
       
     2 This file is part of CanFestival, a library implementing CanOpen Stack. 
       
     3 
       
     4 Copyright (C): Edouard TISSERANT and Francis DUPIN
       
     5 
       
     6 See COPYING file for copyrights details.
       
     7 
       
     8 This library is free software; you can redistribute it and/or
       
     9 modify it under the terms of the GNU Lesser General Public
       
    10 License as published by the Free Software Foundation; either
       
    11 version 2.1 of the License, or (at your option) any later version.
       
    12 
       
    13 This library is distributed in the hope that it will be useful,
       
    14 but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    16 Lesser General Public License for more details.
       
    17 
       
    18 You should have received a copy of the GNU Lesser General Public
       
    19 License along with this library; if not, write to the Free Software
       
    20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    21 */
       
    22 
       
    23 #include <stdio.h>
       
    24 #include <string.h>
       
    25 #include <unistd.h>
       
    26 #include <stdlib.h>
       
    27 #include <time.h>
       
    28 #include <pthread.h>
       
    29 
       
    30 #include <applicfg.h>
       
    31 #include <timerhw.h>
       
    32 #include <linuxCan.h>
       
    33 
       
    34 #include "def.h"
       
    35 #include "can.h"
       
    36 #include "canOpenDriver.h"
       
    37 #include "sdo.h"
       
    38 #include "pdo.h"
       
    39 #include "init.h"
       
    40 #include "timer.h"
       
    41 #include "lifegrd.h"
       
    42 
       
    43 #include "nmtSlave.h"
       
    44 
       
    45 // Adlink 7841 or Peak PCI/CAN board
       
    46 // ---------------------------------
       
    47 
       
    48 // Baudrate values for Peak board :
       
    49 // CAN_BAUD_1M CAN_BAUD_500K CAN_BAUD_250K CAN_BAUD_125K CAN_BAUD_100K CAN_BAUD_50K
       
    50 // CAN_BAUD_20K CAN_BAUD_10K CAN_BAUD_5K
       
    51 
       
    52 #ifdef CAN_BAUD_250K
       
    53 # define BAUDRATE CAN_BAUD_250K
       
    54 #else
       
    55 // Appli have been compiled for Adlink-arbraca. Baudrate not used
       
    56 # define BAUDRATE 0
       
    57 #endif
       
    58 
       
    59 s_BOARD board = {"1", BAUDRATE};
       
    60 
       
    61 
       
    62 // The variables sent or updated by PDO
       
    63 // -----------------------------------------------------
       
    64 extern UNS8 seconds;		// Mapped at index 0x2000, subindex 0x1
       
    65 extern UNS8 minutes;		// Mapped at index 0x2000, subindex 0x2
       
    66 extern UNS8 hours;		// Mapped at index 0x2000, subindex 0x3
       
    67 extern UNS8 day;		// Mapped at index 0x2000, subindex 0x4
       
    68 extern UNS32 canopenErrNB;	// Mapped at index 0x6000, subindex 0x0
       
    69 extern UNS32 canopenErrVAL;	// Mapped at index 0x6001, subindex 0x0
       
    70 
       
    71 // Required definition variables
       
    72 // -----------------------------
       
    73 // The variables that you should define for debugging.
       
    74 // They are used by the macro MSG_ERR and MSG_WAR in applicfg.h
       
    75 // if the node is a slave, they can be mapped in the object dictionnary.
       
    76 // if not null, allow the printing of message to the console
       
    77 // Could be managed by PDO
       
    78 UNS8 printMsgErrToConsole = 1;
       
    79 UNS8 printMsgWarToConsole = 1;
       
    80 
       
    81 
       
    82 
       
    83 /*************************User's variables declaration**************************/
       
    84 struct tm date;
       
    85 struct tm *ptrdate;
       
    86 struct tm date_prec;
       
    87 time_t  tme;
       
    88 UNS8 lastSecond;
       
    89 e_nodeState lastState;
       
    90 pthread_t threadRcvMsg;
       
    91 pthread_t threadHeartbeatAndSDO;
       
    92 UNS8 sendingError = 0;
       
    93 
       
    94 
       
    95 /******************************prototypes*****************************/
       
    96 /* You *must* have these 2 functions in your code*/
       
    97 void heartbeatError(UNS8 heartbeatID);
       
    98 void SD0timeoutError(UNS8 bus_id, UNS8 line);
       
    99 
       
   100 UNS8 scanSDOtimeout(void);
       
   101 void preOperational(void);
       
   102 void operational(void); 
       
   103 void stopped(void);
       
   104 void waitMessage(void);
       
   105 void waitMessage_heartbeat(void);
       
   106 
       
   107 /*********************************************************************/
       
   108 void heartbeatError(UNS8 heartbeatID)
       
   109 {
       
   110   MSG_ERR(0x1F00, "!!! No heart beat received from node : ", heartbeatID);
       
   111 }
       
   112 
       
   113 /*****************************************************************************/
       
   114 void SD0timeoutError (UNS8 bus_id, UNS8 line)
       
   115 {
       
   116   // Informations on what occurs are in transfers[bus_id][line]....
       
   117   // See scanSDOtimeout() in sdo.c
       
   118 }
       
   119 
       
   120 /*********************************** THREADS **********************************/
       
   121 //------------------------------------------------------------------------------
       
   122 // Wait for a received message
       
   123 void waitMessage( void )
       
   124 {       
       
   125   while (1) {
       
   126     receiveMsgHandler(0); // blocked until new message
       
   127   }
       
   128 }
       
   129 
       
   130 //------------------------------------------------------------------------------
       
   131 // Heartbeat Manager (sending and receiving) and test SDO timeout
       
   132 void heartbeatAndSDO(void)
       
   133 {
       
   134   while (1) {
       
   135     heartbeatMGR();
       
   136     // Check if some SDO response are missing
       
   137     scanSDOtimeout();
       
   138     // Sleep 10 ms
       
   139     usleep(10000);	
       
   140   }
       
   141 }
       
   142 
       
   143 /*********************************************************************/
       
   144 void preOperational( void )
       
   145 {	
       
   146   /* Init some variables */
       
   147   canopenErrNB = 0;
       
   148   canopenErrVAL = 0;
       
   149 }
       
   150 
       
   151 
       
   152 /********************************************************************/
       
   153 void operational( void )
       
   154 {
       
   155   /* read systeme date */
       
   156   tme = time (&tme);
       
   157   ptrdate = gmtime(&tme);
       
   158   date = *ptrdate;
       
   159   
       
   160   /* Update the dictionary */
       
   161   day = date.tm_mday;
       
   162   hours = date.tm_hour;
       
   163   minutes = date.tm_min;
       
   164   seconds = date.tm_sec;
       
   165   
       
   166 
       
   167   if ( date_prec.tm_min != date.tm_min ) {
       
   168     MSG_WAR(0x3F00, "event : minutes change -> node decides to send it. Value : ", date.tm_min);
       
   169     sendPDOevent( 0, &minutes );
       
   170     date_prec = date;
       
   171   }
       
   172   if (canopenErrNB == 0)
       
   173     sendingError = 0;
       
   174 
       
   175   if (lastSecond != seconds) {
       
   176     MSG_WAR (0x3F50, "Seconds = ", seconds);
       
   177     if ((seconds == 50) && (sendingError == 0))
       
   178       {
       
   179 	MSG_ERR(0x1F55, "DEMO of ERROR. Sent by PDO. Value : ", 0xABCD);
       
   180 	sendingError = 1;
       
   181       }
       
   182     
       
   183     if (canopenErrNB) {
       
   184       MSG_WAR(0x3F56, "ERROR nb : ",  canopenErrNB);
       
   185     }
       
   186     lastSecond = seconds;
       
   187     
       
   188   }
       
   189 }
       
   190 
       
   191 
       
   192 /*****************************************************************************/
       
   193 void stopped( void )
       
   194 {
       
   195 }
       
   196 
       
   197 void help()
       
   198 {
       
   199   printf("**************************************************************\n");
       
   200   printf("*  AppliSlave                                                *\n");
       
   201   printf("*                [-b b]                                      *\n");
       
   202   printf("*                                                            *\n");
       
   203   printf("*     b : bus [default 1]                                    *\n");
       
   204   printf("*                                                            *\n");
       
   205   printf("*  This exemple run AppliSlave on bus 0                      *\n");
       
   206   printf("*   AppliSlave -b 0                                          *\n");
       
   207   printf("*                                                            *\n");
       
   208   printf("**************************************************************\n");
       
   209 }
       
   210 
       
   211 /****************************************************************************/
       
   212 /***************************  MAIN  *****************************************/
       
   213 /****************************************************************************/
       
   214 int main(int argc,char **argv)
       
   215 {
       
   216 
       
   217   HANDLE ok;
       
   218   UNS32 *    pSize;
       
   219   UNS32      size;
       
   220   pSize = &size;
       
   221   char c;
       
   222   extern char *optarg;
       
   223 
       
   224   while ((c = getopt(argc, argv, "-b:")) != EOF)
       
   225   {
       
   226     switch(c)
       
   227     {
       
   228       case 'b' :
       
   229         if (optarg[0] == 0)
       
   230         {
       
   231           help();
       
   232           exit(1);
       
   233         }
       
   234         board.busname = optarg;
       
   235         break;
       
   236       default:
       
   237         help();
       
   238         exit(1);
       
   239     }
       
   240   }
       
   241 
       
   242   // Global initialization before launching the threads. (also done in init mode.
       
   243   /* Defining the node Id */
       
   244   setNodeId(0x05);
       
   245   MSG_WAR(0x3F06, "My node ID is : ", getNodeId()); 
       
   246   initCANopenMain();
       
   247   initTimer( );
       
   248   heartbeatInit();
       
   249   initResetMode();
       
   250 
       
   251   /* Launch the thread to receive the messages */
       
   252   pthread_create( &threadRcvMsg, NULL, (void *)&waitMessage, NULL); 
       
   253   /* Launch the thread to manage the heartbeat */
       
   254   pthread_create( &threadHeartbeatAndSDO, NULL, (void *)&heartbeatAndSDO, NULL); 
       
   255 
       
   256   /* open the communication with the board */
       
   257   ok = f_can_open(& board);
       
   258   if (ok == NULL) {
       
   259     MSG_ERR(0x1F02,"Unable to open the board", 0);
       
   260     MSG_ERR(0x1F03,"Edit includeMakefileLinux to verify that the application is configured for the good board", 0);
       
   261     exit (-1);
       
   262   }
       
   263   else {
       
   264     MSG_WAR(0x3F03, "Board 1 opened ", 0);
       
   265     /* slave's state initialization */
       
   266     setState(Initialisation);
       
   267     lastState = Unknown_state;
       
   268 
       
   269 
       
   270     while(1) { /* slave's state machine */
       
   271       switch( getState() ) {	
       
   272       case Initialisation:
       
   273 	if (lastState != getState()) 
       
   274 	  MSG_WAR(0X3F05, "I am in INITIALISATION mode ", 0);
       
   275         /* Defining the node Id */
       
   276 	setNodeId(0x05);
       
   277 	MSG_WAR(0x3F06, "My node ID is : ", getNodeId()); 
       
   278 	  // Node identity ?
       
   279 	{
       
   280 	  UNS8 *data;
       
   281 	  UNS8 size;
       
   282 	  UNS8 dataType;
       
   283 	  // Manufacturer Device name (default = empty string)
       
   284 	  getODentry(0x1008, 0x0, (void **)&data, &size, &dataType, 0);
       
   285 	  MSG_WAR(0x3F09, data, 0);
       
   286 	  // Manufacturer Hardware version. (default = compilation. date)
       
   287 	  getODentry(0x1009, 0x0, (void **)&data, &size, &dataType, 0);
       
   288 	  MSG_WAR(0x3F09, data, 0);
       
   289 	  // Manufacturer Software version. (default = compilation. time)
       
   290 	  getODentry(0x100A, 0x0, (void **)&data, &size, &dataType, 0);
       
   291 	  MSG_WAR(0x3F09, data, 0);
       
   292 	}
       
   293 
       
   294 	initCANopenMain();
       
   295 	initTimer( );
       
   296 	heartbeatInit();
       
   297 	initResetMode();
       
   298 	/* the slave send an NMT trame to say to the master 
       
   299 	   that it is going to enter into operational state 
       
   300 	   In fact, you must send the boot-up when you are in 
       
   301 	   operational mode !
       
   302 	*/
       
   303   
       
   304 	/* change automatically into pre_operational state */ 
       
   305 	lastState = getState();
       
   306 	setState(Pre_operational);
       
   307 	break;
       
   308 					
       
   309       case Pre_operational:
       
   310 	if (lastState != getState())
       
   311 	  {
       
   312 	  MSG_WAR(0X3F11, "I am in PRE_OPERATIONAL mode ", 0);
       
   313 	  // Some stuff to do when the node enter in pre-operational mode
       
   314 	  initPreOperationalMode();
       
   315 	  }
       
   316 	if (lastState == Initialisation)
       
   317 	  slaveSendBootUp(0);
       
   318 	lastState = getState();
       
   319 	preOperational( );	
       
   320 	break;
       
   321 					
       
   322       case Operational:
       
   323 	if (lastState != getState())
       
   324 	  MSG_WAR(0X3F12, "I am in OPERATIONAL mode ", 0);
       
   325 	lastState = getState();
       
   326 	operational( );
       
   327 	break;
       
   328 			
       
   329       case Stopped:
       
   330 	if (lastState !=  getState())
       
   331 	  MSG_WAR(0X3F13, "I am in STOPPED mode", 0);
       
   332 	lastState = getState();
       
   333 	stopped( );
       
   334 	break;
       
   335       }//end switch case
       
   336       // Sleep 10 ms
       
   337       usleep(10000);	
       
   338     }//end while
       
   339   }//end else
       
   340 
       
   341  
       
   342   return 0;	
       
   343 }
       
   344