📄 can.c
字号:
uint8 bFreezeMode;
if(iTxMBNo >= NUMBER_OF_MB)
{
return; // out of range
}
// Make sure FlexCAN is in Freeze mode
if(!(pFlexCANReg->MCR & FLEXCAN_MCR_HALT)) //FLEXCAN_MCR_FRZ_ACK))
{
FlexCAN_Stop(); // halt FlexCAN safely
bFreezeMode = 0;
}
else
{
bFreezeMode = 1;
}
// Start transmit/receive with specified tx/rx code
pFlexCANReg->MB[iTxMBNo].CS = (pFlexCANReg->MB[iTxMBNo].CS & ~(FLEXCAN_MB_CS_CODE_MASK))
| FLEXCAN_MB_CS_CODE(txrxCode) // write code
;
// Restore FlexCAN operation mode
if(!bFreezeMode)
{
FlexCAN_Start();
}
}
/**************************************************************
ReadCANMB
** Read directly from CAN Message Buffer up to 8 bytes and return
** the size in bytes of data read.
** NOTE:
** So the ID format is:
** B31 30 29 28 27 26 ... 11 10 9 8 7 6 5 4 3 2 1 0
** | | | |
** | | |------------------------------------|
** | | |--> 29 bits ID
** | |
** | |--> 1: RTR bit set, 0: RTR bit clear
** |
** |--> 1 : Extended ID, 0: Standardard ID
**************************************************************/
uint16 FlexCAN_ReadCANMB(uint16 iMB, uint32 *id, uint32 * timeStamp, uint8 *data, uint8 bUnlock )
{
int8 i,wno,bno;
uint16 code;
uint8 *pMBData;
int16 length;
int8 leftBytes;
int8 format;
uint8 *pBytes = data;
// Lock the MB
code = FLEXCAN_get_code(pFlexCANReg->MB[iMB].CS);
length = FLEXCAN_get_length(pFlexCANReg->MB[iMB].CS);
//
format = (pFlexCANReg->MB[iMB].CS & FLEXCAN_MB_CS_IDE)? 1:0;
*id = (pFlexCANReg->MB[iMB].ID & FLEXCAN_MB_ID_EXT_MASK);
if(!format)
{
// standard ID
*id >>= FLEXCAN_MB_ID_STD_BIT_NO;
}
else
{
*id |= CAN_MSG_IDE_MASK; // flag extended ID
}
format = (pFlexCANReg->MB[iMB].CS & FLEXCAN_MB_CS_RTR)? 1:0;
if(format)
{
*id |= CAN_MSG_TYPE_MASK; // flag Remote Frame type
}
// Read message bytes
wno = (length-1)>>2;
bno = length-1;
if(wno>0)
{
//
(*(uint32*)pBytes) = pFlexCANReg->MB[iMB].WORD0;
swap_4bytes(pBytes);
bno -= 4;
pMBData = (uint8*)&pFlexCANReg->MB[iMB].WORD1+3;
}
else
{
pMBData = (uint8*)&pFlexCANReg->MB[iMB].WORD0+3;
}
for(i=0; i <= bno; i++)
{
pBytes[i+(wno<<2)] = *pMBData--;
}
// Read time stamp
*timeStamp = pFlexCANReg->MB[iMB].CS & FLEXCAN_MB_CS_TIMESTAMP_MASK ;
if(bUnlock)
{
// Unlock the MB
code = pFlexCANReg->TIMER;
}
return length;
}
/**************************************************************
PrepareRxCANMB
** Prepare a CAN MB for rx.
** NOTE:
** If using FCANMB_SET_ID or FCANMB_GET_ID, consider the condition:
** #define FCAN_ID_EXT 0x80000000 // specifies extended ID anywhere the ID is required
** #define FCAN_ID_RTR 0x40000000 // turns on the RTR bit when calling FCANMB_SET_ID (only)
** So the ID format is:
** B31 30 29 28 27 26 ... 11 10 9 8 7 6 5 4 3 2 1 0
** | | | |
** | | |------------------------------------|
** | | |--> 29 bits ID
** | |
** | |--> 1: RTR bit set, 0: RTR bit clear
** |
** |--> 1 : Extended ID, 0: Standardard ID
**************************************************************/
void FlexCAN_PrepareRxCANMB(uint16 iMB, uint32 id)
{
uint32 id2;
// Deactivate the rx MB for cpu write
pFlexCANReg->MB[iMB].CS = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_RX_INACTIVE); // write inactive code
// Write ID
id2 = id & ~(CAN_MSG_IDE_MASK | CAN_MSG_TYPE_MASK);
if(id & CAN_MSG_IDE_MASK)
{
pFlexCANReg->MB[iMB].ID = id2;
}
else
{
pFlexCANReg->MB[iMB].ID = id2<<FLEXCAN_MB_ID_STD_BIT_NO;
}
// Activate the MB for rx
pFlexCANReg->MB[iMB].CS = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_RX_EMPTY);
// flag to caller transfer is started
bMBFlags1 &= ~(1<<iMB);
}
void FlexCAN_EnableMB_Interrupt(uint16 iMB)
{
pFlexCANReg->IMASK1 |= (1<<iMB);
}
void FlexCAN_DisableMB_Interrupt(uint16 iMB)
{
pFlexCANReg->IMASK1 &= ~(1<<iMB);
}
uint8 FlexCAN_Is_Transfer_Done(uint16 iMB)
{
if(bMBFlags1 & (1<<iMB))
{
return 1;
}
return 0;
}
void FlexCAN_MB_ISR(void)
{
// Check Rx MB flags, so Rx MBs has highest priority than Tx MBs
FlexCAN_Poll_RxMBs();
// Check Tx MB flags
FlexCAN_Poll_TxMBs();
// Check Rx FIFO status and handle it
// If Rx FIFO is enabled, check FIFO flag
if(pFlexCANReg->MCR & FLEXCAN_MCR_FEN)
{
FlexCAN_Poll_RxFIFO();
}
}
void FlexCAN_Poll_RxMBs(void)
{
int16 iMB;
for(iMB = pFlexCANDrvObj->bRxMBStart; iMB <= pFlexCANDrvObj->bRxMBEnd; iMB++)
{
if(pFlexCANReg->IFLAG1 & (1<<iMB))
{
// Read the Message information
if((wrRxMailBox+1) != rdRxMailBox)
{
RxMailBox[wrRxMailBox].data_len =
FlexCAN_ReadCANMB(iMB,
(uint32*)&RxMailBox[wrRxMailBox].identifier,
(uint32*)&RxMailBox[wrRxMailBox].timestamp,
(uint8*)RxMailBox[wrRxMailBox].data,
1);
wrRxMailBox++;
if(wrRxMailBox >=MAX_RX_MAILS)
{
wrRxMailBox = 0;
}
}
// clear flag
pFlexCANReg->IFLAG1 = (1<<iMB);
bMBFlags1 |= (1<<iMB); // set flag to caller indicating this MB is done
// Call custom Rx callback to do follow up processing
FlexCAN_MB_Callback(iMB);
}
}
}
void FlexCAN_Poll_TxMBs(void)
{
int16 iMB;
for(iMB = pFlexCANDrvObj->bTxMBStart; iMB <= pFlexCANDrvObj->bTxMBEnd; iMB++)
{
if(pFlexCANReg->IFLAG1 & (1<<iMB))
{
// Read the time stamp information
if(rdTxMailBox != wrTxMailBox)
{
// if Tx MailBox not empty,do
FlexCAN_PrepareAndStartTransmit(iMB,
TxMailBox[rdTxMailBox].identifier,
TxMailBox[rdTxMailBox].priority,
(uint8*)TxMailBox[rdTxMailBox].data,
TxMailBox[rdTxMailBox].data_len,
FLEXCAN_MB_CODE_TX_ONCE // tx once code
);
rdTxMailBox++;
if(rdTxMailBox >=MAX_TX_MAILS)
{
rdTxMailBox = 0;
}
}
else
{
occurence = 0; // flag to call PrepareTransmit again
bMBFlags1 |= (1<<iMB); // set flag to caller indicating this MB is done by ISR
}
// clear flag
pFlexCANReg->IFLAG1 = (1<<iMB);
// Call custom Tx callback to do follow up processing
// such as queue another message to be transmitted
FlexCAN_MB_Callback(iMB);
}
}
}
void FlexCAN_Poll_RxFIFO(void)
{
uint16 iMatchHit;
if(pFlexCANReg->IFLAG1 & FLEXCAN_IFLAG1_BUF5I)
{
// frames are available in Rx FIFO, read it into RxFIFO queue
if((wrRxFIFOQue+1) != rdRxFIFOQue)
{
RxFIFOQue[wrRxFIFOQue].data_len =
FlexCAN_ReadCANMB(0, // MB0 is the read buffer of RxFIFO
(uint32*)&RxFIFOQue[wrRxFIFOQue].identifier,
(uint32*)&RxFIFOQue[wrRxFIFOQue].timestamp,
(uint8*)RxFIFOQue[wrRxFIFOQue].data,
0);
// read RXFIR
iMatchHit = pFlexCANReg->RXFIR & 0x1FF;
wrRxFIFOQue++;
if(wrRxFIFOQue >=MAX_RXFIFO_MAILS)
{
wrRxFIFOQue = 0;
}
}
// clear Rx FIFO flag
pFlexCANReg->IFLAG1 = FLEXCAN_IFLAG1_BUF5I;
}
// Check Rx FIFO Warning flag
if(pFlexCANReg->IFLAG1 & FLEXCAN_IFLAG1_BUF6I)
{
pFlexCANReg->IFLAG1 = FLEXCAN_IFLAG1_BUF6I;
}
// Check Rx FIFO Overflow flag
if(pFlexCANReg->IFLAG1 & FLEXCAN_IFLAG1_BUF7I)
{
// This should be error
nCANErrorCount++;
pFlexCANReg->IFLAG1 = FLEXCAN_IFLAG1_BUF7I;
// Call RxFIFO error call back
FlexCAN_RxFIFOErr_Callback();
}
}
void FlexCAN_BusOff_ISR(void)
{
pFlexCANReg->ESR1 = FLEXCAN_ESR_BOFF_INT;
}
void FlexCAN_Error_ISR(void)
{
// check error flags
uint32_t status;
status = pFlexCANReg->ESR1;
if( status & FLEXCAN_ESR_ERR_INT)
{
nCANErrorCount++;
// Call CAN error call back
FlexCAN_Err_Callback(status);
// clear the error flag
pFlexCANReg->ESR1 = status;
}
}
void FlexCAN_TxWarning_ISR(void)
{
pFlexCANReg->ESR1 = FLEXCAN_ESR_TX_WRN;
//printf("FlexCAN Transmit warning occured!\n");
}
void FlexCAN_RxWarning_ISR(void)
{
pFlexCANReg->ESR1 = FLEXCAN_ESR_RX_WRN;
//printf("FlexCAN Receive warning occured!\n");
}
void FlexCAN_Wakeup_ISR(void)
{
pFlexCANReg->ESR1 = FLEXCAN_ESR_WAK_INT; // clear wakeup interrupt
//printf("FlexCAN wakeup interrupt occurs!\n");
}
void FlexCAN_IMEU_ISR(void)
{
pFlexCANReg->ESR2 = FLEXCAN_ESR2_IMEUF;
}
void FlexCAN_LostRx_ISR(void)
{
if( pFlexCANReg->ESR2 & FLEXCAN_ESR2_LOSTRLF)
{
// Lost Rx is locked
pFlexCANReg->ESR2 = FLEXCAN_ESR2_LOSTRLF;
}
if( pFlexCANReg->ESR2 & FLEXCAN_ESR2_LOSTRMF)
{
// Lost Rx is matched
pFlexCANReg->ESR2 = FLEXCAN_ESR2_LOSTRMF;
}
//printf("FlexCAN Lost receive interrupt occurs!\n");
}
uint16 FlexCAN_CheckAbortStatus(uint16 iMB)
{
uint8 code;
// If it is still pending, just return pending status
if(!(pFlexCANReg->IFLAG1 & (1<<iMB)))
{
return (FLEXCAN_ERROR_PENDING_TX);
}
// Check CODE field to see if it is aborted or not
code = FLEXCAN_get_code(pFlexCANReg->MB[iMB].CS);
if(code == FLEXCAN_MB_CODE_TX_ABORT)
{
// Abort success
return (FLEXCAN_ERROR_SUCCESS);
}
else if(code == FLEXCAN_MB_CODE_TX_INACTIVE )
{
// MB is not aborted but transmitted instead
return (FLEXCAN_ERROR_TX_DONE);
}
// Other status
return (FLEXCAN_ERROR_TX_ERR);
}
// Callback routines
void FlexCAN_MB_Callback(uint16 iMBNo)
{
}
void FlexCAN_RxFIFOErr_Callback(void)
{
}
void FlexCAN_Err_Callback(uint32 status)
{
if(status & FLEXCAN_ESR_BIT0_ERR)
{
printf("BIT0 error occured!\n");
}
if(status & FLEXCAN_ESR_BIT1_ERR)
{
printf("BIT1 error occured!\n");
}
if(status & FLEXCAN_ESR_STF_ERR)
{
printf("Stuffing error occured!\n");
}
if(status & FLEXCAN_ESR_FRM_ERR)
{
printf("Form error occured!\n");
}
if(status & FLEXCAN_ESR_CRC_ERR)
{
printf("CRC error occured!\n");
}
if(status & FLEXCAN_ESR_ACK_ERR)
{
printf("Ack error occured!\n");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -