]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/devs/can/arm/lpc2xxx/v2_0/src/can_accfilt_lpc2xxx.c
Initial revision
[karo-tx-redboot.git] / packages / devs / can / arm / lpc2xxx / v2_0 / src / can_accfilt_lpc2xxx.c
1 //==========================================================================
2 //
3 //      devs/can/arm/lpc2xxx/current/src/can_accfilt_lpc2xxx.c
4 //
5 //      Acceptance filter management for LPC2xxx CAN driver
6 //
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
13 //
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.
17 //
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
21 // for more details.
22 //
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.
26 //
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.
33 //
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.
36 //
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####
43 //
44 // Author(s):    Uwe Kindler
45 // Contributors: Uwe Kindler
46 // Date:         2007-05-28
47 // Purpose:      Support LPC2xxx on-chip CAN acceptance filters
48 // Description: 
49 //
50 //####DESCRIPTIONEND####
51 //
52 //==========================================================================
53
54
55 //===========================================================================
56 // Data types
57 //===========================================================================
58 //
59 // Acceptance filter entry
60 //
61 typedef struct lpc2xxx_accfilt_entry
62 {
63     cyg_uint32 data;          // the value inclusive channel number
64     cyg_uint32 id;
65     cyg_uint32 lower_id_bound;
66     cyg_uint32 upper_id_bound;
67     cyg_uint8  channel_no;
68 } lpc2xxx_accfilt_entry_t;
69
70
71 //===========================================================================
72 // Declarations
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.
78 //
79 // On the LPC2468 the LUT channel numbers are also numbered from 0 - 4.
80 //
81 #if defined(CYGHWR_HAL_ARM_LPC2XXX_SUFFIX_01) || (CYGHWR_HAL_ARM_LPC2XXX_VARIANT_VERSION == 4)
82 # define LPC2XXX_CAN_FIRST_IN_LUT   (0)
83 #else
84 # define LPC2XXX_CAN_FIRST_IN_LUT   (1) 
85 #endif
86
87 //
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
93 // code
94 //
95 #define CAN_CHAN_NO_LUT(_info_) (CAN_CHAN_NO(_info_) + LPC2XXX_CAN_FIRST_IN_LUT)
96
97 //--------------------------------------------------------------------------
98 // Lowlevel acceptance filter access
99 //
100 #ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
101 static bool lpc2xxx_can_accfilt_add(lpc2xxx_can_info_t *info, 
102                                     cyg_uint32          lower_id, 
103                                     cyg_uint32          upper_id, 
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);
108 #else
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);
112
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);
116 #endif
117
118
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)
124 {
125     cyg_uint32 EntryAddress = 0xFFFFFFFF;
126     cyg_uint32 TableAddress;
127     
128     HAL_READ_UINT32(TableAddressRegister, TableAddress); 
129     switch (TableAddressRegister) 
130     {
131 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
132     case CAN_ACCFILT_SFF_SA:
133          EntryAddress = ((EntryNo / 2) << 2) + TableAddress; 
134          break;
135              
136     case CAN_ACCFILT_SFF_GRP_SA:
137          EntryAddress = TableAddress + (EntryNo << 2);
138          break;
139 #endif // CYGOPT_IO_CAN_STD_CAN_ID
140
141 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
142     case CAN_ACCFILT_EFF_SA:
143          EntryAddress = TableAddress + (EntryNo << 2);
144          break;
145                     
146     case CAN_ACCFILT_EFF_GRP_SA:
147          EntryAddress = TableAddress + (EntryNo << 3);
148          break; 
149 #endif // CYGOPT_IO_CAN_EXT_CAN_ID
150     default:
151         CYG_ASSERT(0, "Wrong TableAddressRegister");
152     }  
153     
154     return EntryAddress;
155 }
156
157
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)
162 {
163     cyg_int32   remove_address = lpc2xxx_can_accfilt_calc_entry_address(Table, EntryNo);
164     cyg_int32   entry_address;
165     lsc_buf_t   lsc_val;
166     cyg_uint8   entry_size = sizeof(cyg_uint32);
167     cyg_uint32  sff_sa;
168     cyg_uint32  sff_grp_sa;
169     cyg_uint32  eff_sa;
170     cyg_uint32  eff_grp_sa;
171     cyg_int32   end_of_table;  
172     
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);
178    
179     //
180     // Do not try to remove from an empty table
181     //
182     if (!end_of_table)
183     {
184         return;
185     }
186         
187     entry_address = remove_address;
188     
189     if ((remove_address < eff_grp_sa) && (CAN_ACCFILT_EFF_GRP_SA != Table))
190     {
191         if ((remove_address < eff_sa) && (CAN_ACCFILT_EFF_SA != Table))
192         {
193             if ((remove_address < sff_grp_sa) && (CAN_ACCFILT_SFF_GRP_SA != Table))
194             { 
195                 lsc_buf_t nextval;
196                 
197                 if (EntryNo % 2)
198                 {
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);
203                 }
204                 
205                 //
206                 // Start copy immediatelly after removed entry
207                 //   
208                 while (entry_address < sff_grp_sa)
209                 {
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);
216                 }
217                 
218                 //
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
223                 //           
224                 if (lsc_val.column.lower & ACCFILT_STD_DIS)
225                 {
226                     sff_grp_sa -= sizeof(cyg_uint32);  
227                     entry_address = sff_grp_sa;
228                 }
229                 else
230                 {
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
235                 }
236             } // if (pLine < pStdGrpStart)
237             
238             eff_sa -= entry_size;          
239         } // if (pLine < pExtIdStart)
240         
241         eff_grp_sa -= entry_size;         
242     } // if (pLine < pExtGrpStart)
243     
244     //
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
247     //
248     if (!entry_size)
249     {
250 #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
251         lpc2xxx_can_accfilt_dbg_dump();
252 #endif
253         return;
254     }
255     
256     if (CAN_ACCFILT_EFF_GRP_SA == Table)
257     {
258         //
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
261         //  
262         entry_size += sizeof(cyg_uint32);
263     }
264     
265     end_of_table -= entry_size;
266   
267     //
268     // Move all entries one or two dword downwards - that means we remove a line
269     //
270     while (entry_address < end_of_table)
271     {
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);
275     }
276     
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);
282     
283 #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
284     lpc2xxx_can_accfilt_dbg_dump();
285 #endif
286 }
287
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)
293 {
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;
297     lsc_buf_t   lsc_val;
298     cyg_uint8   entry_size = sizeof(cyg_uint32);
299     cyg_uint32  sff_sa;
300     cyg_uint32  sff_grp_sa;
301     cyg_uint32  eff_sa;
302     cyg_uint32  eff_grp_sa;
303     cyg_uint32  end_of_table;
304     
305     
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);
311     
312     if ((insert_address <= eff_grp_sa) && (CAN_ACCFILT_EFF_GRP_SA != Table))
313     {
314         if ((insert_address <= eff_sa) && (CAN_ACCFILT_EFF_SA != Table))
315         {
316             if ((insert_address <= sff_grp_sa) && (CAN_ACCFILT_SFF_GRP_SA != Table))
317             {
318                 //
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
322                 //
323                 if (sff_grp_sa)
324                 {
325                     HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + sff_grp_sa - sizeof(cyg_uint32), lsc_val.dword); // read last entry
326                     //
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.
335                     //
336                     if (lsc_val.words.low & ACCFILT_STD_DIS)
337                     {
338                         copy_start = end_of_table + sizeof(cyg_uint32); // we do not need to insert a new line and do not copy anything
339                         entry_size = 0;          
340                     }
341                 }
342                 
343                 if (entry_size)
344                 {
345                     copy_start = sff_grp_sa;          // copy everything behind std id group
346                     sff_grp_sa += entry_size;   
347                 }
348             } // if (pLine < pStdGrpStart)
349             
350             eff_sa += entry_size;
351         } // if (pLine < pExtIdStart)
352         
353         eff_grp_sa += entry_size;
354     } // if (pLine < pExtGrpStart)
355           
356     if (CAN_ACCFILT_EFF_GRP_SA == Table)
357     {
358         //
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
361         //
362         entry_size += sizeof(cyg_uint32); // one entry is 2 dword long
363     }
364     
365     entry_address = end_of_table - sizeof(cyg_uint32);
366     end_of_table  += entry_size;  // add one additional entry
367         
368     //
369     // Move all entries one or two dwords upwards - that means we insert a new empty line
370     //
371     while (entry_address >= copy_start)
372     {
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);  
376     }
377     
378     //
379     // For the std ID area we need a special procedure
380     //
381     if (CAN_ACCFILT_SFF_SA == Table)
382     {
383         lsc_buf_t preval;
384         //
385         // Start copy with last entry of std id table
386         //
387         entry_address = sff_grp_sa - sizeof(cyg_uint32);    
388                 
389         while (entry_address > insert_address)
390         {
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);
397         }
398         
399         //
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
402         //
403         if (!(EntryNo % 2))
404         {
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);
408         }
409         
410         //
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
413         //
414         if (entry_size)
415         {
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);
419         }
420     }
421     
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);
427 }
428
429
430 //===========================================================================
431 // Query number of entries in a certain table
432 //===========================================================================
433 static cyg_uint16 lpc2xxx_can_accfilt_get_table_entries(cyg_uint32 TableStartAddress)
434 {
435     cyg_uint32  start;
436     cyg_uint32  end;
437     
438     switch (TableStartAddress)
439     {
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);
444          if (end - start)
445          {
446              lsc_buf_t data;
447              HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + end - sizeof(cyg_uint32), data.dword);
448              if (data.column.upper & ACCFILT_STD_DIS)
449              {
450                  return (((end - start) >> 1) - 1);
451              }
452          }
453          return (end - start) >> 1;
454          
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
460
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;
466                  
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
472     default:
473         CYG_FAIL("Invalid identifier table address");
474         return 0;         
475     } // switch (TableStartAddress)
476 }
477
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)
482 {
483     cyg_uint32 EntryAddress = lpc2xxx_can_accfilt_calc_entry_address(TableStartAddress, EntryNo);
484     lsc_buf_t  Data;
485
486     HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress, Data.dword);
487     pEntry->data = Data.dword;
488     switch (TableStartAddress)
489     {
490 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
491     case CAN_ACCFILT_SFF_SA:
492     {
493          cyg_uint16 column; 
494          if (EntryNo % 2)
495          {
496              column = Data.column.upper;
497          }
498          else
499          {
500              column = Data.column.lower; 
501          }
502          pEntry->id         = ACCFILT_STD_GET_ID(column);
503          pEntry->channel_no = ACCFILT_STD_GET_CTRL(column);
504     }
505     break;
506                  
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);
511          break;
512 #endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID
513     
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);
518          break;
519                         
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);
525          break;
526 #endif // #ifedf CYGOPT_IO_CAN_EXT_CAN_ID
527     default:
528         CYG_FAIL("Invalid identifier table address");
529     } // switch ()
530 }
531
532
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)
537 {
538     cyg_uint32 EntryAddress = lpc2xxx_can_accfilt_calc_entry_address(TableStartAddress, EntryNo);
539     lsc_buf_t Data;
540
541     switch (TableStartAddress)
542     {
543 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
544     case CAN_ACCFILT_SFF_SA:
545          {
546              HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress, Data.dword);            
547              if (EntryNo % 2)
548              {
549                  Data.column.upper = (pEntry->channel_no << 13) | (pEntry->id & ACCFILT_STD_ID_MASK);
550              }
551              else
552              {
553                  Data.column.lower = (pEntry->channel_no << 13) | (pEntry->id & ACCFILT_STD_ID_MASK);
554              }
555          }
556          break;
557                  
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);
561          break;
562 #endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID
563
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); 
567          break;
568                         
569     case CAN_ACCFILT_EFF_GRP_SA:
570          {
571              lsc_buf_t Data2;
572              
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);
576          }
577          break;
578 #endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
579          
580     default:
581         CYG_FAIL("Invalid identifier table address");
582     } // switch ()
583     
584     HAL_WRITE_UINT32(CAN_ACCFILT_RAM_BASE + EntryAddress, Data.dword);
585 }
586
587
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, 
594                                     cyg_uint32          lower_id, 
595                                     cyg_uint32          upper_id, 
596                                     cyg_can_id_type     ext)
597 {
598     cyg_uint32              accfilt_bck; // acceptance filter backup
599     cyg_uint32              end_of_table;
600     cyg_uint32              table;
601     lpc2xxx_accfilt_entry_t entry;
602     lpc2xxx_accfilt_entry_t new_entry;
603     
604     
605     //
606     // first step: disable acceptance filter and prepare it for modification
607     //
608     HAL_READ_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
609     HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF | AFMR_BYPASS);
610     
611     //
612     // Check if table is full
613     //
614     HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table);
615     if (end_of_table >= ACCFILT_RAM_SIZE)
616     {
617         return false;   
618     }
619     
620     new_entry.id             = lower_id;
621     new_entry.lower_id_bound = lower_id;
622     new_entry.upper_id_bound = upper_id;
623     
624     //
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
627     //
628     new_entry.channel_no = CAN_CHAN_NO_LUT(info);
629     
630     //
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
633     //
634     if ((lower_id == upper_id) || (lower_id > upper_id))
635     {
636         //
637         // setup single message filter (standard or extended) here
638         //
639 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
640         if (ext)
641         {
642             table = CAN_ACCFILT_EFF_SA;
643         }
644         else
645 #endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
646         {
647 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
648             table = CAN_ACCFILT_SFF_SA;
649 #endif // CYGOPT_IO_CAN_STD_CAN_ID
650         }
651     }
652     else
653     {
654         //
655         // setup single message filter (standard or extended) here
656         //
657 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
658         if (ext)
659         {
660             table = CAN_ACCFILT_EFF_GRP_SA;
661         }
662         else
663 #endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
664         {
665 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
666             table = CAN_ACCFILT_SFF_GRP_SA;
667 #endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID
668         }
669     }
670         
671     cyg_uint16 entries = lpc2xxx_can_accfilt_get_table_entries(table);
672     cyg_uint16 i;
673     
674            
675     for (i = 0; i < entries; ++i)
676     {
677         lpc2xxx_can_accfilt_get_entry(table, i, &entry);
678
679         if (entry.channel_no > new_entry.channel_no)
680         {
681             break;
682         }
683         
684         if ((entry.channel_no == new_entry.channel_no)
685         &&  (entry.id > new_entry.id))
686         {
687             break;
688         }
689     } // for (i = 0; i < entries; ++i)
690     
691     lpc2xxx_can_accfilt_ram_insert_entry(table, i);
692     lpc2xxx_can_accfilt_set_entry(table, i, &new_entry);
693
694     //
695     // finally restore the previous state of the acceptance filter
696     //
697     HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
698     return true;
699 }
700
701
702 //===========================================================================
703 // Remove all entries from a certain controller
704 //===========================================================================
705 void lpc2xxx_can_accfilt_remove_all_ctrl_entries(lpc2xxx_can_info_t *info)
706 {
707     cyg_uint32               accfilt_bck; // acceptance filter backup
708     cyg_uint16               i;
709     cyg_uint16               entries;
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;
714     
715     //
716     // first step: disable acceptance filter and prepare it for modification
717     //
718     HAL_READ_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
719     HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF | AFMR_BYPASS);
720     
721     //
722     // now remove all entries for a certain controller
723     //
724     for (TableStartAddress = CAN_ACCFILT_SFF_SA; TableStartAddress < CAN_ACCFILT_ENDOFTABLE; TableStartAddress += 4)
725     {
726         entries = lpc2xxx_can_accfilt_get_table_entries(TableStartAddress);
727         entry_idx = 0;
728         for (i = 0; i < entries; ++i)
729         {
730             lpc2xxx_can_accfilt_get_entry(TableStartAddress, entry_idx, &Entry);
731             if (Entry.channel_no == channel_no)
732             {
733                lpc2xxx_can_accfilt_ram_remove_entry(TableStartAddress, entry_idx);
734             }
735             else
736             {
737                 entry_idx++;
738             }
739         } // for (i = 0; i < entries; ++i)
740     } // for (TableStartAddress = CAN_ACCFILT_SFF_SA ...
741     
742     //
743     // finally restore the previous state of the acceptance filter
744     //
745     HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
746 }
747 #endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
748
749
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)
757 {
758     cyg_uint32                regval;
759     
760     //
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
763     //
764     HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, regval);
765     if (regval)
766     {
767         return;
768     }
769     
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;
777 #endif
778 #else
779     cyg_uint8                 ext_address = 0;
780 #endif
781     
782     //
783     // first step: disable acceptance filter and prepare it for modification
784     //
785     HAL_READ_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
786     HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF | AFMR_BYPASS);
787     
788     //
789     // Write table start adresses - we use only standard group and extended filter
790     // group
791     //
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);
796     
797     //
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
800     //
801     while (lpc2xxx_global_can_info.active_channels[i])
802     {
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);
805
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
812
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])
822        
823     //
824     // finally store end of table value and restore the previous state of the 
825     // acceptance filter
826     //
827     HAL_WRITE_UINT32(CAN_ACCFILT_ENDOFTABLE, ext_address);
828     HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
829 }
830 #endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
831
832
833 //===========================================================================
834 // Reset acceptance filter to poweron defaults
835 //===========================================================================
836 void lpc2xxx_can_accfilt_reset(void)
837 {
838     cyg_uint32  accfilt_bck; // acceptance filter backup
839     //
840     // first step: disable acceptance filter and prepare it for modification
841     //
842     HAL_READ_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
843     HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF | AFMR_BYPASS);
844     
845     //
846     // Now write zero to all addresses of acceptance filter table
847     //
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);
853     
854     //
855     // finally restore the previous state of the acceptance filter
856     //
857     HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, accfilt_bck);
858 }
859
860
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)
866 {
867     cyg_uint32          sff_sa;
868     cyg_uint32          sff_grp_sa;
869     cyg_uint32          eff_sa;
870     cyg_uint32          eff_grp_sa;
871     cyg_uint32          end_of_table;
872     cyg_uint32          entry_address;
873     lsc_buf_t           data;
874     
875     
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);
881     
882     entry_address = sff_sa;
883     
884     //
885     // Print lookup table registers
886     //
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);
894     
895     //
896     // Print table of standard identifiers
897     //
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)
902     {
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);   
906     }
907     
908     //
909     // Print table of standard identifier groups
910     //
911     diag_printf("\nSFF_GRP_sa\tcolumn_lower\tcolumn_upper\traw_data\n");
912     diag_printf("----------------------------------------------------------\n");
913     while (entry_address < eff_sa)
914     {  
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); 
918     }
919     
920     //
921     // Print table of extended identifiers
922     //
923     diag_printf("\nEFF_sa\t\t-\t\t-\t\traw_data\n");
924     diag_printf("----------------------------------------------------------\n");
925     while (entry_address < eff_grp_sa)
926     {
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);
930     }
931     
932     //
933     // Print table of extended identifier groups
934     //
935     diag_printf("\nEFF_GRP_sa\t-\t\t-\t\traw_data\n");
936     diag_printf("----------------------------------------------------------\n");
937     while (entry_address < end_of_table)
938     {
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);    
942     }
943 }
944 #endif // CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
945
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)
951 {
952     can_channel *chan    = (can_channel*)devtab_entry->priv;
953     cyg_uint32   reg_val;
954     CAN_DECLARE_INFO(chan);
955     
956     chan = chan; // avoid compiler warnings for unused variables
957     //
958     // Print table of extended identifier groups
959     //
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);
987     
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);
997     
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); 
1007 }
1008 #endif // #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
1009
1010 //---------------------------------------------------------------------------
1011 // EOF can_accfilt_lpc2xxx.c