Hello
I am testing PRU MII Rx and Tx on our target hardware which uses AM3356 CPU. To test our target hardware, I started with a small firmware that would receive a complete frame and echo it back out the transmit port.
Initially I tested just the transmit part with a pre-configured ARP frame and I am able to get the PRU MII Transmit to work and now working on Rx but having issues with EOF detection.
I wrote a small firmware to receive Ethernet frames, save in a buffer and echo back the received frame. However, I have an issue with the EOF detection. It appears that the RX_EOF bit in the R31 read does not get set correctly.
Here is the code I tried for receiving an Ethernet Frame and then send the same frame out.
volatile register uint32_t __R30;
volatile register uint32_t __R31;
uint8_t Packet[1528];
uint32_t rx_idx;
uint32_t tx_idx;
volatile uint32_t rx_status;
volatile uint8_t *data_p;
uint8_t data;
#define TX_PUSH8 (1<<24)
#define TX_PUSH16 (1<<25)
#define TX_EOF (1<<29)
#define TX_CRC_HIGH (1<<27)
#define TX_CRC_LOW (1<<26)
#define TX_RESET (1<<30)
#define RX_POP8 (1 << 16)
#define RX_POP16 (1 << 17)
#define RX_RESET (1 << 18)
#define RX_SOF_CLR (1 << 20)
#define RX_SFD_CLR (1 << 21)
#define RX_EOF_CLR (1 << 22)
#define DATA_RDY (1 << 16)
#define BYTE_RDY (1 << 17)
#define WORD_RDY (1 << 18)
#define RX_EOF (1 << 20)
#define RX_SFD (1 << 21)
#define RX_SOF (1 << 22)
void main(void)
{
/* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
__delay_cycles( 10 );
while (1)
{
__R31 = RX_RESET;
__R31 = TX_RESET;
data_p = (uint8_t *)&Packet[0];
rx_idx = 0;
tx_idx = 0;
rx_status = 0;
while (1)
{
rx_status = __R31;
while ( ( rx_status & RX_SOF ) == 0 )
{
rx_status = __R31;
}
while ( ( rx_status & RX_EOF) != 1 )
{
if (rx_status & BYTE_RDY)
{
__R31 = RX_POP8; // Pop 1 byte
data = __R31;
*data_p++ = data;
if (++rx_idx >= sizeof( Packet ))
{
break;
}
__delay_cycles( 2 );
}
rx_status = __R31;
}
if (( rx_status & RX_EOF ) != 0)
{
/* EOF detected*/
__R31 = ( RX_EOF_CLR | RX_SOF_CLR | RX_SFD_CLR );
break;
}
}
__delay_cycles(100000);
data_p = (uint8_t *)&Packet[0];
for (tx_idx = 0; tx_idx < rx_idx; tx_idx++, data_p++)
{
data = *data_p;
__R30 = 0xFFFF0000 | data; //TX mask to transmit data from R30, not RX FIFO
__R31 = TX_PUSH8; //push to the mii tx
}
__R31 = ( TX_CRC_HIGH | TX_CRC_LOW | TX_EOF ); // Append CRC and indicate EOF
__delay_cycles(200000);
}
/* Nothing to do so halt */
__halt();
}
When I try this, the EOF is never detected and the firmware exits the innermost while loop when it fills up the packet buffer.
Just for experiment, I tried to force end of Rx when I receive 42 bytes instead of checking if I reached end of packet or received EOF (42 bytes was the typical ARP frame in my setup) and then transmit those bytes with some zero padding to make the total frame 64 including CRC and that worked. If I don’t terminate the end of Rx but depend on the EOF indication my buffer (size 1528) fills up without EOF indication.
I changed the following in the above code:
if (++rx_idx >= sizeof( Packet ))
{
break;
}
to check for 42 instead of the Packet buffer size.
In the transmit, I then padded with extra bytes to make the total frame including CRC as 64 and was able to transmit.
It appears that there is an issue either in my firmware or with the TRM documentation regarding the RX_EOF check.
Can you please review the above code and let me know if there is an issue with this?