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.

TMDS243EVM: How to assert TX_EN on RGMII L1 FIFO?

Part Number: TMDS243EVM
Other Parts Discussed in Thread: AM2434, , SYSCONFIG

hi,

I am trying to use the L1 FIFO of the MII_G_RT module on PRU1 on ICSSG0 of the AM2434 on the TMDS243EVM board. Unfortunately I cannot get the FIFO to share its content with the outside world.

I use the following code on PRU1:

#include <stdint.h>      // uint8_t, uint16_t, ...
#include <pru_cfg.h>
#include <pru_mii_rt.h>
#include <pru_mii_g_rt.h>

volatile register uint32_t __R30;
volatile register uint32_t __R31;

uint32_t fill_level, data, status, control;

void main(void)
{
    // initial config
    CT_CFG.spp_reg_bit.xfr_shift_en = 1;                                // enable GP SP r0 32-bit shifting feature
    CT_CFG.gpcfg1_reg_bit.pr1_pru1_gp_mux_sel = 2;                      // select MII mode

    // general configuration MII
    CT_MII_RT.txcfg0_bit.tx_enable0 = 0;                                // disable TX0 PORT
    CT_MII_RT.txcfg1_bit.tx_enable1 = 0;                                // disable TX1 PORT
    CT_MII_RT.txcfg0_bit.tx_mux_sel0 = 0;                               // select PRU0 for TX0
    CT_MII_RT.txcfg1_bit.tx_mux_sel1 = 1;                               // select PRU1 for TX1

    // configure MII TX1
    CT_MII_RT.txcfg1_bit.tx_auto_preamble1 = 0;                         // PRU inserts custom pre-amble
    CT_MII_RT.txcfg1_bit.tx_byte_swap1 = 0;                             // no byte swap
    //CT_MII_RT.txcfg1_bit.tx_32_mode_en1 = 1;                          // enable auto push with R30
    // CT_MII_RT.txcfg1_bit.tx_ipg_wire_clk_en1 = 0;                    // dont care about inter package gap
    //CT_MII_RT.txcfg0_bit.tx_ipg_wire_clk_en0 = 0;                     // same settings must apply for TX0 PORT
    CT_MII_RT.txcfg1_bit.tx_start_delay1 = 0;                           // no start delay
    CT_MII_RT.txcfg0_bit.tx_start_delay0 = 0;                           // no start delay
    CT_MII_RT.txcfg1_bit.tx_clk_delay1 = 0;                             // no delay
    CT_MII_RT.txcfg0_bit.tx_clk_delay0 = 0;                             // no delay
    CT_MII_RT.tx_ipg1_bit.tx_ipg1 = 16;                                 // 16 cycles delay between packets

    // ...

    CT_MII_RT.txcfg0_bit.tx_enable0 = 1;                                // enable TX0 PORT (?)
    CT_MII_RT.txcfg1_bit.tx_enable1 = 1;                                // enable TX1 PORT (?)

    // configure MII_G TX1
    CT_MII_G_RT.icss_g_cfg_bit.mii1_mode = 1;                           // RGMII mode
    CT_MII_G_RT.icss_g_cfg_bit.tx_l2_en = 1;                            // enable TX L2 FIFO
    CT_MII_G_RT.icss_g_cfg_bit.tx_l1_en = 1;                            // enable TX L1 FIFO

    // start sending bytes
    //__R31 |= (1 << 18);                                               // reset RX
    __R31 |= (1 << 30);                                                 // reset TX
    fill_level = CT_MII_RT.tx_fifo_level1_bit.tx_fifo_level1;           // read nibble cnt in FIFO (should be zero)

    // fill FIFO with some data
    data = 0xFFFFFFFF;
    __xout(40, 2, 0, data);
    __xout(40, 2, 0, data);
    __xout(40, 2, 0, data);

    fill_level = CT_MII_RT.tx_fifo_level1_bit.tx_fifo_level1;           // read nibble cnt in FIFO

    __R31 |= (1 << 29);  // TX EOF

    // L1 FIFO seems not to start ...

    while(1)
    {
        fill_level = CT_MII_RT.tx_fifo_level1_bit.tx_fifo_level1;
        __xin(40, 19, 0, status);
    }
}

I can see that the FIFO gets filled by checking CT_MII_RT.tx_fifo_level1_bit.tx_fifo_level1. I also see that the L2 FIFO has pushed the data to the L1 FIFO by reading the status via __xin(40, 19, 0, status);. However, the L1 FIFO seems to never push out its data on the signal lines TXD0-3. TXEN never gets high. The TRM lists a few conditions for the TX_EN to rise:

"
There are four dependencies that must be true for TX_EN to assert.
1. TX L1 FIFO not empty
2. Interpacket gap (IPG) timer expiration
3. RX_DV to TX_EN timer expiration
4. TX_EN compare timer expiration

"

I assume that all of them are either met or irrelevant for my use case. I am not interrested in a pre-amble, CRC or receiving anything, I just want the FIFO to output the bytes loaded into it. As far as I know, if I yould use the MII mode then there is a 25MHz clock needed as an input, however I use the RGMII mode (CT_MII_G_RT.icss_g_cfg_bit.mii1_mode=1), so the chip should use its internal RGMII clock (= MAIN_PLL0_HSDIV4).

Below a picture of my pin configuration:

I checked with the oscilloscope that TXD0 (W4) and/or TXEN (U5) never rise. Also I would expect CT_MII_RT.tx_fifo_level1_bit.tx_fifo_level1 to decrease anyway.

Can someone please help me to get this to work. Thank you.

Kind regards,
Martin

  • Hi Martin.

    Apologies for the delay. I was OOO thus the delay. Allow me some time to review the details and share the response by friday.

  • Hi Martin

    Understand that this query was supported offline - can you please let us know if there is anything open here?

    Regards

    Pratheesh

  • Hi there,

    I am sorry, I forgot a bit about this issue. It was solved with the help of TI offline.

    To provide a summary of the solution for others:

    1. Unfortunately, if you configure e.g. the MII1_TXD0 signal in the SysConfig Tool under PRU (ICSS)->Additional ICSS Settings ->MII_G_RT then the PAD PRG0_RGMII2_TD0 is not configured sufficiently for RGMII. The SysConfig Tools sets pull-up-down etc. accordingly, but it keeps the PAD configured for the PRG0_PRU1_GPO11 signal and not the required PRG0_RGMII2_TD0. Hence, I needed to configure it manually for the AM2434:

    #define PRG0_RGMII2_TD0_PAD_CFG        *(uint32_t*)0x000F41DC
    #define PRG0_RGMII2_TXC_PAD_CFG        *(uint32_t*)0x000F41F0
    #define PRG0_RGMII2_TX_CTL_PAD_CFG     *(uint32_t*)0x000F41EC
    #define PRG0_RGMII2_RXC_PAD_CFG        *(uint32_t*)0x000F41C8
    
    ...
    
    // manual config of PINs
    PRG0_RGMII2_TD0_PAD_CFG = (1 << 16) | 2;                          // out: disable pull-down/up and config MUX for RGMII
    PRG0_RGMII2_TXC_PAD_CFG = (1 << 16) | 2;                          // out: disable pull-down/up and config MUX for RGMII
    PRG0_RGMII2_TX_CTL_PAD_CFG = (1 << 16) | 2;                       // out: disable pull-down/up and config MUX for RGMII
    PRG0_RGMII2_RXC_PAD_CFG = (1 << 18) | (0 << 17) | (0 << 16) | 2;  // in: enable pull-up and config MUX for RGMII

    2. Despite I was interested in TX only RGMII, the RX clock PAD still needed to be configured and it needed to see a few edges. I alternated the the pull-up/down to simulate some edges on the receiving clock. This was sufficient. Alternately a clock could of course be connected to the RX clock pad.

    // RGMII_RX_CLK PIN needs to be toggled a few times, otherwise TX PORT will not work
    void PRU_poke_RGMII_RX_CLK(void)
    {
        for (uint8_t i = 0; i < 255; i++) {
            PRG0_RGMII2_RXC_PAD_CFG |= (1 << 17);   // pull-up
            PRG0_RGMII2_RXC_PAD_CFG &= ~(1 << 17);  // pull-down
        }
    }
    

    TI told me in offline support that the RX clock needed a few edges after configuration, because otherwise some registers in the clock domain of the RX clock would not be programmed properly. The TX logic needs these registers to be programmed properly even for sending only.

    My configuration for TX only RGMII looks now:

    #include <stdint.h>      // uint8_t, uint16_t, ...
    #include <pru_cfg.h>
    #include <pru_mii_rt.h>
    #include <pru_mii_g_rt.h>
    #include <pru_iep.h>
    
    #define RGMII_L2_FIFO_DEVICE_ID 40
    
    volatile register uint32_t __R30;
    volatile register uint32_t __R31;
    
    extern void asm_routine(void);
    
    void main(void)
    {
        // initial config
        CT_CFG.spp_reg_bit.xfr_shift_en = 1;                                // enable GP SP r0 32-bit shifting feature
    
        // configure GP CFG register
        CT_CFG.gpcfg1_reg_bit.pr1_pru1_gp_mux_sel = 2;                      // select GP MUX MII mode (in this mode PIN U5 never works)
        CT_CFG.gpcfg1_reg_bit.pru1_gpi_mode = 3;                            // select GPI MII mode
    
        // configure RGMII register
        CT_MII_G_RT.rgmii_cfg_bit.rgmii0_link = 1;                           // write to RD only link
        CT_MII_G_RT.rgmii_cfg_bit.rgmii0_speed = 2;                          // write to RD only speed
        CT_MII_G_RT.rgmii_cfg_bit.rgmii0_fullduplex = 1;                     // write to RD only full duplex
        CT_MII_G_RT.rgmii_cfg_bit.rgmii1_link = 1;                           // write to RD only link
        CT_MII_G_RT.rgmii_cfg_bit.rgmii1_speed = 2;                          // write to RD only speed
        CT_MII_G_RT.rgmii_cfg_bit.rgmii1_fullduplex = 1;                     // write to RD only full duplex
        CT_MII_G_RT.rgmii_cfg_bit.rgmii_eee_en = 0;                          // disable RGMII energy efficient
        CT_MII_G_RT.rgmii_cfg_bit.rgmii_eee_phy_only = 0;                    // disable phy low power
        CT_MII_G_RT.rgmii_cfg_bit.rgmii0_inband = 0;                         // disable InBAND for PORT0
        CT_MII_G_RT.rgmii_cfg_bit.rgmii0_gig_in = 1;                         // enable gig speed for PORT0
        CT_MII_G_RT.rgmii_cfg_bit.rgmii0_fullduplex_in = 1;                  // enable full duplex for PORT0
        CT_MII_G_RT.rgmii_cfg_bit.rgmii1_inband = 0;                         // disable InBAND for PORT1
        CT_MII_G_RT.rgmii_cfg_bit.rgmii1_gig_in = 1;                         // enable gig speed PORT1
        CT_MII_G_RT.rgmii_cfg_bit.rgmii1_fullduplex_in = 1;                  // enable full duplex for PORT1
    
        // configure MII_G_RT interface
        CT_MII_G_RT.icss_g_cfg_bit.tx_l1_en = 1;                             // enable TX L1 FIFO
        CT_MII_G_RT.icss_g_cfg_bit.tx_l2_en = 1;                             // enable TX L2 FIFO
        CT_MII_G_RT.icss_g_cfg_bit.rx_l2_g_en = 0;                           // disable RX L2 mode
        CT_MII_G_RT.icss_g_cfg_bit.mii0_mode = 1;                            // RGMII mode for PORT0
        CT_MII_G_RT.icss_g_cfg_bit.mii1_mode = 1;                            // RGMII mode for PORT1
        CT_MII_G_RT.icss_g_cfg_bit.iep1_tx_en = 0;                           // use IEP0 (default)
        CT_MII_G_RT.icss_g_cfg_bit.rtu_pru_psi_share_en = 0;                 // (default)
        CT_MII_G_RT.icss_g_cfg_bit.rx_sfd_tx_sof_en = 0;                     // (default)
        CT_MII_G_RT.icss_g_cfg_bit.sgmii_mode = 1;                           // SGMII default mode
    
        // configure inter-package-gap register
        CT_MII_RT.tx_ipg1_bit.tx_ipg1 = 40;                                  // (default)
        CT_MII_RT.tx_ipg0_bit.tx_ipg0 = 40;                                  // (default)
    
        // configure TX CFG registers
        CT_MII_RT.txcfg0_bit.tx_auto_preamble0 = 0;                          // enable auto preamble for PORT0
        CT_MII_RT.txcfg1_bit.tx_auto_preamble1 = 0;                          // enable auto preamble for PORT1
        CT_MII_RT.txcfg0_bit.tx_en_mode0 = 0;                                // disable TX_ENABLE self clear (default)
        CT_MII_RT.txcfg1_bit.tx_en_mode1 = 0;                                // disable TX_ENABLE self clear (default)
        CT_MII_RT.txcfg0_bit.tx_mux_sel0 = 0;                                // select PRU0 for TX0
        CT_MII_RT.txcfg1_bit.tx_mux_sel1 = 1;                                // select PRU1 for TX1
        CT_MII_RT.txcfg0_bit.tx_enable0 = 1;                                 // enable TX0 PORT
        CT_MII_RT.txcfg1_bit.tx_enable1 = 1;                                 // enable TX1 PORT
        CT_MII_RT.txcfg0_bit.tx_32_mode_en0 = 1;                             // enable 32-bit mode for PORT0
        CT_MII_RT.txcfg1_bit.tx_32_mode_en1 = 1;                             // enable 32-bit mode for PORT1
        CT_MII_RT.txcfg1_bit.tx_start_delay1 = 0;                            // no start delay
        CT_MII_RT.txcfg0_bit.tx_start_delay0 = 0;                            // no start delay
        CT_MII_RT.txcfg1_bit.tx_clk_delay1 = 0;                              // no delay
        CT_MII_RT.txcfg0_bit.tx_clk_delay0 = 0;                              // no delay
    
        // enable IEP counters
        CT_IEP0.global_cfg_reg_bit.cnt_enable = 1;                           // TODO: remove
        CT_IEP1.global_cfg_reg_bit.cnt_enable = 1;                           // TODO: remove
    
        CT_MII_RT.txcfg1_bit.tx_enable1 = 1;                                 // enable TX PORT1
        CT_MII_RT.txcfg0_bit.tx_enable0 = 1;                                 // enable TX PORT0
        CT_MII_G_RT.tx_stat_total_bytes_port1 = 0;
    
        // reset everything
        __R31 |= (1 << 30) | (1 << 23) | (1 << 18);                         // reset TX, reset RX, RX error clear
    
        // main loop
        while(1)
        {
            asm_routine();
        }
    }
    
    // To finally fill FIFO:
    // .asg 40, RGMII_L2_FIFO_DEVICE_ID  ; use RGMII TX Interface PORT 2
    //     xout RGMII_L2_FIFO_DEVICE_ID, &r2, 4
    
    

    I hope my summary helps others.

    Kind regards,

    Martin

  • Thank you for the detailed information Martin.