I am sending data one byte at a time on CAN2 Tx and receiving it on CAN1 Rx. Is the following initialization correct for CAN1 for receiving data ?
#define StandardFilter (*((volatile unsigned long *) 0xE0038000));this is where the acceptance filter RAM starts void init_can1_Rx(void) {PINSEL1 |= 0x00050000;//Enable Pin 0.25 as CAN1 RX and 0.24 as CAN2 TX C1MOD = 0x00000001;//Set CAN controller into reset C1BTR = 0x001C001D;//Set bit timing to 125k C1IER = 0x00000001;//Enable the Receive interrupt VICVectCntl0 = 0x0000003A;//select the priority channel=26 for a given interrupt.Bit5=1 means interrupt is enabled VICVectAddr0=(unsigned long)CAN1IRQ;// Pass address of IRQ in to VIC slot //Bits 4:0 =11010 means s/w interrupt #26 is assigned to VicVectCntl0 VICIntEnable = 0x04000000;//enable interrupt no 26 of the 0 to 31 interrputs AFMR = 0x00000001;//Disable the Acceptance filters to allow setup of the table StandardFilter = 0x20012002;//std individual identifier nos 1 and 2 of controller#1 (node number) SFF_sa = 0xE0038000;//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.If this is set to 0x00000002,then ALL messages are reeived ==> no filtering C1MOD = 0x00000000;//Release CAN controller }
Since i am only sending one byte to node 2, i use only one standard identifier and have set the SFF_sa to the acceptance filter address.
But my doubt is as i am not using the extended and group identifiers, what address should i set them to? The user manual says that if unused, SFF_GRP_sa should be identical to EFF_sa which should be identical to EFF_GRP_sa which again should be identical to ENDofTable. So i set all the unused filters to an arbitraty value of 0x00000008.
In my program, the TX happens properly but the CAN1 Rx interrupt is not happening, which means it is not sensing the data being transmitted, which makes me think something is wrong the way i have set up the acceptance filers.
Anybody familiar with CAN;please do give some inputs...
I have worked a lot with CAN on the 2129. I do believe that they have some RX vec interrupt problems. Check your registers first to see if you are getting an overrun error. I was never able to solve this problem and just went to a pulled interrupt because it was acceptable for the project. The CAN example in the LCP2000 forum group is good code to use, but it needs a few fixes on the init to update it.
here is an snippet of acceptance filter set up:
/************************************************************************** Setting a CAN receive filter as described in LPC_FullCAN_SW.h ***************************************************************************/ short FullCAN_SetFilter ( unsigned short can_port, // CAN interface number unsigned int CANID // 11-bit CAN ID ) { unsigned int p, n; unsigned int buf0, buf1; unsigned int ID_lower, ID_upper; unsigned int candata; unsigned int *pAddr; // Double check can_port value if ((can_port < 1) || (can_port > MAX_CANPORTS)) { // Illegal value for can_port return 0; } can_port = can_port - 1; // Acceptance Filter Mode Register = off ! AFMR = 0x00000001L; if (gCANFilter == 0) { // First call, init entry zero gFullCANList[0].Dat1 = 0x000037FFL; // CAN 1, disabled and unused } if (gCANFilter >= MAX_FILTERS) { return 0; } CANID &= 0x000007FFL; // Mask out 11-bit ID CANID |= (can_port << 13); // Put can_port info in bits 13-15 // Filters must be sorted by interface, then by priority // new filter is sorted into array p = 0; while (p < gCANFilter) // loop through all existing filters { if ((gFullCANList[p].Dat1 & 0x0000FFFFL) > CANID) { break; } p++; } // insert new filter here buf0 = gFullCANList[p].Dat1; // save current entry gFullCANList[p].Dat1 = CANID; // insert the new entry // move all remaining entries one row up gCANFilter++; while (p < gCANFilter) { p++; buf1 = gFullCANList[p].Dat1; gFullCANList[p].Dat1 = buf0; buf0 = buf1; } // Now work on Acceptance Filter Configuration // Set CAN filter for 11-bit standard identifiers p = 0; // Set pointer for Standard Frame Individual // Standard Frame Explicit SFF_sa = p; pAddr = (unsigned int *) ACCEPTANCE_FILTER_RAM_BASE; for (n = 0; n < ((gCANFilter+1)/2); n++) { ID_lower = gFullCANList[n * 2].Dat1 & 0x0000FFFFL; ID_upper = gFullCANList[n * 2 + 1].Dat1 & 0x0000FFFFL; candata = (ID_lower << 16) + ID_upper; *pAddr = candata; p += 4; pAddr++; } // p is still pointing to ENDofTable; // Set pointer for Standard Frame Groups // Standard Frame Group Start Address Register SFF_GRP_sa = p; // Set pointer for Extended Frame Individual // Extended Frame Start Address Register EFF_sa = p; // Set pointer for Extended Frame Groups // Extended Frame Group Start Address Register EFF_GRP_sa = p; // Set ENDofTable // End of AF Tables Register ENDofTable = p; // Acceptance Filter Mode Register, start using filter AFMR = 0; return 1; }
Hello Bracken,
Thank you for the snipppet.I have a doubt in it.Why are you assigning the values of p to SFF_sa, SFF_GRP_sa etc? I mean aren't these regs supposed to hold the addresses of the respective acceptance IDs?In other words, they should be holding the contents of pAddr(?)
You are already inserting the address into the RAM table here using the pointer pAddr:
pAddr = (unsigned int *) ACCEPTANCE_FILTER_RAM_BASE; for (n = 0; n < ((gCANFilter+1)/2); n++) { ID_lower = gFullCANList[n * 2].Dat1 & 0x0000FFFFL; ID_upper = gFullCANList[n * 2 + 1].Dat1 & 0x0000FFFFL; candata = (ID_lower << 16) + ID_upper; *pAddr = candata; p += 4; pAddr++; }
p is only sending where the end of the table is.
DataSheet-SFF_sa: "The start address of the table of individual Standard Identifiers in AF Lookup RAM. If the table is empty, write the same value in this register and the SFF_GRP_sa register described below. For compatibility with possible future devices, please write zeroes in bits 31:11 and 1:0 of this register. If the eFCAN bit in the AFMR is 1, this value also indicates the size of the table of Standard IDs which the Acceptance Filter will search and (if found) automatically store received messages in Acceptance Filter RAM."
"SFF_sa: The start address of the table of individual Standard Identifiers in AF Lookup RAM."
i.e SFF_sa must contain at what location the identifier starts.So it must contain the value of pAddr, ie the address where the table starts in the memory. Now
*pAddr = candata;
This only inserts the values of the identifiers that are to be filtered(accepted) by that particular CAN node.
What am i missing ?
The code snippet from the 'Insiders guide to ARM7' does the same thing with SFF_sa too !
unsigned int StandardFilter[2] _at_ 0xE0038000;//Fair enough, as table starts at this address StandardFilter[0] =0x20012002;//ok, now identfiers are 1 and 2 for controller no.2 SFF_sa =0x00000000;//WHY !! ISN'T THIS SUPPOSED TO BE 0xE0038000?
SFF_sa: The start address of the table of individual Standard Identifiers in AF Lookup RAM."
SFF_sa holds the address from the table, not from each table entry.
I use 30 entries in the table and it works fine at that way Bracken Meyers has allready posted.
read the .. manual again and you will see how it's work.
good luck
Finally, i got it. They are supposed to hold offset values relative to the table start address. This app note is great! www.nxp.com/.../AN10674_1.pdf
An excerpt:
Each of the pointers is used to define the start of a section. They are relative (offset)pointers to the starting address of the Filter Table. When a section is not defined, the register should be set to the current free entry in the Filter Table. It is assumed that for the FULLCAN message ID section the starting address (offset) is always 0.
Thank you guys for the inputs.