master/slave.c
changeset 2060 8b67602f5161
parent 2045 ff2a13a4603c
child 2589 2b9c78543663
equal deleted inserted replaced
2059:ab0b96ac18bb 2060:8b67602f5161
   157     init_waitqueue_head(&slave->foe_queue);
   157     init_waitqueue_head(&slave->foe_queue);
   158 
   158 
   159     INIT_LIST_HEAD(&slave->soe_requests);
   159     INIT_LIST_HEAD(&slave->soe_requests);
   160     init_waitqueue_head(&slave->soe_queue);
   160     init_waitqueue_head(&slave->soe_queue);
   161 
   161 
   162     // init state machine datagram
   162     // init datagram
   163     ec_datagram_init(&slave->fsm_datagram);
   163     ec_datagram_init(&slave->datagram);
   164     snprintf(slave->fsm_datagram.name, EC_DATAGRAM_NAME_SIZE,
   164     snprintf(slave->datagram.name, EC_DATAGRAM_NAME_SIZE,
   165             "slave%u-fsm", slave->ring_position);
   165             "slave%u-fsm", slave->ring_position);
   166     ret = ec_datagram_prealloc(&slave->fsm_datagram, EC_MAX_DATA_SIZE);
   166     ret = ec_datagram_prealloc(&slave->datagram, EC_MAX_DATA_SIZE);
   167     if (ret < 0) {
   167     if (ret < 0) {
   168         ec_datagram_clear(&slave->fsm_datagram);
   168         ec_datagram_clear(&slave->datagram);
   169         EC_SLAVE_ERR(slave, "Failed to allocate FSM datagram.\n");
   169         EC_SLAVE_ERR(slave, "Failed to allocate FSM datagram.\n");
   170         return;
   170         return;
   171     }
   171     }
       
   172     ec_mbox_init(&slave->mbox,&slave->datagram);
   172 
   173 
   173     // create state machine object
   174     // create state machine object
   174     ec_fsm_slave_init(&slave->fsm, slave, &slave->fsm_datagram);
   175     ec_fsm_slave_init(&slave->fsm, slave, &slave->mbox);
   175 }
   176 }
   176 
   177 
   177 /*****************************************************************************/
   178 /*****************************************************************************/
   178 
   179 
   179 /**
   180 /**
   192     while (!list_empty(&slave->slave_sdo_requests)) {
   193     while (!list_empty(&slave->slave_sdo_requests)) {
   193         ec_master_sdo_request_t *request =
   194         ec_master_sdo_request_t *request =
   194             list_entry(slave->slave_sdo_requests.next,
   195             list_entry(slave->slave_sdo_requests.next,
   195                 ec_master_sdo_request_t, list);
   196                 ec_master_sdo_request_t, list);
   196         list_del_init(&request->list); // dequeue
   197         list_del_init(&request->list); // dequeue
   197         EC_SLAVE_WARN(slave, "Discarding SDO request,"
   198         EC_SLAVE_WARN(slave, "Discarding SDO request %p,"
   198                 " slave about to be deleted.\n");
   199                 " slave about to be deleted.\n",request);
   199         request->req.state = EC_INT_REQUEST_FAILURE;
   200         request->req.state = EC_INT_REQUEST_FAILURE;
       
   201         kref_put(&request->refcount,ec_master_sdo_request_release);
   200         wake_up(&slave->sdo_queue);
   202         wake_up(&slave->sdo_queue);
   201     }
   203     }
   202 
   204 
   203     while (!list_empty(&slave->foe_requests)) {
   205     while (!list_empty(&slave->foe_requests)) {
   204         ec_master_foe_request_t *request =
   206         ec_master_foe_request_t *request =
   206                 ec_master_foe_request_t, list);
   208                 ec_master_foe_request_t, list);
   207         list_del_init(&request->list); // dequeue
   209         list_del_init(&request->list); // dequeue
   208         EC_SLAVE_WARN(slave, "Discarding FoE request,"
   210         EC_SLAVE_WARN(slave, "Discarding FoE request,"
   209                 " slave about to be deleted.\n");
   211                 " slave about to be deleted.\n");
   210         request->req.state = EC_INT_REQUEST_FAILURE;
   212         request->req.state = EC_INT_REQUEST_FAILURE;
       
   213         kref_put(&request->refcount,ec_master_foe_request_release);
   211         wake_up(&slave->foe_queue);
   214         wake_up(&slave->foe_queue);
   212     }
   215     }
   213 
   216 
   214     while (!list_empty(&slave->soe_requests)) {
   217     while (!list_empty(&slave->soe_requests)) {
   215         ec_master_soe_request_t *request =
   218         ec_master_soe_request_t *request =
   217                 ec_master_soe_request_t, list);
   220                 ec_master_soe_request_t, list);
   218         list_del_init(&request->list); // dequeue
   221         list_del_init(&request->list); // dequeue
   219         EC_SLAVE_WARN(slave, "Discarding SoE request,"
   222         EC_SLAVE_WARN(slave, "Discarding SoE request,"
   220                 " slave about to be deleted.\n");
   223                 " slave about to be deleted.\n");
   221         request->req.state = EC_INT_REQUEST_FAILURE;
   224         request->req.state = EC_INT_REQUEST_FAILURE;
       
   225         kref_put(&request->refcount,ec_master_soe_request_release);
   222         wake_up(&slave->soe_queue);
   226         wake_up(&slave->soe_queue);
   223     }
   227     }
   224 
   228 
   225     if (slave->config)
   229     if (slave->config)
   226         ec_slave_config_detach(slave->config);
   230         ec_slave_config_detach(slave->config);
   250     }
   254     }
   251 
   255 
   252     if (slave->sii_words)
   256     if (slave->sii_words)
   253         kfree(slave->sii_words);
   257         kfree(slave->sii_words);
   254     ec_fsm_slave_clear(&slave->fsm);
   258     ec_fsm_slave_clear(&slave->fsm);
   255     ec_datagram_clear(&slave->fsm_datagram);
   259     ec_mbox_clear(&slave->mbox);
   256 }
   260 }
   257 
   261 
   258 /*****************************************************************************/
   262 /*****************************************************************************/
   259 
   263 
   260 /** Clear the sync manager array. 
   264 /** Clear the sync manager array. 
   801     }
   805     }
   802 }
   806 }
   803 
   807 
   804 /*****************************************************************************/
   808 /*****************************************************************************/
   805 
   809 
       
   810 /** returns the previous connected port of a given port.
       
   811  */
       
   812 
       
   813 unsigned int ec_slave_get_previous_port(
       
   814     ec_slave_t *slave, /**< EtherCAT slave. */
       
   815     unsigned int i /**< Port index */
       
   816     )
       
   817 {
       
   818     do
       
   819     {
       
   820         switch (i)
       
   821         {
       
   822         case 0: i = 2; break;
       
   823         case 1: i = 3; break;
       
   824         case 2: i = 1; break;
       
   825         case 3:
       
   826         default:i = 0; break;
       
   827         }
       
   828         if (slave->ports[i].next_slave)
       
   829             return i;
       
   830     } while (i);
       
   831     return 0;
       
   832 }
       
   833 
       
   834 /*****************************************************************************/
       
   835 
       
   836 /** returns the next connected port of a given port.
       
   837  */
       
   838 
       
   839 unsigned int ec_slave_get_next_port(
       
   840     ec_slave_t *slave, /**< EtherCAT slave. */
       
   841     unsigned int i /**< Port index */
       
   842     )
       
   843 {
       
   844     do
       
   845     {
       
   846         switch (i)
       
   847         {
       
   848         case 0: i = 3; break;
       
   849         case 1: i = 2; break;
       
   850         case 3: i = 1; break;
       
   851         case 2:
       
   852         default:i = 0; break;
       
   853         }
       
   854         if (slave->ports[i].next_slave)
       
   855             return i;
       
   856     } while (i);
       
   857     return 0;
       
   858 }
       
   859 
       
   860 
       
   861 /*****************************************************************************/
       
   862 
   806 /** Calculates the sum of round-trip-times of connected ports 1-3.
   863 /** Calculates the sum of round-trip-times of connected ports 1-3.
   807  */
   864  */
   808 uint32_t ec_slave_calc_rtt_sum(
   865 uint32_t ec_slave_calc_rtt_sum(
   809         ec_slave_t *slave /**< EtherCAT slave. */
   866         ec_slave_t *slave /**< EtherCAT slave. */
   810         )
   867         )
   811 {
   868 {
   812     uint32_t rtt_sum = 0, rtt;
   869     uint32_t rtt_sum = 0, rtt;
   813     unsigned int i;
   870     unsigned int i = ec_slave_get_next_port(slave,0);
   814     
   871     while (i != 0) {
   815     for (i = 1; i < EC_MAX_PORTS; i++) {
   872         rtt = slave->ports[i].receive_time - slave->ports[ec_slave_get_previous_port(slave,i)].receive_time;
   816         if (slave->ports[i].next_slave) {
   873         rtt_sum += rtt;
   817             rtt = slave->ports[i].receive_time - slave->ports[i - 1].receive_time;
   874         i = ec_slave_get_next_port(slave,i);
   818             rtt_sum += rtt;
       
   819         }
       
   820     }
   875     }
   821 
   876 
   822     return rtt_sum;
   877     return rtt_sum;
   823 }
   878 }
   824 
   879 
   828  */
   883  */
   829 ec_slave_t *ec_slave_find_next_dc_slave(
   884 ec_slave_t *ec_slave_find_next_dc_slave(
   830         ec_slave_t *slave /**< EtherCAT slave. */
   885         ec_slave_t *slave /**< EtherCAT slave. */
   831         )
   886         )
   832 {
   887 {
       
   888     unsigned int i;
   833     ec_slave_t *dc_slave = NULL;
   889     ec_slave_t *dc_slave = NULL;
   834 
   890 
   835     if (slave->base_dc_supported) {
   891     if (slave->base_dc_supported) {
   836         dc_slave = slave;
   892         dc_slave = slave;
   837     } else {
   893     } else {
   838         unsigned int i;
   894         i = ec_slave_get_next_port(slave,0);
   839 
   895         while (i != 0) {
   840         for (i = 1; i < EC_MAX_PORTS; i++) {
       
   841             ec_slave_t *next = slave->ports[i].next_slave;
   896             ec_slave_t *next = slave->ports[i].next_slave;
   842             if (next) {
   897             if (next) {
   843                 dc_slave = ec_slave_find_next_dc_slave(next);
   898                 dc_slave = ec_slave_find_next_dc_slave(next);
   844                 if (dc_slave)
   899                 if (dc_slave)
   845                     break;
   900                     break;
   846             }
   901             }
       
   902             i = ec_slave_get_next_port(slave,i);
   847         }
   903         }
   848     }
   904     }
   849 
   905 
   850     return dc_slave;
   906     return dc_slave;
   851 }
   907 }
   857 void ec_slave_calc_port_delays(
   913 void ec_slave_calc_port_delays(
   858         ec_slave_t *slave /**< EtherCAT slave. */
   914         ec_slave_t *slave /**< EtherCAT slave. */
   859         )
   915         )
   860 {
   916 {
   861     unsigned int i;
   917     unsigned int i;
   862     ec_slave_t *next, *next_dc;
   918     ec_slave_t *next_dc;
   863     uint32_t rtt, next_rtt_sum;
   919     uint32_t rtt, next_rtt_sum;
   864 
   920 
   865     if (!slave->base_dc_supported)
   921     if (!slave->base_dc_supported)
   866         return;
   922         return;
   867 
   923 
   868     for (i = 1; i < EC_MAX_PORTS; i++) {
   924     i = ec_slave_get_next_port(slave,0);
   869         next = slave->ports[i].next_slave;
   925     while (i != 0) {
   870         if (!next)
   926         next_dc = ec_slave_find_next_dc_slave(slave->ports[i].next_slave);
   871             continue;
   927         if (next_dc) {
   872         next_dc = ec_slave_find_next_dc_slave(next);
   928             rtt = slave->ports[i].receive_time - slave->ports[ec_slave_get_previous_port(slave,i)].receive_time;
   873         if (!next_dc)
   929             next_rtt_sum = ec_slave_calc_rtt_sum(next_dc);
   874             continue;
   930 
   875 
   931             slave->ports[i].delay_to_next_dc = (rtt - next_rtt_sum) / 2; // FIXME
   876         rtt = slave->ports[i].receive_time - slave->ports[i - 1].receive_time;
   932             next_dc->ports[0].delay_to_next_dc = (rtt - next_rtt_sum) / 2;
   877         next_rtt_sum = ec_slave_calc_rtt_sum(next_dc);
       
   878 
       
   879         slave->ports[i].delay_to_next_dc = (rtt - next_rtt_sum) / 2; // FIXME
       
   880         next_dc->ports[0].delay_to_next_dc = (rtt - next_rtt_sum) / 2;
       
   881 
   933 
   882 #if 0
   934 #if 0
   883         EC_SLAVE_DBG(slave, 1, "delay %u:%u rtt=%u"
   935             EC_SLAVE_DBG(slave, 1, "delay %u:%u rtt=%u"
   884                 " next_rtt_sum=%u delay=%u\n",
   936                     " next_rtt_sum=%u delay=%u\n",
   885                 slave->ring_position, i, rtt, next_rtt_sum,
   937                     slave->ring_position, i, rtt, next_rtt_sum,
   886                 slave->ports[i].delay_to_next_dc);
   938                     slave->ports[i].delay_to_next_dc);
   887 #endif
   939 #endif
       
   940         }
       
   941         i = ec_slave_get_next_port(slave,i);
   888     }
   942     }
   889 }
   943 }
   890 
   944 
   891 /*****************************************************************************/
   945 /*****************************************************************************/
   892 
   946 
   896         ec_slave_t *slave, /**< Current slave. */
   950         ec_slave_t *slave, /**< Current slave. */
   897         uint32_t *delay /**< Sum of delays. */
   951         uint32_t *delay /**< Sum of delays. */
   898         )
   952         )
   899 {
   953 {
   900     unsigned int i;
   954     unsigned int i;
   901     ec_slave_t *next, *next_dc;
   955     ec_slave_t *next_dc;
   902 
   956 
   903 #if 0
   957 #if 1
   904     EC_SLAVE_DBG(slave, 1, "%u\n", *delay);
   958     EC_SLAVE_DBG(slave, 1, "%u\n", *delay);
   905 #endif
   959 #endif
   906 
   960 
   907     slave->transmission_delay = *delay;
   961     slave->transmission_delay = *delay;
   908 
   962 
   909     for (i = 1; i < EC_MAX_PORTS; i++) {
   963     i = ec_slave_get_next_port(slave,0);
       
   964     while (i != 0) {
   910         ec_slave_port_t *port = &slave->ports[i];
   965         ec_slave_port_t *port = &slave->ports[i];
   911         next = port->next_slave;
   966         next_dc = ec_slave_find_next_dc_slave(port->next_slave);
   912         if (!next)
   967         if (next_dc) {
   913             continue;
   968             *delay = *delay + port->delay_to_next_dc;
   914         next_dc = ec_slave_find_next_dc_slave(next);
       
   915         if (!next_dc)
       
   916             continue;
       
   917 
       
   918         *delay = *delay + port->delay_to_next_dc;
       
   919 #if 0
   969 #if 0
   920         EC_SLAVE_DBG(slave, 1, "%u:%u %u\n", slave->ring_position, i, *delay);
   970             EC_SLAVE_DBG(slave, 1, "%u:%u %u\n", slave->ring_position, i, *delay);
   921 #endif
   971 #endif
   922         ec_slave_calc_transmission_delays_rec(next_dc, delay);
   972             ec_slave_calc_transmission_delays_rec(next_dc, delay);
       
   973         }
       
   974         i = ec_slave_get_next_port(slave,i);
   923     }
   975     }
   924 
   976 
   925     *delay = *delay + slave->ports[0].delay_to_next_dc;
   977     *delay = *delay + slave->ports[0].delay_to_next_dc;
   926 }
   978 }
   927 
   979