Hi,

The attached patch against 51ad16e57f8f includes Gavin Lambert's FoE patches as folows:
http://lists.etherlab.org/pipermail/etherlab-dev/attachments/20131129/f8938a33/attachment.obj
http://lists.etherlab.org/pipermail/etherlab-dev/attachments/20130826/64fa4096/attachment.obj
http://lists.etherlab.org/pipermail/etherlab-dev/attachments/20130826/64fa4096/attachment-0001.obj

And includes a one-liner PacketNo read busy sequence patch as well as a FoE spurious timeout patch.

This patch is tested to work with my (proprietary) slave which emits BUSY FoE opcodes on read and write.

        Cheers - Dave

On 2014-01-22 18:18, Dave Page wrote:

    Yes... I see you beat me to it:

@@ -778,6 +792,8 @@ void ec_fsm_foe_state_data_read(
     if (opCode == EC_FOE_OPCODE_BUSY) {
         if (ec_foe_prepare_send_ack(fsm, datagram)) {
             ec_foe_set_rx_error(fsm, FOE_PROT_ERROR);
+        } else {
+            fsm->state = ec_fsm_foe_state_sent_ack;
         }
         return;
     }

    (except for the PacketNo issue). Sorry I missed that one.

My stack is configured to test this at the moment, so its no problem to combine and test for me.

        Best regards - Dave

On 2014-01-22 18:13, Gavin Lambert wrote:
Mere moments ago, quoth I:
Did you see my other patch specifically for FoE busy?  My slave is
working fine for busy reads with both of my patches applied. (There was
a third patch included in the same email as the busy patch, but that's
optional and just increases debug logging.)

My patch also fixes handling of error packets.
These are at
http://lists.etherlab.org/pipermail/etherlab-dev/2013/000324.html, if you're
having trouble finding it.

As for incrementing the packet number or not, it's been a while since I
looked at that so I don't remember whether it increments or not with my
patches applied, but I think I remember making it do whatever the SSC
was expecting.
I had a quick look at my SSC patches, so now I think I remember -- my
version would continue incrementing the packet number (which is partly why I
ran into the 256 packet limit that prompted the other patch).

You're correct that ETG.1020 indicates that the packet number should not be
increasing though; I missed that part.  (It worries me a bit when both
master AND slave code have to be changed to make something fundamental like this work, and it makes me wonder about existing devices -- but I guess FoE
read is not implemented all that often.)

One of us should probably make a combined patch set that fixes all three
issues, for ease of future players (and maybe even merging, one of these
days). I'll probably get to it in a few days when I (hopefully) get back to
EtherCAT-related work, if you don't beat me to it. :)




diff --git a/master/fsm_foe.c b/master/fsm_foe.c
--- a/master/fsm_foe.c
+++ b/master/fsm_foe.c
@@ -37,19 +37,19 @@
 #include "globals.h"
 #include "master.h"
 #include "mailbox.h"
 #include "fsm_foe.h"
 #include "foe.h"
 
 /*****************************************************************************/
 
-/** Maximum time in ms to wait for responses when reading out the dictionary.
+/** Maximum time in jiffies to wait for responses when reading out the 
dictionary.
  */
-#define EC_FSM_FOE_TIMEOUT 3000
+#define EC_FSM_FOE_TIMEOUT (3*HZ)
 
 /** Mailbox type FoE.
  */
 #define EC_MBOX_TYPE_FILEACCESS 0x04
 
 /** Size of the FoE header.
  */
 #define EC_FOE_HEADER_SIZE 6
@@ -256,16 +256,19 @@ int ec_foe_prepare_data_send(
             datagram, EC_MBOX_TYPE_FILEACCESS,
             current_size + EC_FOE_HEADER_SIZE);
     if (IS_ERR(data)) {
         return -1;
     }
 
     EC_WRITE_U16(data, EC_FOE_OPCODE_DATA);    // OpCode = DataBlock req.
     EC_WRITE_U32(data + 2, fsm->tx_packet_no); // PacketNo, Password
+#ifdef DEBUG_FOE
+    EC_SLAVE_DBG(fsm->slave, 0, "sending opcode %u packet %u\n", 
EC_FOE_OPCODE_DATA, fsm->tx_packet_no);
+#endif
 
     memcpy(data + EC_FOE_HEADER_SIZE,
             fsm->tx_buffer + fsm->tx_buffer_offset, current_size);
     fsm->tx_current_size = current_size;
 
     return 0;
 }
 
@@ -293,16 +296,19 @@ int ec_foe_prepare_wrq_send(
     data = ec_slave_mbox_prepare_send(fsm->slave, datagram,
             EC_MBOX_TYPE_FILEACCESS, current_size + EC_FOE_HEADER_SIZE);
     if (IS_ERR(data)) {
         return -1;
     }
 
     EC_WRITE_U16( data, EC_FOE_OPCODE_WRQ); // fsm write request
     EC_WRITE_U32( data + 2, fsm->tx_packet_no );
+#ifdef DEBUG_FOE
+    EC_SLAVE_DBG(fsm->slave, 0, "sending opcode %u packet %u\n", 
EC_FOE_OPCODE_WRQ, fsm->tx_packet_no);
+#endif
 
     memcpy(data + EC_FOE_HEADER_SIZE, fsm->tx_filename, current_size);
 
     return 0;
 }
 
 /*****************************************************************************/
 
@@ -365,19 +371,17 @@ void ec_fsm_foe_state_ack_check(
         EC_SLAVE_ERR(slave, "Reception of FoE mailbox check datagram"
                 " failed: ");
         ec_datagram_print_wc_error(fsm->datagram);
         return;
     }
 
     if (!ec_slave_mbox_check(fsm->datagram)) {
         // slave did not put anything in the mailbox yet
-        unsigned long diff_ms = (fsm->datagram->jiffies_received -
-                fsm->jiffies_start) * 1000 / HZ;
-        if (diff_ms >= EC_FSM_FOE_TIMEOUT) {
+        if (time_after(datagram->jiffies_received, 
fsm->jiffies_start+EC_FSM_FOE_TIMEOUT)) {
             ec_foe_set_tx_error(fsm, FOE_TIMEOUT_ERROR);
             EC_SLAVE_ERR(slave, "Timeout while waiting for ack response.\n");
             return;
         }
 
         ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
         fsm->retries = EC_FSM_RETRIES;
         return;
@@ -431,28 +435,45 @@ void ec_fsm_foe_state_ack_read(
     if (mbox_prot != EC_MBOX_TYPE_FILEACCESS) { // FoE
         ec_foe_set_tx_error(fsm, FOE_MBOX_PROT_ERROR);
         EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
                 mbox_prot);
         return;
     }
 
     opCode = EC_READ_U8(data);
+#ifdef DEBUG_FOE
+    EC_SLAVE_DBG(fsm->slave, 0, "received opcode %u\n", opCode);
+#endif
 
     if (opCode == EC_FOE_OPCODE_BUSY) {
         // slave not ready
         if (ec_foe_prepare_data_send(fsm, datagram)) {
             ec_foe_set_tx_error(fsm, FOE_PROT_ERROR);
             EC_SLAVE_ERR(slave, "Slave is busy.\n");
             return;
         }
         fsm->state = ec_fsm_foe_state_data_sent;
         return;
     }
 
+    if (opCode == EC_FOE_OPCODE_ERR) {
+        fsm->request->error_code = EC_READ_U32(data + 2);
+        EC_SLAVE_ERR(slave, "Received FoE Error Request (code 0x%08x).\n",
+                fsm->request->error_code);
+        if (rec_size > 6 && data[6]) {
+            uint8_t text[256];
+            strncpy(text, data + 6, min(rec_size - 6, sizeof(text)));
+            text[sizeof(text)-1] = 0;
+            EC_SLAVE_ERR(slave, "FoE Error Text: %s\n", text);
+        }
+        ec_foe_set_tx_error(fsm, FOE_OPCODE_ERROR);
+        return;
+    }
+
     if (opCode == EC_FOE_OPCODE_ACK) {
         fsm->tx_packet_no++;
         fsm->tx_buffer_offset += fsm->tx_current_size;
 
         if (fsm->tx_last_packet) {
             fsm->state = ec_fsm_foe_end;
             return;
         }
@@ -566,16 +587,19 @@ int ec_foe_prepare_rrq_send(
             EC_MBOX_TYPE_FILEACCESS, current_size + EC_FOE_HEADER_SIZE);
     if (IS_ERR(data)) {
         return -1;
     }
 
     EC_WRITE_U16(data, EC_FOE_OPCODE_RRQ); // fsm read request
     EC_WRITE_U32(data + 2, 0x00000000); // no passwd
     memcpy(data + EC_FOE_HEADER_SIZE, fsm->rx_filename, current_size);
+#ifdef DEBUG_FOE
+    EC_SLAVE_DBG(fsm->slave, 0, "sending opcode %u\n", EC_FOE_OPCODE_RRQ);
+#endif
 
     if (fsm->slave->master->debug_level) {
         EC_SLAVE_DBG(fsm->slave, 1, "FoE Read Request:\n");
         ec_print_data(data, current_size + EC_FOE_HEADER_SIZE);
     }
 
     return 0;
 }
@@ -596,16 +620,19 @@ int ec_foe_prepare_send_ack(
     data = ec_slave_mbox_prepare_send(fsm->slave, datagram,
             EC_MBOX_TYPE_FILEACCESS, EC_FOE_HEADER_SIZE);
     if (IS_ERR(data)) {
         return -1;
     }
 
     EC_WRITE_U16(data, EC_FOE_OPCODE_ACK);
     EC_WRITE_U32(data + 2, fsm->rx_expected_packet_no);
+#ifdef DEBUG_FOE
+    EC_SLAVE_DBG(fsm->slave, 0, "sending opcode %u packet %u\n", 
EC_FOE_OPCODE_ACK, fsm->rx_expected_packet_no);
+#endif
 
     return 0;
 }
 
 /*****************************************************************************/
 
 /** State: RRQ SENT.
  *
@@ -704,19 +731,17 @@ void ec_fsm_foe_state_data_check(
     if (fsm->datagram->working_counter != 1) {
         ec_foe_set_rx_error(fsm, FOE_WC_ERROR);
         EC_SLAVE_ERR(slave, "Reception of FoE DATA READ: ");
         ec_datagram_print_wc_error(fsm->datagram);
         return;
     }
 
     if (!ec_slave_mbox_check(fsm->datagram)) {
-        unsigned long diff_ms = (fsm->datagram->jiffies_received -
-                fsm->jiffies_start) * 1000 / HZ;
-        if (diff_ms >= EC_FSM_FOE_TIMEOUT) {
+        if (time_after(datagram->jiffies_received, 
fsm->jiffies_start+EC_FSM_FOE_TIMEOUT)) {
             ec_foe_set_tx_error(fsm, FOE_TIMEOUT_ERROR);
             EC_SLAVE_ERR(slave, "Timeout while waiting for ack response.\n");
             return;
         }
 
         ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
         fsm->retries = EC_FSM_RETRIES;
         return;
@@ -734,17 +759,18 @@ void ec_fsm_foe_state_data_check(
 /** Start reading data.
  */
 void ec_fsm_foe_state_data_read(
         ec_fsm_foe_t *fsm, /**< FoE statemachine. */
         ec_datagram_t *datagram /**< Datagram to use. */
         )
 {
     size_t rec_size;
-    uint8_t *data, opCode, packet_no, mbox_prot;
+    uint32_t packet_no;
+    uint8_t *data, opCode, mbox_prot;
 
     ec_slave_t *slave = fsm->slave;
 
 #ifdef DEBUG_FOE
     EC_SLAVE_DBG(fsm->slave, 0, "%s()\n", __func__);
 #endif
 
     if (fsm->datagram->state != EC_DATAGRAM_RECEIVED) {
@@ -770,48 +796,56 @@ void ec_fsm_foe_state_data_read(
     if (mbox_prot != EC_MBOX_TYPE_FILEACCESS) { // FoE
         EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
                 mbox_prot);
         ec_foe_set_rx_error(fsm, FOE_PROT_ERROR);
         return;
     }
 
     opCode = EC_READ_U8(data);
+#ifdef DEBUG_FOE
+    EC_SLAVE_DBG(fsm->slave, 0, "received opcode %u\n", opCode);
+#endif
 
     if (opCode == EC_FOE_OPCODE_BUSY) {
+               fsm->rx_expected_packet_no--;
         if (ec_foe_prepare_send_ack(fsm, datagram)) {
             ec_foe_set_rx_error(fsm, FOE_PROT_ERROR);
+        } else {
+            fsm->state = ec_fsm_foe_state_sent_ack;
         }
         return;
     }
 
     if (opCode == EC_FOE_OPCODE_ERR) {
         fsm->request->error_code = EC_READ_U32(data + 2);
         EC_SLAVE_ERR(slave, "Received FoE Error Request (code 0x%08x).\n",
                 fsm->request->error_code);
-        if (rec_size > 6) {
+        if (rec_size > 6 && data[6]) {
             uint8_t text[256];
             strncpy(text, data + 6, min(rec_size - 6, sizeof(text)));
+            text[sizeof(text)-1] = 0;
             EC_SLAVE_ERR(slave, "FoE Error Text: %s\n", text);
         }
         ec_foe_set_rx_error(fsm, FOE_OPCODE_ERROR);
         return;
     }
 
     if (opCode != EC_FOE_OPCODE_DATA) {
         EC_SLAVE_ERR(slave, "Received OPCODE %x, expected %x.\n",
                 opCode, EC_FOE_OPCODE_DATA);
         fsm->request->error_code = 0x00000000;
         ec_foe_set_rx_error(fsm, FOE_OPCODE_ERROR);
         return;
     }
 
-    packet_no = EC_READ_U16(data + 2);
+    packet_no = EC_READ_U32(data + 2);
     if (packet_no != fsm->rx_expected_packet_no) {
-        EC_SLAVE_ERR(slave, "Received unexpected packet number.\n");
+        EC_SLAVE_ERR(slave, "Received packet number %u, expected %u.\n",
+                packet_no, fsm->rx_expected_packet_no);
         ec_foe_set_rx_error(fsm, FOE_PACKETNO_ERROR);
         return;
     }
 
     rec_size -= EC_FOE_HEADER_SIZE;
 
     if (fsm->rx_buffer_size >= fsm->rx_buffer_offset + rec_size) {
         memcpy(fsm->rx_buffer + fsm->rx_buffer_offset,

<<attachment: dave_page.vcf>>

_______________________________________________
etherlab-dev mailing list
etherlab-dev@etherlab.org
http://lists.etherlab.org/mailman/listinfo/etherlab-dev

Reply via email to