Other Parts Discussed in Thread: TM4C129DNCPDT
Hi all
I'm having some trouble receiving correct CAN messages when the bus is busy.
I am using the TM4C129DNCPDT on our own board. I have 2 boards communicating with a short cable between them.
To get to the bottom of my problem I am transmitting "123456789" over and over on one particular msg id.
I have severeal msg id's doing various other tasks.
It seems that the can bus is sometimes receiving incorrect can messages where the first 2 bytes of the message is changed - usually into 0x03 0x00.
If I disable all other can communication the problem disappears.
I have posted my interrupt function below - Is there anything that can trigger this behaviour?
void HalCanInterruptHandler(uint8_t ucModule)
{
tCANMsgObject sMsgObj;
tMsgObjType eMsgObjType = MSG_OBJ_TYPE_TX;
uint32_t usStatus = 0;
uint16_t usMsgIdx = 0;
uint32_t base = HalCanModule[ucModule].ulCanBase;
HalCanResult msg_stat = HAL_CAN_RESULT_NO_ERROR;
HalCanMessage_t *message;
// Read the CAN interrupt status to find the cause of the interrupt
do
{
usStatus = CANIntStatus(base, CAN_INT_STS_CAUSE);
// If the cause is a controller status interrupt, then get the status
if (usStatus == CAN_INT_INTID_STATUS)
{
// Read the controller status. Also clears the status interrupt
uint32_t canStatus = CANStatusGet(base, CAN_STS_CONTROL);// & HAL_CAN_STATUS_MASK;
canStatus = canStatus & HAL_CAN_STATUS_MASK; //Filter out RX_OK and TX_OK flags
// Only interested in status messages if it is related to an error
if (canStatus != CAN_STATUS_LEC_NONE)
{
int j;
// Now see which errors are present
switch (canStatus & CAN_STATUS_LEC_MASK)
{
case CAN_STATUS_LEC_STUFF: msg_stat |= HAL_CAN_RESULT_LEC_STUFF; break;
case CAN_STATUS_LEC_FORM: msg_stat |= HAL_CAN_RESULT_LEC_FORM; break;
case CAN_STATUS_LEC_ACK: msg_stat |= HAL_CAN_RESULT_LEC_ACK; break;
case CAN_STATUS_LEC_BIT1: msg_stat |= HAL_CAN_RESULT_LEC_BIT1; break;
case CAN_STATUS_LEC_BIT0: msg_stat |= HAL_CAN_RESULT_LEC_BIT0; break;
case CAN_STATUS_LEC_CRC: msg_stat |= HAL_CAN_RESULT_LEC_CRC; break;
}
if (canStatus & CAN_STATUS_BUS_OFF)
{
msg_stat |= HAL_CAN_RESULT_BUS_OFF;
// Bus-off disables the module. To recover we must re-enable the module
CANEnable(base);
}
if (canStatus & CAN_STATUS_EWARN)
{
msg_stat |= HAL_CAN_RESULT_EWARN;
}
if (canStatus & CAN_STATUS_EPASS)
{
msg_stat |= HAL_CAN_RESULT_EPASS;
}
// Can't rely on getting information from CAN module about what TX/RX object was behind interrupt
// when error case. Need to call back to all with status information
for (j = 0; j < HAL_CAN_NO_OF_MSG_OBJS; j++)
{
XHalCanCallBack cb = HalCanMessage[ucModule][j].can_call_back;
eMsgObjType = HalCanMessage[ucModule][j].eObjType;
HalCanMessage[ucModule][j].ulStatus = msg_stat;
// Don't bother telling listeners that the interface is down or running with errors
if ((cb != NULL) && ((eMsgObjType == MSG_OBJ_TYPE_TX) || (eMsgObjType == MSG_OBJ_TYPE_TX_REMOTE)))
{
cb(&HalCanMessage[ucModule][j]);
}
}
}
}
else if ((usStatus > 0) && (usStatus <= 32))
{
message = &HalCanMessage[ucModule][usStatus - 1]; //usStatus is from 1-32
// What was the original message type?
eMsgObjType = message->eObjType;
// In case of reception, go get the message
if ((eMsgObjType == MSG_OBJ_TYPE_RX) || (eMsgObjType == MSG_OBJ_TYPE_RX_REMOTE))
{
// Tell where to store received data (no matter if it is a remote reception)
sMsgObj.pui8MsgData = message->aucData;
// Go get the message
CANMessageGet(base, usStatus, &sMsgObj, true);
// Get the length of the message (only valid for data message)
message->ucLength = sMsgObj.ui32MsgLen;
if ((sMsgObj.ui32Flags & MSG_OBJ_NEW_DATA) != 0)
{
message->ulStatus = HAL_CAN_RESULT_NO_ERROR;
// If a call-back function was given, do call it now
if (message->can_call_back != NULL)
{
message->can_call_back(message);
}
}
}
else
{
// Clear processed message interrupt.
CANIntClear(base, usStatus);
message->ulStatus = HAL_CAN_RESULT_NO_ERROR;
// If a call-back function was given, do call it now
if (message->can_call_back != NULL)
{
message->can_call_back(message);
}
}
}
else if (usStatus != 0)
{
//undefined!!!!
ASSERT(FALSE);
}
} while (usStatus != 0);
}