1 //==========================================================================
3 // devs/can/arm/lpc2xxx/current/src/can_accfilt_lpc2xxx.c
5 // Acceptance filter management for LPC2xxx CAN driver
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2003 Gary Thomas
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
44 // Author(s): Uwe Kindler
45 // Contributors: Uwe Kindler
47 // Purpose: Support LPC2xxx on-chip CAN acceptance filters
50 //####DESCRIPTIONEND####
52 //==========================================================================
55 //===========================================================================
57 //===========================================================================
59 // Acceptance filter entry
61 typedef struct lpc2xxx_accfilt_entry
63 cyg_uint32 data; // the value inclusive channel number
65 cyg_uint32 lower_id_bound;
66 cyg_uint32 upper_id_bound;
68 } lpc2xxx_accfilt_entry_t;
71 //===========================================================================
73 //===========================================================================
74 //--------------------------------------------------------------------------
75 // On no-suffix and /00 devices, the CAN controllers are numbered 1 to n
76 // (n = 2 or 4) in the LUT tables. However, on /01 devices, the CAN controllers
77 // are numbered 0 to nĂ¢1 in the LUT tables.
79 // On the LPC2468 the LUT channel numbers are also numbered from 0 - 4.
81 #if defined(CYGHWR_HAL_ARM_LPC2XXX_SUFFIX_01) || (CYGHWR_HAL_ARM_LPC2XXX_VARIANT_VERSION == 4)
82 # define LPC2XXX_CAN_FIRST_IN_LUT (0)
84 # define LPC2XXX_CAN_FIRST_IN_LUT (1)
88 // This macro calculates the chanel number from the channel info. The channel
89 // number is numbered from 0 - 3 but in the LUT the channel number may differ
90 // depending on the device suffix. For some devices the channel number in
91 // LUT are numbered 0 - 3 and for other devices the channels in LUT are
92 // numbered 1 - 4. This macro abstrats this fact from the acceptance filter
95 #define CAN_CHAN_NO_LUT(_info_) (CAN_CHAN_NO(_info_) + LPC2XXX_CAN_FIRST_IN_LUT)
97 //--------------------------------------------------------------------------
98 // Lowlevel acceptance filter access
100 #ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
101 static bool lpc2xxx_can_accfilt_add(lpc2xxx_can_info_t *info,
104 cyg_can_id_type ext);
105 void lpc2xxx_can_accfilt_ram_insert_entry(cyg_uint32 TableAddress, cyg_uint16 EntryNo);
106 void lpc2xxx_can_accfilt_ram_remove_entry(cyg_uint32 TableAddress, cyg_uint16 EntryNo);
107 void lpc2xxx_can_accfilt_remove_all_ctrl_entries(lpc2xxx_can_info_t *info);
109 static void lpc2xxx_can_accfilt_simple_rx_all(void);
110 #endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
111 void lpc2xxx_can_accfilt_reset(void);
113 #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
114 void lpc2xxx_can_accfilt_dbg_dump(void);
115 void lpc2xxx_can_reg_dump(struct cyg_devtab_entry* devtab_entry);
119 #ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
120 //===========================================================================
121 // Calculate address of entry in certain table
122 //===========================================================================
123 static cyg_uint32 lpc2xxx_can_accfilt_calc_entry_address(cyg_uint32 TableAddressRegister, cyg_uint16 EntryNo)
125 cyg_uint32 EntryAddress = 0xFFFFFFFF;
126 cyg_uint32 TableAddress;
128 HAL_READ_UINT32(TableAddressRegister, TableAddress);
129 switch (TableAddressRegister)
131 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
132 case CAN_ACCFILT_SFF_SA:
133 EntryAddress = ((EntryNo / 2) << 2) + TableAddress;
136 case CAN_ACCFILT_SFF_GRP_SA:
137 EntryAddress = TableAddress + (EntryNo << 2);
139 #endif // CYGOPT_IO_CAN_STD_CAN_ID
141 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
142 case CAN_ACCFILT_EFF_SA:
143 EntryAddress = TableAddress + (EntryNo << 2);
146 case CAN_ACCFILT_EFF_GRP_SA:
147 EntryAddress = TableAddress + (EntryNo << 3);
149 #endif // CYGOPT_IO_CAN_EXT_CAN_ID
151 CYG_ASSERT(0, "Wrong TableAddressRegister");
158 //===========================================================================
159 // Remove one single entry from acceptance filter table
160 //===========================================================================
161 void lpc2xxx_can_accfilt_ram_remove_entry(cyg_uint32 Table, cyg_uint16 EntryNo)
163 cyg_int32 remove_address = lpc2xxx_can_accfilt_calc_entry_address(Table, EntryNo);
164 cyg_int32 entry_address;
166 cyg_uint8 entry_size = sizeof(cyg_uint32);
168 cyg_uint32 sff_grp_sa;
170 cyg_uint32 eff_grp_sa;
171 cyg_int32 end_of_table;
173 HAL_READ_UINT32(CAN_ACCFILT_SFF_SA, sff_sa);
174 HAL_READ_UINT32(CAN_ACCFILT_SFF_GRP_SA, sff_grp_sa);
175 HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, eff_sa);
176 HAL_READ_UINT32(CAN_ACCFILT_EFF_GRP_SA, eff_grp_sa);
177 HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table);
180 // Do not try to remove from an empty table
187 entry_address = remove_address;
189 if ((remove_address < eff_grp_sa) && (CAN_ACCFILT_EFF_GRP_SA != Table))
191 if ((remove_address < eff_sa) && (CAN_ACCFILT_EFF_SA != Table))
193 if ((remove_address < sff_grp_sa) && (CAN_ACCFILT_SFF_GRP_SA != Table))
199 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + remove_address, lsc_val.dword);
200 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + remove_address + sizeof(cyg_uint32), nextval.dword);
201 lsc_val.column.upper = nextval.column.lower;
202 entry_address += sizeof(cyg_uint32);
206 // Start copy immediatelly after removed entry
208 while (entry_address < sff_grp_sa)
210 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, lsc_val.dword);
211 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address + sizeof(cyg_uint32), nextval.dword);
212 lsc_val.column.lower = lsc_val.column.upper;
213 lsc_val.column.upper = nextval.column.lower;
214 HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, lsc_val.dword);
215 entry_address += sizeof(cyg_uint32);
219 // now check if the lower identifier is disabled - if it is disabled, then
220 // also the upper identifier is invalid and we can remove the entry completely
221 // if the lower identifier is not disabled, then it is valid and we need
222 // to disable the upper identifier because it contains an invalid entry
224 if (lsc_val.column.lower & ACCFILT_STD_DIS)
226 sff_grp_sa -= sizeof(cyg_uint32);
227 entry_address = sff_grp_sa;
231 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32), lsc_val.dword);
232 lsc_val.column.upper = 0xffff;
233 HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32), lsc_val.dword);
234 entry_size = 0; // we do not need to remove anything
236 } // if (pLine < pStdGrpStart)
238 eff_sa -= entry_size;
239 } // if (pLine < pExtIdStart)
241 eff_grp_sa -= entry_size;
242 } // if (pLine < pExtGrpStart)
245 // If no entry was removed then we can leave immediately without changing any
246 // table pointers because we only did a change inside the sff table
250 #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
251 lpc2xxx_can_accfilt_dbg_dump();
256 if (CAN_ACCFILT_EFF_GRP_SA == Table)
259 // If we are in the area of extended groups then we need to remove
260 // 2 lines because lower and upper identifier need 1 line each
262 entry_size += sizeof(cyg_uint32);
265 end_of_table -= entry_size;
268 // Move all entries one or two dword downwards - that means we remove a line
270 while (entry_address < end_of_table)
272 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address + entry_size, lsc_val.dword);
273 HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, lsc_val.dword);
274 entry_address += sizeof(cyg_uint32);
277 HAL_WRITE_UINT32(CAN_ACCFILT_SFF_SA, sff_sa);
278 HAL_WRITE_UINT32(CAN_ACCFILT_SFF_GRP_SA, sff_grp_sa);
279 HAL_WRITE_UINT32(CAN_ACCFILT_EFF_SA, eff_sa);
280 HAL_WRITE_UINT32(CAN_ACCFILT_EFF_GRP_SA, eff_grp_sa);
281 HAL_WRITE_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table);
283 #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
284 lpc2xxx_can_accfilt_dbg_dump();
288 //===========================================================================
289 // Insert one empty line into ram - all entries behind this line will be
290 // moved one entry upwards
291 //===========================================================================
292 void lpc2xxx_can_accfilt_ram_insert_entry(cyg_uint32 Table, cyg_uint16 EntryNo)
294 cyg_int16 insert_address = lpc2xxx_can_accfilt_calc_entry_address(Table, EntryNo);
295 cyg_int16 entry_address;
296 cyg_int16 copy_start = insert_address;
298 cyg_uint8 entry_size = sizeof(cyg_uint32);
300 cyg_uint32 sff_grp_sa;
302 cyg_uint32 eff_grp_sa;
303 cyg_uint32 end_of_table;
306 HAL_READ_UINT32(CAN_ACCFILT_SFF_SA, sff_sa);
307 HAL_READ_UINT32(CAN_ACCFILT_SFF_GRP_SA, sff_grp_sa);
308 HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, eff_sa);
309 HAL_READ_UINT32(CAN_ACCFILT_EFF_GRP_SA, eff_grp_sa);
310 HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table);
312 if ((insert_address <= eff_grp_sa) && (CAN_ACCFILT_EFF_GRP_SA != Table))
314 if ((insert_address <= eff_sa) && (CAN_ACCFILT_EFF_SA != Table))
316 if ((insert_address <= sff_grp_sa) && (CAN_ACCFILT_SFF_GRP_SA != Table))
319 // If we are in the range of standard identifiers then we need to
320 // do some special copy procedure for this area because a standard entry
321 // is only 2 byte long. Copy only til start of area with standard groups
325 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32), lsc_val.dword); // read last entry
327 // now check if the upper identifier is disabled - if it is disabled, then
328 // we have an odd number of std ids in the list. Then we do not need to
329 // insert a new line - we simply need to copy all entries 2 bytes upwards
330 // that means we only need to change the std id area and do not need to touch
331 // any other filter id area.
332 // If the last entry is not disabled, then we have a valid filter here.
333 // Then we need to insert a complete new line, that means we also have to move
334 // all following entries and filter tables one dword upwards.
336 if (lsc_val.words.low & ACCFILT_STD_DIS)
338 copy_start = end_of_table + sizeof(cyg_uint32); // we do not need to insert a new line and do not copy anything
345 copy_start = sff_grp_sa; // copy everything behind std id group
346 sff_grp_sa += entry_size;
348 } // if (pLine < pStdGrpStart)
350 eff_sa += entry_size;
351 } // if (pLine < pExtIdStart)
353 eff_grp_sa += entry_size;
354 } // if (pLine < pExtGrpStart)
356 if (CAN_ACCFILT_EFF_GRP_SA == Table)
359 // If we are in the area of extended groups then we need to insert
360 // 2 lines because lower and upper identifier need 1 line each
362 entry_size += sizeof(cyg_uint32); // one entry is 2 dword long
365 entry_address = end_of_table - sizeof(cyg_uint32);
366 end_of_table += entry_size; // add one additional entry
369 // Move all entries one or two dwords upwards - that means we insert a new empty line
371 while (entry_address >= copy_start)
373 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address, lsc_val.dword);
374 HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address + entry_size, lsc_val.dword);
375 entry_address -= sizeof(cyg_uint32);
379 // For the std ID area we need a special procedure
381 if (CAN_ACCFILT_SFF_SA == Table)
385 // Start copy with last entry of std id table
387 entry_address = sff_grp_sa - sizeof(cyg_uint32);
389 while (entry_address > insert_address)
391 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address, lsc_val.dword);
392 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address - sizeof(cyg_uint32), preval.dword);
393 lsc_val.column.upper = lsc_val.column.lower;
394 lsc_val.column.lower = preval.column.upper;
395 HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)entry_address, lsc_val.dword);
396 entry_address -= sizeof(cyg_uint32);
400 // If we insert an entry into the lower column, then we need to move the
401 // content of the lower column into the upper column
405 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)insert_address, lsc_val.dword);
406 lsc_val.column.upper = lsc_val.column.lower;
407 HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + (cyg_uint32)insert_address, lsc_val.dword);
411 // If we inserted a new line, then we have an odd number of identifiers now
412 // and need to disable the last (the upper) entry
416 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32) , lsc_val.dword);
417 lsc_val.column.upper = 0xFFFF; // disable the entry
418 HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32) , lsc_val.dword);
422 HAL_WRITE_UINT32(CAN_ACCFILT_SFF_SA, sff_sa);
423 HAL_WRITE_UINT32(CAN_ACCFILT_SFF_GRP_SA, sff_grp_sa);
424 HAL_WRITE_UINT32(CAN_ACCFILT_EFF_SA, eff_sa);
425 HAL_WRITE_UINT32(CAN_ACCFILT_EFF_GRP_SA, eff_grp_sa);
426 HAL_WRITE_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table);
430 //===========================================================================
431 // Query number of entries in a certain table
432 //===========================================================================
433 static cyg_uint16 lpc2xxx_can_accfilt_get_table_entries(cyg_uint32 TableStartAddress)
438 switch (TableStartAddress)
440 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
441 case CAN_ACCFILT_SFF_SA:
442 HAL_READ_UINT32(CAN_ACCFILT_SFF_SA, start);
443 HAL_READ_UINT32(CAN_ACCFILT_SFF_GRP_SA, end);
447 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + end - sizeof(cyg_uint32), data.dword);
448 if (data.column.upper & ACCFILT_STD_DIS)
450 return (((end - start) >> 1) - 1);
453 return (end - start) >> 1;
455 case CAN_ACCFILT_SFF_GRP_SA:
456 HAL_READ_UINT32(CAN_ACCFILT_SFF_GRP_SA, start);
457 HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, end);
458 return (end - start) >> 2;
459 #endif // CYGOPT_IO_CAN_STD_CAN_ID
461 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
462 case CAN_ACCFILT_EFF_SA:
463 HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, start);
464 HAL_READ_UINT32(CAN_ACCFILT_EFF_GRP_SA, end);
465 return (end - start) >> 2;
467 case CAN_ACCFILT_EFF_GRP_SA:
468 HAL_READ_UINT32(CAN_ACCFILT_EFF_GRP_SA, start);
469 HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end);
470 return (end - start) >> 3;
471 #endif // CYGOPT_IO_CAN_EXT_CAN_ID
473 CYG_FAIL("Invalid identifier table address");
475 } // switch (TableStartAddress)
478 //===========================================================================
479 // Query certain entry from table
480 //===========================================================================
481 static void lpc2xxx_can_accfilt_get_entry(cyg_uint32 TableStartAddress, cyg_uint16 EntryNo, lpc2xxx_accfilt_entry_t *pEntry)
483 cyg_uint32 EntryAddress = lpc2xxx_can_accfilt_calc_entry_address(TableStartAddress, EntryNo);
486 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress, Data.dword);
487 pEntry->data = Data.dword;
488 switch (TableStartAddress)
490 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
491 case CAN_ACCFILT_SFF_SA:
496 column = Data.column.upper;
500 column = Data.column.lower;
502 pEntry->id = ACCFILT_STD_GET_ID(column);
503 pEntry->channel_no = ACCFILT_STD_GET_CTRL(column);
507 case CAN_ACCFILT_SFF_GRP_SA:
508 pEntry->lower_id_bound = ACCFILT_STD_GET_ID(Data.column.lower);
509 pEntry->upper_id_bound = ACCFILT_STD_GET_ID(Data.column.upper);
510 pEntry->channel_no = ACCFILT_STD_GET_CTRL(Data.column.lower);
512 #endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID
514 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
515 case CAN_ACCFILT_EFF_SA:
516 pEntry->id = ACCFILT_EXT_GET_ID(Data.dword);
517 pEntry->channel_no = ACCFILT_EXT_GET_CTRL(Data.dword);
520 case CAN_ACCFILT_EFF_GRP_SA:
521 pEntry->lower_id_bound = ACCFILT_EXT_GET_ID(Data.dword);
522 pEntry->channel_no = ACCFILT_EXT_GET_CTRL(Data.dword);
523 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE+ EntryAddress + sizeof(cyg_uint32), Data.dword);
524 pEntry->upper_id_bound = ACCFILT_EXT_GET_ID(Data.dword);
526 #endif // #ifedf CYGOPT_IO_CAN_EXT_CAN_ID
528 CYG_FAIL("Invalid identifier table address");
533 //===========================================================================
534 // Set certain entry in table
535 //===========================================================================
536 static void lpc2xxx_can_accfilt_set_entry(cyg_uint32 TableStartAddress, cyg_uint16 EntryNo, lpc2xxx_accfilt_entry_t *pEntry)
538 cyg_uint32 EntryAddress = lpc2xxx_can_accfilt_calc_entry_address(TableStartAddress, EntryNo);
541 switch (TableStartAddress)
543 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
544 case CAN_ACCFILT_SFF_SA:
546 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress, Data.dword);
549 Data.column.upper = (pEntry->channel_no << 13) | (pEntry->id & ACCFILT_STD_ID_MASK);
553 Data.column.lower = (pEntry->channel_no << 13) | (pEntry->id & ACCFILT_STD_ID_MASK);
558 case CAN_ACCFILT_SFF_GRP_SA:
559 Data.column.lower = (pEntry->channel_no << 13) | (pEntry->lower_id_bound & ACCFILT_STD_ID_MASK);
560 Data.column.upper = (pEntry->channel_no << 13) | (pEntry->upper_id_bound & ACCFILT_STD_ID_MASK);
562 #endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID
564 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
565 case CAN_ACCFILT_EFF_SA:
566 Data.dword = (pEntry->channel_no << 29) | (pEntry->id & ACCFILT_EXT_ID_MASK);
569 case CAN_ACCFILT_EFF_GRP_SA:
573 Data.dword = (pEntry->channel_no << 29) | (pEntry->lower_id_bound & ACCFILT_EXT_ID_MASK);
574 Data2.dword = (pEntry->channel_no << 29) | (pEntry->upper_id_bound & ACCFILT_EXT_ID_MASK);
575 HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress + sizeof(cyg_uint32), Data2.dword);
578 #endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
581 CYG_FAIL("Invalid identifier table address");
584 HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress, Data.dword);
588 //===========================================================================
589 // Add one entry to acceptance filter RAM
590 // If upper ID is > lower ID then we have to add a group filter - else we
591 // have to add a single message filter here
592 //===========================================================================
593 static bool lpc2xxx_can_accfilt_add(lpc2xxx_can_info_t *info,
598 cyg_uint32 accfilt_bck; // acceptance filter backup
599 cyg_uint32 end_of_table;
601 lpc2xxx_accfilt_entry_t entry;
602 lpc2xxx_accfilt_entry_t new_entry;
606 // first step: disable acceptance filter and prepare it for modification
608 HAL_READ_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
609 HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF | AFMR_BYPASS);
612 // Check if table is full
614 HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table);
615 if (end_of_table >= ACCFILT_RAM_SIZE)
620 new_entry.id = lower_id;
621 new_entry.lower_id_bound = lower_id;
622 new_entry.upper_id_bound = upper_id;
625 // Here we rely on the ISR vector ordering for calculation of channel number
626 // Maybe this is not the right way for newer LPC parts
628 new_entry.channel_no = CAN_CHAN_NO_LUT(info);
631 // If lower_id == upper_id then we know that we have to setup a single message filter
632 // here. If it is not equal the it is group of identifiers to receive
634 if ((lower_id == upper_id) || (lower_id > upper_id))
637 // setup single message filter (standard or extended) here
639 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
642 table = CAN_ACCFILT_EFF_SA;
645 #endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
647 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
648 table = CAN_ACCFILT_SFF_SA;
649 #endif // CYGOPT_IO_CAN_STD_CAN_ID
655 // setup single message filter (standard or extended) here
657 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
660 table = CAN_ACCFILT_EFF_GRP_SA;
663 #endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
665 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
666 table = CAN_ACCFILT_SFF_GRP_SA;
667 #endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID
671 cyg_uint16 entries = lpc2xxx_can_accfilt_get_table_entries(table);
675 for (i = 0; i < entries; ++i)
677 lpc2xxx_can_accfilt_get_entry(table, i, &entry);
679 if (entry.channel_no > new_entry.channel_no)
684 if ((entry.channel_no == new_entry.channel_no)
685 && (entry.id > new_entry.id))
689 } // for (i = 0; i < entries; ++i)
691 lpc2xxx_can_accfilt_ram_insert_entry(table, i);
692 lpc2xxx_can_accfilt_set_entry(table, i, &new_entry);
695 // finally restore the previous state of the acceptance filter
697 HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
702 //===========================================================================
703 // Remove all entries from a certain controller
704 //===========================================================================
705 void lpc2xxx_can_accfilt_remove_all_ctrl_entries(lpc2xxx_can_info_t *info)
707 cyg_uint32 accfilt_bck; // acceptance filter backup
710 cyg_uint32 TableStartAddress = CAN_ACCFILT_SFF_SA;
711 lpc2xxx_accfilt_entry_t Entry;
712 cyg_uint8 channel_no = CAN_CHAN_NO_LUT(info);
713 cyg_uint16 entry_idx;
716 // first step: disable acceptance filter and prepare it for modification
718 HAL_READ_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
719 HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF | AFMR_BYPASS);
722 // now remove all entries for a certain controller
724 for (TableStartAddress = CAN_ACCFILT_SFF_SA; TableStartAddress < CAN_ACCFILT_ENDOFTABLE; TableStartAddress += 4)
726 entries = lpc2xxx_can_accfilt_get_table_entries(TableStartAddress);
728 for (i = 0; i < entries; ++i)
730 lpc2xxx_can_accfilt_get_entry(TableStartAddress, entry_idx, &Entry);
731 if (Entry.channel_no == channel_no)
733 lpc2xxx_can_accfilt_ram_remove_entry(TableStartAddress, entry_idx);
739 } // for (i = 0; i < entries; ++i)
740 } // for (TableStartAddress = CAN_ACCFILT_SFF_SA ...
743 // finally restore the previous state of the acceptance filter
745 HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
747 #endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
750 #ifndef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
751 //===========================================================================
752 // Setup reception of all CAN identifiers
753 // If runtime acceptance filter configuration is not required then we simply
754 // setup the acceptance filter here to receive all CAN identifiers
755 //===========================================================================
756 static void lpc2xxx_can_accfilt_simple_rx_all(void)
761 // First check if it is really necessary to setup filters. If end of table is
762 // != 0 then the acceptance filter is already setup properly
764 HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, regval);
770 cyg_uint32 accfilt_bck; // acceptance filter backup
771 cyg_uint8 i = 0; // loop counter
772 lsc_buf_t accfilt_entry; // std group entry
773 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
774 cyg_uint8 std_address = 0; // std group entry address
775 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
776 cyg_uint8 ext_address = lpc2xxx_global_can_info.init_cnt << 2;
779 cyg_uint8 ext_address = 0;
783 // first step: disable acceptance filter and prepare it for modification
785 HAL_READ_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
786 HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF | AFMR_BYPASS);
789 // Write table start adresses - we use only standard group and extended filter
792 HAL_WRITE_UINT32(CAN_ACCFILT_SFF_SA, 0);
793 HAL_WRITE_UINT32(CAN_ACCFILT_SFF_GRP_SA, 0);
794 HAL_WRITE_UINT32(CAN_ACCFILT_EFF_SA, ext_address);
795 HAL_WRITE_UINT32(CAN_ACCFILT_EFF_GRP_SA, ext_address);
798 // Now loop through all active CAN channels and setup the acceptance filter for
799 // each channel to receive all standard and extended CAN identifiers
801 while (lpc2xxx_global_can_info.active_channels[i])
803 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)lpc2xxx_global_can_info.active_channels[i++]->dev_priv;
804 cyg_uint8 channel_no = CAN_CHAN_NO_LUT(info);
806 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
807 accfilt_entry.column.lower = (channel_no << 13) | (0x000 & ACCFILT_STD_ID_MASK);
808 accfilt_entry.column.upper = (channel_no << 13) | (0x7FF & ACCFILT_STD_ID_MASK);
809 HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + std_address, accfilt_entry.dword);
810 std_address += sizeof(cyg_uint32);
811 #endif // CYGOPT_IO_CAN_STD_CAN_ID
813 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
814 accfilt_entry.dword = (channel_no << 29) | (0x00000000 & ACCFILT_EXT_ID_MASK);
815 HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + ext_address, accfilt_entry.dword);
816 ext_address += sizeof(cyg_uint32);
817 accfilt_entry.dword = (channel_no << 29) | (0x1FFFFFFF & ACCFILT_EXT_ID_MASK);
818 HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + ext_address, accfilt_entry.dword);
819 ext_address += sizeof(cyg_uint32);
820 #endif // CYGOPT_IO_CAN_EXT_CAN_ID
821 } // while (lpc2xxx_global_can_info.active_channels[i])
824 // finally store end of table value and restore the previous state of the
827 HAL_WRITE_UINT32(CAN_ACCFILT_ENDOFTABLE, ext_address);
828 HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
830 #endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
833 //===========================================================================
834 // Reset acceptance filter to poweron defaults
835 //===========================================================================
836 void lpc2xxx_can_accfilt_reset(void)
838 cyg_uint32 accfilt_bck; // acceptance filter backup
840 // first step: disable acceptance filter and prepare it for modification
842 HAL_READ_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
843 HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF | AFMR_BYPASS);
846 // Now write zero to all addresses of acceptance filter table
848 HAL_WRITE_UINT32(CAN_ACCFILT_SFF_SA, 0);
849 HAL_WRITE_UINT32(CAN_ACCFILT_SFF_GRP_SA, 0);
850 HAL_WRITE_UINT32(CAN_ACCFILT_EFF_SA, 0);
851 HAL_WRITE_UINT32(CAN_ACCFILT_EFF_GRP_SA, 0);
852 HAL_WRITE_UINT32(CAN_ACCFILT_ENDOFTABLE, 0);
855 // finally restore the previous state of the acceptance filter
857 HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
861 //===========================================================================
862 // Dump content of acceptance filter lookup table
863 //===========================================================================
864 #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
865 void lpc2xxx_can_accfilt_dbg_dump(void)
868 cyg_uint32 sff_grp_sa;
870 cyg_uint32 eff_grp_sa;
871 cyg_uint32 end_of_table;
872 cyg_uint32 entry_address;
876 HAL_READ_UINT32(CAN_ACCFILT_SFF_SA, sff_sa);
877 HAL_READ_UINT32(CAN_ACCFILT_SFF_GRP_SA, sff_grp_sa);
878 HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, eff_sa);
879 HAL_READ_UINT32(CAN_ACCFILT_EFF_GRP_SA, eff_grp_sa);
880 HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table);
882 entry_address = sff_sa;
885 // Print lookup table registers
887 diag_printf("\n\nDUMP CAN ACCEPTANCE FILTER REGISTERS\n");
888 diag_printf("----------------------------------------\n");
889 diag_printf("SFF_sa:\t\t0x%08x\n", sff_sa);
890 diag_printf("SFF_GRP_sa:\t0x%08x\n", sff_grp_sa);
891 diag_printf("EFF_sa:\t\t0x%08x\n", eff_sa);
892 diag_printf("EFF_GRP_sa:\t0x%08x\n", eff_grp_sa);
893 diag_printf("EOT:\t\t0x%08x\n", end_of_table);
896 // Print table of standard identifiers
898 diag_printf("\n\nDUMP CAN LOOKUP TABLE RAM");
899 diag_printf("\nSFF_sa\t\tcolumn_lower\tcolumn_upper\traw_data\n");
900 diag_printf("----------------------------------------------------------\n");
901 while (entry_address < sff_grp_sa)
903 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, data.dword);
904 diag_printf("0x%04x:\t\t0x%x\t\t0x%x\t\t0x%x\n", entry_address, data.column.lower, data.column.upper, data.dword);
905 entry_address += sizeof(cyg_uint32);
909 // Print table of standard identifier groups
911 diag_printf("\nSFF_GRP_sa\tcolumn_lower\tcolumn_upper\traw_data\n");
912 diag_printf("----------------------------------------------------------\n");
913 while (entry_address < eff_sa)
915 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, data.dword);
916 diag_printf("0x%04x:\t\t0x%x\t\t0x%x\t\t0x%x\n", entry_address, data.column.lower, data.column.upper, data.dword);
917 entry_address += sizeof(cyg_uint32);
921 // Print table of extended identifiers
923 diag_printf("\nEFF_sa\t\t-\t\t-\t\traw_data\n");
924 diag_printf("----------------------------------------------------------\n");
925 while (entry_address < eff_grp_sa)
927 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, data.dword);
928 diag_printf("0x%04x:\t\t\t\t\t\t0x%x\n", entry_address, data.dword);
929 entry_address += sizeof(cyg_uint32);
933 // Print table of extended identifier groups
935 diag_printf("\nEFF_GRP_sa\t-\t\t-\t\traw_data\n");
936 diag_printf("----------------------------------------------------------\n");
937 while (entry_address < end_of_table)
939 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + entry_address, data.dword);
940 diag_printf("0x%04x:\t\t\t\t\t\t0x%x\n", entry_address, data.dword);
941 entry_address += sizeof(cyg_uint32);
944 #endif // CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
946 //===========================================================================
947 // Dump content of acceptance filter lookup table
948 //===========================================================================
949 #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
950 void lpc2xxx_can_reg_dump(struct cyg_devtab_entry* devtab_entry)
952 can_channel *chan = (can_channel*)devtab_entry->priv;
954 CAN_DECLARE_INFO(chan);
956 chan = chan; // avoid compiler warnings for unused variables
958 // Print table of extended identifier groups
960 diag_printf("\n\nCAN REGISTER DUMP\n");
961 diag_printf("\nRegister\tValue\n");
962 diag_printf("----------------------------------------------------------\n");
963 HAL_READ_UINT32(CAN_CTRL_MOD(info), reg_val);
964 diag_printf("CANMOD\t\t0x%08x\n", reg_val);
965 HAL_READ_UINT32(CAN_CTRL_CMR(info), reg_val);
966 diag_printf("CANCMR\t\t0x%08x\n", reg_val);
967 HAL_READ_UINT32(CAN_CTRL_GSR(info), reg_val);
968 diag_printf("CANGSR\t\t0x%08x\n", reg_val);
969 HAL_READ_UINT32(CAN_CTRL_ICR(info), reg_val);
970 diag_printf("CANICR\t\t0x%08x\n", reg_val);
971 HAL_READ_UINT32(CAN_CTRL_IER(info), reg_val);
972 diag_printf("CANIER\t\t0x%08x\n", reg_val);
973 HAL_READ_UINT32(CAN_CTRL_BTR(info), reg_val);
974 diag_printf("CANBTR\t\t0x%08x\n", reg_val);
975 HAL_READ_UINT32(CAN_CTRL_EWL(info), reg_val);
976 diag_printf("CANEWL\t\t0x%08x\n", reg_val);
977 HAL_READ_UINT32(CAN_CTRL_SR(info), reg_val);
978 diag_printf("CANSR\t\t0x%08x\n", reg_val);
979 HAL_READ_UINT32(CAN_CTRL_RFS(info), reg_val);
980 diag_printf("CANRFS\t\t0x%08x\n", reg_val);
981 HAL_READ_UINT32(CAN_CTRL_RID(info), reg_val);
982 diag_printf("CANRID\t\t0x%08x\n", reg_val);
983 HAL_READ_UINT32(CAN_CTRL_RDA(info), reg_val);
984 diag_printf("CANRDA\t\t0x%08x\n", reg_val);
985 HAL_READ_UINT32(CAN_CTRL_RDB(info), reg_val);
986 diag_printf("CANRDB\t\t0x%08x\n", reg_val);
988 diag_printf("\n\nCAN CENTRAL REGISTER DUMP\n");
989 diag_printf("\nRegister\tValue\n");
990 diag_printf("----------------------------------------------------------\n");
991 HAL_READ_UINT32(CAN_CENTRAL_TXSR, reg_val);
992 diag_printf("CANTxSR\t\t0x%08x\n", reg_val);
993 HAL_READ_UINT32(CAN_CENTRAL_RXSR, reg_val);
994 diag_printf("CANRxSR\t\t0x%08x\n", reg_val);
995 HAL_READ_UINT32(CAN_CENTRAL_MSR, reg_val);
996 diag_printf("CANMSR\t\t0x%08x\n", reg_val);
998 diag_printf("\n\nCAN ACCEPTANCE FILTER REGISTER DUMP\n");
999 diag_printf("\nRegister\tValue\n");
1000 diag_printf("----------------------------------------------------------\n");
1001 HAL_READ_UINT32(CAN_ACCFILT_AFMR, reg_val);
1002 diag_printf("AFMR\t\t0x%08x\n", reg_val);
1003 HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR, reg_val);
1004 diag_printf("LUTERR\t\t0x%08x\n", reg_val);
1005 HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR_ADDR, reg_val);
1006 diag_printf("LUTERRADDR\t0x%08x\n", reg_val);
1008 #endif // #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
1010 //---------------------------------------------------------------------------
1011 // EOF can_accfilt_lpc2xxx.c