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.

AM5728: Processors forum

Part Number: AM5728


Hello,

Following application note for GOOSE forwarding ( https://www.ti.com/lit/ug/tidubo1/tidubo1.pdf ), barebone example should work and not report "taskPruss: link down" on IPU core. The example has been pulled from the git repo of tipde0074 ( https://git.ti.com/cgit/apps/tidep0074/tree/ipu1/PktProcEng.c ) with few minor changes (link status was down even before those changes).

We're using:
EDMA2_12_5

IPC3_47_1_0

BIOS6_73_0_12

PDK1_0_2

the first and most important change was in function "PRUICSS_create""PRUICSS_create" always starts from PRU0_ICSS1. Since we changed which PRU that we're using (PRU0_ICSS2 and PRU1_ICSS2), we used function from pdk1_0_12, which allows to choose what PRU core to initialize with instance number.

The other change was introduced to server.c -> Server_exec. Here we removed everything regarding IPC communication and just left icss_tx in infinite while loop with 5 second interval. 

pktProcEng.c (unchanged functions were omitted)

/*
 *    ---task to initialize PRU---
 */
Void taskPruss(void)
{
	Uint8 firmwareLoad_done = FALSE;

	System_printf("start task PRU-ICSS\n");

	uint32_t pgVersion = (VHW_RD_REG32(
				CSL_MPU_CTRL_MODULE_WKUP_CORE_REGISTERS_REGS +
				CTRL_WKUP_ID_CODE) & 0xf0000000) >> 28;
	PRUICSS_pruDisable(pruIcssHandle, ICSS_EMAC_PORT_1-1);
	PRUICSS_pruDisable(pruIcssHandle, ICSS_EMAC_PORT_2-1);

#ifdef SOC_AM572x
	if (pgVersion >= 2)
	{
	    System_printf("taskPruss: Load FW to PG2.0 AM572x\n");
		if(PRUICSS_pruWriteMemory(pruIcssHandle,PRU_ICSS_IRAM(0), 0,
					(uint32_t *) PRU0_FIRMWARE_NAME,
					sizeof(PRU0_FIRMWARE_NAME)))
		{
			if(PRUICSS_pruWriteMemory(pruIcssHandle,
						PRU_ICSS_IRAM(1), 0,
						(uint32_t *) PRU1_FIRMWARE_NAME,
						sizeof(PRU1_FIRMWARE_NAME)))
				firmwareLoad_done = TRUE;
		}
	}
	else
	{
		if(PRUICSS_pruWriteMemory(pruIcssHandle,PRU_ICSS_IRAM(0), 0,
					(uint32_t *) PRU0_FIRMWARE_V1_0_NAME,
					sizeof(PRU0_FIRMWARE_V1_0_NAME)))
		{
			if(PRUICSS_pruWriteMemory(pruIcssHandle,
					PRU_ICSS_IRAM(1), 0,
					(uint32_t *) PRU1_FIRMWARE_V1_1_NAME,
					sizeof(PRU1_FIRMWARE_V1_1_NAME)))
				firmwareLoad_done = TRUE;
		}
	}
#else
	if(PRUICSS_pruWriteMemory(pruIcssHandle,PRU_ICSS_IRAM(0) ,0,
				(uint32_t *) PRU0_FIRMWARE_NAME,
				sizeof(PRU0_FIRMWARE_NAME)))
	{
		if(PRUICSS_pruWriteMemory(pruIcssHandle,PRU_ICSS_IRAM(1) ,0,
					(uint32_t *) PRU1_FIRMWARE_NAME,
					sizeof(PRU1_FIRMWARE_NAME)))
			firmwareLoad_done = TRUE;
	}
#endif

	if( firmwareLoad_done)
	{
	    int32_t fbge = 5;
		fbge = PRUICSS_pruEnable(pruIcssHandle, ICSS_EMAC_PORT_1-1);
        System_printf("enable status 1: %d\n", fbge);
		fbge = PRUICSS_pruEnable(pruIcssHandle, ICSS_EMAC_PORT_2-1);
        System_printf("enable status 2: %d\n", fbge);
	}
    System_printf("sleeping 5 sec\n");

	Task_sleep(5000);

	while (!(((ICSS_EmacObject*)emachandle->object)->linkStatus[0] | 
			((ICSS_EmacObject*)emachandle1->object)->linkStatus[0]))
	{
	    System_printf("linkStatus 1: %d, linkstatus 2: %d\n", ((ICSS_EmacObject*)emachandle->object)->linkStatus[0], ((ICSS_EmacObject*)emachandle1->object)->linkStatus[0]);
		System_printf("taskPruss: link down\n");
		Task_sleep(1000);
    //	((ICSS_EmacObject*)emachandle->object)->linkStatus[0] = 1;
    //	((ICSS_EmacObject*)emachandle1->object)->linkStatus[0] = 1;
	}

	System_printf("link is finally up \n");

	ICSS_EmacRegisterHwIntRx(emachandle, (ICSS_EmacCallBack)testCallbackRxPacket);
	//ICSS_EmacRegisterHwIntRx(emachandle1, testCallbackRxPacket);
}

/**
 * @brief initialize PRU & ICSS_EMAC config parameters due to MMU in IPU
 *
 * @param none
 *
 * @retval none
 */
void initPruIcssEmacCfg()
{
	uint32_t i;

	/* phys. to virt translation for prussInitCfg[0], [1]*/
	for(i=0; i<sizeof(PRUICSS_HwAttrs)/2; i++)
		*((uint32_t *)prussInitCfg + i) += VIRT0;

	prussInitCfg[0].version = 0;
	prussInitCfg[1].version = 0;

	/* phys. to virt translation for ICSS_EmacBaseAddrCfgParams[0], [1]*/
	for(i=0; i<sizeof(ICSS_EmacBaseAddrCfgParams)/2; i++)
		*((uint32_t *)icss_EmacBaseAddrCfgParams + i) += VIRT0;
}

PRUICSS_Handle PRUICSS_create1(PRUICSS_Config *config ,int32_t instance);
PRUICSS_Handle PRUICSS_create1(PRUICSS_Config *config ,int32_t instance)
{
    PRUICSS_Handle handle;
    PRUICSS_V1_Object *object;
    PRUICSS_HwAttrs      const    *hwAttrs;
    uint32_t temp_addr = 0U;
    uint32_t temp_val;

    handle = (PRUICSS_Config *)&config[instance-1];
    hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
    object = (PRUICSS_V1_Object*)handle->object;
    object->instance = instance;
    // REVID register is offset by 0 in AM5728,
    // othervise you should put "CSL_ICSSCFG_REVID"
    temp_addr = (hwAttrs->prussCfgRegBase + 0/*CSL_ICSSCFG_REVID*/);
    temp_val = HWREG(temp_addr) & 0xFFFFU;
    object->pruicss_version = temp_val;
    return(&config[instance-1]);

}

/**
 * @brief PRU & ICSS_EMAC initialization
 *
 * @param none
 *
 * @retval 0: success
 *         -1: rx semaphore creation failed
 * 	   -2: rx task creation failed
 */
int pru_icss()
{

	Error_Block eb;
	Task_Params taskParams;
	SemaphoreP_Params semParams;

	Error_init(&eb);

	initPruIcssEmacCfg();

	pruIcssHandle = PRUICSS_create1((PRUICSS_Config *)pruss_config, PRUICCSS_INSTANCE_TWO);

	Task_Params_init(&taskParams);
	taskParams.priority = 15;
	taskParams.instance->name = "SwitchTask";
	Task_create((Task_FuncPtr)taskPruss, &taskParams, &eb);

	/*ETH0 initializations*/
	emachandle = (ICSS_EmacHandle)malloc(sizeof(ICSS_EmacConfig));

	ICSS_EmacInitConfig* switchEmacCfg;
	switchEmacCfg = (ICSS_EmacInitConfig*)malloc(sizeof(ICSS_EmacInitConfig));
	switchEmacCfg->phyAddr[0] = 0;
	switchEmacCfg->portMask = ICSS_EMAC_MODE_MAC1;
	switchEmacCfg->ethPrioQueue = ICSS_EMAC_QUEUE1;

	/* Crosssbar confiiguration */
	*(unsigned int*)(0x4A0027E8U + VIRT0) =(unsigned int)(0x00C400CA);
	*(unsigned int*)(0x4A0027ECU + VIRT0) =(unsigned int)(0x00CB00C5);

	switchEmacCfg->halfDuplexEnable = 1;
	switchEmacCfg->enableIntrPacing = ICSS_EMAC_ENABLE_PACING;
	switchEmacCfg->ICSS_EmacIntrPacingMode = ICSS_EMAC_INTR_PACING_MODE1;
	switchEmacCfg->pacingThreshold = 100;
	switchEmacCfg->learningEn = 0;
	SOCCtrlGetPortMacAddr(0,lclMac);
	switchEmacCfg->macId = lclMac;

	ICSSEmacDRVInit(emachandle, 2); 

	switchEmacCfg->rxIntNum = 70;
	switchEmacCfg->linkIntNum = 69;

	((ICSS_EmacObject*)emachandle->object)->pruIcssHandle = pruIcssHandle;
	((ICSS_EmacObject*)emachandle->object)->emacInitcfg = switchEmacCfg;

	/*ETH1 initializations*/
	emachandle1 = (ICSS_EmacHandle)malloc(sizeof(ICSS_EmacConfig));

	ICSS_EmacInitConfig* switchEmacCfg1;
	switchEmacCfg1 = (ICSS_EmacInitConfig*)malloc(sizeof(ICSS_EmacInitConfig));
	switchEmacCfg1->phyAddr[0] = 1;

	switchEmacCfg1->portMask = ICSS_EMAC_MODE_MAC2;
	switchEmacCfg1->ethPrioQueue = ICSS_EMAC_QUEUE3;
	switchEmacCfg1->enableIntrPacing = ICSS_EMAC_DISABLE_PACING;
	switchEmacCfg1->pacingThreshold = 100;

	switchEmacCfg1->learningEn = 0;

	SOCCtrlGetPortMacAddr(1,lclMac1);
	switchEmacCfg1->macId = lclMac1;

	ICSSEmacDRVInit(emachandle1, 2);
	switchEmacCfg1->rxIntNum = 78;
	switchEmacCfg1->linkIntNum = 75;

	((ICSS_EmacObject*)emachandle1->object)->pruIcssHandle = pruIcssHandle;
	((ICSS_EmacObject*)emachandle1->object)->emacInitcfg = switchEmacCfg1;

	PRUICSS_IntcInitData pruss_intc_initdata = PRUSS_INTC_INITDATA;
	ICSS_EmacInit(emachandle,&pruss_intc_initdata,ICSS_EMAC_MODE_MAC1);
	ICSS_EmacInit(emachandle1,&pruss_intc_initdata,ICSS_EMAC_MODE_MAC2);

	Task_Params_init(&taskParams);
	taskParams.priority = 10;
	taskParams.instance->name = (char*)"port0_rxTaskFnc";
	taskParams.stackSize = 0x1000;
	taskParams.arg0 = (UArg)emachandle;
	((ICSS_EmacObject*)emachandle->object)->rxTaskHandle = 
		Task_create(ICSS_EMacOsRxTaskFnc, &taskParams, NULL);

	if(((ICSS_EmacObject*)emachandle->object)->rxTaskHandle==NULL)
		return -2;

	Task_Params_init(&taskParams);
	taskParams.priority = 10;
	taskParams.instance->name = (char*)"port1_rxTaskFnc";
	taskParams.stackSize = 0x1000;
	taskParams.arg0 = (UArg)emachandle1;
	((ICSS_EmacObject*)emachandle1->object)->rxTaskHandle = 
		Task_create(ICSS_EMacOsRxTaskFnc, &taskParams, NULL);

	if(((ICSS_EmacObject*)emachandle1->object)->rxTaskHandle==NULL)
		return -2;

	PRUICSS_pinMuxConfig(pruIcssHandle, 0x0); 
	InterruptInit(emachandle);
	InterruptInit(emachandle1);

    EMACOpen(emachandle, 2);
//    EMACOpen(emachandle1, 2);

	EnableEMACInterrupts(emachandle);
	EnableEMACInterrupts(emachandle1);

	semParams.mode = SemaphoreP_Mode_COUNTING;
	semParams.name= "icss_rxSemaphore";
	icssRxSem =  SemaphoreP_create(0,&semParams);;
	if(icssRxSem == NULL)
		return -1;

	semParams.mode = SemaphoreP_Mode_COUNTING;
	semParams.name= "icss_rxSemaphore1";
	icssRxSem1 =  SemaphoreP_create(0,&semParams);;
	if(icssRxSem1 == NULL)
		return -1;

	System_printf("main_pruss: initialization done!\n");


	return(0);
}

/**
 * @brief Get MAC address
 *
 * @param portNum: port number
 *        pMacAddr: MAC address data pointer
 *
 * @retval none
 */
void SOCCtrlGetPortMacAddr(uint32_t portNum, uint8_t *pMacAddr)
{
	if(portNum == 0) {
		pMacAddr[5U] =  (VHW_RD_REG32(0x4A002514)
				>> 0U) & 0xFFU;
		pMacAddr[4U] =  (VHW_RD_REG32(0x4A002514)
				>> 8U) & 0xFF;
		pMacAddr[3U] =  (VHW_RD_REG32(0x4A002514)
				>> 16U) & 0xFFU;
		pMacAddr[2U] =  (VHW_RD_REG32(0x4A002518)
				>> 0U) & 0xFFU;
		pMacAddr[1U] =  (VHW_RD_REG32(0x4A002518)
				>> 8U) & 0xFFU;
		pMacAddr[0U] =  (VHW_RD_REG32(0x4A002518)
				>> 16U) & 0xFFU;
	}
	else {
		pMacAddr[5U] =  (VHW_RD_REG32(0x4A00251c)
				>> 0U) & 0xFFU;
		pMacAddr[4U] =  (VHW_RD_REG32(0x4A00251c)
				>> 8U) & 0xFF;
		pMacAddr[3U] =  (VHW_RD_REG32(0x4A00251c)
				>> 16U) & 0xFFU;
		pMacAddr[2U] =  (VHW_RD_REG32(0x4A002520)
				>> 0U) & 0xFFU;
		pMacAddr[1U] =  (VHW_RD_REG32(0x4A002520)
				>> 8U) & 0xFFU;
		pMacAddr[0U] =  (VHW_RD_REG32(0x4A002520)
				>> 16U) & 0xFFU;
	}
}

we identified a possible issue :

  • wrong MAC address retrieval: function SOCCtrlGetPortMacAddr returns different MAC address that is eth2 and eth3 interface, and is always constant. MAC addresses are randomly initialized for port1 and 2 during booting

[ 4.243312] prueth pruss2_eth: port 1: using random MAC addr: 2e:7c:13:0c:a2:db
[ 4.308953] prueth pruss2_eth: port 1: using random MAC addr: 92:5b:94:07:ac:08
[ 4.312874] prueth pruss2_eth: port 2: using random MAC addr: a6:07:29:c5:f3:12
[ 4.329570] prueth pruss2_eth: port 1: using random MAC addr: 3a:b7:41:ab:21:a6
[ 4.341593] prueth pruss2_eth: port 2: using random MAC addr: 8a:00:7d:2c:d9:76

we tried to force the randomly assigned MAC address by directly changing lclMac and lclMac1 after the SOCCtrlGetPortMacAddr finished, yet the link still wouldn't get up.

trace for IPU (added linkStatus 1: 0, linkstatus 2: 0 by myself):

[0][ 0.000] start task PRU-ICSS
[0][ 0.000] taskPruss: Load FW to PG2.0 AM572x
[0][ 5.000] linkStatus 1: 0, linkstatus 2: 0
[0][ 5.000] taskPruss: link down
[0][ 6.000] linkStatus 1: 0, linkstatus 2: 0

etc... repeats forever

Have to add: PRU are fine, since we are able to use all 3 ethernet ports (2 of which are over PRU cores) to ping both directions and connect to am5728 via SSH. that is possible only if we use this firmwares:

am57xx-pru0-prueth-fw.elf 

am57xx-pru1-prueth-fw.elf 

so it has to be something with the IPU<->PRU part