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 CCS Technical Support

CAN message interrupts stop after first interrupt serviced
Goto page 1, 2  Next
 
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

CAN message interrupts stop after first interrupt serviced
PostPosted: Mon May 20, 2024 12:30 pm     Reply with quote

PIC24EP512GU810 Using CAN1.

I can correctly see 1 message getting serviced, but very strangely I am unable to get an INT_CAN1 interrupt after the first one. It's as if the INT_CAN1 interrupts are turned off (?) after the first run of the interrupt ISR.

I will post code that shows this behavior in 2 mins, since I am about to trace the behavior into the ECAN1 register map.

Has someone has seen this kind of behavior before ?
bryant@balancebitsconsult



Joined: 21 Nov 2023
Posts: 38

View user's profile Send private message

PostPosted: Mon May 20, 2024 12:33 pm     Reply with quote

Sample code seeing this behavior:

main_can_sand.h
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

// 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)



main_can_sand.c
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>

#INT_CAN1
void can1_isr(void)
{
   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);
}

void main(void)
{

   output_high(CAN_PWR_EN); //turn on the CAN power

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

   fprintf(RS232_U1,"Running..\r\n" );

   while(TRUE)
   {
     
   }
}



[/code]
dyeatman



Joined: 06 Sep 2003
Posts: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Mon May 20, 2024 12:42 pm     Reply with quote

Compiler version?
_________________
Google and Forum Search are some of your best tools!!!!
bryant@balancebitsconsult



Joined: 21 Nov 2023
Posts: 38

View user's profile Send private message

PostPosted: Mon May 20, 2024 12:50 pm     Reply with quote

dyeatman wrote:
Compiler version?


v5.116


ALSO -- and this is weird --

The code will work correctly and ping-pong, as long as there is not a CAN Message on the bus when the board starts.

If there is a message sitting on the bus, and it gets picked up on startup, then the RX does not work beyond the first message!!
dyeatman



Joined: 06 Sep 2003
Posts: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Mon May 20, 2024 12:53 pm     Reply with quote

Interesting...trying to figure out to test this...
_________________
Google and Forum Search are some of your best tools!!!!
bryant@balancebitsconsult



Joined: 21 Nov 2023
Posts: 38

View user's profile Send private message

PostPosted: Mon May 20, 2024 12:58 pm     Reply with quote

dyeatman wrote:
Interesting...trying to figure out to test this...


I have a PCAN adaptor connected to the CAN line that is sending a message once a second to this code. The code responds when it works correctly and the PCAN adaptor sees it.
dyeatman



Joined: 06 Sep 2003
Posts: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Mon May 20, 2024 1:12 pm     Reply with quote

I just noticed there is quite a bit of errata on this chip including CAN & ECAN
on silicon revision B1.... You wouldn't be unlucky enough to be using this one?
One thing it says if you are using B1 is that BOR must always be enabled.
_________________
Google and Forum Search are some of your best tools!!!!
bryant@balancebitsconsult



Joined: 21 Nov 2023
Posts: 38

View user's profile Send private message

PostPosted: Mon May 20, 2024 1:26 pm     Reply with quote

dyeatman wrote:
I just noticed there is quite a bit of errata on this chip including CAN & ECAN
on silicon revision B1.... You wouldn't be unlucky enough to be using this one?
One thing it says if you are using B1 is that BOR must always be enabled.




I see:
PIC24EP512GU810-I/PF E3
2336RCU[/img]
bryant@balancebitsconsult



Joined: 21 Nov 2023
Posts: 38

View user's profile Send private message

PostPosted: Mon May 20, 2024 1:40 pm     Reply with quote

[quote="bryant@balancebitsconsult"]
dyeatman wrote:
I just noticed there is quite a bit of errata on this chip including CAN & ECAN
on silicon revision B1.... You wouldn't be unlucky enough to be using this one?
One thing it says if you are using B1 is that BOR must always be enabled.


I see:
PIC24EP512GU810-I/PF E3
2336RCU




Ok, so implementing #FUSES BROWNOUT does not alter the behavior. Still looking ...
bryant@balancebitsconsult



Joined: 21 Nov 2023
Posts: 38

View user's profile Send private message

PostPosted: Mon May 20, 2024 2:02 pm     Reply with quote

Notable issue :

Module: CAN

A transmit-interrupt event (even if it is disabled as
an interrupt source) that happens immediately
after the reception-interrupt event will cause the
ICODE bits to point to the transmit buffer instead
of the receive buffer.

Work around
Use FILHIT, rather than ICODE, when processing
an Rx interrupt.

Affected Silicon Revisions : B1



Seeing if I have this issue ...
bryant@balancebitsconsult



Joined: 21 Nov 2023
Posts: 38

View user's profile Send private message

PostPosted: Mon May 20, 2024 4:49 pm     Reply with quote

New code, shows that the interrupts I am receiving are CAN_INTERRUPT_INVALID.

Once I receive once of these interrupts, I never receive another CAN interrupt of any other type, as a result I cannot service any CAN(1) buffers and they just accumulate.

Explicitnly using can_clear_interrupt(CAN_INTERRUPT_INVALID) does not appear to work.

How can I clear this and move on ?


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)



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


#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_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);
     
      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_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)
   {
     
   }
}


Last edited by bryant@balancebitsconsult on Wed May 22, 2024 9:15 am; edited 1 time in total
waffles



Joined: 21 Dec 2021
Posts: 10

View user's profile Send private message

PostPosted: Mon May 20, 2024 7:34 pm     Reply with quote

I'm not familiar with how CAN works on that PIC, but there's possibly ramifications to doing debug prints inside the interrupt with the current setup?

I see that you have 'TXISR' set in the #use statement, but you don't have a transmit buffer size defined? I think that this is going to result in standard polled/locked transmission for the duration of the message.
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Tue May 21, 2024 1:51 am     Reply with quote

My suspicion would be that this might relate to the issue in section 12 of
the errata. So on a CAN error, interrupt can trigger without the ERRIF flag
being set. So this test:

if ( can_interrupt_active( CAN_INTERRUPT_ERR ) )

Will not go true, even though there is an error.
The code needs to test all six of the individual error bits to detect this.
Then the individual error bits would have to be cleared, since the ERRIF
bit is not set. Sad
Presumably since these are not cleared, once this happens the peripheral
would actually be hung.
bryant@balancebitsconsult



Joined: 21 Nov 2023
Posts: 38

View user's profile Send private message

PostPosted: Tue May 21, 2024 3:33 pm     Reply with quote

I will try this now. This seems very plausible.
bryant@balancebitsconsult



Joined: 21 Nov 2023
Posts: 38

View user's profile Send private message

PostPosted: Tue May 21, 2024 5:58 pm     Reply with quote

yes, I expect that I am never going to get a CAN_INTERRUPT_ERR.


I am a little stumped on the "right" way to inspect these ERROR flags every time. Is there a "best practices" way ?
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 1, 2  Next
Page 1 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