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.

TMDX654IDKEVM: Registering 2 interfaces to the NIMU from NIMU_icssg_exampleApp

Part Number: TMDX654IDKEVM

Hi there,

The following is true for our setup:

- Code Composer studio v9.1.0.00010
- PDK for AM65XX v1.0.5
- XDC tools v3.55.02.22
- IPC v3.50.03.05
- NDK v3.60.00.13

Our application is designed to use the PRU2 interface (port 4)for one communication protocol, for example ModbusTCP, whereas some normal TCP/IP communications are developed for the CPSW port (port 6).

The question I have is probably very simple, however any help will be aprreciated. I have been able to succesfully set up and ping all PHYs individually using the NIMU_icssg_exampleApp, however, I am now trying to setup port 4 and 6 simultaneously, but I am unable to ping any port using the below method. I have tried to implement this on the NIMU_icssg_exampleapp:

- Within the testapp, I define that I will be using two ports (port 4 and 6)

#define NIMU_NUM_PORTS 2U

- I then setup both emac ports:

app_test_init_emac_k3(4, 0);
app_test_init_emac_k3(6, 1);

.....
.....
.....

void app_test_init_emac_k3(uint32_t portNum, uint32_t index)
{
    EMAC_HwAttrs_V5 emac_cfg;
    EMAC_socGetInitCfg(0, &emac_cfg);
    int32_t chanNum = 0;
    int32_t subChanNum = 0;

    /* For ICSSG SOC config is or max channel/sub-channel config, only require 1 TX/RX channel and 1 RX sub-channel/flow for NIMU ICSSG example*/
    emac_cfg.portCfg[portNum].nTxChans = 1;
    emac_cfg.portCfg[portNum].rxChannel.nsubChan = 1;

    if (portNum != NIMU_EMAC_PORT_CPSW)
    {
        
        emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.nsubChan = 1;
    }
    /* rxChannel2CfgOverPSI currently not used for dual mac and cpsw use case */
    emac_cfg.portCfg[portNum].rxChannel2CfgOverPSI.nsubChan = 0;

    for (chanNum = 0; chanNum < emac_cfg.portCfg[portNum].nTxChans; chanNum++)
    {
        emac_cfg.portCfg[portNum].txChannel[chanNum].chHandle = (void *)&gUdmaTxChObj[index][chanNum];
        emac_cfg.portCfg[portNum].txChannel[chanNum].freeRingMem= (void*)&gTxRingMem[index][chanNum][0];
        emac_cfg.portCfg[portNum].txChannel[chanNum].compRingMem= (void*)&gTxCompRingMem[index][chanNum][0];
        emac_cfg.portCfg[portNum].txChannel[chanNum].hPdMem = (void*)&gUdmapDescRamTx[index][chanNum][0];
    }
    emac_cfg.portCfg[portNum].rxChannel.chHandle = (void *)&gUdmaRxChObj[index];
    emac_cfg.portCfg[portNum].rxChannel.flowHandle= (void *)&gUdmaFlowHnd[index];

    for (subChanNum = 0; subChanNum < emac_cfg.portCfg[portNum].rxChannel.nsubChan; subChanNum++)
    {
        emac_cfg.portCfg[portNum].rxChannel.subChan[subChanNum].freeRingMem[0] = (void*)&gRxRingMem[index][subChanNum][0];
        emac_cfg.portCfg[portNum].rxChannel.subChan[subChanNum].freeRingHandle[0] = (void*)&gUdmaRxRingHnd[index][subChanNum];
        emac_cfg.portCfg[portNum].rxChannel.subChan[subChanNum].compRingMem= (void*)&gRxCompRingMem[index][subChanNum][0];
        emac_cfg.portCfg[portNum].rxChannel.subChan[subChanNum].compRingHandle= (void*)&gUdmaRxCompRingHnd[index][subChanNum];
        emac_cfg.portCfg[portNum].rxChannel.subChan[subChanNum].hPdMem[0] = (void*)&gUdmapDescRamRx[index][subChanNum][0];
        emac_cfg.portCfg[portNum].rxChannel.subChan[subChanNum].eventHandle = (void *)&gUdmaRxCqEventObj[index][subChanNum];
    }
    emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.chHandle = (void *)&gUdmaRxCfgPsiChObj[index];
    emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.flowHandle= (void *)&gUdmaFlowHndCfgPsi[index];

    for (subChanNum = 0; subChanNum < emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.nsubChan; subChanNum++)
    {
        emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.subChan[subChanNum].freeRingMem[0] = (void*)&gRxRingMemCfgPsi[index][subChanNum][0];
        emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.subChan[subChanNum].freeRingHandle[0] = (void*)&gUdmaRxRingHndCfgPsi[index][subChanNum];
        emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.subChan[subChanNum].compRingMem= (void*)&gRxCompRingMemCfgPsi[index][subChanNum][0];
        emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.subChan[subChanNum].compRingHandle= (void*)&gUdmaRxCompRingHndCfgPsi[index][subChanNum];
        emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.subChan[subChanNum].hPdMem[0] = (void*)&gUdmapDescRamRxCfgPsi[index][subChanNum][0];
        emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.subChan[subChanNum].eventHandle = (void *)&gUdmaRxCfgPsiCqEventObj[index][subChanNum];
    }

#ifdef NIMU_APP_ICSSG
    app_test_setup_fw_dualmac(portNum, &emac_cfg);
#endif

    EMAC_socSetInitCfg(0, &emac_cfg);

}

- I then register both ports to the NIMU:

nimu_device_index = 0;

NIMUDeviceTable[nimu_device_index++].init =  NimuEmacInitFxn[4];
NIMUDeviceTable[nimu_device_index++].init =  NimuEmacInitFxn[6];
NIMUDeviceTable[nimu_device_index].init =  NULL;

However, now when I try to ping any of the two ports I get no response. When I only register one port to the NIMU, I can successfully ping the registered port.

What is the issue here? Or maybe I should define another IP configuration? I have also attached the source file a .cfg file of the example below for reference:

/**
 * @file   main_am65xx.c
 *
 * @brief  NDK/NIMU example for AM65xx
 */
/*
 * Copyright (c) 2018-2019, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


#include <stdio.h>
#include <string.h>


/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/family/arm/v8a/Mmu.h>
#include <ti/sysbios/utils/Load.h>

/* CSL Header files */
#include <ti/csl/soc.h>

/* NDK headers */
#include <ti/ndk/inc/netmain.h>
#include <ti/ndk/inc/stkmain.h>

/* OSAL Header files */
#include <ti/osal/osal.h>

/* BOARD Header files */
#include <ti/board/board.h>

/* UART Header files */
#include <ti/drv/uart/UART.h>
#include <ti/drv/uart/UART_stdio.h>

/* EMAC Driver Header File. */
#include <ti/drv/emac/emac_drv.h>
#include <ti/drv/emac/src/v5/emac_drv_v5.h>
#include <ti/drv/emac/soc/emac_soc_v5.h>


#ifdef NIMU_FTP_APP
#include <ti/transport/ndk/nimu/example/ftpApp/ftpserver/ftpserver.h>
#endif

#ifdef NIMU_APP_ICSSG
#include <ti/drv/emac/firmware/icss_dualmac/config/emac_fw_config_dual_mac.h>
/* PRUSS Driver Header File. */
#include <ti/drv/pruss/soc/pruicss_v1.h>

/* TX port queue memory for 3 icss-g instances */
uint8_t icss_tx_port_queue[1][100352] __attribute__ ((aligned (UDMA_CACHELINE_ALIGNMENT))) __attribute__ ((section (".bss:nimu_msmc_mem")));
#define TX_BUFF_POOL_SIZE 0X1800u
#define TX_BUFF_POOL_TOTAL_DUAL_MAC (TX_BUFF_POOL_SIZE + 0x80) * 8U //50176 per PORT, total of 100352
#endif


#define NIMU_MAX_TABLE_ENTRIES   9U
#define NIMU_NUM_PORTS 2U
#define NIMU_TEST_MAX_SUB_RX_CHANS_PER_PORT 1U
#define NIMU_TEST_MAX_CHANS_PER_PORT 1U

/* brief Number of ring entries - we can prime this much memcpy operations */
#define NIMU_TEST_APP_RING_ENTRIES      (128U)
/* Size (in bytes) of each ring entry (Size of pointer - 64-bit) */
#define NIMU_TEST_APP_RING_ENTRY_SIZE   (sizeof(uint64_t))
 /* Total ring memory */
#define NIMU_TEST_APP_RING_MEM_SIZE     (NIMU_TEST_APP_RING_ENTRIES * \
                                          NIMU_TEST_APP_RING_ENTRY_SIZE)

/* UDMA host mode buffer descriptor memory size.    *  Make it multiple of 128 byte alignment */
#define NIMU_TEST_APP_DESC_SIZE         (sizeof(CSL_UdmapCppi5HMPD) + (128U - sizeof(CSL_UdmapCppi5HMPD)))


/* UDMA driver objects
 */
struct Udma_ChObj       gUdmaTxChObj[NIMU_NUM_PORTS][NIMU_TEST_MAX_CHANS_PER_PORT];
struct Udma_ChObj       gUdmaRxChObj[NIMU_NUM_PORTS];
struct Udma_EventObj    gUdmaRxCqEventObj[NIMU_NUM_PORTS][NIMU_TEST_MAX_SUB_RX_CHANS_PER_PORT];
struct Udma_ChObj       gUdmaRxCfgPsiChObj[NIMU_NUM_PORTS];
struct Udma_EventObj    gUdmaRxCfgPsiCqEventObj[NIMU_NUM_PORTS][NIMU_TEST_MAX_SUB_RX_CHANS_PER_PORT];

struct Udma_FlowObj gUdmaFlowHnd[NIMU_NUM_PORTS] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)));
struct Udma_RingObj gUdmaRxRingHnd[NIMU_NUM_PORTS][NIMU_TEST_MAX_SUB_RX_CHANS_PER_PORT] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)));
struct Udma_RingObj gUdmaRxCompRingHnd[NIMU_NUM_PORTS][NIMU_TEST_MAX_SUB_RX_CHANS_PER_PORT] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)));
struct Udma_RingObj gUdmaRxRingHndCfgPsi[NIMU_NUM_PORTS][NIMU_TEST_MAX_SUB_RX_CHANS_PER_PORT] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)));
struct Udma_RingObj gUdmaRxCompRingHndCfgPsi[NIMU_NUM_PORTS][NIMU_TEST_MAX_SUB_RX_CHANS_PER_PORT] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)));
struct Udma_FlowObj gUdmaFlowHndCfgPsi[NIMU_NUM_PORTS] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)));
static uint8_t gUdmapDescRamTx[NIMU_NUM_PORTS][NIMU_TEST_MAX_CHANS_PER_PORT][NIMU_TEST_APP_RING_ENTRIES * NIMU_TEST_APP_DESC_SIZE] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)))
    __attribute__ ((section (".bss:nimu_ddr_mem")));
static uint8_t gUdmapDescRamRx[NIMU_NUM_PORTS][NIMU_TEST_MAX_SUB_RX_CHANS_PER_PORT][NIMU_TEST_APP_RING_ENTRIES * NIMU_TEST_APP_DESC_SIZE] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)))
    __attribute__ ((section (".bss:nimu_ddr_mem")));
static uint8_t gUdmapDescRamRxCfgPsi[NIMU_NUM_PORTS][NIMU_TEST_MAX_SUB_RX_CHANS_PER_PORT][NIMU_TEST_APP_RING_ENTRIES * NIMU_TEST_APP_DESC_SIZE] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)))
    __attribute__ ((section (".bss:nimu_ddr_mem")));
/*
 * UDMA Memories
 */
static uint8_t gTxRingMem[NIMU_NUM_PORTS][NIMU_TEST_MAX_CHANS_PER_PORT][NIMU_TEST_APP_RING_MEM_SIZE] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)))
    __attribute__ ((section (".bss:nimu_ddr_mem")));
static uint8_t gTxCompRingMem[NIMU_NUM_PORTS][NIMU_TEST_MAX_CHANS_PER_PORT][NIMU_TEST_MAX_CHANS_PER_PORT][NIMU_TEST_APP_RING_MEM_SIZE] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)))
    __attribute__ ((section (".bss:nimu_ddr_mem")));
static uint8_t gRxRingMem[NIMU_NUM_PORTS][NIMU_TEST_MAX_SUB_RX_CHANS_PER_PORT][NIMU_TEST_APP_RING_MEM_SIZE] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)))
    __attribute__ ((section (".bss:nimu_ddr_mem")));
static uint8_t gRxCompRingMem[NIMU_NUM_PORTS][NIMU_TEST_MAX_SUB_RX_CHANS_PER_PORT][NIMU_TEST_APP_RING_MEM_SIZE] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)))
    __attribute__ ((section (".bss:nimu_ddr_mem")));
static uint8_t gRxRingMemCfgPsi[NIMU_NUM_PORTS][NIMU_TEST_MAX_SUB_RX_CHANS_PER_PORT][NIMU_TEST_APP_RING_MEM_SIZE] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)))
    __attribute__ ((section (".bss:nimu_ddr_mem")));
static uint8_t gRxCompRingMemCfgPsi[NIMU_NUM_PORTS][NIMU_TEST_MAX_SUB_RX_CHANS_PER_PORT][NIMU_TEST_APP_RING_MEM_SIZE] __attribute__ ((aligned(UDMA_CACHELINE_ALIGNMENT)))
    __attribute__ ((section (".bss:nimu_ddr_mem")));


#define NIMU_EMAC_PORT_ICSS 4U
#define NIMU_EMAC_PORT_CPSW 6U

#ifdef NIMU_APP_CPSW
uint32_t portNum = NIMU_EMAC_PORT_CPSW;
#else
/* ICSSG case */
#ifdef am65xx_idk
uint32_t portNum = NIMU_EMAC_PORT_ICSS;
#else
uint32_t portNum = NIMU_EMAC_PORT_ICSS + 4;
#endif
#endif

Task_Handle main_task;



NIMU_DEVICE_TABLE_ENTRY NIMUDeviceTable[NIMU_MAX_TABLE_ENTRIES];

void TaskFxn(UArg a0, UArg a1);

extern int32_t (*NimuEmacInitFxn[NIMU_MAX_TABLE_ENTRIES])(STKEVENT_Handle hEvent);

extern char *LocalIPAddr;

#ifdef NIMU_APP_ICSSG
void app_test_setup_fw_dualmac(uint32_t port_num, EMAC_HwAttrs_V5 *pEmacCfg)
{
    EMAC_FW_APP_CONFIG *pFwAppCfg;
    emacGetDualMacFwAppInitCfg(port_num, &pFwAppCfg);
    if ((port_num % 2) == 0)
    {
        pFwAppCfg->txPortQueueLowAddr = 0xFFFFFFFF & ((uint32_t) &icss_tx_port_queue[0][0]);
    }
    else
    {
        pFwAppCfg->txPortQueueLowAddr = 0xFFFFFFFF & ((uint32_t) &icss_tx_port_queue[0][TX_BUFF_POOL_TOTAL_DUAL_MAC]);
    }

    pFwAppCfg->txPortQueueHighAddr = 0;

    emacSetDualMacFwAppInitCfg(port_num, pFwAppCfg);

    /* Need to update the emac configuraiton with  function required by the driver to get the FW configuration to write to shared mem */
    pEmacCfg->portCfg[port_num].getFwCfg = &emacGetDualMacFwConfig;

}
#endif

/*
 *  ======== app_test_init_emac_k3========
 */
void app_test_init_emac_k3(uint32_t portNum, uint32_t index)
{
    EMAC_HwAttrs_V5 emac_cfg;
    EMAC_socGetInitCfg(0, &emac_cfg);
    int32_t chanNum = 0;
    int32_t subChanNum = 0;

    /* For ICSSG SOC config is or max channel/sub-channel config, only require 1 TX/RX channel and 1 RX sub-channel/flow for NIMU ICSSG example*/
    emac_cfg.portCfg[portNum].nTxChans = 1;
    emac_cfg.portCfg[portNum].rxChannel.nsubChan = 1;

    if (portNum != NIMU_EMAC_PORT_CPSW)
    {
        
        emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.nsubChan = 1;
    }
    /* rxChannel2CfgOverPSI currently not used for dual mac and cpsw use case */
    emac_cfg.portCfg[portNum].rxChannel2CfgOverPSI.nsubChan = 0;

    for (chanNum = 0; chanNum < emac_cfg.portCfg[portNum].nTxChans; chanNum++)
    {
        emac_cfg.portCfg[portNum].txChannel[chanNum].chHandle = (void *)&gUdmaTxChObj[index][chanNum];
        emac_cfg.portCfg[portNum].txChannel[chanNum].freeRingMem= (void*)&gTxRingMem[index][chanNum][0];
        emac_cfg.portCfg[portNum].txChannel[chanNum].compRingMem= (void*)&gTxCompRingMem[index][chanNum][0];
        emac_cfg.portCfg[portNum].txChannel[chanNum].hPdMem = (void*)&gUdmapDescRamTx[index][chanNum][0];
    }
    emac_cfg.portCfg[portNum].rxChannel.chHandle = (void *)&gUdmaRxChObj[index];
    emac_cfg.portCfg[portNum].rxChannel.flowHandle= (void *)&gUdmaFlowHnd[index];

    for (subChanNum = 0; subChanNum < emac_cfg.portCfg[portNum].rxChannel.nsubChan; subChanNum++)
    {
        emac_cfg.portCfg[portNum].rxChannel.subChan[subChanNum].freeRingMem[0] = (void*)&gRxRingMem[index][subChanNum][0];
        emac_cfg.portCfg[portNum].rxChannel.subChan[subChanNum].freeRingHandle[0] = (void*)&gUdmaRxRingHnd[index][subChanNum];
        emac_cfg.portCfg[portNum].rxChannel.subChan[subChanNum].compRingMem= (void*)&gRxCompRingMem[index][subChanNum][0];
        emac_cfg.portCfg[portNum].rxChannel.subChan[subChanNum].compRingHandle= (void*)&gUdmaRxCompRingHnd[index][subChanNum];
        emac_cfg.portCfg[portNum].rxChannel.subChan[subChanNum].hPdMem[0] = (void*)&gUdmapDescRamRx[index][subChanNum][0];
        emac_cfg.portCfg[portNum].rxChannel.subChan[subChanNum].eventHandle = (void *)&gUdmaRxCqEventObj[index][subChanNum];
    }
    emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.chHandle = (void *)&gUdmaRxCfgPsiChObj[index];
    emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.flowHandle= (void *)&gUdmaFlowHndCfgPsi[index];

    for (subChanNum = 0; subChanNum < emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.nsubChan; subChanNum++)
    {
        emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.subChan[subChanNum].freeRingMem[0] = (void*)&gRxRingMemCfgPsi[index][subChanNum][0];
        emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.subChan[subChanNum].freeRingHandle[0] = (void*)&gUdmaRxRingHndCfgPsi[index][subChanNum];
        emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.subChan[subChanNum].compRingMem= (void*)&gRxCompRingMemCfgPsi[index][subChanNum][0];
        emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.subChan[subChanNum].compRingHandle= (void*)&gUdmaRxCompRingHndCfgPsi[index][subChanNum];
        emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.subChan[subChanNum].hPdMem[0] = (void*)&gUdmapDescRamRxCfgPsi[index][subChanNum][0];
        emac_cfg.portCfg[portNum].rxChannelCfgOverPSI.subChan[subChanNum].eventHandle = (void *)&gUdmaRxCfgPsiCqEventObj[index][subChanNum];
    }

#ifdef NIMU_APP_ICSSG
    app_test_setup_fw_dualmac(portNum, &emac_cfg);
#endif

    EMAC_socSetInitCfg(0, &emac_cfg);

}

/**
 *  \name TaskFxn
 *  \brief Task Fxn
 *  \param a0
 *  \param a1
 *  \return none
 *
 */
void TaskFxn(UArg a0, UArg a1)
{
    UART_printf("\n\rSYS/BIOS Ethernet/IP () Sample application, EVM IP address I/F 1: %s\n\r", LocalIPAddr);
#ifdef NIMU_FTP_APP
    UART_printf("TaskFxn: calling ftpserver_init\n");
    ftpserver_init();
#endif
}

/**
 *  \name app_test_task_get_stats
 *  \brief get statistics
 *  \param a0
 *  \param a1
 *  \return none
 *
 */
void app_test_task_get_stats(UArg a0, UArg a1)
{

#ifdef NIMU_APP_ICSSG
    EMAC_STATISTICS_ICSSG_T icssStats;
#else
    EMAC_STATISTICS_T cpswStats;
#endif
    uint32_t pNum = (uint32_t) a0;
    while (1)
    {
#ifdef NIMU_APP_ICSSG
        memset(&icssStats, 0, sizeof(EMAC_STATISTICS_ICSSG_T));
            if ((pNum != 6) &&  (emac_get_statistics_icssg(pNum, &icssStats, FALSE) == EMAC_DRV_RESULT_OK))
            {
                UART_printf("**********ICSSG HW stats for PORT NUMBER %d**********\n", pNum);
            UART_printf("-----------------------------------------------------------------------------------------------------------------\n");
            UART_printf(" RX |     Good:      %12u | Bcast:       %12u | Mcast:     %12u | Oct:          %12u |\n",
                            icssStats.RxGoodFrames,
                            icssStats.RxBCastFrames,
                            icssStats.RxMCastFrames,
                            icssStats.RXTotalByte);
            UART_printf(" RX |     CRC :      %12u | MIIErr:      %12u | OddNibble: %12u | MaxSizeLimit: %12u |\n",
                            icssStats.RxCRCErrors,
                            icssStats.RxMIIErrors,
                            icssStats.RXOddNibbleFrame,
                            icssStats.RXMaxSizeFrame);
            UART_printf(" RX |     MaxSizeErr:%12u | MinSizeLimit:%12u | MinSizeErr:%12u | OverrunFrame :%12u |\n",
                            icssStats.RXMaxSizeErrFrame,
                            icssStats.RXMinSizeFrame,
                            icssStats.RXMinSizeErrFrame,
                            icssStats.RXoverrunFrame);
            UART_printf(" RX |     Class0:    %12u | Class1:      %12u | Class2:    %12u | Class3:       %12u |\n",
                            icssStats.RXClass0,
                            icssStats.RXClass1,
                            icssStats.RXClass2,
                            icssStats.RXClass3);
            UART_printf(" RX |     Class4:    %12u | Class5:      %12u | Class6:    %12u | Class7:       %12u |\n",
                            icssStats.RXClass4,
                            icssStats.RXClass5,
                            icssStats.RXClass6,
                            icssStats.RXClass7);
            UART_printf(" RX |     Class8:    %12u | Class9:      %12u | Class10:   %12u | Class11:      %12u |\n",
                            icssStats.RXClass8,
                            icssStats.RXClass9,
                            icssStats.RXClass10,
                            icssStats.RXClass11);
            UART_printf(" RX |     Class12:   %12u | Class13:     %12u | Class14:   %12u | Class15:      %12u |\n",
                            icssStats.RXClass12,
                            icssStats.RXClass13,
                            icssStats.RXClass14,
                            icssStats.RXClass15);
            UART_printf(" TX |     Good:      %12u | Bcast:       %12u | Mcast:     %12u | Oct           %12u |\n",
                            icssStats.TXGoodFrame,
                            icssStats.TXBCFrame,
                            icssStats.TXMCFrame,
                            icssStats.TXTotalByte);
            UART_printf(" TX |     OddNibble: %12u | UnderFlowErr:%12u | MaxSize:   %12u | MaxSizeErr:   %12u |\n",
                            icssStats.TXOddNibbleFrame,
                            icssStats.TXUnderFlowErr,
                            icssStats.TXMaxSizeFrame,
                            icssStats.TXMaxSizeErrFrame);

            UART_printf("---------------------------------------------------------------------------------------------------------------\n");
                Task_sleep(10000);
            }
#else
            memset(&cpswStats, 0, sizeof(EMAC_STATISTICS_T));
            if ((pNum == 6) &&  (emac_get_statistics(pNum, &cpswStats) == EMAC_DRV_RESULT_OK))
            {
                UART_printf("**********CPSW stats for PORT NUMBER %d**********\n", pNum);
                UART_printf("-----------------------------------------------------------------------------------------------------------------\n");
                UART_printf(" RX |     Good:      %12u | Bcast:       %12u | Mcast:     %12u | Oct:          %12u |\n",
                                cpswStats.RxGoodFrames,
                                cpswStats.RxBCastFrames,
                                cpswStats.RxMCastFrames,
                                cpswStats.RxOctets);
                UART_printf(" TX |     Good:      %12u | Bcast:       %12u | Mcast:     %12u | Oct           %12u |\n",
                                cpswStats.TxGoodFrames,
                                cpswStats.TxBCastFrames,
                                cpswStats.TxMCastFrames,
                                cpswStats.TxOctets);
                UART_printf("---------------------------------------------------------------------------------------------------------------\n");
                Task_sleep(10000);
            }
#endif
    }
}


bool app_detect_interposer_card(void)
{
#ifdef am65xx_idk
    EMAC_HwAttrs_V5 emac_cfg;
    EMAC_socGetInitCfg(0, &emac_cfg);
   CSL_MdioRegs *pBaseAddr = (CSL_MdioRegs*) emac_cfg.portCfg[2].mdioRegsBaseAddr;
    if ((CSL_MDIO_isPhyAlive(pBaseAddr,emac_cfg.portCfg[2].phyAddr)) ||(CSL_MDIO_isPhyAlive(pBaseAddr,emac_cfg.portCfg[3].phyAddr)))
    {
        UART_printf("PHYs for ICSSG1 are ALIVE, interposer card is NOT presen\n");
        return FALSE;
    }
    else
    {
        UART_printf("PHYs for ICSSG1 are NOT ALIVE, interposer card is present\n");
        return TRUE;
    }
#else
    return FALSE;
#endif
}

/*
 *  ======== main ========
 */
int main(void)
{
    uint32_t nimu_device_index = 0U;
    Task_Params taskParams;
    Board_STATUS boardInitStatus =0;
    uint32_t interposerCardPresent = 0;
    Board_initCfg cfg = BOARD_INIT_UART_STDIO | BOARD_INIT_PINMUX_CONFIG | BOARD_INIT_MODULE_CLOCK  | BOARD_INIT_ICSS_ETH_PHY | BOARD_INIT_ETH_PHY;
    boardInitStatus = Board_init(cfg);
    if (boardInitStatus !=BOARD_SOK)
    {
        UART_printf("Board_init failure\n");
        return(0);
    }
    UART_printf("Board_init success\n");

    if (portNum == NIMU_EMAC_PORT_CPSW)
    {
        app_test_init_emac_k3(portNum, nimu_device_index);
    }
    else
    {
       /* Need to query MDIO block to see if interposer card is present. If present 
        ICSSG1 PHY's will not be alive, those PHYs scorrelate to port 2 and port 3, lets check for port 2 and 3 */
        if (app_detect_interposer_card())
        {
            interposerCardPresent = 1;
        }
        app_test_init_emac_k3(portNum, nimu_device_index);
        app_test_init_emac_k3(6, 1);

    }

    /* Port 7 is "virtual port" configuration will will map to use Port 3 as tx and Port 0 as Rx */
    /* Port 8 is "virtual port" configuration will will map to use Port 1 as tx and Port 2 as Rx */
    /* with presence of interposer Card, we will use virtual port 7 in this example */
    if (interposerCardPresent ==1)
    {
        /* lets update the port number to EMAC_INTERPOSER_PORT0 */
        portNum = EMAC_INTERPOSER_PORT0;
        NIMUDeviceTable[nimu_device_index++].init = NimuEmacInitFxn[EMAC_INTERPOSER_PORT0];
    }
    else
    {
        NIMUDeviceTable[nimu_device_index++].init =  NimuEmacInitFxn[portNum];
        NIMUDeviceTable[nimu_device_index++].init =  NimuEmacInitFxn[6];
    }
    NIMUDeviceTable[nimu_device_index].init =  NULL;

    /*portNum = 6;
    app_test_init_emac_k3(portNum, nimu_device_index);
    NIMUDeviceTable[nimu_device_index++].init =  NimuEmacInitFxn[portNum];
    NIMUDeviceTable[nimu_device_index].init =  NULL;
*/
    Task_Params_init(&taskParams);
    taskParams.priority = 1;
    taskParams.stackSize = 0x1400;
    main_task = Task_create (TaskFxn, &taskParams, NULL);

    Task_Params_init(&taskParams);
    taskParams.priority = 1;
    taskParams.stackSize = 0x1400;
    taskParams.arg0 = (UArg)portNum;
    Task_create (app_test_task_get_stats, &taskParams, NULL);



    BIOS_start ();
   return 0;
}

#if defined (__aarch64__)
void InitMmu(void)
{
    bool retVal;
    uint32_t     mapIdx = 0;
    Mmu_MapAttrs attrs;

    Mmu_initMapAttrs(&attrs);

    attrs.attrIndx = 0;

    retVal = Mmu_map(0x00100000, 0x00100000, 0x00900000, &attrs); /* Main MMR0 cfg  */
    if(retVal == FALSE)
    {
        goto mmu_exit;
    }

    mapIdx++;
    retVal = Mmu_map(0x00400000, 0x00400000, 0x00001000, &attrs); /* PSC0          */
    if(retVal == FALSE)
    {
        goto mmu_exit;
    }

    mapIdx++;
    retVal = Mmu_map(0x01800000, 0x01800000, 0x00100000, &attrs); /* gicv3       */
    if (retVal == FALSE)
    {
        goto mmu_exit;
    }
    
    mapIdx++;
    retVal = Mmu_map(0x02400000, 0x02400000, 0x000c0000, &attrs); /* dmtimer     */
    if (retVal == FALSE)
    {
        goto mmu_exit;
    }
    
    mapIdx++;
    retVal = Mmu_map(0x02800000, 0x02800000, 0x00001000, &attrs); /* uart        */
    if (retVal == FALSE)
    {
        goto mmu_exit;
    }

    mapIdx++;
    retVal = Mmu_map(0x02000000, 0x02000000, 0x00100000, &attrs); /* I2C            */
    if(retVal == FALSE)
    {
        goto mmu_exit;
    }

    mapIdx++;
    retVal = Mmu_map(0x02100000, 0x02100000, 0x00080000, &attrs); /* McSPI          */
    if(retVal == FALSE)
    {
        goto mmu_exit;
    }

    mapIdx++;
    retVal = Mmu_map(0x40F00000, 0x40F00000, 0x00020000, &attrs); /* MCU MMR0 CFG   */
    if (retVal == FALSE)
    {
        goto mmu_exit;
    }

    mapIdx++;
    retVal = Mmu_map(0x40d00000, 0x40d00000, 0x00002000, &attrs); /* PLL0     CFG       */
    if(retVal == FALSE)
    {
        goto mmu_exit;
    }

    mapIdx++;
    retVal = Mmu_map(0x43000000, 0x43000000, 0x00020000, &attrs); /* WKUP     MMR0 cfg  */
    if(retVal == FALSE)
    {
        goto mmu_exit;
    }

    mapIdx++;
    retVal = Mmu_map(0x02C40000, 0x02C40000, 0x00100000, &attrs); /* pinmux     ctrl    */
    if(retVal == FALSE)
    {
        goto mmu_exit;
    }

        mapIdx++;
        retVal = Mmu_map(0x30800000, 0x30800000, 0x0C000000, &attrs); /* main  navss          */
        if(retVal == FALSE)
        {
            goto mmu_exit;
        }
        mapIdx++;
    retVal = Mmu_map(0x28380000, 0x28380000, 0x03880000, &attrs); /* mcu navss          */
    if(retVal == FALSE)
    {
        goto mmu_exit;
    }

    mapIdx++;
    retVal = Mmu_map(0x30000000ul, 0x30000000ul, 0x0F000000ul, &attrs); /* ctcontro10 */
    if (retVal == FALSE)
    {
        goto mmu_exit;
    }

    mapIdx++;
    /* for CPSW */
    retVal = Mmu_map(CSL_MCU_CPSW0_NUSS_BASE, CSL_MCU_CPSW0_NUSS_BASE, 
                                    (CSL_MCU_CPSW0_NUSS_SIZE*2), &attrs); 
    if (retVal == FALSE)
    {
        goto mmu_exit;
    }

    /* ICSS-G 0 */
    mapIdx++;
    retVal = Mmu_map(0xb000000ul, 0xb000000ul, 0x0100000ul, &attrs);
    if (retVal == FALSE)
   {
        goto mmu_exit;
   }

     /* ICSS-G 1 */
     mapIdx++;
     retVal = Mmu_map(0xb100000ul, 0xb100000ul, 0x0100000ul, &attrs);
     if (retVal == FALSE)
    {
         goto mmu_exit;
    }

     /* ICSS-G 2 */
     mapIdx++;
     retVal = Mmu_map(0xb200000ul, 0xb200000ul, 0x0100000ul, &attrs);
     if (retVal == FALSE)
    {
         goto mmu_exit;
    }

     /* PSC WKUP*/
     mapIdx++;
     retVal = Mmu_map(0x42000000ul, 0x42000000ul, 0x00001000ul, &attrs);
     if (retVal == FALSE)
    {
         goto mmu_exit;
    }

    /* NB0_CFG_MMRS */
    mapIdx++;
    retVal = Mmu_map(0x03802000, 0x03802000, 0x00001000, &attrs);
    if (retVal == FALSE)
    {
        goto mmu_exit;
    }

    attrs.attrIndx = 7;
    mapIdx++;
    retVal = Mmu_map(0x70000000, 0x70000000, 0x04000000, &attrs); /* msmc        */
   if (retVal == FALSE)
    {
        goto mmu_exit;
    }

#define DDR_TEST
#ifdef DDR_TEST
  attrs.attrIndx = 7;
  mapIdx++;
  retVal = Mmu_map(0x80000000, 0x80000000, 0x10000000, &attrs); /* ddr_0        */
 if (retVal == FALSE)
  {
      goto mmu_exit;
  }
#endif


 attrs.attrIndx = 7;
 mapIdx++;
 retVal = Mmu_map(0x41C00000, 0x41C00000, 0x00080000, &attrs); /* ocmc        */
if (retVal == FALSE)
 {
     goto mmu_exit;
 }

mmu_exit:
    if(retVal == FALSE)
    {
        UART_printf("Mmu_map idx %d returned error %d", mapIdx, retVal);
        while(1);
    }
}
#endif


void stackInitHook(void* hCfg)
{
    int             rc;

    rc = 16384; // increase stack size
   CfgAddEntry(hCfg, CFGTAG_OS, CFGITEM_OS_TASKSTKBOOT,CFG_ADDMODE_UNIQUE, sizeof(uint32_t), (uint8_t *)&rc, 0 );
}

2744.nimuExample_a53.cfg

The above main source file is programmed a bit ugly, but this is just a test.

Any advice would be greatly appreciated.

Kind regards,

Johnny

  • Hi,

    Anyone who can provide some assistance?

    How to get two interfaces registered to the NIMU at the same time?

    Regards,

    Johhny

  • Johhny,

    There have been several updates in the NIMU example for AM65xx in later PDK updates that should be easier to use. Would it be possible for you to look at the Processor SDK RTOS 6.3 release for your reference and starting point?

    Best regards,

    Dave

  • Dave,

    Thanks for your response.

    I will look into this and keep you updated on this issue.

    Kind regards,

    Johnny

  • Hi Dave,

    I have looked into the example applications in the latest PDK version, however the NIMU_icssgExample app looks pretty much exactly the same to me which is a bit frustrating. The only difference according to me is a semaphore that gets posted after the NIMUDeviceTable init functions have been initialized. The StackInitHook then pends on this semaphore.

    I also tried using the NIMU_ICSS_BasicExample_am65xx_evm_wSocLib_mpuExampleproject, however according to the Processor SDK documentation that example is not supported on the AM65x. I thus cannot ping any port when using that example. This example seems to define 2 interfaces, but it is still very unclear to me which port will be associated with which interface.

    This is now starting to cost quite some time so it would really be appreciated if you could provide more assistance. How do I get PRU2/PRU1/PRU0 and CPSW working simultaneously so that I can ping both ports?

    CPSW is intended for normal TCP/IP communications, whereas PRU2 will be used for a different protocol like Modbus TCP, and PRU1 and PRU0 will be used at a later stage in development.

    Regards,

    Johnny