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.objhttp://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 athttp://lists.etherlab.org/pipermail/etherlab-dev/2013/000324.html, if you'rehaving 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 -- myversion would continue incrementing the packet number (which is partly why Iran into the 256 packet limit that prompted the other patch).You're correct that ETG.1020 indicates that the packet number should not beincreasing though; I missed that part. (It worries me a bit when bothmaster 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 FoEread 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 thesedays). I'll probably get to it in a few days when I (hopefully) get back toEtherCAT-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