📄 can.c
字号:
return (FLEXCAN_ERROR_SUCCESS);
}
void FlexCAN_Start(void)
{
// De-assert Freeze Mode
pFlexCANReg->MCR &= ~(FLEXCAN_MCR_HALT);
// Wait till exit of freeze mode
while( pFlexCANReg->MCR & FLEXCAN_MCR_FRZ_ACK)
{
}
// Wait till ready
while(pFlexCANReg->MCR & FLEXCAN_MCR_NOT_RDY)
{
}
}
void FlexCAN_Stop(void)
{
// Assert Freeze Mode
pFlexCANReg->MCR |= (FLEXCAN_MCR_HALT);
// Wait till enter freeze mode
while(!(pFlexCANReg->MCR & FLEXCAN_MCR_FRZ_ACK))
{
}
}
int16 FlexCAN_ConfigureRxFIFO_IDTable(uint32 idList[],uint16 idListNo)
{
uint16 nTotalValidTabIDNo; // total # of Rx FIFO table RxIDs
uint16 nIDTab;
uint8 bIDAM;
uint8 bIsExtID,bIsRTR;
uint32 id;
uint32 *pIDTabElement;
int16 i,j;
uint8 bFreezeMode;
int16 status = FLEXCAN_ERROR_SUCCESS;
// Calculate the total # of valid table elements
bIDAM = (pFlexCANReg->MCR & FLEXCAN_MCR_IDAM_MASK)>>FLEXCAN_MCR_IDAM_BIT_NO;
if(bIDAM == 3)
{
// all frames will be rejected, so just return without configuration
status = FLEXCAN_ERROR_SUCCESS;
return (status);
}
nTotalValidTabIDNo = (pFlexCANReg->CTRL2 & FLEXCAN_CTRL2_RFFN)>> FLEXCAN_CTRL2_RFFN_BIT_NO;
nTotalValidTabIDNo = ((nTotalValidTabIDNo+1)<<3) * (1<<bIDAM);
if((idListNo) > nTotalValidTabIDNo)
{
status = (FLEXCAN_ERROR_PARAM_OUT_OF_RANGE);
return (status);
}
nIDTab = min(idListNo, nTotalValidTabIDNo);
// Calculate the address of the starting ID Table Element corresponding startIDTabNo which bases 0
pIDTabElement = (uint32*)&pFlexCANReg->MB[6]; // ID Filter Table Elements starts from MB6
// Make sure FlexCAN is in Freeze mode before writing Filter tables
if(!(pFlexCANReg->MCR & FLEXCAN_MCR_HALT))
{
FlexCAN_Stop(); // halt FlexCAN safely
bFreezeMode = 0;
}
else
{
bFreezeMode = 1;
}
// Configure the RX FIFO ID filter Tab elements
for(i = 0; i < nIDTab; )
{
// Get IDE bit and RTR bit
id = idList[i] & ~(CAN_MSG_IDE_MASK |CAN_MSG_TYPE_MASK);
bIsExtID = (idList[i] & CAN_MSG_IDE_MASK)>>CAN_MSG_IDE_BIT_NO;
bIsRTR = (idList[i] & CAN_MSG_TYPE_MASK)>>CAN_MSG_TYPE_BIT_NO;
if(bIDAM==1)
{
// Format B two IDs
*pIDTabElement = ((id & 0x03fff)<< (16+ (1-bIsExtID)*3)) | (bIsExtID<<30) | (bIsRTR<<31); // RXIDB_0
i++;
if(i < nIDTab)
{
id = idList[i] & ~(CAN_MSG_IDE_MASK |CAN_MSG_TYPE_MASK);
bIsExtID = (idList[i] & CAN_MSG_IDE_MASK)>>CAN_MSG_IDE_BIT_NO;
bIsRTR = (idList[i] & CAN_MSG_TYPE_MASK)>>CAN_MSG_TYPE_BIT_NO;
*pIDTabElement |= ((id & 0x03fff)<< ((1-bIsExtID)*3)) | (bIsExtID<<14) | (bIsRTR<<15); // RXIDB_1
i++;
}
}
else if (bIDAM==2)
{
// Format C
j = 0;
*pIDTabElement = (id & 0x00ff) << (24-(j<<3)); // RXIDC_0
i++;j++;
do{
if(i < nIDTab)
{
id = idList[i] & ~(CAN_MSG_IDE_MASK |CAN_MSG_TYPE_MASK);
bIsExtID = (idList[i] & CAN_MSG_IDE_MASK)>>CAN_MSG_IDE_BIT_NO;
bIsRTR = (idList[i] & CAN_MSG_TYPE_MASK)>>CAN_MSG_TYPE_BIT_NO;
*pIDTabElement |= ((id & 0x00ff) << (24-(j<<3))); // RXIDC_1 .. RXIDC_3
j++; i++;
}
else
{
break;
}
}while(j<3);
}
else if (!bIDAM)
{
if(bIsExtID)
{ // Format A with extended ID
*pIDTabElement = (id<<1) | (bIsExtID<<30) | (bIsRTR<<31); // single ID acceptance codes
}
else
{ // Format A with standard ID
*pIDTabElement = (id<<19) | (bIsRTR<<31); // single ID acceptance codes RXIDA
}
i++;
}
pIDTabElement++; // advance to the next ID table element
}
// Enable Rx FIFO interrupt
// pFlexCANReg->IMASK1 |= FLEXCAN_IFLAG1_BUF5I;
end:
// Restore FlexCAN operation mode
if(!bFreezeMode)
{
FlexCAN_Start();
}
return (status);
}
int16 FlexCAN_ConfigureRxMBMask(uint16 iMB,uint32 mask)
{
uint8 bFreezeMode;
if(iMB > NUMBER_OF_MB)
{
return (FLEXCAN_ERROR_PARAM_OUT_OF_RANGE);
}
// Make sure FlexCAN is in Freeze mode
if(!(pFlexCANReg->MCR & FLEXCAN_MCR_HALT))
{
FlexCAN_Stop(); // halt FlexCAN safely
bFreezeMode = 0;
}
else
{
bFreezeMode = 1;
}
// Check if individual masking is enabled
if(pFlexCANReg->MCR & FLEXCAN_MCR_IRMQ)
{
// individual masks
pFlexCANReg->RXIMR[iMB] = mask;
}
else
{ // Legacy support with global masks
if(iMB == 14)
{
pFlexCANReg->RX14MASK = mask;
}
else if (iMB == 15)
{
pFlexCANReg->RX15MASK = mask;
}
else
{
pFlexCANReg->RXMGMASK = mask;
}
}
// Restore FlexCAN operation mode
if(!bFreezeMode)
{
FlexCAN_Start();
}
return (FLEXCAN_ERROR_SUCCESS);
}
int16 FlexCAN_ConfigureRxFIFOFilterTabElementMask(uint16 iTabElement,uint32 mask)
{
uint8 bFreezeMode;
uint8 bIDAM;
uint16 nTotalValidTabNo;
bIDAM = (pFlexCANReg->MCR & FLEXCAN_MCR_IDAM_MASK)>>FLEXCAN_MCR_IDAM_BIT_NO;
nTotalValidTabNo = (pFlexCANReg->CTRL2 & FLEXCAN_CTRL2_RFFN)>> FLEXCAN_CTRL2_RFFN_BIT_NO;
nTotalValidTabNo = ((nTotalValidTabNo+1)<<3);
if(iTabElement > nTotalValidTabNo)
{
return (FLEXCAN_ERROR_PARAM_OUT_OF_RANGE);
}
// Make sure FlexCAN is in Freeze mode
if(!(pFlexCANReg->MCR & FLEXCAN_MCR_HALT))
{
FlexCAN_Stop(); // halt FlexCAN safely
bFreezeMode = 0;
}
else
{
bFreezeMode = 1;
}
// Configure Rx FIFO table element filter
// Check if individual masking is enabled
if(pFlexCANReg->MCR & FLEXCAN_MCR_IRMQ)
{
// individual masks
pFlexCANReg->RXIMR[iTabElement] = mask; // similar to MB RX IMR
}
else
{ // Legacy support with global masks
pFlexCANReg->RXFGMASK = mask;
}
// Restore FlexCAN operation mode
if(!bFreezeMode)
{
FlexCAN_Start();
}
return (FLEXCAN_ERROR_SUCCESS);
}
int16 FlexCAN_ConfigureRxFIFOGlobalMask(uint32 mask)
{
uint8 bFreezeMode;
// 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;
}
pFlexCANReg->RXFGMASK = mask;
// Restore FlexCAN operation mode
if(!bFreezeMode)
{
FlexCAN_Start();
}
return (FLEXCAN_ERROR_SUCCESS);
}
void FlexCAN_Write(HANDLE h, uint32 msgID, uint8 prio,uint8 bBytes[], int8 iNoBytes)
{
int16 i;
if((wrTxMailBox+1) == rdTxMailBox)
{
// if queue full, return
return;
}
TxMailBox[wrTxMailBox].identifier = msgID;
TxMailBox[wrTxMailBox].priority = prio;
TxMailBox[wrTxMailBox].data_len = iNoBytes;
for(i = 0; i < iNoBytes; i++)
{
TxMailBox[wrTxMailBox].data[i] = bBytes[i];
}
//
wrTxMailBox++;
if(wrTxMailBox >=MAX_TX_MAILS)
{
wrTxMailBox = 0;
}
// Prepare transmit for the first time
if(!occurence)
{
occurence = 1;
FlexCAN_PrepareAndStartTransmit(pFlexCANDrvObj->bTxMBStart,
TxMailBox[rdTxMailBox].identifier,
TxMailBox[rdTxMailBox].priority,
(uint8*)TxMailBox[rdTxMailBox].data,
TxMailBox[rdTxMailBox].data_len,
FLEXCAN_MB_CODE_TX_ONCE // tx once
);
rdTxMailBox++;
if(rdTxMailBox >=MAX_TX_MAILS)
{
rdTxMailBox = 0;
}
}
}
int16 FlexCAN_Read(HANDLE h, int16 iMailBoxQue, uint32 *id, uint8 data[])
{
int16 i;
int16 noBytes = 0;
if(rdRxMailBox == wrRxMailBox)
{
// if queue empty, return
return (noBytes);
}
*id = RxMailBox[rdRxMailBox].identifier;
noBytes = RxMailBox[rdRxMailBox].data_len;
for(i = 0; i < noBytes; i++)
{
data[i] = RxMailBox[rdRxMailBox].data[i];
}
rdRxMailBox++;
if(rdRxMailBox >=MAX_RX_MAILS)
{
rdRxMailBox = 0;
}
return (noBytes);
}
int16 FlexCAN_Read_RxFIFOQueue(HANDLE h, uint32 *id, uint8 data[])
{
int16 i;
int16 noBytes = 0;
if(rdRxFIFOQue == wrRxFIFOQue)
{
// if queue empty, return
return (noBytes);
}
*id = RxFIFOQue[rdRxFIFOQue].identifier;
noBytes = RxFIFOQue[rdRxFIFOQue].data_len;
for(i = 0; i < noBytes; i++)
{
data[i] = RxFIFOQue[rdRxFIFOQue].data[i];
}
rdRxFIFOQue++;
if(rdRxFIFOQue >=MAX_RXFIFO_MAILS)
{
rdRxFIFOQue = 0;
}
return (noBytes);
}
void FlexCAN_PrepareTransmit(uint16 iTxMBNo,uint32 msgID, uint8 prio,uint8 bBytes[], int8 iNoBytes)
{
int16 i,wno,bno;
uint32 word[2] = {0, 0};
if(iTxMBNo >= NUMBER_OF_MB || iNoBytes >8)
{
return; // out of range
}
// convert data bytes to words
wno = (iNoBytes-1)>>2;
bno = (iNoBytes-1)%4;
if(wno >0)
{
word[0] = ((bBytes[0]<<24) | (bBytes[1]<<16) | (bBytes[2]<< 8) | bBytes[3]);
}
for(i=0;i<=bno;i++)
{
word[wno] |= bBytes[(wno<<2)+i] << (24-(i<<3));
}
// Get IDE bit and RTR bit
wno = (msgID & CAN_MSG_IDE_MASK)>>CAN_MSG_IDE_BIT_NO;
bno = (msgID & CAN_MSG_TYPE_MASK)>>CAN_MSG_TYPE_BIT_NO;
// Get ID bit no
i = wno? 0: FLEXCAN_MB_ID_STD_BIT_NO;
// Follow 4 steps for Transmit Process
pFlexCANReg->MB[iTxMBNo].CS = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE) // write inactive code
| (wno<<FLEXCAN_MB_CS_IDE_BIT_NO)
| (bno<<FLEXCAN_MB_CS_RTR_BIT_NO)
| FLEXCAN_MB_CS_LENGTH(iNoBytes) // can write size here
;
pFlexCANReg->MB[iTxMBNo].ID = (prio << FLEXCAN_MB_ID_PRIO_BIT_NO) | ((msgID & ~(CAN_MSG_IDE_MASK|CAN_MSG_TYPE_MASK))<<i);
pFlexCANReg->MB[iTxMBNo].WORD0 = word[0];
pFlexCANReg->MB[iTxMBNo].WORD1 = word[1];
// do not start transmit
}
void FlexCAN_PrepareAndStartTransmit(uint16 iTxMBNo,uint32 msgID, uint8 prio,uint8 bBytes[], int8 iNoBytes, uint8 txCode)
{
int16 i,wno,bno;
uint32 word[2] = {0, 0};
if(iTxMBNo >= NUMBER_OF_MB || iNoBytes >8)
{
return; // out of range
}
// Enable tx MB interrupt
//pFlexCANReg->IMASK1 |= (1<<iTxMBNo);
// Flag transfer starts
bMBFlags1 &= ~(1<<iTxMBNo);
//
FlexCAN_PrepareTransmit(iTxMBNo,msgID,prio, bBytes,iNoBytes);
// Start transmit with specified tx code
pFlexCANReg->MB[iTxMBNo].CS = (pFlexCANReg->MB[iTxMBNo].CS & ~(FLEXCAN_MB_CS_CODE_MASK)) | FLEXCAN_MB_CS_CODE(txCode) // write activate code
| FLEXCAN_MB_CS_LENGTH(iNoBytes);
}
void FlexCAN_WriteCode(uint16 iTxMBNo, uint8 txrxCode)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -