master/fsm.c
changeset 293 14aeb79aa992
parent 292 2cf6ae0a2419
child 297 ac2a057a8ef2
child 1715 e675450f2174
equal deleted inserted replaced
292:2cf6ae0a2419 293:14aeb79aa992
   105     fsm->master_state = ec_fsm_master_start;
   105     fsm->master_state = ec_fsm_master_start;
   106     fsm->master_slaves_responding = 0;
   106     fsm->master_slaves_responding = 0;
   107     fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN;
   107     fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN;
   108     fsm->master_validation = 0;
   108     fsm->master_validation = 0;
   109 
   109 
   110     ec_command_init(&fsm->command);
   110     ec_datagram_init(&fsm->datagram);
   111     if (ec_command_prealloc(&fsm->command, EC_MAX_DATA_SIZE)) {
   111     if (ec_datagram_prealloc(&fsm->datagram, EC_MAX_DATA_SIZE)) {
   112         EC_ERR("Failed to allocate FSM command.\n");
   112         EC_ERR("Failed to allocate FSM datagram.\n");
   113         return -1;
   113         return -1;
   114     }
   114     }
   115 
   115 
   116     return 0;
   116     return 0;
   117 }
   117 }
   122    Destructor.
   122    Destructor.
   123 */
   123 */
   124 
   124 
   125 void ec_fsm_clear(ec_fsm_t *fsm /**< finite state machine */)
   125 void ec_fsm_clear(ec_fsm_t *fsm /**< finite state machine */)
   126 {
   126 {
   127     ec_command_clear(&fsm->command);
   127     ec_datagram_clear(&fsm->datagram);
   128 }
   128 }
   129 
   129 
   130 /*****************************************************************************/
   130 /*****************************************************************************/
   131 
   131 
   132 /**
   132 /**
   160    Starts with getting slave count and slave states.
   160    Starts with getting slave count and slave states.
   161 */
   161 */
   162 
   162 
   163 void ec_fsm_master_start(ec_fsm_t *fsm)
   163 void ec_fsm_master_start(ec_fsm_t *fsm)
   164 {
   164 {
   165     ec_command_brd(&fsm->command, 0x0130, 2);
   165     ec_datagram_brd(&fsm->datagram, 0x0130, 2);
   166     ec_master_queue_command(fsm->master, &fsm->command);
   166     ec_master_queue_datagram(fsm->master, &fsm->datagram);
   167     fsm->master_state = ec_fsm_master_broadcast;
   167     fsm->master_state = ec_fsm_master_broadcast;
   168 }
   168 }
   169 
   169 
   170 /*****************************************************************************/
   170 /*****************************************************************************/
   171 
   171 
   174    Processes the broadcast read slave count and slaves states.
   174    Processes the broadcast read slave count and slaves states.
   175 */
   175 */
   176 
   176 
   177 void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */)
   177 void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */)
   178 {
   178 {
   179     ec_command_t *command = &fsm->command;
   179     ec_datagram_t *datagram = &fsm->datagram;
   180     unsigned int topology_change, states_change, i;
   180     unsigned int topology_change, states_change, i;
   181     ec_slave_t *slave;
   181     ec_slave_t *slave;
   182     ec_master_t *master = fsm->master;
   182     ec_master_t *master = fsm->master;
   183 
   183 
   184     if (command->state != EC_CMD_RECEIVED) {
   184     if (datagram->state != EC_CMD_RECEIVED) {
   185         if (!master->device->link_state) {
   185         if (!master->device->link_state) {
   186             fsm->master_slaves_responding = 0;
   186             fsm->master_slaves_responding = 0;
   187             list_for_each_entry(slave, &master->slaves, list) {
   187             list_for_each_entry(slave, &master->slaves, list) {
   188                 slave->online = 0;
   188                 slave->online = 0;
   189             }
   189             }
   191         fsm->master_state = ec_fsm_master_start;
   191         fsm->master_state = ec_fsm_master_start;
   192         fsm->master_state(fsm); // execute immediately
   192         fsm->master_state(fsm); // execute immediately
   193         return;
   193         return;
   194     }
   194     }
   195 
   195 
   196     topology_change = (command->working_counter !=
   196     topology_change = (datagram->working_counter !=
   197                        fsm->master_slaves_responding);
   197                        fsm->master_slaves_responding);
   198     states_change = (EC_READ_U8(command->data) != fsm->master_slave_states);
   198     states_change = (EC_READ_U8(datagram->data) != fsm->master_slave_states);
   199 
   199 
   200     fsm->master_slave_states = EC_READ_U8(command->data);
   200     fsm->master_slave_states = EC_READ_U8(datagram->data);
   201     fsm->master_slaves_responding = command->working_counter;
   201     fsm->master_slaves_responding = datagram->working_counter;
   202 
   202 
   203     if (topology_change) {
   203     if (topology_change) {
   204         EC_INFO("%i slave%s responding.\n",
   204         EC_INFO("%i slave%s responding.\n",
   205                 fsm->master_slaves_responding,
   205                 fsm->master_slaves_responding,
   206                 fsm->master_slaves_responding == 1 ? "" : "s");
   206                 fsm->master_slaves_responding == 1 ? "" : "s");
   270         return;
   270         return;
   271     }
   271     }
   272 
   272 
   273     // fetch state from each slave
   273     // fetch state from each slave
   274     fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
   274     fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
   275     ec_command_nprd(&fsm->command, fsm->slave->station_address, 0x0130, 2);
   275     ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, 0x0130, 2);
   276     ec_master_queue_command(master, &fsm->command);
   276     ec_master_queue_datagram(master, &fsm->datagram);
   277     fsm->master_state = ec_fsm_master_states;
   277     fsm->master_state = ec_fsm_master_states;
   278 }
   278 }
   279 
   279 
   280 /*****************************************************************************/
   280 /*****************************************************************************/
   281 
   281 
   291 
   291 
   292     // have all states been read?
   292     // have all states been read?
   293     if (slave->list.next != &master->slaves) {
   293     if (slave->list.next != &master->slaves) {
   294         // process next slave
   294         // process next slave
   295         fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
   295         fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
   296         ec_command_nprd(&fsm->command, fsm->slave->station_address, 0x0130, 2);
   296         ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address,
   297         ec_master_queue_command(master, &fsm->command);
   297                          0x0130, 2);
       
   298         ec_master_queue_datagram(master, &fsm->datagram);
   298         fsm->master_state = ec_fsm_master_states;
   299         fsm->master_state = ec_fsm_master_states;
   299         return;
   300         return;
   300     }
   301     }
   301 
   302 
   302     // all slave stated read; check, if a bus validation has to be done
   303     // all slave stated read; check, if a bus validation has to be done
   329 */
   330 */
   330 
   331 
   331 void ec_fsm_master_states(ec_fsm_t *fsm /**< finite state machine */)
   332 void ec_fsm_master_states(ec_fsm_t *fsm /**< finite state machine */)
   332 {
   333 {
   333     ec_slave_t *slave = fsm->slave;
   334     ec_slave_t *slave = fsm->slave;
   334     ec_command_t *command = &fsm->command;
   335     ec_datagram_t *datagram = &fsm->datagram;
   335     uint8_t new_state;
   336     uint8_t new_state;
   336 
   337 
   337     if (command->state != EC_CMD_RECEIVED) {
   338     if (datagram->state != EC_CMD_RECEIVED) {
   338         fsm->master_state = ec_fsm_master_start;
   339         fsm->master_state = ec_fsm_master_start;
   339         fsm->master_state(fsm); // execute immediately
   340         fsm->master_state(fsm); // execute immediately
   340         return;
   341         return;
   341     }
   342     }
   342 
   343 
   343     // did the slave not respond to its station address?
   344     // did the slave not respond to its station address?
   344     if (command->working_counter != 1) {
   345     if (datagram->working_counter != 1) {
   345         if (slave->online) {
   346         if (slave->online) {
   346             slave->online = 0;
   347             slave->online = 0;
   347             EC_INFO("Slave %i: offline.\n", slave->ring_position);
   348             EC_INFO("Slave %i: offline.\n", slave->ring_position);
   348         }
   349         }
   349         ec_fsm_master_action_next_slave_state(fsm);
   350         ec_fsm_master_action_next_slave_state(fsm);
   350         return;
   351         return;
   351     }
   352     }
   352 
   353 
   353     // slave responded
   354     // slave responded
   354     new_state = EC_READ_U8(command->data);
   355     new_state = EC_READ_U8(datagram->data);
   355     if (!slave->online) { // slave was offline before
   356     if (!slave->online) { // slave was offline before
   356         slave->online = 1;
   357         slave->online = 1;
   357         slave->error_flag = 0; // clear error flag
   358         slave->error_flag = 0; // clear error flag
   358         slave->current_state = new_state;
   359         slave->current_state = new_state;
   359         EC_INFO("Slave %i: online (", slave->ring_position);
   360         EC_INFO("Slave %i: online (", slave->ring_position);
   533    their station address, so that they can be reconfigured later.
   534    their station address, so that they can be reconfigured later.
   534 */
   535 */
   535 
   536 
   536 void ec_fsm_master_reconfigure(ec_fsm_t *fsm /**< finite state machine */)
   537 void ec_fsm_master_reconfigure(ec_fsm_t *fsm /**< finite state machine */)
   537 {
   538 {
   538     ec_command_t *command = &fsm->command;
   539     ec_datagram_t *datagram = &fsm->datagram;
   539 
   540 
   540     while (fsm->slave->online) {
   541     while (fsm->slave->online) {
   541         if (fsm->slave->list.next == &fsm->master->slaves) { // last slave?
   542         if (fsm->slave->list.next == &fsm->master->slaves) { // last slave?
   542             fsm->master_state = ec_fsm_master_start;
   543             fsm->master_state = ec_fsm_master_start;
   543             fsm->master_state(fsm); // execute immediately
   544             fsm->master_state(fsm); // execute immediately
   548     }
   549     }
   549 
   550 
   550     EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position);
   551     EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position);
   551 
   552 
   552     // write station address
   553     // write station address
   553     ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2);
   554     ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
   554     EC_WRITE_U16(command->data, fsm->slave->station_address);
   555     EC_WRITE_U16(datagram->data, fsm->slave->station_address);
   555     ec_master_queue_command(fsm->master, command);
   556     ec_master_queue_datagram(fsm->master, datagram);
   556     fsm->master_state = ec_fsm_master_address;
   557     fsm->master_state = ec_fsm_master_address;
   557 }
   558 }
   558 
   559 
   559 /*****************************************************************************/
   560 /*****************************************************************************/
   560 
   561 
   564 */
   565 */
   565 
   566 
   566 void ec_fsm_master_address(ec_fsm_t *fsm /**< finite state machine */)
   567 void ec_fsm_master_address(ec_fsm_t *fsm /**< finite state machine */)
   567 {
   568 {
   568     ec_slave_t *slave = fsm->slave;
   569     ec_slave_t *slave = fsm->slave;
   569     ec_command_t *command = &fsm->command;
   570     ec_datagram_t *datagram = &fsm->datagram;
   570 
   571 
   571     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
   572     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
   572         EC_ERR("Failed to write station address on slave %i.\n",
   573         EC_ERR("Failed to write station address on slave %i.\n",
   573                slave->ring_position);
   574                slave->ring_position);
   574     }
   575     }
   575 
   576 
   576     if (fsm->slave->list.next == &fsm->master->slaves) { // last slave?
   577     if (fsm->slave->list.next == &fsm->master->slaves) { // last slave?
   750    slave, according to its ring position.
   751    slave, according to its ring position.
   751 */
   752 */
   752 
   753 
   753 void ec_fsm_slave_start_reading(ec_fsm_t *fsm /**< finite state machine */)
   754 void ec_fsm_slave_start_reading(ec_fsm_t *fsm /**< finite state machine */)
   754 {
   755 {
   755     ec_command_t *command = &fsm->command;
   756     ec_datagram_t *datagram = &fsm->datagram;
   756 
   757 
   757     // write station address
   758     // write station address
   758     ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2);
   759     ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
   759     EC_WRITE_U16(command->data, fsm->slave->station_address);
   760     EC_WRITE_U16(datagram->data, fsm->slave->station_address);
   760     ec_master_queue_command(fsm->master, command);
   761     ec_master_queue_datagram(fsm->master, datagram);
   761     fsm->slave_state = ec_fsm_slave_read_state;
   762     fsm->slave_state = ec_fsm_slave_read_state;
   762 }
   763 }
   763 
   764 
   764 /*****************************************************************************/
   765 /*****************************************************************************/
   765 
   766 
   767    Slave state: READ_STATUS.
   768    Slave state: READ_STATUS.
   768 */
   769 */
   769 
   770 
   770 void ec_fsm_slave_read_state(ec_fsm_t *fsm /**< finite state machine */)
   771 void ec_fsm_slave_read_state(ec_fsm_t *fsm /**< finite state machine */)
   771 {
   772 {
   772     ec_command_t *command = &fsm->command;
   773     ec_datagram_t *datagram = &fsm->datagram;
   773 
   774 
   774     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
   775     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
   775         fsm->slave->error_flag = 1;
   776         fsm->slave->error_flag = 1;
   776         fsm->slave_state = ec_fsm_slave_end;
   777         fsm->slave_state = ec_fsm_slave_end;
   777         EC_ERR("Failed to write station address of slave %i.\n",
   778         EC_ERR("Failed to write station address of slave %i.\n",
   778                fsm->slave->ring_position);
   779                fsm->slave->ring_position);
   779         return;
   780         return;
   780     }
   781     }
   781 
   782 
   782     // Read AL state
   783     // Read AL state
   783     ec_command_nprd(command, fsm->slave->station_address, 0x0130, 2);
   784     ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0130, 2);
   784     ec_master_queue_command(fsm->master, command);
   785     ec_master_queue_datagram(fsm->master, datagram);
   785     fsm->slave_state = ec_fsm_slave_read_base;
   786     fsm->slave_state = ec_fsm_slave_read_base;
   786 }
   787 }
   787 
   788 
   788 /*****************************************************************************/
   789 /*****************************************************************************/
   789 
   790 
   791    Slave state: READ_BASE.
   792    Slave state: READ_BASE.
   792 */
   793 */
   793 
   794 
   794 void ec_fsm_slave_read_base(ec_fsm_t *fsm /**< finite state machine */)
   795 void ec_fsm_slave_read_base(ec_fsm_t *fsm /**< finite state machine */)
   795 {
   796 {
   796     ec_command_t *command = &fsm->command;
   797     ec_datagram_t *datagram = &fsm->datagram;
   797     ec_slave_t *slave = fsm->slave;
   798     ec_slave_t *slave = fsm->slave;
   798 
   799 
   799     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
   800     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
   800         fsm->slave->error_flag = 1;
   801         fsm->slave->error_flag = 1;
   801         fsm->slave_state = ec_fsm_slave_end;
   802         fsm->slave_state = ec_fsm_slave_end;
   802         EC_ERR("Failed to read AL state of slave %i.\n",
   803         EC_ERR("Failed to read AL state of slave %i.\n",
   803                fsm->slave->ring_position);
   804                fsm->slave->ring_position);
   804         return;
   805         return;
   805     }
   806     }
   806 
   807 
   807     slave->current_state = EC_READ_U8(command->data);
   808     slave->current_state = EC_READ_U8(datagram->data);
   808     if (slave->current_state & EC_ACK) {
   809     if (slave->current_state & EC_ACK) {
   809         EC_WARN("Slave %i has state error bit set (0x%02X)!\n",
   810         EC_WARN("Slave %i has state error bit set (0x%02X)!\n",
   810                 slave->ring_position, slave->current_state);
   811                 slave->ring_position, slave->current_state);
   811         slave->current_state &= 0x0F;
   812         slave->current_state &= 0x0F;
   812     }
   813     }
   813 
   814 
   814     // read base data
   815     // read base data
   815     ec_command_nprd(command, fsm->slave->station_address, 0x0000, 6);
   816     ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0000, 6);
   816     ec_master_queue_command(fsm->master, command);
   817     ec_master_queue_datagram(fsm->master, datagram);
   817     fsm->slave_state = ec_fsm_slave_read_dl;
   818     fsm->slave_state = ec_fsm_slave_read_dl;
   818 }
   819 }
   819 
   820 
   820 /*****************************************************************************/
   821 /*****************************************************************************/
   821 
   822 
   823    Slave state: READ_DL.
   824    Slave state: READ_DL.
   824 */
   825 */
   825 
   826 
   826 void ec_fsm_slave_read_dl(ec_fsm_t *fsm /**< finite state machine */)
   827 void ec_fsm_slave_read_dl(ec_fsm_t *fsm /**< finite state machine */)
   827 {
   828 {
   828     ec_command_t *command = &fsm->command;
   829     ec_datagram_t *datagram = &fsm->datagram;
   829     ec_slave_t *slave = fsm->slave;
   830     ec_slave_t *slave = fsm->slave;
   830 
   831 
   831     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
   832     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
   832         fsm->slave->error_flag = 1;
   833         fsm->slave->error_flag = 1;
   833         fsm->slave_state = ec_fsm_slave_end;
   834         fsm->slave_state = ec_fsm_slave_end;
   834         EC_ERR("Failed to read base data of slave %i.\n",
   835         EC_ERR("Failed to read base data of slave %i.\n",
   835                slave->ring_position);
   836                slave->ring_position);
   836         return;
   837         return;
   837     }
   838     }
   838 
   839 
   839     slave->base_type       = EC_READ_U8 (command->data);
   840     slave->base_type       = EC_READ_U8 (datagram->data);
   840     slave->base_revision   = EC_READ_U8 (command->data + 1);
   841     slave->base_revision   = EC_READ_U8 (datagram->data + 1);
   841     slave->base_build      = EC_READ_U16(command->data + 2);
   842     slave->base_build      = EC_READ_U16(datagram->data + 2);
   842     slave->base_fmmu_count = EC_READ_U8 (command->data + 4);
   843     slave->base_fmmu_count = EC_READ_U8 (datagram->data + 4);
   843     slave->base_sync_count = EC_READ_U8 (command->data + 5);
   844     slave->base_sync_count = EC_READ_U8 (datagram->data + 5);
   844 
   845 
   845     if (slave->base_fmmu_count > EC_MAX_FMMUS)
   846     if (slave->base_fmmu_count > EC_MAX_FMMUS)
   846         slave->base_fmmu_count = EC_MAX_FMMUS;
   847         slave->base_fmmu_count = EC_MAX_FMMUS;
   847 
   848 
   848     // read data link status
   849     // read data link status
   849     ec_command_nprd(command, slave->station_address, 0x0110, 2);
   850     ec_datagram_nprd(datagram, slave->station_address, 0x0110, 2);
   850     ec_master_queue_command(slave->master, command);
   851     ec_master_queue_datagram(slave->master, datagram);
   851     fsm->slave_state = ec_fsm_slave_eeprom_size;
   852     fsm->slave_state = ec_fsm_slave_eeprom_size;
   852 }
   853 }
   853 
   854 
   854 /*****************************************************************************/
   855 /*****************************************************************************/
   855 
   856 
   858    Read the actual size of the EEPROM to allocate the EEPROM image.
   859    Read the actual size of the EEPROM to allocate the EEPROM image.
   859 */
   860 */
   860 
   861 
   861 void ec_fsm_slave_eeprom_size(ec_fsm_t *fsm /**< finite state machine */)
   862 void ec_fsm_slave_eeprom_size(ec_fsm_t *fsm /**< finite state machine */)
   862 {
   863 {
   863     ec_command_t *command = &fsm->command;
   864     ec_datagram_t *datagram = &fsm->datagram;
   864     ec_slave_t *slave = fsm->slave;
   865     ec_slave_t *slave = fsm->slave;
   865     uint16_t dl_status;
   866     uint16_t dl_status;
   866     unsigned int i;
   867     unsigned int i;
   867 
   868 
   868     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
   869     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
   869         fsm->slave->error_flag = 1;
   870         fsm->slave->error_flag = 1;
   870         fsm->slave_state = ec_fsm_slave_end;
   871         fsm->slave_state = ec_fsm_slave_end;
   871         EC_ERR("Failed to read DL status of slave %i.\n",
   872         EC_ERR("Failed to read DL status of slave %i.\n",
   872                slave->ring_position);
   873                slave->ring_position);
   873         return;
   874         return;
   874     }
   875     }
   875 
   876 
   876     dl_status = EC_READ_U16(command->data);
   877     dl_status = EC_READ_U16(datagram->data);
   877     for (i = 0; i < 4; i++) {
   878     for (i = 0; i < 4; i++) {
   878         slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0;
   879         slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0;
   879         slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
   880         slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
   880         slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
   881         slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
   881     }
   882     }
  1066 
  1067 
  1067 void ec_fsm_slave_conf(ec_fsm_t *fsm /**< finite state machine */)
  1068 void ec_fsm_slave_conf(ec_fsm_t *fsm /**< finite state machine */)
  1068 {
  1069 {
  1069     ec_slave_t *slave = fsm->slave;
  1070     ec_slave_t *slave = fsm->slave;
  1070     ec_master_t *master = fsm->master;
  1071     ec_master_t *master = fsm->master;
  1071     ec_command_t *command = &fsm->command;
  1072     ec_datagram_t *datagram = &fsm->datagram;
  1072 
  1073 
  1073     fsm->change_state(fsm); // execute state change state machine
  1074     fsm->change_state(fsm); // execute state change state machine
  1074 
  1075 
  1075     if (fsm->change_state == ec_fsm_change_error) {
  1076     if (fsm->change_state == ec_fsm_change_error) {
  1076         slave->error_flag = 1;
  1077         slave->error_flag = 1;
  1099         fsm->slave_state(fsm); // execute immediately
  1100         fsm->slave_state(fsm); // execute immediately
  1100         return;
  1101         return;
  1101     }
  1102     }
  1102 
  1103 
  1103     // reset FMMUs
  1104     // reset FMMUs
  1104     ec_command_npwr(command, slave->station_address, 0x0600,
  1105     ec_datagram_npwr(datagram, slave->station_address, 0x0600,
  1105                     EC_FMMU_SIZE * slave->base_fmmu_count);
  1106                      EC_FMMU_SIZE * slave->base_fmmu_count);
  1106     memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
  1107     memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
  1107     ec_master_queue_command(master, command);
  1108     ec_master_queue_datagram(master, datagram);
  1108     fsm->slave_state = ec_fsm_slave_sync;
  1109     fsm->slave_state = ec_fsm_slave_sync;
  1109 }
  1110 }
  1110 
  1111 
  1111 /*****************************************************************************/
  1112 /*****************************************************************************/
  1112 
  1113 
  1115    Configure sync managers.
  1116    Configure sync managers.
  1116 */
  1117 */
  1117 
  1118 
  1118 void ec_fsm_slave_sync(ec_fsm_t *fsm /**< finite state machine */)
  1119 void ec_fsm_slave_sync(ec_fsm_t *fsm /**< finite state machine */)
  1119 {
  1120 {
  1120     ec_command_t *command = &fsm->command;
  1121     ec_datagram_t *datagram = &fsm->datagram;
  1121     ec_slave_t *slave = fsm->slave;
  1122     ec_slave_t *slave = fsm->slave;
  1122     unsigned int j;
  1123     unsigned int j;
  1123     const ec_sync_t *sync;
  1124     const ec_sync_t *sync;
  1124     ec_eeprom_sync_t *eeprom_sync, mbox_sync;
  1125     ec_eeprom_sync_t *eeprom_sync, mbox_sync;
  1125 
  1126 
  1126     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
  1127     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
  1127         slave->error_flag = 1;
  1128         slave->error_flag = 1;
  1128         fsm->slave_state = ec_fsm_slave_end;
  1129         fsm->slave_state = ec_fsm_slave_end;
  1129         EC_ERR("Failed to reset FMMUs of slave %i.\n",
  1130         EC_ERR("Failed to reset FMMUs of slave %i.\n",
  1130                slave->ring_position);
  1131                slave->ring_position);
  1131         return;
  1132         return;
  1136         fsm->slave_state(fsm); // execute immediately
  1137         fsm->slave_state(fsm); // execute immediately
  1137         return;
  1138         return;
  1138     }
  1139     }
  1139 
  1140 
  1140     // configure sync managers
  1141     // configure sync managers
  1141     ec_command_npwr(command, slave->station_address, 0x0800,
  1142     ec_datagram_npwr(datagram, slave->station_address, 0x0800,
  1142                     EC_SYNC_SIZE * slave->base_sync_count);
  1143                      EC_SYNC_SIZE * slave->base_sync_count);
  1143     memset(command->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
  1144     memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
  1144 
  1145 
  1145     // known slave type, take type's SM information
  1146     // known slave type, take type's SM information
  1146     if (slave->type) {
  1147     if (slave->type) {
  1147         for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) {
  1148         for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) {
  1148             sync = slave->type->sync_managers[j];
  1149             sync = slave->type->sync_managers[j];
  1149             ec_sync_config(sync, slave, command->data + EC_SYNC_SIZE * j);
  1150             ec_sync_config(sync, slave, datagram->data + EC_SYNC_SIZE * j);
  1150         }
  1151         }
  1151     }
  1152     }
  1152 
  1153 
  1153     // unknown type, but slave has mailbox
  1154     // unknown type, but slave has mailbox
  1154     else if (slave->sii_mailbox_protocols)
  1155     else if (slave->sii_mailbox_protocols)
  1161                     fsm->slave_state = ec_fsm_slave_end;
  1162                     fsm->slave_state = ec_fsm_slave_end;
  1162                     EC_ERR("Invalid sync manager configuration found!");
  1163                     EC_ERR("Invalid sync manager configuration found!");
  1163                     return;
  1164                     return;
  1164                 }
  1165                 }
  1165                 ec_eeprom_sync_config(eeprom_sync,
  1166                 ec_eeprom_sync_config(eeprom_sync,
  1166                                       command->data + EC_SYNC_SIZE
  1167                                       datagram->data + EC_SYNC_SIZE
  1167                                       * eeprom_sync->index);
  1168                                       * eeprom_sync->index);
  1168             }
  1169             }
  1169         }
  1170         }
  1170 
  1171 
  1171         // no sync manager information; guess mailbox settings
  1172         // no sync manager information; guess mailbox settings
  1173             mbox_sync.physical_start_address =
  1174             mbox_sync.physical_start_address =
  1174                 slave->sii_rx_mailbox_offset;
  1175                 slave->sii_rx_mailbox_offset;
  1175             mbox_sync.length = slave->sii_rx_mailbox_size;
  1176             mbox_sync.length = slave->sii_rx_mailbox_size;
  1176             mbox_sync.control_register = 0x26;
  1177             mbox_sync.control_register = 0x26;
  1177             mbox_sync.enable = 1;
  1178             mbox_sync.enable = 1;
  1178             ec_eeprom_sync_config(&mbox_sync, command->data);
  1179             ec_eeprom_sync_config(&mbox_sync, datagram->data);
  1179 
  1180 
  1180             mbox_sync.physical_start_address =
  1181             mbox_sync.physical_start_address =
  1181                 slave->sii_tx_mailbox_offset;
  1182                 slave->sii_tx_mailbox_offset;
  1182             mbox_sync.length = slave->sii_tx_mailbox_size;
  1183             mbox_sync.length = slave->sii_tx_mailbox_size;
  1183             mbox_sync.control_register = 0x22;
  1184             mbox_sync.control_register = 0x22;
  1184             mbox_sync.enable = 1;
  1185             mbox_sync.enable = 1;
  1185             ec_eeprom_sync_config(&mbox_sync,
  1186             ec_eeprom_sync_config(&mbox_sync,
  1186                                   command->data + EC_SYNC_SIZE);
  1187                                   datagram->data + EC_SYNC_SIZE);
  1187         }
  1188         }
  1188 
  1189 
  1189         EC_INFO("Mailbox configured for unknown slave %i\n",
  1190         EC_INFO("Mailbox configured for unknown slave %i\n",
  1190                 slave->ring_position);
  1191                 slave->ring_position);
  1191     }
  1192     }
  1192 
  1193 
  1193     ec_master_queue_command(fsm->master, command);
  1194     ec_master_queue_datagram(fsm->master, datagram);
  1194     fsm->slave_state = ec_fsm_slave_preop;
  1195     fsm->slave_state = ec_fsm_slave_preop;
  1195 }
  1196 }
  1196 
  1197 
  1197 /*****************************************************************************/
  1198 /*****************************************************************************/
  1198 
  1199 
  1201    Change slave state to PREOP.
  1202    Change slave state to PREOP.
  1202 */
  1203 */
  1203 
  1204 
  1204 void ec_fsm_slave_preop(ec_fsm_t *fsm /**< finite state machine */)
  1205 void ec_fsm_slave_preop(ec_fsm_t *fsm /**< finite state machine */)
  1205 {
  1206 {
  1206     ec_command_t *command = &fsm->command;
  1207     ec_datagram_t *datagram = &fsm->datagram;
  1207     ec_slave_t *slave = fsm->slave;
  1208     ec_slave_t *slave = fsm->slave;
  1208 
  1209 
  1209     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
  1210     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
  1210         slave->error_flag = 1;
  1211         slave->error_flag = 1;
  1211         fsm->slave_state = ec_fsm_slave_end;
  1212         fsm->slave_state = ec_fsm_slave_end;
  1212         EC_ERR("Failed to set sync managers on slave %i.\n",
  1213         EC_ERR("Failed to set sync managers on slave %i.\n",
  1213                slave->ring_position);
  1214                slave->ring_position);
  1214         return;
  1215         return;
  1229 
  1230 
  1230 void ec_fsm_slave_fmmu(ec_fsm_t *fsm /**< finite state machine */)
  1231 void ec_fsm_slave_fmmu(ec_fsm_t *fsm /**< finite state machine */)
  1231 {
  1232 {
  1232     ec_slave_t *slave = fsm->slave;
  1233     ec_slave_t *slave = fsm->slave;
  1233     ec_master_t *master = fsm->master;
  1234     ec_master_t *master = fsm->master;
  1234     ec_command_t *command = &fsm->command;
  1235     ec_datagram_t *datagram = &fsm->datagram;
  1235     unsigned int j;
  1236     unsigned int j;
  1236 
  1237 
  1237     fsm->change_state(fsm); // execute state change state machine
  1238     fsm->change_state(fsm); // execute state change state machine
  1238 
  1239 
  1239     if (fsm->change_state == ec_fsm_change_error) {
  1240     if (fsm->change_state == ec_fsm_change_error) {
  1261         fsm->slave_state(fsm); // execute immediately
  1262         fsm->slave_state(fsm); // execute immediately
  1262         return;
  1263         return;
  1263     }
  1264     }
  1264 
  1265 
  1265     // configure FMMUs
  1266     // configure FMMUs
  1266     ec_command_npwr(command, slave->station_address,
  1267     ec_datagram_npwr(datagram, slave->station_address,
  1267                     0x0600, EC_FMMU_SIZE * slave->base_fmmu_count);
  1268                      0x0600, EC_FMMU_SIZE * slave->base_fmmu_count);
  1268     memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
  1269     memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
  1269     for (j = 0; j < slave->fmmu_count; j++) {
  1270     for (j = 0; j < slave->fmmu_count; j++) {
  1270         ec_fmmu_config(&slave->fmmus[j], slave,
  1271         ec_fmmu_config(&slave->fmmus[j], slave,
  1271                        command->data + EC_FMMU_SIZE * j);
  1272                        datagram->data + EC_FMMU_SIZE * j);
  1272     }
  1273     }
  1273 
  1274 
  1274     ec_master_queue_command(master, command);
  1275     ec_master_queue_datagram(master, datagram);
  1275     fsm->slave_state = ec_fsm_slave_saveop;
  1276     fsm->slave_state = ec_fsm_slave_saveop;
  1276 }
  1277 }
  1277 
  1278 
  1278 /*****************************************************************************/
  1279 /*****************************************************************************/
  1279 
  1280 
  1282    Set slave state to SAVEOP.
  1283    Set slave state to SAVEOP.
  1283 */
  1284 */
  1284 
  1285 
  1285 void ec_fsm_slave_saveop(ec_fsm_t *fsm /**< finite state machine */)
  1286 void ec_fsm_slave_saveop(ec_fsm_t *fsm /**< finite state machine */)
  1286 {
  1287 {
  1287     ec_command_t *command = &fsm->command;
  1288     ec_datagram_t *datagram = &fsm->datagram;
  1288 
  1289 
  1289     if (fsm->slave->base_fmmu_count && (command->state != EC_CMD_RECEIVED ||
  1290     if (fsm->slave->base_fmmu_count && (datagram->state != EC_CMD_RECEIVED ||
  1290                                         command->working_counter != 1)) {
  1291                                         datagram->working_counter != 1)) {
  1291         fsm->slave->error_flag = 1;
  1292         fsm->slave->error_flag = 1;
  1292         fsm->slave_state = ec_fsm_slave_end;
  1293         fsm->slave_state = ec_fsm_slave_end;
  1293         EC_ERR("Failed to set FMMUs on slave %i.\n",
  1294         EC_ERR("Failed to set FMMUs on slave %i.\n",
  1294                fsm->slave->ring_position);
  1295                fsm->slave->ring_position);
  1295         return;
  1296         return;
  1377    Starts reading the slave information interface.
  1378    Starts reading the slave information interface.
  1378 */
  1379 */
  1379 
  1380 
  1380 void ec_fsm_sii_start_reading(ec_fsm_t *fsm /**< finite state machine */)
  1381 void ec_fsm_sii_start_reading(ec_fsm_t *fsm /**< finite state machine */)
  1381 {
  1382 {
  1382     ec_command_t *command = &fsm->command;
  1383     ec_datagram_t *datagram = &fsm->datagram;
  1383 
  1384 
  1384     // initiate read operation
  1385     // initiate read operation
  1385     if (fsm->sii_mode) {
  1386     if (fsm->sii_mode) {
  1386         ec_command_npwr(command, fsm->slave->station_address, 0x502, 4);
  1387         ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 4);
  1387     }
  1388     }
  1388     else {
  1389     else {
  1389         ec_command_apwr(command, fsm->slave->ring_position, 0x502, 4);
  1390         ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x502, 4);
  1390     }
  1391     }
  1391 
  1392 
  1392     EC_WRITE_U8 (command->data,     0x00); // read-only access
  1393     EC_WRITE_U8 (datagram->data,     0x00); // read-only access
  1393     EC_WRITE_U8 (command->data + 1, 0x01); // request read operation
  1394     EC_WRITE_U8 (datagram->data + 1, 0x01); // request read operation
  1394     EC_WRITE_U16(command->data + 2, fsm->sii_offset);
  1395     EC_WRITE_U16(datagram->data + 2, fsm->sii_offset);
  1395     ec_master_queue_command(fsm->master, command);
  1396     ec_master_queue_datagram(fsm->master, datagram);
  1396     fsm->sii_state = ec_fsm_sii_read_check;
  1397     fsm->sii_state = ec_fsm_sii_read_check;
  1397 }
  1398 }
  1398 
  1399 
  1399 /*****************************************************************************/
  1400 /*****************************************************************************/
  1400 
  1401 
  1401 /**
  1402 /**
  1402    SII state: READ_CHECK.
  1403    SII state: READ_CHECK.
  1403    Checks, if the SII-read-command has been sent and issues a fetch command.
  1404    Checks, if the SII-read-datagram has been sent and issues a fetch datagram.
  1404 */
  1405 */
  1405 
  1406 
  1406 void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */)
  1407 void ec_fsm_sii_read_check(ec_fsm_t *fsm /**< finite state machine */)
  1407 {
  1408 {
  1408     ec_command_t *command = &fsm->command;
  1409     ec_datagram_t *datagram = &fsm->datagram;
  1409 
  1410 
  1410     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
  1411     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
  1411         EC_ERR("SII: Reception of read command failed.\n");
  1412         EC_ERR("SII: Reception of read datagram failed.\n");
  1412         fsm->sii_state = ec_fsm_sii_error;
  1413         fsm->sii_state = ec_fsm_sii_error;
  1413         return;
  1414         return;
  1414     }
  1415     }
  1415 
  1416 
  1416     fsm->sii_start = get_cycles();
  1417     fsm->sii_start = get_cycles();
  1417 
  1418 
  1418     // issue check/fetch command
  1419     // issue check/fetch datagram
  1419     if (fsm->sii_mode) {
  1420     if (fsm->sii_mode) {
  1420         ec_command_nprd(command, fsm->slave->station_address, 0x502, 10);
  1421         ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10);
  1421     }
  1422     }
  1422     else {
  1423     else {
  1423         ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10);
  1424         ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10);
  1424     }
  1425     }
  1425 
  1426 
  1426     ec_master_queue_command(fsm->master, command);
  1427     ec_master_queue_datagram(fsm->master, datagram);
  1427     fsm->sii_state = ec_fsm_sii_read_fetch;
  1428     fsm->sii_state = ec_fsm_sii_read_fetch;
  1428 }
  1429 }
  1429 
  1430 
  1430 /*****************************************************************************/
  1431 /*****************************************************************************/
  1431 
  1432 
  1432 /**
  1433 /**
  1433    SII state: READ_FETCH.
  1434    SII state: READ_FETCH.
  1434    Fetches the result of an SII-read command.
  1435    Fetches the result of an SII-read datagram.
  1435 */
  1436 */
  1436 
  1437 
  1437 void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */)
  1438 void ec_fsm_sii_read_fetch(ec_fsm_t *fsm /**< finite state machine */)
  1438 {
  1439 {
  1439     ec_command_t *command = &fsm->command;
  1440     ec_datagram_t *datagram = &fsm->datagram;
  1440 
  1441 
  1441     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
  1442     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
  1442         EC_ERR("SII: Reception of check/fetch command failed.\n");
  1443         EC_ERR("SII: Reception of check/fetch datagram failed.\n");
  1443         fsm->sii_state = ec_fsm_sii_error;
  1444         fsm->sii_state = ec_fsm_sii_error;
  1444         return;
  1445         return;
  1445     }
  1446     }
  1446 
  1447 
  1447     // check "busy bit"
  1448     // check "busy bit"
  1448     if (EC_READ_U8(command->data + 1) & 0x81) {
  1449     if (EC_READ_U8(datagram->data + 1) & 0x81) {
  1449         // still busy... timeout?
  1450         // still busy... timeout?
  1450         if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) {
  1451         if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) {
  1451             EC_ERR("SII: Timeout.\n");
  1452             EC_ERR("SII: Timeout.\n");
  1452             fsm->sii_state = ec_fsm_sii_error;
  1453             fsm->sii_state = ec_fsm_sii_error;
  1453 #if 0
  1454 #if 0
  1454             EC_DBG("SII busy: %02X %02X %02X %02X\n",
  1455             EC_DBG("SII busy: %02X %02X %02X %02X\n",
  1455                    EC_READ_U8(command->data + 0),
  1456                    EC_READ_U8(datagram->data + 0),
  1456                    EC_READ_U8(command->data + 1),
  1457                    EC_READ_U8(datagram->data + 1),
  1457                    EC_READ_U8(command->data + 2),
  1458                    EC_READ_U8(datagram->data + 2),
  1458                    EC_READ_U8(command->data + 3));
  1459                    EC_READ_U8(datagram->data + 3));
  1459 #endif
  1460 #endif
  1460         }
  1461         }
  1461 
  1462 
  1462         // issue check/fetch command again
  1463         // issue check/fetch datagram again
  1463         if (fsm->sii_mode) {
  1464         if (fsm->sii_mode) {
  1464             ec_command_nprd(command, fsm->slave->station_address, 0x502, 10);
  1465             ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10);
  1465         }
  1466         }
  1466         else {
  1467         else {
  1467             ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10);
  1468             ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10);
  1468         }
  1469         }
  1469         ec_master_queue_command(fsm->master, command);
  1470         ec_master_queue_datagram(fsm->master, datagram);
  1470         return;
  1471         return;
  1471     }
  1472     }
  1472 
  1473 
  1473 #if 0
  1474 #if 0
  1474     EC_DBG("SII rec: %02X %02X %02X %02X - %02X %02X %02X %02X\n",
  1475     EC_DBG("SII rec: %02X %02X %02X %02X - %02X %02X %02X %02X\n",
  1475            EC_READ_U8(command->data + 0), EC_READ_U8(command->data + 1),
  1476            EC_READ_U8(datagram->data + 0), EC_READ_U8(datagram->data + 1),
  1476            EC_READ_U8(command->data + 2), EC_READ_U8(command->data + 3),
  1477            EC_READ_U8(datagram->data + 2), EC_READ_U8(datagram->data + 3),
  1477            EC_READ_U8(command->data + 6), EC_READ_U8(command->data + 7),
  1478            EC_READ_U8(datagram->data + 6), EC_READ_U8(datagram->data + 7),
  1478            EC_READ_U8(command->data + 8), EC_READ_U8(command->data + 9));
  1479            EC_READ_U8(datagram->data + 8), EC_READ_U8(datagram->data + 9));
  1479 #endif
  1480 #endif
  1480 
  1481 
  1481     // SII value received.
  1482     // SII value received.
  1482     memcpy(fsm->sii_value, command->data + 6, 4);
  1483     memcpy(fsm->sii_value, datagram->data + 6, 4);
  1483     fsm->sii_state = ec_fsm_sii_end;
  1484     fsm->sii_state = ec_fsm_sii_end;
  1484 }
  1485 }
  1485 
  1486 
  1486 /*****************************************************************************/
  1487 /*****************************************************************************/
  1487 
  1488 
  1490    Starts reading the slave information interface.
  1491    Starts reading the slave information interface.
  1491 */
  1492 */
  1492 
  1493 
  1493 void ec_fsm_sii_start_writing(ec_fsm_t *fsm /**< finite state machine */)
  1494 void ec_fsm_sii_start_writing(ec_fsm_t *fsm /**< finite state machine */)
  1494 {
  1495 {
  1495     ec_command_t *command = &fsm->command;
  1496     ec_datagram_t *datagram = &fsm->datagram;
  1496 
  1497 
  1497     // initiate write operation
  1498     // initiate write operation
  1498     ec_command_npwr(command, fsm->slave->station_address, 0x502, 8);
  1499     ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 8);
  1499     EC_WRITE_U8 (command->data,     0x01); // enable write access
  1500     EC_WRITE_U8 (datagram->data,     0x01); // enable write access
  1500     EC_WRITE_U8 (command->data + 1, 0x02); // request write operation
  1501     EC_WRITE_U8 (datagram->data + 1, 0x02); // request write operation
  1501     EC_WRITE_U32(command->data + 2, fsm->sii_offset);
  1502     EC_WRITE_U32(datagram->data + 2, fsm->sii_offset);
  1502     memcpy(command->data + 6, fsm->sii_value, 2);
  1503     memcpy(datagram->data + 6, fsm->sii_value, 2);
  1503     ec_master_queue_command(fsm->master, command);
  1504     ec_master_queue_datagram(fsm->master, datagram);
  1504     fsm->sii_state = ec_fsm_sii_write_check;
  1505     fsm->sii_state = ec_fsm_sii_write_check;
  1505 }
  1506 }
  1506 
  1507 
  1507 /*****************************************************************************/
  1508 /*****************************************************************************/
  1508 
  1509 
  1510    SII state: WRITE_CHECK.
  1511    SII state: WRITE_CHECK.
  1511 */
  1512 */
  1512 
  1513 
  1513 void ec_fsm_sii_write_check(ec_fsm_t *fsm /**< finite state machine */)
  1514 void ec_fsm_sii_write_check(ec_fsm_t *fsm /**< finite state machine */)
  1514 {
  1515 {
  1515     ec_command_t *command = &fsm->command;
  1516     ec_datagram_t *datagram = &fsm->datagram;
  1516 
  1517 
  1517     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
  1518     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
  1518         EC_ERR("SII: Reception of write command failed.\n");
  1519         EC_ERR("SII: Reception of write datagram failed.\n");
  1519         fsm->sii_state = ec_fsm_sii_error;
  1520         fsm->sii_state = ec_fsm_sii_error;
  1520         return;
  1521         return;
  1521     }
  1522     }
  1522 
  1523 
  1523     fsm->sii_start = get_cycles();
  1524     fsm->sii_start = get_cycles();
  1524 
  1525 
  1525     // issue check/fetch command
  1526     // issue check/fetch datagram
  1526     ec_command_nprd(command, fsm->slave->station_address, 0x502, 2);
  1527     ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 2);
  1527     ec_master_queue_command(fsm->master, command);
  1528     ec_master_queue_datagram(fsm->master, datagram);
  1528     fsm->sii_state = ec_fsm_sii_write_check2;
  1529     fsm->sii_state = ec_fsm_sii_write_check2;
  1529 }
  1530 }
  1530 
  1531 
  1531 /*****************************************************************************/
  1532 /*****************************************************************************/
  1532 
  1533 
  1534    SII state: WRITE_CHECK2.
  1535    SII state: WRITE_CHECK2.
  1535 */
  1536 */
  1536 
  1537 
  1537 void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */)
  1538 void ec_fsm_sii_write_check2(ec_fsm_t *fsm /**< finite state machine */)
  1538 {
  1539 {
  1539     ec_command_t *command = &fsm->command;
  1540     ec_datagram_t *datagram = &fsm->datagram;
  1540 
  1541 
  1541     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
  1542     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
  1542         EC_ERR("SII: Reception of write check command failed.\n");
  1543         EC_ERR("SII: Reception of write check datagram failed.\n");
  1543         fsm->sii_state = ec_fsm_sii_error;
  1544         fsm->sii_state = ec_fsm_sii_error;
  1544         return;
  1545         return;
  1545     }
  1546     }
  1546 
  1547 
  1547     if (EC_READ_U8(command->data + 1) & 0x82) {
  1548     if (EC_READ_U8(datagram->data + 1) & 0x82) {
  1548         // still busy... timeout?
  1549         // still busy... timeout?
  1549         if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) {
  1550         if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) {
  1550             EC_ERR("SII: Write timeout.\n");
  1551             EC_ERR("SII: Write timeout.\n");
  1551             fsm->sii_state = ec_fsm_sii_error;
  1552             fsm->sii_state = ec_fsm_sii_error;
  1552         }
  1553         }
  1553 
  1554 
  1554         // issue check/fetch command again
  1555         // issue check/fetch datagram again
  1555         ec_master_queue_command(fsm->master, command);
  1556         ec_master_queue_datagram(fsm->master, datagram);
  1556     }
  1557     }
  1557     else if (EC_READ_U8(command->data + 1) & 0x40) {
  1558     else if (EC_READ_U8(datagram->data + 1) & 0x40) {
  1558         EC_ERR("SII: Write operation failed!\n");
  1559         EC_ERR("SII: Write operation failed!\n");
  1559         fsm->sii_state = ec_fsm_sii_error;
  1560         fsm->sii_state = ec_fsm_sii_error;
  1560     }
  1561     }
  1561     else { // success
  1562     else { // success
  1562         fsm->sii_state = ec_fsm_sii_end;
  1563         fsm->sii_state = ec_fsm_sii_end;
  1593    Change state: START.
  1594    Change state: START.
  1594 */
  1595 */
  1595 
  1596 
  1596 void ec_fsm_change_start(ec_fsm_t *fsm /**< finite state machine */)
  1597 void ec_fsm_change_start(ec_fsm_t *fsm /**< finite state machine */)
  1597 {
  1598 {
  1598     ec_command_t *command = &fsm->command;
  1599     ec_datagram_t *datagram = &fsm->datagram;
  1599     ec_slave_t *slave = fsm->slave;
  1600     ec_slave_t *slave = fsm->slave;
  1600 
  1601 
  1601     // write new state to slave
  1602     // write new state to slave
  1602     ec_command_npwr(command, slave->station_address, 0x0120, 2);
  1603     ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2);
  1603     EC_WRITE_U16(command->data, fsm->change_new);
  1604     EC_WRITE_U16(datagram->data, fsm->change_new);
  1604     ec_master_queue_command(fsm->master, command);
  1605     ec_master_queue_datagram(fsm->master, datagram);
  1605     fsm->change_state = ec_fsm_change_check;
  1606     fsm->change_state = ec_fsm_change_check;
  1606 }
  1607 }
  1607 
  1608 
  1608 /*****************************************************************************/
  1609 /*****************************************************************************/
  1609 
  1610 
  1611    Change state: CHECK.
  1612    Change state: CHECK.
  1612 */
  1613 */
  1613 
  1614 
  1614 void ec_fsm_change_check(ec_fsm_t *fsm /**< finite state machine */)
  1615 void ec_fsm_change_check(ec_fsm_t *fsm /**< finite state machine */)
  1615 {
  1616 {
  1616     ec_command_t *command = &fsm->command;
  1617     ec_datagram_t *datagram = &fsm->datagram;
  1617     ec_slave_t *slave = fsm->slave;
  1618     ec_slave_t *slave = fsm->slave;
  1618 
  1619 
  1619     if (command->state != EC_CMD_RECEIVED) {
  1620     if (datagram->state != EC_CMD_RECEIVED) {
  1620         fsm->change_state = ec_fsm_change_error;
  1621         fsm->change_state = ec_fsm_change_error;
  1621         EC_ERR("Failed to send state command to slave %i!\n",
  1622         EC_ERR("Failed to send state datagram to slave %i!\n",
  1622                fsm->slave->ring_position);
  1623                fsm->slave->ring_position);
  1623         return;
  1624         return;
  1624     }
  1625     }
  1625 
  1626 
  1626     if (command->working_counter != 1) {
  1627     if (datagram->working_counter != 1) {
  1627         fsm->change_state = ec_fsm_change_error;
  1628         fsm->change_state = ec_fsm_change_error;
  1628         EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not"
  1629         EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not"
  1629                " respond.\n", fsm->change_new, fsm->slave->ring_position);
  1630                " respond.\n", fsm->change_new, fsm->slave->ring_position);
  1630         return;
  1631         return;
  1631     }
  1632     }
  1632 
  1633 
  1633     fsm->change_start = get_cycles();
  1634     fsm->change_start = get_cycles();
  1634 
  1635 
  1635     // read AL status from slave
  1636     // read AL status from slave
  1636     ec_command_nprd(command, slave->station_address, 0x0130, 2);
  1637     ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
  1637     ec_master_queue_command(fsm->master, command);
  1638     ec_master_queue_datagram(fsm->master, datagram);
  1638     fsm->change_state = ec_fsm_change_status;
  1639     fsm->change_state = ec_fsm_change_status;
  1639 }
  1640 }
  1640 
  1641 
  1641 /*****************************************************************************/
  1642 /*****************************************************************************/
  1642 
  1643 
  1644    Change state: STATUS.
  1645    Change state: STATUS.
  1645 */
  1646 */
  1646 
  1647 
  1647 void ec_fsm_change_status(ec_fsm_t *fsm /**< finite state machine */)
  1648 void ec_fsm_change_status(ec_fsm_t *fsm /**< finite state machine */)
  1648 {
  1649 {
  1649     ec_command_t *command = &fsm->command;
  1650     ec_datagram_t *datagram = &fsm->datagram;
  1650     ec_slave_t *slave = fsm->slave;
  1651     ec_slave_t *slave = fsm->slave;
  1651 
  1652 
  1652     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
  1653     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
  1653         fsm->change_state = ec_fsm_change_error;
  1654         fsm->change_state = ec_fsm_change_error;
  1654         EC_ERR("Failed to check state 0x%02X on slave %i.\n",
  1655         EC_ERR("Failed to check state 0x%02X on slave %i.\n",
  1655                fsm->change_new, slave->ring_position);
  1656                fsm->change_new, slave->ring_position);
  1656         return;
  1657         return;
  1657     }
  1658     }
  1658 
  1659 
  1659     slave->current_state = EC_READ_U8(command->data);
  1660     slave->current_state = EC_READ_U8(datagram->data);
  1660 
  1661 
  1661     if (slave->current_state == fsm->change_new) {
  1662     if (slave->current_state == fsm->change_new) {
  1662         // state has been set successfully
  1663         // state has been set successfully
  1663         fsm->change_state = ec_fsm_change_end;
  1664         fsm->change_state = ec_fsm_change_end;
  1664         return;
  1665         return;
  1669         fsm->change_new = slave->current_state & 0x0F;
  1670         fsm->change_new = slave->current_state & 0x0F;
  1670         EC_ERR("Failed to set state 0x%02X - Slave %i refused state change"
  1671         EC_ERR("Failed to set state 0x%02X - Slave %i refused state change"
  1671                " (code 0x%02X)!\n", fsm->change_new, slave->ring_position,
  1672                " (code 0x%02X)!\n", fsm->change_new, slave->ring_position,
  1672                slave->current_state);
  1673                slave->current_state);
  1673         // fetch AL status error code
  1674         // fetch AL status error code
  1674         ec_command_nprd(command, slave->station_address, 0x0134, 2);
  1675         ec_datagram_nprd(datagram, slave->station_address, 0x0134, 2);
  1675         ec_master_queue_command(fsm->master, command);
  1676         ec_master_queue_datagram(fsm->master, datagram);
  1676         fsm->change_state = ec_fsm_change_code;
  1677         fsm->change_state = ec_fsm_change_code;
  1677         return;
  1678         return;
  1678     }
  1679     }
  1679 
  1680 
  1680     if (get_cycles() - fsm->change_start >= (cycles_t) 10 * cpu_khz) {
  1681     if (get_cycles() - fsm->change_start >= (cycles_t) 10 * cpu_khz) {
  1684                fsm->change_new, slave->ring_position);
  1685                fsm->change_new, slave->ring_position);
  1685         return;
  1686         return;
  1686     }
  1687     }
  1687 
  1688 
  1688     // still old state: check again
  1689     // still old state: check again
  1689     ec_command_nprd(command, slave->station_address, 0x0130, 2);
  1690     ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
  1690     ec_master_queue_command(fsm->master, command);
  1691     ec_master_queue_datagram(fsm->master, datagram);
  1691 }
  1692 }
  1692 
  1693 
  1693 /*****************************************************************************/
  1694 /*****************************************************************************/
  1694 
  1695 
  1695 /**
  1696 /**
  1722    Change state: CODE.
  1723    Change state: CODE.
  1723 */
  1724 */
  1724 
  1725 
  1725 void ec_fsm_change_code(ec_fsm_t *fsm /**< finite state machine */)
  1726 void ec_fsm_change_code(ec_fsm_t *fsm /**< finite state machine */)
  1726 {
  1727 {
  1727     ec_command_t *command = &fsm->command;
  1728     ec_datagram_t *datagram = &fsm->datagram;
  1728     ec_slave_t *slave = fsm->slave;
  1729     ec_slave_t *slave = fsm->slave;
  1729     uint32_t code;
  1730     uint32_t code;
  1730     const ec_code_msg_t *al_msg;
  1731     const ec_code_msg_t *al_msg;
  1731 
  1732 
  1732     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
  1733     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
  1733         fsm->change_state = ec_fsm_change_error;
  1734         fsm->change_state = ec_fsm_change_error;
  1734         EC_ERR("Reception of AL status code command failed.\n");
  1735         EC_ERR("Reception of AL status code datagram failed.\n");
  1735         return;
  1736         return;
  1736     }
  1737     }
  1737 
  1738 
  1738     if ((code = EC_READ_U16(command->data))) {
  1739     if ((code = EC_READ_U16(datagram->data))) {
  1739         for (al_msg = al_status_messages; al_msg->code; al_msg++) {
  1740         for (al_msg = al_status_messages; al_msg->code; al_msg++) {
  1740             if (al_msg->code != code) continue;
  1741             if (al_msg->code != code) continue;
  1741             EC_ERR("AL status message 0x%04X: \"%s\".\n",
  1742             EC_ERR("AL status message 0x%04X: \"%s\".\n",
  1742                    al_msg->code, al_msg->message);
  1743                    al_msg->code, al_msg->message);
  1743             break;
  1744             break;
  1745         if (!al_msg->code)
  1746         if (!al_msg->code)
  1746             EC_ERR("Unknown AL status code 0x%04X.\n", code);
  1747             EC_ERR("Unknown AL status code 0x%04X.\n", code);
  1747     }
  1748     }
  1748 
  1749 
  1749     // acknowledge "old" slave state
  1750     // acknowledge "old" slave state
  1750     ec_command_npwr(command, slave->station_address, 0x0120, 2);
  1751     ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2);
  1751     EC_WRITE_U16(command->data, slave->current_state);
  1752     EC_WRITE_U16(datagram->data, slave->current_state);
  1752     ec_master_queue_command(fsm->master, command);
  1753     ec_master_queue_datagram(fsm->master, datagram);
  1753     fsm->change_state = ec_fsm_change_ack;
  1754     fsm->change_state = ec_fsm_change_ack;
  1754 }
  1755 }
  1755 
  1756 
  1756 /*****************************************************************************/
  1757 /*****************************************************************************/
  1757 
  1758 
  1759    Change state: ACK.
  1760    Change state: ACK.
  1760 */
  1761 */
  1761 
  1762 
  1762 void ec_fsm_change_ack(ec_fsm_t *fsm /**< finite state machine */)
  1763 void ec_fsm_change_ack(ec_fsm_t *fsm /**< finite state machine */)
  1763 {
  1764 {
  1764     ec_command_t *command = &fsm->command;
  1765     ec_datagram_t *datagram = &fsm->datagram;
  1765     ec_slave_t *slave = fsm->slave;
  1766     ec_slave_t *slave = fsm->slave;
  1766 
  1767 
  1767     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
  1768     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
  1768         fsm->change_state = ec_fsm_change_error;
  1769         fsm->change_state = ec_fsm_change_error;
  1769         EC_ERR("Reception of state ack command failed.\n");
  1770         EC_ERR("Reception of state ack datagram failed.\n");
  1770         return;
  1771         return;
  1771     }
  1772     }
  1772 
  1773 
  1773     // read new AL status
  1774     // read new AL status
  1774     ec_command_nprd(command, slave->station_address, 0x0130, 2);
  1775     ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
  1775     ec_master_queue_command(fsm->master, command);
  1776     ec_master_queue_datagram(fsm->master, datagram);
  1776     fsm->change_state = ec_fsm_change_ack2;
  1777     fsm->change_state = ec_fsm_change_ack2;
  1777 }
  1778 }
  1778 
  1779 
  1779 /*****************************************************************************/
  1780 /*****************************************************************************/
  1780 
  1781 
  1783    Acknowledge 2.
  1784    Acknowledge 2.
  1784 */
  1785 */
  1785 
  1786 
  1786 void ec_fsm_change_ack2(ec_fsm_t *fsm /**< finite state machine */)
  1787 void ec_fsm_change_ack2(ec_fsm_t *fsm /**< finite state machine */)
  1787 {
  1788 {
  1788     ec_command_t *command = &fsm->command;
  1789     ec_datagram_t *datagram = &fsm->datagram;
  1789     ec_slave_t *slave = fsm->slave;
  1790     ec_slave_t *slave = fsm->slave;
  1790 
  1791 
  1791     if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) {
  1792     if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
  1792         fsm->change_state = ec_fsm_change_error;
  1793         fsm->change_state = ec_fsm_change_error;
  1793         EC_ERR("Reception of state ack check command failed.\n");
  1794         EC_ERR("Reception of state ack check datagram failed.\n");
  1794         return;
  1795         return;
  1795     }
  1796     }
  1796 
  1797 
  1797     slave->current_state = EC_READ_U8(command->data);
  1798     slave->current_state = EC_READ_U8(datagram->data);
  1798 
  1799 
  1799     if (slave->current_state == fsm->change_new) {
  1800     if (slave->current_state == fsm->change_new) {
  1800         fsm->change_state = ec_fsm_change_error;
  1801         fsm->change_state = ec_fsm_change_error;
  1801         EC_INFO("Acknowleged state 0x%02X on slave %i.\n",
  1802         EC_INFO("Acknowleged state 0x%02X on slave %i.\n",
  1802                 slave->current_state, slave->ring_position);
  1803                 slave->current_state, slave->ring_position);