Newer
Older
Florian Pose
committed
void ec_fsm_slave_conf_enter_pdo_sync(
ec_fsm_slave_t *fsm /**< slave state machine */
)
Florian Pose
committed
{
ec_slave_t *slave = fsm->slave;
ec_datagram_t *datagram = fsm->datagram;
unsigned int i, offset, num_syncs;
const ec_sync_t *sync;
ec_direction_t dir;
uint16_t size;
Florian Pose
committed
if (!slave->sii_sync_count) {
Florian Pose
committed
ec_fsm_slave_conf_enter_fmmu(fsm);
return;
}
if (slave->sii_mailbox_protocols) {
offset = 2; // slave has mailboxes
} else {
offset = 0;
}
num_syncs = slave->sii_sync_count - offset;
Florian Pose
committed
// configure sync managers for process data
ec_datagram_npwr(datagram, slave->station_address,
0x0800 + EC_SYNC_PAGE_SIZE * offset,
EC_SYNC_PAGE_SIZE * num_syncs);
memset(datagram->data, 0x00, EC_SYNC_PAGE_SIZE * num_syncs);
for (i = 0; i < num_syncs; i++) {
sync = &slave->sii_syncs[i + offset];
dir = ec_sync_direction(sync);
size = ec_pdo_mapping_total_size(&slave->config->mapping[dir]);
ec_sync_config(sync, size, datagram->data + EC_SYNC_PAGE_SIZE * i);
Florian Pose
committed
}
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_slave_conf_state_pdo_sync;
Florian Pose
committed
}
/*****************************************************************************/
/**
Florian Pose
committed
void ec_fsm_slave_conf_state_pdo_sync(ec_fsm_slave_t *fsm /**< slave state machine */)
Florian Pose
committed
{
ec_datagram_t *datagram = fsm->datagram;
ec_slave_t *slave = fsm->slave;
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
Florian Pose
committed
return;
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_slave_state_error;
EC_ERR("Failed to receive process data sync manager configuration"
" datagram for slave %i (datagram state %i).\n",
slave->ring_position, datagram->state);
Florian Pose
committed
return;
}
if (datagram->working_counter != 1) {
slave->error_flag = 1;
fsm->state = ec_fsm_slave_state_error;
EC_ERR("Failed to set process data sync managers of slave %i: ",
slave->ring_position);
ec_datagram_print_wc_error(datagram);
Florian Pose
committed
return;
}
ec_fsm_slave_conf_enter_fmmu(fsm);
}
/*****************************************************************************/
/**
* Check for FMMUs to be configured.
*/
Florian Pose
committed
void ec_fsm_slave_conf_enter_fmmu(ec_fsm_slave_t *fsm /**< slave state machine */)
{
ec_slave_t *slave = fsm->slave;
ec_datagram_t *datagram = fsm->datagram;
unsigned int i;
const ec_fmmu_config_t *fmmu;
const ec_sync_t *sync;
Florian Pose
committed
if (!slave->base_fmmu_count) { // skip FMMU configuration
ec_fsm_slave_conf_enter_saveop(fsm);
Florian Pose
committed
return;
}
// configure FMMUs
ec_datagram_npwr(datagram, slave->station_address,
0x0600, EC_FMMU_PAGE_SIZE * slave->base_fmmu_count);
memset(datagram->data, 0x00, EC_FMMU_PAGE_SIZE * slave->base_fmmu_count);
for (i = 0; i < slave->config->used_fmmus; i++) {
fmmu = &slave->config->fmmu_configs[i];
if (!(sync = ec_slave_get_pdo_sync(slave, fmmu->dir))) {
fsm->state = ec_fsm_slave_state_error;
EC_ERR("Failed to determine PDO sync manager for FMMU on slave"
" %u!\n", slave->ring_position);
return;
}
ec_fmmu_config_page(fmmu, sync,
datagram->data + EC_FMMU_PAGE_SIZE * i);
Florian Pose
committed
}
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_slave_conf_state_fmmu;
}
/*****************************************************************************/
/**
Slave configuration state: FMMU.
*/
void ec_fsm_slave_conf_state_fmmu(ec_fsm_slave_t *fsm /**< slave state machine */)
{
ec_datagram_t *datagram = fsm->datagram;
ec_slave_t *slave = fsm->slave;
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
Florian Pose
committed
return;
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_slave_state_error;
EC_ERR("Failed to receive FMMUs datagram for slave %i"
" (datagram state %i).\n",
slave->ring_position, datagram->state);
Florian Pose
committed
return;
}
if (datagram->working_counter != 1) {
slave->error_flag = 1;
Florian Pose
committed
fsm->state = ec_fsm_slave_state_error;
EC_ERR("Failed to set FMMUs of slave %i: ",
slave->ring_position);
ec_datagram_print_wc_error(datagram);
Florian Pose
committed
return;
}
ec_fsm_slave_conf_enter_saveop(fsm);
}
/*****************************************************************************/
/**
Florian Pose
committed
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
*/
void ec_fsm_slave_conf_enter_saveop(ec_fsm_slave_t *fsm /**< slave state machine */)
{
fsm->state = ec_fsm_slave_conf_state_saveop;
ec_fsm_change_start(&fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_SAVEOP);
ec_fsm_change_exec(&fsm->fsm_change); // execute immediately
}
/*****************************************************************************/
/**
Slave configuration state: SAVEOP.
*/
void ec_fsm_slave_conf_state_saveop(ec_fsm_slave_t *fsm /**< slave state machine */)
{
ec_master_t *master = fsm->slave->master;
ec_slave_t *slave = fsm->slave;
if (ec_fsm_change_exec(&fsm->fsm_change)) return;
if (!ec_fsm_change_success(&fsm->fsm_change)) {
if (!fsm->fsm_change.spontaneous_change)
fsm->slave->error_flag = 1;
Florian Pose
committed
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
fsm->state = ec_fsm_slave_state_error;
return;
}
// slave is now in SAVEOP
if (master->debug_level) {
EC_DBG("Slave %i is now in SAVEOP.\n", slave->ring_position);
}
if (fsm->slave->current_state == fsm->slave->requested_state) {
fsm->state = ec_fsm_slave_state_end; // successful
if (master->debug_level) {
EC_DBG("Finished configuration of slave %i.\n",
slave->ring_position);
}
return;
}
// set state to OP
fsm->state = ec_fsm_slave_conf_state_op;
ec_fsm_change_start(&fsm->fsm_change, slave, EC_SLAVE_STATE_OP);
ec_fsm_change_exec(&fsm->fsm_change); // execute immediately
}
/*****************************************************************************/
/**
Slave configuration state: OP
*/
void ec_fsm_slave_conf_state_op(ec_fsm_slave_t *fsm /**< slave state machine */)
{
ec_master_t *master = fsm->slave->master;
ec_slave_t *slave = fsm->slave;
if (ec_fsm_change_exec(&fsm->fsm_change)) return;
if (!ec_fsm_change_success(&fsm->fsm_change)) {
if (!fsm->fsm_change.spontaneous_change)
slave->error_flag = 1;
Florian Pose
committed
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
fsm->state = ec_fsm_slave_state_error;
return;
}
// slave is now in OP
if (master->debug_level) {
EC_DBG("Slave %i is now in OP.\n", slave->ring_position);
EC_DBG("Finished configuration of slave %i.\n", slave->ring_position);
}
fsm->state = ec_fsm_slave_state_end; // successful
}
/******************************************************************************
* Common state functions
*****************************************************************************/
/**
State: ERROR.
*/
void ec_fsm_slave_state_error(ec_fsm_slave_t *fsm /**< slave state machine */)
{
}
/*****************************************************************************/
/**
State: END.
*/
void ec_fsm_slave_state_end(ec_fsm_slave_t *fsm /**< slave state machine */)
{
}
/*****************************************************************************/