Renesas RZG2L

Hi, I want to use canfd internal loopback on Renesas RZG2 because my board doesn´t have CAN transceivers, Any idea or example to use it.

Regards

Parents Reply
  • So, the idea is use it on Cortex-M33, so I configured canfd 1, I'm using this API to change CANFD operation mode, 

    R_CANFD_ModeTransition(&g_canfd1_ctrl,CAN_OPERATION_MODE_NORMAL,CAN_TEST_MODE_LOOPBACK_INERRNAL);

    After write something in the can bus the callback is called but the event is for CAN_EVENT_TX_COMPLETE, my question is Where is the received data on canfd? and Why interrupt is not called when a RX even happen. I attach an image.

Children
  • #include "canfd_thread.h"
    /* CANFD_thread entry function */
    
    #define CAN_EXAMPLE_ID      (0x18ff622)
    
    can_frame_t g_can0_tx_frame;
    can_frame_t g_can0_rx_frame;
    
    can_frame_t g_can1_tx_frame;
    can_frame_t g_can1_rx_frame;
    
    
    volatile canfd_error_t g_err_status = (canfd_error_t) 0;
    
    #define CAN_EXAMPLE_64_BYTES    64
    
    
    const canfd_afl_entry_t p_canfd0_afl[CANFD_CFG_AFL_CH0_RULE_NUM] =
    {
        /* Store all data frames with at least 0 bytes from Extended IDs CAN_EXAMPLE_ID in RX FIFO 0 */
        {
            .id =
            {
                .id         = CAN_EXAMPLE_ID,
                .frame_type = CAN_FRAME_TYPE_DATA,
                .id_mode    = CAN_ID_MODE_EXTENDED
            },
            .mask =
            {
                .mask_id         =  0x1FFFFFFF,
                .mask_frame_type = 1,
                .mask_id_mode    = 1
            },
            .destination =
            {
                .minimum_dlc       = CANFD_MINIMUM_DLC_0,
                .rx_buffer         = CANFD_RX_MB_NONE,
                .fifo_select_flags = (canfd_rx_fifo_t) (CANFD_RX_FIFO_0)
            }
        }
    };
    
    const canfd_afl_entry_t p_canfd1_afl[CANFD_CFG_AFL_CH1_RULE_NUM] =
    {
     /* Store all data frames with at least 0 bytes from Extended IDs CAN_EXAMPLE_ID in RX FIFO 1 */
        {
            .id =
            {
                .id         = CAN_EXAMPLE_ID,
                .frame_type = CAN_FRAME_TYPE_DATA,
                .id_mode    = CAN_ID_MODE_EXTENDED
            },
            .mask =
            {
                .mask_id         =  0x1FFFFFFF,
                .mask_frame_type = 1,
                .mask_id_mode    = 1
            },
            .destination =
            {
                .minimum_dlc       = CANFD_MINIMUM_DLC_0,
                .rx_buffer         = CANFD_RX_MB_NONE,
                .fifo_select_flags = (canfd_rx_fifo_t) (CANFD_RX_FIFO_1)
            }
        }
    };
    
    
    void canfd0_callback (can_callback_args_t * p_args)
    {
        switch (p_args->event)
        {
            case CAN_EVENT_RX_COMPLETE:    /* Receive complete event. */
            {
                /* Read received frame */
                memcpy(&g_can0_rx_frame, p_args->p_frame, sizeof(can_frame_t));
                /* Handle event */
                break;
            }
            case CAN_EVENT_TX_COMPLETE:    /* Transmit complete event. */
            {
                /* Handle event */
    
                break;
            }
            case CAN_EVENT_ERR_GLOBAL:                        /* Global error. */
            case CAN_EVENT_ERR_CHANNEL:                       /* Channel error. */
            {
                /* Get error status */
                g_err_status = (canfd_error_t) p_args->error; /* Check error code with canfd_error_t. */
                /* Handle event */
                break;
            }
            default:
            {
                break;
            }
        }
    }
    
    void canfd1_callback (can_callback_args_t * p_args)
    {
        switch (p_args->event)
        {
            case CAN_EVENT_RX_COMPLETE:    /* Receive complete event. */
            {
                /* Read received frame */
                memcpy(&g_can1_rx_frame, p_args->p_frame, sizeof(can_frame_t));
                /* Handle event */
                break;
            }
            case CAN_EVENT_TX_COMPLETE:    /* Transmit complete event. */
            {
                /* Handle event */
    
                break;
            }
            case CAN_EVENT_ERR_GLOBAL:                        /* Global error. */
            case CAN_EVENT_ERR_CHANNEL:                       /* Channel error. */
            {
                /* Get error status */
                g_err_status = (canfd_error_t) p_args->error; /* Check error code with canfd_error_t. */
                /* Handle event */
                break;
            }
            default:
            {
                break;
            }
        }
    }
    
    
    /* pvParameters contains TaskHandle_t */
    void canfd_thread_entry(void *pvParameters)
    {
        FSP_PARAMETER_NOT_USED (pvParameters);
    
        /* Assert reset signal for CANFD. */
        R_BSP_MODULE_RSTON(FSP_IP_CANFD, 0);
        R_BSP_MODULE_RSTON(FSP_IP_CANFD, 1);
    
        fsp_err_t err;
        err = R_CANFD_Open(&g_canfd0_ctrl, &g_canfd0_cfg);
        err = R_CANFD_Open(&g_canfd1_ctrl, &g_canfd1_cfg);
        /* Handle any errors. This function should be defined by the user. */
        assert(FSP_SUCCESS == err);
    
        /* Switch to external loopback mode */
        err = R_CANFD_ModeTransition(&g_canfd0_ctrl, CAN_OPERATION_MODE_NORMAL, CAN_TEST_MODE_LOOPBACK_INTERNAL);
        err = R_CANFD_ModeTransition(&g_canfd1_ctrl, CAN_OPERATION_MODE_NORMAL, CAN_TEST_MODE_LOOPBACK_INTERNAL);
        //err = R_CANFD_ModeTransition(&g_canfd0_ctrl, CAN_OPERATION_MODE_NORMAL, CAN_TEST_MODE_LOOPBACK_EXTERNAL);
        //err = R_CANFD_ModeTransition(&g_canfd1_ctrl, CAN_OPERATION_MODE_NORMAL, CAN_TEST_MODE_LOOPBACK_EXTERNAL);
        assert(FSP_SUCCESS == err);
    
        /* Configure a frame to write 64 bytes with bitrate switching (BRS) enabled */
        g_can0_tx_frame.id               = CAN_EXAMPLE_ID;
        g_can0_tx_frame.id_mode          = CAN_ID_MODE_EXTENDED;
        g_can0_tx_frame.type             = CAN_FRAME_TYPE_DATA;
        g_can0_tx_frame.data_length_code = CAN_EXAMPLE_64_BYTES;
        g_can0_tx_frame.options          = CANFD_FRAME_OPTION_FD | CANFD_FRAME_OPTION_BRS;
    
        /* Configure a frame to write 64 bytes with bitrate switching (BRS) enabled */
        g_can1_tx_frame.id               = CAN_EXAMPLE_ID;
        g_can1_tx_frame.id_mode          = CAN_ID_MODE_EXTENDED;
        g_can1_tx_frame.type             = CAN_FRAME_TYPE_DATA;
        g_can1_tx_frame.data_length_code = CAN_EXAMPLE_64_BYTES;
        g_can1_tx_frame.options          = CANFD_FRAME_OPTION_FD | CANFD_FRAME_OPTION_BRS;
    
        /* Write some data to the transmit frame */
        for (uint32_t i = 0; i < CAN_DATA_BUFFER_LENGTH; i++)
        {
            if (i % 2 == 0) {
                g_can0_tx_frame.data[i] = (uint8_t) 0xAA;
            }
            else {
                g_can0_tx_frame.data[i] = (uint8_t) 0x55;
            }
        }
        for (uint32_t i = 0; i < CAN_DATA_BUFFER_LENGTH; i++)
        {
            if (i % 2 == 0) {
                g_can1_tx_frame.data[i] = (uint8_t) 0x55;
            }
            else {
                g_can1_tx_frame.data[i] = (uint8_t) 0xAA;
            }
        }
    
        /* Send data on the bus */
        err = R_CANFD_Write(&g_canfd0_ctrl, CANFD_TX_MB_0, &g_can0_tx_frame);
        assert(FSP_SUCCESS == err);
        err = R_CANFD_Write(&g_canfd1_ctrl, CANFD_TX_MB_0, &g_can1_tx_frame);
        assert(FSP_SUCCESS == err);
        /* Wait for a transmit and/or receive callback event */
    
        while (1)
        {
            vTaskDelay (1);
        }
    }
    

    Have a look at this.

    RXFIFO0 and RXFIFO1 have to be configured in the smart configurator.

  • So I tried with this example, but interrupt by CAN_RX_EVENT_COMPLETE never happens even RXFIFO0 and RXFIFO1 are enabled

    Should I configure something else to get an interrupt by a RX event?

  • Normally not.

    Paste the rest of the configuration.

  • OK. You have to enable the TX Buffer Merge Mode.
    This is to send more than 20 bytes, however it should not matter for RX interrupts.

    Is Linux running? Or stopped at u-boot?

    Are you sure you reset the module(s)?

    /* Assert reset signal for CANFD. */
    R_BSP_MODULE_RSTON(FSP_IP_CANFD, 0);
    R_BSP_MODULE_RSTON(FSP_IP_CANFD, 1);

  • Done, but it doesn´t work. Even I connected a logic analyzer to see CAN frames on Tx line I see an error frame,

    SMARC carrier board has a PMOD0 connector where CAN1_TX and CAN1_RX pins can be connected. I multiplexed but even TX is not working properly

     

  • It does work here.

    Forget Cortex-M33 for a moment, can you get the internal loopback mode working in Linux as per suggested wiki page?

  • I´m using canfd 0 and now is working internal loopback, thanks for the support