Problem with CAN on LPC2129/01 series

Started by amit kankaran October 6, 2008
Hi all,

I am Having a problem with CAN on LPC2129/01 series.
Whenever i recieve a CAN frame , the control is not coming out of ISR,
but when i reset the CAN controller ,the control is coming out ,but
after that i am not able to recieve next CAN frame . if i enable CAN
controller again in main function ,it is continously switching b/w ISR
and main()
Following is my code

#include
#define wait 1000000 //count to give delay
#define OEM_NO *((unsigned long*)0x40003FFC)
#define IDENTIFIER 0x00010002

#define StandardFilter0 (*((volatile unsigned long *) 0xE0038000))
#define StandardFilter1 (*((volatile unsigned long *) 0xE0038004))

void CAN1IRQ (void) __attribute__ ((interrupt("IRQ")));

typedef union CAN_DATA{

unsigned char string[8];
unsigned int two_int[2];

}CAN_DATA;

typedef struct CAN_FRAME
{
unsigned long TFI;
unsigned long ID;
CAN_DATA Can_Data;
}CAN_FRAME;

CAN_DATA GSend_OEM_Frame = { {"SND_OEM"} };
CAN_DATA GSend_IDN_Frame = { {"SND_IDN"} };
void Decode(CAN_DATA * pData_Frame);
unsigned int Compare(CAN_DATA* pData_Frame1,CAN_DATA* pData_Frame2);
void can_init(void);
void filter(void)
{
AFMR = 0x00000001; //Disable the Acceptance filters to allow setup
of the table
StandardFilter0 =0x00010002; //0X10010002;
StandardFilter1 =0x10031004;//0X10031004;
SFF_sa = 0x00000000; //Set start address of Standard table
SFF_GRP_sa = 0x00000008; //Set start address of Standard group table
EFF_sa = 0x00000008; //Set start address of Extended table
EFF_GRP_sa = 0x00000008; //Set start address of Extended group table
ENDofTable = 0x00000008; //Set end of table address
AFMR = 0x00000000; //Enable Acceptance filters
}

void print(unsigned long int p,unsigned long q)
{
int i=0;
VPBDIV=0x00000002;
PINSEL0 |= 0x00010001; /* Enable UART TxD0 Txd1 */
U0LCR = 0x00000083; /* 8 bits, no Parity, 1 Stop bit */
U0DLL = 0x000000C2; /* 9600 Baud Rate @ 30MHz VPB Clock */
U0LCR = 0x00000003; /* DLAB = 0 */

for (i=0;i<4;i++)
{
while (!(U0LSR & 0x20));
U0THR =p;
p=p>>8;
}
for (i=0;i<4;i++)
{
while (!(U0LSR & 0x20));
U0THR =q;
q=q>>8;
}
C1CMR=0X00000004; // release the buffer
}

void delay(void)
{
volatile unsigned int i;
for(i=0;i }

void CAN1IRQ(void)
{
// CAN_DATA Recieved_can_data;

// Recieved_can_data.two_int[0] = C1RDA;
// Recieved_can_data.two_int[1] = C1RDB;

// Decode(&Recieved_can_data);

print(C1RDA,C1RDB);

IO1PIN = 0X00000000; // /* Turn on LED
delay(); // call wait function
IO1PIN = 0X00F00000; // Turn off LED
delay();
IO1PIN = 0X00000000;

C1CMR=0X00000004; //release the recieve buffer
VICVectAddr = 0x00000000;

C1MOD = 0x01; // Disable Can Controller

}

void can2tx(CAN_FRAME* ptr)
{
C1MOD = 0x00; // Enable Can Controller
while(!(C2SR&0X00000004)); // wait till tx buffer 1 is free
C2TFI1=ptr->TFI;
C2TID1=ptr->ID;
C2TDA1=ptr->Can_Data.two_int[0];
C2TDB1=ptr->Can_Data.two_int[1];

C2CMR=0x00000021; //request transmission
// print(C2TDA1,C2TDB1);
}

void can_init(void)
{
C2MODOD=0X00000001;
C2BTRTR=0X001C001D; //for 125k bit rate
PINSEL1=0X00050000; //select can1 rx and can2 tx
C1IER=0X00000001; //enable can1 rx interrupt
C2MODOD=0X00000000;
VICVectCntl0=0X00000003A;
VICVectAddr0=(unsigned)CAN1IRQ; //assign address of isr to
vic 0 channel
VICIntEnable=0X04000000; //enable can1 rx interrupt
}

CAN_FRAME temp_frame = {0x00080000,IDENTIFIER};
int main()
{
IODIR1=0X00FF0000;
temp_frame.Can_Data = GSend_OEM_Frame;
// OEM_NO = 0x000000100;
can_init();
filter();

can2tx(&temp_frame);
while(1)
{

C1MOD = 0x00; // Enable Can Controller
IO1PIN = 0x00000000;
delay();
IO1PIN = 0x00070000;
delay();
}

}
With Regards,
Amit Chaudhary

An Engineer's Guide to the LPC2100 Series

--- In l..., "amit kankaran"
wrote:
>
> Hi all,
>
> I am Having a problem with CAN on LPC2129/01 series.
> Whenever i recieve a CAN frame , the control is not coming out of
ISR,
> but when i reset the CAN controller ,the control is coming out ,but
> after that i am not able to recieve next CAN frame . if i enable CAN
> controller again in main function ,it is continously switching b/w
ISR
> and main()
> Following is my code
>
> #include
> #define wait 1000000 //count to give delay
> #define OEM_NO *((unsigned long*)0x40003FFC)
> #define IDENTIFIER 0x00010002
>
> #define StandardFilter0 (*((volatile unsigned long *) 0xE0038000))
> #define StandardFilter1 (*((volatile unsigned long *) 0xE0038004))
>
> void CAN1IRQ (void) __attribute__ ((interrupt("IRQ")));
>
> typedef union CAN_DATA{
>
> unsigned char string[8];
> unsigned int two_int[2];
>
> }CAN_DATA;
>
> typedef struct CAN_FRAME
> {
> unsigned long TFI;
> unsigned long ID;
> CAN_DATA Can_Data;
> }CAN_FRAME;
>
> CAN_DATA GSend_OEM_Frame = { {"SND_OEM"} };
> CAN_DATA GSend_IDN_Frame = { {"SND_IDN"} };
> void Decode(CAN_DATA * pData_Frame);
> unsigned int Compare(CAN_DATA* pData_Frame1,CAN_DATA* pData_Frame2);
> void can_init(void);
> void filter(void)
> {
> AFMR = 0x00000001; //Disable the Acceptance
filters to allow setup
> of the table
> StandardFilter0 =0x00010002; //0X10010002;
> StandardFilter1 =0x10031004;//0X10031004;
> SFF_sa = 0x00000000; //Set start address of Standard
table
> SFF_GRP_sa = 0x00000008; //Set start address of
Standard group table
> EFF_sa = 0x00000008; //Set start address of
Extended table
> EFF_GRP_sa = 0x00000008; //Set start address of
Extended group table
> ENDofTable = 0x00000008; //Set end of table address
> AFMR = 0x00000000; //Enable Acceptance filters
> }
>
> void print(unsigned long int p,unsigned long q)
> {
> int i=0;
> VPBDIV=0x00000002;
> PINSEL0 |= 0x00010001; /* Enable UART TxD0
Txd1 */
> U0LCR = 0x00000083; /* 8 bits, no Parity, 1
Stop bit */
> U0DLL = 0x000000C2; /* 9600 Baud Rate @
30MHz VPB Clock */
> U0LCR = 0x00000003; /* DLAB = 0 */
>
> for (i=0;i<4;i++)
> {
> while (!(U0LSR & 0x20));
> U0THR =p;
> p=p>>8;
> }
> for (i=0;i<4;i++)
> {
> while (!(U0LSR & 0x20));
> U0THR =q;
> q=q>>8;
> }
> C1CMR=0X00000004; // release the
buffer
> }
>
> void delay(void)
> {
> volatile unsigned int i;
> for(i=0;i > }
>
> void CAN1IRQ(void)
> {
> // CAN_DATA Recieved_can_data;
>
>
>
> // Recieved_can_data.two_int[0] = C1RDA;
> // Recieved_can_data.two_int[1] = C1RDB;
>
> // Decode(&Recieved_can_data);
>
> print(C1RDA,C1RDB);
>
> IO1PIN 0X00000000; // /* Turn on LED
> delay(); // call wait
function
> IO1PIN = 0X00F00000; // Turn
off LED
> delay();
> IO1PIN = 0X00000000;
>
> C1CMR=0X00000004;
//release the recieve buffer
> VICVectAddr = 0x00000000;
>
> C1MOD = 0x01; // Disable Can Controller
>
> }
> void can2tx(CAN_FRAME* ptr)
> {
> C1MOD = 0x00; // Enable Can
Controller
> while(!(C2SR&0X00000004)); // wait till tx
buffer 1 is free
> C2TFI1=ptr->TFI;
> C2TID1=ptr->ID;
> C2TDA1=ptr->Can_Data.two_int[0];
> C2TDB1=ptr->Can_Data.two_int[1];
>
> C2CMR=0x00000021; //request
transmission
> // print(C2TDA1,C2TDB1);
> }
> void can_init(void)
> {
> C2MODOD=0X00000001;
> C2BTRTR=0X001C001D; //for 125k
bit rate
> PINSEL1=0X00050000; //select
can1 rx and can2 tx
> C1IER=0X00000001;
//enable can1 rx interrupt
> C2MODOD=0X00000000;
> VICVectCntl0=0X00000003A;
> VICVectAddr0=(unsigned)CAN1IRQ; //assign address
of isr to
> vic 0 channel
> VICIntEnable=0X04000000; //enable can1
rx interrupt
> }
>
> CAN_FRAME temp_frame = {0x00080000,IDENTIFIER};
> int main()
> {
> IODIR1=0X00FF0000;
> temp_frame.Can_Data = GSend_OEM_Frame;
> // OEM_NO = 0x000000100;
> can_init();
> filter();
>
> can2tx(&temp_frame);
> while(1)
> {
>
> C1MOD = 0x00; // Enable Can Controller
> IO1PIN = 0x00000000;
> delay();
> IO1PIN = 0x00070000;
> delay();
> }
>
> }
> With Regards,
> Amit Chaudhary
>

A couple of things:

In the /01 parts they have put in the newer CAN controller as used in
the LPC2468, etc. This has an issue when you let the RX buffer
fill ... It locks the CAN controller and you need to do the reset you
mention. (see the LPC2129/01 - Errata v1.0 - 27th July 2007)

Also, this won't be helped by the fact you have put delays in the
interrupt handler !!! You need to do the MINIMUM amount of work in
the handler (i.e. get the message and store it somewhere and set a
flag for the main loop to process this message).

Simon.