I am using eclipse and diab compiler to develope a bootloader code for S32R247 flash programming over CAN interface. Actually i have a problem with the reception and transmission of CAN messges, when message buffer interrupt is used.
Any time if I am sending CAN messages from the host to the bootloader then an interrupt flag going to be active, this is fine and works fine. After recognising an interrupt arrived and handled, I am reading the message out from the buffer and send a response back to the host.
Here comes the trouble! The answer what I sent back is causing the problem because it is reflected somehow to the receive messge buffer and causing interruption again. Therefore the sent message will be transmited all over and over again
do you have any ide how could I disable this reflection?
I am using to receive and transmit FlexCAN_0
- receive message to message buffer 0
- transmit message from message buffer 15
here is a snippet of code I am using to initialize the CAN interface
additionally a question would be: why I can only enable CAN_0.IMASK1.B.BUF31TO0M = 1; interrupt for all message buffers. I want to enable interrupt ! only ! for message buffer 0
void FlexCAN0_Init( void )
{
int i = 0;
/*Module enable*/
CAN_0.MCR.B.MDIS = 0;
/* Freeze ON */
CAN_0.MCR.B.FRZ = 1;
/*Source clk is oscillator clock (40MHz)*/
CAN_0.CTRL1.B.CLKSRC = 0;
/*Error correction configuration register enable*/
CAN_0.CTRL2.B.ECRWRE = 1;
/*Enable unrestricted write access to FlexCAN memory*/
CAN_0.CTRL2.B.WRMFRZ = 1;
/*Error configuration register write enable*/
CAN_0.MECR.B.ECRWRDIS = 0;
/*Disable memory error correction*/
CAN_0.MECR.B.ECCDIS = 1;
/*Keep normal operation*/
CAN_0.MECR.B.NCEFAFRZ = 0;
/*Error configuration register write disable*/
CAN_0.MECR.B.ECRWRDIS = 1;
/*Disable unrestricted write access to FlexCAN memory*/
CAN_0.CTRL2.B.WRMFRZ = 0;
/*Error correction configuration register disable*/
CAN_0.CTRL2.B.ECRWRE = 0;
/* Loop back mode Disabled */
CAN_0.CTRL1.B.LPB = 0;
/*Enable individual RX masking*/
CAN_0.MCR.B.IRMQ = 1;
/* ADDED TO EVADE SELF RECEPTION */
CAN_0.MCR.B.SRXDIS = 1;
//Sclock frequency = PE clock frequency / (PRESDIV + 1)
// Bit Rate = f_CANCLK / (PRESDIV + 1) x (PROP_SEG + PSEG1 + PSEG2 + 4)
// /*CAN bit timing - 40MHz oscillator, 100kbps bitrate,*/
// CAN_0.CTRL1.B.PRESDIV = 39;
// CAN_0.CTRL1.B.PROPSEG = 0;
// CAN_0.CTRL1.B.PSEG1 = 3;
// CAN_0.CTRL1.B.PSEG2 = 3;
// CAN_0.CTRL1.B.RJW = 3;
/*CAN bit timing - 40MHz oscillator, 500kbps bitrate,*/
CAN_0.CTRL1.B.PRESDIV = 4;
CAN_0.CTRL1.B.PROPSEG = 2;
CAN_0.CTRL1.B.PSEG1 = 5;
CAN_0.CTRL1.B.PSEG2 = 5;
CAN_0.CTRL1.B.RJW = 1;
/*CAN bit timing - 40MHz oscillator, 1000kbps bitrate,*/
// CAN_0.CTRL1.B.PRESDIV = 3;
// CAN_0.CTRL1.B.PROPSEG = 4;
// CAN_0.CTRL1.B.PSEG1 = 1;
// CAN_0.CTRL1.B.PSEG2 = 1;
// CAN_0.CTRL1.B.RJW = 0;
/*enable interrupt for MB0*/
CAN_0.IMASK1.B.BUF31TO0M = 1;
/*Clear all RX individual Mask Registers The corresponding bit in the
* filter is "don't care."*/
for(i = 0; i < 64; i++)
{
CAN_0.RXIMR[i].R = 0xFFFFFFFF;
}
/*Set all message buffers RX inactive*/
for(i = 0; i <64; i++)
{
CAN_0.MB[i].CS.R = 0x0000;
}
CAN_0.RXMGMASK.R = 0x00000001;
/* Freeze OFF */
CAN_0.MCR.B.FRZ = 0;
/*No freeze mode request*/
CAN_0.MCR.B.HALT = 0;
}
void ConfigureRXMessageBuffer(void)
{
CAN_0.MB[0].CS.B.CODE = 0x0; //MB inactive
CAN_0.MB[0].CS.B.IDE = 0;
CAN_0.MB[0].ID.R = 0; //set standard ID
CAN_0.MB[0].DATA.W[1] = 0x00000000; //data1 set (optional)
CAN_0.MB[0].DATA.W[0] = 0x00000000; //data0 set (optional)
CAN_0.MB[0].CS.B.CODE = 0x4; //MB empty - ready for receive
}
void transmitMessage(int MB, int ID, unsigned char* pbData, unsigned char bLen)
{
uint32 dwTemp;
if (CAN_0.MB[MB].CS.B.CODE != 0xC)
{
CAN_0.MB[MB].CS.B.CODE = 0x8; // MB TX inactive
CAN_0.MB[MB].CS.B.IDE = 1; // extended bit enabled
CAN_0.MB[MB].ID.R = ID; // set message STD ID
// CAN_0.MB[MB].DATA.W[0] = 0x12345678; // data0 set
// CAN_0.MB[MB].DATA.W[1] = 0x90ABCDEF; // data1 set
if (bLen >= 1)
{
CAN_0.MB[MB].DATA.W[0] = ((*pbData++) << 24); // data0 set
if (bLen >= 2)
{
CAN_0.MB[MB].DATA.W[0] += ((*pbData++) << 16);
if (bLen >= 3)
{
CAN_0.MB[MB].DATA.W[0] += ((*pbData++) << 8);
if (bLen >= 4)
{
CAN_0.MB[MB].DATA.W[0] += ((*pbData++));
if (bLen >= 5)
{
CAN_0.MB[MB].DATA.W[1] = ((*pbData++) << 24); // data1 set
if (bLen >= 6)
{
CAN_0.MB[MB].DATA.W[1] += ((*pbData++) << 16);
if (bLen >= 7)
{
CAN_0.MB[MB].DATA.W[1] += ((*pbData++) << 8);
if (bLen == 8)
{
CAN_0.MB[MB].DATA.W[1] += ((*pbData));
}
}
}
}
}
}
}
}
CAN_0.MB[MB].CS.B.DLC = bLen; // message length max 8 bytes
CAN_0.MB[MB].CS.B.RTR = 0; // remote frame disable
CAN_0.MB[MB].CS.B.SRR = 1; // used with STD_ID
CAN_0.MB[MB].CS.B.CODE = 0xC; // MB once transmit data
dwTemp = CAN_0.TIMER.R;
//mandatory to wait until the message is not shifted out completely
//do{
// kickWDT();
//}while(CAN_0.ESR1.B.IDLE == 0);
}
}
int frameworkCheckInterrupt( void )
{
uint32 dwTemp;
//check interrupt flag and sign it if something is received
if (CAN_0.IFLAG1.R & 0x00000001)
{
CAN_0.MB[0].ID.R = 0;
fw.status = RECEIVED;
dwTemp = CAN_0.IFLAG1.R;
CAN_0.IFLAG1.R = dwTemp;
/* mandatory - read control/status word - lock the MB */
dwTemp = CAN_0.MB[0].CS.R;
canReadBuffer(fw.fBuffer);
fw.task = fw.fBuffer[0];
//used when user cmd is used as task
fw.subTask = fw.fBuffer[1];
}
else
fw.status = IDLE;
return fw.status;
}
Hi,
Yes somehow the self reception is active and I cannot switch it off. Therefore I just made a workaround and ignoring the self received messages, differentiating based on the can id field.
I cannot really debug it because I'm downloading my bootloader over an other bootloader, what needs to trigger external wdt and so on.
It really seems that my transmitt is also causing interrupt in that message buffer where from I sent data. I'm using 15th MB to transmit data and any time I'm transmitting something the interrupt flag going to be 1 on MB 15.
anyway thanks your feedback,
G
I have the same issue, somehow the self reception is active and I cannot switch it off. I try with:
base->MCR |= CAN_MCR_SRXDIS(1);
I have noticed that the instruction takes effect only if I debug the program step by step at the point of the instruction execution of self reception off.
Hi,
it looks the Self reception is still enabled. Check with the debugger that the MCR[SRXDIS] is really set.
The CAN_0.IMASK1.B.BUF31TO0M = 1; and CAN_0.IMASK1.R = 1; do the same; MB0 interrupt is only enabled.
BR, Petr