2 This file is part of CanFestival, a library implementing CanOpen
5 Copyright (C): Edouard TISSERANT and Francis DUPIN
7 See COPYING file for copyrights details.
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 ** @author Edouard TISSERANT
28 ** @date Mon Jun 4 17:19:24 2007
37 #include "canfestival.h"
42 void ConsumerHearbeatAlarm(CO_Data* d, UNS32 id);
45 void ProducerHearbeatAlarm(CO_Data* d, UNS32 id);
47 UNS32 OnHearbeatProducerUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex);
57 e_nodeState getNodeState (CO_Data* d, UNS8 nodeId)
59 e_nodeState networkNodeState = d->NMTable[nodeId];
60 return networkNodeState;
64 ** The Consumer Timer Callback
69 void ConsumerHearbeatAlarm(CO_Data* d, UNS32 id)
71 /*MSG_WAR(0x00, "ConsumerHearbeatAlarm", 0x00);*/
73 /* timer have been notified and is now free (non periodic)*/
74 /* -> avoid deleting re-assigned timer if message is received too late*/
75 d->ConsumerHeartBeatTimers[id]=TIMER_NONE;
76 /*! call heartbeat error with NodeId */
77 (*d->heartbeatError)(d, (UNS8)( ((d->ConsumerHeartbeatEntries[id]) & (UNS32)0x00FF0000) >> (UNS8)16 ));
86 void proceedNODE_GUARD(CO_Data* d, Message* m )
88 UNS8 nodeId = (UNS8) GET_NODE_ID((*m));
92 ** Notice that only the master can have sent this
93 ** node guarding request
97 ** Receiving a NMT NodeGuarding (request of the state by the
99 ** Only answer to the NMT NodeGuarding request, the master is
100 ** not checked (not implemented)
102 if (nodeId == *d->bDeviceNodeId )
105 UNS16 tmp = *d->bDeviceNodeId + 0x700;
106 msg.cob_id = UNS16_LE(tmp);
107 msg.len = (UNS8)0x01;
109 msg.data[0] = d->nodeState;
112 msg.data[0] |= 0x80 ;
117 /* send the nodeguard response. */
118 MSG_WAR(0x3130, "Sending NMT Nodeguard to master, state: ", d->nodeState);
119 canSend(d->canHandle,&msg );
122 }else{ /* Not a request CAN */
124 MSG_WAR(0x3110, "Received NMT nodeId : ", nodeId);
125 /* the slave's state receievd is stored in the NMTable */
126 /* The state is stored on 7 bit */
127 d->NMTable[nodeId] = (e_nodeState) ((*m).data[0] & 0x7F) ;
129 /* Boot-Up frame reception */
130 if ( d->NMTable[nodeId] == Initialisation)
133 ** The device send the boot-up message (Initialisation)
134 ** to indicate the master that it is entered in
135 ** pre_operational mode
136 ** Because the device enter automaticaly in pre_operational
138 ** the pre_operational mode is stored
139 ** NMTable[bus_id][nodeId] = Pre_operational
141 MSG_WAR(0x3100, "The NMT is a bootup from node : ", nodeId);
143 if(!send_consise_dcf(d,nodeId)){
144 /* call post SlaveBootup with NodeId */
145 (*d->post_SlaveBootup)(d, nodeId);
149 if( d->NMTable[nodeId] != Unknown_state ) {
150 UNS8 index, ConsummerHeartBeat_nodeId ;
151 for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ )
153 ConsummerHeartBeat_nodeId = (UNS8)( ((d->ConsumerHeartbeatEntries[index]) & (UNS32)0x00FF0000) >> (UNS8)16 );
154 if ( nodeId == ConsummerHeartBeat_nodeId )
156 TIMEVAL time = ( (d->ConsumerHeartbeatEntries[index]) & (UNS32)0x0000FFFF ) ;
157 /* Renew alarm for next heartbeat. */
158 DelAlarm(d->ConsumerHeartBeatTimers[index]);
159 d->ConsumerHeartBeatTimers[index] = SetAlarm(d, index, &ConsumerHearbeatAlarm, MS_TO_TIMEVAL(time), 0);
166 /*! The Consumer Timer Callback
172 void ProducerHearbeatAlarm(CO_Data* d, UNS32 id)
174 if(*d->ProducerHeartBeatTime)
177 /* Time expired, the heartbeat must be sent immediately
178 ** generate the correct node-id: this is done by the offset 1792
179 ** (decimal) and additionaly
180 ** the node-id of this device.
182 UNS16 tmp = *d->bDeviceNodeId + 0x700;
183 msg.cob_id = UNS16_LE(tmp);
184 msg.len = (UNS8)0x01;
186 msg.data[0] = d->nodeState; /* No toggle for heartbeat !*/
187 /* send the heartbeat */
188 MSG_WAR(0x3130, "Producing heartbeat: ", d->nodeState);
189 canSend(d->canHandle,&msg );
192 d->ProducerHeartBeatTimer = DelAlarm(d->ProducerHeartBeatTimer);
196 /*! This is called when Index 0x1017 is updated.
200 ** @param unsused_indextable
201 ** @param unsused_bSubindex
205 UNS32 OnHeartbeatProducerUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex)
217 void heartbeatInit(CO_Data* d)
220 UNS8 index; /* Index to scan the table of heartbeat consumers */
221 RegisterSetODentryCallBack(d, 0x1017, 0x00, &OnHeartbeatProducerUpdate);
225 for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ )
227 TIMEVAL time = (UNS16) ( (d->ConsumerHeartbeatEntries[index]) & (UNS32)0x0000FFFF ) ;
228 /* MSG_WAR(0x3121, "should_time : ", should_time ) ; */
231 d->ConsumerHeartBeatTimers[index] = SetAlarm(d, index, &ConsumerHearbeatAlarm, MS_TO_TIMEVAL(time), 0);
235 if ( *d->ProducerHeartBeatTime )
237 TIMEVAL time = *d->ProducerHeartBeatTime;
238 d->ProducerHeartBeatTimer = SetAlarm(d, 0, &ProducerHearbeatAlarm, MS_TO_TIMEVAL(time), MS_TO_TIMEVAL(time));
247 void heartbeatStop(CO_Data* d)
250 for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ )
252 d->ConsumerHeartBeatTimers[index] = DelAlarm(d->ConsumerHeartBeatTimers[index]);
255 d->ProducerHeartBeatTimer = DelAlarm(d->ProducerHeartBeatTimer);
261 ** @param heartbeatID
263 void _heartbeatError(CO_Data* d, UNS8 heartbeatID){}
264 void _post_SlaveBootup(CO_Data* d, UNS8 SlaveID){}