CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

CAN message interrupts stop after first interrupt serviced
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
bryant@balancebitsconsult



Joined: 21 Nov 2023
Posts: 38

View user's profile Send private message

PostPosted: Tue May 21, 2024 6:17 pm     Reply with quote

here's what I have so far

Code:

#include <main_can_sand.h>
#include <stdint.h>

#define CAN_PWR_EN  PIN_D9    // Power PIN to turn on CAN to the MCU

/*************************************
 * CAN1 #defines set for the can-pic24_dsPIC33.c driver
 *************************************/
#define CAN_CLOCK_DIVISOR 2            // Sets the CAN clock divisor from the system clock can be 1 or 2, default is 2.
#define CAN_BAUD_RATE 500000           // Sets CAN1 baud rate, default is 125000.
#define CAN_DEFAULT_SAMPLE_POINT 875   // Sets sample point, default is 875 for 87.5% of the bit time

/*************************************
 * *QUIRK* - CAN_TX_BUFFERS + CAN_RX_BUFFERS must equal 4, 6, 8, 12, 16, 24 or 32.
 *************************************/
#define CAN_TX_BUFFERS 8  // max 8
#define CAN_RX_BUFFERS 16  // max 32

#define CAN1_RXD  PIN_D10
#define CAN1_TXD  PIN_D0

#pin_select C1TX = CAN1_TXD
#pin_select C1RX = CAN1_RXD

/*************************************
 * CAN2 #defines set for the can-pic24_dsPIC33.c driver
 *************************************/
#define USE_CAN2_PERIPHERAL   TRUE
#define CAN2_CLOCK_DIVISOR 2            // Sets the CAN clock divisor from the system clock can be 1 or 2, default is 2.
#define CAN2_BAUD_RATE 500000
#define CAN2_DEFAULT_SAMPLE_POINT 875   // Sets sample point, default is 875 for 87.5% of the bit time

/*************************************
 * *QUIRK* - CAN2_TX_BUFFERS + CAN2_RX_BUFFERS must equal 4, 6, 8, 12, 16, 24 or 32.
 *************************************/
#define CAN2_TX_BUFFERS 8  // max 8
#define CAN2_RX_BUFFERS 16  // max 32

#define CAN2_RXD  PIN_D8
#define CAN2_TXD  PIN_D7

#pin_select C2TX = CAN2_TXD
#pin_select C2RX = CAN2_RXD


#include <can-pic24_dsPIC33.h>
#include <can-pic24_dsPIC33.c>  // see the .h in the canbus.h file


void clear_everything()
{

   int16* C1INTF = (int16*)0x040A;
   int16* C1INTE = (int16*)0x040C;
   int16* C1EC = (int16*)0x040E;
   int16* IEC2 = (int16*)0x0824;
   
   uint16_t intval,inte,ec,iec;
   
   intval=*C1INTF;
   inte=*C1INTE;
   ec=*C1EC;
   iec=*IEC2;
   fprintf(RS232_U1,"C1INTF=%X C1INTE=%X C1EC=%X IEC=%X\r\n",intval,inte,ec,iec);
 
   output_toggle(PIN_D12);    // Toggle output pin D12 (red LED)
   delay_ms(100);
   output_toggle(PIN_D12);    // Toggle output pin D12 (red LED)

   if (intval>1) {
     *C1INTF = 0x00;
     intval=*C1INTF;
     fprintf(RS232_U1,"Reset and running..\r\n" );
   }
   else
   {
      fprintf(RS232_U1,"Called, but C1NTF is 0..\r\n" );
   }
   
   fprintf(RS232_U1,"C1INTF=%X C1INTE=%X C1EC=%X IEC=%X\r\n",intval,inte,ec,iec);
   return;
}


#INT_CAN1
void can1_isr(void)
{

   if ( can_interrupt_active( CAN_INTERRUPT_ERR ) )
   {
      fprintf(RS232_U1,"...Handling an ERR ..\r\n" );
   }
   else if ( can_interrupt_active( CAN_INTERRUPT_RX ) )
   {
      fprintf(RS232_U1,"...Handling a normal RX ..\r\n" );
   }
   else if ( can_interrupt_active( CAN_INTERRUPT_RXOV ) )
   {
      fprintf(RS232_U1,"...Handling a RXOV ..\r\n" ); 
   }
   else if ( can_interrupt_active( CAN_INTERRUPT_WAKE ) )
   {
      fprintf(RS232_U1,"...Handling a WAKE ..\r\n" ); 
   }
   else if ( can_interrupt_active( CAN_INTERRUPT_FIFO ) )
   {
      fprintf(RS232_U1,"...Handling a FIFO ..\r\n" ); 
   }
   else if ( can_interrupt_active ( CAN_INTERRUPT_INVALID) )
   {
      fprintf(RS232_U1,"...Handling INVALID ..\r\n" );
     
      can_clear_interrupt (CAN_INTERRUPT_INVALID);
      can_clear_interrupt (CAN_INTERRUPT_WAKE);
      can_clear_interrupt (CAN_INTERRUPT_FIFO);
      can_clear_interrupt (CAN_INTERRUPT_ERR);
     
//      fprintf(RS232_U1,"Interrupt register:%d\r\n",

//      can_set_mode(CAN_OP_DISABLE);
//      delay_ms(1);
//      can_set_mode(CAN_OP_NORMAL);

      clear_everything();
     
      return;
   }
   else {
      fprintf(RS232_U1,"...Handling something unknown ..\r\n" );
   }

   CAN_RX_HEADER RxHeader;
   CAN_TX_HEADER TxHeader;
   uint8_t Data[8];
   uint8_t i;

   fprintf(RS232_U1,"Getting..\r\n" );
   can_getd(&RxHeader, Data);
   
   for(i=0;i<RxHeader.Length;i++)
      Data[i] += 10;
   
   TxHeader.Id = 0x1000;
   TxHeader.Length = RxHeader.Length;
   TxHeader.Priority = 3;
   TxHeader.ext = TRUE;
   TxHeader.rtr = FALSE;
   
   fprintf(RS232_U1,"Sending..\r\n" );

   can_putd(&TxHeader, Data);
   
   
   // Clear errors ..
   //can_clear_interrupt (CAN_INTERRUPT_INVALID);
   
}

void main(void)
{

   output_high(CAN_PWR_EN); //turn on the CAN power
//   can_disable_interrupts(CAN_INTERRUPT_RX);
//   can_disable_interrupts(INT_CAN1);

   can_init(CAN_OP_NORMAL);
 
//   can_enable_interrupts(CAN_INTERRUPT_RX);  //enables which CAN interrupts cause overall CAN interrupt to occur

   can_enable_interrupts(CAN_INTERRUPT_RX|CAN_INTERRUPT_ERR|CAN_INTERRUPT_RXOV|CAN_INTERRUPT_WAKE|CAN_INTERRUPT_FIFO|CAN_INTERRUPT_INVALID);  //enables which CAN interrupts cause overall CAN interrupt to occur

/*
       CAN_INTERRUPT_TX
       *CAN_INTERRUPT_RX
       *CAN_INTERRUPT_RXOV
       *CAN_INTERRUPT_FIFO
       *CAN_INTERRUPT_ERR
       *CAN_INTERRUPT_WAKE
       *CAN_INTERRUPT_INVALID
*/ 


   can_disable_rtr(CAN_BUFFER_0);
   can_disable_rtr(CAN_BUFFER_1);
   can_disable_rtr(CAN_BUFFER_2);
   can_disable_rtr(CAN_BUFFER_3);
   can_disable_rtr(CAN_BUFFER_4);
   can_disable_rtr(CAN_BUFFER_5);
   can_disable_rtr(CAN_BUFFER_6);
   can_disable_rtr(CAN_BUFFER_7);


   enable_interrupts(INT_CAN1);
   enable_interrupts(GLOBAL);

   fprintf(RS232_U1,"Running..\r\n" );
   
//   fprintf ( RS232_U1, "CAN Interrupts active..%Ld\r\n", can_interrupts_active

   while(TRUE)
   {
     
   }
}




The output I see is :


Code:

Running..
...Handling INVALID ..
C1INTF=2 C1INTE=EE C1EC=0 IEC=8
Reset and running..
C1INTF=0 C1INTE=EE C1EC=0 IEC=8




And we're still not progressing beyond that .. so I think I am missing more ?
bryant@balancebitsconsult



Joined: 21 Nov 2023
Posts: 38

View user's profile Send private message

PostPosted: Tue May 21, 2024 6:45 pm     Reply with quote

Ok, a little closer ... I think these are the registers, but I am never seeing these as > 0.



Code:

/*****************************************
 The ERRIF status flag (CiINTF[5]) does not get set
 when a CAN error condition occurs, and as a
 result, an interrupt is not generated even if
 enabled.

 ***
 Work around
 ***
 Use the Invalid Message Interrupt (IVRIF) to
 inspect the individual error condition status flags
 TXBO, TXBP, RXBP, TXWAR, RXWAR and
 EWARN (CiINTF[13:8]) to determine if an error
 condition has occurred.
*/

void clear_everything()
{

   int16* C1INTF = (int16*)0x040A;
   int16* C1INTE = (int16*)0x040C;
   int16* C1EC = (int16*)0x040E;
   int16* IEC2 = (int16*)0x0824;
   
   uint16_t intval,inte,ec,iec;
   
   intval=*C1INTF;
   inte=*C1INTE;
   ec=*C1EC;
   iec=*IEC2;
   fprintf(RS232_U1,"Entering .. C1INTF=%X C1INTE=%X C1EC=%X IEC=%X\r\n",intval,inte,ec,iec);
 
   output_toggle(PIN_D12);    // Toggle output pin D12 (red LED)
   delay_ms(100);
   output_toggle(PIN_D12);    // Toggle output pin D12 (red LED)

   //8      // transmitter or receiver in error state warning bit
   if ( CAN_C1INTF.ewarn > 0 )
   {
      fprintf(RS232_U1,"warn bit was set\r\n");
      CAN_C1INTF.ewarn = 0;
   }

   //9      // receiver in error state warning bit
   if ( CAN_C1INTF.rxwar > 0 )
   {
      fprintf(RS232_U1,"rxwar bit was set\r\n");
      CAN_C1INTF.rxwar = 0;
   }
   
   //10     // transmitter in error state warning bit
   if ( CAN_C1INTF.txwar > 0 )
   {
      fprintf(RS232_U1,"txwar bit was set\r\n");
      CAN_C1INTF.txwar = 0;
   }

   //11     // receiver in error state bus passive bit
   if ( CAN_C1INTF.rxbp > 0 )
   {
      fprintf(RS232_U1,"rxbp bit was set\r\n");
      CAN_C1INTF.rxbp = 0;
   } 
   
   //12     // transmitter in error state bus passive bit
   if ( CAN_C1INTF.txbp > 0 )
   {
      fprintf(RS232_U1,"txbp bit was set\r\n");
      CAN_C1INTF.txbp = 0;
   }
   
   //13     // transmitter in error state bus off bit
   if ( CAN_C1INTF.txbo > 0 )
   {
      fprintf(RS232_U1,"txbo bit was set\r\n");
      CAN_C1INTF.txbo = 0;
   } 


   if (intval>1) {
     *C1INTF = 0x00;
     intval=*C1INTF;
     fprintf(RS232_U1,"Reset and running..\r\n" );
   }
   else
   {
      fprintf(RS232_U1,"Called, but C1NTF is 0..\r\n" );
   }
 
   fprintf(RS232_U1,"Leaving .. C1INTF=%X C1INTE=%X C1EC=%X IEC=%X\r\n",intval,inte,ec,iec);
   
   
   return;
}


#INT_CAN1
void can1_isr(void)
{

   if ( can_interrupt_active( CAN_INTERRUPT_ERR ) )
   {
      fprintf(RS232_U1,"...Handling an ERR ..\r\n" );
   }
   else if ( can_interrupt_active( CAN_INTERRUPT_RX ) )
   {
      fprintf(RS232_U1,"...Handling a normal RX ..\r\n" );
   }
   else if ( can_interrupt_active( CAN_INTERRUPT_RXOV ) )
   {
      fprintf(RS232_U1,"...Handling a RXOV ..\r\n" ); 
   }
   else if ( can_interrupt_active( CAN_INTERRUPT_WAKE ) )
   {
      fprintf(RS232_U1,"...Handling a WAKE ..\r\n" ); 
   }
   else if ( can_interrupt_active( CAN_INTERRUPT_FIFO ) )
   {
      fprintf(RS232_U1,"...Handling a FIFO ..\r\n" ); 
   }
   else if ( can_interrupt_active ( CAN_INTERRUPT_INVALID) )
   {
      fprintf(RS232_U1,"...Handling INVALID ..\r\n" );
     
//      can_clear_interrupt (CAN_INTERRUPT_INVALID);
//      can_clear_interrupt (CAN_INTERRUPT_WAKE);
//      can_clear_interrupt (CAN_INTERRUPT_FIFO);
//      can_clear_interrupt (CAN_INTERRUPT_ERR);
     
//      fprintf(RS232_U1,"Interrupt register:%d\r\n",

//      can_set_mode(CAN_OP_DISABLE);
//      delay_ms(1);
//      can_set_mode(CAN_OP_NORMAL);

      clear_everything();
     
      return;
   }
   else {
      fprintf(RS232_U1,"...Handling something unknown ..\r\n" );
   }

   CAN_RX_HEADER RxHeader;
   CAN_TX_HEADER TxHeader;
   uint8_t Data[8];
   uint8_t i;

   fprintf(RS232_U1,"Getting..\r\n" );
   can_getd(&RxHeader, Data);
   
   for(i=0;i<RxHeader.Length;i++)
      Data[i] += 10;
   
   TxHeader.Id = 0x1000;
   TxHeader.Length = RxHeader.Length;
   TxHeader.Priority = 3;
   TxHeader.ext = TRUE;
   TxHeader.rtr = FALSE;
   
   fprintf(RS232_U1,"Sending..\r\n" );

   can_putd(&TxHeader, Data);
   
   
   // Clear errors ..
   //can_clear_interrupt (CAN_INTERRUPT_INVALID);
   
}






Output -- it does seem to recover from just 1 message that's an error on the bus. But this is not quite the solve ...

Code:

Running..
...Handling INVALID ..
Entering .. C1INTF=82 C1INTE=EE C1EC=0 IEC=8
Reset and running..
Leaving .. C1INTF=0 C1INTE=EE C1EC=0 IEC=8
...Handling a normal RX ..
Getting..
Sending..
bryant@balancebitsconsult



Joined: 21 Nov 2023
Posts: 38

View user's profile Send private message

PostPosted: Tue May 21, 2024 9:18 pm     Reply with quote

I am also seeing this in the errata -- I wonder if I am experiencing this too. I see that it is used in can_init().


15. Module: DMA
When the DMA is set up for CAN receive,
interrupts can sometimes be lost if the DMA is held
in an OFF state by the system arbiter. If a CAN
receive interrupt occurs while the DMA is waiting
for a grant for the previous CAN transaction, this
current interrupt will be dropped.

Work arounds
There are two possible work arounds for this issue:
1. Use Dual Port RAM (If available) for target
DMA memory; the DMA cannot be held
“OFF” when accessing the back side of
DPRAM. Only channels set up for CAN
receive would need to use DPRAM; all
other peripherals can use any RAM.

2. Elevate the system priority of DMA by writing a 0x20 to the MSTRPR (Master Priority)
SFR register (address: 0x0058). This will
also prevent the DMA from being held
“OFF”.
Ttelmah



Joined: 11 Mar 2010
Posts: 19326

View user's profile Send private message

PostPosted: Wed May 22, 2024 12:37 am     Reply with quote

That erratum, is only for DMA operation. You are not using this. So
I don't think this applies. (Phew).

Does your debug get to the 'Handling something unknown' location?.
I think it should. The point about the error erratum, is that the CAN interrupt
gets triggered, but none of the actual interrupt 'flag' bits get set. So
the CAN_INTERRUPT_ERR bit is not set, though there is an error. Duh!...

So I think it ought to get to the 'unknown' location. If so the
clear_everything code can go here.
What is annoying, is that for most errors like this MicroChip post
example code of what is needed, but for this one they don't. If they
did it'd be easy to re-code this.
That they don't, I suspect, is a sign of just how nasty this bug really is.
Sad
bryant@balancebitsconsult



Joined: 21 Nov 2023
Posts: 38

View user's profile Send private message

PostPosted: Wed May 22, 2024 12:37 am     Reply with quote

Ok, this is fairly hideous, but it does work !!

I have implemented additional errata, including the DMA issue and one built already by CCS in the can-pic24_dsPIC33.c inside of can_getd() , you can see it now with the code block inside DONT_USE_ERRATA_WORKAROUND.

Insights and comments are welcome.



Code:

#include <main_can_sand.h>
#include <stdint.h>

#define CAN_PWR_EN  PIN_D9    // Power PIN to turn on CAN to the MCU

/*************************************
 * CAN1 #defines set for the can-pic24_dsPIC33.c driver
 *************************************/
#define CAN_CLOCK_DIVISOR 2            // Sets the CAN clock divisor from the system clock can be 1 or 2, default is 2.
#define CAN_BAUD_RATE 500000           // Sets CAN1 baud rate, default is 125000.
#define CAN_DEFAULT_SAMPLE_POINT 875   // Sets sample point, default is 875 for 87.5% of the bit time

/*************************************
 * *QUIRK* - CAN_TX_BUFFERS + CAN_RX_BUFFERS must equal 4, 6, 8, 12, 16, 24 or 32.
 *************************************/
#define CAN_TX_BUFFERS 8  // max 8
#define CAN_RX_BUFFERS 16  // max 32

#define CAN1_RXD  PIN_D10
#define CAN1_TXD  PIN_D0

#pin_select C1TX = CAN1_TXD
#pin_select C1RX = CAN1_RXD

/*************************************
 * CAN2 #defines set for the can-pic24_dsPIC33.c driver
 *************************************/
#define USE_CAN2_PERIPHERAL   TRUE
#define CAN2_CLOCK_DIVISOR 2            // Sets the CAN clock divisor from the system clock can be 1 or 2, default is 2.
#define CAN2_BAUD_RATE 500000
#define CAN2_DEFAULT_SAMPLE_POINT 875   // Sets sample point, default is 875 for 87.5% of the bit time

/*************************************
 * *QUIRK* - CAN2_TX_BUFFERS + CAN2_RX_BUFFERS must equal 4, 6, 8, 12, 16, 24 or 32.
 *************************************/
#define CAN2_TX_BUFFERS 8  // max 8
#define CAN2_RX_BUFFERS 16  // max 32

#define CAN2_RXD  PIN_D8
#define CAN2_TXD  PIN_D7

#pin_select C2TX = CAN2_TXD
#pin_select C2RX = CAN2_RXD

#include <can-pic24_dsPIC33.h>
#include <can-pic24_dsPIC33.c>  // see the .h in the canbus.h file

/***********************************
Notes on writing to the SFR (from datasheet)

21.3 Writing to the CAN CxFCTRL SFR
There are two rules that need to be observed when
writing data to the CxFCTRL register in the CAN module.

1. The register cannot be written with a 16-bit
word. The register must be written as two separate operations to the FSA[4:0] portion and the
DBABS[2:0] portion.

2. The FSA[4:0] bits must be written first and then
followed by the DMABS[2:0] bits.
EXAMPLE 21-1: ILLEGAL OPERATIONS

C1FCTRL = 0x2001; // NOT ALLOWED to
                  // write entire
                  // 16-bits in 1
                  // operation
C1FCTRLbits.DMABS = 2; // WRONG ORDER
C1FCTRLbits.FSA = 1;
********************************/

// CCS Calls  this :
// CAN_C1CTRL1
// and
// CAN_C1CTRL2


/*****************************************
 The ERRIF status flag (CiINTF[5]) does not get set
 when a CAN error condition occurs, and as a
 result, an interrupt is not generated even if
 enabled.

 ***
 Work around
 ***
 Use the Invalid Message Interrupt (IVRIF) to
 inspect the individual error condition status flags
 TXBO, TXBP, RXBP, TXWAR, RXWAR and
 EWARN (CiINTF[13:8]) to determine if an error
 condition has occurred.
******************************************/


void clear_everything()
{

   int16* C1INTF = (int16*)0x040A;
   int16* C1INTE = (int16*)0x040C;
   int16* C1EC = (int16*)0x040E;
   int16* IEC2 = (int16*)0x0824;
   
   uint16_t intval,inte,ec,iec;
   
   intval=*C1INTF;
   inte=*C1INTE;
   ec=*C1EC;
   iec=*IEC2;
   fprintf(RS232_U1,"Entering clear_everything() .. C1INTF=%X C1INTE=%X C1EC=%X IEC=%X\r\n",intval,inte,ec,iec);
 
   output_toggle(PIN_D12);    // Toggle output pin D12 (red LED)

   //8      // transmitter or receiver in error state warning bit
   if ( CAN_C1INTF.ewarn > 0 )
   {
      fprintf(RS232_U1,"warn bit was set\r\n");
      CAN_C1INTF.ewarn = 0;
   }

   //9      // receiver in error state warning bit
   if ( CAN_C1INTF.rxwar > 0 )
   {
      fprintf(RS232_U1,"rxwar bit was set\r\n");
      CAN_C1INTF.rxwar = 0;
   }
   
   //10     // transmitter in error state warning bit
   if ( CAN_C1INTF.txwar > 0 )
   {
      fprintf(RS232_U1,"txwar bit was set\r\n");
      CAN_C1INTF.txwar = 0;
   }

   //11     // receiver in error state bus passive bit
   if ( CAN_C1INTF.rxbp > 0 )
   {
      fprintf(RS232_U1,"rxbp bit was set\r\n");
      CAN_C1INTF.rxbp = 0;
   } 
   
   //12     // transmitter in error state bus passive bit
   if ( CAN_C1INTF.txbp > 0 )
   {
      fprintf(RS232_U1,"txbp bit was set\r\n");
      CAN_C1INTF.txbp = 0;
   }
   
   //13     // transmitter in error state bus off bit
   if ( CAN_C1INTF.txbo > 0 )
   {
      fprintf(RS232_U1,"txbo bit was set\r\n");
      CAN_C1INTF.txbo = 0;
   } 

   if (intval>=1) {
     *C1INTF = 0x00;
     intval=*C1INTF;
     fprintf(RS232_U1,"Reset C1INTF and running..\r\n" );
   }
   else
   {
      fprintf(RS232_U1,"Called, but C1NTF is 0..\r\n" );
   }
 
   fprintf(RS232_U1,"Leaving .. C1INTF=%X C1INTE=%X C1EC=%X IEC=%X\r\n",intval,inte,ec,iec);
   output_toggle(PIN_D12);    // Toggle output pin D12 (red LED)
   return;
}


void clear_can1_buffer (CAN_BUFFER Buffer=CAN_RX_BUFFER_FIFO)
{

   fprintf(RS232_U1,"...inside clear_can1_buffer() ..\r\n" );
   
   can_ec_t Result = CAN_EC_OK;
   uint16_t tBuffer[8];
   
   if(Buffer == CAN_RX_BUFFER_FIFO)
   {
      Buffer = CAN_C1FIFO.fnrb;
     
      if(!CAN_C1RXFUL.array[Buffer])
         Result = CAN_EC_BUFFER_RX_EMPTY;
   }
   else if(Buffer == CAN_RX_BUFFER_ANY)
   {
      for(Buffer=CAN_BUFFER_0;Buffer<=CAN_BUFFER_31;Buffer++)
      {
         if(CAN_C1RXFUL.array[Buffer])
            break;
      }
     
      if(Buffer > CAN_BUFFER_31)
         Result = CAN_EC_BUFFER_RX_EMPTY;
         
      return;
   }
   else if(Buffer <= CAN_BUFFER_31)
   {
      if(!CAN_C1RXFUL.array[Buffer])
         Result = CAN_EC_BUFFER_RX_EMPTY;
         
       return;
   }
         
   #ifndef DONT_USE_ERRATA_WORKAROUND
      if(Buffer < CAN_BUFFER_16)
      {
         CAN_C1RXFUL.w[0] = (~(0x0001 << Buffer));
         CAN_C1RXOVF.w[0] &= (~(0x0001 << Buffer));
      }
      else
      {
         Buffer -= 16;
         
         CAN_C1RXFUL.w[1] = (~(0x0001 << Buffer));
         CAN_C1RXOVF.w[1] &= (~(0x0001 << Buffer));
      }
   #else
      CAN_C1RXFUL.array[Buffer] = 0;
      CAN_C1RXOVF.array[Buffer] = 0;
   #endif
     
   CAN_C1INTF.ivrif = 0;
     
   if(CAN_C1RXFUL.rxful == 0)
      CAN_C1INTF.rbif = 0;

}


#INT_CAN1
void can1_isr(void)
{

   CAN_RX_HEADER RxHeader;
   CAN_TX_HEADER TxHeader;
   uint8_t Data[8];
   uint8_t i;

   if ( can_interrupt_active( CAN_INTERRUPT_ERR ) )
   {
      fprintf(RS232_U1,"...Handling an ERR ..\r\n" );  // probably never fires.
   }
   else if ( can_interrupt_active( CAN_INTERRUPT_RX ) )
   {
      fprintf(RS232_U1,"...Handling a normal RX ..\r\n" );
   }
   else if ( can_interrupt_active( CAN_INTERRUPT_RXOV ) )
   {
      fprintf(RS232_U1,"...Handling a RXOV ..\r\n" ); 
   }
   else if ( can_interrupt_active( CAN_INTERRUPT_WAKE ) )
   {
      fprintf(RS232_U1,"...Handling a WAKE ..\r\n" ); 
   }
   else if ( can_interrupt_active( CAN_INTERRUPT_FIFO ) )
   {
      fprintf(RS232_U1,"...Handling a FIFO ..\r\n" ); 
   }
   else if ( can_interrupt_active ( CAN_INTERRUPT_INVALID) )
   {
      fprintf(RS232_U1,"...Handling INVALID ..\r\n" );
     
//      can_clear_interrupt (CAN_INTERRUPT_INVALID);
//      can_clear_interrupt (CAN_INTERRUPT_WAKE);
//      can_clear_interrupt (CAN_INTERRUPT_FIFO);
//      can_clear_interrupt (CAN_INTERRUPT_ERR);
     
//      fprintf(RS232_U1,"Interrupt register:%d\r\n",

//      can_set_mode(CAN_OP_DISABLE);
//      delay_ms(1);
//      can_set_mode(CAN_OP_NORMAL);

      fprintf(RS232_U1,"Getting..via invalid\r\n" );
      can_getd(&RxHeader, Data);
      clear_everything();
      clear_can1_buffer();
      return;

   }
   else {
      fprintf(RS232_U1,"...Handling something unknown ..\r\n" );
   }


   fprintf(RS232_U1,"Getting..\r\n" );
   can_getd(&RxHeader, Data);
   
   clear_everything();
         
   for(i=0;i<RxHeader.Length;i++)
      Data[i] += 10;
   
   TxHeader.Id = 0x1000;
   TxHeader.Length = RxHeader.Length;
   TxHeader.Priority = 3;
   TxHeader.ext = TRUE;
   TxHeader.rtr = FALSE; 
 
   fprintf(RS232_U1,"Sending..\r\n" );
   can_putd(&TxHeader, Data);
   fprintf(RS232_U1,"Done sending\r\n" );
}

void main(void)
{

   fprintf(RS232_U1,"Running..\r\n" );
   
   output_high(CAN_PWR_EN); //turn on the CAN power

   can_init(CAN_OP_NORMAL);

/********************************
  CAN_INTERRUPT_TX
  *CAN_INTERRUPT_RX
  *CAN_INTERRUPT_RXOV
  *CAN_INTERRUPT_FIFO
  *CAN_INTERRUPT_ERR
  *CAN_INTERRUPT_WAKE
  *CAN_INTERRUPT_INVALID
***********************************/ 
   can_enable_interrupts(CAN_INTERRUPT_RX|CAN_INTERRUPT_ERR|CAN_INTERRUPT_RXOV|CAN_INTERRUPT_WAKE|CAN_INTERRUPT_FIFO|CAN_INTERRUPT_INVALID);  //enables which CAN interrupts cause overall CAN interrupt to occur

//!   can_disable_rtr(CAN_BUFFER_0);
//!   can_disable_rtr(CAN_BUFFER_1);
//!   can_disable_rtr(CAN_BUFFER_2);
//!   can_disable_rtr(CAN_BUFFER_3);
//!   can_disable_rtr(CAN_BUFFER_4);
//!   can_disable_rtr(CAN_BUFFER_5);
//!   can_disable_rtr(CAN_BUFFER_6);
//!   can_disable_rtr(CAN_BUFFER_7);

/******************
15. Module: DMA
When the DMA is set up for CAN receive,
interrupts can sometimes be lost if the DMA is held
in an OFF state by the system arbiter. If a CAN
receive interrupt occurs while the DMA is waiting
for a grant for the previous CAN transaction, this
current interrupt will be dropped.

Work arounds
There are two possible work arounds for this issue:
1. Use Dual Port RAM (If available) for target
DMA memory; the DMA cannot be held
“OFF” when accessing the back side of
DPRAM. Only channels set up for CAN
receive would need to use DPRAM; all
other peripherals can use any RAM.

2. Elevate the system priority of DMA by writing a 0x20 to the MSTRPR (Master Priority)
SFR register (address: 0x0058). This will
also prevent the DMA from being held
"OFF"
******************/

   int16* MSTRPR = (int16*)0x0058;  // master priority required for DMA workaround

 
/* Disable this when debugging */
   fprintf(RS232_U1,"BEFORE read of MSTRPR: 0x%04x\r\n", *MSTRPR );
   *MSTRPR = 0x20;                   // magic number
   fprintf(RS232_U1,"AFTER read of MSTRPR: 0x%04x\r\n", *MSTRPR );

   enable_interrupts(INT_CAN1);
   enable_interrupts(GLOBAL);
   
//   fprintf ( RS232_U1, "CAN Interrupts active..%Ld\r\n", can_interrupts_active

   while(TRUE)
   {
     
   }
}




.h file
Code:

#include <24EP512GU810.h>
#device ICSP=1
#use delay(clock=120MHz,oscillator=4MHz)

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES BROWNOUT                // required as per errata *********

// Serial pin mapping for the board, 2 serial connections are possible
#define DBG_TXD   PIN_E5
#define DBG_RXD   PIN_E6

#define DBG2_TXD  PIN_E7
#define DBG2_RXD  PIN_E8

#use rs232(baud=115200,parity=N,xmit=DBG_TXD,rcv=DBG_RXD,bits=8,stream=RS232_U1,UART1,RECEIVE_BUFFER=64,TXISR,ERRORS)

temtronic



Joined: 01 Jul 2010
Posts: 9160
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed May 22, 2024 5:07 am     Reply with quote

hmm, I know, you've already thought of this but.....
... have you confirmed the CAN bus pullups / terminators are the correct values ?
'weird' stuff can happen with CAN.......
bryant@balancebitsconsult



Joined: 21 Nov 2023
Posts: 38

View user's profile Send private message

PostPosted: Wed May 22, 2024 6:21 pm     Reply with quote

temtronic wrote:
hmm, I know, you've already thought of this but.....
... have you confirmed the CAN bus pullups / terminators are the correct values ?
'weird' stuff can happen with CAN.......


Yes, all checked thoroughly. The problem is not that there are errors , it is about how errors are handled when received. Previously if any error was present ( through normal bus actions ) the interrupts would stop.
Ttelmah



Joined: 11 Mar 2010
Posts: 19326

View user's profile Send private message

PostPosted: Fri May 24, 2024 7:12 am     Reply with quote

Well done on getting it working. Looking at it, though a bit complex, it
does make sense when you look at what they are saying can happen.
For some weird reason you get the chip triggering a CAN interrupt,
but not setting the actual 'flag' in the register to say that this is an error
interrupt. Duh!...
It is interesting, since there is conflicting data about this on the web.
One of the Microchip notes says the chip will interrupt if the error
interrupt is enabled, but no ERRIF flag will be set to say that there is an
error. The actual erratum sheet says it won't interrupt. From what you
were seeing, it looks as if the former is what happens.
Very sad, and a 'caveat' to anyone using this chip.
Glad you have a fix, even if it is less elegant than you might like!... . Very Happy
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group