Hi at all, i have a problem with ethernet connection under WinCE on netx100:
This is my scenario:
i've implemented a Modbus Slave on netx100 (own hardware) with winsock that communicate over ethernet port 0. On my PC i have a Modbus Master that continuosly read and write some WORD on Slave. For test timing response , on master side the polling time is 0 i.e. i don't wait between the end of a Modbus Transaction and the next query.
If i do this test between 2 PC everything goes well (verified with ethernet sniffer (Wireshark)), all transaction are OK and the loop time is about 1.5 ms but if i put the Modbus Slave on Netx i have some problem.
It seem that netx lose some packet and then the TCP engine of modbus master force a packet retransmission. The retransmission happening with about 300ms of delay due the RTO timeout of TCP protocol.!!! This is a problem because this scenario became about every 20 modbus transaction and the transfer rate decrease.
If i put a delay between two consecutive modbus master query (e.g. 30ms) everything goes well also on Netx.
It's so strange because my implementation use blocking send and recv socket function and then the next modbus query is sent only when the previous modbus response was received.
I have also try to expand receive buffer with the winsock option SO_RCVBUF but the result is the same.
Where is the problem? Netx lose some interrupt.......(maybe)?
P.S. In order to avoid some mistake, i have implemented a generic client/server (no modbus) that echoes the same message between client and server in the same manner of modbus exchange (with zero delay between response and the next query). Putting the server on PC1, client on PC2 everything works well, putting server on netx and client on PC the problem is the same as described above.
Thank's in advance
Matias
Hi, i have logged on a file the result of DumpStatistic() but i see only one instance of dump log message and all is 0.
I have notice an interesting thing: if i put a 1ms delay in the NetXEthHandleInterrupt(IN NDIS_HANDLE hMiniportAdapterContext) everything works well.
Here the modified code:
.... pAdapter->ulIRQState = g_tNetXEthMiniportBlock.pdwXPecIrqRegs[pAdapter->ulIoBaseAddress]; g_tNetXEthMiniportBlock.pdwXPecIrqRegs[pAdapter->ulIoBaseAddress] = pAdapter->ulIRQState & MSK_irq_xpec0_xpec_irq;NdisStallExecution(1000); /// <-------- ADDED LINE
DEBUGMSG (ZONE_INTR, (TEXT ("NetXEth: HandleInterrupt. RecvLo=%u, RecvHi=%u, ConfLo=%u, ConfHi=%u. IrqState:0x%x\r\n"),
dwRecvFramesLo, dwRecvFramesHi, dwConfirmationsLo, dwConfirmationsHi,
pAdapter->ulIRQState));if(pAdapter->ulIRQState & MSK_ETHMAC_XPEC2ARM_INTERRUPTS_LINK_STA_CHANGED_IRQ)
CardHandleLinkChange(pAdapter);
pAdapter->ulIRQState = 0;while(dwRecvFramesHi-- > 0)
{
FIFO_POINTER tFifoPtr = {0};
DEBUGCHK(ptFifoArea->aulPFifoFillLevelBase[dwXCFifoOffset + IND_FIFO_PORT_HI] > 0);
tFifoPtr.uiVal = ptFifoArea->aulPFifo[dwXCFifoOffset + IND_FIFO_PORT_HI];
CardHandleRX(pAdapter, &tFifoPtr);
tFifoPtr.uiVal &= (MSK_FIFO_PTR_SEGMENT | MSK_FIFO_PTR_FRAMENR);
ptFifoArea->aulPFifo[dwXCFifoOffset + EMPTY_PTR_FIFO] = tFifoPtr.uiVal;
}
....
Why this behaviour???
P.S. i put here a delay because when i print to file the DEBUGMSG under the delay added line thing goes well, i suppose because writing to file waste a bit of time.
Thank's
Matias
Hilscher Gesellschaft für Systemautomation mbH
Could you try the following (instead of NdisStallExecution), and see if it helps:
.... DWORD dwRecvFramesHi; DWORD dwRecvFramesLo; DWORD dwConfirmationsHi; DWORD dwConfirmationsLo;pAdapter->ulIRQState = g_tNetXEthMiniportBlock.pdwXPecIrqRegs[pAdapter->ulIoBaseAddress];
g_tNetXEthMiniportBlock.pdwXPecIrqRegs[pAdapter->ulIoBaseAddress] = pAdapter->ulIRQState & MSK_irq_xpec0_xpec_irq;dwRecvFramesHi = ptFifoArea->aulPFifoFillLevelBase[dwXCFifoOffset + IND_FIFO_PORT_HI];
dwRecvFramesLo = ptFifoArea->aulPFifoFillLevelBase[dwXCFifoOffset + IND_FIFO_PORT_LO];
dwConfirmationsHi = ptFifoArea->aulPFifoFillLevelBase[dwXCFifoOffset + CON_FIFO_PORT_HI];
dwConfirmationsLo = ptFifoArea->aulPFifoFillLevelBase[dwXCFifoOffset + CON_FIFO_PORT_LO];
...
PS: Basically it is just moving the readout of the fill levels below IRQ confirmation, which was the way I expected this routine to work (see my first posting).
Regards
MT
i have tried your appended code but the result was the same.....but with this configuration, if i put a NdisStallExecution(250) (before was 1000 ) everywhere in the NetXEthHandleInterrupt function, things goes well.
I put my NetXEthHandleInterrupt here:
VOID NetXEthHandleInterrupt(IN NDIS_HANDLE hMiniportAdapterContext)
{
PNETXETH_ADAPTER pAdapter = (PNETXETH_ADAPTER)(hMiniportAdapterContext); // The adapter to process
BOOL fReceivedFrame = FALSE;
UINT uiRecvPacketLength = 0;
PBYTE pbRecvDataTmp = NULL;
PBYTE pbRecvDataTmpVirt = NULL;
PFIFO_AREA_T ptFifoArea = (PFIFO_AREA_T)g_tNetXEthMiniportBlock.pdwFifoBase;
DWORD dwXCFifoOffset;
DWORD dwInterrupts;
DWORD dwRecvFramesHi;
DWORD dwRecvFramesLo;
DWORD dwConfirmationsHi;
DWORD dwConfirmationsLo;
NdisStallExecution(250);
dwXCFifoOffset = 8 * pAdapter->ulIoBaseAddress;
dwInterrupts = pAdapter->pdwXpecBase[REL_Adr_irq / sizeof(DWORD)];
pAdapter->ulIRQState = g_tNetXEthMiniportBlock.pdwXPecIrqRegs[pAdapter->ulIoBaseAddress];
g_tNetXEthMiniportBlock.pdwXPecIrqRegs[pAdapter->ulIoBaseAddress] = pAdapter->ulIRQState & MSK_irq_xpec0_xpec_irq;
dwRecvFramesHi = ptFifoArea->aulPFifoFillLevelBase[dwXCFifoOffset + IND_FIFO_PORT_HI];
dwRecvFramesLo = ptFifoArea->aulPFifoFillLevelBase[dwXCFifoOffset + IND_FIFO_PORT_LO];
dwConfirmationsHi = ptFifoArea->aulPFifoFillLevelBase[dwXCFifoOffset + CON_FIFO_PORT_HI];
dwConfirmationsLo = ptFifoArea->aulPFifoFillLevelBase[dwXCFifoOffset + CON_FIFO_PORT_LO];
DEBUGMSG (ZONE_INTR, (TEXT ("NetXEth: HandleInterrupt. RecvLo=%u, RecvHi=%u, ConfLo=%u, ConfHi=%u. IrqState:0x%x\r\n"),
dwRecvFramesLo, dwRecvFramesHi, dwConfirmationsLo, dwConfirmationsHi,
pAdapter->ulIRQState));
if(pAdapter->ulIRQState & MSK_ETHMAC_XPEC2ARM_INTERRUPTS_LINK_STA_CHANGED_IRQ)
CardHandleLinkChange(pAdapter);
pAdapter->ulIRQState = 0;
while(dwRecvFramesHi-- > 0)
{
FIFO_POINTER tFifoPtr = {0};
DEBUGCHK(ptFifoArea->aulPFifoFillLevelBase[dwXCFifoOffset + IND_FIFO_PORT_HI] > 0);
tFifoPtr.uiVal = ptFifoArea->aulPFifo[dwXCFifoOffset + IND_FIFO_PORT_HI];
CardHandleRX(pAdapter, &tFifoPtr);
tFifoPtr.uiVal &= (MSK_FIFO_PTR_SEGMENT | MSK_FIFO_PTR_FRAMENR);
ptFifoArea->aulPFifo[dwXCFifoOffset + EMPTY_PTR_FIFO] = tFifoPtr.uiVal;
}
while(dwRecvFramesLo-- > 0)
{
FIFO_POINTER tFifoPtr = {0};
DEBUGCHK(ptFifoArea->aulPFifoFillLevelBase[dwXCFifoOffset + IND_FIFO_PORT_LO] > 0);
tFifoPtr.uiVal = ptFifoArea->aulPFifo[dwXCFifoOffset + IND_FIFO_PORT_LO];
CardHandleRX(pAdapter, &tFifoPtr);
tFifoPtr.uiVal &= (MSK_FIFO_PTR_SEGMENT | MSK_FIFO_PTR_FRAMENR);
ptFifoArea->aulPFifo[dwXCFifoOffset + EMPTY_PTR_FIFO] = tFifoPtr.uiVal;
}
while(dwConfirmationsHi-- > 0)
{
FIFO_POINTER tFifoPtr = {0};
tFifoPtr.uiVal = ptFifoArea->aulPFifo[dwXCFifoOffset + CON_FIFO_PORT_HI];
CardHandleTX(pAdapter, &tFifoPtr);
}
while(dwConfirmationsLo-- > 0)
{
FIFO_POINTER tFifoPtr = {0};
tFifoPtr.uiVal = ptFifoArea->aulPFifo[dwXCFifoOffset + CON_FIFO_PORT_LO];
CardHandleTX(pAdapter, &tFifoPtr);
}
}
Do you see anything wrong?? or strange???
It's strange that i can put the delay everywhere....it seem that the problem was between two consecutive interrupt.
Thank's for your help!
Matias
M T
Hilscher Gesellschaft für Systemautomation mbH
Strange. I've never heard of such a problem yet. There should no interrupts being missed, as the IRQ is confirmed and afterwards the fill level of the received frames is evaluated. So if there is a new frame received you will always get another IRQ. Only thing that might happen in seldom cases that you get an interrupt for an already processed frame (in case the next frame is received completely, before the fill counter has been read), which is then ignored by the Interrupt Handler.
Do you have the chance to look into the error counters provided by the XC unit (See DumpStatistics() functions in the netcard driver) ? This may show if the XC probably has detected an erroneous frame on the bus?
Regards
MT