672 ) |
672 ) |
673 { |
673 { |
674 ec_datagram_t *datagram, *next; |
674 ec_datagram_t *datagram, *next; |
675 size_t queue_size = 0; |
675 size_t queue_size = 0; |
676 |
676 |
677 if (master->fsm_queue_lock_cb) |
677 if (master->fsm_queue_lock_cb) { |
678 master->fsm_queue_lock_cb(master->fsm_queue_locking_data); |
678 master->fsm_queue_lock_cb(master->fsm_queue_locking_data); |
|
679 } |
|
680 |
679 if (ec_mutex_trylock(&master->fsm_queue_mutex) == 0) { |
681 if (ec_mutex_trylock(&master->fsm_queue_mutex) == 0) { |
680 if (master->fsm_queue_unlock_cb) |
682 goto unlock_cb; |
681 master->fsm_queue_unlock_cb(master->fsm_queue_locking_data); |
683 } |
682 return; |
684 |
683 } |
|
684 if (list_empty(&master->fsm_datagram_queue)) { |
685 if (list_empty(&master->fsm_datagram_queue)) { |
685 ec_mutex_unlock(&master->fsm_queue_mutex); |
686 goto unlock; |
686 if (master->fsm_queue_unlock_cb) |
687 } |
687 master->fsm_queue_unlock_cb(master->fsm_queue_locking_data); |
688 |
688 return; |
|
689 } |
|
690 list_for_each_entry(datagram, &master->datagram_queue, queue) { |
689 list_for_each_entry(datagram, &master->datagram_queue, queue) { |
691 queue_size += datagram->data_size; |
690 queue_size += datagram->data_size; |
692 } |
691 } |
693 |
692 |
694 list_for_each_entry_safe(datagram, next, &master->fsm_datagram_queue, |
693 list_for_each_entry_safe(datagram, next, &master->fsm_datagram_queue, |
702 datagram->data_size, queue_size); |
701 datagram->data_size, queue_size); |
703 #endif |
702 #endif |
704 #ifdef EC_HAVE_CYCLES |
703 #ifdef EC_HAVE_CYCLES |
705 datagram->cycles_sent = 0; |
704 datagram->cycles_sent = 0; |
706 #endif |
705 #endif |
707 datagram->jiffies_sent = 0; |
706 datagram->jiffies_sent = 0; // FIXME why? |
708 ec_master_queue_datagram(master, datagram); |
707 ec_master_queue_datagram(master, datagram); |
709 } |
708 } else { |
710 else { |
|
711 if (datagram->data_size > master->max_queue_size) { |
709 if (datagram->data_size > master->max_queue_size) { |
712 list_del_init(&datagram->fsm_queue); |
710 list_del_init(&datagram->fsm_queue); |
713 datagram->state = EC_DATAGRAM_ERROR; |
711 datagram->state = EC_DATAGRAM_ERROR; |
714 EC_MASTER_ERR(master, "Fsm datagram %p is too large," |
712 EC_MASTER_ERR(master, "Fsm datagram %p is too large," |
715 " size=%zu, max_queue_size=%zu\n", |
713 " size=%zu, max_queue_size=%zu\n", |
775 master->max_queue_size -= master->max_queue_size / 10; |
777 master->max_queue_size -= master->max_queue_size / 10; |
776 } |
778 } |
777 |
779 |
778 /*****************************************************************************/ |
780 /*****************************************************************************/ |
779 |
781 |
780 /** Places an request (SDO/FoE/SoE/EoE) fsm datagram in the sdo datagram queue. |
782 /** Places an request (SDO/FoE/SoE/EoE) fsm datagram in the sdo datagram |
|
783 * queue. |
781 */ |
784 */ |
782 void ec_master_queue_request_fsm_datagram( |
785 void ec_master_queue_request_fsm_datagram( |
783 ec_master_t *master, /**< EtherCAT master */ |
786 ec_master_t *master, /**< EtherCAT master */ |
784 ec_datagram_t *datagram /**< datagram */ |
787 ec_datagram_t *datagram /**< datagram */ |
785 ) |
788 ) |
786 { |
789 { |
787 ec_master_queue_fsm_datagram(master,datagram); |
790 ec_master_queue_fsm_datagram(master, datagram); |
788 master->fsm.idle = 0; // pump the bus as fast as possible |
791 master->fsm.idle = 0; // pump the bus as fast as possible |
789 } |
792 } |
790 |
793 |
791 /*****************************************************************************/ |
794 /*****************************************************************************/ |
792 |
795 |
793 /** Places an fsm datagram in the sdo datagram queue. |
796 /** Places an fsm datagram in the sdo datagram queue. |
797 ec_datagram_t *datagram /**< datagram */ |
800 ec_datagram_t *datagram /**< datagram */ |
798 ) |
801 ) |
799 { |
802 { |
800 ec_datagram_t *queued_datagram; |
803 ec_datagram_t *queued_datagram; |
801 |
804 |
802 if (master->fsm_queue_lock_cb) |
805 if (master->fsm_queue_lock_cb) { |
803 master->fsm_queue_lock_cb(master->fsm_queue_locking_data); |
806 master->fsm_queue_lock_cb(master->fsm_queue_locking_data); |
|
807 } |
804 ec_mutex_lock(&master->fsm_queue_mutex); |
808 ec_mutex_lock(&master->fsm_queue_mutex); |
805 |
809 |
806 // check, if the datagram is already queued |
810 // check, if the datagram is already queued |
807 list_for_each_entry(queued_datagram, &master->fsm_datagram_queue, |
811 list_for_each_entry(queued_datagram, &master->fsm_datagram_queue, |
808 fsm_queue) { |
812 fsm_queue) { |
809 if (queued_datagram == datagram) { |
813 if (queued_datagram == datagram) { |
810 datagram->state = EC_DATAGRAM_QUEUED; |
814 datagram->state = EC_DATAGRAM_QUEUED; |
811 ec_mutex_unlock(&master->fsm_queue_mutex); |
815 goto unlock; |
812 if (master->fsm_queue_unlock_cb) |
|
813 master->fsm_queue_unlock_cb(master->fsm_queue_locking_data); |
|
814 return; |
|
815 } |
816 } |
816 } |
817 } |
817 |
818 |
818 #if DEBUG_INJECT |
819 #if DEBUG_INJECT |
819 EC_MASTER_DBG(master, 2, "Requesting fsm datagram %p size=%zu\n", |
820 EC_MASTER_DBG(master, 2, "Requesting fsm datagram %p size=%zu\n", |
823 list_add_tail(&datagram->fsm_queue, &master->fsm_datagram_queue); |
824 list_add_tail(&datagram->fsm_queue, &master->fsm_datagram_queue); |
824 datagram->state = EC_DATAGRAM_QUEUED; |
825 datagram->state = EC_DATAGRAM_QUEUED; |
825 #ifdef EC_HAVE_CYCLES |
826 #ifdef EC_HAVE_CYCLES |
826 datagram->cycles_sent = get_cycles(); |
827 datagram->cycles_sent = get_cycles(); |
827 #endif |
828 #endif |
828 datagram->jiffies_sent = jiffies; |
829 datagram->jiffies_sent = jiffies; // FIXME why? |
829 |
830 |
|
831 unlock: |
830 ec_mutex_unlock(&master->fsm_queue_mutex); |
832 ec_mutex_unlock(&master->fsm_queue_mutex); |
831 if (master->fsm_queue_unlock_cb) |
833 if (master->fsm_queue_unlock_cb) { |
832 master->fsm_queue_unlock_cb(master->fsm_queue_locking_data); |
834 master->fsm_queue_unlock_cb(master->fsm_queue_locking_data); |
|
835 } |
833 } |
836 } |
834 |
837 |
835 /*****************************************************************************/ |
838 /*****************************************************************************/ |
836 |
839 |
837 /** Places a datagram in the datagram queue. |
840 /** Places a datagram in the datagram queue. |
927 } |
930 } |
928 |
931 |
929 list_add_tail(&datagram->sent, &sent_datagrams); |
932 list_add_tail(&datagram->sent, &sent_datagrams); |
930 datagram->index = master->datagram_index++; |
933 datagram->index = master->datagram_index++; |
931 |
934 |
932 EC_MASTER_DBG(master, 2, "adding datagram %p i=0x%02X size=%zu\n",datagram, |
935 EC_MASTER_DBG(master, 2, "Adding datagram %p i=0x%02X size=%zu\n", |
933 datagram->index,datagram_size); |
936 datagram, datagram->index,datagram_size); |
934 |
937 |
935 // set "datagram following" flag in previous frame |
938 // set "datagram following" flag in previous frame |
936 if (follows_word) |
939 if (follows_word) { |
937 EC_WRITE_U16(follows_word, EC_READ_U16(follows_word) | 0x8000); |
940 EC_WRITE_U16(follows_word, |
|
941 EC_READ_U16(follows_word) | 0x8000); |
|
942 } |
938 |
943 |
939 // EtherCAT datagram header |
944 // EtherCAT datagram header |
940 EC_WRITE_U8 (cur_data, datagram->type); |
945 EC_WRITE_U8 (cur_data, datagram->type); |
941 EC_WRITE_U8 (cur_data + 1, datagram->index); |
946 EC_WRITE_U8 (cur_data + 1, datagram->index); |
942 memcpy(cur_data + 2, datagram->address, EC_ADDR_LEN); |
947 memcpy(cur_data + 2, datagram->address, EC_ADDR_LEN); |
946 cur_data += EC_DATAGRAM_HEADER_SIZE; |
951 cur_data += EC_DATAGRAM_HEADER_SIZE; |
947 |
952 |
948 // EtherCAT datagram data |
953 // EtherCAT datagram data |
949 frame_datagram_data = cur_data; |
954 frame_datagram_data = cur_data; |
950 if (datagram->domain) { |
955 if (datagram->domain) { |
951 unsigned int datagram_address = EC_READ_U32(datagram->address); |
956 unsigned int datagram_address = |
|
957 EC_READ_U32(datagram->address); |
952 int i = 0; |
958 int i = 0; |
953 uint8_t *domain_data = datagram->data; |
959 uint8_t *domain_data = datagram->data; |
954 list_for_each_entry(domain_fmmu, &datagram->domain->fmmu_configs, list) { |
960 list_for_each_entry(domain_fmmu, |
|
961 &datagram->domain->fmmu_configs, list) { |
955 if (domain_fmmu->dir == EC_DIR_OUTPUT ) { |
962 if (domain_fmmu->dir == EC_DIR_OUTPUT ) { |
956 unsigned int frame_offset = domain_fmmu->logical_start_address-datagram_address; |
963 unsigned int frame_offset = |
957 memcpy(frame_datagram_data+frame_offset, domain_data, domain_fmmu->data_size); |
964 domain_fmmu->logical_start_address |
|
965 - datagram_address; |
|
966 memcpy(frame_datagram_data+frame_offset, domain_data, |
|
967 domain_fmmu->data_size); |
958 if (unlikely(master->debug_level > 1)) { |
968 if (unlikely(master->debug_level > 1)) { |
959 EC_DBG("sending dg %p i=0x%02X fmmu %u fp=%u dp=%zu size=%u\n", |
969 EC_DBG("sending dg %p i=0x%02X fmmu %u fp=%u" |
960 datagram,datagram->index, i,frame_offset,domain_data-datagram->data,domain_fmmu->data_size); |
970 " dp=%zu size=%u\n", |
961 ec_print_data(domain_data, domain_fmmu->data_size); |
971 datagram, datagram->index, i, |
|
972 frame_offset, |
|
973 domain_data - datagram->data, |
|
974 domain_fmmu->data_size); |
|
975 ec_print_data(domain_data, |
|
976 domain_fmmu->data_size); |
962 } |
977 } |
963 } |
978 } |
964 domain_data += domain_fmmu->data_size; |
979 domain_data += domain_fmmu->data_size; |
965 ++i; |
980 ++i; |
966 } |
981 } |
967 } |
982 } else { |
968 else { |
983 memcpy(frame_datagram_data, datagram->data, |
969 memcpy(frame_datagram_data, datagram->data, datagram->data_size); |
984 datagram->data_size); |
970 } |
985 } |
971 cur_data += datagram->data_size; |
986 cur_data += datagram->data_size; |
972 |
987 |
973 // EtherCAT datagram footer |
988 // EtherCAT datagram footer |
974 EC_WRITE_U16(cur_data, 0x0000); // reset working counter |
989 EC_WRITE_U16(cur_data, 0x0000); // reset working counter |
1121 |
1136 |
1122 cur_data += data_size + EC_DATAGRAM_FOOTER_SIZE; |
1137 cur_data += data_size + EC_DATAGRAM_FOOTER_SIZE; |
1123 continue; |
1138 continue; |
1124 } |
1139 } |
1125 frame_datagram_data = cur_data; |
1140 frame_datagram_data = cur_data; |
|
1141 |
1126 if (datagram->domain) { |
1142 if (datagram->domain) { |
1127 size_t datagram_address = EC_READ_U32(datagram->address); |
1143 size_t datagram_address = EC_READ_U32(datagram->address); |
1128 int i = 0; |
1144 int i = 0; |
1129 uint8_t *domain_data = datagram->data; |
1145 uint8_t *domain_data = datagram->data; |
1130 list_for_each_entry(domain_fmmu, &datagram->domain->fmmu_configs, list) { |
1146 |
1131 if (domain_fmmu->dir == EC_DIR_INPUT ) { |
1147 list_for_each_entry(domain_fmmu, &datagram->domain->fmmu_configs, |
1132 unsigned int frame_offset = domain_fmmu->logical_start_address-datagram_address; |
1148 list) { |
1133 memcpy(domain_data, frame_datagram_data+frame_offset, domain_fmmu->data_size); |
1149 if (domain_fmmu->dir == EC_DIR_INPUT) { |
|
1150 unsigned int frame_offset = |
|
1151 domain_fmmu->logical_start_address - datagram_address; |
|
1152 memcpy(domain_data, frame_datagram_data + frame_offset, |
|
1153 domain_fmmu->data_size); |
1134 if (unlikely(master->debug_level > 1)) { |
1154 if (unlikely(master->debug_level > 1)) { |
1135 EC_DBG("receiving dg %p i=0x%02X fmmu %u fp=%u dp=%zu size=%u\n", |
1155 EC_DBG("receiving dg %p i=0x%02X fmmu %u fp=%u" |
1136 datagram,datagram->index, i, |
1156 " dp=%zu size=%u\n", |
1137 frame_offset,domain_data-datagram->data,domain_fmmu->data_size); |
1157 datagram, datagram->index, i, |
|
1158 frame_offset, domain_data - datagram->data, |
|
1159 domain_fmmu->data_size); |
1138 ec_print_data(domain_data, domain_fmmu->data_size); |
1160 ec_print_data(domain_data, domain_fmmu->data_size); |
1139 } |
1161 } |
1140 } |
1162 } |
1141 domain_data += domain_fmmu->data_size; |
1163 domain_data += domain_fmmu->data_size; |
1142 ++i; |
1164 ++i; |
1143 } |
1165 } |
1144 } |
1166 } else { |
1145 else { |
|
1146 // copy received data into the datagram memory |
1167 // copy received data into the datagram memory |
1147 memcpy(datagram->data, frame_datagram_data, data_size); |
1168 memcpy(datagram->data, frame_datagram_data, data_size); |
1148 } |
1169 } |
1149 cur_data += data_size; |
1170 cur_data += data_size; |
1150 |
1171 |
1280 static int ec_master_idle_thread(void *priv_data) |
1301 static int ec_master_idle_thread(void *priv_data) |
1281 { |
1302 { |
1282 ec_master_t *master = (ec_master_t *) priv_data; |
1303 ec_master_t *master = (ec_master_t *) priv_data; |
1283 ec_slave_t *slave = NULL; |
1304 ec_slave_t *slave = NULL; |
1284 size_t sent_bytes; |
1305 size_t sent_bytes; |
|
1306 |
1285 // send interval in IDLE phase |
1307 // send interval in IDLE phase |
1286 ec_master_set_send_interval(master, 1000000 / HZ); |
1308 ec_master_set_send_interval(master, 1000000 / HZ); |
1287 |
1309 |
1288 EC_MASTER_DBG(master, 1, "Idle thread running with send interval = %u us," |
1310 EC_MASTER_DBG(master, 1, "Idle thread running with send interval = %u us," |
1289 " max data size=%zu\n", master->send_interval, |
1311 " max data size=%zu\n", master->send_interval, |
1296 ec_mutex_lock(&master->io_mutex); |
1318 ec_mutex_lock(&master->io_mutex); |
1297 ecrt_master_receive(master); |
1319 ecrt_master_receive(master); |
1298 ec_mutex_unlock(&master->io_mutex); |
1320 ec_mutex_unlock(&master->io_mutex); |
1299 |
1321 |
1300 // execute master & slave state machines |
1322 // execute master & slave state machines |
1301 if (ec_mutex_lock_interruptible(&master->master_mutex)) |
1323 if (ec_mutex_lock_interruptible(&master->master_mutex)) { |
1302 break; |
1324 break; |
|
1325 } |
1303 if (ec_fsm_master_exec(&master->fsm)) { |
1326 if (ec_fsm_master_exec(&master->fsm)) { |
1304 ec_master_mbox_queue_datagrams(master, &master->fsm_mbox); |
1327 ec_master_mbox_queue_datagrams(master, &master->fsm_mbox); |
1305 } |
1328 } |
1306 for (slave = master->slaves; |
1329 for (slave = master->slaves; |
1307 slave < master->slaves + master->slave_count; |
1330 slave < master->slaves + master->slave_count; |
1308 slave++) { |
1331 slave++) { |
1309 ec_fsm_slave_exec(&slave->fsm); // may queue datagram in fsm queue |
1332 ec_fsm_slave_exec(&slave->fsm); // may queue datagram in fsm queue |
1310 } |
1333 } |
1311 #if defined(EC_EOE) |
1334 #if defined(EC_EOE) |
1312 if (!ec_master_eoe_processing(master)) |
1335 if (!ec_master_eoe_processing(master)) { |
1313 master->fsm.idle = 0; // pump the bus as fast as possible |
1336 master->fsm.idle = 0; // pump the bus as fast as possible |
|
1337 } |
1314 #endif |
1338 #endif |
1315 ec_mutex_unlock(&master->master_mutex); |
1339 ec_mutex_unlock(&master->master_mutex); |
1316 |
1340 |
1317 // queue and send |
1341 // queue and send |
1318 ec_mutex_lock(&master->io_mutex); |
1342 ec_mutex_lock(&master->io_mutex); |
1360 |
1384 |
1361 // output statistics |
1385 // output statistics |
1362 ec_master_output_stats(master); |
1386 ec_master_output_stats(master); |
1363 |
1387 |
1364 // execute master & slave state machines |
1388 // execute master & slave state machines |
1365 if (ec_mutex_lock_interruptible(&master->master_mutex)) |
1389 if (ec_mutex_lock_interruptible(&master->master_mutex)) { |
1366 break; |
1390 break; |
1367 if (ec_fsm_master_exec(&master->fsm)) |
1391 } |
|
1392 if (ec_fsm_master_exec(&master->fsm)) { |
1368 ec_master_mbox_queue_datagrams(master, &master->fsm_mbox); |
1393 ec_master_mbox_queue_datagrams(master, &master->fsm_mbox); |
|
1394 } |
1369 for (slave = master->slaves; |
1395 for (slave = master->slaves; |
1370 slave < master->slaves + master->slave_count; |
1396 slave < master->slaves + master->slave_count; |
1371 slave++) { |
1397 slave++) { |
1372 ec_fsm_slave_exec(&slave->fsm); // may queue datagram in fsm queue |
1398 ec_fsm_slave_exec(&slave->fsm); // may queue datagram in fsm queue |
1373 } |
1399 } |
2078 |
2104 |
2079 ec_master_inject_fsm_datagrams(master); |
2105 ec_master_inject_fsm_datagrams(master); |
2080 |
2106 |
2081 if (unlikely(!master->main_device.link_state)) { |
2107 if (unlikely(!master->main_device.link_state)) { |
2082 // link is down, no datagram can be sent |
2108 // link is down, no datagram can be sent |
2083 list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) { |
2109 list_for_each_entry_safe(datagram, next, &master->datagram_queue, |
|
2110 queue) { |
2084 datagram->state = EC_DATAGRAM_ERROR; |
2111 datagram->state = EC_DATAGRAM_ERROR; |
2085 list_del_init(&datagram->queue); |
2112 list_del_init(&datagram->queue); |
2086 } |
2113 } |
2087 |
2114 |
2088 // query link state |
2115 // query link state |