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.

Issue with RM57x EMAC

Other Parts Discussed in Thread: HALCOGEN, UNIFLASH, DP83640

I integrated the FreeRTOS UDP/IP stack I got from FreeRTOS.org and got it running correctly on an RM46x HDK.

I ported that code to an RM57x HDK, but ran into an issue. The code is hanging in the HL_emac.c file on line 1474:

while (EMAC_BUF_DESC_EOQ != (EMACSwizzleData(curr_bd->flags_pktlen) & EMAC_BUF_DESC_EOQ))

Apparently, the end of queue (EOQ) flag is not being set in any of the emac's buffer descriptors. I have not modified how the emac is being initialized between the RM46x and the RM57x - I call EMACHWInit from xNetworkInterfaceInitialise.

The EMAC device driver code looks pretty much the same between the two platforms - the biggest difference is the "twizzle" macro. Any idea why this might be happening?

Ray

  • Hi Ray,

      I think the problem is that RM57 has a byte swap issue when writing to the buffer descriptor. The EOQ bit is at bit28 of either the transmit or the receive BD. Due to the incorrect swap the EOQ bit is at bit 4 instead. There is a errata for this. Please see below.

      The workaround is to do a s/w swap between byte0 and byte 3 and also between between byte 1 and byte 2 before writing to the BD. 

      If you were to start off the EMAC example from RM57 in HalcoGen then the swap is taken care of. The emac.c that you ported from RM46 does not have this s/w swap. Please see below snippet of code in the emac.c for RM57 generated by HalcoGen.

    /**
     * \brief   Performs byte inversion of 32-bit data to counteract swizzling performed by CPU during reads of CPPI RAM.(Due to BE8 format)
     *
     * \param   word	The 32-bit word to be swizzled.
     * \return  uint32
     *
     **/
    /* SourceId : ETH_SourceId_056 */
    /* DesignId : ETH_DesignId_056*/
    /* Requirements : HL_ETH_SR78 */
    uint32 EMACSwizzleData(uint32 word) {
    	return
    		(((word << 24U) & 0xFF000000U) |
    		((word <<  8U) & 0x00FF0000U)  |
    		((word >>  8U) & 0x0000FF00U)  |
    		((word >> 24U) & 0x000000FFU));
    }

     I will suggest that you start off from RM57 emac example as I don't know how many places the swapping might need to be inserted. 

      

  • Charles,

    I started the RM57x project by generating code using HalCoGen. It appears the generated source in emac.c is incorrect as it is:

    uint32 EMACSwizzleData(uint32 word) {
    
    #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
        return word;
    #else
        return
            (((word << 24U) & 0xFF000000U) |
            ((word <<  8U) & 0x00FF0000U)  |
            ((word >>  8U) & 0x0000FF00U)  |
            ((word >> 24U) & 0x000000FFU));
    /*#endif*/
    }
    

    So I straightened that out. The next check is: while (((uint32)0U != *((uint32 *)0xFCF78600U)))

    the value at 0xFCF78600 is constant and is: 0xFC520000

    That value is in the EMAC address space. I've been trying to figure out what register is being read and what is at that address, but the TRM doesn't really provide that information.

    Ray

     

  • It appears I responded too quickly. According to the TRM:

     The location being read "while (((uint32)0U != *((uint32 *)0xFCF78600U)))" is not in the EMAC's address space and the value returned "0xFC520000" isn't either. I'm not sure I have all the data I need to debug this

    Ray

  • HI Ray,

      You are correct. The EMAC Slave registers should start at 0xFCF7_8000 and the EMAC Wrapper register should start at 0xFCF7_8800.

      For the same line of code what do you see in the RM46 version? They should be idetical between RM46 and RM57 as far as the EMAC registers are concerned.

  • Just one more note. The Ethernet RAM (the CPPI memory slave) is at 0xFC520000.
  • Charles,

    Again, I think I spoke before I knew what I was talking about. In looking closer in the TRM I see the EMAC Module Registers start at 0xFCF78000. Offset 0x600 is the Transmit Channel 0 DMA Head Descriptor Pointer Register. The code is waiting for TXDP0 to be equal to zero, but that isn't happening. I went back and made sure I have all the signals approriately connect to the EMAC, and I believe I do. One other difference between the RM46x and the RM57x is the value of the clock applied.

    For the RM46x VCLKA4_DIVR_EMAC is set to 80MHz.

    For the RM57x VCLKA4_DIV is set to 75MHz

    I assume VCLKA4_DIV is driving the EMAC, but HALCoGen isn't specific about that.

    Ray

  • Charles,

    I opened the HALCoGen project for the RM57x demonstration project that includes the LwIP demonstration - that demo works with the RM57x. I compared the settings to my HALCoGen settings and there are a couple of differences in the VCLKA4 setting and the input pimux settings. The LwIP project has the VCLKA4 set to 37.5MHz and in the pinmux input settings all the MDIO and MII settings are set to the alternate terminals. I see the same behavior: the code is stuck waiting for TXDP0 to be equal to zero. It stays constant with a value of 0xFC520000.

    There is another interesting difference in the emac.h file:

    LwIP emac.h: #define EMAC_MACSRCADDRLO_CONFIGVALUE ((uint32)((uint32)0x6CU << 8U) | (uint32)((uint32)0x08U))

    My RM57 emac.h file: #define EMAC_MACSRCADDRLO_CONFIGVALUE ((uint32)((uint32)0x6CU << 8U) | (uint32)((uint32)0xA6U))

    I tried changing my emac.h file to match the LwIP file and it didn't seem to make a difference. Any ideas on what I should try next?

    Ray

  • Further inspecting the LwIP HALCoGen project, I think the emac.h file is wrong on the MAC address - the LWiP HALCoGen is using the same MAC address as I am. Not sure how the values got messed up in the LwIP emac.h file.
  • Hi Ray,

      I'm not an ethernet expert so I have forwarded this thread to the HalcoGen team. In the meantime, please look at the below two threads that might help you in answering some of the questions.

    https://e2e.ti.com/support/microcontrollers/hercules/f/312/t/383664

    https://e2e.ti.com/support/microcontrollers/hercules/f/312/p/198066/1000463#1000463

     

  • Hi Ray,

    Will it be possible for you to share the Complete Project? We will try to recreate the issue at our bench. Thanks!

  • Charles,

    Thanks for the links, but I'm nearly positive my problem is not related to the MAC address.

    Thanks for your help,
    Ray
  • Hi Ray,
    Our HalCogen team will look at your project to see what went wrong. Below is another thread which talks about swapping of the order of the ip address due to the RM57 byte swapping errata.
    e2e.ti.com/.../1222243
  • Ray,
    I haven't tried your project yet, but do check again that your pinmux and clock and other configuration settings are correct. That's what usually causes me this issue. I'm not entirely clear if you see the same behaviour after changing the settings.
    Also, the MAC address is arbitrary and doesn't really affect behaviour, as long as it's not the Broadcast address.
    You've also mentioned that the generated code for EMACSwizzleData was wrong and that you straightened it out. Could you be more specific about the changes that you made? I don't think there's anything wrong with the generated code, unless you're using a much older version.
    Speaking of which, could you also tell us what version of HALCoGen you're using?

    Thanks and Regards,
    Chaitanya
  • Ray,
    I looked at the changes you made to EMACSwizzleData. Swizzling is required only for Big Endian devices and not for Little Endian ones (RM). So you ought to leave that API intact. Could you try that out and let me know if it works?

    Earlier, I think you had issues with your configuration when you made this API change but now it appears to be correct, so it ought to work.

    Thanks and Regards,
    Chaitanya
  • Chaitanya,

    Before I changed the "swizzle" code, execution was hanging in the HL_emac.c file on line 1474:

    while (EMAC_BUF_DESC_EOQ != (EMACSwizzleData(curr_bd->flags_pktlen) & EMAC_BUF_DESC_EOQ))

    It appeared as if the end of queue (EOQ) flag was not being set in any of the emac's buffer descriptors. I changed the code based on a suggestion from TI. You can follow this thread to see the conversation thread.

    Ray

  • Chaitanya,

    I haven't heard anything in two days. Are you still looking into this? I ported the FreeRTOS+UDP to a HALCoGen RM46x project and got everything working correctly. I used HALCoGen and generated a project for an RM57x and attempted to use the UDP/IP stack, but ran into issues within the EMAC device driver. I've double checked all the HALCoGen settings and posted my project for your review. I'm stuck and don't know how to proceed.

    Thank you,

    Ray
  • Ray,

    My apologies for the delay. I'd posted another message asking you to try with the original swizzle API and the updated configuration since the swizzle changes that were suggested to you do not apply to Little Endian devices, which includes RM57. This is most likely the issue.

    The EOQ issue that you've mentioned almost always occurs either due to Pinmux or due to the incorrect swizzle. This is because the loop condition fails either due to an incorrect condition or because it isn't able to transmit any data. Ideally this should get detected a lot earlier, but EMACHWInit passes as long as the PHY is able to detect a connection and hence works even if Pinmux isn't correctly configured. So basically, the loop you mentioned is the first real check of whether data is being transmitted properly even if your physical setup is fine.

    I have been having issues with the lone RM57 board that I have and haven't been able to get any project running running on it, and hence haven't been able to test your project on it.

    I'd ask you to replace your swizzle API with the old one and try with the new configuration, where you've enabled the required pins in input muxing as well. Here is the original API:

    uint32 EMACSwizzleData(uint32 word) {
        
    #if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
        return word;
    #else
        return
            (((word << 24U) & 0xFF000000U) |
            ((word <<  8U) & 0x00FF0000U)  |
            ((word >>  8U) & 0x0000FF00U)  |
            ((word >> 24U) & 0x000000FFU));
    #endif
    }

    My apologies again for the delay in replying. I hope you can get things running.


    Thanks and Regards,

    Chaitanya

  • Chaitanya,

    Before I changed the "swizzle" code, execution was hanging in the HL_emac.c file on line 1474:

    while (EMAC_BUF_DESC_EOQ != (EMACSwizzleData(curr_bd->flags_pktlen) & EMAC_BUF_DESC_EOQ))

    It appeared as if the end of queue (EOQ) flag was not being set in any of the emac's buffer descriptors - which doesn't seem likely. I changed the code based on a suggestion from TI - please follow this thread to see the conversation.

    Ray

  • Ray,
    I have been following this thread and correct me if i'm wrong but the sequence appears to be like this: (EOQ flag error -> Swizzle API changed. -> Input Muxing fix.) Before you changed the swizzle code, you didn't have the right pinmux settings, which could've been causing the issue at that point. So all I'm asking is if you're running right now with the correct pinmux settings and the original swizzle API. This part is not clear to me from this thread and the project that you've uploaded has the modified swizzle API. It'd help if you could clarify that since I'm unable to debug your project on an actual board at this point.

    Thanks and Regards,
    Chaitanya
  • Chaitanya,

    The changes I made in HALCoGen were to change VCLK4 from 75MHz to 37.5MHz and use the alternate terminal connections for MII and MDIO as opposed to the primary. I'm not sure I'd classify those changes as a piinmux "fix".

    I assume the MAC is the same on both the RM46 and the RM57 - on the RM46 VCLK4 is set to 80MHZ, but that selection isn't possible using HALCoGen for the RM57x target. 

    I'm not convinced that either of these settings have anything to do with the behavior I'm seeing, but I'll go back and conduct more tests while controlling all the changes. I probably won't be able to get back to until sometime next week.

    Ray

  • Chaitanya,

    I loaded the RM57x demonstration project for LwIP on my RM57x HDK hardware. Everything works correctly with respect to the Ethernet interface - I could ping it from my host.

    I used HALCoGen to compare my project settings to those in the LwIP demonstration project - they are the same.

    I used the debugger to trace the problem to line #109 in HL_mdio.h (this appears on line #71 in the LwIP version):

    *dataPtr = (uint16)((HWREG(baseAddr + MDIO_USERACCESS0))
                                        & PHY_DATA_MASK);
    
    baseAddr = 0xFCF78900
    
    MDIO_USERACCESS0 = 0x20610000
    
    PHY_DATA_MASK = 0xFFFFU
    
    These values are the same for both projects, but my project always returns "0"

    I've ruled out the hardware platform,

    I've ruled out the HALCoGen settings,

    I also made copies of the source files from both projects and re-named them appropriately so that I could compare them. It appears there are differences with respect to "C" casting in the FreeRTOS generated HALCoGen code, but other than that I couldn't find any real differences.

    Can you help with what I should look at next? What would cause the MDIO interface to return zero?

    Ray

  • Chaitanya,

    I meant to add one more thing. When I use the LwIP project, the red error LED is NOT illuminated and I can use UniFlash to program the image. In my project the red error LED is ALWAYS illuminated and I have to use a work around Charles Tsai came up with to generate the RAM ECC in the link command file rather than let the flash programmer do it. You can ask Charles, but I have to go through a manual process to program an image to flash using CCS.

    I need FreeRTOS because I'm using the RM57x to perform closed loop feedback mechanical motion control and the FreeRTOS scheduler provides the real-time timing for me while allowing me to use the spare CPU cycles for other things.

    Ray
  • Ray,

    Could you post the call stack in your project? That is, which API is calling MDIOPhyRegRead, since most of the PHY APIs do so. I'm guessing it's either Dp83640IDGet or Dp83640LinkStatusGet in EMACHWInit. This is where you're likely to have such issues and this usually occurs when the PHY can't detect a connection. Since you said that the same setup works with the lwIP demo, I don't think it's a hardware issue. Knowing which API is calling the MDIO API will help but these errors almost always occur when there's a connection issue with the PHY.

    Could you also check those C casting differences you were talking about? While it might seem farfetched, I've had some strange issues pop up due to casting in the past.

    As far as the red LED goes, could you check what ESM error triggers it? You can do so by checking the ESM status registers in the registers tab. We had a similar issue due to incorrect flash ECC and the workaround used to be to fill the flash before loading your program. I'm not sure if your workaround is similar, I'll ask Charles to comment on this.


    Thanks and Regards,

    Chaitanya

  • Chaitanya,

    I'm multi-tasking between several projects and I won't be able to respond timely to some of your requests as my tasking has me bouncing between offices. I can't get to the call stack right now, but you are correct in that the API is being called from EMACHWInit. I call EMACHWInit from network code that initializes the HW and the UDP/IP stack. Please keep in mind the code I use to call the HW initialization for the HW and UDP/IP stack works on my RM46x. I used HALCoGen to generate the HW layer for the RM57x HDK, but the code making the calls into the API and implementing the stack is the same and is known to work (on the RM46x).

    This is absolutely a HW issue - but it could be caused by how the pinmux is configured. As I already said, I compared my settings to the LwIP project settings and they are the same, however, there could be other settings I'm not aware need to be checked. You are also correct that the error indicates the PHY can't detect a connection - I can verify this is not a network issue (recall the LwIP demo works on the same HW without re-configuring the network connections).

    Finally, the red LED issue is well documented in the thread where I worked with Charles to resolve the flash programming problems. Please see:

    The casting differences are no trivial quantity to verify - there are hundreds (maybe thousands) of them. On a cursory check in HL_emac.c, they all look OK. If you are aware of anyone at TI that has used HALCoGen to generate the HW abstraction layer for the RM57x and verified the EMAC is working correctly, that project would be helpful to me in troubleshooting the problem. Please note that the HALCoGen project for the LwIP and the FreeRTOS projects produce code that is largely the same, but does have some differences. The differences lead me to think the result is coming from two separate TI teams.

    I'm currently assuming the most likely issue is a pinmux (or other HW) configuration problem. THe best case scenario for me is if you or someone at TI could use my project to duplicate the issue.

    Ray

  • Ray

    The lwIP demo is ported from an older project. HALCoGen, in the mean time, has been updated with various MISRA C fixes. Hence the casting differences. I misunderstood your earlier comment, I should've mentioned this earlier. These are mostly MISRA fixes and don't affect functionality.

    Also, there's a simple EMAC loopback example in HALCoGen for RM57. It's just the main file with instructions on the required project configurations, so it may not be as helpful. You could try it out though, just to check if you still see the issue.

    Also, as I mentioned earlier, my lone RM57x HDK is no longer working. I'll see if I can find another one to try out your project.

    Thanks and Regards,

    Chaitanya

  • Hi Chaitanya,

    Any update in regards to locating an RM57x HDK for testing? Were you able to succesfully run Ray's project to recreate the issue?

    Best Regards,

    Mark-

  • Mark,
    I've just got my hands on an RM57 board.
    Ray,
    I'm having a load issue where I get the following error with your project:

    CortexR5: File Loader: Memory write failed: Unknown property "FlashBlankCheckToggle"

    Let me know if there's some settings I need to change or something I'm doing wrong. This is when I import your project and build+load straight out.

    Thanks and Regards,
    Chaitanya
  • Chaitanya,

    The problem you're experiencing is the flash programming issue I described earlier. Charles Tsai came up with a work around, but I believe there is still some issue with HALCoGen. You can read the thread between Charles and I here: https://e2e.ti.com/support/microcontrollers/hercules/f/312/t/394975#pi239031349=2 

    Essentially Charles had me disable the auto ECC capability in CCS, then manually start the flash programming and debugger start process. Charles provided a modified linker command file that implements the ECC and auto set of flash memory (you should be able to find that file in the project). I used UniFlash to erase the flash then followed Charles' instructions on loading the image and strating the debugger.

    If you use HALCoGen and generate an empty FreeRTOS project on your own you'll see you have the flash programming issue - it has nothing to do with my project specifically.

    Ray

  • Hi Chaitanya,

    This "FlashBlankCheckToggle" is an error in the debug server flash package, one of the XML files.

    Dave Livingston has an updater package for CCS that is in the pipeline to fix this.  I'll send this to you directly.
    It will likely be available this week on the external update site as well.

  • Ray,

    Thanks for clarifying on this. I'll get back to you once I'm running the project.

    Anthony,

    Thanks for this. I'll update immediately.

    Regards,

    Chaitanya

  • Ray, 1. It looks like the return code from the "EMACHWInit(emacAddress)" is ignored! Verify that you successfully initialized PHY. 2. Is it possible to call EMACTransmit() before the EMACHWInit() done? I was using notepad to look at the code! Thanks, Joe
  • Joe,

    Good catch. In the code I sent to you I believe I'm using a simple wait timer to make sure that doesn't happen as I also thought that could be a problem - I experimented with the wait time value to make sure enough time is passing. The code you have is prototype and I don't intend to leave it that way for my deliverable. In fact, I've already changed the code to get positive feedback whether the initialization succeeds or fails and proceed or not with my sockets code depending on the outcome.

    Unfortunately, that isn't the problem - I'm sure my sockets code is not calling EMACTransmit before the EMACHWInit call has a chance to succeed or fail. Also, please keep in mind the UDP/IP stack code is an application - it is not related to the HW abstraction layer (other than the call to initialized the EMAC) - and it works fine on the RM46x target. The fact that the red error LED is never extinguished when using a HALCoGen generated RM57x FreeRTOS image tells me something is wrong. The other RM57x images: LwIP and Hercules Demo code do not have the red error LED lit.

    Ray

  • I've been busy working proposals for the last two weeks. Has any progress been made on this issues? I saw that updates to CCS were released - at least one change was related to flash issues. Is there any new status?

    Thank you,

    Ray

  • Ray,

    The new CCS update seems to fix the Flash issue, though in my case, I had to disable data verification to get the project running.

    I also tried your project and had the same issue, and to be honest, I can't figure out why it's happening. The ALIVE and LINK registers each have a bit set, which means the board is detected. I also changed the PHY channel number to 1, but that didn't work either (that's the PHY channel used in the lwIP demo, and also the bit that gets set in the MDIO registers). All the configuration apart from that seems to be the same.

    As you've mentioned, the fact that the red LED gets lit up each time indicates that there's an error caused with something that's seemingly unrelated but is affecting Ethernet connectivity.

    Have you found anything different since the last time?


    Chaitanya

  • Hello,

    I have almost the same problem. I am using a TMS570LC4 with a DP83848 Ethernet Physical Layer Transceiver. With the Halcogen drivers for the dp83640 I am able to check the link (true) and to read out the ID (correct). Unfortunately, when I use the function EMACTransmit(...) the program hangs in:

    while (EMAC_BUF_DESC_EOQ != (EMACSwizzleData(curr_bd->flags_pktlen) & EMAC_BUF_DESC_EOQ))
        {
        }

    What am I doing wrong? Any news on this issue?

    Kindly regards,

    Werner

  • Hi,
    there is an other HALCoGen - EMAC related problem (as I see).

    The HALCoGen (version 04.04.00) generated code (file: HL_emac.c, function EMACTransmit())

    /* Don't write to TXHDP0 until it turns to zero */
    /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Hardware status bit read check" */
    /*SAFETYMCUSW 134 S MR:12.2 <APPROVED> "LDRA Tool issue" */
    while (((uint32)0U != *((uint32 *)0xFCF78600U)))
    {
    }
    /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are assigned in this driver" */
    curr_bd->next = active_head;
    /*SAFETYMCUSW 134 S MR:12.2 <APPROVED> "LDRA Tool issue" */
    /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are assigned in this driver" */
    if (EMAC_BUF_DESC_EOQ == (EMACSwizzleData(curr_bd->flags_pktlen) & EMAC_BUF_DESC_EOQ)) {
    /* Write the Header Descriptor Pointer and start DMA */
    /*SAFETYMCUSW 439 S MR:11.3 <APPROVED> "Address stored in pointer is passed as as an int parameter. - Advisory as per MISRA" */
    /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Valid non NULL input parameters are assigned in this driver" */
    EMACTxHdrDescPtrWrite(hdkif->emac_base, (uint32)(active_head), (uint32)EMAC_CHANNELNUMBER);
    }

    The problem is that, checking of TXHDPx register doesn't follow the change of EMAC_CHANNELNUMBER - so the code is waiting for zero value of TXHDP0 while DMA channel number 1-7 is beeing used.

    Szilard