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.

AM3894: EMAC Receive Threshold Interrupt setup

Part Number: AM3894

The AM389x TRM (SPRUGX7C) states the following about EMAC Receive Threshold Interrupts: 

  • The receive threshold interrupts use the same free buffer count and threshold logic as does flow control, but the interrupts are independently enabled from flow control. The threshold interrupts are intended to give the host an indication that resources are running low for a particular channel(s).

I would like to add the Receive Threshold notification (without flow control) to my design, which currently only implements Receive Packet Completion Interrupts for the receive channel, in order to avoid cases where the EMAC runs out of available Rx buffers (causing a HOSTPEND error).  However, my attempts at using the Rx Threshold feature have been unsuccessful so far.


Per the instructions in the TRM, it seems like it should be fairly straightforward. to use  As I understand it, the steps necessary to configure the Rx Threshold functionality are as follows:

  1. Initialize the receive channel n free buffer count register (RXnFREEBUFFER) with the total number of allocated Rx buffers for the channel.
  2. Establish the trigger threshold via the RXnFLOWTHRESH register.
  3. Enable the receive channel interrupt bits in the receive interrupt mask set register (RXINTMASKSET), which was already being done for Rx Packet Completion Interrupts.
  4. Enable the interrupt via the CMRXTHRESHINTEN register.

After setting all this up (including modifying my code to update RxnFREEBUFFER for every buffer reclaimed by the host), I can see the RxnFREEBUFFER updating as expected (EMAC is consuming buffers, host is reclaiming buffers).  However, even with the RXnFLOWTHRESH buffer set to an artificially high threshold value, I never see the CMRXTHRESHINTSTAT register indicate a Rx Threshold condition on the channel.  Could there be some setup step that I'm missing?

Thanks!


  • Hi Shane,

    You check CMRXTHRESHINTSTAT register for pending interrupt, but what about MACINVECTOR register? Can you also check this register for pending interrupt?

    Which of the 8 channels exactly you are using? Or you are using all of them?

    An RX_THRES_PEND[7:0] interrupt bit is asserted when enabled and when the channel’s associated receive channel n free buffer count register (RXnFREEBUFFER) is less than or equal to the channel’s associated receive channel n flow control threshold register (RXnFLOWTHRESH).

    First verify that interrupt is enabled, then verify that RXnFREEBUFFER register value is less than or equal to RXnFLOWTHRESH value.

    Can you also provide me register dump (address and value) of the involved registers? Make that dump at configuration time and then at the time you expect the interrupt to occur.

    CMRXTHRESHINTEN
    CMRXTHRESHINTSTAT
    MACINVECTOR
    RXINTMASKSET
    RXnFLOWTHRESH
    RXnFREEBUFFER


    Regards,
    Pavel
  • Hi Pavel,

    We are using channel 0 only.

    Here are those register dumps you requested. The first set is immediately after configuration and the second set is after I've initiated the condition that I believe should have triggered the Rx Threshold Interrupt. (For this experiment, I allocated 256 Rx buffers and set the Rx Threshold artificially high at 255 (the max value), just to make sure the interrupt would trigger without much effort).

    Register values after init:
    ---------------------------------
    CMRXTHRESHINTEN: 0x00000001
    CMRXTHRESHINTSTAT:0x00000000
    MACINVECTOR: 0x00000000
    RXINTMASKSET: 0x00000001
    RX0FLOWTHRESH: 0x000000FF
    RX0FREEBUFFER: 0x00000100

    Register values during condition that should cause Rx Threshold Interrupt
    ---------------------------------------------------------------------------------------------------
    CMRXTHRESHINTEN: 0x00000001
    CMRXTHRESHINTSTAT:0x00000000
    MACINVECTOR: 0x00000001
    RXINTMASKSET: 0x00000001
    RX0FLOWTHRESH: 0x000000FF
    RX0FREEBUFFER: 0x000000FA

    The Rx packet completion interrupt works reliably, but I've never seen the Rx Threshold interrupt go active.

    Thanks,
    Shane
  • Shane,

    Do you use AM389x EZSDK? Can you also add register MACEOIVECTOR in the list with register dump.

    Make sure that some piece of code do not clear bit 0 (from 1 to 0) in CMRXTHRESHINTSTAT register, before you read it to check if interrupt had occur.

    Regards,
    Pavel
  • Pavel,

    We don't use the AM389x EZSDK. We are using VxWorks 6.9 with a modified version of the ti_dm81xx_evm BSP that has been customized for our hardware. However, VxWorks only manages EMAC0 in our system. EMAC1 is managed directly by our own custom “driver” based loosely on the DM816x test code provided by Spectrum Digital. We started with the code found in evm816x_BSL\evm816x\tests\emac_loopback\emac_gmii_test.c and adapted it for use as a VxWorks task, which services EMAC1. I currently don't have any ISR's connected or enabled for the Rx Threshold interrupt, so as far as I know, there shouldn't be any code accessing the CMRXTHRESHINTSTAT register.

    Here are those register dumps again, this time with the MACEOIVECTOR value included:

    Register values after init:
    ---------------------------------
    CMRXTHRESHINTEN: 0x00000001
    CMRXTHRESHINTSTAT:0x00000000
    MACINVECTOR: 0x00000000
    MACEOIVECTOR: 0x00000001
    RXINTMASKSET: 0x00000001
    RX0FLOWTHRESH: 0x000000FF
    RX0FREEBUFFER: 0x00000100

    Register values during condition that should cause Rx Threshold Interrupt
    ---------------------------------------------------------------------------------------------------
    CMRXTHRESHINTEN: 0x00000001
    CMRXTHRESHINTSTAT:0x00000000
    MACINVECTOR: 0x00000001
    MACEOIVECTOR: 0x00000001
    RXINTMASKSET: 0x00000001
    RX0FLOWTHRESH: 0x000000FF
    RX0FREEBUFFER: 0x000000F6

    Thanks,
    Shane
  • Shane,

    Shane Hargrove said:
    However, VxWorks only manages EMAC0 in our system. EMAC1 is managed directly by our own custom “driver” based loosely on the DM816x test code provided by Spectrum Digital.

    Do you observe this issue for both EMAC0 and EMAC1?

    Shane Hargrove said:
    We started with the code found in evm816x_BSL\evm816x\tests\emac_loopback\emac_gmii_test.c and adapted it for use as a VxWorks task, which services EMAC1. I currently don't have any ISR's connected or enabled for the Rx Threshold interrupt, so as far as I know, there shouldn't be any code accessing the CMRXTHRESHINTSTAT register.

    I am not familiar with VxWorks code base, so I can not confirm that nothing is clearing the interrupt from pending.

    Shane Hargrove said:
    RX0FLOWTHRESH: 0x000000FF
    RX0FREEBUFFER: 0x00000100

    Can you try with the below registers settings, will be there any difference?

    RX0FLOWTHRESH: 0x000000FA

    RX0FREEBUFFER: 0x0000010F

    Shane Hargrove said:
    RXINTMASKSET: 0x00000001

    Can you also add RXINTMASKCLEAR register in the list with register dump.

    Regards,
    Pavel

  • Pavel,

    Are you asking if we've ever seen the HOSTPEND condition on EMAC0? If so, then the answer is no, I don't think so. However, the VxWorks networking stack tasks operate a higher priority than the user application tasks, so they are much less likely to experience this type of issue. Also, we are using EMAC1 in a completely different fashion than EMAC0. EMAC1 is functioning as a "backplane" Ethernet interface, communicating via link-layer messaging directly with another processor on the board, whereas EMAC0 is a typical external LAN interface.

    However, I did examine the VxWorks END driver for the TI EMAC, which was included with our BSP, hoping to find an example of how to process the Rx Threshold interrupt, but it does not appear to implement that interrupt. I only find handling of Rx and Tx packet interrupts in the driver code, so there is nothing to compare it to.

    I am fairly certain that VxWorks isn't manipulating EMAC1 registers in our system. That interface has been disabled in the OS so that we can control it directly from our application code.

    Is there anything special about those values of RX0FLOWTHRESH and RX0FREEBUFFER that you specified? (I assume you want me to use 0x0000010F as the initial value of RX0FREEBUFFER, since that value changes dynamically after initialization, correct?) I may have to do some additional work to set up that experiment. In my current test setup, I can only throw data at the EMAC at a rate that will cause the delta between RX0FREEBUFFER and RX0FLOWTHRESH to be around 9 at most (based on my observations). That's why I was setting the threshold so high. To achieve a delta of 21 will take some time and additional equipment that I don't currently have access to.

    RXINTMASKCLEAR is always 0x00000001.

    Thanks,
    Shane
  • Shane H said:
    Are you asking if we've ever seen the HOSTPEND condition on EMAC0?

    No, I am not. I am asking about Rx threshold interrupt condition.

    Shane H said:
    However, I did examine the VxWorks END driver for the TI EMAC, which was included with our BSP, hoping to find an example of how to process the Rx Threshold interrupt, but it does not appear to implement that interrupt. I only find handling of Rx and Tx packet interrupts in the driver code, so there is nothing to compare it to.

    I also checked AM389x EZSDK (u-boot, linux kernel) and TI EVM EMAC diagnostic test, but Rx Threshold interrupt is not implemented.

    Shane H said:
    Is there anything special about those values of RX0FLOWTHRESH and RX0FREEBUFFER that you specified? (I assume you want me to use 0x0000010F as the initial value of RX0FREEBUFFER, since that value changes dynamically after initialization, correct?) I may have to do some additional work to set up that experiment. In my current test setup, I can only throw data at the EMAC at a rate that will cause the delta between RX0FREEBUFFER and RX0FLOWTHRESH to be around 9 at most (based on my observations). That's why I was setting the threshold so high. To achieve a delta of 21 will take some time and additional equipment that I don't currently have access to.

    My idea is to isolate some timing issue, when Rx threshold interrupt condition happen too fast for the system and thus missed. Delta between 9 should be fine for that use case, for example:

    RX0FLOWTHRESH: 0x000000F7

    RX0FREEBUFFER: 0x00000100

    Regards,
    Pavel

  • Pavel,

    Thank you for checking EZSDK and the TI EVM EMAC diagnostic test source code. I was wondering if any of the TI drivers implemented that particular interrupt.

    Your idea makes sense to me...I was thinking the exact same thing. However, that's why I decided to use a small delta (as small as 1) instead of a larger delta, in an effort to make it easier to trigger the threshold interrupt, and perhaps stay in that condition longer. The TRM states: "The receive threshold interrupts are level interrupts that remain asserted until the triggering condition is cleared by the host." Am I thinking about this incorrectly?

    Thanks,
    Shane