Not applicable
May 20, 2014
06:21 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
May 20, 2014
06:21 AM
Hello,
I try to find a easy solution for determining the interrupt source of the MCAN module of an XMC4500. The module has 8 Interrupt lines to which 3x4 Node Interrupt and 64x2 message object Interrupts (total 140 sources) can be connected. But I havent found a register which tells me what was the cause for the Interrupt. There are a lot of registers (MSPND[0..7], MCR.MPSEL, MOIPR[0-63] and MOSTAT[0..63] alone for the message Objects) but if I have to do the complex calculation (searching MSPND[0..7] which is dependent to the interrupt Line (0..7) and MCR.MPSEL) to extract the message Object which was the cause for the interrupt I can't respond very quickly to the interrupt. And to configure one interrupt line for one source is not really possible because 8 interrupt lines for 3 CAN-buses is not enough by far.
Can anybody post a solution for determining the source?
Thanks in advance,
best regards
Mario
I try to find a easy solution for determining the interrupt source of the MCAN module of an XMC4500. The module has 8 Interrupt lines to which 3x4 Node Interrupt and 64x2 message object Interrupts (total 140 sources) can be connected. But I havent found a register which tells me what was the cause for the Interrupt. There are a lot of registers (MSPND[0..7], MCR.MPSEL, MOIPR[0-63] and MOSTAT[0..63] alone for the message Objects) but if I have to do the complex calculation (searching MSPND[0..7] which is dependent to the interrupt Line (0..7) and MCR.MPSEL) to extract the message Object which was the cause for the interrupt I can't respond very quickly to the interrupt. And to configure one interrupt line for one source is not really possible because 8 interrupt lines for 3 CAN-buses is not enough by far.
Can anybody post a solution for determining the source?
Thanks in advance,
best regards
Mario
- Tags:
- IFX
5 Replies
May 20, 2014
11:38 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
May 20, 2014
11:38 PM
Hi MarioW,
Step 1: Determine the IRQ number
- Set a break point at your CAN interrupt function
- When the software breaks, check on the ICSR (Interrupt Control and State register)
Example:
If ICSR.VECTACTIVE = 0x05C = 92
Therefore IRQ number = 92 - 16 = 76
So IRQ76 correspond to CAN_SR00.
Step 2: Check DAVE3 Resource Mapping Information
- Click on the "Resource Mapping Information" icon >> Signal Assignment tab. (See picture below)
- Run your mouse pointer to the "Interrupt Node" which show you the IRQ number = 76. This simply means that this node is assigned to IRQ76 or CAN SR00 and the corresponding Interrupt function is Node_B_ISR.
- Then run your mouse pointer to the Logical message object correspond to the IRQ number 76. For this case is "LM01 Receive Interrupt". You shall see that Message Object 0 is being assigned for received interrupt.
Step 3: Check Message Object Transmit and Receive status within interrupt function
- Now you have a clear picture regarding your interrupt resources and mapping. Such that Message Object 0 is tasked for receive interrupt which is channeled to Interrupt function Node_B_ISR.
- There might be cases when many message objects transmit or receive are being shared to the same Interrupt function Node_B_ISR, hence you have to use the software to check the Message Object status register and clear the status as shown below.
Example:
void Node_B_ISR(void)
{
if (CAN_MO0->MOSTAT & 0x00000001) // Check RXPND (Receive Pending)
{
// Message Object 00 Receive Interrupt
CAN_MO0->MOCTR &= 0x00000001; //Clear RXPND
}
}
Step 1: Determine the IRQ number
- Set a break point at your CAN interrupt function
- When the software breaks, check on the ICSR (Interrupt Control and State register)
Example:
If ICSR.VECTACTIVE = 0x05C = 92
Therefore IRQ number = 92 - 16 = 76
So IRQ76 correspond to CAN_SR00.
Step 2: Check DAVE3 Resource Mapping Information
- Click on the "Resource Mapping Information" icon >> Signal Assignment tab. (See picture below)
- Run your mouse pointer to the "Interrupt Node" which show you the IRQ number = 76. This simply means that this node is assigned to IRQ76 or CAN SR00 and the corresponding Interrupt function is Node_B_ISR.
- Then run your mouse pointer to the Logical message object correspond to the IRQ number 76. For this case is "LM01 Receive Interrupt". You shall see that Message Object 0 is being assigned for received interrupt.
Step 3: Check Message Object Transmit and Receive status within interrupt function
- Now you have a clear picture regarding your interrupt resources and mapping. Such that Message Object 0 is tasked for receive interrupt which is channeled to Interrupt function Node_B_ISR.
- There might be cases when many message objects transmit or receive are being shared to the same Interrupt function Node_B_ISR, hence you have to use the software to check the Message Object status register and clear the status as shown below.
Example:
void Node_B_ISR(void)
{
if (CAN_MO0->MOSTAT & 0x00000001) // Check RXPND (Receive Pending)
{
// Message Object 00 Receive Interrupt
CAN_MO0->MOCTR &= 0x00000001; //Clear RXPND
}
}
Not applicable
May 21, 2014
06:08 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
May 21, 2014
06:08 AM
Hi Travis,
thanks for your detailed answer!
The goal for my question was mainly your Step 3, the steps before are fortunately fixed (it is not a interrupt handler handling the requests of all peripheral modules). Moreover I do not use Dave at all, I write bare C/C++ code.
I am writing a generic interrupt handler for an application which handles the TX/RX Interrupts for 0..63 Message objects.
My actual solution is to set the Message pending Registers (MSPND[0..7]/MSID[0..7] in the following way:
MCR.MPSEL = 0 -> MOIPR.TXINP/RXINP (Interrupt request line 0..7 of MCAN0) have no influence on MSPND
MOIPR.MPN Bits 0..5 are for the message object index
MOIPR.MPN Bits 6..7 is the CAN node index the message object is assigned to
MSIMASK = all bits set
-> within the interrupt I can read the message object index from MSPND[0,1] (MSID[0,1] for node 0 and so on.
-> The only thing the handler must determine is the type of the interrupt (TX/RX) to handle it...
Message Objects with no interrupt enabled set the Bits 6..7 in MOIPR.MPN to 0b11 -> CAN node index 3 (not existing, MSPND[6..7]/MSID[6..7]) so that they do not disturb the MSPND[0..5]/MSID[0..5] registers.
If there is a better solution for this, I am looking forward to see your ideas...
Best regards,
Mario
thanks for your detailed answer!
The goal for my question was mainly your Step 3, the steps before are fortunately fixed (it is not a interrupt handler handling the requests of all peripheral modules). Moreover I do not use Dave at all, I write bare C/C++ code.
I am writing a generic interrupt handler for an application which handles the TX/RX Interrupts for 0..63 Message objects.
My actual solution is to set the Message pending Registers (MSPND[0..7]/MSID[0..7] in the following way:
MCR.MPSEL = 0 -> MOIPR.TXINP/RXINP (Interrupt request line 0..7 of MCAN0) have no influence on MSPND
MOIPR.MPN Bits 0..5 are for the message object index
MOIPR.MPN Bits 6..7 is the CAN node index the message object is assigned to
MSIMASK = all bits set
-> within the interrupt I can read the message object index from MSPND[0,1] (MSID[0,1] for node 0 and so on.
-> The only thing the handler must determine is the type of the interrupt (TX/RX) to handle it...
Message Objects with no interrupt enabled set the Bits 6..7 in MOIPR.MPN to 0b11 -> CAN node index 3 (not existing, MSPND[6..7]/MSID[6..7]) so that they do not disturb the MSPND[0..5]/MSID[0..5] registers.
If there is a better solution for this, I am looking forward to see your ideas...
Best regards,
Mario
May 23, 2014
02:48 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
May 23, 2014
02:48 AM
MarioW wrote:
Hi Travis,
thanks for your detailed answer!
The goal for my question was mainly your Step 3, the steps before are fortunately fixed (it is not a interrupt handler handling the requests of all peripheral modules). Moreover I do not use Dave at all, I write bare C/C++ code.
I am writing a generic interrupt handler for an application which handles the TX/RX Interrupts for 0..63 Message objects.
My actual solution is to set the Message pending Registers (MSPND[0..7]/MSID[0..7] in the following way:
MCR.MPSEL = 0 -> MOIPR.TXINP/RXINP (Interrupt request line 0..7 of MCAN0) have no influence on MSPND
MOIPR.MPN Bits 0..5 are for the message object index
MOIPR.MPN Bits 6..7 is the CAN node index the message object is assigned to
MSIMASK = all bits set
-> within the interrupt I can read the message object index from MSPND[0,1] (MSID[0,1] for node 0 and so on.
-> The only thing the handler must determine is the type of the interrupt (TX/RX) to handle it...
Message Objects with no interrupt enabled set the Bits 6..7 in MOIPR.MPN to 0b11 -> CAN node index 3 (not existing, MSPND[6..7]/MSID[6..7]) so that they do not disturb the MSPND[0..5]/MSID[0..5] registers.
If there is a better solution for this, I am looking forward to see your ideas...
Best regards,
Mario
Hi Mario,
This is an interrupt routine which I channelled all the Message Objects Tx/Rx to a single Interrupt Request line.
void INTERRUPT (CAN_SRN0INT) CAN_viSRN0(void)
{
// USER CODE BEGIN (SRN0,2)
// USER CODE END
CAN_MSIMASK.U = 0x00000007; // set message index mask register
while (CAN_MSID0.U != 0x00000020)
{
switch(CAN_MSID0.U){
case 0: // message object 0 interrupt
if(CAN_MOSTAT0.B.RXPND) // if message object 0 receive interrupt
{
if(CAN_MOSTAT0.B.NEWDAT) // if NEWDAT is set
{
if (CAN_MOSTAT0.B.MSGLST) // if MSGLST is set
{
// Indicates that the CAN controller has stored a new
// message into this object, while NEWDAT was still set,
// ie. the previously stored message is lost.
CAN_MOCTR0.U = CAN_MOCTRm_CTR_RESMSGLST_MASK; // reset MSGLST
// USER CODE BEGIN (SRN0_OBJ0,1)
// USER CODE END
}
else
{
// The CAN controller has stored a new message
// into this object.
// USER CODE BEGIN (SRN0_OBJ0,2)
// USER CODE END
}
CAN_MOCTR0.U = CAN_MOCTRm_CTR_RESNEWDAT_MASK; // reset NEWDAT
}
CAN_MOCTR0.U = CAN_MOCTRm_CTR_RESRXPND_MASK; // reset RXPND
} // End of RXPND0
if(CAN_MOSTAT0.B.TXPND) // if message object 0 transmit interrupt
{
// The CAN controller has send a remote frame
// with identifier and control of this object.
// USER CODE BEGIN (SRN0_OBJ0,6)
// USER CODE END
CAN_MOCTR0.U = CAN_MOCTRm_CTR_RESTXPND_MASK; // reset TXPND
} // End of TXPND0
CAN_MSPND0.U = ~0x00000001; // reset PND bit
// USER CODE BEGIN (SRN0_OBJ0,7)
// USER CODE END
break;
case 1: // message object 1 interrupt
if(CAN_MOSTAT1.B.RXPND) // if message object 1 receive interrupt
{
if(CAN_MOSTAT1.B.NEWDAT) // if NEWDAT is set
{
if (CAN_MOSTAT1.B.MSGLST) // if MSGLST is set
{
// Indicates that the CAN controller has stored a new
// message into this object, while NEWDAT was still set,
// ie. the previously stored message is lost.
CAN_MOCTR1.U = CAN_MOCTRm_CTR_RESMSGLST_MASK; // reset MSGLST
// USER CODE BEGIN (SRN0_OBJ1,1)
// USER CODE END
}
else
{
// The CAN controller has stored a new message
// into this object.
// USER CODE BEGIN (SRN0_OBJ1,2)
// USER CODE END
}
CAN_MOCTR1.U = CAN_MOCTRm_CTR_RESNEWDAT_MASK; // reset NEWDAT
}
CAN_MOCTR1.U = CAN_MOCTRm_CTR_RESRXPND_MASK; // reset RXPND
} // End of RXPND1
if(CAN_MOSTAT1.B.TXPND) // if message object 1 transmit interrupt
{
// The CAN controller has send a remote frame
// with identifier and control of this object.
// USER CODE BEGIN (SRN0_OBJ1,6)
// USER CODE END
CAN_MOCTR1.U = CAN_MOCTRm_CTR_RESTXPND_MASK; // reset TXPND
} // End of TXPND1
CAN_MSPND0.U = ~0x00000002; // reset PND bit
// USER CODE BEGIN (SRN0_OBJ1,7)
// USER CODE END
break;
case 2: // message object 2 interrupt
if(CAN_MOSTAT2.B.RXPND) // if message object 2 receive interrupt
{
if(CAN_MOSTAT2.B.NEWDAT) // if NEWDAT is set
{
if (CAN_MOSTAT2.B.MSGLST) // if MSGLST is set
{
// Indicates that the CAN controller has stored a new
// message into this object, while NEWDAT was still set,
// ie. the previously stored message is lost.
CAN_MOCTR2.U = CAN_MOCTRm_CTR_RESMSGLST_MASK; // reset MSGLST
// USER CODE BEGIN (SRN0_OBJ2,1)
// USER CODE END
}
else
{
// The CAN controller has stored a new message
// into this object.
// USER CODE BEGIN (SRN0_OBJ2,2)
// USER CODE END
}
CAN_MOCTR2.U = CAN_MOCTRm_CTR_RESNEWDAT_MASK; // reset NEWDAT
}
CAN_MOCTR2.U = CAN_MOCTRm_CTR_RESRXPND_MASK; // reset RXPND
} // End of RXPND2
if(CAN_MOSTAT2.B.TXPND) // if message object 2 transmit interrupt
{
// The CAN controller has send a remote frame
// with identifier and control of this object.
// USER CODE BEGIN (SRN0_OBJ2,6)
// USER CODE END
CAN_MOCTR2.U = CAN_MOCTRm_CTR_RESTXPND_MASK; // reset TXPND
} // End of TXPND2
CAN_MSPND0.U = ~0x00000004; // reset PND bit
// USER CODE BEGIN (SRN0_OBJ2,7)
// USER CODE END
break;
default:
// USER CODE BEGIN (SRN0,3)
// USER CODE END
break;
} // end switch
// USER CODE BEGIN (SRN0,7)
// USER CODE END
} // end of while CAN_MSID
// USER CODE BEGIN (SRN0,15)
// USER CODE END
} // End of function CAN_viSRN0
Not applicable
May 27, 2014
04:04 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
May 27, 2014
04:04 AM
Hi Travis,
thanks again for your detailed answer! I have thougt I have overseen some possibility to do the task of handling my interrupt very efficiently, but when I look at your code I see that there is no way to do this without a lot of code and wasting a lot of time within the interrupt... Because of this the response to a message with my generic handler will take a while, perhaps I have to use seperate Interrupt lines (if 8 are enough) for the time critical handlers...
Best regards,
Mario
thanks again for your detailed answer! I have thougt I have overseen some possibility to do the task of handling my interrupt very efficiently, but when I look at your code I see that there is no way to do this without a lot of code and wasting a lot of time within the interrupt... Because of this the response to a message with my generic handler will take a while, perhaps I have to use seperate Interrupt lines (if 8 are enough) for the time critical handlers...
Best regards,
Mario
May 27, 2014
08:19 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
May 27, 2014
08:19 PM
MarioW wrote:
Hi Travis,
thanks again for your detailed answer! I have thougt I have overseen some possibility to do the task of handling my interrupt very efficiently, but when I look at your code I see that there is no way to do this without a lot of code and wasting a lot of time within the interrupt... Because of this the response to a message with my generic handler will take a while, perhaps I have to use seperate Interrupt lines (if 8 are enough) for the time critical handlers...
Best regards,
Mario
Hi Mario,
Yes, there are 8 Interrupt Request line which you may want to divide them among your message boxes Tx/Rx to make it more systematic or efficient.
Thanks for the very nice sharing and good luck to you.
Best Regards
Travis