37 #include "canfestival.h" |
37 #include "canfestival.h" |
38 #include "dcf.h" |
38 #include "dcf.h" |
39 #include "sysdep.h" |
39 #include "sysdep.h" |
40 |
40 |
41 |
41 |
42 void ConsumerHearbeatAlarm(CO_Data* d, UNS32 id); |
42 void ConsumerHeartbeatAlarm(CO_Data* d, UNS32 id); |
43 |
43 void ProducerHeartbeatAlarm(CO_Data* d, UNS32 id); |
44 |
44 UNS32 OnHearbeatProducerUpdate(CO_Data* d, const indextable * unused_indextable, UNS8 unused_bSubindex); |
45 void ProducerHearbeatAlarm(CO_Data* d, UNS32 id); |
45 |
46 |
46 void GuardTimeAlarm(CO_Data* d, UNS32 id); |
47 UNS32 OnHearbeatProducerUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex); |
47 UNS32 OnNodeGuardUpdate(CO_Data* d, const indextable * unused_indextable, UNS8 unused_bSubindex); |
48 |
48 |
49 /*! |
49 |
50 ** |
|
51 ** |
|
52 ** @param d |
|
53 ** @param nodeId |
|
54 ** |
|
55 ** @return |
|
56 **/ |
|
57 e_nodeState getNodeState (CO_Data* d, UNS8 nodeId) |
50 e_nodeState getNodeState (CO_Data* d, UNS8 nodeId) |
58 { |
51 { |
59 e_nodeState networkNodeState = Unknown_state; |
52 e_nodeState networkNodeState = Unknown_state; |
60 #if NMT_MAX_NODE_ID>0 |
53 #if NMT_MAX_NODE_ID>0 |
61 if(nodeId < NMT_MAX_NODE_ID) |
54 if(nodeId < NMT_MAX_NODE_ID) |
67 /*! |
60 /*! |
68 ** The Consumer Timer Callback |
61 ** The Consumer Timer Callback |
69 ** |
62 ** |
70 ** @param d |
63 ** @param d |
71 ** @param id |
64 ** @param id |
|
65 * @ingroup heartbeato |
72 **/ |
66 **/ |
73 void ConsumerHearbeatAlarm(CO_Data* d, UNS32 id) |
67 void ConsumerHeartbeatAlarm(CO_Data* d, UNS32 id) |
74 { |
68 { |
75 UNS8 nodeId = (UNS8)(((d->ConsumerHeartbeatEntries[id]) & (UNS32)0x00FF0000) >> (UNS8)16); |
69 UNS8 nodeId = (UNS8)(((d->ConsumerHeartbeatEntries[id]) & (UNS32)0x00FF0000) >> (UNS8)16); |
76 /*MSG_WAR(0x00, "ConsumerHearbeatAlarm", 0x00);*/ |
70 /*MSG_WAR(0x00, "ConsumerHearbeatAlarm", 0x00);*/ |
77 |
71 |
78 /* timer have been notified and is now free (non periodic)*/ |
72 /* timer have been notified and is now free (non periodic)*/ |
131 /* The state is stored on 7 bit */ |
119 /* The state is stored on 7 bit */ |
132 e_nodeState newNodeState = (e_nodeState) ((*m).data[0] & 0x7F); |
120 e_nodeState newNodeState = (e_nodeState) ((*m).data[0] & 0x7F); |
133 |
121 |
134 MSG_WAR(0x3110, "Received NMT nodeId : ", nodeId); |
122 MSG_WAR(0x3110, "Received NMT nodeId : ", nodeId); |
135 |
123 |
|
124 /*! |
|
125 ** Record node response for node guarding service |
|
126 */ |
|
127 d->nodeGuardStatus[nodeId] = *d->LifeTimeFactor; |
|
128 |
136 if (d->NMTable[nodeId] != newNodeState) |
129 if (d->NMTable[nodeId] != newNodeState) |
137 { |
130 { |
138 (*d->post_SlaveStateChange)(d, nodeId, newNodeState); |
131 (*d->post_SlaveStateChange)(d, nodeId, newNodeState); |
139 /* the slave's state receievd is stored in the NMTable */ |
132 /* the slave's state receievd is stored in the NMTable */ |
140 d->NMTable[nodeId] = newNodeState; |
133 d->NMTable[nodeId] = newNodeState; |
152 /* call post SlaveBootup with NodeId */ |
145 /* call post SlaveBootup with NodeId */ |
153 (*d->post_SlaveBootup)(d, nodeId); |
146 (*d->post_SlaveBootup)(d, nodeId); |
154 } |
147 } |
155 |
148 |
156 if( d->NMTable[nodeId] != Unknown_state ) { |
149 if( d->NMTable[nodeId] != Unknown_state ) { |
157 UNS8 index, ConsummerHeartBeat_nodeId ; |
150 UNS8 index, ConsumerHeartBeat_nodeId ; |
158 for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ ) |
151 for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ ) |
159 { |
152 { |
160 ConsummerHeartBeat_nodeId = (UNS8)( ((d->ConsumerHeartbeatEntries[index]) & (UNS32)0x00FF0000) >> (UNS8)16 ); |
153 ConsumerHeartBeat_nodeId = (UNS8)( ((d->ConsumerHeartbeatEntries[index]) & (UNS32)0x00FF0000) >> (UNS8)16 ); |
161 if ( nodeId == ConsummerHeartBeat_nodeId ) |
154 if ( nodeId == ConsumerHeartBeat_nodeId ) |
162 { |
155 { |
163 TIMEVAL time = ( (d->ConsumerHeartbeatEntries[index]) & (UNS32)0x0000FFFF ) ; |
156 TIMEVAL time = ( (d->ConsumerHeartbeatEntries[index]) & (UNS32)0x0000FFFF ) ; |
164 /* Renew alarm for next heartbeat. */ |
157 /* Renew alarm for next heartbeat. */ |
165 DelAlarm(d->ConsumerHeartBeatTimers[index]); |
158 DelAlarm(d->ConsumerHeartBeatTimers[index]); |
166 d->ConsumerHeartBeatTimers[index] = SetAlarm(d, index, &ConsumerHearbeatAlarm, MS_TO_TIMEVAL(time), 0); |
159 d->ConsumerHeartBeatTimers[index] = SetAlarm(d, index, &ConsumerHeartbeatAlarm, MS_TO_TIMEVAL(time), 0); |
167 } |
160 } |
168 } |
161 } |
169 } |
162 } |
170 } |
163 } |
171 } |
164 } |
172 |
165 |
173 /*! The Consumer Timer Callback |
166 /*! The Producer Timer Callback |
174 ** |
167 ** |
175 ** |
168 ** |
176 ** @param d |
169 ** @param d |
177 ** @param id |
170 ** @param id |
|
171 * @ingroup heartbeato |
178 **/ |
172 **/ |
179 void ProducerHearbeatAlarm(CO_Data* d, UNS32 id) |
173 void ProducerHeartbeatAlarm(CO_Data* d, UNS32 id) |
180 { |
174 { |
181 if(*d->ProducerHeartBeatTime) |
175 if(*d->ProducerHeartBeatTime) |
182 { |
176 { |
183 Message msg; |
177 Message msg; |
184 /* Time expired, the heartbeat must be sent immediately |
178 /* Time expired, the heartbeat must be sent immediately |
198 }else{ |
192 }else{ |
199 d->ProducerHeartBeatTimer = DelAlarm(d->ProducerHeartBeatTimer); |
193 d->ProducerHeartBeatTimer = DelAlarm(d->ProducerHeartBeatTimer); |
200 } |
194 } |
201 } |
195 } |
202 |
196 |
|
197 /** |
|
198 * @brief The guardTime - Timer Callback. |
|
199 * |
|
200 * This function is called every GuardTime (OD 0x100C) ms <br> |
|
201 * On every call, a NodeGuard-Request is sent to all nodes which have a |
|
202 * node-state not equal to "Unknown" (according to NMTable). If the node has |
|
203 * not responded within the lifetime, the nodeguardError function is called and |
|
204 * the status of this node is set to "Disconnected" |
|
205 * |
|
206 * @param d Pointer on a CAN object data structure |
|
207 * @param id |
|
208 * @ingroup nodeguardo |
|
209 */ |
|
210 void GuardTimeAlarm(CO_Data* d, UNS32 id) |
|
211 { |
|
212 if (*d->GuardTime) { |
|
213 UNS8 i; |
|
214 |
|
215 MSG_WAR(0x00, "Producing nodeguard-requests: ", 0); |
|
216 |
|
217 for (i = 0; i < NMT_MAX_NODE_ID; i++) { |
|
218 /** Send node guard request to all nodes except this node, if the |
|
219 * node state is not "Unknown_state" |
|
220 */ |
|
221 if (d->NMTable[i] != Unknown_state && i != *d->bDeviceNodeId) { |
|
222 |
|
223 /** Check if the node has confirmed the guarding request within |
|
224 * the LifeTime (GuardTime x LifeTimeFactor) |
|
225 */ |
|
226 if (d->nodeGuardStatus[i] <= 0) { |
|
227 |
|
228 MSG_WAR(0x00, "Node Guard alarm for nodeId : ", i); |
|
229 |
|
230 // Call error-callback function |
|
231 if (*d->nodeguardError) { |
|
232 (*d->nodeguardError)(d, i); |
|
233 } |
|
234 |
|
235 // Mark node as disconnected |
|
236 d->NMTable[i] = Disconnected; |
|
237 |
|
238 } |
|
239 |
|
240 d->nodeGuardStatus[i]--; |
|
241 |
|
242 masterSendNMTnodeguard(d, i); |
|
243 |
|
244 } |
|
245 } |
|
246 } else { |
|
247 d->GuardTimeTimer = DelAlarm(d->GuardTimeTimer); |
|
248 } |
|
249 |
|
250 |
|
251 |
|
252 } |
|
253 |
|
254 /** |
|
255 * This function is called, if index 0x100C or 0x100D is updated to |
|
256 * restart the node-guarding service with the new parameters |
|
257 * |
|
258 * @param d Pointer on a CAN object data structure |
|
259 * @param unused_indextable |
|
260 * @param unused_bSubindex |
|
261 * @ingroup nodeguardo |
|
262 */ |
|
263 UNS32 OnNodeGuardUpdate(CO_Data* d, const indextable * unused_indextable, UNS8 unused_bSubindex) |
|
264 { |
|
265 nodeguardStop(d); |
|
266 nodeguardInit(d); |
|
267 return 0; |
|
268 } |
|
269 |
|
270 |
203 /*! This is called when Index 0x1017 is updated. |
271 /*! This is called when Index 0x1017 is updated. |
204 ** |
272 ** |
205 ** |
273 ** |
206 ** @param d |
274 ** @param d |
207 ** @param unsused_indextable |
275 ** @param unused_indextable |
208 ** @param unsused_bSubindex |
276 ** @param unused_bSubindex |
209 ** |
277 ** |
210 ** @return |
278 ** @return |
|
279 * @ingroup heartbeato |
211 **/ |
280 **/ |
212 UNS32 OnHeartbeatProducerUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex) |
281 UNS32 OnHeartbeatProducerUpdate(CO_Data* d, const indextable * unused_indextable, UNS8 unused_bSubindex) |
213 { |
282 { |
214 heartbeatStop(d); |
283 heartbeatStop(d); |
215 heartbeatInit(d); |
284 heartbeatInit(d); |
216 return 0; |
285 return 0; |
217 } |
286 } |
218 |
287 |
219 /*! |
|
220 ** |
|
221 ** |
|
222 ** @param d |
|
223 **/ |
|
224 void heartbeatInit(CO_Data* d) |
288 void heartbeatInit(CO_Data* d) |
225 { |
289 { |
226 |
290 |
227 UNS8 index; /* Index to scan the table of heartbeat consumers */ |
291 UNS8 index; /* Index to scan the table of heartbeat consumers */ |
228 RegisterSetODentryCallBack(d, 0x1017, 0x00, &OnHeartbeatProducerUpdate); |
292 RegisterSetODentryCallBack(d, 0x1017, 0x00, &OnHeartbeatProducerUpdate); |
230 d->toggle = 0; |
294 d->toggle = 0; |
231 |
295 |
232 for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ ) |
296 for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ ) |
233 { |
297 { |
234 TIMEVAL time = (UNS16) ( (d->ConsumerHeartbeatEntries[index]) & (UNS32)0x0000FFFF ) ; |
298 TIMEVAL time = (UNS16) ( (d->ConsumerHeartbeatEntries[index]) & (UNS32)0x0000FFFF ) ; |
235 /* MSG_WAR(0x3121, "should_time : ", should_time ) ; */ |
|
236 if ( time ) |
299 if ( time ) |
237 { |
300 { |
238 d->ConsumerHeartBeatTimers[index] = SetAlarm(d, index, &ConsumerHearbeatAlarm, MS_TO_TIMEVAL(time), 0); |
301 d->ConsumerHeartBeatTimers[index] = SetAlarm(d, index, &ConsumerHeartbeatAlarm, MS_TO_TIMEVAL(time), 0); |
239 } |
302 } |
240 } |
303 } |
241 |
304 |
242 if ( *d->ProducerHeartBeatTime ) |
305 if ( *d->ProducerHeartBeatTime ) |
243 { |
306 { |
244 TIMEVAL time = *d->ProducerHeartBeatTime; |
307 TIMEVAL time = *d->ProducerHeartBeatTime; |
245 d->ProducerHeartBeatTimer = SetAlarm(d, 0, &ProducerHearbeatAlarm, MS_TO_TIMEVAL(time), MS_TO_TIMEVAL(time)); |
308 d->ProducerHeartBeatTimer = SetAlarm(d, 0, &ProducerHeartbeatAlarm, MS_TO_TIMEVAL(time), MS_TO_TIMEVAL(time)); |
246 } |
309 } |
247 } |
310 } |
248 |
311 |
249 /*! |
312 |
250 ** |
313 void nodeguardInit(CO_Data* d) |
251 ** |
314 { |
252 ** @param d |
315 |
253 **/ |
316 RegisterSetODentryCallBack(d, 0x100C, 0x00, &OnNodeGuardUpdate); |
|
317 RegisterSetODentryCallBack(d, 0x100D, 0x00, &OnNodeGuardUpdate); |
|
318 |
|
319 if (*d->GuardTime && *d->LifeTimeFactor) { |
|
320 UNS8 i; |
|
321 |
|
322 TIMEVAL time = *d->GuardTime; |
|
323 d->GuardTimeTimer = SetAlarm(d, 0, &GuardTimeAlarm, MS_TO_TIMEVAL(time), MS_TO_TIMEVAL(time)); |
|
324 MSG_WAR(0x0, "GuardTime: ", time); |
|
325 |
|
326 for (i = 0; i < NMT_MAX_NODE_ID; i++) { |
|
327 /** Set initial value for the nodes */ |
|
328 if (d->NMTable[i] != Unknown_state && i != *d->bDeviceNodeId) { |
|
329 d->nodeGuardStatus[i] = *d->LifeTimeFactor; |
|
330 } |
|
331 } |
|
332 |
|
333 MSG_WAR(0x0, "Timer for node-guarding startet", 0); |
|
334 } |
|
335 |
|
336 } |
|
337 |
254 void heartbeatStop(CO_Data* d) |
338 void heartbeatStop(CO_Data* d) |
255 { |
339 { |
256 UNS8 index; |
340 UNS8 index; |
257 for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ ) |
341 for( index = (UNS8)0x00; index < *d->ConsumerHeartbeatCount; index++ ) |
258 { |
342 { |
260 } |
344 } |
261 |
345 |
262 d->ProducerHeartBeatTimer = DelAlarm(d->ProducerHeartBeatTimer); |
346 d->ProducerHeartBeatTimer = DelAlarm(d->ProducerHeartBeatTimer); |
263 } |
347 } |
264 |
348 |
265 /*! |
349 void nodeguardStop(CO_Data* d) |
266 ** |
350 { |
267 ** |
351 d->GuardTimeTimer = DelAlarm(d->GuardTimeTimer); |
268 ** @param heartbeatID |
352 } |
269 **/ |
353 |
|
354 |
|
355 void lifeGuardInit(CO_Data* d) |
|
356 { |
|
357 heartbeatInit(d); |
|
358 nodeguardInit(d); |
|
359 } |
|
360 |
|
361 |
|
362 void lifeGuardStop(CO_Data* d) |
|
363 { |
|
364 heartbeatStop(d); |
|
365 nodeguardStop(d); |
|
366 } |
|
367 |
|
368 |
270 void _heartbeatError(CO_Data* d, UNS8 heartbeatID){} |
369 void _heartbeatError(CO_Data* d, UNS8 heartbeatID){} |
271 void _post_SlaveBootup(CO_Data* d, UNS8 SlaveID){} |
370 void _post_SlaveBootup(CO_Data* d, UNS8 SlaveID){} |
272 void _post_SlaveStateChange(CO_Data* d, UNS8 nodeId, e_nodeState newNodeState){} |
371 void _post_SlaveStateChange(CO_Data* d, UNS8 nodeId, e_nodeState newNodeState){} |
273 |
372 void _nodeguardError(CO_Data* d, UNS8 id){} |
|
373 |