在 28377s 平台使用 CAN 通讯发送数据,配置的时候没有使能 CanaRegs.CAN_CTL.bit.Test 和 CanaRegs.CAN_TEST.bit.EXL 寄存器,然后接收邮箱和发送邮箱使用不同编号的邮箱。
使用 "src = CANStatusGet(CANAASEADDR, CAN_STS_NEWDAT);" 进行接收判断,但是检测到发送邮箱的置位和接收到自身发送的数据,也就是说发送的数据回传了。
使用 280049 平台在相同情况进行测试,也出现了这个数据回传问题。
请问一下可能是什么问题导致出现这种错误?
Green Deng:请问你是使用的TI例程更改的吗?方便贴出CAN部分的代码吗?
在 28377s 平台使用 CAN 通讯发送数据,配置的时候没有使能 CanaRegs.CAN_CTL.bit.Test 和 CanaRegs.CAN_TEST.bit.EXL 寄存器,然后接收邮箱和发送邮箱使用不同编号的邮箱。
使用 "src = CANStatusGet(CANAASEADDR, CAN_STS_NEWDAT);" 进行接收判断,但是检测到发送邮箱的置位和接收到自身发送的数据,也就是说发送的数据回传了。
使用 280049 平台在相同情况进行测试,也出现了这个数据回传问题。
请问一下可能是什么问题导致出现这种错误?
luke lin:
回复 Green Deng:
这个问题主要是针对 280049 的,不是 28377s 的。
目前 280049 测试过程中发现是因为发送邮箱配置函数的不同导致的,当调用官方 can.c 中的 CAN_SetupMessageObject() 和 CAN_sendMessage() 来配置和发送时,读取 CAN_O_NDAT_21 寄存器会发现配置的发送邮箱的对应位会变成 1,而我们的程序都是通过读取 CAN_O_NDAT_21 来判断是否接收到新的数据,然后根据邮箱编号来接收数据。这就造成了在不加其他判断逻辑的条件下自身发送时也能触发接收逻辑,出现了误判断。
但调用官方 can.c 内的 CANMessageSet() 则不会出现上述现象。使用任意邮箱发送数据时,CAN_O_NDAT_21 寄存器的任意位都不会变成 1。
对于这两种配置,希望您这边可以帮忙分析并给出一些建议。谢谢!
void
CAN_setupMessageObject(uint32_t base, uint32_t objID, uint32_t msgID,
CAN_MsgFrameType frame, CAN_MsgObjType msgType,
uint32_t msgIDMask, uint32_t flags, uint16_t msgLen)
{
uint32_t cmdMaskReg = 0U;
uint32_t maskReg = 0U;
uint32_t arbReg = 0U;
uint32_t msgCtrl = 0U;
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
ASSERT((objID <= 32U) && (objID > 0U));
ASSERT(msgLen <= 8U);
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
switch(msgType)
{
//
// Transmit message object.
//
case CAN_MSG_OBJ_TYPE_TX:
{
//
// Set message direction to transmit.
//
arbReg = CAN_IF1ARB_DIR;
break;
}
//
// Remote frame receive remote, with auto-transmit message object.
//
case CAN_MSG_OBJ_TYPE_RXTX_REMOTE:
{
//
// Set message direction to Tx for remote receivers.
//
arbReg = CAN_IF1ARB_DIR;
//
// Set this object to auto answer if a matching identifier is seen.
//
msgCtrl = (uint32_t)((uint32_t)CAN_IF1MCTL_RMTEN |
(uint32_t)CAN_IF1MCTL_UMASK);
break;
}
//
// Transmit remote request message object (CAN_MSG_OBJ_TYPE_TX_REMOTE)
// or Receive message object (CAN_MSG_OBJ_TYPE_RX).
//
default:
{
//
// Set message direction to read.
//
arbReg = 0U;
break;
}
}
//
// Set values based on Extended Frame or Standard Frame
//
if(frame == CAN_MSG_FRAME_EXT)
{
//
// Configure the Mask Registers for 29 bit Identifier mask.
//
if((flags & CAN_MSG_OBJ_USE_ID_FILTER) == CAN_MSG_OBJ_USE_ID_FILTER)
{
maskReg = msgIDMask & CAN_IF1MSK_MSK_M;
}
//
// Set the 29 bit version of the Identifier for this message
// object. Mark the message as valid and set the extended ID bit.
//
arbReg |= (msgID & CAN_IF1ARB_ID_M) | CAN_IF1ARB_MSGVAL |
CAN_IF1ARB_XTD;
}
else
{
//
// Configure the Mask Registers for 11 bit Identifier mask.
//
if((flags & CAN_MSG_OBJ_USE_ID_FILTER) == CAN_MSG_OBJ_USE_ID_FILTER)
{
maskReg = ((msgIDMask << CAN_IF1ARB_STD_ID_S) &
CAN_IF1ARB_STD_ID_M);
}
//
// Set the 11 bit version of the Identifier for this message
// object. The lower 18 bits are set to zero. Mark the message as
// valid.
//
arbReg |= ((msgID << CAN_IF1ARB_STD_ID_S) & CAN_IF1ARB_STD_ID_M) |
CAN_IF1ARB_MSGVAL;
}
//
// If the caller wants to filter on the extended ID bit then set it.
//
maskReg |= (flags & CAN_MSG_OBJ_USE_EXT_FILTER);
//
// The caller wants to filter on the message direction field.
//
maskReg |= (flags & CAN_MSG_OBJ_USE_DIR_FILTER);
//
// If any filtering is requested, set the UMASK bit to use mask register
//
if(((flags & CAN_MSG_OBJ_USE_ID_FILTER) |
(flags & CAN_MSG_OBJ_USE_DIR_FILTER) |
(flags & CAN_MSG_OBJ_USE_EXT_FILTER)) != 0U)
{
msgCtrl |= CAN_IF1MCTL_UMASK;
}
//
// Set the data length since this is set for all transfers. This is
// also a single transfer and not a FIFO transfer so set EOB bit.
//
msgCtrl |= ((uint32_t)msgLen & CAN_IF1MCTL_DLC_M);
//
// Mark this as the last entry if this is not the last entry in a FIFO.
//
if((flags & CAN_MSG_OBJ_FIFO) == 0U)
{
msgCtrl |= CAN_IF1MCTL_EOB;
}
//
// Enable transmit interrupts if they should be enabled.
//
msgCtrl |= (flags & CAN_MSG_OBJ_TX_INT_ENABLE);
//
// Enable receive interrupts if they should be enabled.
//
msgCtrl |= (flags & CAN_MSG_OBJ_RX_INT_ENABLE);
//
// Set the Control, Arb, and Mask bit so that they get transferred to the
// Message object.
//
cmdMaskReg |= CAN_IF1CMD_ARB;
cmdMaskReg |= CAN_IF1CMD_CONTROL;
cmdMaskReg |= CAN_IF1CMD_MASK;
cmdMaskReg |= CAN_IF1CMD_DIR;
//
// Write out the registers to program the message object.
//
HWREG_BP(base + CAN_O_IF1MSK) = maskReg;
HWREG_BP(base + CAN_O_IF1ARB) = arbReg;
HWREG_BP(base + CAN_O_IF1MCTL) = msgCtrl;
//
// Transfer data to message object RAM
//
HWREG_BP(base + CAN_O_IF1CMD) = cmdMaskReg | (objID & CAN_IF1CMD_MSG_NUM_M);
}
//*****************************************************************************
//
// CAN_sendMessage
//
//*****************************************************************************
void
CAN_sendMessage(uint32_t base, uint32_t objID, uint16_t msgLen,
const uint16_t *msgData)
{
uint32_t msgCtrl = 0U;
//
// Check the arguments.
//
ASSERT(CAN_isBaseValid(base));
ASSERT((objID <= 32U) && (objID > 0U));
ASSERT(msgLen <= 8U);
//
// Set IF command to read message object control value
//
// Set up the request for data from the message object.
// Transfer the message object to the IF register.
//
HWREG_BP(base + CAN_O_IF1CMD) = CAN_IF1CMD_CONTROL |
(objID & CAN_IF1CMD_MSG_NUM_M);
//
// Wait for busy bit to clear
//
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
//
// Read IF message control
//
msgCtrl = HWREGH(base + CAN_O_IF1MCTL);
//
// Check provided DLC size with actual Message DLC size
//
ASSERT((msgCtrl & CAN_IF1MCTL_DLC_M) == msgLen);
//
// Write the data out to the CAN Data registers.
//
CAN_writeDataReg(msgData, (int16_t *)(base + CAN_O_IF1DATA),
(msgCtrl & CAN_IF1MCTL_DLC_M));
//
// Set Data to be transferred from IF
//
if(msgLen > 0U)
{
msgCtrl = CAN_IF1CMD_DATA_B | CAN_IF1CMD_DATA_A;
}
else
{
msgCtrl = 0U;
}
//
// Set Direction to write
//
// Set Tx Request Bit
//
// Transfer the message object to the message object specified by
// objID.
//
HWREG_BP(base + CAN_O_IF1CMD) = (msgCtrl | CAN_IF1CMD_DIR |
CAN_IF1CMD_TXRQST |
(objID & CAN_IF1CMD_MSG_NUM_M));
}
//***********************************************************************************************************
//
// CANMessageSet
//
//***********************************************************************************************************
void
CANMessageSet(uint32_t ui32Base, uint32_t ui32ObjID, tCANMsgObject *pMsgObject,
tMsgObjType eMsgType)
{
uint32_t ui32CmdMaskReg;
uint32_t ui32MaskReg;
uint32_t ui32ArbReg;
uint32_t ui32MsgCtrl;
bool bTransferData;
bool bUseExtendedID;
bTransferData = 0;
// Check the arguments.
ASSERT(CAN_isBaseValid(ui32Base));
ASSERT((ui32ObjID <= 32) && (ui32ObjID != 0));
ASSERT((eMsgType == MSG_OBJ_TYPE_TX) ||
(eMsgType == MSG_OBJ_TYPE_TX_REMOTE) ||
(eMsgType == MSG_OBJ_TYPE_RX) ||
(eMsgType == MSG_OBJ_TYPE_RX_REMOTE) ||
(eMsgType == MSG_OBJ_TYPE_TX_REMOTE) ||
(eMsgType == MSG_OBJ_TYPE_RXTX_REMOTE));
// Wait for busy bit to clear
while(HWREGH(ui32Base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY)
{
}
// See if we need to use an extended identifier or not.
if((pMsgObject->ui32MsgID > CAN_MAX_11BIT_MSG_ID) ||
(pMsgObject->ui32Flags & MSG_OBJ_EXTENDED_ID))
{
bUseExtendedID = 1;
}
else
{
bUseExtendedID = 0;
}
// This is always a write to the Message object as this call is setting a
// message object. This call will also always set all size bits so it sets
// both data bits. The call will use the CONTROL register to set control
// bits so this bit needs to be set as well.
ui32CmdMaskReg = (CAN_IF1CMD_DIR | CAN_IF1CMD_DATA_A | CAN_IF1CMD_DATA_B |
CAN_IF1CMD_CONTROL);
// Initialize the values to a known state before filling them in based on
// the type of message object that is being configured.
ui32ArbReg = 0;
ui32MsgCtrl = 0;
ui32MaskReg = 0;
switch(eMsgType)
{
// Transmit message object.
case MSG_OBJ_TYPE_TX:
{
// Set the TXRQST bit and the reset the rest of the register.
ui32MsgCtrl |= CAN_IF1MCTL_TXRQST;
ui32ArbReg = CAN_IF1ARB_DIR;
bTransferData = 1;
break;
}
// Transmit remote request message object
case MSG_OBJ_TYPE_TX_REMOTE:
{
// Set the TXRQST bit and the reset the rest of the register.
ui32MsgCtrl |= CAN_IF1MCTL_TXRQST;
ui32ArbReg = 0;
break;
}
// Receive message object.
case MSG_OBJ_TYPE_RX:
{
// This clears the DIR bit along with everything else. The TXRQST
// bit was cleared by defaulting ui32MsgCtrl to 0.
ui32ArbReg = 0;
break;
}
// Receive remote request message object.
case MSG_OBJ_TYPE_RX_REMOTE:
{
// The DIR bit is set to one for remote receivers. The TXRQST bit
// was cleared by defaulting ui32MsgCtrl to 0.
ui32ArbReg = CAN_IF1ARB_DIR;
// Set this object so that it only indicates that a remote frame
// was received and allow for software to handle it by sending back
// a data frame.
ui32MsgCtrl = CAN_IF1MCTL_UMASK;
// Use the full Identifier by default.
ui32MaskReg = CAN_IF1MSK_MSK_M;
// Make sure to send the mask to the message object.
ui32CmdMaskReg |= CAN_IF1CMD_MASK;
break;
}
// Remote frame receive remote, with auto-transmit message object.
case MSG_OBJ_TYPE_RXTX_REMOTE:
{
// Oddly the DIR bit is set to one for remote receivers.
ui32ArbReg = CAN_IF1ARB_DIR;
// Set this object to auto answer if a matching identifier is seen.
ui32MsgCtrl = CAN_IF1MCTL_RMTEN | CAN_IF1MCTL_UMASK;
// The data to be returned needs to be filled in.
bTransferData = 1;
break;
}
// This case should never happen due to the ASSERT statement at the
// beginning of this function.
default:
{
return;
}
}
// Configure the Mask Registers.
if(pMsgObject->ui32Flags & CAN_MSG_OBJ_USE_ID_FILTER)
{
if(bUseExtendedID)
{
// Set the 29 bits of Identifier mask that were requested.
ui32MaskReg = pMsgObject->ui32MsgIDMask & CAN_IF1MSK_MSK_M;
}
else
{
// Put the 11 bit Mask Identifier into the upper bits of the field
// in the register.
ui32MaskReg = ((pMsgObject->ui32MsgIDMask << CAN_IF1ARB_STD_ID_S) &
CAN_IF1ARB_STD_ID_M);
}
}
// If the caller wants to filter on the extended ID bit then set it.
if((pMsgObject->ui32Flags & CAN_MSG_OBJ_USE_EXT_FILTER) ==
CAN_MSG_OBJ_USE_EXT_FILTER)
{
ui32MaskReg |= CAN_IF1MSK_MXTD;
}
// The caller wants to filter on the message direction field.
if((pMsgObject->ui32Flags & CAN_MSG_OBJ_USE_DIR_FILTER) ==
CAN_MSG_OBJ_USE_DIR_FILTER)
{
ui32MaskReg |= CAN_IF1MSK_MDIR;
}
if(pMsgObject->ui32Flags & (CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_USE_DIR_FILTER |
CAN_MSG_OBJ_USE_EXT_FILTER))
{
// Set the UMASK bit to enable using the mask register.
ui32MsgCtrl |= CAN_IF1MCTL_UMASK;
// Set the MASK bit so that this gets transferred to the Message
// Object.
ui32CmdMaskReg |= CAN_IF1CMD_MASK;
}
// Set the Arb bit so that this gets transferred to the Message object.
ui32CmdMaskReg |= CAN_IF1CMD_ARB;
// Configure the Arbitration registers.
if(bUseExtendedID)
{
// Set the 29 bit version of the Identifier for this message object.
// Mark the message as valid and set the extended ID bit.
ui32ArbReg |= (pMsgObject->ui32MsgID & CAN_IF1ARB_ID_M) |
CAN_IF1ARB_MSGVAL | CAN_IF1ARB_XTD;
}
else
{
// Set the 11 bit version of the Identifier for this message object.
// The lower 18 bits are set to zero.
// Mark the message as valid.
ui32ArbReg |= ((pMsgObject->ui32MsgID << CAN_IF1ARB_STD_ID_S) &
CAN_IF1ARB_STD_ID_M) | CAN_IF1ARB_MSGVAL;
}
// Set the data length since this is set for all transfers. This is also a
// single transfer and not a FIFO transfer so set EOB bit.
ui32MsgCtrl |= (pMsgObject->ui32MsgLen & CAN_IF1MCTL_DLC_M);
// Mark this as the last entry if this is not the last entry in a FIFO.
if((pMsgObject->ui32Flags & CAN_MSG_OBJ_FIFO) == 0)
{
ui32MsgCtrl |= CAN_IF1MCTL_EOB;
}
// Enable transmit interrupts if they should be enabled.
if(pMsgObject->ui32Flags & CAN_MSG_OBJ_TX_INT_ENABLE)
{
ui32MsgCtrl |= CAN_IF1MCTL_TXIE;
}
// Enable receive interrupts if they should be enabled.
if(pMsgObject->ui32Flags & CAN_MSG_OBJ_RX_INT_ENABLE)
{
ui32MsgCtrl |= CAN_IF1MCTL_RXIE;
}
// Write the data out to the CAN Data registers if needed.
if(bTransferData)
{
CANDataRegWrite(pMsgObject->pucMsgData,
(uint32_t *)(ui32Base + CAN_O_IF1DATA),
pMsgObject->ui32MsgLen);
}
// Write out the registers to program the message object.
HWREGH(ui32Base + CAN_O_IF1CMD + 2) = ui32CmdMaskReg >> 16;
HWREGH(ui32Base + CAN_O_IF1MSK) = ui32MaskReg & CAN_REG_WORD_MASK;
HWREGH(ui32Base + CAN_O_IF1MSK + 2) = ui32MaskReg >> 16;
HWREGH(ui32Base + CAN_O_IF1ARB) = ui32ArbReg & CAN_REG_WORD_MASK;
HWREGH(ui32Base + CAN_O_IF1ARB + 2) = ui32ArbReg >> 16;
HWREGH(ui32Base + CAN_O_IF1MCTL) = ui32MsgCtrl & CAN_REG_WORD_MASK;
// Transfer the message object to the message object specific by ui32ObjID.
HWREGH(ui32Base + CAN_O_IF1CMD) = ui32ObjID & CAN_IF1CMD_MSG_NUM_M;
return;
}