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.

AM263P4-Q1: TCP/UDP communication TMDSCNCD263PX Evaluation Board

Part Number: AM263P4-Q1

Tool/software:

Hi,

Anyone can please help in solving the below problem. While trying to establish a TCP/UDP connection we are able to form a connection but not able to receive the data. We are using the sample program from resource Explorer.

1

TCP testing: when we run the TCP client example, we are able to receive the data to server., But, in receiving data from the server, we are not able to access the receive buffer:

 

struct netbuf *rxBbuf = NULL;

 

(we could not find the structure of “netbuf”, so we are unable to access the “receive buffer data” over TCP)

2

UDP testing:

UDP data is being received at server side but unable to receive data from server.

What are the functions to be called for UDP socket Open, send/receive data and close the socket, in the same TCP client App? We need to run both UDP and TCP to send/receive data on both the sockets at a time.

 

In the code section of UDP client:

  We did not receive the data to “gRxDataBuff “ sent from server:

           ret = lwip_recvfrom(sock, gRxDataBuff, APP_SOCKET_MAX_RX_DATA_LEN, 0, pAddr, &len);

            gRxDataBuff[ret] = '\0';

           EnetAppUtils_print("Message from host: %s\r\n", gRxDataBuff);

  • Hi Srujana,

    Can you help me by answering the below questions:

    1. I assume your AM263Px device has a label mentioning PROC# E2 revision. Can you please check the state of SW-14, SW-15, SW-16 switches on the board? Expected state for proper working for this example is OFF, OFF, OFF respectively.

    2. What bootmode are you in? I would recommend having SBL Null flashed to the device and running in OSPI boot mode. This is just to ensure the peripheral clocks are initialized properly. Sometimes there can be an issue with Gel scripts leading to incorrect clock configuration and ethernet packets not being received/ sent.

    3.When you run into DHCP mode, do you get an IP address or the application gets stuck in "Waiting for network" loop.

    4. When you run the example (static or DHCP any mode), are you able to ping the EVM?

    5. Can you please check the lwip_stats in the expressions window of CCS. Halt your core after you try to initiate a communication. Then go to expressions window and type "lwip_stats" and see the different contents of the structure. If it is an issue with the CPSW, these stats should indicate a number > 0. 

    6. Can you also paste the expression "(CSL_Xge_cpswRegs ) 0x52820000" and expand this? With these stats, not only can you see the configurations of CPSW, but also the port-wise behavior, number of packets sent/received/dropped etc. Expand the P[0] array and P[N] arrays to see the count of frames sent/received.

    7. If all the above seems fine, on your Host PC check if there is a firewall blocking the packets.

    My suspicion is majorly on point-1 and point-2. Please let me know the answer to the above questions so we can look further into this.

    Regards,
    Shaunak

  • Hi,

    Please find the below response

    1.  Yes, the labelling is PROC159E2.SW14 - OFF, SW15-OFF, SW-16 OFF.

    2.  DEV BOOT MODE

    3. Yes we got IP address.

    4. DHCP enabled and EVM IP is being detected, and Ping is working.

     At Server side: data is being received.

    when we sent the message from server "This is the message from Server", the following part of code should execute and display the message in serial window:

     

    File Name: app_tcpclient.c

    Function: static void AppTcp_simpleclient(void *pArg):

    code addded:

                    if (netconn_recv(pConn, &rxBbuf) == ERR_OK)

                    {

                       

                        DebugP_log("Successfully received the packet %d\r\n", i+1);

                        //Below Line is Added by AVS

                        DebugP_log("Received Packet is: %s\r\n", rxBbuf);

                        netbuf_delete(rxBbuf);

                    }

      Why are we not getting the message ""This is the message from Server" in the "rxBbuf" though it is being received successfully. 

    We are not able to see the message after Received Packet is                   .  it is displaying empty.

  • Hi Srujana,

    • When I run the enet_cpsw_udpclient example from the SDK, I am able to see the message on Host PC sent by the AM263Px devices, and im also able to see message sent by Host to the AM263Px device.
      Have you tried running the standalone UDP client application? 
    • When you say you want to implement both TCP and UDP communications in the same project, what LwIP APIs do you want to use? Netconn APIs or Socket APIs? I see you call lwip_recvfrom() function which is Socket API function and for TCP you call netconn_recv which is NetConn API.
      I would recommend you use the same API patterns
    • Let's say you want to implement a TCP and a UDP connection using NetConn APIs, you would need two unique netconn structs to be passed to the netconn_new() function, then call the netconn_connect() API for both the connections having a unique IP address, then handle the netconn_write() or netconn_recv properly. Refer the examples "enet_cpsw_tcpclient" for code flow and API calls.

    • There are some Netconn APIs specifically meant to be used for TCP and for UDP. please refer: www.nongnu.org/.../group__netconn.html

    Regards,
    Shaunak

  • Hi,

    I have a question related to MCAN can you please help.

              I am currently working with the AM263Px Control Card using the CCS Theia environment and MCU+ SDK version 10.0.0.35 with example file of mcan_external_read_write. I can be able to transmit data bytes with extended CAN IDs with mcan_external_read_write example for MCU + SDK 10.0.0.35 from AM263Px Control Card. But while recieving data bytes code is getting stuck at vApplicationIdleHook function.

    Attached my code for your reference

    /* This example demonstrates the CAN message communication to external CAN
     * controller in with the following configuration.
     * CAN FD Message Format.
     * Message ID Type is Standard, Msg Id 0xC0.
     * MCAN is configured in Interrupt Mode.
     * MCAN Interrupt Line Number 0.
     * Arbitration Bit Rate 1Mbps.
     * Data Bit Rate 5Mbps.
     * Buffer mode is used for Tx and RX to store message in message RAM.
     * Instance MCAN1 is set as a Commander in Transmit Mode. Message is transmitted and received
     * back from external CAN controller. Once message is transmitted the example will wait for
     * recieving the messages from external PC. Have to manually transmit ten messages from external
     * PC for test to finish. When the received message id and the data matches with the transmitted
     * one, then the example is completed.
     */

    #include <stdio.h>
    #include <kernel/dpl/DebugP.h>
    #include <kernel/dpl/AddrTranslateP.h>
    #include <kernel/dpl/SemaphoreP.h>
    #include <drivers/mcan.h>
    #include "drivers/mcan/v0/mcan.h"
    #include "ti_drivers_config.h"
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"

    #define APP_MCAN_BASE_ADDR                       (CONFIG_MCAN0_BASE_ADDR)
    #define APP_MCAN_INTR_NUM                        (CONFIG_MCAN0_INTR)
    #define APP_MCAN_MSG_LOOP_COUNT                  (1U)
    #define APP_MCAN_LOOPBACK_MODE_DISABLE           (FALSE)

    /* Allocate Message RAM memory section to filter elements, buffers, FIFO */
    /* Maximum STD Filter Element can be configured is 128 */
    #define APP_MCAN_STD_ID_FILTER_CNT               (0U)
    /* Maximum EXT Filter Element can be configured is 64 */
    #define APP_MCAN_EXT_ID_FILTER_CNT               (1U)
    /* Maximum TX Buffer + TX FIFO, combined can be configured is 32 */
    #define APP_MCAN_TX_BUFF_CNT                     (0U)
    #define APP_MCAN_TX_FIFO_CNT                     (1U)
    /* Maximum TX Event FIFO can be configured is 32 */
    #define APP_MCAN_TX_EVENT_FIFO_CNT               (0U)
    /* Maximum RX FIFO 0 can be configured is 64 */
    #define APP_MCAN_FIFO_0_CNT                      (1U)
    /* Maximum RX FIFO 1 can be configured is 64 and
     * rest of the memory is allocated to RX buffer which is again of max size 64 */
    #define APP_MCAN_FIFO_1_CNT                      (0U)

    /* Standard Id configured in this app */
    //#define APP_MCAN_STD_ID                          (0xC0U)
    //#define APP_MCAN_STD_ID_MASK                     (0x7FFU)
    //#define APP_MCAN_STD_ID_SHIFT                    (18U)

    #define APP_MCAN_EXT_ID                          (0x1230U)
    #define APP_MCAN_EXT_ID_MASK                     (0x1FFFFFFFU)
    //#define APP_MCAN_EXT_ID_SHIFT                    (0U)

    #define APP_MCAN_CLASSIC_BIT_MASK                (0xFFFFFFFFU)
    /* In the CAN FD format, the Data length coding differs from the standard CAN.
     * In case of standard CAN it is 8 bytes */
    static const uint8_t gMcanDataSize[16U] = {0U,  1U,  2U,  3U, 4U,  5U,  6U, 7U, 8U,
                                               12U, 16U, 20U, 24U, 32U, 48U, 64U};

    /* Semaphore to indicate transfer completion */
    static SemaphoreP_Object gMcanTxDoneSem, gMcanRxDoneSem;
    static HwiP_Object       gMcanHwiObject;
    static uint32_t          gMcanBaseAddr;

    /* Static Function Declarations */
    static void    App_mcanIntrISR(void *arg);
    static void    App_mcanConfig(Bool enableInternalLpbk);
    static void    App_mcanInitMsgRamConfigParams(
                   MCAN_MsgRAMConfigParams *msgRAMConfigParams);
    static void    App_mcanEnableIntr(void);
    static void    App_mcanConfigTxMsg(MCAN_TxBufElement *txMsg);
    static void    App_mcanCompareMsg(MCAN_TxBufElement *txMsg,
                                      MCAN_RxBufElement *rxMsg);

    static void    App_mcanInitExtFilterElemParams(MCAN_ExtMsgIDFilterElement *extFiltElem,
                                      uint32_t bufNum);

    void mcanEnableTransceiver(void);

    void mcan_external_read_write_main(void *args)
    {
        int32_t                 status = SystemP_SUCCESS;
        HwiP_Params             hwiPrms;
        MCAN_TxBufElement       txMsg;
        MCAN_ProtocolStatus     protStatus;
        MCAN_RxBufElement       rxMsg;
        MCAN_RxNewDataStatus    newDataStatus;
        MCAN_ErrCntStatus       errCounter;
        uint32_t                i, bufNum, fifoNum, bitPos = 0U;

        /* Open drivers to open the UART driver for console */
        Drivers_open();
        Board_driversOpen();

        mcanEnableTransceiver();

        DebugP_log("[MCAN] External read - write test, application started ...\r\n");

        /* Construct Tx/Rx Semaphore objects */
        status = SemaphoreP_constructBinary(&gMcanTxDoneSem, 0);
        DebugP_assert(SystemP_SUCCESS == status);
        status = SemaphoreP_constructBinary(&gMcanRxDoneSem, 0);
        DebugP_assert(SystemP_SUCCESS == status);

        /* Register interrupt */
        HwiP_Params_init(&hwiPrms);
        hwiPrms.intNum      = APP_MCAN_INTR_NUM;
        hwiPrms.callback    = &App_mcanIntrISR;
        status              = HwiP_construct(&gMcanHwiObject, &hwiPrms);
        DebugP_assert(status == SystemP_SUCCESS);

        /* Assign MCAN instance address */
        gMcanBaseAddr = (uint32_t) AddrTranslateP_getLocalAddr(APP_MCAN_BASE_ADDR);

        /* Configure MCAN module, Enable External LoopBack Mode */
        App_mcanConfig(APP_MCAN_LOOPBACK_MODE_DISABLE);

        /* Enable Interrupts */
        App_mcanEnableIntr();

        DebugP_log("After transmitting the messages, it will wait to recieve message for test to pass ...\r\n");

        /* Transmit And Receive Message */
        for (i = 0U; i < APP_MCAN_MSG_LOOP_COUNT; i++)
        {
            /* Configure Tx Msg to transmit */
            App_mcanConfigTxMsg(&txMsg);

            /* Select buffer number, 32 buffers available */
            bufNum = 0U;
            /* Enable Transmission interrupt for the selected buf num,
             * If FIFO is used, then need to send FIFO start index until FIFO count */
            status = MCAN_txBufTransIntrEnable(gMcanBaseAddr, bufNum, (uint32_t)TRUE);
            DebugP_assert(status == CSL_PASS);

            /* Write message to Msg RAM */
            MCAN_writeMsgRam(gMcanBaseAddr, MCAN_MEM_TYPE_BUF, bufNum, &txMsg);

            /* Add request for transmission, This function will trigger transmission */
            status = MCAN_txBufAddReq(gMcanBaseAddr, bufNum);
            DebugP_assert(status == CSL_PASS);

            /* Wait for Tx completion */
            SemaphoreP_pend(&gMcanTxDoneSem, SystemP_WAIT_FOREVER);

            MCAN_getProtocolStatus(gMcanBaseAddr, &protStatus);
            /* Checking for Tx Errors */
            if (((MCAN_ERR_CODE_NO_ERROR != protStatus.lastErrCode) ||
                 (MCAN_ERR_CODE_NO_CHANGE != protStatus.lastErrCode)) &&
                ((MCAN_ERR_CODE_NO_ERROR != protStatus.dlec) ||
                 (MCAN_ERR_CODE_NO_CHANGE != protStatus.dlec)) &&
                (0U != protStatus.pxe))
            {
                 DebugP_assert(FALSE);
            }

            /* Wait for Rx completion */
            SemaphoreP_pend(&gMcanRxDoneSem, SystemP_WAIT_FOREVER);

            /* Checking for Rx Errors */
            MCAN_getErrCounters(gMcanBaseAddr, &errCounter);
            DebugP_assert((0U == errCounter.recErrCnt) &&
                          (0U == errCounter.canErrLogCnt));

            /* Get the new data staus, indicates buffer num which received message */
            MCAN_getNewDataStatus(gMcanBaseAddr, &newDataStatus);
            MCAN_clearNewDataStatus(gMcanBaseAddr, &newDataStatus);

            /* Select buffer and fifo number, Buffer is used in this app */
            bufNum = 0U;
            fifoNum = MCAN_RX_FIFO_NUM_0;

            bitPos = (1U << bufNum);
            if (bitPos == (newDataStatus.statusLow & bitPos))
            {
                MCAN_readMsgRam(gMcanBaseAddr, MCAN_MEM_TYPE_BUF, bufNum, fifoNum, &rxMsg);
            }
            else
            {
                DebugP_assert(FALSE);
            }

            /* Compare Tx/Rx data */
            App_mcanCompareMsg(&txMsg, &rxMsg);
        }
        /* De-Construct Tx/Rx Semaphore objects */
        HwiP_destruct(&gMcanHwiObject);
        SemaphoreP_destruct(&gMcanTxDoneSem);
        SemaphoreP_destruct(&gMcanRxDoneSem);
        MCAN_reset(gMcanBaseAddr);

        DebugP_log("All tests have passed!!\r\n");

        Board_driversClose();
        Drivers_close();

        return;
    }

    static void App_mcanConfig(Bool enableInternalLpbk)
    {

        MCAN_ExtMsgIDFilterElement extFiltElem[APP_MCAN_EXT_ID_FILTER_CNT] = {0U};
        MCAN_InitParams            initParams = {0U};
        MCAN_ConfigParams          configParams = {0U};
        MCAN_MsgRAMConfigParams    msgRAMConfigParams = {0U};
        MCAN_BitTimingParams       bitTimes = {0U};
        uint32_t                   i;

        /* Initialize MCAN module initParams */
        MCAN_initOperModeParams(&initParams);
        /* CAN FD Mode and Bit Rate Switch Enabled */
        initParams.fdMode          = FALSE;
        initParams.brsEnable       = FALSE;

        /* Initialize MCAN module Global Filter Params */
        MCAN_initGlobalFilterConfigParams(&configParams);

        /* Initialize MCAN module Bit Time Params */
        /* Configuring default 1Mbps and 5Mbps as nominal and data bit-rate resp */
        MCAN_initSetBitTimeParams(&bitTimes);

        /* Initialize MCAN module Message Ram Params */
        App_mcanInitMsgRamConfigParams(&msgRAMConfigParams);

        /* Initialize Filter element to receive msg, should be same as tx msg id */

        for (i = 0U; i < APP_MCAN_EXT_ID_FILTER_CNT; i++)
        {
            App_mcanInitExtFilterElemParams(&extFiltElem[i], i);
        }
        /* wait for memory initialization to happen */
        while (FALSE == MCAN_isMemInitDone(gMcanBaseAddr))
        {}

        /* Put MCAN in SW initialization mode */
        MCAN_setOpMode(gMcanBaseAddr, MCAN_OPERATION_MODE_SW_INIT);
        while (MCAN_OPERATION_MODE_SW_INIT != MCAN_getOpMode(gMcanBaseAddr))
        {}

        /* Initialize MCAN module */
        MCAN_init(gMcanBaseAddr, &initParams);
        /* Configure MCAN module Gloabal Filter */
        MCAN_config(gMcanBaseAddr, &configParams);
        /* Configure Bit timings */
        MCAN_setBitTime(gMcanBaseAddr, &bitTimes);
        /* Configure Message RAM Sections */
        MCAN_msgRAMConfig(gMcanBaseAddr, &msgRAMConfigParams);
        /* Set Extended ID Mask */
        MCAN_setExtIDAndMask(gMcanBaseAddr, APP_MCAN_EXT_ID_MASK);


        
        for (i = 0U; i < APP_MCAN_EXT_ID_FILTER_CNT; i++)
        {
            MCAN_addExtMsgIDFilter(gMcanBaseAddr, i, &extFiltElem[i]);
        }
        if (TRUE == enableInternalLpbk)
        {
            MCAN_lpbkModeEnable(gMcanBaseAddr, MCAN_LPBK_MODE_INTERNAL, TRUE);
        }

        /* Take MCAN out of the SW initialization mode */
        MCAN_setOpMode(gMcanBaseAddr, MCAN_OPERATION_MODE_NORMAL);
        while (MCAN_OPERATION_MODE_NORMAL != MCAN_getOpMode(gMcanBaseAddr))
        {}

        return;
    }

    static void App_mcanConfigTxMsg(MCAN_TxBufElement *txMsg)
    {
        uint32_t i;

        /* Initialize message to transmit */
        MCAN_initTxBufElement(txMsg);
        /* Standard message identifier 11 bit, stored into ID[28-18] */
        txMsg->id  = ((APP_MCAN_EXT_ID) & MCAN_EXT_ID_MASK);
        txMsg->dlc = MCAN_DATA_SIZE_8BYTES; /* Payload size is 64 bytes */
        txMsg->fdf = FALSE; /* CAN FD Frame Format */
        txMsg->xtd = TRUE; /* Extended id not configured */
        for (i = 0U; i < gMcanDataSize[MCAN_DATA_SIZE_8BYTES]; i++)
        {
            txMsg->data[i] = i;
        }

        return;
    }


    static void App_mcanInitExtFilterElemParams(MCAN_ExtMsgIDFilterElement *extFiltElem,
                                                uint32_t bufNum)
    {
        /* sfid1 defines the ID of the standard message to be stored. */
        extFiltElem->efid1 = APP_MCAN_EXT_ID + bufNum;
        /* As buffer mode is selected, sfid2 should be bufNum[0 - 63] */
        extFiltElem->efid2 = APP_MCAN_CLASSIC_BIT_MASK;
        /* Store message in buffer */
        extFiltElem->efec  = MCAN_EXT_FILT_ELEM_FIFO0;
        /* Below configuration is ignored if message is stored in buffer */
        extFiltElem->eft   = MCAN_EXT_FILT_TYPE_CLASSIC;

        return;
    }

    static void App_mcanEnableIntr(void)
    {
        MCAN_enableIntr(gMcanBaseAddr, MCAN_INTR_MASK_ALL, (uint32_t)TRUE);
        MCAN_enableIntr(gMcanBaseAddr, MCAN_INTR_SRC_RES_ADDR_ACCESS, (uint32_t)FALSE);
        /* Select Interrupt Line 0 */
        MCAN_selectIntrLine(gMcanBaseAddr, MCAN_INTR_MASK_ALL, MCAN_INTR_LINE_NUM_0);
        /* Enable Interrupt Line */
        MCAN_enableIntrLine(gMcanBaseAddr, MCAN_INTR_LINE_NUM_0, (uint32_t)TRUE);

        return;
    }

    static void App_mcanInitMsgRamConfigParams(MCAN_MsgRAMConfigParams
                                               *msgRAMConfigParams)
    {
        int32_t status;

        MCAN_initMsgRamConfigParams(msgRAMConfigParams);

        /* Configure the user required msg ram params */
        msgRAMConfigParams->lss = APP_MCAN_STD_ID_FILTER_CNT;
        msgRAMConfigParams->lse = APP_MCAN_EXT_ID_FILTER_CNT;
        msgRAMConfigParams->txBufCnt = APP_MCAN_TX_BUFF_CNT;
        msgRAMConfigParams->txFIFOCnt = APP_MCAN_TX_FIFO_CNT;
        /* Buffer/FIFO mode is selected */
        msgRAMConfigParams->txBufMode = MCAN_TX_MEM_TYPE_BUF;
        msgRAMConfigParams->txEventFIFOCnt = APP_MCAN_TX_EVENT_FIFO_CNT;
        msgRAMConfigParams->rxFIFO0Cnt = APP_MCAN_FIFO_0_CNT;
        msgRAMConfigParams->rxFIFO1Cnt = APP_MCAN_FIFO_1_CNT;
        /* FIFO blocking mode is selected */
        msgRAMConfigParams->rxFIFO0OpMode = MCAN_RX_FIFO_OPERATION_MODE_BLOCKING;
        msgRAMConfigParams->rxFIFO1OpMode = MCAN_RX_FIFO_OPERATION_MODE_BLOCKING;

        status = MCAN_calcMsgRamParamsStartAddr(msgRAMConfigParams);
        DebugP_assert(status == CSL_PASS);

        return;
    }

    static void App_mcanCompareMsg(MCAN_TxBufElement *txMsg,
                                   MCAN_RxBufElement *rxMsg)
    {
        uint32_t i;


        //if (((txMsg->id >> APP_MCAN_EXT_ID_SHIFT) & APP_MCAN_EXT_ID_MASK) ==
               // ((rxMsg->id >> APP_MCAN_EXT_ID_SHIFT) & APP_MCAN_EXT_ID_MASK))
        if ((txMsg->id & APP_MCAN_EXT_ID_MASK) ==
                (rxMsg->id  & APP_MCAN_EXT_ID_MASK))
        {
            for (i = 0U; i < gMcanDataSize[MCAN_DATA_SIZE_8BYTES]; i++)
            {
                if (txMsg->data[i] != rxMsg->data[i])
                {
                    DebugP_logError("Data mismatch !!!\r\n");
                    DebugP_assert(FALSE);
                }
            }
        }
        else
        {
            DebugP_logError("Message ID mismatch !!!\r\n");
            DebugP_assert(FALSE);
        }

        return;
    }

    static void App_mcanIntrISR(void *arg)
    {
        uint32_t intrStatus;

        intrStatus = MCAN_getIntrStatus(gMcanBaseAddr);
        MCAN_clearIntrStatus(gMcanBaseAddr, intrStatus);

        if (MCAN_INTR_SRC_TRANS_COMPLETE ==
            (intrStatus & MCAN_INTR_SRC_TRANS_COMPLETE))
        {
            SemaphoreP_post(&gMcanTxDoneSem);
        }

        /* If FIFO0/FIFO1 is used, then MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG macro
         * needs to be replaced by MCAN_INTR_SRC_RX_FIFO0_NEW_MSG/
         * MCAN_INTR_SRC_RX_FIFO1_NEW_MSG respectively */
        if (MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG ==
            (intrStatus & MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG))
        {
            SemaphoreP_post(&gMcanRxDoneSem);
        }

        return;
    }

    /*
     *  Copyright (C) 2023 Texas Instruments Incorporated
     *
     *  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.
     */
    
    /* This example demonstrates the CAN message communication to external CAN
     * controller in with the following configuration.
     * CAN FD Message Format.
     * Message ID Type is Standard, Msg Id 0xC0.
     * MCAN is configured in Interrupt Mode.
     * MCAN Interrupt Line Number 0.
     * Arbitration Bit Rate 1Mbps.
     * Data Bit Rate 5Mbps.
     * Buffer mode is used for Tx and RX to store message in message RAM.
     * Instance MCAN1 is set as a Commander in Transmit Mode. Message is transmitted and received
     * back from external CAN controller. Once message is transmitted the example will wait for
     * recieving the messages from external PC. Have to manually transmit ten messages from external
     * PC for test to finish. When the received message id and the data matches with the transmitted
     * one, then the example is completed.
     */
    
    #include <stdio.h>
    #include <kernel/dpl/DebugP.h>
    #include <kernel/dpl/AddrTranslateP.h>
    #include <kernel/dpl/SemaphoreP.h>
    #include <drivers/mcan.h>
    #include "drivers/mcan/v0/mcan.h"
    #include "ti_drivers_config.h"
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"
    
    #define APP_MCAN_BASE_ADDR                       (CONFIG_MCAN0_BASE_ADDR)
    #define APP_MCAN_INTR_NUM                        (CONFIG_MCAN0_INTR)
    #define APP_MCAN_MSG_LOOP_COUNT                  (1U)
    #define APP_MCAN_LOOPBACK_MODE_DISABLE           (FALSE)
    
    /* Allocate Message RAM memory section to filter elements, buffers, FIFO */
    /* Maximum STD Filter Element can be configured is 128 */
    #define APP_MCAN_STD_ID_FILTER_CNT               (0U)
    /* Maximum EXT Filter Element can be configured is 64 */
    #define APP_MCAN_EXT_ID_FILTER_CNT               (1U)
    /* Maximum TX Buffer + TX FIFO, combined can be configured is 32 */
    #define APP_MCAN_TX_BUFF_CNT                     (0U)
    #define APP_MCAN_TX_FIFO_CNT                     (1U)
    /* Maximum TX Event FIFO can be configured is 32 */
    #define APP_MCAN_TX_EVENT_FIFO_CNT               (0U)
    /* Maximum RX FIFO 0 can be configured is 64 */
    #define APP_MCAN_FIFO_0_CNT                      (1U)
    /* Maximum RX FIFO 1 can be configured is 64 and
     * rest of the memory is allocated to RX buffer which is again of max size 64 */
    #define APP_MCAN_FIFO_1_CNT                      (0U)
    
    /* Standard Id configured in this app */
    //#define APP_MCAN_STD_ID                          (0xC0U)
    //#define APP_MCAN_STD_ID_MASK                     (0x7FFU)
    //#define APP_MCAN_STD_ID_SHIFT                    (18U)
    
    #define APP_MCAN_EXT_ID                          (0x1230U)
    #define APP_MCAN_EXT_ID_MASK                     (0x1FFFFFFFU)
    //#define APP_MCAN_EXT_ID_SHIFT                    (0U)
    
    #define APP_MCAN_CLASSIC_BIT_MASK                (0xFFFFFFFFU)
    /* In the CAN FD format, the Data length coding differs from the standard CAN.
     * In case of standard CAN it is 8 bytes */
    static const uint8_t gMcanDataSize[16U] = {0U,  1U,  2U,  3U, 4U,  5U,  6U, 7U, 8U,
                                               12U, 16U, 20U, 24U, 32U, 48U, 64U};
    
    /* Semaphore to indicate transfer completion */
    static SemaphoreP_Object gMcanTxDoneSem, gMcanRxDoneSem;
    static HwiP_Object       gMcanHwiObject;
    static uint32_t          gMcanBaseAddr;
    
    /* Static Function Declarations */
    static void    App_mcanIntrISR(void *arg);
    static void    App_mcanConfig(Bool enableInternalLpbk);
    static void    App_mcanInitMsgRamConfigParams(
                   MCAN_MsgRAMConfigParams *msgRAMConfigParams);
    static void    App_mcanEnableIntr(void);
    static void    App_mcanConfigTxMsg(MCAN_TxBufElement *txMsg);
    static void    App_mcanCompareMsg(MCAN_TxBufElement *txMsg,
                                      MCAN_RxBufElement *rxMsg);
    
    static void    App_mcanInitExtFilterElemParams(MCAN_ExtMsgIDFilterElement *extFiltElem,
                                      uint32_t bufNum);
    
    void mcanEnableTransceiver(void);
    
    void mcan_external_read_write_main(void *args)
    {
        int32_t                 status = SystemP_SUCCESS;
        HwiP_Params             hwiPrms;
        MCAN_TxBufElement       txMsg;
        MCAN_ProtocolStatus     protStatus;
        MCAN_RxBufElement       rxMsg;
        MCAN_RxNewDataStatus    newDataStatus;
        MCAN_ErrCntStatus       errCounter;
        uint32_t                i, bufNum, fifoNum, bitPos = 0U;
    
        /* Open drivers to open the UART driver for console */
        Drivers_open();
        Board_driversOpen();
    
        mcanEnableTransceiver();
    
        DebugP_log("[MCAN] External read - write test, application started ...\r\n");
    
        /* Construct Tx/Rx Semaphore objects */
        status = SemaphoreP_constructBinary(&gMcanTxDoneSem, 0);
        DebugP_assert(SystemP_SUCCESS == status);
        status = SemaphoreP_constructBinary(&gMcanRxDoneSem, 0);
        DebugP_assert(SystemP_SUCCESS == status);
    
        /* Register interrupt */
        HwiP_Params_init(&hwiPrms);
        hwiPrms.intNum      = APP_MCAN_INTR_NUM;
        hwiPrms.callback    = &App_mcanIntrISR;
        status              = HwiP_construct(&gMcanHwiObject, &hwiPrms);
        DebugP_assert(status == SystemP_SUCCESS);
    
        /* Assign MCAN instance address */
        gMcanBaseAddr = (uint32_t) AddrTranslateP_getLocalAddr(APP_MCAN_BASE_ADDR);
    
        /* Configure MCAN module, Enable External LoopBack Mode */
        App_mcanConfig(APP_MCAN_LOOPBACK_MODE_DISABLE);
    
        /* Enable Interrupts */
        App_mcanEnableIntr();
    
        DebugP_log("After transmitting the messages, it will wait to recieve message for test to pass ...\r\n");
    
        /* Transmit And Receive Message */
        for (i = 0U; i < APP_MCAN_MSG_LOOP_COUNT; i++)
        {
            /* Configure Tx Msg to transmit */
            App_mcanConfigTxMsg(&txMsg);
    
            /* Select buffer number, 32 buffers available */
            bufNum = 0U;
            /* Enable Transmission interrupt for the selected buf num,
             * If FIFO is used, then need to send FIFO start index until FIFO count */
            status = MCAN_txBufTransIntrEnable(gMcanBaseAddr, bufNum, (uint32_t)TRUE);
            DebugP_assert(status == CSL_PASS);
    
            /* Write message to Msg RAM */
            MCAN_writeMsgRam(gMcanBaseAddr, MCAN_MEM_TYPE_BUF, bufNum, &txMsg);
    
            /* Add request for transmission, This function will trigger transmission */
            status = MCAN_txBufAddReq(gMcanBaseAddr, bufNum);
            DebugP_assert(status == CSL_PASS);
    
            /* Wait for Tx completion */
            SemaphoreP_pend(&gMcanTxDoneSem, SystemP_WAIT_FOREVER);
    
            MCAN_getProtocolStatus(gMcanBaseAddr, &protStatus);
            /* Checking for Tx Errors */
            if (((MCAN_ERR_CODE_NO_ERROR != protStatus.lastErrCode) ||
                 (MCAN_ERR_CODE_NO_CHANGE != protStatus.lastErrCode)) &&
                ((MCAN_ERR_CODE_NO_ERROR != protStatus.dlec) ||
                 (MCAN_ERR_CODE_NO_CHANGE != protStatus.dlec)) &&
                (0U != protStatus.pxe))
            {
                 DebugP_assert(FALSE);
            }
    
            /* Wait for Rx completion */
            SemaphoreP_pend(&gMcanRxDoneSem, SystemP_WAIT_FOREVER);
    
            /* Checking for Rx Errors */
            MCAN_getErrCounters(gMcanBaseAddr, &errCounter);
            DebugP_assert((0U == errCounter.recErrCnt) &&
                          (0U == errCounter.canErrLogCnt));
    
            /* Get the new data staus, indicates buffer num which received message */
            MCAN_getNewDataStatus(gMcanBaseAddr, &newDataStatus);
            MCAN_clearNewDataStatus(gMcanBaseAddr, &newDataStatus);
    
            /* Select buffer and fifo number, Buffer is used in this app */
            bufNum = 0U;
            fifoNum = MCAN_RX_FIFO_NUM_0;
    
            bitPos = (1U << bufNum);
            if (bitPos == (newDataStatus.statusLow & bitPos))
            {
                MCAN_readMsgRam(gMcanBaseAddr, MCAN_MEM_TYPE_BUF, bufNum, fifoNum, &rxMsg);
            }
            else
            {
                DebugP_assert(FALSE);
            }
    
            /* Compare Tx/Rx data */
            App_mcanCompareMsg(&txMsg, &rxMsg);
        }
        /* De-Construct Tx/Rx Semaphore objects */
        HwiP_destruct(&gMcanHwiObject);
        SemaphoreP_destruct(&gMcanTxDoneSem);
        SemaphoreP_destruct(&gMcanRxDoneSem);
        MCAN_reset(gMcanBaseAddr);
    
        DebugP_log("All tests have passed!!\r\n");
    
        Board_driversClose();
        Drivers_close();
    
        return;
    }
    
    static void App_mcanConfig(Bool enableInternalLpbk)
    {
    
        MCAN_ExtMsgIDFilterElement extFiltElem[APP_MCAN_EXT_ID_FILTER_CNT] = {0U};
        MCAN_InitParams            initParams = {0U};
        MCAN_ConfigParams          configParams = {0U};
        MCAN_MsgRAMConfigParams    msgRAMConfigParams = {0U};
        MCAN_BitTimingParams       bitTimes = {0U};
        uint32_t                   i;
    
        /* Initialize MCAN module initParams */
        MCAN_initOperModeParams(&initParams);
        /* CAN FD Mode and Bit Rate Switch Enabled */
        initParams.fdMode          = FALSE;
        initParams.brsEnable       = FALSE;
    
        /* Initialize MCAN module Global Filter Params */
        MCAN_initGlobalFilterConfigParams(&configParams);
    
        /* Initialize MCAN module Bit Time Params */
        /* Configuring default 1Mbps and 5Mbps as nominal and data bit-rate resp */
        MCAN_initSetBitTimeParams(&bitTimes);
    
        /* Initialize MCAN module Message Ram Params */
        App_mcanInitMsgRamConfigParams(&msgRAMConfigParams);
    
        /* Initialize Filter element to receive msg, should be same as tx msg id */
    
        for (i = 0U; i < APP_MCAN_EXT_ID_FILTER_CNT; i++)
        {
            App_mcanInitExtFilterElemParams(&extFiltElem[i], i);
        }
        /* wait for memory initialization to happen */
        while (FALSE == MCAN_isMemInitDone(gMcanBaseAddr))
        {}
    
        /* Put MCAN in SW initialization mode */
        MCAN_setOpMode(gMcanBaseAddr, MCAN_OPERATION_MODE_SW_INIT);
        while (MCAN_OPERATION_MODE_SW_INIT != MCAN_getOpMode(gMcanBaseAddr))
        {}
    
        /* Initialize MCAN module */
        MCAN_init(gMcanBaseAddr, &initParams);
        /* Configure MCAN module Gloabal Filter */
        MCAN_config(gMcanBaseAddr, &configParams);
        /* Configure Bit timings */
        MCAN_setBitTime(gMcanBaseAddr, &bitTimes);
        /* Configure Message RAM Sections */
        MCAN_msgRAMConfig(gMcanBaseAddr, &msgRAMConfigParams);
        /* Set Extended ID Mask */
        MCAN_setExtIDAndMask(gMcanBaseAddr, APP_MCAN_EXT_ID_MASK);
    
    
        
        for (i = 0U; i < APP_MCAN_EXT_ID_FILTER_CNT; i++)
        {
            MCAN_addExtMsgIDFilter(gMcanBaseAddr, i, &extFiltElem[i]);
        }
        if (TRUE == enableInternalLpbk)
        {
            MCAN_lpbkModeEnable(gMcanBaseAddr, MCAN_LPBK_MODE_INTERNAL, TRUE);
        }
    
        /* Take MCAN out of the SW initialization mode */
        MCAN_setOpMode(gMcanBaseAddr, MCAN_OPERATION_MODE_NORMAL);
        while (MCAN_OPERATION_MODE_NORMAL != MCAN_getOpMode(gMcanBaseAddr))
        {}
    
        return;
    }
    
    static void App_mcanConfigTxMsg(MCAN_TxBufElement *txMsg)
    {
        uint32_t i;
    
        /* Initialize message to transmit */
        MCAN_initTxBufElement(txMsg);
        /* Standard message identifier 11 bit, stored into ID[28-18] */
        txMsg->id  = ((APP_MCAN_EXT_ID) & MCAN_EXT_ID_MASK);
        txMsg->dlc = MCAN_DATA_SIZE_8BYTES; /* Payload size is 64 bytes */
        txMsg->fdf = FALSE; /* CAN FD Frame Format */
        txMsg->xtd = TRUE; /* Extended id not configured */
        for (i = 0U; i < gMcanDataSize[MCAN_DATA_SIZE_8BYTES]; i++)
        {
            txMsg->data[i] = i;
        }
    
        return;
    }
    
    
    static void App_mcanInitExtFilterElemParams(MCAN_ExtMsgIDFilterElement *extFiltElem,
                                                uint32_t bufNum)
    {
        /* sfid1 defines the ID of the standard message to be stored. */
        extFiltElem->efid1 = APP_MCAN_EXT_ID + bufNum;
        /* As buffer mode is selected, sfid2 should be bufNum[0 - 63] */
        extFiltElem->efid2 = APP_MCAN_CLASSIC_BIT_MASK;
        /* Store message in buffer */
        extFiltElem->efec  = MCAN_EXT_FILT_ELEM_FIFO0;
        /* Below configuration is ignored if message is stored in buffer */
        extFiltElem->eft   = MCAN_EXT_FILT_TYPE_CLASSIC;
    
        return;
    }
    
    static void App_mcanEnableIntr(void)
    {
        MCAN_enableIntr(gMcanBaseAddr, MCAN_INTR_MASK_ALL, (uint32_t)TRUE);
        MCAN_enableIntr(gMcanBaseAddr, MCAN_INTR_SRC_RES_ADDR_ACCESS, (uint32_t)FALSE);
        /* Select Interrupt Line 0 */
        MCAN_selectIntrLine(gMcanBaseAddr, MCAN_INTR_MASK_ALL, MCAN_INTR_LINE_NUM_0);
        /* Enable Interrupt Line */
        MCAN_enableIntrLine(gMcanBaseAddr, MCAN_INTR_LINE_NUM_0, (uint32_t)TRUE);
    
        return;
    }
    
    static void App_mcanInitMsgRamConfigParams(MCAN_MsgRAMConfigParams
                                               *msgRAMConfigParams)
    {
        int32_t status;
    
        MCAN_initMsgRamConfigParams(msgRAMConfigParams);
    
        /* Configure the user required msg ram params */
        msgRAMConfigParams->lss = APP_MCAN_STD_ID_FILTER_CNT;
        msgRAMConfigParams->lse = APP_MCAN_EXT_ID_FILTER_CNT;
        msgRAMConfigParams->txBufCnt = APP_MCAN_TX_BUFF_CNT;
        msgRAMConfigParams->txFIFOCnt = APP_MCAN_TX_FIFO_CNT;
        /* Buffer/FIFO mode is selected */
        msgRAMConfigParams->txBufMode = MCAN_TX_MEM_TYPE_BUF;
        msgRAMConfigParams->txEventFIFOCnt = APP_MCAN_TX_EVENT_FIFO_CNT;
        msgRAMConfigParams->rxFIFO0Cnt = APP_MCAN_FIFO_0_CNT;
        msgRAMConfigParams->rxFIFO1Cnt = APP_MCAN_FIFO_1_CNT;
        /* FIFO blocking mode is selected */
        msgRAMConfigParams->rxFIFO0OpMode = MCAN_RX_FIFO_OPERATION_MODE_BLOCKING;
        msgRAMConfigParams->rxFIFO1OpMode = MCAN_RX_FIFO_OPERATION_MODE_BLOCKING;
    
        status = MCAN_calcMsgRamParamsStartAddr(msgRAMConfigParams);
        DebugP_assert(status == CSL_PASS);
    
        return;
    }
    
    static void App_mcanCompareMsg(MCAN_TxBufElement *txMsg,
                                   MCAN_RxBufElement *rxMsg)
    {
        uint32_t i;
    
    
        //if (((txMsg->id >> APP_MCAN_EXT_ID_SHIFT) & APP_MCAN_EXT_ID_MASK) ==
               // ((rxMsg->id >> APP_MCAN_EXT_ID_SHIFT) & APP_MCAN_EXT_ID_MASK))
        if ((txMsg->id & APP_MCAN_EXT_ID_MASK) ==
                (rxMsg->id  & APP_MCAN_EXT_ID_MASK))
        {
            for (i = 0U; i < gMcanDataSize[MCAN_DATA_SIZE_8BYTES]; i++)
            {
                if (txMsg->data[i] != rxMsg->data[i])
                {
                    DebugP_logError("Data mismatch !!!\r\n");
                    DebugP_assert(FALSE);
                }
            }
        }
        else
        {
            DebugP_logError("Message ID mismatch !!!\r\n");
            DebugP_assert(FALSE);
        }
    
        return;
    }
    
    static void App_mcanIntrISR(void *arg)
    {
        uint32_t intrStatus;
    
        intrStatus = MCAN_getIntrStatus(gMcanBaseAddr);
        MCAN_clearIntrStatus(gMcanBaseAddr, intrStatus);
    
        if (MCAN_INTR_SRC_TRANS_COMPLETE ==
            (intrStatus & MCAN_INTR_SRC_TRANS_COMPLETE))
        {
            SemaphoreP_post(&gMcanTxDoneSem);
        }
    
        /* If FIFO0/FIFO1 is used, then MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG macro
         * needs to be replaced by MCAN_INTR_SRC_RX_FIFO0_NEW_MSG/
         * MCAN_INTR_SRC_RX_FIFO1_NEW_MSG respectively */
        if (MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG ==
            (intrStatus & MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG))
        {
            SemaphoreP_post(&gMcanRxDoneSem);
        }
    
        return;
    }

  • Hi Srujana,

    please raise a new thread since the topic is different. There will be another expert who can help with MCAN.

    Regards,

    Shaunak