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 Luis Jimenez
28 ** @date Wed Sep 26 2007
30 ** @brief Definitions of the functions that manage EMCY (emergency) messages
37 #include "canfestival.h"
42 UNS32 OnNumberOfErrorsUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex);
43 UNS8 sendEMCY(CO_Data* d, UNS16 errCode, UNS8 errRegister);
46 /*! This is called when Index 0x1003 is updated.
50 ** @param unsused_indextable
51 ** @param unsused_bSubindex
55 UNS32 OnNumberOfErrorsUpdate(CO_Data* d, const indextable * unsused_indextable, UNS8 unsused_bSubindex)
58 // if 0, reset Pre-defined Error Field
59 // else, don't change and give an abort message (eeror code: 0609 0030h)
60 if (*d->error_number == 0)
61 for (index = 0; index < d->error_history_size; ++index)
62 *(d->error_first_element + index) = 0; /* clear all the fields in Pre-defined Error Field (1003h) */
68 /*! start the EMCY mangagement.
73 void emergencyInit(CO_Data* d)
75 RegisterSetODentryCallBack(d, 0x1003, 0x00, &OnNumberOfErrorsUpdate);
85 void emergencyStop(CO_Data* d)
98 UNS8 sendEMCY(CO_Data* d, UNS16 errCode, UNS8 errRegister)
102 MSG_WAR(0x3051, "sendEMCY", 0);
104 m.cob_id = UNS16_LE(*(UNS32*)d->error_cobid);
105 m.rtr = NOT_A_REQUEST;
107 m.data[0] = errCode & 0xFF; /* LSB */
108 m.data[1] = (errCode >> 8) & 0xFF; /* MSB */
109 m.data[2] = errRegister;
110 m.data[3] = 0; /* Manufacturer specific Error Field still not implemented */
116 return canSend(d->canHandle,&m);
119 /*! Sets a new error with code errCode. Also sets corresponding bits in Error register (1001h)
123 ** @param errCode Code of the error
124 ** @param errRegister Bits of Error register (1001h) to be set.
125 ** @return 1 if error, 0 if successful
127 UNS8 EMCY_setError(CO_Data* d, UNS16 errCode, UNS8 errRegMask, UNS16 addInfo)
130 UNS8 errRegister_tmp;
132 for (index = 0; index < EMCY_MAX_ERRORS; ++index)
134 if (d->error_data[index].errCode == errCode) /* error already registered */
136 if (d->error_data[index].active)
138 MSG_WAR(0x3052, "EMCY message already sent", 0);
140 } else d->error_data[index].active = 1; /* set as active error */
145 if (index == EMCY_MAX_ERRORS) /* if errCode not already registered */
146 for (index = 0; index < EMCY_MAX_ERRORS; ++index) if (d->error_data[index].active == 0) break; /* find first inactive error */
148 if (index == EMCY_MAX_ERRORS) /* error_data full */
150 MSG_ERR(0x3053, "error_data full", 0);
154 d->error_data[index].errCode = errCode;
155 d->error_data[index].errRegMask = errRegMask;
156 d->error_data[index].active = 1;
158 /* set the new state in the error state machine */
159 d->error_state = Error_occurred;
161 /* set Error Register (1001h) */
162 for (index = 0, errRegister_tmp = 0; index < EMCY_MAX_ERRORS; ++index)
163 if (d->error_data[index].active == 1) errRegister_tmp |= d->error_data[index].errRegMask;
164 *d->error_register = errRegister_tmp;
166 /* set Pre-defined Error Field (1003h) */
167 for (index = d->error_history_size - 1; index > 0; --index)
168 *(d->error_first_element + index) = *(d->error_first_element + index - 1);
169 *(d->error_first_element) = errCode | ((UNS32)addInfo << 16);
170 if(*d->error_number < d->error_history_size) ++(*d->error_number);
172 /* send EMCY message */
173 if (d->CurrentCommunicationState.csEmergency)
174 return sendEMCY(d, errCode, *d->error_register);
178 /*! Deletes error errCode. Also clears corresponding bits in Error register (1001h)
182 ** @param errCode Code of the error
183 ** @param errRegister Bits of Error register (1001h) to be set.
184 ** @return 1 if error, 0 if successful
186 void EMCY_errorRecovered(CO_Data* d, UNS16 errCode)
189 UNS8 errRegister_tmp;
190 UNS8 anyActiveError = 0;
192 for (index = 0; index < EMCY_MAX_ERRORS; ++index)
193 if (d->error_data[index].errCode == errCode) break; /* find the position of the error */
196 if ((index != EMCY_MAX_ERRORS) && (d->error_data[index].active == 1))
198 d->error_data[index].active = 0;
200 /* set Error Register (1001h) and check error state machine */
201 for (index = 0, errRegister_tmp = 0; index < EMCY_MAX_ERRORS; ++index)
202 if (d->error_data[index].active == 1)
205 errRegister_tmp |= d->error_data[index].errRegMask;
207 if(anyActiveError == 0)
209 d->error_state = Error_free;
210 /* send a EMCY message with code "Error Reset or No Error" */
211 if (d->CurrentCommunicationState.csEmergency)
212 sendEMCY(d, 0x0000, 0x00);
214 *d->error_register = errRegister_tmp;
217 MSG_WAR(0x3054, "recovered error was not active", 0);
220 /*! This function is responsible to process an EMCY canopen-message.
224 ** @param m The CAN-message which has to be analysed.
227 void proceedEMCY(CO_Data* d, Message* m)
233 MSG_WAR(0x3055, "EMCY received. Proceed. ", 0);
235 /* Test if the size of the EMCY is ok */
237 MSG_ERR(0x1056, "Error size EMCY. CobId : ", m->cob_id);
241 /* post the received EMCY */
242 nodeID = UNS16_LE(m->cob_id) & 0x7F;
243 errCode = m->data[0] | ((UNS16)m->data[1] << 8);
245 (*d->post_emcy)(d, nodeID, errCode, errReg);
248 void _post_emcy(CO_Data* d, UNS8 nodeID, UNS16 errCode, UNS8 errReg){}