Part Number: TMS320F280025C
Other Parts Discussed in Thread: C2000WARE
Tool/software:
Hi everyone!
I'm here to share a problem I'm facing in dealing with canbus tx interrupt.
I'm using the F280025C launchpad which has one canbus channel CANA and two possible interrupt lines linked with it (CANINT0 and CANINT1).
I setup the peripheral and interrupt table in order to trigger:
Rx - CANINT0
Tx - CANINT1
Moreover, regarding the interface registers, I chose to use IF1 for trasmission purposes and IF2 for receiving.
I enabled both the TxIE, RxIE bitfileds and the global interrupt lines for canbus.
Concerning receiving interrupt everything works fine, trasmission always fails when i try to send a canbus message (I've been using a can analyzer as other node).
Literally it's as if nothing happens.
After that, I tried to exclude the Rx interrupt (line 0) from the code and focus on the Tx only (line 1).
By debugging the canbus registers themselves I could see a very strange thing: the trasmission line which is triggered is 0 (which is supposed to be linked to Rx from the setup).
I couldn't figure it out why.
Then, another very strange thing is that the IPEN_21 register identifies the correct message object, the TxOk bit is high and LEC one doesn't show any warnings.
In this case the tx interrupt is generated but there's no way to clean it by the usual way (IntClrPnd = 1). Indeed, the tx interrupt is entered endlessly.
Why does the Tx interrupt gets triggered just as I exclude the Rx one?
Can anyone help me out with this?.
I attach some of the code i've been writing about, hoping it's useful to catch the issue.
Let me know please :)
Elia
========================================
PIE SETUP
========================================
EALLOW;
PieVectTable.CANA0_INT = &cana_rx_isr;
PieVectTable.CANA1_INT = &cana_tx_isr;
PieCtrlRegs.PIEIER9.bit.INTx6 = 1;
PieCtrlRegs.PIEIER9.bit.INTx5 = 1;
//PieCtrlRegs.PIEIER9.bit.INTx6 = 1;
IER |= M_INT9;
EDIS;
========================================
INITIALIZATION
========================================
void InitCAN(void)
{
int16_t iMsg;
//
// Place CAN controller in init state, regardless of previous state. This
// will put controller in idle, and allow the message object RAM to be
// programmed.
//
CanaRegs.CAN_CTL.bit.Init = 1;
CanaRegs.CAN_CTL.bit.CCE = 1;
CanaRegs.CAN_CTL.bit.SWR = 1; // Software Reset (si attiva solo se Init è settato)
//
// Wait for busy bit to clear
//
while(CanaRegs.CAN_IF1CMD.bit.Busy) // c'è un trasferimento in corso tra interface register e la ram
{
}
//
// Clear the message value bit in the arbitration register. This indicates
// the message is not valid and is a "safe" condition to leave the message
// object. The same arb reg is used to program all the message objects.
//
CanaRegs.CAN_IF1CMD.bit.DIR = 1; // 0 read, 1 write : 0 legge dalla mailbox verso l'interface register, 1 viceversa
CanaRegs.CAN_IF1CMD.bit.Arb = 1; // Arbitration bits (Identifier + Dir + Xtd + MsgVal) trasferiti da IF -> MAILBOX (se write, viceversa se read)
CanaRegs.CAN_IF1CMD.bit.Control = 1; // Control bits come sopra
CanaRegs.CAN_IF1ARB.all = 0;
CanaRegs.CAN_IF1MCTL.all = 0;
CanaRegs.CAN_IF2CMD.bit.DIR = 1;
CanaRegs.CAN_IF2CMD.bit.Arb = 1;
CanaRegs.CAN_IF2CMD.bit.Control = 1;
CanaRegs.CAN_IF2ARB.all = 0;
CanaRegs.CAN_IF2MCTL.all = 0;
//
// Loop through to program all 32 message objects
//
for(iMsg = 1; iMsg <= 32; iMsg+=2)
{
//
// Wait for busy bit to clear
//
while(CanaRegs.CAN_IF1CMD.bit.Busy)
{
}
//
// Initiate programming the message object
//
CanaRegs.CAN_IF1CMD.bit.MSG_NUM = iMsg;
//
// Wait for busy bit to clear
//
while(CanaRegs.CAN_IF2CMD.bit.Busy)
{
}
//
// Initiate programming the message object
//
CanaRegs.CAN_IF2CMD.bit.MSG_NUM = iMsg + 1;
}
CanaRegs.CAN_IF1CMD.bit.DATA_A = 1;
CanaRegs.CAN_IF1CMD.bit.DATA_B = 1;
CanaRegs.CAN_IF2CMD.bit.DATA_A = 1;
CanaRegs.CAN_IF2CMD.bit.DATA_B = 1;
//
// Acknowledge any pending status interrupts.
//
volatile uint32_t discardRead = CanaRegs.CAN_ES.all; // ERROR and STATUS registers
}
========================================
CAN ENABLE
========================================
void CAN_Enable(void){
//
// Enable the CAN for operation.
//
CanaRegs.CAN_CTL.bit.DAR = 1; // Disable automatic retransmission
CanaRegs.CAN_CTL.bit.Test = 0; // Enable test mode and select external loopback
CanaRegs.CAN_TEST.bit.EXL = 0; // External Loopback
CanaRegs.CAN_CTL.bit.IE0 = 1; // Abilito interrupt
CanaRegs.CAN_GLB_INT_EN.bit.GLBINT0_EN = 1;
CanaRegs.CAN_CTL.bit.IE1 = 1;
CanaRegs.CAN_GLB_INT_EN.bit.GLBINT1_EN = 1;
CanaRegs.CAN_CTL.bit.Init = 0; // Enable the CAN for operation (0 processa i messaggi normalmente)
}
========================================
TX MAILBOX SETUP
========================================
void CAN_Mailbox_Setup_TX(uint32_t objID, uint32_t msgID, uint16_t dlc)
{
//
// Use Shadow variable for IF1CMD. IF1CMD should be written to in
// single 32-bit write.
//
union CAN_IF1CMD_REG CAN_IF1CMD_SHADOW;
//
// Wait for busy bit to clear.
//
while(CanaRegs.CAN_IF1CMD.bit.Busy)
{
}
//
// Clear and Write out the registers to program the message object.
//
CAN_IF1CMD_SHADOW.all = 0;
CanaRegs.CAN_IF1MSK.all = 0;
CanaRegs.CAN_IF1ARB.all = 0;
CanaRegs.CAN_IF1MCTL.all = 0;
//
// Set the Control, Mask, and Arb bit so that they get transferred to the
// Message object.
//
CAN_IF1CMD_SHADOW.bit.Control = 1;
CAN_IF1CMD_SHADOW.bit.Arb = 1;
CAN_IF1CMD_SHADOW.bit.Mask = 1;
CAN_IF1CMD_SHADOW.bit.DIR = 1;
CanaRegs.CAN_IF1ARB.bit.Dir = 1; // se non lo forzo ad 1 manda un messaggio vuoto (remote frame RTR)
CanaRegs.CAN_IF1MCTL.bit.TxIE = 1;
//
// Set Message ID (this example assumes 11 bit ID mask)
//
CanaRegs.CAN_IF1ARB.bit.ID = (msgID << CAN_MSG_ID_SHIFT);
CanaRegs.CAN_IF1ARB.bit.MsgVal = 1;
//
// 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.
//
CanaRegs.CAN_IF1MCTL.bit.DLC = dlc;
CanaRegs.CAN_IF1MCTL.bit.EoB = 1;
//
// Transfer data to message object RAM
//
CAN_IF1CMD_SHADOW.bit.MSG_NUM = objID;
CanaRegs.CAN_IF1CMD.all = CAN_IF1CMD_SHADOW.all;
}
========================================
TX INTERRUPT HANDLING
========================================
// Devo riuscire a farlo funzionare!
__interrupt void cana_tx_isr(void){
dbg.can_tx++;
#if 0
while(!CanaRegs.CAN_ES.bit.TxOk){
}
#endif
#if 0
if(!CanaRegs.CAN_ES.bit.TxOk){
CanaRegs.CAN_ES.bit.TxOk = 0;
GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
comando_feeder = 0;
}
#endif
if((CanaRegs.CAN_IPEN_21 && (1 << (CAN_TX_LOCK-1))) && (CanaRegs.CAN_INT.bit.INT1ID == CAN_TX_LOCK)){
GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
CanaRegs.CAN_IF1CMD.bit.ClrIntPnd = 1;
}
//volatile uint32_t status = CanaRegs.CAN_ES.all; // ERROR and STATUS registers
CanaRegs.CAN_GLB_INT_CLR.bit.INT1_FLG_CLR = 1;
PieCtrlRegs.PIEACK.bit.ACK9 = 1;
}