Hi All
While working with the new LPC17XX, which has the same Ethernet controller built in as the LPC23XX and LPC24XX I was rather concerned about the quite poor performance of the Ethernet interface. After a series of tests to try to understand the reason why it was sometimes losing transmission frames I identified that the way that the TxConsumeIndex and TxProduceIndex was operating was not correct.
Basically the TxProduceIndex is maintained by the software and the TxConsumeIndex by the hardware. By checking these values it can be identified whether the Ethernet transmitter buffers have space to add Ethernet frames or not. If ever the Ethernet controller has not sent the first frame in a queue of Ethernet frames, the software waits a short time before it finally can add the new frame's data or else gives up since the buffers have been blocked for too long. In fact one would not normally expect the software to have to wait, especially when several tx buffers are available.
But things were not working as expected as could be seen by the fact that sometimes the TxConsumeIndex was not counting. Generally it was being incremented after a delay of around 2.6ms and not at the speed that the Ethernet frames were being transmitted. It was even possible to cause an infinity loop if the expected sequence was waited for (without an escape path on long delays).
Finally I found that this became more noticeable when the number of tx buffers was decreased. With 3 rx buffers and 7 tx buffers it wasn't really noticed. [note that the first LPC23XX chips have a bug which means that the number of rx buffers is limited to a maximum of 5 and so the number of tx buffers was always set fairly high. In the case of the LPC24xx this limit is no longer applicable but the project set up was not correct - it was using proportionally too many tx buffers: 3 rx and 7 tx, whereas the inverse was probably desired]. In the LPC17XX case I realised that the rx/tx ratio was inverted and after its 'optimisation' I then realised that something was not right...
So to cut a long story short, the TxConsumeIndex was doing some very strange things which obviously didn't allow it to be used as intended because it would sometimes incorrectly recognise full buffers and could cause loss of transmissions. But it turns out that this strangeness can be completely removed if the end of frame interrupt is enabled (the tx interrupt is not needed and is in fact disabled) in the buffer descriptor belonging to the frame buffer. Once set, the TxConsumeIndex was being incremented correctly and also without the 2.6ms delay (it was in the us range as expected). With the 7 rx and 3 tx buffer ratio (this uses the 16k of the available LAN RAM in a favorable way since more rx buffers is generally better) the performance was then correspondingly better.
Therefore I suggest all users of the LPC23xx and LPC24xx to verify the following changes in their projects.
1) In app_hw_lpc23xx.h !!only LPC24XX users or those who are sure that the LPC23xx chips don't have the Ethernet buffer errata!!
#define LAN_RX_BUF_COUNT 7 // rx buffer space defined to be 7 times the full buffer
#define LAN_TX_BUF_COUNT 3
2) In lpc23xx.c in the routine fnStartEthTx() add the TX_LAN_INTERRUPT_ON_DONE flag:
LPC23XX_RX_BD *ptrBd = (LPC23XX_RX_BD *)EMAC_TxDescriptor;
ptrBd += EMAC_TxProduceIndex;
ptrBd->bd_details = (TX_LAN_INTERRUPT_ON_DONE | TX_LAST_FRAG | TX_APPEND_CRC | TX_PAD_FRAME | (DataLen - 1)); // {18}
This should optimise and improve performance generally.
In the case of the LPC24XX there is a further error which was solved during this work concerting Port 2 edge interrupts:
In LPC23XX.c:
#ifdef _LPC24XX
static void ( *gpio_handlers_2[32] )( void ) = {0}; // {19} a handler for each possible port 2 pin
#else
static void ( *gpio_handlers_2[14] )( void ) = {0}; // a handler for each possible port 2 pin
#endif[/color]
The LPC24XX has 32 pins on Port 2 (the LPC23XX has only 14) and so the number of interrupt handlers for the port should correspond. The Olimex LPC-2478-STK uses Port 2-25 as PHY interrupt and the interrupt was potentially corrupting RAM and leading to a data abort.
Regards
Mark