00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00039
00040
00041 #include "globals.h"
00042 #include "master.h"
00043 #include "fsm_change.h"
00044
00045
00046
00047 void ec_fsm_change_state_start(ec_fsm_change_t *);
00048 void ec_fsm_change_state_check(ec_fsm_change_t *);
00049 void ec_fsm_change_state_status(ec_fsm_change_t *);
00050 void ec_fsm_change_state_code(ec_fsm_change_t *);
00051 void ec_fsm_change_state_start_ack(ec_fsm_change_t *);
00052 void ec_fsm_change_state_ack(ec_fsm_change_t *);
00053 void ec_fsm_change_state_check_ack(ec_fsm_change_t *);
00054 void ec_fsm_change_state_end(ec_fsm_change_t *);
00055 void ec_fsm_change_state_error(ec_fsm_change_t *);
00056
00057
00058
00063 void ec_fsm_change_init(ec_fsm_change_t *fsm,
00064 ec_datagram_t *datagram
00065 )
00066 {
00067 fsm->state = NULL;
00068 fsm->datagram = datagram;
00069 }
00070
00071
00072
00077 void ec_fsm_change_clear(ec_fsm_change_t *fsm )
00078 {
00079 }
00080
00081
00082
00087 void ec_fsm_change_start(ec_fsm_change_t *fsm,
00088 ec_slave_t *slave,
00089 ec_slave_state_t state
00090 )
00091 {
00092 fsm->mode = EC_FSM_CHANGE_MODE_FULL;
00093 fsm->slave = slave;
00094 fsm->requested_state = state;
00095 fsm->state = ec_fsm_change_state_start;
00096 }
00097
00098
00099
00104 void ec_fsm_change_ack(ec_fsm_change_t *fsm,
00105 ec_slave_t *slave
00106 )
00107 {
00108 fsm->mode = EC_FSM_CHANGE_MODE_ACK_ONLY;
00109 fsm->slave = slave;
00110 fsm->requested_state = EC_SLAVE_STATE_UNKNOWN;
00111 fsm->state = ec_fsm_change_state_start_ack;
00112 }
00113
00114
00115
00121 int ec_fsm_change_exec(ec_fsm_change_t *fsm )
00122 {
00123 fsm->state(fsm);
00124
00125 return fsm->state != ec_fsm_change_state_end
00126 && fsm->state != ec_fsm_change_state_error;
00127 }
00128
00129
00130
00136 int ec_fsm_change_success(ec_fsm_change_t *fsm )
00137 {
00138 return fsm->state == ec_fsm_change_state_end;
00139 }
00140
00141
00142
00143
00144
00149 void ec_fsm_change_state_start(ec_fsm_change_t *fsm)
00151 {
00152 ec_datagram_t *datagram = fsm->datagram;
00153 ec_slave_t *slave = fsm->slave;
00154
00155 fsm->take_time = 1;
00156 fsm->old_state = fsm->slave->current_state;
00157
00158
00159 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2);
00160 EC_WRITE_U16(datagram->data, fsm->requested_state);
00161 ec_master_queue_datagram(fsm->slave->master, datagram);
00162 fsm->state = ec_fsm_change_state_check;
00163 }
00164
00165
00166
00171 void ec_fsm_change_state_check(ec_fsm_change_t *fsm)
00173 {
00174 ec_datagram_t *datagram = fsm->datagram;
00175 ec_slave_t *slave = fsm->slave;
00176
00177 if (datagram->state != EC_DATAGRAM_RECEIVED) {
00178 fsm->state = ec_fsm_change_state_error;
00179 EC_ERR("Failed to send state datagram to slave %i!\n",
00180 fsm->slave->ring_position);
00181 return;
00182 }
00183
00184 if (fsm->take_time) {
00185 fsm->take_time = 0;
00186 fsm->jiffies_start = datagram->jiffies_sent;
00187 }
00188
00189 if (datagram->working_counter != 1) {
00190 if (datagram->jiffies_received - fsm->jiffies_start >= 3 * HZ) {
00191 char state_str[EC_STATE_STRING_SIZE];
00192 ec_state_string(fsm->requested_state, state_str);
00193 fsm->state = ec_fsm_change_state_error;
00194 EC_ERR("Failed to set state %s on slave %i: Slave did not"
00195 " respond.\n", state_str, fsm->slave->ring_position);
00196 return;
00197 }
00198
00199
00200 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2);
00201 EC_WRITE_U16(datagram->data, fsm->requested_state);
00202 ec_master_queue_datagram(fsm->slave->master, datagram);
00203 return;
00204 }
00205
00206 fsm->take_time = 1;
00207
00208
00209 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
00210 ec_master_queue_datagram(fsm->slave->master, datagram);
00211 fsm->state = ec_fsm_change_state_status;
00212 }
00213
00214
00215
00220 void ec_fsm_change_state_status(ec_fsm_change_t *fsm)
00222 {
00223 ec_datagram_t *datagram = fsm->datagram;
00224 ec_slave_t *slave = fsm->slave;
00225
00226 if (datagram->state != EC_DATAGRAM_RECEIVED
00227 || datagram->working_counter != 1) {
00228 char req_state[EC_STATE_STRING_SIZE];
00229 ec_state_string(fsm->requested_state, req_state);
00230 fsm->state = ec_fsm_change_state_error;
00231 EC_ERR("Failed to check state %s on slave %i.\n",
00232 req_state, slave->ring_position);
00233 return;
00234 }
00235
00236 if (fsm->take_time) {
00237 fsm->take_time = 0;
00238 fsm->jiffies_start = datagram->jiffies_sent;
00239 }
00240
00241 slave->current_state = EC_READ_U8(datagram->data);
00242
00243 if (slave->current_state == fsm->requested_state) {
00244
00245 fsm->state = ec_fsm_change_state_end;
00246 return;
00247 }
00248
00249 if (slave->current_state != fsm->old_state) {
00250 char req_state[EC_STATE_STRING_SIZE], cur_state[EC_STATE_STRING_SIZE];
00251
00252 ec_state_string(slave->current_state, cur_state);
00253
00254 if ((slave->current_state & 0x0F) != (fsm->old_state & 0x0F)) {
00255
00256
00257
00258 fsm->old_state = slave->current_state;
00259 EC_WARN("Slave %i changed to %s in the meantime.\n",
00260 slave->ring_position, cur_state);
00261 goto again;
00262 }
00263
00264
00265
00266 slave->error_flag = 1;
00267 ec_state_string(fsm->requested_state, req_state);
00268
00269 EC_ERR("Failed to set %s state, slave %i refused state change (%s).\n",
00270 req_state, slave->ring_position, cur_state);
00271
00272 ec_datagram_nprd(datagram, slave->station_address, 0x0134, 2);
00273 ec_master_queue_datagram(fsm->slave->master, datagram);
00274 fsm->state = ec_fsm_change_state_code;
00275 return;
00276 }
00277
00278
00279
00280 if (datagram->jiffies_received - fsm->jiffies_start >= HZ) {
00281
00282 char state_str[EC_STATE_STRING_SIZE];
00283 ec_state_string(fsm->requested_state, state_str);
00284 fsm->state = ec_fsm_change_state_error;
00285 EC_ERR("Timeout while setting state %s on slave %i.\n",
00286 state_str, slave->ring_position);
00287 return;
00288 }
00289
00290 again:
00291
00292 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
00293 ec_master_queue_datagram(fsm->slave->master, datagram);
00294 }
00295
00296
00297
00302 const ec_code_msg_t al_status_messages[] = {
00303 {0x0001, "Unspecified error"},
00304 {0x0011, "Invalud requested state change"},
00305 {0x0012, "Unknown requested state"},
00306 {0x0013, "Bootstrap not supported"},
00307 {0x0014, "No valid firmware"},
00308 {0x0015, "Invalid mailbox configuration"},
00309 {0x0016, "Invalid mailbox configuration"},
00310 {0x0017, "Invalid sync manager configuration"},
00311 {0x0018, "No valid inputs available"},
00312 {0x0019, "No valid outputs"},
00313 {0x001A, "Synchronisation error"},
00314 {0x001B, "Sync manager watchdog"},
00315 {0x001C, "Invalid sync manager types"},
00316 {0x001D, "Invalid output configuration"},
00317 {0x001E, "Invalid input configuration"},
00318 {0x001F, "Invalid watchdog configuration"},
00319 {0x0020, "Slave needs cold start"},
00320 {0x0021, "Slave needs INIT"},
00321 {0x0022, "Slave needs PREOP"},
00322 {0x0023, "Slave needs SAVEOP"},
00323 {0x0030, "Invalid DC SYNCH configuration"},
00324 {0x0031, "Invalid DC latch configuration"},
00325 {0x0032, "PLL error"},
00326 {0x0033, "Invalid DC IO error"},
00327 {0x0034, "Invalid DC timeout error"},
00328 {0x0042, "MBOX EOE"},
00329 {0x0043, "MBOX COE"},
00330 {0x0044, "MBOX FOE"},
00331 {0x0045, "MBOX SOE"},
00332 {0x004F, "MBOX VOE"},
00333 {}
00334 };
00335
00336
00337
00342 void ec_fsm_change_state_code(ec_fsm_change_t *fsm)
00344 {
00345 ec_datagram_t *datagram = fsm->datagram;
00346 uint32_t code;
00347 const ec_code_msg_t *al_msg;
00348
00349 if (datagram->state != EC_DATAGRAM_RECEIVED
00350 || datagram->working_counter != 1) {
00351 EC_WARN("Reception of AL status code datagram failed.\n");
00352 }
00353 else {
00354 if ((code = EC_READ_U16(datagram->data))) {
00355 for (al_msg = al_status_messages; al_msg->code; al_msg++) {
00356 if (al_msg->code != code) continue;
00357 EC_ERR("AL status message 0x%04X: \"%s\".\n",
00358 al_msg->code, al_msg->message);
00359 break;
00360 }
00361 if (!al_msg->code)
00362 EC_ERR("Unknown AL status code 0x%04X.\n", code);
00363 }
00364 }
00365
00366
00367 ec_fsm_change_state_start_ack(fsm);
00368 }
00369
00370
00371
00376 void ec_fsm_change_state_start_ack(ec_fsm_change_t *fsm)
00378 {
00379 ec_slave_t *slave = fsm->slave;
00380 ec_datagram_t *datagram = fsm->datagram;
00381
00382 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2);
00383 EC_WRITE_U16(datagram->data, slave->current_state);
00384 ec_master_queue_datagram(fsm->slave->master, datagram);
00385 fsm->state = ec_fsm_change_state_ack;
00386 }
00387
00388
00389
00394 void ec_fsm_change_state_ack(ec_fsm_change_t *fsm )
00395 {
00396 ec_datagram_t *datagram = fsm->datagram;
00397 ec_slave_t *slave = fsm->slave;
00398
00399 if (datagram->state != EC_DATAGRAM_RECEIVED
00400 || datagram->working_counter != 1) {
00401 fsm->state = ec_fsm_change_state_error;
00402 EC_ERR("Reception of state ack datagram failed.\n");
00403 return;
00404 }
00405
00406 fsm->take_time = 1;
00407
00408
00409 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
00410 ec_master_queue_datagram(fsm->slave->master, datagram);
00411 fsm->state = ec_fsm_change_state_check_ack;
00412 }
00413
00414
00415
00420 void ec_fsm_change_state_check_ack(ec_fsm_change_t *fsm)
00422 {
00423 ec_datagram_t *datagram = fsm->datagram;
00424 ec_slave_t *slave = fsm->slave;
00425
00426 if (datagram->state != EC_DATAGRAM_RECEIVED
00427 || datagram->working_counter != 1) {
00428 fsm->state = ec_fsm_change_state_error;
00429 EC_ERR("Reception of state ack check datagram failed.\n");
00430 return;
00431 }
00432
00433 if (fsm->take_time) {
00434 fsm->take_time = 0;
00435 fsm->jiffies_start = datagram->jiffies_sent;
00436 }
00437
00438 slave->current_state = EC_READ_U8(datagram->data);
00439
00440 if (!(slave->current_state & EC_SLAVE_STATE_ACK_ERR)) {
00441 char state_str[EC_STATE_STRING_SIZE];
00442 ec_state_string(slave->current_state, state_str);
00443 if (fsm->mode == EC_FSM_CHANGE_MODE_FULL) {
00444 fsm->state = ec_fsm_change_state_error;
00445 }
00446 else {
00447 fsm->state = ec_fsm_change_state_end;
00448 }
00449 EC_INFO("Acknowledged state %s on slave %i.\n",
00450 state_str, slave->ring_position);
00451 return;
00452 }
00453
00454 if (datagram->jiffies_received - fsm->jiffies_start >= HZ) {
00455
00456 char state_str[EC_STATE_STRING_SIZE];
00457 ec_state_string(slave->current_state, state_str);
00458 fsm->state = ec_fsm_change_state_error;
00459 EC_ERR("Timeout while acknowledging state %s on slave %i.\n",
00460 state_str, slave->ring_position);
00461 return;
00462 }
00463
00464
00465 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
00466 ec_master_queue_datagram(fsm->slave->master, datagram);
00467 }
00468
00469
00470
00475 void ec_fsm_change_state_error(ec_fsm_change_t *fsm)
00477 {
00478 }
00479
00480
00481
00486 void ec_fsm_change_state_end(ec_fsm_change_t *fsm)
00488 {
00489 }
00490
00491