// ============================================================================ // º¯ÊýÃû³Æ: CANMessageSend() // º¯Êý¹¦ÄÜ: CAN·¢Ëͺ¯Êý // Êä Èë: ui32Base is the base address of the CAN controller //! ui32ObjID is the object number to configure (1-32). //! pMsgObject is a pointer to a structure containing message object settings. //! eMsgType indicates the type of message for this object. // Êä ³ö: ÎÞ // ÉÈ Èë: BspCan_CanTx // CAN³õʼ»¯ // ÉÈ ³ö: ÎÞ // ÆäËü˵Ã÷: ÎÞ // =========================================================================== int16 CANMessageSend(Uint32 ui32Base, Uint32 ui32ObjID, tCANMsgObject *pMsgObject, tMsgObjType eMsgType) { Uint32 ui32CmdMaskReg = 0; Uint32 ui32MaskReg = 0; Uint32 ui32ArbReg = 0; Uint32 ui32MsgCtrl = 0; bool bTransferData = FALSE; bool bUseExtendedID = FALSE; Uint16 S_Temp = 0; int16 Rtv = SYS_CAN_OP_OK; bTransferData = 0; while(((CAN_ADDR16(ui32Base + CAN_O_IF1CMD) & \ CAN_IF1CMD_BUSY) != 0) && (S_Temp < 1000)) // ¼ì²éÊÇ·ñ´¦ÓÚ¿ÕÏÐ״̬,Èç¹ûÕâÀïͨ²»¹ý£¬ÄÇÏÂÃæµÄ¼Ä´æÆ÷¶¼ÎÞ·¨²Ù×÷£¬ÒòΪ¼Ä´æÆ÷¶¼ÊÜbusy±£»¤ { DELAY_US(1); // ×î¶àµÈ´ý1msºóÍ˳ö S_Temp++; // ͨ¹ý×öʵÑ飬ÕâÀïÔÚ³õʼ»¯µÄʱºò²»»á½øÈë } if (S_Temp >= 1000) { S_Temp = 0; // Í˳öºó½«µÈ´ý¼ÆÊýÇåÀí´¦Àí Rtv = SYS_CAN_OP_ERROR; // ·µ»ØCAN·¢ËÍ´íÎó } else { S_Temp = 0; } if((pMsgObject->ui32MsgID > CAN_MAX_11BIT_MSG_ID) || ((pMsgObject->ui32Flags & MSG_OBJ_EXTENDED_ID) != 0)) // ÅжÏÊÇ·ñΪ±ê×¼Ö¡»¹ÊÇÀ©Õ¹Ö¡ { bUseExtendedID = 1; } else { bUseExtendedID = 0; } ui32CmdMaskReg = (CAN_IF1CMD_DIR | CAN_IF1CMD_DATA_A | CAN_IF1CMD_DATA_B | CAN_IF1CMD_CONTROL); // 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. ui32ArbReg = 0; // Initialize the values to a known state before filling them in based on the type of message object that is being configured. ui32MsgCtrl = 0; ui32MaskReg = 0; switch(eMsgType) { case MSG_OBJ_TYPE_TX: // Transmit message object. { ui32MsgCtrl |= CAN_IF1MCTL_TXRQST; // Set the TXRQST bit and the reset the rest of the register. ui32ArbReg = CAN_IF1ARB_DIR; bTransferData = 1; break; } case MSG_OBJ_TYPE_TX_REMOTE: // Transmit remote request message object { ui32MsgCtrl |= CAN_IF1MCTL_TXRQST; // Set the TXRQST bit and the reset the rest of the register. ui32ArbReg = 0; break; } case MSG_OBJ_TYPE_RX: // Receive message object. { ui32ArbReg = 0; // This clears the DIR bit along with everything else. The TXRQST bit was cleared by defaulting ui32MsgCtrl to 0. break; } case MSG_OBJ_TYPE_RX_REMOTE: // Receive remote request message object. { ui32ArbReg = CAN_IF1ARB_DIR; // The DIR bit is set to one for remote receivers. The TXRQST bit was cleared by defaulting ui32MsgCtrl to 0. ui32MsgCtrl = CAN_IF1MCTL_UMASK; // 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. ui32MaskReg = CAN_IF1MSK_MSK_M; // Use the full Identifier by default. ui32CmdMaskReg |= CAN_IF1CMD_MASK; // Make sure to send the mask to the message object. break; } case MSG_OBJ_TYPE_RXTX_REMOTE: // Remote frame receive remote, with auto-transmit message object. { ui32ArbReg = CAN_IF1ARB_DIR; // Oddly the DIR bit is set to one for remote receivers. ui32MsgCtrl = CAN_IF1MCTL_RMTEN | CAN_IF1MCTL_UMASK; // Set this object to auto answer if a matching identifier is seen. bTransferData = 1; // The data to be returned needs to be filled in. break; } default: // This case should never happen due to the ASSERT statement at the beginning of this function. { Rtv = SYS_CAN_OP_ERROR; break; } } if ((pMsgObject->ui32Flags & MSG_OBJ_USE_ID_FILTER) != 0) // Configure the Mask Registers. { if(bUseExtendedID) { ui32MaskReg = pMsgObject->ui32MsgIDMask & CAN_IF1MSK_MSK_M; // Set the 29 bits of Identifier mask that were requested. } else { ui32MaskReg = ((pMsgObject->ui32MsgIDMask << CAN_IF1ARB_STD_ID_S) & CAN_IF1ARB_STD_ID_M); // Put the 11 bit Mask Identifier into the upper bits of the field in the register. } } else { ; } if ((pMsgObject->ui32Flags & MSG_OBJ_USE_EXT_FILTER) == MSG_OBJ_USE_EXT_FILTER) // If the caller wants to filter on the extended ID bit then set it. { ui32MaskReg |= CAN_IF1MSK_MXTD; } else { ; } if ((pMsgObject->ui32Flags & MSG_OBJ_USE_DIR_FILTER) == MSG_OBJ_USE_DIR_FILTER) // The caller wants to filter on the message direction field. { ui32MaskReg |= CAN_IF1MSK_MDIR; } else { ; } if ((pMsgObject->ui32Flags & (MSG_OBJ_USE_ID_FILTER | MSG_OBJ_USE_DIR_FILTER | MSG_OBJ_USE_EXT_FILTER)) != 0) { ui32MsgCtrl |= CAN_IF1MCTL_UMASK; // Set the UMASK bit to enable using the mask register. ui32CmdMaskReg |= CAN_IF1CMD_MASK; // Set the MASK bit so that this gets transferred to the Message Object. } else { ; } ui32CmdMaskReg |= CAN_IF1CMD_ARB; // Set the Arb bit so that this gets transferred to the Message object. if (bUseExtendedID) // Configure the Arbitration registers. { ui32ArbReg |= (pMsgObject->ui32MsgID & CAN_IF1ARB_ID_M) | CAN_IF1ARB_MSGVAL | CAN_IF1ARB_XTD; // Set the 29 bit version of the Identifier for this message object.Mark the message as valid and set the extended ID bit. } else { ui32ArbReg |= ((pMsgObject->ui32MsgID << CAN_IF1ARB_STD_ID_S) & CAN_IF1ARB_STD_ID_M) | CAN_IF1ARB_MSGVAL; // 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. } ui32MsgCtrl |= (pMsgObject->ui32MsgLen & CAN_IF1MCTL_DLC_M); // 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. if ((pMsgObject->ui32Flags & MSG_OBJ_FIFO) == 0) // Mark this as the last entry if this is not the last entry in a FIFO. { ui32MsgCtrl |= CAN_IF1MCTL_EOB; } else { ; } if ((pMsgObject->ui32Flags & MSG_OBJ_TX_INT_ENABLE) != 0) // Enable transmit interrupts if they should be enabled. { ui32MsgCtrl |= CAN_IF1MCTL_TXIE; } else { ; } if ((pMsgObject->ui32Flags & MSG_OBJ_RX_INT_ENABLE) != 0) // Enable receive interrupts if they should be enabled. { ui32MsgCtrl |= CAN_IF1MCTL_RXIE; } else { ; } if (bTransferData) // Write the data out to the CAN Data registers if needed. { CANDataRegWrite(pMsgObject->pucMsgData, (Uint32 *)(ui32Base + CAN_O_IF1DATA), pMsgObject->ui32MsgLen); } else { ; } CAN_ADDR16(ui32Base + CAN_O_IF1CMD + 2) = ui32CmdMaskReg >> 16; // Write out the registers to program the message object. CAN_ADDR16(ui32Base + CAN_O_IF1MSK) = ui32MaskReg & CAN_REG_WORD_MASK; CAN_ADDR16(ui32Base + CAN_O_IF1MSK + 2) = ui32MaskReg >> 16; CAN_ADDR16(ui32Base + CAN_O_IF1ARB) = ui32ArbReg & CAN_REG_WORD_MASK; CAN_ADDR16(ui32Base + CAN_O_IF1ARB + 2) = ui32ArbReg >> 16; CAN_ADDR16(ui32Base + CAN_O_IF1MCTL) = ui32MsgCtrl & CAN_REG_WORD_MASK; CAN_ADDR16(ui32Base + CAN_O_IF1CMD) = ui32ObjID & CAN_IF1CMD_MSG_NUM_M; // Transfer the message object to the message object specific by ui32ObjID. return (Rtv); }