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.

RTOS/AM4379: EtherCat to EtherNet gateway

Part Number: AM4379

Tool/software: TI-RTOS

Hi,

 I have successfully compile and test the EtherCat slave full exemple (option #2 if important). 

So I need to use RTOS...

Now, I need to find a starting point to integrate an EtherNet stack on the remaining Ethernet connector of the AN437x Industrial EVM to do my gateway.

 

Any help will be appreciated.

Thanks

Stéphane Germain

  • Hi Stéphane,

    Are you planing to run EtherCAT on one PRU-ICSS and EtherNet/IP on another PRU-ICSS? Or you meant traditional Ethernet from CPSW? If it's the latter, you may start from the thread - e2e.ti.com/.../2883725

    Regards,
    Garrett
  • Hi Garrett,
    I plan to run EtherCAT slave on the two PRU-ICSS and EtherNet/IP on traditional Ethernet. But I think that CPSW is Linux related?
    Cause of the EtherCat slave needs, I use TI-RTOS.

    But I also observe the the post in reference is talking about TI-RTOS.
    So perhaps if I can find the stated example code of TCP_echo_Server, it could help me!

    Thanks
    Stéphane Germain
  • Stéphane,

    EtherNet/IP from PRU-ICSS industrial SW is also PRU-ICSS rather than CPSW (traditional Ethernet) based.

    If you just need a TCP echo server, please check ndk_3_40_01_01/docs/ndk/NDK_API_Reference.html#tcpudp-server-daemon-support
    Also this thread may help - e2e.ti.com/.../763952

    Regards,
    Garrett
  • Hi Garrett,

     It's time to specify that I am brand new to the Sitara world.

    So thank you for pointing me the NDK. It helped a lot.

    But I am not sure if I understand what you where trying to say with "EtherNet/IP from PRU-ICSS industrial SW is also PRU-ICSS rather than CPSW (traditional Ethernet) based."

    But let me re-phrase me need:

    I need the 2 PRU connector for make an EtherCat slave within the sitara.

    In the same time, I need the EtherNet connector on which, I will execute, for beginning, the echo server, on the same sitara.

    After messing with include file, include directory and undefined symbole (Ex.: OS_TASKPRINORM), I finally compile something but still have some issue at link time.

    So here the remaining error that I cannot get ride of:

    C:\ti\ndk_3_40_01_01\packages\ti\ndk\stack\lib\stk6.aa9fg(nimu.oa9fg): In function `NIMUInit':

    /db/vtree/library/trees/ndk/ndk-p19/src/ti/ndk/stack/nimu/nimu.c:1197: undefined reference to `NIMUDeviceTable'

    Again, any information or indication of pertinent manual will be appreciated.

    Thanks

    Stéphane Germain

  • Hi Stéphane,

    Welcome to Sitara world! It will be fun : -)

    For undefined reference to `NIMUDeviceTable', this thread should help - e2e.ti.com/.../766404

    essentially you need add the table in your application like below:
    NIMU_DEVICE_TABLE_ENTRY NIMUDeviceTable[MAX_TABLE_ENTRIES];

    Regards,
    Garrett
  • Hi Garrett,

    Thank you, all this help a lot.
    But still not working .

    I solve all my compilation and link issue.
    But it crash as soon as I try to Start the Stack:

    #include <protocols/ethercat_slave/include/tiescutils.h>
    #include <time.h>
    #include <stkmain.h>
    #include <stack/stack.h>
    #include <socket.h>
    #include <socketndk.h>
    #include <nettools/NETTOOLS.H>
    #include <netctrl/netctrl.h>
    #include <signal.h>

    #define MAX_TABLE_ENTRIES 3
    NIMU_DEVICE_TABLE_ENTRY NIMUDeviceTable[MAX_TABLE_ENTRIES];

    int main()
    {

    int rc;
    rc = NC_SystemOpen(NC_PRIORITY_LOW, NC_OPMODE_POLLING);
    if (rc) {
        DbgPrintf(DBG_ERROR, "NC_SystemOpen Failed (%d)\n");
    }

    void *hCfg;
    /* create and build the system configuration from scratch. */
    hCfg = CfgNew();
    if (!hCfg) {
        DbgPrintf(DBG_INFO, "Unable to create configuration\n");
    }

    rc = NC_NetStart( hCfg, NetworkStart, NetworkStop, NetworkIPAddr); ///////// Crashing line

    ...

    }

    Note that in: Project Properties / GNU Linker / Libraries,  I added nettool.aa9fg


    I’ve tried to add the initialisation of the Ip from the section 2.1.4.1.2 from the User’s guide, but it didn’t help.
    Is there any example of the stack initialisation without using XGCONF ?

    Thanks
    Stéphane Germain

  • Hi Stéphane,

    You can start from the NIMU_BasicExample_idkAM437x_armExampleproject available from PDK.
    The project can be created using the pdkProjectCreate.bat script, see section 1.4.5.1.4. PDK Example and Test Project Creation, on software-dl.ti.com/.../index_overview.html

    And you can refer to the source code packages\ti\transport\ndk\nimu\example\src\main_idkAM437x.c to enable NDK.

    Regards,
    Garrett
  • Hi Garrett,

    I work with Stéphane and I'm now in charge of the development of our gateway application.

    Currently, we have 2 application that works fine, the ftp server example and the EtherCat example, but we are not able to merge the two example.

    When we integrate all the code,  we are not able to ping the Ethernet port even if every thing start without any error.

    Is there a configuration in the Ethercat example that mess with the configuration of the ethernet port ?

    I've removed idkAM437x_icssPinMuxFlag and rebuild the library as propose in this post: https://e2e.ti.com/support/processors/f/791/p/778872/2883725#2883725 But it didn't help.

    Here my main:

    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <xdc/std.h>
    #include <xdc/runtime/Error.h>
    #include <xdc/runtime/System.h>
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/family/arm/a8/Mmu.h>
    
    #include <ti/ndk/inc/stkmain.h>
    
    #include <ti/drv/emac/emac_drv.h>
    #include <ti/drv/emac/src/v4/emac_drv_v4.h>
    
    #include "RawSocketServer.h"
    
    
    #include <ti/starterware/include/types.h>
    #include <ti/starterware/include/hw/hw_types.h>
    #include <ti/starterware/include/hw/hw_control_am43xx.h>
    #include <ti/starterware/include/hw/am437x.h>
    #include <ti/starterware/include/ethernet.h>
    
    #include <ti/board/board.h>
    
    /* UART Header files */
    #include <ti/drv/uart/UART.h>
    #include <ti/drv/uart/UART_stdio.h>
    
    /* GPIO header files and defines*/
    #include <ti/drv/gpio/GPIO.h>
    #include <ti/drv/gpio/soc/GPIO_v1.h>
    
    #include <protocols/ethercat_slave/include/tiescutils.h>
    
    #include <ti/starterware/include/am43xx/chipdb_defs.h>
    
    
    
    
    #define GPIO_USER0_LED_PIN_NUM    (0x0B)
    #define GPIO_USER0_LED_PORT_NUM   (0x05)
    #define GPIO_USER1_LED_PIN_NUM    (0x0A)
    #define GPIO_USER1_LED_PORT_NUM   (0x05)
    
    
    extern char *LocalIPAddr;
    extern void app_stats(UArg arg0, UArg arg1);
    extern int32_t PINMUXModuleConfig(chipdbModuleID_t moduleId, uint32_t instNum, void *pParam1);
    /* Enable the below macro to have prints on the IO Console */
    #define IO_CONSOLE
    
    #ifndef IO_CONSOLE
    #define NIMU_log                UART_printf
    #else
    #define NIMU_log                printf
    #endif
    
    /* ========================================================================== */
    /*                             Macros                                  */
    /* ========================================================================== */
    
    
    #define MAX_TABLE_ENTRIES   3
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    
    /**Task handle for EIP*/
    Task_Handle main_task;
    
    static int nimu_device_index = 0U;
    
    
    NIMU_DEVICE_TABLE_ENTRY NIMUDeviceTable[MAX_TABLE_ENTRIES];
    
    void TaskFxn(UArg a0, UArg a1);
    extern int CpswEmacInit (STKEVENT_Handle hEvent);
    
    
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    void Osal_TaskCreate(void* pCbFn)
    {
    
        Task_Params     taskParams;
        Error_Block eb;
    
        Error_init(&eb);
    
        Task_Params_init(&taskParams);
        taskParams.priority = 10;
        taskParams.instance->name = "EmacPollPkt";
        Task_create((ti_sysbios_knl_Task_FuncPtr)pCbFn, &taskParams, &eb);
    }
    
    void CpswPortMacModeSelect(uint32_t portNum, uint32_t macMode)
    {
        uint32_t regVal = 0U;
    
        regVal = HW_RD_REG32(SOC_CONTROL_MODULE_REG + CTRL_GMII_SEL);
    
        switch(macMode)
        {
            case ETHERNET_MAC_TYPE_MII:
            case ETHERNET_MAC_TYPE_GMII:
                if(1U == portNum)
                {
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_GMII1, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RGMII1_IDMODE, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RMII1_IO_CLK_EN, 0U);
                }
                else if(2U == portNum)
                {
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_GMII2, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RGMII2_IDMODE, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RMII2_IO_CLK_EN, 0U);
                }
                else
                {
                    /* This error does not happen because of check done already */
                }
                break;
    
            case ETHERNET_MAC_TYPE_RMII: /* RMII */
                if(1U == portNum)
                {
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_GMII1, 1U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RGMII1_IDMODE, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RMII1_IO_CLK_EN, 0U);
                }
                else if(2U == portNum)
                {
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_GMII2, 1U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RGMII2_IDMODE, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RMII2_IO_CLK_EN, 0U);
                }
                else
                {
                    /* This error does not happen because of check done already */
                }
                break;
    
            case ETHERNET_MAC_TYPE_RGMII: /* RGMII */
                if(1U == portNum)
                {
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_GMII1, 2U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RGMII1_IDMODE, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RMII1_IO_CLK_EN, 0U);
                }
                else if(2U == portNum)
                {
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_GMII2, 2U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RGMII2_IDMODE, 0U);
                    HW_SET_FIELD(regVal, CTRL_GMII_SEL_RMII2_IO_CLK_EN, 0U);
                }
                else
                {
                    /* This error does not happen because of check done already */
                }
                break;
    
             default:
             break;
        }
    
        HW_WR_REG32((SOC_CONTROL_MODULE_REG + CTRL_GMII_SEL), regVal);
    }
    
    
    #define SYS_MMU_BUFFERABLE      1
    #define SYS_MMU_CACHEABLE       2
    #define SYS_MMU_SHAREABLE       4
    #define SYS_MMU_NO_EXECUTE      8
    typedef struct _sys_mmu_entry
    {
    
        void* address;
        /**< Address to be entered in MMU table. */
        unsigned int attributes;
        /**< Attributes of the memory. */
    }SYS_MMU_ENTRY;
    
    
    SYS_MMU_ENTRY applMmuEntries[] = {
        {(void*)0x30000000,SYS_MMU_CACHEABLE},  //QSPI CS0 Maddr1space - Cacheable
        {(void*)0x30100000,SYS_MMU_CACHEABLE},  //QSPI CS0 Maddr1space - Cacheable
        {(void*)0x30200000,SYS_MMU_CACHEABLE},  //QSPI CS0 Maddr1space - Cacheable
        {(void*)0x30300000,SYS_MMU_CACHEABLE},  //QSPI CS0 Maddr1space - Cacheable
        {(void*)0x40300000,0},  //OCMCRAM  - Cacheable
        {(void*)0x44D00000, SYS_MMU_BUFFERABLE},  //PRCM - Non bufferable| Non Cacheable
        {(void*)0x44E00000, SYS_MMU_BUFFERABLE},  //Clock Module, PRM, GPIO0, UART0, I2C0, - Non bufferable| Non Cacheable
        {(void*)0x47900000,SYS_MMU_BUFFERABLE},  //QSPI MMR Maddr0space
        {(void*)0x48000000, SYS_MMU_BUFFERABLE},  //UART1,UART2,I2C1,McSPI0,McASP0 CFG,McASP1 CFG,DMTIMER,GPIO1 -Non bufferable| Non Cacheable
        {(void*)0x48100000,0},  //I2C2,McSPI1,UART3,UART4,UART5, GPIO2,GPIO3,MMC1 - Non bufferable| Non Cacheable
        {(void*)0x48200000, SYS_MMU_BUFFERABLE},  //
        {(void*)0x48300000, SYS_MMU_BUFFERABLE},  //PWM - Non bufferable| Non Cacheable
        {(void*)0x49000000, SYS_MMU_BUFFERABLE},   //EDMA3CC - Non bufferable| Non Cacheable
        {(void*)0x4A000000, SYS_MMU_BUFFERABLE},  //L4 FAST CFG- Non bufferable| Non Cacheable
        {(void*)0x4A100000, SYS_MMU_BUFFERABLE},  //CPSW - Non bufferable| Non Cacheable
        {(void*)0x54400000, SYS_MMU_BUFFERABLE},  //PRU-ICSS0/1 -Bufferable| Non Cacheable | Shareable
        {(void*)0x80000000,SYS_MMU_CACHEABLE},  //QSPI CS0 Maddr1space - Non bufferable| Non Cacheable
        {(void*)0xFFFFFFFF,0xFFFFFFFF}
    };
    int SDKMMUInit(SYS_MMU_ENTRY mmuEntries[])
    {
        unsigned short itr = 0;
        Mmu_FirstLevelDescAttrs attrs;
    
        if(NULL == mmuEntries)
            return -1;
    
        Mmu_disable();
    
        Mmu_initDescAttrs(&attrs);
    
        attrs.type = Mmu_FirstLevelDesc_SECTION;
        attrs.domain = 0;
        attrs.imp = 1;
        attrs.accPerm = 3;
    
    
        for(itr = 0 ; mmuEntries[itr].address != (void*)0xFFFFFFFF ; itr++)
        {
            attrs.bufferable = ((mmuEntries[itr].attributes) & SYS_MMU_BUFFERABLE) && 1 ;
            attrs.cacheable  = ((mmuEntries[itr].attributes) & SYS_MMU_CACHEABLE) && 1;
            if (!attrs.bufferable && !attrs.cacheable)
                attrs.tex = 0; //tex is initialized to 1 and need this to force strongly ordered
            attrs.shareable  = ((mmuEntries[itr].attributes) & SYS_MMU_SHAREABLE) && 1;
            attrs.noexecute  = ((mmuEntries[itr].attributes) & SYS_MMU_NO_EXECUTE) && 1;
            Mmu_setFirstLevelDesc((Ptr)(mmuEntries[itr].address), (Ptr)(mmuEntries[itr].address) , &attrs);  // PWM
        }
        Mmu_enable();
        return 0;
    }
    
    /**
     *  \name main
     *  \brief Main Function
     *  \param none
     *  \return none
     *
     */
    int main()
    {
        /* Call board init functions */
        Board_initCfg boardCfg;
        Task_Params taskParams;
    
        SDKMMUInit(applMmuEntries);
    
        //boardCfg = BOARD_INIT_PINMUX_CONFIG | BOARD_INIT_MODULE_CLOCK | BOARD_INIT_UART_STDIO;
        //boardCfg = BOARD_INIT_PINMUX_CONFIG | BOARD_INIT_ICSS_PINMUX | BOARD_INIT_MODULE_CLOCK | BOARD_INIT_UART_STDIO;
        boardCfg = BOARD_INIT_MODULE_CLOCK | BOARD_INIT_UART_STDIO;
    
        PINMUXModuleConfig(CHIPDB_MOD_ID_CPSW, 0U, NULL);
        PINMUXModuleConfig(CHIPDB_MOD_ID_PRU_ICSS, 1U, NULL);
    
        Board_init(boardCfg);
    
    
    
        /* Chip configuration MII/RMII selection */
        CpswPortMacModeSelect(1, ETHERNET_MAC_TYPE_RGMII);
        CpswPortMacModeSelect(2, ETHERNET_MAC_TYPE_RGMII);
    
        Task_Params_init(&taskParams);
    
        taskParams.priority = OS_TASKPRINORM;
        taskParams.stackSize = 0x1400;
    
        main_task = Task_create (TaskFxn, &taskParams, NULL);
    
        NIMUDeviceTable[nimu_device_index++].init =  &CpswEmacInit ;
        NIMUDeviceTable[nimu_device_index].init =  NULL ;
    
        common_main();
    
        BIOS_start();
    
        return -1;
    }
    
    /**
     *  \name TaskFxn
     *  \brief Task which do EIP initialization
     *  \param a0
     *  \param a1
     *  \return none
     *
     */
    void TaskFxn(UArg a0, UArg a1)
    {
        NIMU_log("\n\rSYS/BIOS Ethernet/IP (CPSW) Sample application, EVM IP address: %s\n\r", LocalIPAddr);
        InitRawSocket();
    }
    

    Thanks,

    Thibault

  • Hi Garrett,

    I've found out that that everything is correctly setup, but it seems that the Ethercat task block others task. Here the loop that block the others task:

    if(u8Err == 0)
        {
            bRunApplication = TRUE;
    
            do
            {
    #ifdef PROFILE_ECAT_STACK
                {
                    uint32_t mainloop_start, mainloop_stop;
                    bsp_get_local_sys_time(&mainloop_start, 0);
    #endif
                    //MainLoop();
    #ifdef PROFILE_ECAT_STACK
                    bsp_get_local_sys_time(&mainloop_stop,  0);
    
                    if(mainloop_stop >= mainloop_start)
                    {
                        mainloop_delta = mainloop_stop - mainloop_start;
                    }
    
                    else
                    {
                        mainloop_delta = 0xFFFFFFFFF - mainloop_start + mainloop_stop;
                    }
    
                    if(mainloop_delta > mainloop_max)
                    {
                        mainloop_max = mainloop_delta;
                    }
                }
    #endif
                TaskP_yield();
            }
            while(bRunApplication == TRUE);
        }

    I need to replace the TaskP_yiel with TaskP_sleep(1) to have a working ethernet. 

    All the task we have created for the Ethernet and the Ethercat are the same as examples. 

    Is there a conflict between the priority ? Does changing TaskP_yiel  to TaskP_sleep willl affect the application ?

    Thanks,

    Thibault 

  • Thibault,

    TaskP_yield() will yield the processor when another task of the same priority is ready. Some internal NDK task may have lower priorities than the task of EtherCAT, then has no chance to run, please refer to the thread for NDK tasks priority - e2e.ti.com/.../1403614

    TaskP_sleep() will delay execution of the current task. In the case of EtherCAT application requires short cycle time, TaskP_sleep(1) might be too long (1ms).

    You may try to change the EtherCAT application from task to HWI based, see tiescbsp.h.

    /*Comment to following to enable PDI ISR and SYNC ISR in HWI context */
    #define ENABLE_PDI_TASK
    /* #define ENABLE_PDI_SWI */
    #define ENABLE_SYNC_TASK


    Regards,
    Garrett
  • Thanks Garrett,

    Everything work as expected now.

    Regards,
    Stéphane Germain