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.

Compiler/BEAGLEBK: PRU MII receive

Part Number: BEAGLEBK

Tool/software: TI C/C++ Compiler

Hello!

I have a question about MII_RT (mii0) interface at the BeagleBone Black. I use the PRU Cape Demo Software (https://git.ti.com/pru-software-support-package/pru-software-support-package/trees/master/pru_cape) example. I change the LED1 example for MII_RT using.

Tx work good (I connect LAN8710 ethernet phy (Microchip) to the BeagleBone and can see packets which I send on the WireShark on the PC), I have the problems with Rx. For testing Rx mode I use the LAN8710 configuring at NEAR-END LOOPBACK mode. I set the MII_Rx mode without Rx_L2 (because of https://e2e.ti.com/support/development_tools/compiler/f/343/t/586407?tisearch=e2e-sitesearch&keymatch=am335x%20pru%20mii last answer advice). 

My program for the PRU:

volatile register uint32_t __R30;
volatile register uint32_t __R31;

void main(void)
{
volatile uint32_t rx_data;
  
	/* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
	CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;

	/* TODO: Create stop condition, else it will toggle indefinitely */
	while (1) {
       	 /* MII */
      	 __R31 = (1<<18);//rx_reset (I try do not reset the RX, not any difference), look spruh73p, table 4_36
  __delay_cycles(400000);

        	int i;
        for (i=0; i<50; i++)//send the pack start
            {
            __R30 = 0xFFFF0000|0x7755;// 0x7755 - data
            __R31 = (1<<25);//push to the mii tx
            }
        __R30 = 0xFFFF0001; ;// 0x1 - data

        __R31 = (1<<25)|(1<<29);//push to the mii tx, EOF_TX, send the pack finish

        CT_SHAREDMEM.mem[0] = i; check that the share memory work good, I must read correct value “I” from the AM3358 main programm

        __delay_cycles(40000);

        rx_data = __R31;//read the data and status at the MII_RX_L1
        CT_SHAREDMEM.mem[1] = rx_data;//I need to read rx_data at the AM3358 main programm

        __delay_cycles(400);

        __R31 = (1<<17);//rx_pop16
        __delay_cycles(400);
        rx_data = __R31;
        __delay_cycles(40000);
        CT_SHAREDMEM.mem[2] = rx_data;

        __delay_cycles(400);
         CT_SHAREDMEM.mem[4] = 0x55;

My program for the AM3358:

//sets pin mux for PRU cape
	PRUCapePinmux();

	//Sets and Enables clock, Zeros memory, resets PRU
	PRUICSSInit();


    //******************************************************************************
    //							MII
    //******************************************************************************

    
    gpi_cfg = HWREG(SOC_PRUICSS1_REGS + SOC_PRUICSS_CFG_OFFSET + 0x8);
    HWREG(SOC_PRUICSS1_REGS + SOC_PRUICSS_CFG_OFFSET + 0x8) = gpi_cfg | 0x3;// GPI to MII mode

   HWREG(SOC_PRUICSS1_REGS + SOC_PRUICSS_CFG_OFFSET + 0x40) = 0x0;// Internal pinmux

    /* MII Config */
    HWREG(SOC_PRUICSS1_REGS + SOC_PRUICSS_MII_OFFSET + 0x0) = 0x1;//RXCFG0
/* RX_L2 – 0x0, disable
 RX_ENABLE – 0x1*/

    HWREG(SOC_PRUICSS1_REGS + SOC_PRUICSS_MII_OFFSET + 0x10) = 0x60400101; //TXCFG0
/* TX_CLK_DELAY – 0x6
TX_START_DELAY – 0x40
TX_MUX_SEL – 0x1 (Data from pru1)
TX_ENABLE – 0x1*/

    MMUConfigAndEnable();
    CacheEnable(CACHE_ALL);

    while(1)
        {
        MDIO_WRITE(0, 0x7100);//write to the LAN8710 Regs (set the LOOPBACK mode)

        Delay(200000000);
        char temp[1];
        ConsoleUtilsPrintf("\n\nPress 1 to start the programm\n\n");
        ConsoleUtilsGets(temp, 3);
        ConsoleUtilsPrintf("\nSTART\n");

        int reg1 = MDIO_READ(0x1); );//read LAN8710 Status

        if ((reg1&0x4)&&0x4)//Link status UP
            {
            ConsoleUtilsPrintf("LINK is UP\n");

            PRUMemLoad(PRU_ICSS1, PRU1_IRAM, 0, sizeof(LED1_INST), (unsigned int*)LED1_INST);
            PRUMemLoad(PRU_ICSS1, PRU1_DRAM, 0, sizeof(LED1_DATA), (unsigned int*)LED1_DATA);

            ConsoleUtilsPrintf("\nRunning PRUs...\n\n");
            PRUEnable(PRU_ICSS1, PRU1);

            int i, j;
            for (j=0; j<3; j++)
                {
                ConsoleUtilsPrintf("data = ");
                for (i=0; i<7; i++)
                    {
                    data_from_PRU[i] = HWREG(SOC_PRUICSS1_REGS + SOC_PRUICSS_SHARED_RAM_OFFSET + 0x4*i);
                    ConsoleUtilsPrintf("%x ", data_from_PRU[i]);
                    }
                ConsoleUtilsPrintf("\n");
                Delay(150000000);
                }        
            int rx = HWREG(SOC_PRUICSS1_REGS + SOC_PRUICSS_MII_OFFSET + 0x0);
            int tx = HWREG(SOC_PRUICSS1_REGS + SOC_PRUICSS_MII_OFFSET + 0x10);

            ConsoleUtilsPrintf("cfg: rx = %x tx = %x\n", rx, tx);//status do not changed

            PRUHalt(PRU_ICSS1, PRU1);
            }
        else ConsoleUtilsPrintf("LINK is DOWN\n");
        }

    while(1);
}

void PRUCapePinmux(void)
{
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(0)) = AM335X_PIN_INPUT | CONTROL_CONF_MUXMODE(2);//clk
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(1)) =AM335X_PIN_OUTPUT|CONTROL_CONF_MUXMODE(2);//txen
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(2)) = AM335X_PIN_OUTPUT | CONTROL_CONF_MUXMODE(2);//tx
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(3)) = AM335X_PIN_OUTPUT | CONTROL_CONF_MUXMODE(2);//tx
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(4)) = AM335X_PIN_OUTPUT | CONTROL_CONF_MUXMODE(2);//tx
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(5)) = AM335X_PIN_OUTPUT | CONTROL_CONF_MUXMODE(2);//tx
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(8)) = AM335X_PIN_INPUT | CONTROL_CONF_MUXMODE(5);//rx
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(9)) = AM335X_PIN_INPUT | CONTROL_CONF_MUXMODE(5);//rx
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(10)) = AM335X_PIN_INPUT | CONTROL_CONF_MUXMODE(5);//rx
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(11)) = AM335X_PIN_INPUT | CONTROL_CONF_MUXMODE(5);//rx
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(13)) = AM335X_PIN_INPUT | CONTROL_CONF_MUXMODE(5);//rxer
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(15)) = AM335X_PIN_INPUT |CONTROL_CONF_MUXMODE(5);//rxdv
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_PCLK) = AM335X_PIN_INPUT | CONTROL_CONF_MUXMODE(2);//crs
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_LCD_DATA(14)) = AM335X_PIN_INPUT | CONTROL_CONF_MUXMODE(5);//clk

    //******************************************************************************
    //							MDIO by GPIO
    //******************************************************************************
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_AD(12)) = 0x3f;//mdio_clk
    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_GPMC_AD(14)) = 0x3f;//mdio_clk
}

Using the oscilloscope I can see the MII correctly signals on the mii_rxd[0-3], mii_txd[0-3], mii_rx_clk, mii_tx_clk, mii_tx_en, mii_rx_dv pins. I do not understand how I must connect the mii_rx_link (I do not connect it now). mii_rx_er signal is always “0”. mii_rx_col signal using only at the RMII mode.

When I read the __R31 register I always get 0x1000000 (1<<24 - at the GPI_MII mode it must be CRC error, spruh73p, Table4_32).  Another strange situation become when I write the following code:

rx_data = __R31;

      //  rx_data = 0x1000000; //if I not comment this line, program will work further, otherwise hung after “if condition”
      i f (rx_data == 0x1000000)
            CT_SHAREDMEM.mem[3] = 0x2;
            
        else CT_SHAREDMEM.mem[3] = 0x1;

        __delay_cycles(400);

           CT_SHAREDMEM.mem[4] = 0x55;//this line work only if not comment line “rx_data = 0x1000000;”

I do not understand why it hung. I try to compile with different optimization flags. O0 do not work, O1,O2 – no difference.

 

So, what the wrong? I do:

  1. Internal pru pinmux
  2. Global pinmux
  3. Set PRU_MII_RT registers
  4. Set PRU_CFG registers
  5. Correctly send the packet using the PRU_MII_RT
  6. Get correct signals on mii_rx pins (look using the oscilloscope)
  7. See that at the PRU_MII_RT_PRS0 register _Current state of pr1_mii0_crs = 0x1  (if I send data in cycle)
  8. Can not read anything information about the packet (not data, not status), always read 0x1000000 (1<<24).
  9. I try to reset rx (1<<18 command), rx_pop16 (1<<17 command)

  • The software team have been notified. They will respond here.
  • Hi Alex,

    >>Can not read anything information about the packet (not data, not status), always read 0x1000000 (1<<24).
    So you actually don't receive any packet before you store the rx_data to CT_SHAREDMEM.mem[1], correct? Or do you read R31 as 0x1000000 ( 1<<24) only after RX_POP16? Since the RX_EOF bit is not set in R31, the bit 24 ERROR_CRC is invalid.

    Have you tried to read the pinmux control module registers to see if the PRUCapePinmux() is written as expected? As you have seen the signals on the mii_rxd[0-3], it appears these pins are not multiplexed properly.
    mii_rx_link signal is not necessary to be connected, and it's typically for fast link detection which uses LED status instead of MDIO internal state machine.

    Regards,
    Garrett

  • Hi, Garrett! Thank for your reply!

    >> Or do you read R31 as 0x1000000 ( 1<<24) only after RX_POP16?

    I read  0x1000000 ( 1<<24) always, when GPI is at the MII mode regardless do I RX_POP16 command or not. If I change GPI mode I will read 0x0.

    >>Have you tried to read the pinmux control module registers to see if the PRUCapePinmux() is written as expected?

    After PRUCapePinmux() I read control module and get all right:

    CONTROL_CONF_LCD_DATA(8)_rx_data mode = 2d   //mode 5, input

    CONTROL_CONF_LCD_DATA(9)_rx_data mode = 2d   //mode 5, input

    CONTROL_CONF_LCD_DATA(10)_rx_data mode = 2d   //mode 5, input

    CONTROL_CONF_LCD_DATA(11)_rx_data mode = 2d   //mode 5, input

    CONTROL_CONF_LCD_DATA(13)_rx_er mode = 2d   //mode 5, input

    CONTROL_CONF_LCD_DATA(15)_rx_dv mode = 2d   //mode 5, input

    CONTROL_CONF_LCD_PCLK_crs = 2a   //mode 2, input

    CONTROL_CONF_LCD_DATA(14)_rx_clk = 2d   //mode 5, input

    >>As you have seen the signals on the mii_rxd[0-3], it appears these pins are not multiplexed properly.

    Why? It was external signals which I tried to read. I tried several ways (with the same result):

    1.send packs from PC to the BBB using PHY (Lan8710, Microchip). This way was probable because I was using the prototyping board and get a lot of noise instead of real signal.

    2. connect rx<->tx inside PHY chip (loop mode) so tx signal was copping to the rx. The noise was more lower and the signals seemed good.

    3. connect rx<->tx (tx_data[i] > rx_data[i]; tx_en > rx_dv; clock (25MHz from clocout2 output) to the rx_clk and tx_clk, tried to connect tx_en > crs and tx_en > rx_er(I want to see error status at the R31 reg) on the prototyping board (look the photo). The signal was really good with low noise.

    Every time I can see that the rx_dv signal was changed from LOW level to HIGH level, which means (as I understand) that MII_RT module receive the pack. (also PRS0_pr1_mii0_crs status bit indicates "1" during this time).

    I have the idea, that error can be at the this area:

    May be when I connetc tx to rx, MII_RT module get wrong structure of the pack and can not parse it? Is it possible? Or not?

  • Alex,

    Your analysis makes sense. So have you tried to update the Tx code below to include 7 octet 0x55 preamble and one octet SFD 0xD5? What does the RXERR0/1 register look like?

    for (i=0; i<50; i++)//send the pack start
    {
    __R30 = 0xFFFF0000|0x7755;// 0x7755 - data
    __R31 = (1<<25);//push to the mii tx
    }

    Also, are you able to inject the packets from external traffic generator to see if any packet can be received?

    Regards,
    Garrett
  • Garrett, 

    when I connect BBB to the the PC (or any ethernet device: switch, hub, custom boards), I get a lot of short fake packs (I look to the mii_rxdv, it was HIGH sometimes about 200 ns - only 5 cycles). I get these pack even if the PC (or another device) really send no pack (also no ARP requests). I guess it was errors caused by noise (prototype board is not good for ethernet). But sometimes at the RXERR0 I can read some errors (often 0xF). It is difficult to repeat this experiment because of  noise.

    Now, when I connect mii_tx[i] directly to mii_rx[i] and so on, I always read 0x0 at the  RXERR0\1. I tried to add the preambule and SFD. I was not sure about the order of the nibbles and bits inside the nibble, so I tried different cases: 0x555d, 0x55d5, 0xaaab, 0xaaba, 0xd555 and so on (8 cases). No any results. I can see that the preambule and SFD is OK:

    My last code:

            /* MII_LOOPBACK */
    
            __R31 = (1<<18);//rx_reset
    
    
            __delay_cycles(400);
    
    
            volatile int h = 0x80;
            volatile int i;
    
    
            __R30 = 0xFFFF0000|0x5555;//preambule 1,2 octets
            __R31 = (1<<25);//push to the mii tx
    
            __R30 = 0xFFFF0000|0x5555;//preambule 3,4 octets
            __R31 = (1<<25);//push to the mii tx
    
            __R30 = 0xFFFF0000|0x5555;//preambule 5,6 octets
            __R31 = (1<<25);//push to the mii tx
    
            __R30 = 0xFFFF0000|0x55d5;//preambule 7 octet + SFD
            __R31 = (1<<25);//push to the mii tx
    
            for (i=0; i<40; i++)
                {
                __R30 = 0xFFFF0000|0xABAB;//pack data
                __R31 = (1<<25);//push to the mii tx
                }
    			
            __R30 = 0xFFFF0001;//pack data
            __R31 = (1<<25)|(1<<29);//push to the mii tx
    
            __delay_cycles(4000);//try with this line and without
    
            for (i=0; i<200; i++)
                {
                rx_data = __R31;
                __R31 = (1<<17);//rx_pop16
                __delay_cycles(10);
                if (i == 85)
                    CT_SHAREDMEM.mem[i] = 0x67;//for control reading data
                else CT_SHAREDMEM.mem[i] = rx_data;
                }
            while (1);

    So, concluding, I think that this code will be workable, if I purchase this board: 

    But I can purchase it only at the January or February. What do you think, is it real to get any pack without it? Why it can not get the pack with preambule and SFD?

  • Hi Alex,

    I agree that you should try to run the code on the AM335x IDK production board to alleviate any hardware issue. If we still miss anything that should be subtle if the code also doesn't work on the IDK.

    Regards,
    Garrett
  • Hi, Garrett!

    Thank for your reply!

    If I will have any problem with the  AM335x IDK at January, I have to write here, not create new issue?

  • Alex,

    Either way is Okay unless the issue you have on AM335x IDK is not related to PRU MII.

    Regards,
    Garrett
  • Garrett, Ok, thank you for your helping!

    I will write here later if it will be necessary, or mark issue as resolved!

    Regards, Alex