|
|
View previous topic :: View next topic |
Author |
Message |
bryant@balancebitsconsult
Joined: 21 Nov 2023 Posts: 38
|
CAN message interrupts stop after first interrupt serviced |
Posted: Mon May 20, 2024 12:30 pm |
|
|
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
|
|
Posted: Mon May 20, 2024 12:33 pm |
|
|
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: 1933 Location: Norman, OK
|
|
Posted: Mon May 20, 2024 12:42 pm |
|
|
Compiler version? _________________ Google and Forum Search are some of your best tools!!!! |
|
|
bryant@balancebitsconsult
Joined: 21 Nov 2023 Posts: 38
|
|
Posted: Mon May 20, 2024 12:50 pm |
|
|
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: 1933 Location: Norman, OK
|
|
Posted: Mon May 20, 2024 12:53 pm |
|
|
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
|
|
Posted: Mon May 20, 2024 12:58 pm |
|
|
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: 1933 Location: Norman, OK
|
|
Posted: Mon May 20, 2024 1:12 pm |
|
|
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
|
|
Posted: Mon May 20, 2024 1:26 pm |
|
|
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
|
|
Posted: Mon May 20, 2024 1:40 pm |
|
|
[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
|
|
Posted: Mon May 20, 2024 2:02 pm |
|
|
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
|
|
Posted: Mon May 20, 2024 4:49 pm |
|
|
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: 8
|
|
Posted: Mon May 20, 2024 7:34 pm |
|
|
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: 19495
|
|
Posted: Tue May 21, 2024 1:51 am |
|
|
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.
Presumably since these are not cleared, once this happens the peripheral
would actually be hung. |
|
|
bryant@balancebitsconsult
Joined: 21 Nov 2023 Posts: 38
|
|
Posted: Tue May 21, 2024 3:33 pm |
|
|
I will try this now. This seems very plausible. |
|
|
bryant@balancebitsconsult
Joined: 21 Nov 2023 Posts: 38
|
|
Posted: Tue May 21, 2024 5:58 pm |
|
|
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 ? |
|
|
|
|
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
|