BF609: Ethernet - sending on one core, receive on another

Hello, guys!

I have some question about ethernet. For example, in my application I need to send data from Core0 and receive on Core1. But if I initialize lwip on Core 0, and do same action on Core 1, I can see that sending operation on Core0 through sendto() return number sended bytes, but traffic analyzer (Wireshark) doesn't see this sent packet, but if I do sending operation on Core 1 (core which initialize lwip second time) then I see this packet in Wireshark. I tried not initialize lwip on Core1 (commenting function adi_lwip_Init() in adi_initialize.c) and I got next results: sending on Core0 goes success and packet falls into Wireshark, but listening on Core1 through the same socket is possible only if on Core0 ethernet listening thread works, i.e. I have double work on receiving operation for both cores, moreover if I'm not using receiving thread on Core0 (excluding it from execution) I can't thereafter receiving data in remaining listening thread on Core1. Search the reasons such behavior in source files for ethernet drivers for now doesn't help me. Maybe I do something wrong. If you know how to solve this problem, please, let me know.

For lwip settings I use static ip address, in my case 10.10.70.1 and port 7001. Sending and receiving goes through the same port on both cores, but I tried different ports - result is same. 

  • 0
    •  Analog Employees 
    on Oct 23, 2020 4:55 AM 1 month ago
  • 0
    •  Analog Employees 
    on Oct 29, 2020 8:25 AM 1 month ago

    Hi,

    EMAC0 is controlled by Core0 and EMAC1 by Core1.

    When we operate any device from CORE-1, we need to map the corresponding interrupt to CORE-1. By default, all interrupts are mapped to CORE-0. In other words, Any system interrupt source can be assigned to any of the available cores on the BF609 processor. This can be done by function call “adi_sec_SetCoreID(INTR_EMAC1_STAT,ADI_SEC_CORE_1)" in core1 initialization

    Please find corresponding documentation related to this by following steps.

    Help->Help Contents->CrossCoreRegistered Embedded Studio 2.x.x-> ->System Run-Time Documentation -> System Services and Device Drivers->ADSP-BF60x API Reference->Modules->Interrupt Related APIs->System Event Controller (SEC) APIs

    Also, CCES provides example codes, could you please try by running the examples from LwIP installation.

    You can find the multicast examples after installing the lwIP BSP.You can download the BSP in the below link.
    download.analog.com/.../ADI_lwIP_Stack-Rel2.6.0.exe

    After finished the installation,examples can be found in the below installation path.
    <lwipInstallationPath>\lwip\Blackfin\examples\multicast\projects

    We recommended to refer the lwIP user guide which is available in the below path.
    <installation path>\Analog Devices\lwIP_Stack-Rel2.6.0\Docs

    If still you are facing issues, Can you please provide more details about the problem, this will help us to assist you further.

    1. What is the application you are using.
    2. Please describe your test setup - connection between PC to EZ-Kit (using direct connection or router), Lwip configuration, PC configuration in order to send/receive data.
    3. Can you please share the sample project with steps to reproduce this issue.

    Regards,
    Nishanthi.V

  • Hello!

    Thanks for your quick answer, sorry for my late)

    If I set INTR_EMAC1_STAT for core_1 then I'm rewriting handlers for core_0 and transmitting/receiving operations for core_0 will be impossible. But I need core_0 receiving and transmitting messages too as core 1. I've seen ethernet drivers code. Function adi_sec_setCoreID() used as sub call in function 

    adi_int_InstallHandler(pDev->Interrupt/* INTR_EMAC1_STAT */, EMACInterruptHandler, (void *)pDev, true)

    Besides during lwip initialization on core_1 system modifys some of the emac registers which common for core_0 and core_1.

    Is exist any solution save lwip functionality for core_0 after initialization core_1?

    I've changed port configurations for core 0 and for core 1 EMAC0_PHY0_DP83848_PORT_CFG EMAC0_PHY0_DP83848_INT and EMAC0_PHY0_DP83848_ACK_PHY_INT in adi_gemac_proc_int.h. Now core_0 and core_1 have different interrupts id. I saw something like this here:

    https://ez.analog.com/dsp/software-and-development-tools/cces/f/q-a/115640/gpio-interrupt-handling-issue/345826#345826

    But this is not solved the problem.

    You are right when said about INTR_EMAC1_STAT. After resetting handlers things goes bad)

    I saw definition  INTR_EMAC1_STAT in defBF609.h

    Maybe you know:

    1) Is would impossible to set similar on INTR_EMAC1_STAT(his number 70) interrupt definition for example to 71 position which reserved?

    2) If I will be reset INTR_EMAC1_STAT handlers and modified emac registers before using any lwip operation on core_0 and core_1 correspondingly is it solve my problem?

    Thanks

  • 0
    •  Analog Employees 
    on Nov 19, 2020 2:08 PM 13 days ago in reply to CDEADS

    Hi,

    Can you please try with our example project and let us know if it is working correctly. Also can you please let us know if you are using the custom board or Ez kit.

    The lwIP examples are distributed with the add-in and installed in these directories:
    <lwipInstallationPath>\lwip\Blackfin\examples.

    Refer to the readme.html file provided with each example for details.

    Also please refer the below given CCES help path for referring the API's which might help you:
    CrossCore® Embedded Studio 2.9.x > System Run-Time Documentation > System Services and Device Drivers > ADSP-BF60x API Reference > Data Structures

    Also can you please share us your project along with the steps to reproduce the issue and share us the screenshot of the issue if possible.

    Regards,
    Nishanthi.V

  • Hello,

    Your example project works well.

    Unfortunately, I'm using custom board and on it PHY works with EMAC1. Early I modified code for work with EMAC1 device. And things goes well when I worked with LWIP stack on one of the cores - core_1 or core_0 it doesn't matter. In time of project development I needed to use core_0 and core_1 both work with lwip stack. And here I stalked with problem about which I wrote to this topic.

    I have also BF609 EZ-Kit pcb board and I think I can compile part of my project on it to reproduce my problem.

    As about questions which I asked in early message. I can answer by myself on second one. Yeah, it's possible make switch between lwip settings for core_0 and core_1. If last time when you used for ethernet transmitting/receiving operations, for example, core_1 and want to use now for transmit/receiving core_0 then you need next actions before any operations:

    ADI_EMAC_DEVICE* const  pDev = (ADI_EMAC_DEVICE*)&gEMAC1;
    
    pDev->pEMAC_REGS->EMAC_DMA_OPMODE &= ~(BITM_EMAC_DMA_OPMODE_SR);
    pDev->pEMAC_REGS->EMAC_DMA_OPMODE &= ~(BITM_EMAC_DMA_OPMODE_ST);
    
    adi_int_InstallHandler(pDev->Interrupt /*INTR_EMAC1_STAT*/, EMACInterruptHandler, (void *)pDev, true);
    
    /* if you use different mac addresses on each core */  
    adi_ether_SetMACAddress(pDev,(const uint8_t *)pDev->MacAddress);
    ADI_EMAC_REGISTERS* const  pEmacRegs = pDev->pEMAC_REGS;
    
    pEmacRegs->EMAC_DMA_TXDSC_ADDR  = (uint32_t)pDev->Tx.DMAChan[0].pDmaDescHead;
    pEmacRegs->EMAC_DMA_RXDSC_ADDR  = (uint32_t)pDev->Rx.DMAChan[0].pDmaDescHead;
    
    uint32_t RxDmaStatus = pEmacRegs->EMAC_DMA_STAT & BITM_EMAC_DMA_STAT_RS;
    
    if( RxDmaStatus == ENUM_EMAC_DMA_STAT_RS_SUSPENDED) { pEmacRegs->EMAC_DMA_RXPOLL = 0x1; }
    else if (RxDmaStatus == ENUM_EMAC_DMA_STAT_RS_STOPPED) { pEmacRegs->EMAC_DMA_OPMODE |= BITM_EMAC_DMA_OPMODE_SR; }
    pDev->pEMAC_REGS->EMAC_DMA_OPMODE |= BITM_EMAC_DMA_OPMODE_SR;
    
    uint32_t TxDmaStatus = pEmacRegs->EMAC_DMA_STAT & BITM_EMAC_DMA_STAT_TS;
    if( RxDmaStatus == ENUM_EMAC_DMA_STAT_RS_SUSPENDED) { pEmacRegs->EMAC_DMA_TXPOLL = 0x1; }
    else if (RxDmaStatus == ENUM_EMAC_DMA_STAT_RS_STOPPED) { pEmacRegs->EMAC_DMA_OPMODE |= BITM_EMAC_DMA_OPMODE_ST; }
    pDev->pEMAC_REGS->EMAC_DMA_OPMODE |= BITM_EMAC_DMA_OPMODE_ST;
    
    /* do receining/send actions below */

    In my case I use same PHY(DP83848i) device for each core. But this is useless approach in my case.

    In hardware reference I saw this picture

    Is there really no way associate same source interrupt to both cores for simultaneous interrupt processing? In my project ETH1_PHYINT signal goes on PE12. And if for SSI I associate signal from this pin on different interrupt sources, as below

    // for core_0
    #	define EMAC1_PHY0_DP83848_PORT_CFG                          \
    	do { 									                    \
    		*pREG_PINT3_ASSIGN   |= (BITM_PINT_ASSIGN_B1MAP);       \
    		*pREG_PINT3_MSK_SET   = BITM_PINT_MSK_SET_PIQ12 ;       \
    		*pREG_PINT3_INV_SET   = BITM_PINT_INV_SET_PIQ12 ;       \
    																\
    		*pREG_PORTE_FER_CLR   = BITM_PORT_FER_CLR_PX12  ;       \
    		*pREG_PORTE_DIR_CLR   = BITM_PORT_DIR_CLR_PX12  ;       \
    		*pREG_PORTE_INEN_SET  = BITM_PORT_INEN_SET_PX12 ;       \
    		*pREG_PORTE_POL_SET   = BITM_PORT_POL_SET_PX12  ;       \
    																\
    		*pREG_SEC0_GCTL      |= ENUM_SEC_GCTL_EN;               \
    		*pREG_SEC0_CCTL0     |= ENUM_SEC_CCTL_EN;               \
    																\
    		*pREG_PINT3_LATCH    = BITM_PINT_LATCH_PIQ12;           \
    	} while (0)
        
    #		define EMAC1_PHY0_DP83848_INT    (INTR_PINT3_BLOCK)
    #		define EMAC1_PHY0_DP83848_ACK_PHY_INT    do { *pREG_PINT3_REQ = BITM_PINT_REQ_PIQ12; } while (0)
    
    // for core_1
    #	define EMAC1_PHY0_DP83848_PORT_CFG                          \
    	do { 									                    \
    		*pREG_PINT4_MSK_SET   = BITM_PINT_MSK_SET_PIQ28 ;       \
    		*pREG_PINT4_INV_SET   = BITM_PINT_INV_SET_PIQ28 ;       \
    																\
    		*pREG_PORTE_FER_CLR   = BITM_PORT_FER_CLR_PX12  ;       \
    		*pREG_PORTE_DIR_CLR   = BITM_PORT_DIR_CLR_PX12  ;       \
    		*pREG_PORTE_INEN_SET  = BITM_PORT_INEN_SET_PX12 ;       \
    		*pREG_PORTE_POL_SET   = BITM_PORT_POL_SET_PX12  ;       \
    																\
    		*pREG_SEC0_GCTL      |= ENUM_SEC_GCTL_EN;               \
    		*pREG_SEC0_CCTL0     |= ENUM_SEC_CCTL_EN;               \
    																\
    		*pREG_PINT4_LATCH    = BITM_PINT_LATCH_PIQ28;           \
    	} while (0)
        
    #		define EMAC1_PHY0_DP83848_INT    (INTR_PINT4_BLOCK)
    #		define EMAC1_PHY0_DP83848_ACK_PHY_INT    do { *pREG_PINT4_REQ = BITM_PINT_REQ_PIQ28; } while (0)
    	

    Then for core interrupt id INTR_EMAC1_STAT (number 70) SEC can be associated with peripheral interrupts only for one of the cores through

    adi_int_InstallHandler(pDev->Interrupt /*INTR_EMAC1_STAT*/, EMACInterruptHandler, (void *)pDev, true);

    and there is no way for SEC translate interrupt handling on core_0 and core_1 simultaneously?