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.

AM437x NDK Ethernet MAC example questions

Hi,

I use idkam437x with ccs 6.1.2, sysbios 6.45.1.29, sdk 2.1.1.2 and ndk 2.24.3.35.

By the use of ethernet_mac example from sdk packet I established two IP addresses at PHYs connected to PRU0 and PRU1 - a suitable comment is displayed at the console that Networks were added and ping test to both gives the good result. 

Now, I would like to add function that handles the data sent through ethernet connection. Based on wiki introduction I added the following definition of callback function to handle the packets of priority higher than for ICSS_EMAC_QUEUE3 value:

/*Packet processing callback*/
((((ICSS_EmacObject*)icssEmacHandle->object)->callBackHandle)->rxRTCallBack)->callBack = (ICSS_EmacCallBack)processProtocolFrames;
((((ICSS_EmacObject*)icssEmacHandle->object)->callBackHandle)->rxRTCallBack)->userArg = icssEmacHandle;

Now, the definition of processProtocolFrames() function uses the ICSS_EmacRxPktGet() function to copy the data into appropriate location. Then, some questions appear:

1. Should the above scheme be supplemented by anything? E.g. do I also need to open a socket for data transmission? I read that they are needed only for non-real time operations so the above should be sufficient for me.

2. I cannot check its operation - ping test does not trigger my processProtocolFrames() function (and I think its correct as it uses only transmission layer). Can I use one of winapps in ndk packet to do that: e.g. send, testudp etc?

3. When using ICSS_EmacRxPktGet() function I need to specify the port on which the data was sent. What if I do not know which port was used by the PC?

4. processProtocolFrames() is specified in icssEmacHandle as RTcallback function with one argument defined by userArg pointer. However, in the definiton of processProtocolFrames() in wiki, the first argument of the function is uint32_t* queue_number. Is it a general rule, that the gueue number is passed to callback functions somehow?

Thank you in advance for your help - the ethernet examples and most of the APIs are quite unclear for me.

JJ

  • I will notify the ISDK team.
  • Hi Jacek,

    1. Your scheme is sufficient to handle the data sent through ethernet connection, assume you already have the logic as described in the wiki to determine where the packets transfers to based on queue priority settings.

     if(queue_number >= ((ICSSEMAC_Object*)(icssEmacHandle->object))->emacInitcfg->ethPrioQueue) {

        /*Based on queue priority settings decide if the packet is to be sent to the TCP/IP stack*/

        /*This API is hooked to NDK*/

        icssEmacHwIntRx(&queue_number,icssEmacHandle);

      else {

        /*Protocol specific callback*/

    2. Ping ICMP packets should have been routed to NDK with icssEmacHwIntRx() as shown above. You can try to verify the processProtocolFrames() function with an external network traffic generator to generate the packets with VLAN tag that specifies the priority. When a packet is received in firmware the 3 bit PCP field of a VLAN tag is read and the packet is copied to the appropriate queue.

    3. ICSS_EmacRxPktGet() requires EMAC port number, were you referring to TCP/UDP port number?

    4. os_drivers/lld/emac/icss_emacCommon.h defines typedef int32_t (*ICSS_EmacCallBack)(void *arg, void *arg2), I am not sure which piece of code that has "RTcallback function with one argument defined by userArg pointer".


    Regards, Garrett

  • Hi Garett,

    Thanks for your answer.

    Yes, I dived into this document at first. The problem is that the application I developed does not work or I do not know how to check it.

    1. So the opening of a socket is unnecessary in my case? What is the difference in packet processing when I use a socket utilizing some udp or tcp code? It will be non-RT for sure as it is transported to stack through RxTask function - how and when the proper socket function is called to process it?

    2. Ok - I tried with a tcp/udp packet sender but it does not provide selection of vlan tag. Selection of too big ethPrioQueue level generates the interrupt all the time so I suppose the function is hooked properly...

    3. The previous software tool did not provide free port number selection. I know that a packet was received and I do not know from which PC application - is there any way of checking to which port number the latest packet was directed before calling ICSS_EmacRxPktGet() function?

    4. Sorry for ambiguity - declaration of callback function contains two function arguments - due to that it is declared in WIKI document as:

    void processProtocolFrames(uint32_t* queue_number, void* userArg)

    However, in Pruicss Emac object I am able to pass only one argument, e.g. emac handle which is the second argument in callback prototype:

    ((((ICSS_EmacObject*)emachandle1->object)->callBackHandle)->rxRTCallBack)->userArg = emachandle;

    Now, how am I supposed to pass the first argument of callback prototype (the queue number)? It is passed automatically somehow?

    Thanks in advance,

    JJ

  • Hi Jacek,

    1. For the TCP/UDP packets that are not in the categaory of 'Protocol specific callback', you will need socket APIs to process. The function icssEmacHwIntRx() in the above code snippet is hooked to NDK as the code comments. Refer to "Network Developer's Kit (NDK) Support Package Ethernet Driver Design Guide" (sprufp2a) section 1.3 for the Tx/Rx packet processing call flow and socket APIs in NDK.

    3. ICSS_EmacRxPktInfo() loops around all available Host Queues structures to check for arrival of packets, compares write pointer and read pointer of all queues and returns the Queue number where packet is present and the Physical Port number from where the packet has arrived.

    4. icssEmacHandle->object)->callBackHandle)->rxRTCallBack)->callBack=(ICSS_EmacCallBack)processProtocolFrames;

      icssEmacHandle->object)->callBackHandle)->rxRTCallBack)->userArg = icssEmacHandle;

    and queue_number is specifically passed as below:

     /*Protocol specific callback*/

        if(((((ICSS_EmacObject*)icssEmacHandle->object)->callBackHandle)->rxRTCallBack)->callBack != NULL) {

           ((((ICSS_EmacObject*)icssEmacHandle->object)->callBackHandle)->rxRTCallBack)->callBack(&queue_number,

           ((((ICSS_EmacObject*)icssEmacHandle->object)->callBackHandle)->rxRTCallBack)->userArg);

  • Hi Garett,

    Thanks for the answer. 

    I dived into the code of sdk 2.1.1.2, pdk 1.0.2 and ndk to relate all the things you wrote and now everything is much more clear however still some big mismatches occur.

    First of all, directing a packet based on the following condition:

    if(queue_number >= ((ICSSEMAC_Object*)(icssEmacHandle->object))->emacInitcfg->ethPrioQueue)

    is made both in pdk and sdk. However in sdk the function rxNRTCallBack is called instead of icssEmacHwIntRx(&queue_number,icssEmacHandle);

    I would like to achieve what is within NIMU_ICSS_BasicExample_idkAM437x_wSoCLib_armExampleproject in PDK 1.0.2: two mac instances and a few deamons exist so I can easily connect to the application by any TCP/UDP packet sender - I ping both the IPs and correctly connect to the ports defined when creating the deamons.

    My problem occurs when using the sdk 2.1.1.2 - I created two mac instances with different IPs but none of them can be pinged... I suspect it is because the difference in icss_emacDrv.h API. In pdk example the only thing to do to process the nonRT packets was the command:

    ((ICSS_EmacObject*)emachandle->object)->rxTaskHandle = Task_create(ICSS_EMacOsRxTaskFnc, &taskParams, NULL);

    When using sdk API I wrote:

    ((ICSSEMAC_Object*)emacHandle->object)->rxTaskHandle = Task_create(RxTask, &taskParams, NULL);

    In pdk this step was sufficient to initialize the NDK stack transmission through the icssEmacHwIntRx function - when using sdk 2.1.1.2 what else should I do to process the TCP packets correctly by the deamon created?

    Thank you in advance,

    JJ

  • Jacek,

    The rxTaskHandle initialization is different between PDK and SDK. If you look into SDK ICSS_EmacOSInit() which is called by ICSS_EmacInit() in os_drivers/lld/emac/icss_emacFwInit.c, you will see RxTask function has been passed to the rxTaskHandle:
    ((ICSSEMAC_Object *)icssEmacHandle->object)->rxTaskHandle = TaskOSAL_create(10, taskName, 0x1000, icssEmacHandle, RxTask);
    so you don't need the
    ((ICSSEMAC_Object*)emacHandle->object)->rxTaskHandle = Task_create(RxTask, &taskParams, NULL);
    in your application.

    In PDK, ICSS_EmacOSInit() only has rxSemaphore and txSemaphore handle initialized, then the rxTaskHandle has to be initialized externally and pass ICSS_EMacOsRxTaskFnc to it explicitly.

    You may refer to ethernet_mac example to have ICSS_EmacInit properly configured and called.
    ICSS_EmacInit(emacHandle1, &pruss_intc_initdata,
    ICSS_EMAC_MODE_MAC1 | ICSS_EMAC_MODE_DUALMAC);
    ICSS_EmacInit(emacHandle2, &pruss_intc_initdata,
    ICSS_EMAC_MODE_MAC2 | ICSS_EMAC_MODE_DUALMAC);
    Also make sure your application have OSDRV_addNetifEntry((NIMUInitFn)&EmacInit, emacHandle1) called which basically registers the HwIntRx()->EMACRxServiceCheck() to ICSS_EMAC Rx hardware interrupt callback.

    By following the initialization sequence in ethernet_mac to get ping work, then you can start to add TCP/UDP socket APIs as well your own RT processProtocolFrames...

    Regards,
    Garrett
  • Hi Garrett,

    Thanks for your answer.

    Indeed, the RxTask is passed and it seems to work without any additional configuration. In my case, this additional declaration disturbed the application based on the mac_example code. Also, I found that a proper setting of MMU memory is necessary to launch the emac example. When I fixed these issues, my emac application responds to ping test. 

    Thanks!

    JJ