This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3356: PRU MII RX_EOF Indication is not getting set correctly

Part Number: AM3356

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?

  • Hi Srini,

    Essentially the bit 20 as noted in the "ICSS_DUAL_EMAC_Firmware_Design_Guide.pdf" (PDK packages\ti\drv\icss_emac\firmware\icss_dualemac\docs):

    "Bit 20 of R31 corresponds to RX_EOF for MII RX Data to PRU R31 ® and RX FIFO. We can’t use this bit for ICSS revision 1 as on AM335x and AM437x, RX_EOF is auto-clear when a new frame arrives in RX L2 mode."

    Please refer to the tiemac_pruss_intc_mapping.h file in ICSS_EMAC driver. This file maps RX_EOF to Channel 0 and Channel 1, which are in turn mapped to Host Interrupt 0 and Host Interrupt 1.

    From TRM, 4.4.2.1 INTC Overview,

    Host Interrupt 0 is connected to bit 30 in register 31 of PRU0 and PRU1.
    Host Interrupt 1 is connected to bit 31 in register 31 for PRU0 and PRU1.

    Gunter will give you a call to explain the details.

    Regards,

    Garrett
     

  • Thanks Garrett. However, please note that in my firmware I did not enable RX L2 (Bit 4 in RXCFG0 and RXCFG1). Does RX_EOF auto-clear even f RX L2 is disabled?

    In the TRM SPRUH73Q, bits 30 and 31 as shown as reserved (Table 4-32).

    Srini

  • Srini,

    I will get back to you for the RXL1 mode after confirming with IP team.

    Regards,
    Garrett

  • Srini,

    You probably have resolved the issue by referring to the examples Gunter shared with you.

    IP team clarified that the RX_EOF auto-clear is independent to RXL2 or RXL1 mode.

    Regards,

    Garrett

  • Hello Garrett

    Sorry I could not confirm about this earlier as I took few days off for my son's wedding and just back at work today. Yes, the examples you/Gunter shared were very helpful. I finally got the loop back working on the PRU MII ports. 

    Now that we crossed the initial hurdle of verifying our target hardware with the loop back test, we are starting on writing firmware to implement full Ethernet driver for each of the PRU MII ports on the lines of the example PRU Dual EMAC code but not quite the same. We are writing this for our own target hardware as I mentioned previously and also we are using a different OS (Threadx RTOS) and Ethernet Stack (Treck). We need to write the PRU Ethernet driver for the Ethernet packet Rx/Tx and then pass the packets on to the core and then interface with our ethernet stack.

    Since the PRU Ethernet driver is much more involved than the simple loop back test firmware, we need to be able to debug the PRU firmware that we write. We are using Code Composer studio V10 with TI CGT 2.3 tools and do have couple of XDS100 debug probes that came with TI Dev kits/Beagle Bone Black. However, we are not sure how to setup/debug PRU firmware with CCS and XDS probes. Any information we find on the TI wiki pages seems to be very TI dev kit/Beagle Bone black specific.

    Would you like me to open a separate thread regarding the AM335x PRU debugging with CCS and XDS probes or if there is already information elsewhere that could be helpful to us, please let us know.

    I appreciate all the help that you and Gunter have provided last several weeks. It was very useful.

    Thanks again.

    Srini Dingari

    SEL, Inc

  • Hi Srini,

    Congratulations on the wedding of your son. I believe you have been dreaming of this day :-)

    Yes, we have some material about PRU debugging including tips and tricks. I will pass to Gunter and share with you. It would be great if you can open a separate thread if you need other info.

    Regards,
    Garrett