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.

CCS/TM4C123GH6PGE: TM4C123GH6PGE CANMessageGet() repair my ID message

Part Number: TM4C123GH6PGE

Tool/software: Code Composer Studio

This picture is Config Message CAN[5].

After interupts, I call: CANMessageGet(CAN0_BASE, 6, &g_sCAN0Message[5], 0);

Then the ID and Length is repaired because in funtion CANMessageGet: ( to 2 and 0 )

ui16CmdMaskReg = (CAN_IF1CMSK_DATAA | CAN_IF1CMSK_DATAB |
CAN_IF1CMSK_CONTROL | CAN_IF1CMSK_MASK |
CAN_IF1CMSK_ARB);

psMsgObject->ui32MsgID = (ui16ArbReg1 & CAN_IF1ARB2_ID_M) >> 2;

Next time: the interuupst still appear and CANMessageGet(CAN0_BASE, 6, &g_sCAN0Message[5], 0);  still call

I dont know why, please help me

  • I am afraid I am not sure I understand your question. If you are telling me that:
    1. you setup mailbox 6
    2. then get an interrupt as a CAN message is received,
    3. in the interrupt routine you read the message with "CANMessageGet(CAN0_BASE, 6, &g_sCAN0Message[5], 0);"
    4. You exit the interrupt routine, but the interrupt is immediately called again.

    Then the issue is that you did not clear the interrupt because the last parameter of the CANMessageGet function is a Boolean that tells if the function should clear the pending interrupt. You set that parameter to '0', which is "false". To clear the pending interrupt the call should look like:

    CANMessageGet(CAN0_BASE, 6, &g_sCAN0Message[5], 1);

    For readability I suggest you include <stdbool.h> and call the function as:

    CANMessageGet(CAN0_BASE, 6, &g_sCAN0Message[5], true);"
  • I show you step:
    1> Init :
    ------------------------------------------------------------------------------------------------------
    /* Initial message box information */
    for (i = 0U; i < CAN_MSGBOX_NUMBER; i++)
    {
    CAN_DATA[i].CAN_Counter = 0U;
    CAN_DATA[i].CAN_Flag = 0U;
    if (CAN_ID[i].CanEnable != DISABLE)
    {
    g_sCAN0Message[i].ui32MsgID = CAN_ID[i].CanMsgID;
    g_sCAN0Message[i].ui32MsgIDMask = 0U;
    g_sCAN0Message[i].pui8MsgData = CAN_DATA[i].CAN_Data; /* Pointer receive data */
    g_sCAN0Message[i].ui32MsgLen = CAN_ID[i].CanLen;
    if (CAN_ID[i].CanMode == MSG_OBJ_TYPE_RX)
    {
    g_sCAN0Message[i].ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER; /* Enable Receive in Interrupts */
    CANMessageSet(CAN0_BASE, (i+1U), &g_sCAN0Message[i], (tMsgObjType)CAN_ID[i].CanMode); /* Setup Msg */
    }
    else /* TX */
    {
    g_sCAN0Message[i].ui32Flags = MSG_OBJ_TX_INT_ENABLE; /*MSG_OBJ_NO_FLAGS;*/ /* Enable Transfer Interrupts */
    }
    }
    else /* Disable Msg */
    {
    g_sCAN0Message[i].ui32MsgID = 0U;
    g_sCAN0Message[i].ui32MsgIDMask = 0U;
    g_sCAN0Message[i].ui32MsgLen = 0U;
    }
    }
    -------------------------------------------------------------------------------------------------------------------
    2> Init success. The interrupts happen
    void CAN0_Interrupts_Handler(void)
    {
    if (ui32Status == 6U) /* Check if the cause is message object 1~32. */
    {
    CANIntClear(CAN0_BASE, ui32Status);
    if ((tMsgObjType)CAN_ID[ui32Status-1].CanMode == MSG_OBJ_TYPE_RX)
    {
    CAN_DATA[ui32Status-1].CAN_Flag = 1U; /* Inform Rx Data */
    }
    }
    }
    3> In my appcication: call each 10ms
    void CAN_Rx_Appication(void) /* run each 10ms */
    {
    for (i = 0; i < CAN_MSGBOX_NUMBER; i ++) /* 0 ~ 31 */
    {
    if (CAN_DATA[i].CAN_Flag == 1U)
    {
    CANMessageGet(CAN0_BASE, (i+1), &g_sCAN0Message[i], 0);
    }
    }
    }

    After call: CANMessageGet(CAN0_BASE, (i+1), &g_sCAN0Message[i], 0);
    -> the setup of g_sCAN0Message[5] was modified: ID = 2, Len = 0.  ( I have add In top question )
    Then, I sent next message 0x03, the interrupts still appear, CANMessageGet(CAN0_BASE, (i+1), &g_sCAN0Message[i], 0); recall
    why ???? ( if ID was modified, why the interupts appear ? )

    The question 4 of you: I don't disable interrupts, because the message always sent from master

  • I am still not sure I understand your question. If this does not answer your question, please try to rephrase and ask again.

    You setup CAN mailbox 6 to receive message ID 0x0002, but you set the MsgIdMask = 0x0000, all bits are masked. This means any message ID received would go into this mailbox. In your case, the message ID 0x0003 came and was stored in the mailbox. The CANMessageGet() routine updates the structure with the received ID (0x0003) and the length of the received message (0). If you wanted to receive only message ID 0x0002 in mailbox 6, you should set the MsgIdMask = 0xFFFFFFFF, all bits of the ID are used.

  • I show you my project: ( I'm Slave)

    1. Master Send 2 Message ( ID = 2(1byte), ID = 3( 8 byte) -> Send OK each 1 second.

    2. I'm Slaver, I config:
    tCANMsgObject g_sCAN0Message[32];
    /* Init message 1, ID = 3 */
    g_sCAN0Message[5].ui32MsgID = 3;
    g_sCAN0Message[5].ui32MsgIDMask =0;
    g_sCAN0Message[5].ui32MsgLen = 8;
    g_sCAN0Message[5].pui8MsgData = g_ui8CANData_3; /* g_ui8CANData_3[8] */
    g_sCAN0Message[5].ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER;
    CANMessageSet(CAN0_BASE, 6, &g_sCAN0Message[5], MSG_OBJ_TYPE_RX);
    /* Init message 2, ID = 2 */
    g_sCAN0Message[8].ui32MsgID = 2;
    g_sCAN0Message[8].ui32MsgIDMask =0;
    g_sCAN0Message[8].ui32MsgLen = 1;
    g_sCAN0Message[8].pui8MsgData = (uint8_t *)g_ui8CANData_2; /* g_ui8CANData_2[1] */
    g_sCAN0Message[8].ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER;
    CANMessageSet(CAN0_BASE, 9, &g_sCAN0Message[8], MSG_OBJ_TYPE_RX);

    In Interrupts Handler:

    else if (ui32Status == 6U) /* Check if the cause is message object 1~32. */
    {
    CANIntClear(CAN0_BASE, ui32Status);
    flag_rx1 = 1;
    }
    else if (ui32Status == 9U) /* Check if the cause is message object 1~32. */
    {
    CANIntClear(CAN0_BASE, ui32Status);
    flag_rx2 = 1;
    }

    Each 10ms Application:

    if (flag_rx1 == 1)
    {
    CANMessageGet(CAN0_BASE, 6, &g_sCAN0Message[5], false);
    flag_rx1 = 0;
    }
    else if (flag_rx2 == 1)
    {
    CANMessageGet(CAN0_BASE, 9, &g_sCAN0Message[8], false);
    flag_rx2 = 0;
    }

    The problem:
    - When the 1st application happen: g_sCAN0Message[5] was modified, ID = 2 and length = 0 ( let's see in picture in first question )
    - T flag_rx2 never = 1, the (ui32Status == 9U) never appear

    I dont know why. Please help me to solve it
  • You must change:

    g_sCAN0Message[5].ui32MsgIDMask =0;

    to

    g_sCAN0Message[5].ui32MsgIDMask =0x00FFFFFF;

  • I have already changed g_sCAN0Message[5].ui32MsgIDMask =0x00FFFFFF;

    but after 1 st frame receive , ID -> 2, Mask -> 0x000007FF, Length -> 0
    I dont know why
  • Dear Bob Crosby,

    I have already solved this problem. This Error is:

    TivaWare_C_Series-2.1.3.156 in Driverlib -> can.c -> CANIntClear(uint32_t ui32Base, uint32_t ui32IntClr)

    I modify: HWREG(ui32Base + CAN_O_IF1CMSK) |= CAN_IF1CMSK_CLRINTPND;

    to HWREG(ui32Base + CAN_O_IF1CMSK) = CAN_IF1CMSK_CLRINTPND; /* DaoHVN -> fix in forum e2e.ti.com/ Forum */
    and when get data: CANMessageGet(CAN0_BASE, 6, &g_sCAN0Message[5], true);

    thanks so much