master/fsm_master.c
changeset 637 d5d04c868e0e
parent 612 aede068f9a74
child 642 3ed80c8ed616
equal deleted inserted replaced
636:9114b3a5f9d3 637:d5d04c868e0e
   133 {
   133 {
   134     return fsm->state != ec_fsm_master_state_end
   134     return fsm->state != ec_fsm_master_state_end
   135         && fsm->state != ec_fsm_master_state_error;
   135         && fsm->state != ec_fsm_master_state_error;
   136 }
   136 }
   137 
   137 
   138 /*****************************************************************************/
       
   139 
       
   140 /**
       
   141    \return true, if the master state machine terminated gracefully
       
   142 */
       
   143 
       
   144 int ec_fsm_master_success(ec_fsm_master_t *fsm /**< master state machine */)
       
   145 {
       
   146     return fsm->state == ec_fsm_master_state_end;
       
   147 }
       
   148 
       
   149 /******************************************************************************
   138 /******************************************************************************
   150  *  operation/idle state machine
   139  *  master state machine
   151  *****************************************************************************/
   140  *****************************************************************************/
   152 
   141 
   153 /**
   142 /**
   154    Master state: START.
   143    Master state: START.
   155    Starts with getting slave count and slave states.
   144    Starts with getting slave count and slave states.
   156 */
   145 */
   157 
   146 
   158 void ec_fsm_master_state_start(ec_fsm_master_t *fsm)
   147 void ec_fsm_master_state_start(ec_fsm_master_t *fsm)
   159 {
   148 {
   160     ec_datagram_brd(fsm->datagram, 0x0130, 2);
   149     ec_datagram_brd(fsm->datagram, 0x0130, 2);
   161     ec_master_queue_datagram(fsm->master, fsm->datagram);
       
   162     fsm->state = ec_fsm_master_state_broadcast;
   150     fsm->state = ec_fsm_master_state_broadcast;
   163 }
   151 }
   164 
   152 
   165 /*****************************************************************************/
   153 /*****************************************************************************/
   166 
   154 
   174     ec_datagram_t *datagram = fsm->datagram;
   162     ec_datagram_t *datagram = fsm->datagram;
   175     unsigned int i;
   163     unsigned int i;
   176     ec_slave_t *slave;
   164     ec_slave_t *slave;
   177     ec_master_t *master = fsm->master;
   165     ec_master_t *master = fsm->master;
   178 
   166 
   179     if (datagram->state == EC_DATAGRAM_TIMED_OUT) {
   167     if (datagram->state == EC_DATAGRAM_TIMED_OUT)
   180         // always retry
   168         return; // always retry
   181         ec_master_queue_datagram(fsm->master, fsm->datagram);
       
   182         return;
       
   183     }
       
   184 
   169 
   185     if (datagram->state != EC_DATAGRAM_RECEIVED) { // EC_DATAGRAM_ERROR
   170     if (datagram->state != EC_DATAGRAM_RECEIVED) { // EC_DATAGRAM_ERROR
   186         // link is down
   171         // link is down
   187         fsm->slaves_responding = 0;
   172         fsm->slaves_responding = 0;
   188         list_for_each_entry(slave, &master->slaves, list) {
   173         list_for_each_entry(slave, &master->slaves, list) {
   258 
   243 
   259         EC_INFO("Scanning bus.\n");
   244         EC_INFO("Scanning bus.\n");
   260 
   245 
   261         // begin scanning of slaves
   246         // begin scanning of slaves
   262         fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
   247         fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
       
   248         fsm->state = ec_fsm_master_state_scan_slaves;
   263         ec_fsm_slave_start_scan(&fsm->fsm_slave, fsm->slave);
   249         ec_fsm_slave_start_scan(&fsm->fsm_slave, fsm->slave);
   264         ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately
   250         ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately
   265         fsm->state = ec_fsm_master_state_scan_slaves;
       
   266         return;
   251         return;
   267     }
   252     }
   268 
   253 
   269     // fetch state from each slave
   254     // fetch state from each slave
   270     fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
   255     fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
   271     ec_datagram_nprd(fsm->datagram, fsm->slave->station_address, 0x0130, 2);
   256     ec_datagram_nprd(fsm->datagram, fsm->slave->station_address, 0x0130, 2);
   272     ec_master_queue_datagram(master, fsm->datagram);
       
   273     fsm->retries = EC_FSM_RETRIES;
   257     fsm->retries = EC_FSM_RETRIES;
   274     fsm->state = ec_fsm_master_state_read_states;
   258     fsm->state = ec_fsm_master_state_read_states;
   275 }
   259 }
   276 
   260 
   277 /*****************************************************************************/
   261 /*****************************************************************************/
   363                        slave->ring_position, old_state);
   347                        slave->ring_position, old_state);
   364             }
   348             }
   365         }
   349         }
   366 
   350 
   367         fsm->slave = slave;
   351         fsm->slave = slave;
       
   352         fsm->state = ec_fsm_master_state_configure_slave;
   368         ec_fsm_slave_start_conf(&fsm->fsm_slave, slave);
   353         ec_fsm_slave_start_conf(&fsm->fsm_slave, slave);
   369         ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately
   354         ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately
   370         fsm->state = ec_fsm_master_state_configure_slave;
       
   371         return;
   355         return;
   372     }
   356     }
   373 
   357 
   374     // Check, if EoE processing has to be started
   358     // Check, if EoE processing has to be started
   375     ec_master_eoe_start(master);
   359     ec_master_eoe_start(master);
   389                 master->sdo_seq_master++;
   373                 master->sdo_seq_master++;
   390             }
   374             }
   391             else {
   375             else {
   392                 // start uploading SDO
   376                 // start uploading SDO
   393                 fsm->slave = slave;
   377                 fsm->slave = slave;
       
   378                 fsm->sdo_request = master->sdo_request;
   394                 fsm->state = ec_fsm_master_state_sdo_request;
   379                 fsm->state = ec_fsm_master_state_sdo_request;
   395                 fsm->sdo_request = master->sdo_request;
       
   396                 ec_fsm_coe_upload(&fsm->fsm_coe, slave, fsm->sdo_request);
   380                 ec_fsm_coe_upload(&fsm->fsm_coe, slave, fsm->sdo_request);
   397                 ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
   381                 ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
   398                 return;
   382                 return;
   399             }
   383             }
   400         }
   384         }
   444     ec_slave_t *slave = fsm->slave;
   428     ec_slave_t *slave = fsm->slave;
   445 
   429 
   446     // is there another slave to query?
   430     // is there another slave to query?
   447     if (slave->list.next != &master->slaves) {
   431     if (slave->list.next != &master->slaves) {
   448         // process next slave
   432         // process next slave
   449         fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
   433         fsm->slave = list_entry(slave->list.next, ec_slave_t, list);
   450         ec_datagram_nprd(fsm->datagram, fsm->slave->station_address,
   434         ec_datagram_nprd(fsm->datagram, fsm->slave->station_address,
   451                          0x0130, 2);
   435                          0x0130, 2);
   452         ec_master_queue_datagram(master, fsm->datagram);
       
   453         fsm->retries = EC_FSM_RETRIES;
   436         fsm->retries = EC_FSM_RETRIES;
   454         fsm->state = ec_fsm_master_state_read_states;
   437         fsm->state = ec_fsm_master_state_read_states;
   455         return;
   438         return;
   456     }
   439     }
   457 
   440 
   486 void ec_fsm_master_state_read_states(ec_fsm_master_t *fsm /**< master state machine */)
   469 void ec_fsm_master_state_read_states(ec_fsm_master_t *fsm /**< master state machine */)
   487 {
   470 {
   488     ec_slave_t *slave = fsm->slave;
   471     ec_slave_t *slave = fsm->slave;
   489     ec_datagram_t *datagram = fsm->datagram;
   472     ec_datagram_t *datagram = fsm->datagram;
   490 
   473 
   491     if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
   474     if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
   492         ec_master_queue_datagram(fsm->master, fsm->datagram);
   475         return;
   493         return;
       
   494     }
       
   495 
   476 
   496     if (datagram->state != EC_DATAGRAM_RECEIVED) {
   477     if (datagram->state != EC_DATAGRAM_RECEIVED) {
   497         EC_ERR("Failed to receive AL state datagram for slave %i"
   478         EC_ERR("Failed to receive AL state datagram for slave %i"
   498                 " (datagram state %i)\n", slave->ring_position, datagram->state);
   479                 " (datagram state %i)\n", slave->ring_position, datagram->state);
   499         fsm->state = ec_fsm_master_state_error;
   480         fsm->state = ec_fsm_master_state_error;
   511     ec_slave_set_state(slave, EC_READ_U8(datagram->data)); // set app state first
   492     ec_slave_set_state(slave, EC_READ_U8(datagram->data)); // set app state first
   512     ec_slave_set_online_state(slave, EC_SLAVE_ONLINE);
   493     ec_slave_set_online_state(slave, EC_SLAVE_ONLINE);
   513 
   494 
   514     // check, if new slave state has to be acknowledged
   495     // check, if new slave state has to be acknowledged
   515     if (slave->current_state & EC_SLAVE_STATE_ACK_ERR && !slave->error_flag) {
   496     if (slave->current_state & EC_SLAVE_STATE_ACK_ERR && !slave->error_flag) {
       
   497         fsm->state = ec_fsm_master_state_acknowledge;
   516         ec_fsm_change_ack(&fsm->fsm_change, slave);
   498         ec_fsm_change_ack(&fsm->fsm_change, slave);
   517         ec_fsm_change_exec(&fsm->fsm_change);
   499         ec_fsm_change_exec(&fsm->fsm_change);
   518         fsm->state = ec_fsm_master_state_acknowledge;
       
   519         return;
   500         return;
   520     }
   501     }
   521 
   502 
   522     ec_fsm_master_action_next_slave_state(fsm);
   503     ec_fsm_master_action_next_slave_state(fsm);
   523 }
   504 }
   590 {
   571 {
   591     ec_datagram_t *datagram = fsm->datagram;
   572     ec_datagram_t *datagram = fsm->datagram;
   592 
   573 
   593     while (fsm->slave->online_state == EC_SLAVE_ONLINE) {
   574     while (fsm->slave->online_state == EC_SLAVE_ONLINE) {
   594         if (fsm->slave->list.next == &fsm->master->slaves) { // last slave?
   575         if (fsm->slave->list.next == &fsm->master->slaves) { // last slave?
   595             fsm->state = ec_fsm_master_state_start;
   576             fsm->state = ec_fsm_master_state_end;
   596             fsm->state(fsm); // execute immediately
       
   597             return;
   577             return;
   598         }
   578         }
   599         // check next slave
   579         // check next slave
   600         fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
   580         fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
   601     }
   581     }
   604         EC_DBG("Reinitializing slave %i.\n", fsm->slave->ring_position);
   584         EC_DBG("Reinitializing slave %i.\n", fsm->slave->ring_position);
   605 
   585 
   606     // write station address
   586     // write station address
   607     ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
   587     ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
   608     EC_WRITE_U16(datagram->data, fsm->slave->station_address);
   588     EC_WRITE_U16(datagram->data, fsm->slave->station_address);
   609     ec_master_queue_datagram(fsm->master, datagram);
       
   610     fsm->retries = EC_FSM_RETRIES;
   589     fsm->retries = EC_FSM_RETRIES;
   611     fsm->state = ec_fsm_master_state_rewrite_addresses;
   590     fsm->state = ec_fsm_master_state_rewrite_addresses;
   612 }
   591 }
   613 
   592 
   614 /*****************************************************************************/
   593 /*****************************************************************************/
   668                                      )
   647                                      )
   669 {
   648 {
   670     ec_slave_t *slave = fsm->slave;
   649     ec_slave_t *slave = fsm->slave;
   671     ec_datagram_t *datagram = fsm->datagram;
   650     ec_datagram_t *datagram = fsm->datagram;
   672 
   651 
   673     if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) {
   652     if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
   674         ec_master_queue_datagram(fsm->master, fsm->datagram);
   653         return;
   675         return;
       
   676     }
       
   677 
   654 
   678     if (datagram->state != EC_DATAGRAM_RECEIVED) {
   655     if (datagram->state != EC_DATAGRAM_RECEIVED) {
   679         EC_ERR("Failed to receive address datagram for slave %i"
   656         EC_ERR("Failed to receive address datagram for slave %i"
   680                 " (datagram state %i).\n",
   657                 " (datagram state %i).\n",
   681                 slave->ring_position, datagram->state);
   658                 slave->ring_position, datagram->state);
   689         fsm->state = ec_fsm_master_state_error;
   666         fsm->state = ec_fsm_master_state_error;
   690         return;
   667         return;
   691     }
   668     }
   692 
   669 
   693     if (fsm->slave->list.next == &fsm->master->slaves) { // last slave?
   670     if (fsm->slave->list.next == &fsm->master->slaves) { // last slave?
   694         fsm->state = ec_fsm_master_state_start;
   671         fsm->state = ec_fsm_master_state_end;
   695         fsm->state(fsm); // execute immediately
       
   696         return;
   672         return;
   697     }
   673     }
   698 
   674 
   699     // check next slave
   675     // check next slave
   700     fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
   676     fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
   710 */
   686 */
   711 
   687 
   712 void ec_fsm_master_state_scan_slaves(ec_fsm_master_t *fsm /**< master state machine */)
   688 void ec_fsm_master_state_scan_slaves(ec_fsm_master_t *fsm /**< master state machine */)
   713 {
   689 {
   714     ec_master_t *master = fsm->master;
   690     ec_master_t *master = fsm->master;
   715     ec_slave_t *slave;
   691     ec_slave_t *slave = fsm->slave;
   716 
   692 
   717     if (ec_fsm_slave_exec(&fsm->fsm_slave)) // execute slave state machine
   693     if (ec_fsm_slave_exec(&fsm->fsm_slave)) // execute slave state machine
   718         return;
   694         return;
   719 
   695 
   720     // another slave to fetch?
   696     // another slave to fetch?
   721     if (fsm->slave->list.next != &master->slaves) {
   697     if (slave->list.next != &master->slaves) {
   722         fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
   698         fsm->slave = list_entry(slave->list.next, ec_slave_t, list);
   723         ec_fsm_slave_start_scan(&fsm->fsm_slave, fsm->slave);
   699         ec_fsm_slave_start_scan(&fsm->fsm_slave, fsm->slave);
   724         ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately
   700         ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately
   725         return;
   701         return;
   726     }
   702     }
   727 
   703 
   801 
   777 
   802     // check for another EEPROM write request
   778     // check for another EEPROM write request
   803     if (ec_fsm_master_action_process_eeprom(fsm))
   779     if (ec_fsm_master_action_process_eeprom(fsm))
   804         return; // processing another request
   780         return; // processing another request
   805 
   781 
   806     // restart master state machine.
   782     fsm->state = ec_fsm_master_state_end;
   807     fsm->state = ec_fsm_master_state_start;
       
   808     fsm->state(fsm); // execute immediately
       
   809 }
   783 }
   810 
   784 
   811 /*****************************************************************************/
   785 /*****************************************************************************/
   812 
   786 
   813 /**
   787 /**
   833         ec_slave_sdo_dict_info(slave, &sdo_count, &entry_count);
   807         ec_slave_sdo_dict_info(slave, &sdo_count, &entry_count);
   834         EC_DBG("Fetched %i SDOs and %i entries from slave %i.\n",
   808         EC_DBG("Fetched %i SDOs and %i entries from slave %i.\n",
   835                sdo_count, entry_count, slave->ring_position);
   809                sdo_count, entry_count, slave->ring_position);
   836     }
   810     }
   837 
   811 
   838     // restart master state machine.
   812     fsm->state = ec_fsm_master_state_end;
   839     fsm->state = ec_fsm_master_state_start;
       
   840     fsm->state(fsm); // execute immediately
       
   841 }
   813 }
   842 
   814 
   843 /*****************************************************************************/
   815 /*****************************************************************************/
   844 
   816 
   845 /**
   817 /**
   863     // SDO dictionary fetching finished
   835     // SDO dictionary fetching finished
   864 
   836 
   865     request->return_code = 1;
   837     request->return_code = 1;
   866     master->sdo_seq_master++;
   838     master->sdo_seq_master++;
   867 
   839 
   868     // restart master state machine.
   840     fsm->state = ec_fsm_master_state_end;
   869     fsm->state = ec_fsm_master_state_start;
       
   870     fsm->state(fsm); // execute immediately
       
   871 }
   841 }
   872 
   842 
   873 /*****************************************************************************/
   843 /*****************************************************************************/
   874 
   844 
   875 /**
   845 /**