|
|
View previous topic :: View next topic |
Author |
Message |
bryant@balancebitsconsult
Joined: 21 Nov 2023 Posts: 38
|
|
Posted: Tue May 21, 2024 6:17 pm |
|
|
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
|
|
Posted: Tue May 21, 2024 6:45 pm |
|
|
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
|
|
Posted: Tue May 21, 2024 9:18 pm |
|
|
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: 19529
|
|
Posted: Wed May 22, 2024 12:37 am |
|
|
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.
|
|
|
bryant@balancebitsconsult
Joined: 21 Nov 2023 Posts: 38
|
|
Posted: Wed May 22, 2024 12:37 am |
|
|
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: 9232 Location: Greensville,Ontario
|
|
Posted: Wed May 22, 2024 5:07 am |
|
|
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
|
|
Posted: Wed May 22, 2024 6:21 pm |
|
|
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: 19529
|
|
Posted: Fri May 24, 2024 7:12 am |
|
|
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!... . |
|
|
|
|
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
|