]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/can/m68k/mcf52xx/v2_0/src/can_mcf52xx.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / devs / can / m68k / mcf52xx / v2_0 / src / can_mcf52xx.c
1 //==========================================================================
2 //
3 //      devs/serial/m68k/flexcan/current/src/can_mcf_flexcan.c
4 //
5 //      CAN driver for Motorola coldfire processors
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:         2005-05-12
47 // Purpose:      support coldfire on-chip flexcan moduls
48 // Description: 
49 //
50 //####DESCRIPTIONEND####
51 //
52 //==========================================================================
53
54
55 //==========================================================================
56 //                              INCLUDES
57 //==========================================================================
58 #include <pkgconf/system.h>
59 #include <pkgconf/io_can.h>
60 #include <pkgconf/devs_can_mcf52xx_flexcan.h>
61
62 #include <cyg/infra/diag.h>
63
64 #include <cyg/io/io.h>
65 #include <cyg/io/devtab.h>
66 #include <cyg/io/can.h>
67
68 #include <cyg/hal/hal_arch.h>
69 #include <cyg/hal/hal_intr.h>
70 #include <cyg/hal/hal_io.h>
71
72
73 //===========================================================================
74 //                                DEFINES  
75 //===========================================================================
76
77 //
78 // we define our own ste of register bits in order to be independent from
79 // platform specific names
80 //
81
82 //---------------------------------------------------------------------------
83 // MCR regsiter bits
84 //
85 #define FLEXCAN_MCR_STOP                    (0x01 << 15)
86 #define FLEXCAN_MCR_FRZ                     (0x01 << 14)
87 #define FLEXCAN_MCR_HALT                    (0x01 << 12)
88 #define FLEXCAN_MCR_NOTRDY                  (0x01 << 11)
89 #define FLEXCAN_MCR_WAKEMSK                 (0x01 << 10)
90 #define FLEXCAN_MCR_SOFTRST                 (0x01 << 9)
91 #define FLEXCAN_MCR_FRZACK                  (0x01 << 8)
92 #define FLEXCAN_MCR_SUPV                    (0x01 << 7)
93 #define FLEXCAN_MCR_SELFWAKE                (0x01 << 6)
94 #define FLEXCAN_MCR_APS                     (0x01 << 5)
95 #define FLEXCAN_MCR_STOPACK                 (0x01 << 4)
96
97
98 //---------------------------------------------------------------------------
99 // CTRL0 register bits
100 //
101 #define FLEXCAN_CTRL0_BOFFMSK                   (0x01 << 7)
102 #define FLEXCAN_CTRL0_ERRMASK                   (0x01 << 6)
103 #define FLEXCAN_CTRL0_RXMODE                    (0x01 << 2)
104 #define FLEXCAN_CTRL0_RXMODE_0_DOMINANT         (0x00 << 2)
105 #define FLEXCAN_CTRL0_RXMODE_1_DOMINANT         (0x01 << 2)
106 #define FLEXCAN_CTRL0_TXMODE_MASK               (0x03 << 0)
107 #define FLEXCAN_CTRL0_TXMODE_SHIFT              0
108 #define FLEXCAN_CTRL0_TXMODE_FULL_0_DOMINANT    (0x00 << 0)
109 #define FLEXCAN_CTRL0_TXMODE_FULL_1_DOMINANT    (0x01 << 0)
110 #define FLEXCAN_CTRL0_TXMODE_OPEN_0_DOMINANT    (0x02 << 0)
111
112
113 //---------------------------------------------------------------------------
114 // CTRL1 register bits
115 //
116 #define FLEXCAN_CTRL1_SAMP                      (0x01 << 7)
117 #define FLEXCAN_CTRL1_TSYNC                     (0x01 << 5)
118 #define FLEXCAN_CTRL1_LBUF                      (0x01 << 4)
119 #define FLEXCAN_CTRL1_LOM                       (0x01 << 3)
120 #define FLEXCAN_CTRL1_PROPSEG_MASK              (0x07 << 0)
121 #define FLEXCAN_CTRL1_PROPSEG_SHIFT             0
122
123
124 //---------------------------------------------------------------------------
125 // CTRL2 register bits
126 //
127 #define FLEXCAN_CTRL2_RJW_MASK                  (0x03 << 6)
128 #define FLEXCAN_CTRL2_RJW_SHIFT                 6
129 #define FLEXCAN_CTRL2_PSEG1_MASK                (0x07 << 3)
130 #define FLEXCAN_CTRL2_PSEG1_SHIFT               3
131 #define FLEXCAN_CTRL2_PSEG2_MASK                (0x07 << 0)
132 #define FLEXCAN_CTRL2_PSEG2_SHIFT               0
133
134 //---------------------------------------------------------------------------
135 // ESTAT register bits
136 //
137 #define FLEXCAN_ESTAT_BITERR_MASK               (0x03 << 14)
138 #define FLEXCAN_ESTAT_BITERR_SHIFT              14
139 #define FLEXCAN_ESTAT_BITERR_NONE               (0x00 << 14)
140 #define FLEXCAN_ESTAT_BITERR_DOMINANT_RECESSIVE (0x01 << 14)
141 #define FLEXCAN_ESTAT_BITERR_RECESSIVE_DOMINANT (0x02 << 14)
142 #define FLEXCAN_ESTAT_ACKERR                    (0x01 << 13)
143 #define FLEXCAN_ESTAT_CRCERR                    (0x01 << 12)
144 #define FLEXCAN_ESTAT_FORMERR                   (0x01 << 11)
145 #define FLEXCAN_ESTAT_STUFFERR                  (0x01 << 10)
146 #define FLEXCAN_ESTAT_TXWARN                    (0x01 << 9)
147 #define FLEXCAN_ESTAT_RXWARN                    (0x01 << 8)
148 #define FLEXCAN_ESTAT_IDLE                      (0x01 << 7)
149 #define FLEXCAN_ESTAT_TX_RX                     (0x01 << 6)
150 #define FLEXCAN_ESTAT_FCS_MASK                  (0x03 << 4)
151 #define FLEXCAN_ESTAT_FCS_SHIFT                 4
152 #define FLEXCAN_ESTAT_FCS_ERROR_ACTIVE          (0x00 << 4)
153 #define FLEXCAN_ESTAT_FCS_ERROR_PASSIVE         (0x01 << 4)
154 #define FLEXCAN_ESTAT_BOFFINT                   (0x01 << 2)
155 #define FLEXCAN_ESTAT_ERRINT                    (0x01 << 1)
156 #define FLEXCAN_ESTAT_WAKEINT                   (0x01 << 0)
157
158 //
159 // For receive event calls we use these two identifiers for
160 // err and bus off events - message boxes use 0 - 15
161 //
162 #define FLEXCAN_ERR_EVENT                       16
163 #define FLEXCAN_BUSOFF_EVENT                    17
164 #define FLEXCAN_WAKE_EVENT                      18
165
166 //
167 // Acceptance mask
168 //
169 #define FLEXCAN_ACCEPTANCE_MASK_RX_ALL          0x00       // receive all messages - mbox ID does not matter
170 #define FLEXCAN_ACCEPTANCE_MASK_RX_ID           0x1FFFFFFF // receive only messages where ID exactly matches mbox ID
171
172
173 //---------------------------------------------------------------------------
174 // message buffer cfg bits
175 //
176 #define MBOX_RXCODE_NOT_ACTIVE 0x00
177 #define MBOX_RXCODE_BUSY       0x10
178 #define MBOX_RXCODE_EMPTY      0x40
179 #define MBOX_RXCODE_FULL       0x20
180 #define MBOX_RXCODE_OVERRUN    0x60
181
182 #define MBOX_TXCODE_NOT_READY  0x80
183 #define MBOX_TXCODE_TRANSMIT   0xC0
184 #define MBOX_TXCODE_RESPONSE   0xA0
185
186 #define MBOX_DATA_FRAME        0x00 // data frame
187 #define MBOX_REMOTE_FRAME      0x01 // remote frame
188 #define MBOX_STD_ID            0x00 // standard identifier
189 #define MBOX_EXT_ID            0x01 // remote identifier
190 #define MBOX_TX                0x08 // tx message box
191 #define MBOX_RX                0x00 // rx messge box
192
193 #define MBOX_CFG_IDE           0x08
194 #define MBOX_CFG_RTR_EXT       0x01
195 #define MBOX_CFG_RTR_STD       0x10
196 #define MBOX_CFG_SSR           0x10
197 #define MBOX_CFG_DLC_MASK      0x0F
198 #define MBOX_CFG_STAT_MASK     0xF0
199
200
201 //---------------------------------------------------------------------------
202 // flexcan message buffer configuration
203 //
204 #define FLEXCAN_MBOX_MIN      0
205 #define FLEXCAN_MBOX_MAX       15
206 #define FLEXCAN_MBOX_CNT      16
207 #define FLEXCAN_MBOX_TX       CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX
208 #define FLEXCAN_MBOX_RX_MIN   0
209 #define FLEXCAN_MBOX_RX_MAX   (FLEXCAN_MBOX_MAX - 1) // one msg box is tx
210 #define FLEXCAN_MBOX_RX_CNT   (FLEXCAN_MBOX_CNT - 1) // one msg box is tx
211
212
213 #define FLEXCAN_CTRLSTAT_NOT_READ 0 // indicates that control status register is not read
214
215
216 //===========================================================================
217 //                                 DATA TYPES
218 //===========================================================================
219 //
220 // Type of message buffer - required for function getevent in order to
221 // identify the type of message box that cause event
222 //
223 typedef enum
224 {
225     MBOX_STATE_DISABLED,  // message box unused (free)
226     MBOX_STATE_TX,        // TX message box
227     MBOX_STATE_REMOTE_TX, // remote TX msaage box (data will be sent on reception of rtr frame) 
228     MBOX_STATE_RX_ALL_STD, // RX message box for standard IDs
229     MBOX_STATE_RX_ALL_EXT, // RX message box for standard IDs
230     MBOX_STATE_RX_FILT     // RX message box for filter mboxes
231 } flexcan_mbox_state;
232
233
234 //
235 // configuration info for flexcan message buffer
236 //
237 typedef struct flexcan_mbox_info_st
238 {
239     cyg_vector_t       isr_vec;           // isr vector
240     int                isr_priority;      // isr priority
241     cyg_interrupt      interrupt;         // stores interrupt data
242     cyg_handle_t       interrupt_handle;  // stores interrupt number 
243     cyg_uint8          num;               // number of message buffer
244     bool               busy;              // if true, then transmission or reception is in progress
245     flexcan_mbox_state state;             // message box state
246     cyg_uint8          ctrlstat_shadow;   // shadow register of message box ctrlstat register
247 } flexcan_mbox_info; 
248
249 //
250 // Between ISR and DSR handling there is some kind of circular buffer.
251 // A DSR is only invoked if no other message box invoked a DSR before
252 // the DSR will read all available message buffers. This structure
253 // is for exchange of information between ISR and DSR
254 //
255 typedef struct st_rxmbox_circbuf
256 {
257     cyg_uint8 idx_rd;       // the message box the DSR will read from
258     cyg_uint8 idx_wr;       // the message box that will receive the next message
259     cyg_uint8 count;        // the number of received message before DSR starts (number of ISR nesting)
260 } flexcan_rxmbox_circbuf;
261
262 //
263 // flexcan interrupt (busoff, err, wake) data - stores interrupt data for
264 // a non message box interrupt (bus off, err or wake interrupt)
265 //
266 typedef struct flexcan_int_st
267 {
268     cyg_vector_t        isr_vec;  
269     int                 isr_priority;
270     cyg_interrupt       interrupt;
271     cyg_handle_t        interrupt_handle;
272 } flexcan_int;
273
274 //
275 // flexcan message box initialisation
276 //
277 #define FLEXCAN_MBOX_INIT(_mbox0_vec, _prio, _mbox_no) { \
278     isr_vec      : (_mbox0_vec) + (_mbox_no),            \
279     isr_priority : (_prio),                              \
280     num          : (_mbox_no),                           \
281     busy         : false                                 \
282 }
283
284 //
285 // Interrupt initialisation
286 //
287 #define FLEXCAN_INT_INIT(_vec, _prio) \
288 {                                     \
289     isr_vec      : (_vec),            \
290     isr_priority : (_prio)            \
291 }
292
293 //
294 // flexcan configuration 
295 //
296 typedef struct flexcan_info 
297 {
298     cyg_uint8          *base;            // base address of flexcan modul
299     cyg_vector_t        isr_vec_mbox0;   // vector number of ISR vector of first message box
300     flexcan_mbox_info   mboxes[FLEXCAN_MBOX_CNT];// message boxes
301     cyg_uint32          last_tx_id;      // last transmitted message identifier
302     
303     flexcan_int         boff_int;        // bus off interrupt data
304     flexcan_int         err_int;         // error interrupt data
305     flexcan_int         wake_int;        // wake interrupt data
306     
307     cyg_uint8           tx_all_mbox;     // number of message box for all transmit messages
308     cyg_uint8           free_mboxes;     // number of free message boxes for msg filters and rtr buffers
309     cyg_can_state       state;           // state of CAN controller
310     
311     flexcan_rxmbox_circbuf rxmbox_std_circbuf;
312     flexcan_rxmbox_circbuf rxmbox_ext_circbuf;
313
314     cyg_uint8           mboxes_std_cnt;   // contains number of standard message boxes available
315     cyg_uint8           mboxes_ext_cnt;   // number of message boxes with ext id
316     cyg_uint8           mboxes_rx_all_cnt;// number of all available mboxes
317
318     bool                rx_all;           // true if reception of call can messages is active
319     cyg_uint16          imask_shadow;    // interrupt mask shadow register
320 #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT 
321     cyg_can_message     last_tx_msg;     // stores last transmitted message for TX events
322 #endif
323
324 #ifdef FLEXCAN_CAN_STATS
325     cyg_uint32          isr_count;
326     cyg_uint32          dsr_count;
327     cyg_uint32          rx_bytes;
328     cyg_uint32          tx_bytes;
329     cyg_uint32          rx_errors;
330 #endif  
331 } flexcan_info;
332
333
334 //
335 // flexcan info initialisation
336 //
337 #define FLEXCAN_INFO(_l,                                                \
338                      _baseaddr,                                         \
339                      _isr_vec_mbox0,                                    \
340                      _mbox0_isr_prio,                                   \
341                      _mbox1_isr_prio,                                   \
342                      _mbox2_isr_prio,                                   \
343                      _mbox3_isr_prio,                                   \
344                      _mbox4_isr_prio,                                   \
345                      _mbox5_isr_prio,                                   \
346                      _mbox6_isr_prio,                                   \
347                      _mbox7_isr_prio,                                   \
348                      _mbox8_isr_prio,                                   \
349                      _mbox9_isr_prio,                                   \
350                      _mbox10_isr_prio,                                  \
351                      _mbox11_isr_prio,                                  \
352                      _mbox12_isr_prio,                                  \
353                      _mbox13_isr_prio,                                  \
354                      _mbox14_isr_prio,                                  \
355                      _mbox15_isr_prio,                                  \
356                      _boff_isr_vec, _boff_isr_prio,                     \
357                      _err_isr_vec, _err_isr_prio,                       \
358                      _wake_isr_vec, _wake_isr_prio,                     \
359                      _tx_all_mbox,                                      \
360                      _std_mboxes, _ext_mboxes)                          \
361 flexcan_info _l = {                                                     \
362     (void *)( _baseaddr),                                               \
363     (_isr_vec_mbox0),                                                   \
364     mboxes : {                                                          \
365     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox0_isr_prio), 0),          \
366     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox1_isr_prio), 1),          \
367     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox2_isr_prio), 2),          \
368     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox3_isr_prio), 3),          \
369     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox4_isr_prio), 4),          \
370     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox5_isr_prio), 5),          \
371     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox6_isr_prio), 6),          \
372     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox7_isr_prio), 7),          \
373     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox8_isr_prio), 8),          \
374     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox9_isr_prio), 9),          \
375     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox10_isr_prio),10),         \
376     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox11_isr_prio),11),         \
377     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox12_isr_prio),12),         \
378     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox13_isr_prio),13),         \
379     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox14_isr_prio),14),         \
380     FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_mbox15_isr_prio),15),         \
381     },                                                                  \
382     last_tx_id      : 0xFFFFFFFF,                                       \
383     boff_int        : FLEXCAN_INT_INIT(_boff_isr_vec, _boff_isr_prio),  \
384     err_int         : FLEXCAN_INT_INIT(_err_isr_vec, _err_isr_prio),    \
385     wake_int        : FLEXCAN_INT_INIT(_wake_isr_vec, _wake_isr_prio),  \
386     tx_all_mbox     : _tx_all_mbox,                                     \
387     free_mboxes      : ((_std_mboxes) + (_ext_mboxes)),                 \
388     state            : CYGNUM_CAN_STATE_ACTIVE,                         \
389     rx_all           : true,                                            \
390     mboxes_std_cnt   : _std_mboxes,                                     \
391     mboxes_ext_cnt   : _ext_mboxes,                                     \
392     mboxes_rx_all_cnt : ((_std_mboxes) + (_ext_mboxes))                 \
393 };
394
395
396 //===========================================================================
397 //                          GLOBAL DATA
398 //===========================================================================
399 //
400 // Note: two levels of macro are required to get proper expansion.
401 //
402 #define _FLEXCAN_MBOX_INTPRIO(n) CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX##n
403 #define FLEXCAN_MBOX_INTPRIO(n) _FLEXCAN_MBOX_INTPRIO(n)
404
405 //
406 // Define number of message boxes if they are not defined yet
407 //
408 #ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES
409 #define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES 0
410 #endif
411 #ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES
412 #define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES 0
413 #endif
414 #ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES
415 #define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES 0
416 #endif
417 #ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES
418 #define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES 0
419 #endif
420
421
422 #ifdef CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN0
423 //
424 // FlexCAN channel initialisation for FlexCAN channel 0
425 //
426 FLEXCAN_INFO(flexcan_can0_info, 
427              HAL_MCF52xx_MBAR + HAL_MCF52xx_FLEXCAN0_BASE,
428              HAL_MCF52xx_FLEXCAN0_MBOX0_ISRVEC,
429              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX0,
430              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX1,
431              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX2,
432              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX3,
433              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX4,
434              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX5,
435              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX6,
436              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX7,
437              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX8,
438              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX9,
439              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX10,
440              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX11,
441              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX12,
442              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX13,
443              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX14,
444              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX15,
445              HAL_MCF52xx_FLEXCAN0_BOFF_ISRVEC,
446              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_BOFFINT,  
447              HAL_MCF52xx_FLEXCAN0_ERR_ISRVEC,          
448              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_ERRINT,
449              HAL_MCF52xx_FLEXCAN0_WAKE_ISRVEC,       
450              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_WAKEINT,
451              CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX,
452              CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES,
453              CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES);
454 #endif // CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN[set ::flexcan]
455
456 #ifdef CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN1
457 //
458 // FlexCAN channel initialisation for FlexCAN channel 1
459 //
460 FLEXCAN_INFO(flexcan_can0_info,
461              HAL_MCF52xx_MBAR + HAL_MCF52xx_FLEXCAN0_BASE,
462              HAL_MCF52xx_FLEXCAN1_MBOX0_ISRVEC,
463              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX0,
464              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX1,
465              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX2,
466              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX3,
467              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX4,
468              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX5,
469              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX6,
470              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX7,
471              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX8,
472              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX9,
473              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX10,
474              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX11,
475              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX12,
476              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX13,
477              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX14,
478              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_MBOX15,
479              HAL_MCF52xx_FLEXCAN1_BOFF_ISRVEC,
480              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_BOFFINT,
481              HAL_MCF52xx_FLEXCAN1_ERR_ISRVEC,
482              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_ERRINT,
483              HAL_MCF52xx_FLEXCAN1_WAKE_ISRVEC,
484              CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN1_WAKEINT,
485              CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_DEFAULT_TX_MBOX,
486              CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES,
487              CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES);
488 #endif // CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN1
489
490 //
491 // message box structure for hardware access of message box
492 //
493 typedef struct flexcan_mbox
494 {
495     cyg_uint8  timestamp; 
496     cyg_uint8  ctrlstat;
497     cyg_uint16 id_hi;
498     cyg_uint16 id_lo;
499     cyg_uint8  data[8];
500     cyg_uint16 reserved;
501 } flexcan_mbox;
502
503 //
504 // flexcan register layout for hardware register access of FlexCAN modul
505 //
506 typedef struct flexcan_regs
507 {
508     cyg_uint16 CANMCR;       // 0x00
509     cyg_uint16 reserved0[2]; // 0x02
510     cyg_uint8  CANCTRL0;     // 0x06
511     cyg_uint8  CANCTRL1;     // 0x07
512     cyg_uint8  PRESDIV;      // 0x08
513     cyg_uint8  CANCTRL2;     // 0x09
514     cyg_uint16 TIMER;        // 0x0A
515     cyg_uint16 reserved1[2]; // 0x0C
516     cyg_uint16 RXGMASK_HI;   // 0x10
517     cyg_uint16 RXGMASK_LO;   // 0x12
518     cyg_uint16 RX14MASK_HI;  // 0x14
519     cyg_uint16 RX14MASK_LO;  // 0x16
520     cyg_uint16 RX15MASK_HI;  // 0x18
521     cyg_uint16 RX15MASK_LO;  // 0x1A
522     cyg_uint16 reserved2[2]; // 0x1C
523     cyg_uint16 ESTAT;        // 0x20
524     cyg_uint16 IMASK;        // 0x22
525     cyg_uint16 IFLAG;        // 0x24
526     cyg_uint8  RXERRCNT;     // 0x26
527     cyg_uint8  TXERRCNT;     // 0x27
528     cyg_uint16 reserved3[44];// 0x28
529     flexcan_mbox mbox[16]; // 0x80
530 } flexcan_regs;
531
532
533 //===========================================================================
534 //                                 LOCAL DATA
535 //===========================================================================
536 static cyg_uint16 flexcan_baud_rates[] = {
537     0,      // Unused
538     10,     // 10 kbit/s
539     20,     // 20
540     50,     // 50
541     100,    // 100
542     125,    // 125
543     250,    // 250
544     500,    // 500
545     800,    // 800
546     1000,   // 1000 kbit/s
547 };
548
549
550 //===========================================================================
551 //                              PROTOTYPES
552 //===========================================================================
553 static bool        flexcan_init(struct cyg_devtab_entry* devtab_entry);
554 static Cyg_ErrNo   flexcan_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name);
555 static Cyg_ErrNo   flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len);
556 static Cyg_ErrNo   flexcan_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len);
557 static bool        flexcan_putmsg(can_channel *priv, cyg_can_message *pmsg, void *pdata);
558 static bool        flexcan_getevent(can_channel *priv, cyg_can_event *pevent, void *pdata);
559 static void        flexcan_start_xmit(can_channel* chan);
560 static void        flexcan_stop_xmit(can_channel* chan);
561
562 //
563 // TX and RX ISRs and DSRs
564 //
565 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
566 static cyg_uint32  flexcan_mbox_rx_std_isr(cyg_vector_t, cyg_addrword_t);
567 static void        flexcan_mbox_rx_std_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
568 #endif // CYGOPT_IO_CAN_STD_CAN_ID
569 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
570 static cyg_uint32  flexcan_mbox_rx_ext_isr(cyg_vector_t, cyg_addrword_t);
571 static void        flexcan_mbox_rx_ext_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
572 #endif // CYGOPT_IO_CAN_EXT_CAN_ID
573 static cyg_uint32  flexcan_mbox_rx_filt_isr(cyg_vector_t, cyg_addrword_t);
574 static cyg_uint32  flexcan_mbox_tx_isr(cyg_vector_t, cyg_addrword_t);
575 static void        flexcan_mbox_tx_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
576 static void        flexcan_mbox_rx_filt_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t );
577
578 //
579 // All other flexcan interrupt handlers
580 //
581 static cyg_uint32  flexcan_err_isr(cyg_vector_t, cyg_addrword_t);
582 static void        flexcan_err_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
583 static cyg_uint32  flexcan_busoff_isr(cyg_vector_t, cyg_addrword_t);
584 static void        flexcan_busoff_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
585 static cyg_uint32  flexcan_wake_isr(cyg_vector_t, cyg_addrword_t);
586 static void        flexcan_wake_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
587
588 //
589 // Flexcan utility functions
590 //
591 static bool flexcan_cfg_mbox_tx(flexcan_mbox *pmbox, cyg_can_message  *pmsg, bool rtr);
592 static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox, cyg_can_message  *pmsg, bool enable);
593 static void flexcan_read_from_mbox(can_channel *chan, cyg_uint8 mbox, cyg_can_event *pevent, cyg_uint8 *ctrlstat);
594 static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_can_id_type ext);
595 static void flexcan_start_chip(can_channel *chan);
596 static void flexcan_enter_standby(can_channel *chan, bool selfwake);
597 static void flexcan_stop_chip(can_channel *chan);
598 static void flexcan_leave_standby(can_channel *chan);
599 static bool flexcan_set_baud(can_channel *chan, cyg_uint16 baudrate);
600 static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool init);
601 static cyg_int8 flexcan_alloc_mbox(flexcan_info *info);
602 static void flexcan_disable_mbox(can_channel *chan, cyg_uint32 mbox_id);
603 static void flexcan_setup_rxmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_ISR_t *isr, cyg_can_message *pmsg, bool enable, bool int_enable);
604 static void flexcan_setup_txmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_can_message *pmsg);
605 static void flexcan_setup_rtrmbox(can_channel *chan, cyg_uint32 mbox_id, cyg_can_message *pmsg);
606 static void flexcan_mboxint_enable(flexcan_info *info, cyg_uint32 mbox_id);
607 static void flexcan_mboxint_disable(flexcan_info *info, cyg_uint32 mbox_id);
608 static void flexcan_config_rx_all(can_channel *chan);
609 static void flexcan_enable_rxmbox(can_channel *chan, cyg_uint32 mbox_id);
610
611
612 CAN_LOWLEVEL_FUNS(flexcan_lowlevel_funs,
613                   flexcan_putmsg,
614                   flexcan_getevent,
615                   flexcan_get_config,
616                   flexcan_set_config,
617                   flexcan_start_xmit,
618                   flexcan_stop_xmit
619      );
620
621
622 cyg_can_event    flexcan_can0_rxbuf[CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX]; // buffer for 32 rx can events
623 cyg_can_message  flexcan_can0_txbuf[CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX]; // buffer for 32 tx can messageds
624
625
626 CAN_CHANNEL_USING_INTERRUPTS(flexcan_can0_chan,
627                              flexcan_lowlevel_funs,
628                              flexcan_can0_info,
629                              CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_KBAUD),
630                              flexcan_can0_txbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX,
631                              flexcan_can0_rxbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX
632     );
633
634
635 DEVTAB_ENTRY(flexcan_devtab, 
636              CYGDAT_DEVS_CAN_MCF52xx_FLEXCAN0_NAME,
637              0,                     // Does not depend on a lower level interface
638              &cyg_io_can_devio, 
639              flexcan_init, 
640              flexcan_lookup,        // CAN driver may need initializing
641              &flexcan_can0_chan
642     );
643
644
645 //===========================================================================
646 //  Lookup the device and return its handle
647 //===========================================================================
648 static Cyg_ErrNo
649 flexcan_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name)
650 {
651     can_channel* chan    = (can_channel*) (*tab)->priv;
652     (chan->callbacks->can_init)(chan);
653     
654     return ENOERR;
655 }
656
657
658 //===========================================================================
659 // Enable hardware message box for reception
660 //===========================================================================
661 static __inline__  void flexcan_hwmbox_enable_rx(flexcan_regs *flexcan, cyg_uint32 mbox_id)
662 {
663     HAL_WRITE_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), MBOX_RXCODE_EMPTY);
664 }
665
666
667 //===========================================================================
668 // Disable hardware message box
669 //===========================================================================
670 static __inline__  void flexcan_hwmbox_disable(flexcan_regs *flexcan, cyg_uint32 mbox_id)
671 {
672     HAL_WRITE_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), MBOX_RXCODE_NOT_ACTIVE);
673 }
674
675
676 //===========================================================================
677 // lock mbox by reading control status register
678 //===========================================================================
679 static __inline__  void flexcan_hwmbox_lock(flexcan_regs *flexcan, cyg_uint32 mbox_id, cyg_uint8 *pctrlstat)
680 {
681     HAL_READ_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), *pctrlstat); // this read will lock the mbox
682 }
683
684
685 //===========================================================================
686 //  Enable message box interrupt for one message box
687 //===========================================================================
688 static void flexcan_mboxint_enable(flexcan_info *info, cyg_uint32 mbox_id)
689 {
690     flexcan_regs *flexcan = (flexcan_regs *)info->base;
691     
692     info->imask_shadow |= (0x0001 << mbox_id);
693     HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
694 }
695
696
697 //===========================================================================
698 //  Disable message box interrupt for one message box
699 //===========================================================================
700 static void flexcan_mboxint_disable(flexcan_info *info, cyg_uint32 mbox_id)
701 {
702     flexcan_regs *flexcan = (flexcan_regs *)info->base;
703     
704     info->imask_shadow &= ~(0x0001 << mbox_id);
705     HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
706 }
707
708
709 //===========================================================================
710 // Allocate message box
711 // Try to find a free message box and return its ID
712 //===========================================================================
713 static cyg_int8 flexcan_alloc_mbox(flexcan_info *info)
714 {
715     cyg_uint8     i;
716     cyg_int8      res = CYGNUM_CAN_MSGBUF_NA;
717     
718     if (info->free_mboxes)
719     {  
720         for (i = (FLEXCAN_MBOX_RX_CNT - info->free_mboxes); i <= FLEXCAN_MBOX_RX_MAX; ++i)
721         {
722             if (MBOX_STATE_DISABLED == info->mboxes[i].state)
723             {
724                 info->free_mboxes--;
725                 res = i;
726                 break;
727             }               
728         }
729     } // if (info->free_mboxes)
730     
731     return res;
732 }
733
734
735 //===========================================================================
736 // Enable a previously configured rx mbox - a mbox ready to recive
737 //===========================================================================
738 static void flexcan_enable_rxmbox(can_channel     *chan,
739                                   cyg_uint32       mbox_id)
740 {
741     flexcan_info *info = (flexcan_info *)chan->dev_priv;
742     flexcan_regs *flexcan = (flexcan_regs *)info->base;
743
744     flexcan_hwmbox_enable_rx(flexcan, mbox_id);
745     flexcan_mboxint_enable(info, mbox_id);
746 }
747
748 //===========================================================================
749 // Prepare message buffer filter
750 // Setup a RX message box for reception of a certain CAN identifier but do
751 // not enable it
752 //===========================================================================
753 static void flexcan_setup_rxmbox(can_channel     *chan, 
754                                  cyg_uint32       mbox_id,
755                                  cyg_ISR_t       *isr,
756                                  cyg_can_message *pmsg,
757                                  bool             enable,
758                                  bool             int_enable)
759 {
760     flexcan_info      *info    = (flexcan_info *)chan->dev_priv;
761     flexcan_regs      *flexcan = (flexcan_regs *)info->base;
762     flexcan_mbox_info *pmbox;
763     cyg_DSR_t         *dsr_func = &flexcan_mbox_rx_filt_dsr;
764     
765     //
766     // Set state of message buffer accoring to ISR function that
767     // will be registered
768     //
769 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
770     if (*isr == flexcan_mbox_rx_std_isr)
771     {
772         //
773         // If we have only one single RX all message box then we use
774         // the filter ISR instead of RX all standard ISR because it
775         // is better suited for a single RX mbox
776     //
777         if (info->mboxes_std_cnt > 1)
778         {
779             info->mboxes[mbox_id].state = MBOX_STATE_RX_ALL_STD;
780             dsr_func = &flexcan_mbox_rx_std_dsr;
781         }
782         else
783         {
784             info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT;
785             isr = flexcan_mbox_rx_filt_isr;
786         }
787     }
788     else
789 #endif // CYGOPT_IO_CAN_STD_CAN_ID
790 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
791     if (*isr == flexcan_mbox_rx_ext_isr)
792     {
793         //
794         // If we have only one single RX all message box then we use
795         // the filter ISR instead of RX all standard ISR because it
796         // is better suited for a single RX mbox
797         //
798         if (info->mboxes_ext_cnt > 1)
799         {
800             info->mboxes[mbox_id].state = MBOX_STATE_RX_ALL_EXT;
801             dsr_func = &flexcan_mbox_rx_ext_dsr;
802         }
803         else
804         {
805             info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT;
806             isr = flexcan_mbox_rx_filt_isr;
807         }
808     }
809     else
810 #endif // CYGOPT_IO_CAN_EXT_CAN_ID
811     if (*isr == flexcan_mbox_rx_filt_isr)
812     {
813         info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT;
814     }
815     else
816     {
817         CYG_ASSERT(0, "Invalid ISR function pointer");
818     }
819
820     pmbox = &info->mboxes[mbox_id];
821     flexcan_cfg_mbox_rx(&flexcan->mbox[mbox_id], pmsg, enable);
822
823     cyg_drv_interrupt_create(pmbox->isr_vec,
824                              pmbox->isr_priority,
825                              (cyg_addrword_t) chan,
826                              isr,
827                              dsr_func,
828                              &(pmbox->interrupt_handle),
829                              &(pmbox->interrupt));
830     cyg_drv_interrupt_attach(pmbox->interrupt_handle);
831     cyg_drv_interrupt_unmask(pmbox->isr_vec);
832     
833     //
834     // now enable interrupt for this message box - but only if we
835     // really should do it
836     //
837     if (int_enable)
838     {
839     flexcan_mboxint_enable(info, mbox_id);
840     }
841 }
842
843
844 //===========================================================================
845 // Disable a message box - after this call a message box is available
846 // again for message filters or remote buffers
847 //===========================================================================
848 static void flexcan_disable_mbox(can_channel *chan, cyg_uint32 mbox_id)
849 {
850     flexcan_info      *info    = (flexcan_info *)chan->dev_priv;
851     flexcan_regs      *flexcan = (flexcan_regs *)info->base;
852     flexcan_mbox_info *pmbox;
853     
854     //
855     // if message box is already disabled we do not need to disable it
856     // here
857     //
858     if (MBOX_STATE_DISABLED == info->mboxes[mbox_id].state)
859     {
860         return;
861     }
862     
863     HAL_WRITE_UINT8(&flexcan->mbox[mbox_id].ctrlstat, MBOX_RXCODE_NOT_ACTIVE);
864     info->mboxes[mbox_id].state = MBOX_STATE_DISABLED;
865     pmbox = &info->mboxes[mbox_id];
866     
867     //
868     // now disable interrupts for this message box and free all
869     // interrupt resources
870     //
871     flexcan_mboxint_disable(info, mbox_id);
872     cyg_drv_interrupt_mask(pmbox->isr_vec);
873     cyg_drv_interrupt_detach(pmbox->interrupt_handle);
874     cyg_drv_interrupt_delete(pmbox->interrupt_handle);
875     
876     info->free_mboxes++;
877 }
878
879
880 //===========================================================================
881 // Setup a transmit message box
882 //===========================================================================
883 static void flexcan_setup_txmbox(can_channel      *chan,
884                                  cyg_uint32        mbox_id,
885                                  cyg_can_message  *pmsg)
886 {
887     flexcan_info      *info   = (flexcan_info *)chan->dev_priv;
888     flexcan_regs      *flexcan = (flexcan_regs *)info->base;
889     flexcan_mbox_info *pmbox;
890     
891     info->mboxes[mbox_id].state = MBOX_STATE_TX;
892     pmbox = &info->mboxes[mbox_id];
893     flexcan_cfg_mbox_tx(&flexcan->mbox[mbox_id], pmsg, false);
894
895     //
896     // prepare message box interrupt for message box 
897     //
898     cyg_drv_interrupt_create(pmbox->isr_vec,
899                              pmbox->isr_priority,
900                              (cyg_addrword_t) chan,
901                              &flexcan_mbox_tx_isr,
902                              &flexcan_mbox_tx_dsr,
903                              &(pmbox->interrupt_handle),
904                              &(pmbox->interrupt));
905     cyg_drv_interrupt_attach(pmbox->interrupt_handle);
906     cyg_drv_interrupt_unmask(pmbox->isr_vec);
907     
908     //
909     // now enable interrupt for this message box
910     //
911     flexcan_mboxint_enable(info, mbox_id);
912 }
913
914
915 //===========================================================================
916 // Setup a RTR response message box
917 //===========================================================================
918 static void flexcan_setup_rtrmbox(can_channel      *chan,
919                                   cyg_uint32        mbox_id,
920                                   cyg_can_message  *pmsg)
921 {
922     flexcan_info      *info   = (flexcan_info *)chan->dev_priv;
923     flexcan_regs      *flexcan = (flexcan_regs *)info->base;
924     
925     info->mboxes[mbox_id].state = MBOX_STATE_REMOTE_TX;
926     flexcan_cfg_mbox_tx(&flexcan->mbox[mbox_id], pmsg, true);
927 }
928
929
930 //===========================================================================
931 // Setup the list of message boxes ready to receive a message
932 //===========================================================================
933 static void flexcan_setup_rxmbox_circbuf(flexcan_rxmbox_circbuf *pbuf)
934 {
935     pbuf->count  = 0;
936     pbuf->idx_rd = 0;
937     pbuf->idx_wr = 0;
938 }
939
940
941 //===========================================================================
942 // Setup flexCAN modul for reception of any kind of message
943 //===========================================================================
944 static void flexcan_config_rx_all(can_channel *chan)
945 {
946     flexcan_info *info       = (flexcan_info *)chan->dev_priv;
947     flexcan_regs       *flexcan = (flexcan_regs *)info->base;
948     cyg_int8           i;
949     
950         //
951     // setup all available message boxes for reception of of messages
952     // All standard and extended message buffers will be configured
953         //
954     for (i = 0; i < info->mboxes_rx_all_cnt; ++i)
955              {
956         cyg_can_message filter_param;
957         filter_param.id  = 0;
958
959         //
960         // configure message buffers for standard frames
961         //
962 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
963         if (i < info->mboxes_std_cnt)
964                  {
965             filter_param.ext = CYGNUM_CAN_ID_STD;
966             flexcan_setup_rxmbox(chan, i, &flexcan_mbox_rx_std_isr, &filter_param, false, true);
967                  }
968 #endif // CYGOPT_IO_CAN_STD_CAN_ID
969
970        //
971        // configure message buffers for extended frames
972        //
973 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
974         else
975                  {
976             filter_param.ext = CYGNUM_CAN_ID_EXT;
977             flexcan_setup_rxmbox(chan, i, &flexcan_mbox_rx_ext_isr, &filter_param, false, true);
978                  }
979 #endif // CYGOPT_IO_CAN_EXT_CAN_ID
980             }
981        
982         //
983     // We need to receive all available CAN messages so we have to set the acceptance filter
984     // properly
985     //
986     flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI,  FLEXCAN_ACCEPTANCE_MASK_RX_ALL,  CYGNUM_CAN_ID_EXT);
987     flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ALL, CYGNUM_CAN_ID_EXT);
988     info->free_mboxes = FLEXCAN_MBOX_RX_CNT - info->mboxes_rx_all_cnt;
989     info->rx_all = true;
990
991     //
992     // now finally setup the first active message boxes and enable ist
993         //     
994 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
995     if (info->mboxes_std_cnt)
996              { 
997         flexcan_setup_rxmbox_circbuf(&info->rxmbox_std_circbuf);
998         flexcan_enable_rxmbox(chan, 0);
999     }
1000 #endif // CYGOPT_IO_CAN_STD_CAN_ID
1001                              
1002 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
1003     if (info->mboxes_ext_cnt)
1004                  {
1005         flexcan_setup_rxmbox_circbuf(&info->rxmbox_ext_circbuf);
1006         flexcan_enable_rxmbox(chan, info->mboxes_std_cnt);
1007                  }
1008 #endif // CYGOPT_IO_CAN_EXT_CAN_ID
1009
1010 }
1011
1012 //===========================================================================
1013 // Setup Flex CAN moduls in a state where all message boxes are disabled
1014 // After this call single message filters and buffers can be added
1015 //===========================================================================
1016 static void flexcan_config_rx_none(can_channel *chan)
1017 {
1018     flexcan_info       *info = (flexcan_info *)chan->dev_priv;
1019     flexcan_regs       *flexcan = (flexcan_regs *)info->base;
1020     cyg_int8           i;
1021                  
1022                  //
1023     // setup all RX messages moxes into a disabled state
1024                  //
1025     for (i = 0; i < FLEXCAN_MBOX_RX_CNT; ++i)
1026                  {
1027         flexcan_disable_mbox(chan, i);
1028     }
1029                      
1030     //
1031     // If we want to receive only certain CAN identiffiers then the ID does matter and
1032     // we have to setup the acceptance mask properly
1033     //
1034     flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI,  FLEXCAN_ACCEPTANCE_MASK_RX_ID,  CYGNUM_CAN_ID_EXT);
1035     flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, FLEXCAN_ACCEPTANCE_MASK_RX_ID,  CYGNUM_CAN_ID_EXT);
1036     info->free_mboxes = FLEXCAN_MBOX_RX_CNT;
1037     info->rx_all = false;
1038 }
1039
1040
1041 //===========================================================================
1042 // Configure message buffers
1043 //===========================================================================
1044 static Cyg_ErrNo flexcan_set_config_msgbuf(can_channel *chan, cyg_can_msgbuf_cfg *buf)
1045 {
1046     Cyg_ErrNo     res = ENOERR;
1047     flexcan_info *info = (flexcan_info *)chan->dev_priv;
1048
1049     switch (buf->cfg_id)
1050                      {
1051                          //
1052         // clear all message filters and remote buffers - prepare for message buffer
1053         // configuration
1054                          //
1055         case CYGNUM_CAN_MSGBUF_RESET_ALL :
1056                      {
1057                  flexcan_config_rx_none(chan);
1058                      }
1059             break;
1060
1061                      //
1062         // setup FlexCAN modul for reception of all standard and extended messages
1063                      //
1064         case CYGNUM_CAN_MSGBUF_RX_FILTER_ALL :
1065                      {
1066                 if (!info->rx_all) // if rx_all is enabled we do not need to do anything
1067                      {
1068                     flexcan_config_rx_none(chan); // set into default state
1069                     flexcan_config_rx_all(chan);  // setup RX all state
1070                      }
1071              }
1072              break;
1073         
1074         //
1075         // add single message filter, message with filter ID will be received
1076         //     
1077         case CYGNUM_CAN_MSGBUF_RX_FILTER_ADD :
1078              {
1079                  cyg_can_filter *filter   = (cyg_can_filter*) buf;
1080                  
1081                  //
1082                  // if FlexCAN is configured to receive all messages then it is not
1083                  // allowed to add single message filters because then more than
1084                  // one message buffer would receive the same CAN id
1085                  //
1086                  if (info->rx_all)
1087                  {
1088                     return -EPERM;
1089                  }
1090                  
1091                  //
1092                  // try to allocate a free message box - if we have a free one
1093                  // then we can prepare the message box for reception of the
1094                  // desired message id
1095                  //
1096                  filter->handle = flexcan_alloc_mbox(info);
1097                  if (filter->handle > CYGNUM_CAN_MSGBUF_NA)
1098                  {
1099                      flexcan_setup_rxmbox(chan, filter->handle, &flexcan_mbox_rx_filt_isr, &filter->msg, true, true);
1100                  }
1101              }
1102              break; //CYGNUM_CAN_MSGBUF_RX_FILTER_ADD
1103
1104                      //
1105         // Try to add a new RTR response message buffer for automatic transmisson
1106         // of data frame on reception of a remote frame
1107                      //
1108         case CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD :
1109                      {
1110                  cyg_can_remote_buf *rtr_buf    = (cyg_can_remote_buf*) buf;
1111                  rtr_buf->handle = flexcan_alloc_mbox(info);
1112                      
1113                  if (rtr_buf->handle > CYGNUM_CAN_MSGBUF_NA)
1114                      {
1115                      //
1116                      // if we have a free message buffer then we setup this buffer
1117                      // for remote frame reception
1118                      //
1119                      flexcan_setup_rtrmbox(chan, rtr_buf->handle, &rtr_buf->msg);
1120                  }
1121                      }
1122              break;
1123                      
1124                      //
1125         // write data into remote response buffer
1126         //
1127         case CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE :
1128              {
1129                  cyg_can_remote_buf *rtr_buf    = (cyg_can_remote_buf*) buf;
1130
1131                  //
1132                  // If we have a valid rtr buf handle then we can store data into
1133                  // rtr message box
1134                      // 
1135                  if ((rtr_buf->handle >= 0) && (rtr_buf->handle <= FLEXCAN_MBOX_RX_MAX))
1136                  {
1137                      flexcan_regs *flexcan = (flexcan_regs *)info->base;
1138                      flexcan_cfg_mbox_tx(&flexcan->mbox[rtr_buf->handle], &rtr_buf->msg, true);
1139                  }
1140                  else
1141                  {
1142                     return -EINVAL;
1143                  }    
1144              }
1145              break;
1146     } // switch (buf->cfg_id)
1147         
1148      return res;
1149 }
1150
1151 //===========================================================================
1152 // Set device configuration
1153 //===========================================================================
1154 static Cyg_ErrNo
1155 flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
1156 {
1157     Cyg_ErrNo     res = ENOERR;
1158
1159     switch(key)
1160              {
1161                  //
1162         //Setup a new CAN configuration. This will i.e. setup a new baud rate
1163                  //
1164         case CYG_IO_SET_CONFIG_CAN_INFO:
1165                  {
1166                  cyg_can_info_t*  config = (cyg_can_info_t*) buf;
1167                  if (*len < sizeof(cyg_can_info_t))
1168                      {
1169                     return -EINVAL;
1170                  }
1171                  *len = sizeof(cyg_can_info_t);
1172                  if (!flexcan_config(chan, config, false))
1173                  {
1174                     return -EINVAL;
1175                      }
1176                  }
1177             break;
1178                  
1179                  //
1180         // configure message buffers
1181                  //
1182         case CYG_IO_SET_CONFIG_CAN_MSGBUF :
1183              {
1184                 cyg_can_msgbuf_cfg *msg_buf = (cyg_can_msgbuf_cfg *) buf;
1185
1186                 if (*len != sizeof(cyg_can_msgbuf_cfg))
1187                 {
1188                     return -EINVAL;
1189                 }
1190
1191                 flexcan_set_config_msgbuf(chan, msg_buf);
1192              }
1193              break;
1194         
1195         //
1196         // Change CAN state of FlexCAN modul. This function will set the FlexCAN
1197         // modul into STOPPED, ACTIVE or STANDBY state
1198         //    
1199         case CYG_IO_SET_CONFIG_CAN_MODE :
1200              {
1201                 cyg_can_mode   *can_mode  = (cyg_can_mode*) buf;
1202                 
1203                 if (*len != sizeof(cyg_can_mode)) 
1204                 {
1205                     return -EINVAL;
1206                 }
1207                 *len = sizeof(cyg_can_mode);
1208                 
1209                 //
1210                 // decide what to do acording to mode
1211                 //
1212                 switch (*can_mode)
1213                 {
1214                     case CYGNUM_CAN_MODE_STOP :      // stop FlexCANm modul
1215                          flexcan_stop_chip(chan);
1216                          break;
1217                          
1218                     case CYGNUM_CAN_MODE_START :     // start FlexCAN modul
1219                          flexcan_leave_standby(chan);
1220                          break;
1221                           
1222                     case CYGNUM_CAN_MODE_STANDBY :   // set FlexCAN modul into standby state
1223                          flexcan_enter_standby(chan, true);
1224                          break;
1225                          
1226                     case CYGNUM_CAN_MODE_CONFIG : // stop FlexCAN modul for configuration
1227                          flexcan_stop_chip(chan);
1228                          break;
1229                 }
1230              }
1231              break; // case CYG_IO_SET_CONFIG_CAN_MODE :         
1232     } // switch (key)
1233     
1234     return res;
1235 }
1236
1237
1238 //===========================================================================
1239 //  Query device configuration
1240 //===========================================================================
1241 static Cyg_ErrNo
1242 flexcan_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
1243 {
1244     Cyg_ErrNo     res  = ENOERR;
1245     flexcan_info *info = (flexcan_info *)chan->dev_priv;
1246     
1247     switch(key)
1248     {
1249         //
1250         // query state of CAN controller
1251         //
1252         case CYG_IO_GET_CONFIG_CAN_STATE :
1253              {
1254                 cyg_can_state *can_state  = (cyg_can_state*) buf;
1255                 
1256                 if (*len != sizeof(cyg_can_state)) 
1257                 {
1258                     return -EINVAL;
1259                 }
1260                 *len = sizeof(cyg_can_state);
1261                 *can_state = info->state;
1262              }
1263              break;
1264         
1265         //
1266         // Query message box information - returns available and free message
1267         // boxes
1268         //     
1269         case CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO :
1270              {
1271                  cyg_can_msgbuf_info *mbox_info  = (cyg_can_msgbuf_info*) buf;
1272                 
1273                  if (*len != sizeof(cyg_can_msgbuf_info)) 
1274                  {
1275                      return -EINVAL;
1276                  }
1277                 *len = sizeof(cyg_can_msgbuf_info);
1278                 
1279                  mbox_info->count = FLEXCAN_MBOX_RX_CNT;
1280                  mbox_info->free  = info->free_mboxes;
1281              }
1282              break;
1283         
1284         //
1285         // Query hardware description of FlexCAN device driver
1286         //     
1287         case CYG_IO_GET_CONFIG_CAN_HDI :
1288              {
1289                 cyg_can_hdi *hdi = (cyg_can_hdi *)buf;
1290                 //
1291                 // comes from high level driver so we do not need to
1292                 // check buffer size here
1293                 //             
1294                 hdi->support_flags = CYGNUM_CAN_HDI_FRAMETYPE_EXT_ACTIVE
1295                                    | CYGNUM_CAN_HDI_FULLCAN;
1296 #ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP 
1297                 hdi->support_flags |= CYGNUM_CAN_HDI_TIMESTAMP;
1298 #endif
1299              }
1300              break;
1301              
1302         default :
1303             res = -EINVAL;
1304     }// switch(key)
1305     
1306     return res;
1307
1308
1309
1310 //===========================================================================
1311 //  Check if we received self transmitted frame
1312 //===========================================================================
1313 static bool flexcan_is_no_self_tx(cyg_can_event *pevent, flexcan_info *info, flexcan_mbox_info *pmbox)
1314 {
1315     //
1316     // If we received a self transmitted frame
1317     // then this is not really an rx event and we return false. We rely on the
1318     // fact here that two devices in network do not send the same identifier
1319     //
1320     if (pevent->msg.id == info->last_tx_id)
1321     {
1322         info->last_tx_id = 0xFFFFFFFF; // set last received ID to an invalid value
1323         return false;
1324     }
1325     else
1326     {
1327         pevent->flags |= CYGNUM_CAN_EVENT_RX;
1328
1329         //
1330         // check if an overun occured in this message box
1331         //
1332         if ((pmbox->ctrlstat_shadow & MBOX_RXCODE_OVERRUN) == MBOX_RXCODE_OVERRUN)
1333         {
1334             pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX;
1335         }
1336
1337         return true;
1338     }
1339 }
1340
1341
1342 //===========================================================================
1343 //  Read one event from can hardware - called from high level I/O CAN driver
1344 //===========================================================================
1345 static bool flexcan_getevent(can_channel *chan, cyg_can_event *pevent, void *pdata)
1346 {
1347     flexcan_info *info           = (flexcan_info *)chan->dev_priv;
1348     flexcan_regs *flexcan        = (flexcan_regs *)info->base;
1349     bool          res            = true;
1350     cyg_uint16    estat;
1351     cyg_uint8     event_id       = *((cyg_uint8 *)pdata);
1352      
1353     //   
1354     // if event_id is 0 - 15 the we have a message box event
1355     //
1356     if (event_id < FLEXCAN_ERR_EVENT)
1357     {   
1358         flexcan_mbox_info *pmbox_info;
1359         pmbox_info = &info->mboxes[event_id];
1360         
1361         //
1362         // Deceide what to do according to type of message box that caused this event
1363         //
1364         switch (pmbox_info->state)
1365         {
1366             //
1367             // If we have an RX event then we need to read the received data from
1368             // message box that caused this event and fill it into message queue of
1369             // high level I/O CAN driver. We could handle this stuff in a function
1370             // because it is the same like MBOX_STATE_RX_ALL_EXT but speed is more
1371             // important here than codesize
1372             //
1373             case MBOX_STATE_RX_ALL_STD:
1374             case MBOX_STATE_RX_ALL_EXT:
1375             case MBOX_STATE_RX_FILT:
1376             {
1377                  //
1378                  // read data from message box - during processing of this function
1379                  // the message box is locked and cannot receive further messages
1380                  //
1381                  flexcan_read_from_mbox(chan, event_id, pevent, &(pmbox_info->ctrlstat_shadow));
1382                  res = flexcan_is_no_self_tx(pevent, info, pmbox_info);
1383                  }
1384                  break;           
1385
1386 #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT
1387             //
1388             // If a TX message box cause the event then we store the last transmitted
1389             // message into the receive message queue
1390             //
1391             case MBOX_STATE_TX:  
1392                  pevent->flags = CYGNUM_CAN_EVENT_TX;
1393                  pevent->msg = info->last_tx_msg;
1394                  break;
1395 #endif // CYGOPT_IO_CAN_TX_EVENT_SUPPORT
1396                             
1397             case MBOX_STATE_REMOTE_TX:
1398                  break;
1399                  
1400             default:
1401                  res = false;
1402         } // switch (pmbox->state)
1403     }
1404     else // (event_id >= FLEXCAN_ERR_EVENT)
1405     {
1406         //
1407         // We have an status event - check if it is an bus off interrupt or an
1408         // error interrupt and provide error information to upper layer
1409         //
1410         HAL_READ_UINT16(&flexcan->ESTAT, estat);
1411         pevent->msg.data.bytes[0] = estat & 0xFF;
1412         pevent->msg.data.bytes[1] = (estat >> 8) & 0xFF; 
1413         HAL_READ_UINT8(&flexcan->RXERRCNT, pevent->msg.data.bytes[2]);
1414         HAL_READ_UINT8(&flexcan->TXERRCNT, pevent->msg.data.bytes[3]);
1415         switch (event_id)
1416         {
1417             case FLEXCAN_ERR_EVENT :
1418                  //
1419                  // indicate error passive event and provide content of estat register
1420                  // for a more precise error information
1421                  //
1422                  if (estat & FLEXCAN_ESTAT_FCS_ERROR_PASSIVE)
1423                  {
1424                     pevent->flags = CYGNUM_CAN_EVENT_ERR_PASSIVE;
1425                  }
1426                  //
1427                  // If we are not in error passive state then we check if the
1428                  // error counters reached the warning level
1429                  //
1430                  else
1431                  {               
1432                      //
1433                      // indicate tx error counter warning level reached
1434                      //
1435                      if (estat & FLEXCAN_ESTAT_TXWARN)
1436                      {
1437                          pevent->flags |= CYGNUM_CAN_EVENT_WARNING_TX;
1438                      }
1439                  
1440                      //
1441                      // indicate rx error counter warning level reached
1442                      //
1443                      if (estat & FLEXCAN_ESTAT_RXWARN)
1444                      {
1445                          pevent->flags |= CYGNUM_CAN_EVENT_WARNING_RX;
1446                      }
1447                  }
1448                  break;
1449                  
1450             case FLEXCAN_BUSOFF_EVENT:
1451                  pevent->flags = CYGNUM_CAN_EVENT_BUS_OFF;
1452                  break;
1453                  
1454             case FLEXCAN_WAKE_EVENT:
1455                  pevent->flags = CYGNUM_CAN_EVENT_LEAVING_STANDBY;
1456                  break;
1457         } // switch (event_id)
1458     }
1459     
1460     return res;
1461 }
1462
1463
1464 //===========================================================================
1465 // Send one CAN message to CAN hardware
1466 //===========================================================================
1467 static bool flexcan_putmsg(can_channel *chan, cyg_can_message *pmsg, void *pdata)
1468 {
1469     flexcan_info      *info    = (flexcan_info *)chan->dev_priv;
1470     flexcan_regs      *flexcan = (flexcan_regs *)info->base;
1471     cyg_uint8          mbox    = *((cyg_uint8 *)pdata);
1472     flexcan_mbox_info *pmbox   = &info->mboxes[mbox];
1473     cyg_uint16         iflag;
1474    
1475     HAL_READ_UINT16(&flexcan->IFLAG, iflag);
1476     
1477     //
1478     // check if device is busy sending a message
1479     //
1480     if (pmbox->busy)
1481     {
1482         //
1483         // if device is busy and the interrupt flag is set, then we know
1484         // that device is not busy any longer
1485         //
1486         if (iflag & (0x0001 << mbox))
1487         {
1488             HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));
1489         }
1490         else
1491         {
1492             return false;
1493         }
1494     }
1495     
1496     pmbox->busy    = true;        // mark transmitter as busy
1497     info->last_tx_id  = pmsg->id; // store message in order to identify self recieved frames 
1498
1499 #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT 
1500     info->last_tx_msg = *pmsg;    // store the transmitted message for TX events
1501 #endif  
1502   
1503     flexcan_cfg_mbox_tx(&flexcan->mbox[mbox], pmsg, false); // send message
1504     
1505     return true;
1506 }
1507
1508
1509 //===========================================================================
1510 // Flexcan start xmit - If the chip is in standby mode then a call to this
1511 // function will cause the FlexCAN modul to leave the standby mode. So
1512 // the output queue should be empty before entering stadby mode
1513 //===========================================================================
1514 static void flexcan_start_xmit(can_channel* chan)
1515 {
1516     flexcan_info         *info    = (flexcan_info *)chan->dev_priv;
1517     CYG_INTERRUPT_STATE   saved_state;
1518
1519     HAL_DISABLE_INTERRUPTS(saved_state);
1520     
1521     //
1522     // if we are in standby state the we leave standby state now. This is
1523     // the reason that the user should wait until the TX queue is empty before 
1524     // entering standby mode- or he should drain or flush the TX queue
1525     //
1526     if (CYGNUM_CAN_STATE_STANDBY == info->state)
1527     {
1528         flexcan_leave_standby(chan);
1529     }
1530     
1531     //
1532     // Now enable message box 15 interrupts
1533     //
1534     flexcan_mboxint_enable(info, info->tx_all_mbox);
1535     
1536     //
1537     // kick transmitter
1538     //
1539     chan->callbacks->xmt_msg(chan, &info->tx_all_mbox);  // Kick transmitter (if necessary)
1540     
1541     HAL_RESTORE_INTERRUPTS(saved_state);
1542 }
1543
1544
1545 //===========================================================================
1546 // Flexcan stop transmission
1547 //===========================================================================
1548 static void flexcan_stop_xmit(can_channel* chan)
1549 {
1550     flexcan_info         *info    = (flexcan_info *)chan->dev_priv;
1551     CYG_INTERRUPT_STATE  saved_state;
1552
1553     HAL_DISABLE_INTERRUPTS(saved_state);
1554     
1555     //
1556     // Now disable message box 15 interrupts
1557     //
1558     flexcan_mboxint_disable(info, info->tx_all_mbox);
1559
1560     HAL_RESTORE_INTERRUPTS(saved_state);
1561 }
1562
1563
1564 //===========================================================================
1565 // Configure flexcan channel
1566 //===========================================================================
1567 static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool init)
1568 {
1569     flexcan_info    *info    = (flexcan_info *)chan->dev_priv;
1570     flexcan_regs    *flexcan = (flexcan_regs *)info->base;
1571     cyg_uint16       tmp16;
1572     cyg_uint8        tmp8;
1573     cyg_uint8        i;
1574     
1575     //
1576     // the first thing we need to do is to stop the chip
1577     //
1578     flexcan_stop_chip(chan);  
1579     
1580     //
1581     // if this is the first initialisation of the FlexCAN modul we need to execute
1582     // some extra steps here
1583     //
1584     if (init)
1585     {
1586 #if defined(CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN0) && defined(HAL_MCF52xx_FLEXCAN0_PROC_INIT)
1587         if (info == &flexcan_can0_info) {
1588             HAL_MCF52xx_FLEXCAN0_PROC_INIT();
1589         }
1590 #endif
1591         
1592         //
1593         // Issue a reset in order to go into halt mode. The reset will set the
1594         // the halt bit in mcr
1595         //
1596         HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
1597         tmp16 &= ~FLEXCAN_MCR_FRZ;
1598         HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16);
1599         tmp16 |= FLEXCAN_MCR_SOFTRST;
1600         HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16);
1601         HAL_DELAY_US(10);
1602     
1603         //
1604         // Check reset status
1605         //
1606         HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
1607         if (tmp16 & FLEXCAN_MCR_SOFTRST)
1608         {
1609             return false;
1610         }
1611     
1612         //
1613         // Initialize the transmit and receive pin modes
1614         //
1615         HAL_WRITE_UINT8(&flexcan->CANCTRL0 , (FLEXCAN_CTRL0_TXMODE_FULL_0_DOMINANT  
1616                                             | FLEXCAN_CTRL0_RXMODE_0_DOMINANT)
1617                                             & ~FLEXCAN_CTRL0_BOFFMSK
1618                                             & ~FLEXCAN_CTRL0_ERRMASK);
1619                                             
1620         //
1621         // deactivate all message buffers - this is mandatory for configuration
1622         // of message buffers
1623         //
1624         for (i = FLEXCAN_MBOX_MIN; i <= FLEXCAN_MBOX_MAX; ++i)
1625         {
1626             HAL_WRITE_UINT16(&flexcan->mbox[i], MBOX_RXCODE_NOT_ACTIVE);
1627         }   
1628         
1629         //
1630         // mask all interrupts
1631         //
1632         info->imask_shadow = 0x0000;
1633         HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
1634         HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
1635         HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 & ~(FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));    
1636         
1637         //
1638         // setup bus arbitration mode - the LBUF bit defines the 
1639         // transmit-first scheme 0 = message buffer with lowest ID
1640         // 1 = message buffer with lowest number. We use lowest ID here
1641         //
1642         HAL_READ_UINT8(&flexcan->CANCTRL1, tmp8);
1643         HAL_WRITE_UINT8(&flexcan->CANCTRL1, (tmp8 & ~FLEXCAN_CTRL1_LBUF));    
1644         
1645         //
1646         // setup all rx message buffers
1647         //
1648         flexcan_config_rx_all(chan);
1649     
1650         //
1651         // bus off interrupt and error interrupt
1652         //
1653         HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
1654         HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 | (FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));                             
1655     } // if (init)
1656                       
1657     flexcan_set_baud(chan, config->baud); // setup baud rate
1658     
1659     //
1660     // store new config values
1661     //
1662     if (config != &chan->config) 
1663     {
1664         chan->config = *config;
1665     }
1666     flexcan_start_chip(chan);             // now we can start the chip again
1667     
1668     return true;
1669 }
1670
1671 //===========================================================================
1672 /// First initialisation and reset of CAN modul.
1673 //===========================================================================
1674 static bool flexcan_init(struct cyg_devtab_entry* devtab_entry)
1675 {
1676     can_channel       *chan    = (can_channel*)devtab_entry->priv;
1677     flexcan_info      *info    = (flexcan_info *)chan->dev_priv;
1678     flexcan_mbox_info *pmbox;
1679
1680     if (!flexcan_config(chan, &chan->config, true))
1681     {
1682         return false;
1683     }
1684        
1685     //
1686     // prepare message box interrupt for message box 15 - the tx message box
1687     //
1688     pmbox = &info->mboxes[info->tx_all_mbox];
1689     cyg_drv_interrupt_create(pmbox->isr_vec,
1690                              pmbox->isr_priority,
1691                              (cyg_addrword_t) chan,
1692                              &flexcan_mbox_tx_isr,
1693                              &flexcan_mbox_tx_dsr,
1694                              &(pmbox->interrupt_handle),
1695                              &(pmbox->interrupt));
1696     cyg_drv_interrupt_attach(pmbox->interrupt_handle);
1697     cyg_drv_interrupt_unmask(pmbox->isr_vec);
1698     
1699     //
1700     // prepare error interrupt
1701     //
1702     cyg_drv_interrupt_create(info->err_int.isr_vec,
1703                              info->err_int.isr_priority,
1704                              (cyg_addrword_t) chan,
1705                              &flexcan_err_isr,
1706                              &flexcan_err_dsr,
1707                              &(info->err_int.interrupt_handle),
1708                              &(info->err_int.interrupt));
1709     cyg_drv_interrupt_attach(info->err_int.interrupt_handle);
1710     cyg_drv_interrupt_unmask(info->err_int.isr_vec);
1711     
1712     //
1713     // prepare busoff interrupt
1714     //
1715     cyg_drv_interrupt_create(info->boff_int.isr_vec,
1716                              info->boff_int.isr_priority,
1717                              (cyg_addrword_t) chan,
1718                              &flexcan_busoff_isr,
1719                              &flexcan_busoff_dsr,
1720                              &(info->boff_int.interrupt_handle),
1721                              &(info->boff_int.interrupt));
1722     cyg_drv_interrupt_attach(info->boff_int.interrupt_handle);
1723     cyg_drv_interrupt_unmask(info->boff_int.isr_vec);
1724     
1725     //
1726     // prepare wake interrupt
1727     //
1728     cyg_drv_interrupt_create(info->wake_int.isr_vec,
1729                              info->wake_int.isr_priority,
1730                              (cyg_addrword_t) chan,
1731                              &flexcan_wake_isr,
1732                              &flexcan_wake_dsr,
1733                              &(info->wake_int.interrupt_handle),
1734                              &(info->wake_int.interrupt));
1735     cyg_drv_interrupt_attach(info->wake_int.interrupt_handle);
1736     cyg_drv_interrupt_unmask(info->wake_int.isr_vec);
1737         
1738     return true;
1739 }
1740
1741
1742 //===========================================================================
1743 // Flexcan error interrupt handler
1744 //===========================================================================
1745 static cyg_uint32  flexcan_err_isr(cyg_vector_t vec, cyg_addrword_t data)
1746 {
1747     can_channel  *chan    = (can_channel *)data;
1748     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
1749     flexcan_regs *flexcan = (flexcan_regs *)info->base;
1750     cyg_uint8     ctrl0;
1751     cyg_uint16    estat;
1752     
1753     //
1754     // first we disable error interrupts - DSR will reenable it later
1755     //
1756     HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
1757     HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 & ~FLEXCAN_CTRL0_ERRMASK);
1758     
1759     //
1760     // for clearing the interrupt we first read the flag register as 1
1761     // and then write it as 1 (and not as zero like the manual stated)
1762     // we clear only the flag of this interrupt and leave all other
1763     // message box interrupts untouched
1764     //
1765     HAL_READ_UINT16(&flexcan->ESTAT, estat);
1766     HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_ERRINT); 
1767     
1768     //
1769     // On the mcf5272 there is no need to acknowledge internal
1770     // interrupts, only external ones.
1771     // cyg_drv_interrupt_acknowledge(vec);
1772     //
1773     return CYG_ISR_CALL_DSR;
1774 }
1775
1776
1777 //===========================================================================
1778 // DSR for all interrupts that are no message box interrupts
1779 //===========================================================================
1780 static void flexcan_err_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
1781 {
1782     can_channel  *chan     = (can_channel *)data;
1783     flexcan_info *info     = (flexcan_info *)chan->dev_priv;
1784     flexcan_regs *flexcan  = (flexcan_regs *)info->base;
1785     cyg_uint8     ctrl0;
1786     cyg_uint8     event_id = FLEXCAN_ERR_EVENT;
1787
1788     //
1789     // signal CAN event to generic IO CAN driver - it will do any further 
1790     // processing
1791     //            
1792     chan->callbacks->rcv_event(chan, &event_id);
1793     
1794     //
1795     // reenable bus off interrupts
1796     //
1797     HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
1798     HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 | FLEXCAN_CTRL0_ERRMASK);
1799 }
1800
1801
1802 //===========================================================================
1803 // Bus off interrupt handler
1804 //===========================================================================
1805 static cyg_uint32  flexcan_busoff_isr(cyg_vector_t vec, cyg_addrword_t data)
1806 {
1807     can_channel  *chan    = (can_channel *)data;
1808     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
1809     flexcan_regs *flexcan = (flexcan_regs *)info->base;
1810     cyg_uint8     ctrl0;
1811     cyg_uint16    estat;
1812     
1813     //
1814     // first we disable bus off interrupts - DSR will reenable it later
1815     //
1816     HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
1817     HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 & ~FLEXCAN_CTRL0_BOFFMSK);
1818     
1819     //
1820     // for clearing the interrupt we first read the flag register as 1
1821     // and then write it as 1 (and not as zero like the manual stated)
1822     // we clear only the flag of this interrupt and leave all other
1823     // message box interrupts untouched
1824     //
1825     HAL_READ_UINT16(&flexcan->ESTAT, estat);
1826     HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_BOFFINT);  
1827     
1828     //
1829     // On the mcf5272 there is no need to acknowledge internal
1830     // interrupts, only external ones.
1831     // cyg_drv_interrupt_acknowledge(vec);
1832     //
1833     return CYG_ISR_CALL_DSR;
1834 }
1835
1836
1837 //===========================================================================
1838 // DSR for all interrupts that are no message box interrupts
1839 //===========================================================================
1840 static void flexcan_busoff_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
1841 {
1842     can_channel  *chan     = (can_channel *)data;
1843     flexcan_info *info     = (flexcan_info *)chan->dev_priv;
1844     flexcan_regs *flexcan  = (flexcan_regs *)info->base;
1845     cyg_uint8     ctrl0;
1846     cyg_uint8     event_id = FLEXCAN_BUSOFF_EVENT;
1847
1848     //
1849     // signal CAN event to generic IO CAN driver - it will do any further 
1850     // processing
1851     //            
1852     chan->callbacks->rcv_event(chan, &event_id);
1853     
1854     //
1855     // reenable bus off interrupts
1856     //
1857     HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
1858     HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 | FLEXCAN_CTRL0_BOFFMSK);  
1859 }
1860
1861
1862 //===========================================================================
1863 // Bus off interrupt handler
1864 //===========================================================================
1865 static cyg_uint32  flexcan_wake_isr(cyg_vector_t vec, cyg_addrword_t data)
1866 {
1867     can_channel  *chan    = (can_channel *)data;
1868     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
1869     flexcan_regs *flexcan = (flexcan_regs *)info->base;
1870     cyg_uint16    estat;
1871     
1872     //
1873     // first we disable wake interrupts - we set the mcr register to
1874     // zero in order to bring it back to normal state
1875     //
1876     HAL_WRITE_UINT16(&flexcan->CANMCR, 0);
1877     
1878     //
1879     // for clearing the interrupt we first read the flag register as 1
1880     // and then write it as 1 (and not as zero like the manual stated)
1881     // we clear only the flag of this interrupt and leave all other
1882     // message box interrupts untouched
1883     //
1884     HAL_READ_UINT16(&flexcan->ESTAT, estat);
1885     HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_WAKEINT);
1886        
1887     //
1888     // On the mcf5272 there is no need to acknowledge internal
1889     // interrupts, only external ones.
1890     // cyg_drv_interrupt_acknowledge(vec);
1891     //
1892     return CYG_ISR_CALL_DSR;
1893 }
1894
1895
1896 //===========================================================================
1897 // DSR for all interrupts that are no message box interrupts
1898 //===========================================================================
1899 static void flexcan_wake_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
1900 {
1901     can_channel  *chan     = (can_channel *)data;
1902     flexcan_info *info     = (flexcan_info *)chan->dev_priv;
1903     flexcan_regs *flexcan  = (flexcan_regs *)info->base;
1904     cyg_uint8     event_id = FLEXCAN_WAKE_EVENT;
1905     cyg_uint8     ctrl0;
1906
1907     //
1908     // signal CAN event to generic IO CAN driver - it will do any further 
1909     // processing we will enable all other interrupts after the call to 
1910     // rcv_event because the user should receive this event as the first
1911     // event after FlexCAN leaves standby.
1912     //            
1913     chan->callbacks->rcv_event(chan, &event_id);
1914     
1915     //
1916     // for standby we disabled all interrut source so we have to enable
1917     // it here again for normal operation
1918     //
1919     HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
1920     HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
1921     HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 |(FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
1922 }
1923
1924
1925 //===========================================================================
1926 // Flexcan message box isr for rx messages if message filtering is
1927 // enabled
1928 //===========================================================================
1929 static cyg_uint32 flexcan_mbox_rx_filt_isr(cyg_vector_t vec, cyg_addrword_t data)
1930 {
1931     can_channel  *chan    = (can_channel *)data;
1932     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
1933     flexcan_regs *flexcan = (flexcan_regs *)info->base;
1934     cyg_uint16    iflag;
1935     
1936     //
1937     // number of message box can be calculated from vector that cause
1938     // interrupt - we pass this message box number as additional data to the
1939     // callback because it is required in the receive event function later
1940     //
1941     cyg_uint8 mbox = vec - info->isr_vec_mbox0;    
1942     
1943     //
1944     // first we disable interrupts of this message box - the DSR will
1945     // reenable it later
1946     //
1947     flexcan_mboxint_disable(info, mbox);
1948     info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ;
1949     
1950     //
1951     // for clearing the interrupt we first read the flag register as 1
1952     // and then write it as 1 (and not as zero like the manual stated)
1953     // we clear only the flag of this interrupt and leave all other
1954     // message box interrupts untouched
1955     //
1956     HAL_READ_UINT16(&flexcan->IFLAG, iflag);
1957     HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));    
1958     
1959     //
1960     // On the mcf5272 there is no need to acknowledge internal
1961     // interrupts, only external ones.
1962     // cyg_drv_interrupt_acknowledge(vec);
1963     //
1964     return CYG_ISR_CALL_DSR;
1965 }
1966
1967
1968 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
1969 //===========================================================================
1970 // Flexcan message box isr for extended identifiers if reception of all
1971 // available messages is enabled
1972 //===========================================================================
1973 static cyg_uint32 flexcan_mbox_rx_ext_isr(cyg_vector_t vec, cyg_addrword_t data)
1974 {
1975     can_channel            *chan    = (can_channel *)data;
1976     flexcan_info           *info    = (flexcan_info *)chan->dev_priv;
1977     flexcan_regs           *flexcan = (flexcan_regs *)info->base;
1978     cyg_uint16              iflag;
1979     flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_ext_circbuf);
1980
1981     //
1982     // number of message box can be calculated from vector that caused
1983     // interrupt - we pass this message box number as additional data to the
1984     // callback because it is required in the receive event function later
1985     //
1986     cyg_uint8 mbox = vec - info->isr_vec_mbox0;
1987     if (++prx_mbox_list->count < info->mboxes_ext_cnt)
1988     {
1989         prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt;
1990         flexcan_hwmbox_enable_rx(flexcan, prx_mbox_list->idx_wr + info->mboxes_std_cnt);
1991         flexcan_hwmbox_lock(flexcan, mbox, &(info->mboxes[mbox].ctrlstat_shadow));
1992         flexcan_hwmbox_disable(flexcan, mbox);  // now disable this message box - it is already locked
1993         //
1994         // first we disable interrupts of this message box - the DSR will
1995         // reenable it later
1996         //
1997         flexcan_mboxint_disable(info, mbox);
1998     }
1999     else
2000     {
2001         prx_mbox_list->count = info->mboxes_ext_cnt;
2002         info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ;
2003     }
2004
2005     //
2006     // for clearing the interrupt we first read the flag register as 1
2007     // and then write it as 1 (and not as zero like the manual stated)
2008     // we clear only the flag of this interrupt and leave all other
2009     // message box interrupts untouched
2010     //
2011     HAL_READ_UINT16(&flexcan->IFLAG, iflag);
2012     HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));
2013
2014     //
2015     // On the mcf5272 there is no need to acknowledge internal
2016     // interrupts, only external ones.
2017     // cyg_drv_interrupt_acknowledge(vec); If counter of mbox list is > 1
2018     // then we know that there is already a DSR running and we do not
2019     // need to invoke one
2020     //
2021     if (prx_mbox_list->count > 1)
2022     {
2023         return CYG_ISR_HANDLED;
2024     }
2025     else
2026     {
2027         return CYG_ISR_CALL_DSR;
2028     }
2029 }
2030
2031
2032 //===========================================================================
2033 // FlexCAN message box DSR for extended CAN frames
2034 //===========================================================================
2035 static void flexcan_mbox_rx_ext_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
2036 {
2037     can_channel  *          chan    = (can_channel *)data;
2038     flexcan_info           *info    = (flexcan_info *)chan->dev_priv;
2039     flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_ext_circbuf);
2040     cyg_uint8               mbox;
2041     cyg_uint8               mbox_cnt;
2042
2043     //
2044     // we do not process the message box we received as event_id
2045     // we take the message boxes from the ring buffer
2046     //
2047     do
2048     {
2049         cyg_drv_isr_lock();
2050         mbox_cnt = --prx_mbox_list->count;
2051         cyg_drv_isr_unlock();
2052
2053         mbox = prx_mbox_list->idx_rd + info->mboxes_std_cnt;
2054         prx_mbox_list->idx_rd = (prx_mbox_list->idx_rd + 1) % info->mboxes_ext_cnt;
2055         chan->callbacks->rcv_event(chan, &mbox);
2056         flexcan_mboxint_enable(info, mbox);
2057
2058         //
2059         // if the last message box is enabled, then we have to enable
2060         // another one now because the last message box is filled already
2061         //
2062         if (mbox_cnt == (info->mboxes_ext_cnt - 1))
2063         {
2064             cyg_uint8     active_mbox;
2065             cyg_uint8     next_mbox;
2066             flexcan_regs *flexcan = (flexcan_regs *)info->base;
2067
2068             cyg_drv_isr_lock();
2069             active_mbox = prx_mbox_list->idx_wr;
2070             next_mbox = prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt;
2071             cyg_drv_isr_unlock();
2072
2073             active_mbox += info->mboxes_std_cnt;
2074             next_mbox += info->mboxes_std_cnt;
2075             flexcan_hwmbox_lock(flexcan, active_mbox, &(info->mboxes[active_mbox].ctrlstat_shadow));
2076             flexcan_hwmbox_disable(flexcan, active_mbox);  // now disable this message box - it is already locked
2077             flexcan_hwmbox_enable_rx(flexcan, next_mbox);
2078         }
2079     }
2080     while (mbox_cnt);
2081 }
2082
2083 #endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
2084
2085
2086 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
2087 //===========================================================================
2088 // Flexcan message box isr for standard identifiers if reception of all
2089 // available messages is enabled
2090 //===========================================================================
2091 static cyg_uint32 flexcan_mbox_rx_std_isr(cyg_vector_t vec, cyg_addrword_t data)
2092 {
2093     can_channel            *chan    = (can_channel *)data;
2094     flexcan_info           *info    = (flexcan_info *)chan->dev_priv;
2095     flexcan_regs           *flexcan = (flexcan_regs *)info->base;
2096     cyg_uint16              iflag;
2097     flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_std_circbuf);
2098
2099     //
2100     // number of message box can be calculated from vector that caused
2101     // interrupt - we pass this message box number as additional data to the
2102     // callback because it is required in the receive event function later
2103     //
2104     cyg_uint8 mbox = vec - info->isr_vec_mbox0;
2105     if (++prx_mbox_list->count < info->mboxes_std_cnt)
2106     {
2107         prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_std_cnt;
2108         flexcan_hwmbox_enable_rx(flexcan, prx_mbox_list->idx_wr);
2109         flexcan_hwmbox_lock(flexcan, mbox, &(info->mboxes[mbox].ctrlstat_shadow));
2110         flexcan_hwmbox_disable(flexcan, mbox);  // now disable this message box - it is already locked
2111         //
2112         // first we disable interrupts of this message box - the DSR will
2113         // reenable it later
2114         //
2115         flexcan_mboxint_disable(info, mbox);
2116     }
2117     else
2118     {
2119         prx_mbox_list->count = info->mboxes_std_cnt;
2120         info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ;
2121     }
2122
2123     //
2124     // for clearing the interrupt we first read the flag register as 1
2125     // and then write it as 1 (and not as zero like the manual stated)
2126     // we clear only the flag of this interrupt and leave all other
2127     // message box interrupts untouched
2128     //
2129     HAL_READ_UINT16(&flexcan->IFLAG, iflag);
2130     HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));
2131
2132     //
2133     // On the mcf5272 there is no need to acknowledge internal
2134     // interrupts, only external ones.
2135     // cyg_drv_interrupt_acknowledge(vec); If counter of mbox list is > 1
2136     // then we know that there is already a DSR running and we do not
2137     // need to invoke one
2138     //
2139     if (prx_mbox_list->count > 1)
2140     {
2141         return CYG_ISR_HANDLED;
2142     }
2143     else
2144     {
2145         return CYG_ISR_CALL_DSR;
2146     }
2147 }
2148
2149
2150 //===========================================================================
2151 // Flexcan message box dsr for standard CAN frames
2152 //===========================================================================
2153 static void flexcan_mbox_rx_std_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
2154 {
2155     can_channel  *          chan    = (can_channel *)data;
2156     flexcan_info           *info    = (flexcan_info *)chan->dev_priv;
2157     flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_std_circbuf);
2158     cyg_uint8               mbox;
2159     cyg_uint8               mbox_cnt;
2160
2161     //
2162     // we do not process the message box we received as event_id
2163     // we take the message boxes from the ring buffer
2164     //
2165     do
2166     {
2167         cyg_drv_isr_lock();
2168         mbox_cnt = --prx_mbox_list->count;
2169         cyg_drv_isr_unlock();
2170
2171         mbox = prx_mbox_list->idx_rd;
2172         prx_mbox_list->idx_rd = (prx_mbox_list->idx_rd + 1) % info->mboxes_std_cnt;
2173         chan->callbacks->rcv_event(chan, &mbox);
2174         flexcan_mboxint_enable(info, mbox);
2175
2176         //
2177         // if the last message box is enabled, then we have to enable
2178         // another one now because the last message box is filled already
2179         //
2180         if (mbox_cnt == (info->mboxes_std_cnt - 1))
2181         {
2182             cyg_uint8     active_mbox;
2183             cyg_uint8     next_mbox;
2184             flexcan_regs *flexcan = (flexcan_regs *)info->base;
2185
2186             cyg_drv_isr_lock();
2187             active_mbox = prx_mbox_list->idx_wr;
2188             next_mbox = prx_mbox_list->idx_wr = (prx_mbox_list->idx_wr + 1) % info->mboxes_ext_cnt;
2189             cyg_drv_isr_unlock();
2190
2191             flexcan_hwmbox_lock(flexcan, active_mbox, &(info->mboxes[active_mbox].ctrlstat_shadow));
2192             flexcan_hwmbox_disable(flexcan, active_mbox);  // now disable this message box - it is already locked
2193             flexcan_hwmbox_enable_rx(flexcan, next_mbox);
2194         }
2195     }
2196     while (mbox_cnt);
2197 }
2198 #endif // CYGOPT_IO_CAN_STD_CAN_ID
2199
2200
2201 //===========================================================================
2202 // FlexCAN DSR for message filters
2203 //===========================================================================
2204 static void flexcan_mbox_rx_filt_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
2205 {
2206     can_channel  *chan    = (can_channel *)data;
2207     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
2208     
2209     //
2210     // number of message box can be calculated from vector that caused
2211     // interrupt - we pass this message box number as additional data to the
2212     // callback
2213     //
2214     cyg_uint8 mbox = vec - info->isr_vec_mbox0;    
2215     
2216     //
2217     // signal CAN event to generic IO CAN driver - it will do any further 
2218     // processing
2219     //            
2220     chan->callbacks->rcv_event(chan, &mbox);
2221
2222     //
2223     // reenable interrupts for the message box that caused the DSR to run
2224     //
2225     flexcan_mboxint_enable(info, mbox);
2226 }
2227
2228 //===========================================================================
2229 // Flexcan message box isr
2230 //===========================================================================
2231 static cyg_uint32 flexcan_mbox_tx_isr(cyg_vector_t vec, cyg_addrword_t data)
2232 {
2233     can_channel       *chan    = (can_channel *)data;
2234     flexcan_info      *info    = (flexcan_info *)chan->dev_priv;
2235     flexcan_regs      *flexcan = (flexcan_regs *)info->base;
2236     cyg_uint16         iflag;
2237     
2238     // number of message box can be calculated from vector that cause
2239     // interrupt - we pass this message box number as additional data to the
2240     // callback
2241     //
2242     cyg_uint8 mbox = vec - info->isr_vec_mbox0;
2243     
2244     //
2245     // the first thing we do here is to disable this message box. we do this
2246     // because if we just sent a remote transmission request with this message
2247     // box then the FLEXCAN modul will automatically set up this message box
2248     // for reception of the requested data frame. But we won't receive messages
2249     // with the TX message box and deactivate it here immediatelly.
2250     // 
2251     HAL_WRITE_UINT8(&flexcan->mbox[mbox].ctrlstat, MBOX_TXCODE_NOT_READY);   
2252     
2253     //
2254     // first we disable interrupts of this message box - the DSR will
2255     // reenable it later
2256     //
2257     flexcan_mboxint_disable(info, mbox);
2258     
2259     //
2260     // for clearing the interrupt we first read the flag register as 1
2261     // and then write it as 1 (and not as zero like the manual stated)
2262     // we clear only the flag of this interrupt and leave all other
2263     // message box interrupts untouched
2264     //
2265     HAL_READ_UINT16(&flexcan->IFLAG, iflag);
2266     HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));   
2267     
2268     //
2269     // On the mcf5272 there is no need to acknowledge internal
2270     // interrupts, only external ones.
2271     // cyg_drv_interrupt_acknowledge(vec);
2272     //
2273     return CYG_ISR_CALL_DSR;
2274 }
2275
2276
2277 //===========================================================================
2278 // Flexcan message box dsr
2279 //===========================================================================
2280 static void flexcan_mbox_tx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
2281 {
2282     can_channel       *chan    = (can_channel *)data;
2283     flexcan_info      *info    = (flexcan_info *)chan->dev_priv;
2284     flexcan_mbox_info *pmbox;
2285     
2286     //
2287     // number of message box can be calculated from vector that caused
2288     // interrupt - we pass this message box number as additional data to the
2289     // callback
2290     //
2291     cyg_uint8 mbox = vec - info->isr_vec_mbox0; 
2292     pmbox = &info->mboxes[mbox];
2293     
2294 #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT 
2295     //
2296     // signal CAN TX event to generic IO CAN driver - it will do any further 
2297     // processing
2298     //            
2299     chan->callbacks->rcv_event(chan, &mbox);
2300 #endif
2301     
2302     pmbox->busy = false;
2303        
2304     //
2305     // send next message 
2306     //            
2307     chan->callbacks->xmt_msg(chan, &mbox);
2308     
2309     //
2310     // reenable interrupts for the message box that caused the DSR to run
2311     //
2312     flexcan_mboxint_enable(info, mbox);
2313 }
2314
2315
2316 //===========================================================================
2317 // Start FlexCAN modul
2318 //===========================================================================
2319 static void flexcan_start_chip(can_channel *chan)
2320 {
2321     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
2322     flexcan_regs *flexcan = (flexcan_regs *)info->base;
2323     
2324     cyg_uint16 tmp16;
2325     
2326     info->state = CYGNUM_CAN_STATE_ACTIVE;
2327     HAL_READ_UINT16(&flexcan->CANMCR, tmp16);    
2328     HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 
2329                  & ~(FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT));
2330 }
2331
2332
2333 //===========================================================================
2334 // Stop FlexCAN modul
2335 //===========================================================================
2336 static void flexcan_stop_chip(can_channel *chan)
2337 {
2338     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
2339     flexcan_regs *flexcan = (flexcan_regs *)info->base;
2340     cyg_uint16    tmp16;
2341     
2342     info->state = CYGNUM_CAN_STATE_STOPPED;
2343     HAL_READ_UINT16(&flexcan->CANMCR, tmp16);    
2344     HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 | FLEXCAN_MCR_HALT);
2345 }
2346
2347
2348 //===========================================================================
2349 // Set FlexCAN modul into standby mode
2350 // If the flag selfwake is active then the FlexCAN modul will be set into
2351 // standby mode with selwake. This means the FlexCAN modul will leave
2352 // standby as soon as a message box will receive a message
2353 //===========================================================================
2354 static void flexcan_enter_standby(can_channel *chan, bool selfwake)
2355 {
2356     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
2357     flexcan_regs *flexcan = (flexcan_regs *)info->base;
2358     cyg_uint16    tmp16;
2359     cyg_uint8     tmp8;
2360     cyg_uint8     i;
2361     
2362     //
2363     // The CPU should disable all interrupts in the FlexCAN before entering low-power
2364     // stop mode. Otherwise it may be interrupted while in STOP mode upon a non
2365     // wake-up condition; If desired, the WAKEMASK bit should be set to enable the
2366     // WAKEINT.
2367     //
2368     HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
2369     HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 & ~(FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
2370     
2371     //
2372     // We disable all message box interrupts. The WAKE DSR will reenable it later
2373     // after processing the WAKE event. This ensures that the wake event will be the
2374     // first event if a message arrives
2375     //
2376     HAL_WRITE_UINT16(&flexcan->IMASK, 0); 
2377     
2378     HAL_READ_UINT16(&flexcan->CANMCR, tmp16);  
2379     
2380     tmp16 |= FLEXCAN_MCR_STOP;
2381     
2382     //
2383     // if we should go to standby then we activate the SELWAKE bit so that a received
2384     // frame will bring us back to live
2385     //
2386     if (selfwake)
2387     {
2388         tmp16 |= FLEXCAN_MCR_SELFWAKE;
2389     }
2390       
2391     HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16);
2392     
2393     //
2394     // we have to poll the STOPACK bit in order to determine if chip
2395     // has entered stop mode. We poll 10 times - se we spent a maximum
2396     // of 2 ms here
2397     //
2398     for (i = 0; i < 10; ++i)
2399     {
2400         HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
2401         
2402         if (tmp16 & FLEXCAN_MCR_STOPACK)
2403         {
2404             info->state = CYGNUM_CAN_STATE_STANDBY;
2405             break;
2406         }
2407         HAL_DELAY_US(200);
2408     }
2409     
2410     //
2411     // if we are not in low power stop mode then we have to reenable interrupts
2412     //
2413     if (10 == i)
2414     {
2415         HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
2416         HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 | (FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
2417     }
2418     else
2419     {
2420         //
2421         // if we go into standby then we activate the wake interrupt so we will receive
2422         // a wake interrupt if we leave standby and can reenable interrups
2423         //
2424         if (selfwake)
2425         {
2426             HAL_READ_UINT16(&flexcan->CANMCR, tmp16);  
2427             HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 | FLEXCAN_MCR_WAKEMSK);  
2428         }
2429     }
2430 }
2431
2432
2433 //===========================================================================
2434 // Leave standby mode
2435 //===========================================================================
2436 static void flexcan_leave_standby(can_channel *chan)
2437 {
2438     flexcan_info *info    = (flexcan_info *)chan->dev_priv;
2439     flexcan_regs *flexcan = (flexcan_regs *)info->base;
2440     cyg_uint16    tmp16;
2441     cyg_uint8     i;
2442     
2443     HAL_READ_UINT16(&flexcan->CANMCR, tmp16);  
2444     HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 & ~(FLEXCAN_MCR_STOP | FLEXCAN_MCR_SELFWAKE));
2445     
2446     //
2447     // we have to poll the STOPACK bit in order to determine if chip
2448     // has leaved stop mode. We poll 10 times - se we spent a maximum
2449     // of 2 ms here
2450     //
2451     for (i = 0; i < 10; ++i)
2452     {
2453         HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
2454         
2455         if (!(tmp16 & FLEXCAN_MCR_STOPACK))
2456         {
2457             HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
2458             info->state = CYGNUM_CAN_STATE_ACTIVE;
2459             break;    
2460         }
2461         HAL_DELAY_US(200);
2462     } // for (i = 0; i < 10; ++i)
2463 }
2464
2465
2466 //===========================================================================
2467 // Set acceptance mask for message buffer
2468 //===========================================================================
2469 static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_can_id_type ext)
2470 {
2471     cyg_uint16 id;
2472     //
2473     // 32 bit access to RXMASK filters is broken so we use  16 Bit
2474     // access here
2475     //
2476     if (CYGNUM_CAN_ID_EXT == ext)
2477     {
2478         id  = ((mask >> 13) & 0xFFE0);       // set mask bits 18 - 28
2479         id |= ((mask >> 15) & 0x7);          // set mask bits 15 -17
2480         HAL_WRITE_UINT16(&rxmask_reg[0], id);
2481         
2482         id = (mask << 1) & 0xFFFE;
2483         HAL_WRITE_UINT16(&rxmask_reg[1], id);
2484     }
2485     else // (CYGNUM_CAN_ID_STD == ext)
2486     {
2487         id = ((mask << 5) & 0xFFE0); 
2488         HAL_WRITE_UINT16(&rxmask_reg[0], id);
2489         HAL_WRITE_UINT16(&rxmask_reg[1], 0xFFFF);  
2490     }
2491     
2492 }
2493
2494
2495
2496 //===========================================================================
2497 // Configure message box for transmission
2498 //===========================================================================
2499 static bool flexcan_cfg_mbox_tx(flexcan_mbox     *pmbox,
2500                                 cyg_can_message  *pmsg,
2501                                 bool              rtr)
2502 {
2503     cyg_uint16 id;
2504   
2505     HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_NOT_READY); 
2506     
2507     if (CYGNUM_CAN_ID_EXT == pmsg->ext)
2508     { 
2509         id  = ((pmsg->id >> 13) & 0xFFE0);   // setup id bits 18 - 28
2510         id |= (MBOX_CFG_IDE | MBOX_CFG_SSR); // set SSR and IDE bit to 1
2511         id |= ((pmsg->id >> 15) & 0x7);      // set id bits 15 - 17
2512         HAL_WRITE_UINT16(&pmbox->id_hi, id);
2513         
2514         id = ((pmsg->id << 1) & 0xFFFE);
2515         
2516         if (pmsg->rtr)
2517         {
2518             id |= MBOX_CFG_RTR_EXT;
2519         }   
2520         
2521         HAL_WRITE_UINT16(&pmbox->id_lo, id);
2522     }   
2523     else
2524     {
2525         id = ((pmsg->id << 5) & 0xFFE0);
2526         if (pmsg->rtr)
2527         {
2528             id |= MBOX_CFG_RTR_STD;           // set rtr bit for standard ID
2529         }
2530         HAL_WRITE_UINT16(&pmbox->id_hi, id);
2531         HAL_WRITE_UINT16(&pmbox->id_lo, 0);
2532     }
2533     
2534     pmsg->dlc %= 9; // limit data length to 8 bytes
2535     
2536     //
2537     // Now copy data bytes into buffer and start transmission
2538     //
2539     HAL_WRITE_UINT8_VECTOR(&pmbox->data, pmsg->data.bytes, pmsg->dlc, 1); 
2540     
2541    
2542     if (rtr)
2543     {
2544         HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_RESPONSE | pmsg->dlc);
2545     }
2546     else
2547     {
2548         HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_TRANSMIT | pmsg->dlc);
2549     }
2550     
2551     return true;
2552 }
2553
2554
2555
2556 //===========================================================================
2557 // Configure message box for reception of a certain CAN identifier
2558 //===========================================================================
2559 static void flexcan_cfg_mbox_rx(flexcan_mbox     *pmbox,
2560                                 cyg_can_message  *pmsg,
2561                                 bool              enable)
2562 {
2563     cyg_uint16 id;
2564     
2565     HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_NOT_ACTIVE); 
2566     
2567     if (CYGNUM_CAN_ID_EXT == pmsg->ext)
2568     { 
2569         id  = ((pmsg->id >> 13) & 0xFFE0);      // setup id bits 18 - 28
2570         id |= (MBOX_CFG_IDE | MBOX_CFG_SSR);    // set SSR and IDE bit to 1
2571         id |= ((pmsg->id >> 15) & 0x7);         // set id bits 15 - 17
2572         HAL_WRITE_UINT16(&pmbox->id_hi, id);    // write ID high
2573         
2574         id = ((pmsg->id << 1) & 0xFFFE);
2575         
2576         HAL_WRITE_UINT16(&pmbox->id_lo, id);// write ID low
2577     }   
2578     else
2579     {
2580         id = ((pmsg->id << 5) & 0xFFE0);
2581
2582         HAL_WRITE_UINT16(&pmbox->id_hi, id);
2583         HAL_WRITE_UINT16(&pmbox->id_lo, 0);
2584     }
2585     
2586     if (enable)
2587     {
2588     HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY);
2589     }
2590 }
2591
2592
2593 //===========================================================================
2594 // Read date from a message box
2595 //==========================================================================
2596 static void flexcan_read_from_mbox(can_channel  *chan,
2597                             cyg_uint8            mbox,
2598                             cyg_can_event       *pevent,
2599                             cyg_uint8           *ctrlstat)
2600 {
2601     flexcan_info    *info    = (flexcan_info *)chan->dev_priv;
2602     flexcan_regs    *flexcan = (flexcan_regs *)info->base;
2603     flexcan_mbox    *pmbox   = &flexcan->mbox[mbox];
2604     cyg_can_message *pmsg    = &pevent->msg;
2605     cyg_uint16       id;
2606     bool             enable_mbox = false;
2607     
2608     //
2609     // If controlstat was not read, then read it now
2610     //
2611     if (FLEXCAN_CTRLSTAT_NOT_READ == *ctrlstat)
2612     {
2613     HAL_READ_UINT8(&pmbox->ctrlstat, *ctrlstat); // this read will lock the mbox
2614         enable_mbox = true;
2615     }
2616     
2617     //
2618     // If message buffer is busy then it is now beeing filled with a new message
2619     // This condition will be cleared within 20 cycles - we simply do a 20 µs
2620     // delay here, that should be enougth
2621     //
2622     if (*ctrlstat & MBOX_RXCODE_BUSY)
2623     {
2624         HAL_DELAY_US(20);
2625     }
2626     
2627     pmsg->dlc = (*ctrlstat & MBOX_CFG_DLC_MASK); // store received data len
2628     
2629     HAL_READ_UINT16(&pmbox->id_hi, id);          // read ID high
2630     
2631     if (id & MBOX_CFG_IDE)
2632     {
2633         pmsg->ext = CYGNUM_CAN_ID_EXT;
2634         pmsg->id  = (id & 0xFFE0) << 13;
2635         pmsg->id |= (id & 0x07) << 15;
2636         
2637         HAL_READ_UINT16(&pmbox->id_lo, id);
2638         pmsg->id |= (id & 0xFFFE) >> 1;
2639         
2640         if (id & MBOX_CFG_RTR_EXT)
2641         {
2642             pmsg->rtr = CYGNUM_CAN_FRAME_RTR;
2643         }
2644         else
2645         {
2646             pmsg->rtr = CYGNUM_CAN_FRAME_DATA;
2647         }
2648     }
2649     else
2650     {
2651         pmsg->ext = CYGNUM_CAN_ID_STD;
2652         pmsg->id  = (id & 0xFFE0) >> 5;
2653         
2654         if (id & MBOX_CFG_RTR_STD)
2655         {
2656             pmsg->rtr = CYGNUM_CAN_FRAME_RTR;
2657         }
2658         else
2659         {
2660             pmsg->rtr = CYGNUM_CAN_FRAME_DATA;
2661         }
2662     }
2663     
2664     //
2665     // now finally copy data
2666     //
2667     HAL_READ_UINT8_VECTOR(&pmbox->data, pmsg->data.bytes, pmsg->dlc, 1);
2668        
2669     //
2670     // now mark this mbox as empty and read the free running timer
2671     // to unlock this mbox
2672     //
2673     if (enable_mbox)
2674     {
2675     HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY);
2676     HAL_READ_UINT16(&flexcan->TIMER, id);
2677     }
2678 #ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP    
2679     pevent->timestamp = id;
2680 #endif
2681 }
2682
2683
2684 //===========================================================================
2685 //                           INIT CAN BAUD RATE
2686 //===========================================================================
2687 static bool flexcan_set_baud(can_channel *chan, cyg_uint16 baud)
2688 {
2689     flexcan_info             *info = (flexcan_info *)chan->dev_priv;
2690     flexcan_regs             *flexcan = (flexcan_regs *)info->base;
2691     cyg_uint16                mcr_bck;
2692     cyg_uint8                 tmp8;
2693     cyg_uint8                 presdiv;
2694     cyg_uint8                 propseg;
2695     cyg_uint8                 pseg1_2;
2696     cyg_uint16                baudrate = flexcan_baud_rates[baud];
2697     
2698     //
2699     // Get bit timings from HAL because bit timings depend on sysclock
2700     //
2701     HAL_MCF52xx_FLEXCAN_GET_BIT_TIMINGS(&baudrate, &presdiv, &propseg, &pseg1_2);
2702     
2703     //
2704     // return false if baudrate is not supported
2705     //
2706     if (0 == baudrate)
2707     {
2708         return false;
2709     }
2710     
2711     //
2712     // For setting the bit timings we have to stop the flexcan modul
2713     //
2714     HAL_READ_UINT16(&flexcan->CANMCR, mcr_bck);
2715     HAL_WRITE_UINT16(&flexcan->CANMCR, mcr_bck | FLEXCAN_MCR_HALT);
2716     
2717     //
2718     // now we setup bit timings
2719     //
2720     HAL_WRITE_UINT8(&flexcan->PRESDIV, presdiv);
2721     HAL_READ_UINT8(&flexcan->CANCTRL1, tmp8);
2722     HAL_WRITE_UINT8(&flexcan->CANCTRL1, (tmp8 & 0xF8) | propseg); 
2723     HAL_READ_UINT8(&flexcan->CANCTRL2, tmp8);
2724     HAL_WRITE_UINT8(&flexcan->CANCTRL2, (tmp8 & 0xC0) | pseg1_2); 
2725     
2726     //
2727     // Now restore the previous state - if the modul was started then
2728     // it will no be started again, if it was stopped, then it remains stopped
2729     //
2730     HAL_WRITE_UINT16(&flexcan->CANMCR, mcr_bck);
2731     
2732     return true;
2733 }
2734
2735 //---------------------------------------------------------------------------
2736 // end of can_mcf_flexcan.c
2737