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
00034
00035
00036 #include "globals.h"
00037 #include "master.h"
00038 #include "mailbox.h"
00039 #include "slave_config.h"
00040
00041 #include "fsm_pdo_entry.h"
00042
00043
00044
00045 void ec_fsm_pdo_entry_read_state_start(ec_fsm_pdo_entry_t *, ec_datagram_t *);
00046 void ec_fsm_pdo_entry_read_state_count(ec_fsm_pdo_entry_t *, ec_datagram_t *);
00047 void ec_fsm_pdo_entry_read_state_entry(ec_fsm_pdo_entry_t *, ec_datagram_t *);
00048
00049 void ec_fsm_pdo_entry_read_action_next(ec_fsm_pdo_entry_t *, ec_datagram_t *);
00050
00051 void ec_fsm_pdo_entry_conf_state_start(ec_fsm_pdo_entry_t *, ec_datagram_t *);
00052 void ec_fsm_pdo_entry_conf_state_zero_entry_count(ec_fsm_pdo_entry_t *,
00053 ec_datagram_t *);
00054 void ec_fsm_pdo_entry_conf_state_map_entry(ec_fsm_pdo_entry_t *,
00055 ec_datagram_t *);
00056 void ec_fsm_pdo_entry_conf_state_set_entry_count(ec_fsm_pdo_entry_t *,
00057 ec_datagram_t *);
00058
00059 void ec_fsm_pdo_entry_conf_action_map(ec_fsm_pdo_entry_t *, ec_datagram_t *);
00060
00061 void ec_fsm_pdo_entry_state_end(ec_fsm_pdo_entry_t *, ec_datagram_t *);
00062 void ec_fsm_pdo_entry_state_error(ec_fsm_pdo_entry_t *, ec_datagram_t *);
00063
00064
00065
00068 void ec_fsm_pdo_entry_init(
00069 ec_fsm_pdo_entry_t *fsm,
00070 ec_fsm_coe_t *fsm_coe
00071 )
00072 {
00073 fsm->fsm_coe = fsm_coe;
00074 ec_sdo_request_init(&fsm->request);
00075 }
00076
00077
00078
00081 void ec_fsm_pdo_entry_clear(
00082 ec_fsm_pdo_entry_t *fsm
00083 )
00084 {
00085 ec_sdo_request_clear(&fsm->request);
00086 }
00087
00088
00089
00092 void ec_fsm_pdo_entry_print(
00093 ec_fsm_pdo_entry_t *fsm
00094 )
00095 {
00096 printk("Currently mapped PDO entries: ");
00097 ec_pdo_print_entries(fsm->cur_pdo);
00098 printk(". Entries to map: ");
00099 ec_pdo_print_entries(fsm->source_pdo);
00100 printk("\n");
00101 }
00102
00103
00104
00107 void ec_fsm_pdo_entry_start_reading(
00108 ec_fsm_pdo_entry_t *fsm,
00109 ec_slave_t *slave,
00110 ec_pdo_t *pdo
00111 )
00112 {
00113 fsm->slave = slave;
00114 fsm->target_pdo = pdo;
00115
00116 ec_pdo_clear_entries(fsm->target_pdo);
00117
00118 fsm->state = ec_fsm_pdo_entry_read_state_start;
00119 }
00120
00121
00122
00125 void ec_fsm_pdo_entry_start_configuration(
00126 ec_fsm_pdo_entry_t *fsm,
00127 ec_slave_t *slave,
00128 const ec_pdo_t *pdo,
00129 const ec_pdo_t *cur_pdo
00130 )
00131 {
00132 fsm->slave = slave;
00133 fsm->source_pdo = pdo;
00134 fsm->cur_pdo = cur_pdo;
00135
00136 if (fsm->slave->master->debug_level) {
00137 EC_SLAVE_DBG(slave, 1, "Changing mapping of PDO 0x%04X.\n",
00138 pdo->index);
00139 EC_SLAVE_DBG(slave, 1, ""); ec_fsm_pdo_entry_print(fsm);
00140 }
00141
00142 fsm->state = ec_fsm_pdo_entry_conf_state_start;
00143 }
00144
00145
00146
00151 int ec_fsm_pdo_entry_running(
00152 const ec_fsm_pdo_entry_t *fsm
00153 )
00154 {
00155 return fsm->state != ec_fsm_pdo_entry_state_end
00156 && fsm->state != ec_fsm_pdo_entry_state_error;
00157 }
00158
00159
00160
00165 int ec_fsm_pdo_entry_exec(
00166 ec_fsm_pdo_entry_t *fsm,
00167 ec_datagram_t *datagram
00168 )
00169 {
00170 fsm->state(fsm, datagram);
00171
00172 return ec_fsm_pdo_entry_running(fsm);
00173 }
00174
00175
00176
00181 int ec_fsm_pdo_entry_success(
00182 const ec_fsm_pdo_entry_t *fsm
00183 )
00184 {
00185 return fsm->state == ec_fsm_pdo_entry_state_end;
00186 }
00187
00188
00189
00190
00191
00194 void ec_fsm_pdo_entry_read_state_start(
00195 ec_fsm_pdo_entry_t *fsm,
00196 ec_datagram_t *datagram
00197 )
00198 {
00199 ecrt_sdo_request_index(&fsm->request, fsm->target_pdo->index, 0);
00200 ecrt_sdo_request_read(&fsm->request);
00201
00202 fsm->state = ec_fsm_pdo_entry_read_state_count;
00203 ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
00204 ec_fsm_coe_exec(fsm->fsm_coe, datagram);
00205 }
00206
00207
00208
00211 void ec_fsm_pdo_entry_read_state_count(
00212 ec_fsm_pdo_entry_t *fsm,
00213 ec_datagram_t *datagram
00214 )
00215 {
00216 if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
00217 return;
00218 }
00219
00220 if (!ec_fsm_coe_success(fsm->fsm_coe)) {
00221 EC_SLAVE_ERR(fsm->slave,
00222 "Failed to read number of mapped PDO entries.\n");
00223 fsm->state = ec_fsm_pdo_entry_state_error;
00224 return;
00225 }
00226
00227 if (fsm->request.data_size != sizeof(uint8_t)) {
00228 EC_SLAVE_ERR(fsm->slave, "Invalid data size %zu at uploading"
00229 " SDO 0x%04X:%02X.\n",
00230 fsm->request.data_size, fsm->request.index,
00231 fsm->request.subindex);
00232 fsm->state = ec_fsm_pdo_entry_state_error;
00233 return;
00234 }
00235
00236 fsm->entry_count = EC_READ_U8(fsm->request.data);
00237
00238 EC_SLAVE_DBG(fsm->slave, 1, "%u PDO entries mapped.\n", fsm->entry_count);
00239
00240
00241 fsm->entry_pos = 1;
00242 ec_fsm_pdo_entry_read_action_next(fsm, datagram);
00243 }
00244
00245
00246
00249 void ec_fsm_pdo_entry_read_action_next(
00250 ec_fsm_pdo_entry_t *fsm,
00251 ec_datagram_t *datagram
00252 )
00253 {
00254 if (fsm->entry_pos <= fsm->entry_count) {
00255 ecrt_sdo_request_index(&fsm->request, fsm->target_pdo->index,
00256 fsm->entry_pos);
00257 ecrt_sdo_request_read(&fsm->request);
00258 fsm->state = ec_fsm_pdo_entry_read_state_entry;
00259 ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
00260 ec_fsm_coe_exec(fsm->fsm_coe, datagram);
00261 return;
00262 }
00263
00264
00265 fsm->state = ec_fsm_pdo_entry_state_end;
00266 }
00267
00268
00269
00272 void ec_fsm_pdo_entry_read_state_entry(
00273 ec_fsm_pdo_entry_t *fsm,
00274 ec_datagram_t *datagram
00275 )
00276 {
00277 if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
00278 return;
00279 }
00280
00281 if (!ec_fsm_coe_success(fsm->fsm_coe)) {
00282 EC_SLAVE_ERR(fsm->slave, "Failed to read mapped PDO entry.\n");
00283 fsm->state = ec_fsm_pdo_entry_state_error;
00284 return;
00285 }
00286
00287 if (fsm->request.data_size != sizeof(uint32_t)) {
00288 EC_SLAVE_ERR(fsm->slave, "Invalid data size %zu at"
00289 " uploading SDO 0x%04X:%02X.\n",
00290 fsm->request.data_size, fsm->request.index,
00291 fsm->request.subindex);
00292 fsm->state = ec_fsm_pdo_entry_state_error;
00293 } else {
00294 uint32_t pdo_entry_info;
00295 ec_pdo_entry_t *pdo_entry;
00296
00297 pdo_entry_info = EC_READ_U32(fsm->request.data);
00298
00299 if (!(pdo_entry = (ec_pdo_entry_t *)
00300 kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
00301 EC_SLAVE_ERR(fsm->slave, "Failed to allocate PDO entry.\n");
00302 fsm->state = ec_fsm_pdo_entry_state_error;
00303 return;
00304 }
00305
00306 ec_pdo_entry_init(pdo_entry);
00307 pdo_entry->index = pdo_entry_info >> 16;
00308 pdo_entry->subindex = (pdo_entry_info >> 8) & 0xFF;
00309 pdo_entry->bit_length = pdo_entry_info & 0xFF;
00310
00311 if (!pdo_entry->index && !pdo_entry->subindex) {
00312 if (ec_pdo_entry_set_name(pdo_entry, "Gap")) {
00313 ec_pdo_entry_clear(pdo_entry);
00314 kfree(pdo_entry);
00315 fsm->state = ec_fsm_pdo_entry_state_error;
00316 return;
00317 }
00318 }
00319
00320 EC_SLAVE_DBG(fsm->slave, 1,
00321 "PDO entry 0x%04X:%02X, %u bit, \"%s\".\n",
00322 pdo_entry->index, pdo_entry->subindex,
00323 pdo_entry->bit_length,
00324 pdo_entry->name ? pdo_entry->name : "???");
00325
00326 list_add_tail(&pdo_entry->list, &fsm->target_pdo->entries);
00327
00328
00329 fsm->entry_pos++;
00330 ec_fsm_pdo_entry_read_action_next(fsm, datagram);
00331 }
00332 }
00333
00334
00335
00336
00337
00340 void ec_fsm_pdo_entry_conf_state_start(
00341 ec_fsm_pdo_entry_t *fsm,
00342 ec_datagram_t *datagram
00343 )
00344 {
00345 if (ec_sdo_request_alloc(&fsm->request, 4)) {
00346 fsm->state = ec_fsm_pdo_entry_state_error;
00347 return;
00348 }
00349
00350
00351 EC_WRITE_U8(fsm->request.data, 0);
00352 fsm->request.data_size = 1;
00353 ecrt_sdo_request_index(&fsm->request, fsm->source_pdo->index, 0);
00354 ecrt_sdo_request_write(&fsm->request);
00355
00356 EC_SLAVE_DBG(fsm->slave, 1, "Setting entry count to zero.\n");
00357
00358 fsm->state = ec_fsm_pdo_entry_conf_state_zero_entry_count;
00359 ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
00360 ec_fsm_coe_exec(fsm->fsm_coe, datagram);
00361 }
00362
00363
00364
00369 ec_pdo_entry_t *ec_fsm_pdo_entry_conf_next_entry(
00370 const ec_fsm_pdo_entry_t *fsm,
00371 const struct list_head *list
00372 )
00373 {
00374 list = list->next;
00375 if (list == &fsm->source_pdo->entries)
00376 return NULL;
00377 return list_entry(list, ec_pdo_entry_t, list);
00378 }
00379
00380
00381
00384 void ec_fsm_pdo_entry_conf_state_zero_entry_count(
00385 ec_fsm_pdo_entry_t *fsm,
00386 ec_datagram_t *datagram
00387 )
00388 {
00389 if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
00390 return;
00391 }
00392
00393 if (!ec_fsm_coe_success(fsm->fsm_coe)) {
00394 EC_SLAVE_WARN(fsm->slave, "Failed to clear PDO mapping.\n");
00395 EC_SLAVE_WARN(fsm->slave, ""); ec_fsm_pdo_entry_print(fsm);
00396 fsm->state = ec_fsm_pdo_entry_state_error;
00397 return;
00398 }
00399
00400
00401 if (!(fsm->entry = ec_fsm_pdo_entry_conf_next_entry(
00402 fsm, &fsm->source_pdo->entries))) {
00403
00404 EC_SLAVE_DBG(fsm->slave, 1, "No entries to map.\n");
00405
00406 fsm->state = ec_fsm_pdo_entry_state_end;
00407 return;
00408 }
00409
00410
00411 fsm->entry_pos = 1;
00412 ec_fsm_pdo_entry_conf_action_map(fsm, datagram);
00413 }
00414
00415
00416
00419 void ec_fsm_pdo_entry_conf_action_map(
00420 ec_fsm_pdo_entry_t *fsm,
00421 ec_datagram_t *datagram
00422 )
00423 {
00424 uint32_t value;
00425
00426 EC_SLAVE_DBG(fsm->slave, 1, "Mapping PDO entry 0x%04X:%02X (%u bit)"
00427 " at position %u.\n",
00428 fsm->entry->index, fsm->entry->subindex,
00429 fsm->entry->bit_length, fsm->entry_pos);
00430
00431 value = fsm->entry->index << 16
00432 | fsm->entry->subindex << 8 | fsm->entry->bit_length;
00433 EC_WRITE_U32(fsm->request.data, value);
00434 fsm->request.data_size = 4;
00435 ecrt_sdo_request_index(&fsm->request, fsm->source_pdo->index,
00436 fsm->entry_pos);
00437 ecrt_sdo_request_write(&fsm->request);
00438
00439 fsm->state = ec_fsm_pdo_entry_conf_state_map_entry;
00440 ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
00441 ec_fsm_coe_exec(fsm->fsm_coe, datagram);
00442 }
00443
00444
00445
00448 void ec_fsm_pdo_entry_conf_state_map_entry(
00449 ec_fsm_pdo_entry_t *fsm,
00450 ec_datagram_t *datagram
00451 )
00452 {
00453 if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
00454 return;
00455 }
00456
00457 if (!ec_fsm_coe_success(fsm->fsm_coe)) {
00458 EC_SLAVE_WARN(fsm->slave, "Failed to map PDO entry"
00459 " 0x%04X:%02X (%u bit) to position %u.\n",
00460 fsm->entry->index, fsm->entry->subindex,
00461 fsm->entry->bit_length, fsm->entry_pos);
00462 EC_SLAVE_WARN(fsm->slave, ""); ec_fsm_pdo_entry_print(fsm);
00463 fsm->state = ec_fsm_pdo_entry_state_error;
00464 return;
00465 }
00466
00467
00468 if (!(fsm->entry = ec_fsm_pdo_entry_conf_next_entry(
00469 fsm, &fsm->entry->list))) {
00470
00471
00472 EC_WRITE_U8(fsm->request.data, fsm->entry_pos);
00473 fsm->request.data_size = 1;
00474 ecrt_sdo_request_index(&fsm->request, fsm->source_pdo->index, 0);
00475 ecrt_sdo_request_write(&fsm->request);
00476
00477 EC_SLAVE_DBG(fsm->slave, 1, "Setting number of PDO entries to %u.\n",
00478 fsm->entry_pos);
00479
00480 fsm->state = ec_fsm_pdo_entry_conf_state_set_entry_count;
00481 ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
00482 ec_fsm_coe_exec(fsm->fsm_coe, datagram);
00483 return;
00484 }
00485
00486
00487 fsm->entry_pos++;
00488 ec_fsm_pdo_entry_conf_action_map(fsm, datagram);
00489 }
00490
00491
00492
00495 void ec_fsm_pdo_entry_conf_state_set_entry_count(
00496 ec_fsm_pdo_entry_t *fsm,
00497 ec_datagram_t *datagram
00498 )
00499 {
00500 if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
00501 return;
00502 }
00503
00504 if (!ec_fsm_coe_success(fsm->fsm_coe)) {
00505 EC_SLAVE_WARN(fsm->slave, "Failed to set number of entries.\n");
00506 EC_SLAVE_WARN(fsm->slave, ""); ec_fsm_pdo_entry_print(fsm);
00507 fsm->state = ec_fsm_pdo_entry_state_error;
00508 return;
00509 }
00510
00511 EC_SLAVE_DBG(fsm->slave, 1, "Successfully configured"
00512 " mapping for PDO 0x%04X.\n", fsm->source_pdo->index);
00513
00514 fsm->state = ec_fsm_pdo_entry_state_end;
00515 }
00516
00517
00518
00519
00520
00523 void ec_fsm_pdo_entry_state_error(
00524 ec_fsm_pdo_entry_t *fsm,
00525 ec_datagram_t *datagram
00526 )
00527 {
00528 }
00529
00530
00531
00534 void ec_fsm_pdo_entry_state_end(
00535 ec_fsm_pdo_entry_t *fsm,
00536 ec_datagram_t *datagram
00537 )
00538 {
00539 }
00540
00541