[etherlab-dev] [PATCH] FoE omnibus patch

Dave Page dave.page at gleeble.com
Wed Jan 22 07:33:07 CET 2014


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. :)
>>
>>
>

-------------- next part --------------
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,
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dave_page.vcf
Type: text/x-vcard
Size: 313 bytes
Desc: not available
URL: <http://lists.etherlab.org/pipermail/etherlab-dev/attachments/20140122/886af00d/attachment-0001.vcf>


More information about the etherlab-dev mailing list