1 //==========================================================================
3 // devs/serial/m68k/flexcan/current/src/can_mcf_flexcan.c
5 // CAN driver for Motorola coldfire processors
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2003 Gary Thomas
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
44 // Author(s): Uwe Kindler
45 // Contributors: Uwe Kindler
47 // Purpose: support coldfire on-chip flexcan moduls
50 //####DESCRIPTIONEND####
52 //==========================================================================
55 //==========================================================================
57 //==========================================================================
58 #include <pkgconf/system.h>
59 #include <pkgconf/io_can.h>
60 #include <pkgconf/devs_can_mcf52xx_flexcan.h>
62 #include <cyg/infra/diag.h>
64 #include <cyg/io/io.h>
65 #include <cyg/io/devtab.h>
66 #include <cyg/io/can.h>
68 #include <cyg/hal/hal_arch.h>
69 #include <cyg/hal/hal_intr.h>
70 #include <cyg/hal/hal_io.h>
73 //===========================================================================
75 //===========================================================================
78 // we define our own ste of register bits in order to be independent from
79 // platform specific names
82 //---------------------------------------------------------------------------
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)
98 //---------------------------------------------------------------------------
99 // CTRL0 register bits
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)
113 //---------------------------------------------------------------------------
114 // CTRL1 register bits
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
124 //---------------------------------------------------------------------------
125 // CTRL2 register bits
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
134 //---------------------------------------------------------------------------
135 // ESTAT register bits
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)
159 // For receive event calls we use these two identifiers for
160 // err and bus off events - message boxes use 0 - 15
162 #define FLEXCAN_ERR_EVENT 16
163 #define FLEXCAN_BUSOFF_EVENT 17
164 #define FLEXCAN_WAKE_EVENT 18
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
173 //---------------------------------------------------------------------------
174 // message buffer cfg bits
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
182 #define MBOX_TXCODE_NOT_READY 0x80
183 #define MBOX_TXCODE_TRANSMIT 0xC0
184 #define MBOX_TXCODE_RESPONSE 0xA0
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
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
201 //---------------------------------------------------------------------------
202 // flexcan message buffer configuration
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
213 #define FLEXCAN_CTRLSTAT_NOT_READ 0 // indicates that control status register is not read
216 //===========================================================================
218 //===========================================================================
220 // Type of message buffer - required for function getevent in order to
221 // identify the type of message box that cause event
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;
235 // configuration info for flexcan message buffer
237 typedef struct flexcan_mbox_info_st
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
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
255 typedef struct st_rxmbox_circbuf
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;
263 // flexcan interrupt (busoff, err, wake) data - stores interrupt data for
264 // a non message box interrupt (bus off, err or wake interrupt)
266 typedef struct flexcan_int_st
268 cyg_vector_t isr_vec;
270 cyg_interrupt interrupt;
271 cyg_handle_t interrupt_handle;
275 // flexcan message box initialisation
277 #define FLEXCAN_MBOX_INIT(_mbox0_vec, _prio, _mbox_no) { \
278 isr_vec : (_mbox0_vec) + (_mbox_no), \
279 isr_priority : (_prio), \
285 // Interrupt initialisation
287 #define FLEXCAN_INT_INIT(_vec, _prio) \
290 isr_priority : (_prio) \
294 // flexcan configuration
296 typedef struct flexcan_info
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
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
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
311 flexcan_rxmbox_circbuf rxmbox_std_circbuf;
312 flexcan_rxmbox_circbuf rxmbox_ext_circbuf;
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
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
324 #ifdef FLEXCAN_CAN_STATS
325 cyg_uint32 isr_count;
326 cyg_uint32 dsr_count;
329 cyg_uint32 rx_errors;
335 // flexcan info initialisation
337 #define FLEXCAN_INFO(_l, \
356 _boff_isr_vec, _boff_isr_prio, \
357 _err_isr_vec, _err_isr_prio, \
358 _wake_isr_vec, _wake_isr_prio, \
360 _std_mboxes, _ext_mboxes) \
361 flexcan_info _l = { \
362 (void *)( _baseaddr), \
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), \
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, \
390 mboxes_std_cnt : _std_mboxes, \
391 mboxes_ext_cnt : _ext_mboxes, \
392 mboxes_rx_all_cnt : ((_std_mboxes) + (_ext_mboxes)) \
396 //===========================================================================
398 //===========================================================================
400 // Note: two levels of macro are required to get proper expansion.
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)
406 // Define number of message boxes if they are not defined yet
408 #ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES
409 #define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_STD_MBOXES 0
411 #ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES
412 #define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_EXT_MBOXES 0
414 #ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES
415 #define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_STD_MBOXES 0
417 #ifndef CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES
418 #define CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN1_EXT_MBOXES 0
422 #ifdef CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN0
424 // FlexCAN channel initialisation for FlexCAN channel 0
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]
456 #ifdef CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN1
458 // FlexCAN channel initialisation for FlexCAN channel 1
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
491 // message box structure for hardware access of message box
493 typedef struct flexcan_mbox
504 // flexcan register layout for hardware register access of FlexCAN modul
506 typedef struct flexcan_regs
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
533 //===========================================================================
535 //===========================================================================
536 static cyg_uint16 flexcan_baud_rates[] = {
550 //===========================================================================
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);
563 // TX and RX ISRs and DSRs
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 );
579 // All other flexcan interrupt handlers
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);
589 // Flexcan utility functions
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);
612 CAN_LOWLEVEL_FUNS(flexcan_lowlevel_funs,
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
626 CAN_CHANNEL_USING_INTERRUPTS(flexcan_can0_chan,
627 flexcan_lowlevel_funs,
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
635 DEVTAB_ENTRY(flexcan_devtab,
636 CYGDAT_DEVS_CAN_MCF52xx_FLEXCAN0_NAME,
637 0, // Does not depend on a lower level interface
640 flexcan_lookup, // CAN driver may need initializing
645 //===========================================================================
646 // Lookup the device and return its handle
647 //===========================================================================
649 flexcan_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name)
651 can_channel* chan = (can_channel*) (*tab)->priv;
652 (chan->callbacks->can_init)(chan);
658 //===========================================================================
659 // Enable hardware message box for reception
660 //===========================================================================
661 static __inline__ void flexcan_hwmbox_enable_rx(flexcan_regs *flexcan, cyg_uint32 mbox_id)
663 HAL_WRITE_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), MBOX_RXCODE_EMPTY);
667 //===========================================================================
668 // Disable hardware message box
669 //===========================================================================
670 static __inline__ void flexcan_hwmbox_disable(flexcan_regs *flexcan, cyg_uint32 mbox_id)
672 HAL_WRITE_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), MBOX_RXCODE_NOT_ACTIVE);
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)
681 HAL_READ_UINT8(&(flexcan->mbox[mbox_id].ctrlstat), *pctrlstat); // this read will lock the mbox
685 //===========================================================================
686 // Enable message box interrupt for one message box
687 //===========================================================================
688 static void flexcan_mboxint_enable(flexcan_info *info, cyg_uint32 mbox_id)
690 flexcan_regs *flexcan = (flexcan_regs *)info->base;
692 info->imask_shadow |= (0x0001 << mbox_id);
693 HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
697 //===========================================================================
698 // Disable message box interrupt for one message box
699 //===========================================================================
700 static void flexcan_mboxint_disable(flexcan_info *info, cyg_uint32 mbox_id)
702 flexcan_regs *flexcan = (flexcan_regs *)info->base;
704 info->imask_shadow &= ~(0x0001 << mbox_id);
705 HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
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)
716 cyg_int8 res = CYGNUM_CAN_MSGBUF_NA;
718 if (info->free_mboxes)
720 for (i = (FLEXCAN_MBOX_RX_CNT - info->free_mboxes); i <= FLEXCAN_MBOX_RX_MAX; ++i)
722 if (MBOX_STATE_DISABLED == info->mboxes[i].state)
729 } // if (info->free_mboxes)
735 //===========================================================================
736 // Enable a previously configured rx mbox - a mbox ready to recive
737 //===========================================================================
738 static void flexcan_enable_rxmbox(can_channel *chan,
741 flexcan_info *info = (flexcan_info *)chan->dev_priv;
742 flexcan_regs *flexcan = (flexcan_regs *)info->base;
744 flexcan_hwmbox_enable_rx(flexcan, mbox_id);
745 flexcan_mboxint_enable(info, mbox_id);
748 //===========================================================================
749 // Prepare message buffer filter
750 // Setup a RX message box for reception of a certain CAN identifier but do
752 //===========================================================================
753 static void flexcan_setup_rxmbox(can_channel *chan,
756 cyg_can_message *pmsg,
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;
766 // Set state of message buffer accoring to ISR function that
767 // will be registered
769 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
770 if (*isr == flexcan_mbox_rx_std_isr)
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
777 if (info->mboxes_std_cnt > 1)
779 info->mboxes[mbox_id].state = MBOX_STATE_RX_ALL_STD;
780 dsr_func = &flexcan_mbox_rx_std_dsr;
784 info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT;
785 isr = flexcan_mbox_rx_filt_isr;
789 #endif // CYGOPT_IO_CAN_STD_CAN_ID
790 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
791 if (*isr == flexcan_mbox_rx_ext_isr)
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
798 if (info->mboxes_ext_cnt > 1)
800 info->mboxes[mbox_id].state = MBOX_STATE_RX_ALL_EXT;
801 dsr_func = &flexcan_mbox_rx_ext_dsr;
805 info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT;
806 isr = flexcan_mbox_rx_filt_isr;
810 #endif // CYGOPT_IO_CAN_EXT_CAN_ID
811 if (*isr == flexcan_mbox_rx_filt_isr)
813 info->mboxes[mbox_id].state = MBOX_STATE_RX_FILT;
817 CYG_ASSERT(0, "Invalid ISR function pointer");
820 pmbox = &info->mboxes[mbox_id];
821 flexcan_cfg_mbox_rx(&flexcan->mbox[mbox_id], pmsg, enable);
823 cyg_drv_interrupt_create(pmbox->isr_vec,
825 (cyg_addrword_t) chan,
828 &(pmbox->interrupt_handle),
829 &(pmbox->interrupt));
830 cyg_drv_interrupt_attach(pmbox->interrupt_handle);
831 cyg_drv_interrupt_unmask(pmbox->isr_vec);
834 // now enable interrupt for this message box - but only if we
835 // really should do it
839 flexcan_mboxint_enable(info, mbox_id);
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)
850 flexcan_info *info = (flexcan_info *)chan->dev_priv;
851 flexcan_regs *flexcan = (flexcan_regs *)info->base;
852 flexcan_mbox_info *pmbox;
855 // if message box is already disabled we do not need to disable it
858 if (MBOX_STATE_DISABLED == info->mboxes[mbox_id].state)
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];
868 // now disable interrupts for this message box and free all
869 // interrupt resources
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);
880 //===========================================================================
881 // Setup a transmit message box
882 //===========================================================================
883 static void flexcan_setup_txmbox(can_channel *chan,
885 cyg_can_message *pmsg)
887 flexcan_info *info = (flexcan_info *)chan->dev_priv;
888 flexcan_regs *flexcan = (flexcan_regs *)info->base;
889 flexcan_mbox_info *pmbox;
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);
896 // prepare message box interrupt for message box
898 cyg_drv_interrupt_create(pmbox->isr_vec,
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);
909 // now enable interrupt for this message box
911 flexcan_mboxint_enable(info, mbox_id);
915 //===========================================================================
916 // Setup a RTR response message box
917 //===========================================================================
918 static void flexcan_setup_rtrmbox(can_channel *chan,
920 cyg_can_message *pmsg)
922 flexcan_info *info = (flexcan_info *)chan->dev_priv;
923 flexcan_regs *flexcan = (flexcan_regs *)info->base;
925 info->mboxes[mbox_id].state = MBOX_STATE_REMOTE_TX;
926 flexcan_cfg_mbox_tx(&flexcan->mbox[mbox_id], pmsg, true);
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)
941 //===========================================================================
942 // Setup flexCAN modul for reception of any kind of message
943 //===========================================================================
944 static void flexcan_config_rx_all(can_channel *chan)
946 flexcan_info *info = (flexcan_info *)chan->dev_priv;
947 flexcan_regs *flexcan = (flexcan_regs *)info->base;
951 // setup all available message boxes for reception of of messages
952 // All standard and extended message buffers will be configured
954 for (i = 0; i < info->mboxes_rx_all_cnt; ++i)
956 cyg_can_message filter_param;
960 // configure message buffers for standard frames
962 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
963 if (i < info->mboxes_std_cnt)
965 filter_param.ext = CYGNUM_CAN_ID_STD;
966 flexcan_setup_rxmbox(chan, i, &flexcan_mbox_rx_std_isr, &filter_param, false, true);
968 #endif // CYGOPT_IO_CAN_STD_CAN_ID
971 // configure message buffers for extended frames
973 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
976 filter_param.ext = CYGNUM_CAN_ID_EXT;
977 flexcan_setup_rxmbox(chan, i, &flexcan_mbox_rx_ext_isr, &filter_param, false, true);
979 #endif // CYGOPT_IO_CAN_EXT_CAN_ID
983 // We need to receive all available CAN messages so we have to set the acceptance filter
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;
992 // now finally setup the first active message boxes and enable ist
994 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
995 if (info->mboxes_std_cnt)
997 flexcan_setup_rxmbox_circbuf(&info->rxmbox_std_circbuf);
998 flexcan_enable_rxmbox(chan, 0);
1000 #endif // CYGOPT_IO_CAN_STD_CAN_ID
1002 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
1003 if (info->mboxes_ext_cnt)
1005 flexcan_setup_rxmbox_circbuf(&info->rxmbox_ext_circbuf);
1006 flexcan_enable_rxmbox(chan, info->mboxes_std_cnt);
1008 #endif // CYGOPT_IO_CAN_EXT_CAN_ID
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)
1018 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1019 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1023 // setup all RX messages moxes into a disabled state
1025 for (i = 0; i < FLEXCAN_MBOX_RX_CNT; ++i)
1027 flexcan_disable_mbox(chan, i);
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
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;
1041 //===========================================================================
1042 // Configure message buffers
1043 //===========================================================================
1044 static Cyg_ErrNo flexcan_set_config_msgbuf(can_channel *chan, cyg_can_msgbuf_cfg *buf)
1046 Cyg_ErrNo res = ENOERR;
1047 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1049 switch (buf->cfg_id)
1052 // clear all message filters and remote buffers - prepare for message buffer
1055 case CYGNUM_CAN_MSGBUF_RESET_ALL :
1057 flexcan_config_rx_none(chan);
1062 // setup FlexCAN modul for reception of all standard and extended messages
1064 case CYGNUM_CAN_MSGBUF_RX_FILTER_ALL :
1066 if (!info->rx_all) // if rx_all is enabled we do not need to do anything
1068 flexcan_config_rx_none(chan); // set into default state
1069 flexcan_config_rx_all(chan); // setup RX all state
1075 // add single message filter, message with filter ID will be received
1077 case CYGNUM_CAN_MSGBUF_RX_FILTER_ADD :
1079 cyg_can_filter *filter = (cyg_can_filter*) buf;
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
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
1096 filter->handle = flexcan_alloc_mbox(info);
1097 if (filter->handle > CYGNUM_CAN_MSGBUF_NA)
1099 flexcan_setup_rxmbox(chan, filter->handle, &flexcan_mbox_rx_filt_isr, &filter->msg, true, true);
1102 break; //CYGNUM_CAN_MSGBUF_RX_FILTER_ADD
1105 // Try to add a new RTR response message buffer for automatic transmisson
1106 // of data frame on reception of a remote frame
1108 case CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD :
1110 cyg_can_remote_buf *rtr_buf = (cyg_can_remote_buf*) buf;
1111 rtr_buf->handle = flexcan_alloc_mbox(info);
1113 if (rtr_buf->handle > CYGNUM_CAN_MSGBUF_NA)
1116 // if we have a free message buffer then we setup this buffer
1117 // for remote frame reception
1119 flexcan_setup_rtrmbox(chan, rtr_buf->handle, &rtr_buf->msg);
1125 // write data into remote response buffer
1127 case CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE :
1129 cyg_can_remote_buf *rtr_buf = (cyg_can_remote_buf*) buf;
1132 // If we have a valid rtr buf handle then we can store data into
1135 if ((rtr_buf->handle >= 0) && (rtr_buf->handle <= FLEXCAN_MBOX_RX_MAX))
1137 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1138 flexcan_cfg_mbox_tx(&flexcan->mbox[rtr_buf->handle], &rtr_buf->msg, true);
1146 } // switch (buf->cfg_id)
1151 //===========================================================================
1152 // Set device configuration
1153 //===========================================================================
1155 flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
1157 Cyg_ErrNo res = ENOERR;
1162 //Setup a new CAN configuration. This will i.e. setup a new baud rate
1164 case CYG_IO_SET_CONFIG_CAN_INFO:
1166 cyg_can_info_t* config = (cyg_can_info_t*) buf;
1167 if (*len < sizeof(cyg_can_info_t))
1171 *len = sizeof(cyg_can_info_t);
1172 if (!flexcan_config(chan, config, false))
1180 // configure message buffers
1182 case CYG_IO_SET_CONFIG_CAN_MSGBUF :
1184 cyg_can_msgbuf_cfg *msg_buf = (cyg_can_msgbuf_cfg *) buf;
1186 if (*len != sizeof(cyg_can_msgbuf_cfg))
1191 flexcan_set_config_msgbuf(chan, msg_buf);
1196 // Change CAN state of FlexCAN modul. This function will set the FlexCAN
1197 // modul into STOPPED, ACTIVE or STANDBY state
1199 case CYG_IO_SET_CONFIG_CAN_MODE :
1201 cyg_can_mode *can_mode = (cyg_can_mode*) buf;
1203 if (*len != sizeof(cyg_can_mode))
1207 *len = sizeof(cyg_can_mode);
1210 // decide what to do acording to mode
1214 case CYGNUM_CAN_MODE_STOP : // stop FlexCANm modul
1215 flexcan_stop_chip(chan);
1218 case CYGNUM_CAN_MODE_START : // start FlexCAN modul
1219 flexcan_leave_standby(chan);
1222 case CYGNUM_CAN_MODE_STANDBY : // set FlexCAN modul into standby state
1223 flexcan_enter_standby(chan, true);
1226 case CYGNUM_CAN_MODE_CONFIG : // stop FlexCAN modul for configuration
1227 flexcan_stop_chip(chan);
1231 break; // case CYG_IO_SET_CONFIG_CAN_MODE :
1238 //===========================================================================
1239 // Query device configuration
1240 //===========================================================================
1242 flexcan_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
1244 Cyg_ErrNo res = ENOERR;
1245 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1250 // query state of CAN controller
1252 case CYG_IO_GET_CONFIG_CAN_STATE :
1254 cyg_can_state *can_state = (cyg_can_state*) buf;
1256 if (*len != sizeof(cyg_can_state))
1260 *len = sizeof(cyg_can_state);
1261 *can_state = info->state;
1266 // Query message box information - returns available and free message
1269 case CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO :
1271 cyg_can_msgbuf_info *mbox_info = (cyg_can_msgbuf_info*) buf;
1273 if (*len != sizeof(cyg_can_msgbuf_info))
1277 *len = sizeof(cyg_can_msgbuf_info);
1279 mbox_info->count = FLEXCAN_MBOX_RX_CNT;
1280 mbox_info->free = info->free_mboxes;
1285 // Query hardware description of FlexCAN device driver
1287 case CYG_IO_GET_CONFIG_CAN_HDI :
1289 cyg_can_hdi *hdi = (cyg_can_hdi *)buf;
1291 // comes from high level driver so we do not need to
1292 // check buffer size here
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;
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)
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
1320 if (pevent->msg.id == info->last_tx_id)
1322 info->last_tx_id = 0xFFFFFFFF; // set last received ID to an invalid value
1327 pevent->flags |= CYGNUM_CAN_EVENT_RX;
1330 // check if an overun occured in this message box
1332 if ((pmbox->ctrlstat_shadow & MBOX_RXCODE_OVERRUN) == MBOX_RXCODE_OVERRUN)
1334 pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX;
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)
1347 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1348 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1351 cyg_uint8 event_id = *((cyg_uint8 *)pdata);
1354 // if event_id is 0 - 15 the we have a message box event
1356 if (event_id < FLEXCAN_ERR_EVENT)
1358 flexcan_mbox_info *pmbox_info;
1359 pmbox_info = &info->mboxes[event_id];
1362 // Deceide what to do according to type of message box that caused this event
1364 switch (pmbox_info->state)
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
1373 case MBOX_STATE_RX_ALL_STD:
1374 case MBOX_STATE_RX_ALL_EXT:
1375 case MBOX_STATE_RX_FILT:
1378 // read data from message box - during processing of this function
1379 // the message box is locked and cannot receive further messages
1381 flexcan_read_from_mbox(chan, event_id, pevent, &(pmbox_info->ctrlstat_shadow));
1382 res = flexcan_is_no_self_tx(pevent, info, pmbox_info);
1386 #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT
1388 // If a TX message box cause the event then we store the last transmitted
1389 // message into the receive message queue
1392 pevent->flags = CYGNUM_CAN_EVENT_TX;
1393 pevent->msg = info->last_tx_msg;
1395 #endif // CYGOPT_IO_CAN_TX_EVENT_SUPPORT
1397 case MBOX_STATE_REMOTE_TX:
1402 } // switch (pmbox->state)
1404 else // (event_id >= FLEXCAN_ERR_EVENT)
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
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]);
1417 case FLEXCAN_ERR_EVENT :
1419 // indicate error passive event and provide content of estat register
1420 // for a more precise error information
1422 if (estat & FLEXCAN_ESTAT_FCS_ERROR_PASSIVE)
1424 pevent->flags = CYGNUM_CAN_EVENT_ERR_PASSIVE;
1427 // If we are not in error passive state then we check if the
1428 // error counters reached the warning level
1433 // indicate tx error counter warning level reached
1435 if (estat & FLEXCAN_ESTAT_TXWARN)
1437 pevent->flags |= CYGNUM_CAN_EVENT_WARNING_TX;
1441 // indicate rx error counter warning level reached
1443 if (estat & FLEXCAN_ESTAT_RXWARN)
1445 pevent->flags |= CYGNUM_CAN_EVENT_WARNING_RX;
1450 case FLEXCAN_BUSOFF_EVENT:
1451 pevent->flags = CYGNUM_CAN_EVENT_BUS_OFF;
1454 case FLEXCAN_WAKE_EVENT:
1455 pevent->flags = CYGNUM_CAN_EVENT_LEAVING_STANDBY;
1457 } // switch (event_id)
1464 //===========================================================================
1465 // Send one CAN message to CAN hardware
1466 //===========================================================================
1467 static bool flexcan_putmsg(can_channel *chan, cyg_can_message *pmsg, void *pdata)
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];
1475 HAL_READ_UINT16(&flexcan->IFLAG, iflag);
1478 // check if device is busy sending a message
1483 // if device is busy and the interrupt flag is set, then we know
1484 // that device is not busy any longer
1486 if (iflag & (0x0001 << mbox))
1488 HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));
1496 pmbox->busy = true; // mark transmitter as busy
1497 info->last_tx_id = pmsg->id; // store message in order to identify self recieved frames
1499 #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT
1500 info->last_tx_msg = *pmsg; // store the transmitted message for TX events
1503 flexcan_cfg_mbox_tx(&flexcan->mbox[mbox], pmsg, false); // send message
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)
1516 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1517 CYG_INTERRUPT_STATE saved_state;
1519 HAL_DISABLE_INTERRUPTS(saved_state);
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
1526 if (CYGNUM_CAN_STATE_STANDBY == info->state)
1528 flexcan_leave_standby(chan);
1532 // Now enable message box 15 interrupts
1534 flexcan_mboxint_enable(info, info->tx_all_mbox);
1539 chan->callbacks->xmt_msg(chan, &info->tx_all_mbox); // Kick transmitter (if necessary)
1541 HAL_RESTORE_INTERRUPTS(saved_state);
1545 //===========================================================================
1546 // Flexcan stop transmission
1547 //===========================================================================
1548 static void flexcan_stop_xmit(can_channel* chan)
1550 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1551 CYG_INTERRUPT_STATE saved_state;
1553 HAL_DISABLE_INTERRUPTS(saved_state);
1556 // Now disable message box 15 interrupts
1558 flexcan_mboxint_disable(info, info->tx_all_mbox);
1560 HAL_RESTORE_INTERRUPTS(saved_state);
1564 //===========================================================================
1565 // Configure flexcan channel
1566 //===========================================================================
1567 static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool init)
1569 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1570 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1576 // the first thing we need to do is to stop the chip
1578 flexcan_stop_chip(chan);
1581 // if this is the first initialisation of the FlexCAN modul we need to execute
1582 // some extra steps here
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();
1593 // Issue a reset in order to go into halt mode. The reset will set the
1594 // the halt bit in mcr
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);
1604 // Check reset status
1606 HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
1607 if (tmp16 & FLEXCAN_MCR_SOFTRST)
1613 // Initialize the transmit and receive pin modes
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);
1621 // deactivate all message buffers - this is mandatory for configuration
1622 // of message buffers
1624 for (i = FLEXCAN_MBOX_MIN; i <= FLEXCAN_MBOX_MAX; ++i)
1626 HAL_WRITE_UINT16(&flexcan->mbox[i], MBOX_RXCODE_NOT_ACTIVE);
1630 // mask all interrupts
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));
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
1642 HAL_READ_UINT8(&flexcan->CANCTRL1, tmp8);
1643 HAL_WRITE_UINT8(&flexcan->CANCTRL1, (tmp8 & ~FLEXCAN_CTRL1_LBUF));
1646 // setup all rx message buffers
1648 flexcan_config_rx_all(chan);
1651 // bus off interrupt and error interrupt
1653 HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
1654 HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 | (FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
1657 flexcan_set_baud(chan, config->baud); // setup baud rate
1660 // store new config values
1662 if (config != &chan->config)
1664 chan->config = *config;
1666 flexcan_start_chip(chan); // now we can start the chip again
1671 //===========================================================================
1672 /// First initialisation and reset of CAN modul.
1673 //===========================================================================
1674 static bool flexcan_init(struct cyg_devtab_entry* devtab_entry)
1676 can_channel *chan = (can_channel*)devtab_entry->priv;
1677 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1678 flexcan_mbox_info *pmbox;
1680 if (!flexcan_config(chan, &chan->config, true))
1686 // prepare message box interrupt for message box 15 - the tx message box
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);
1700 // prepare error interrupt
1702 cyg_drv_interrupt_create(info->err_int.isr_vec,
1703 info->err_int.isr_priority,
1704 (cyg_addrword_t) chan,
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);
1713 // prepare busoff interrupt
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);
1726 // prepare wake interrupt
1728 cyg_drv_interrupt_create(info->wake_int.isr_vec,
1729 info->wake_int.isr_priority,
1730 (cyg_addrword_t) chan,
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);
1742 //===========================================================================
1743 // Flexcan error interrupt handler
1744 //===========================================================================
1745 static cyg_uint32 flexcan_err_isr(cyg_vector_t vec, cyg_addrword_t data)
1747 can_channel *chan = (can_channel *)data;
1748 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1749 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1754 // first we disable error interrupts - DSR will reenable it later
1756 HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
1757 HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 & ~FLEXCAN_CTRL0_ERRMASK);
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
1765 HAL_READ_UINT16(&flexcan->ESTAT, estat);
1766 HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_ERRINT);
1769 // On the mcf5272 there is no need to acknowledge internal
1770 // interrupts, only external ones.
1771 // cyg_drv_interrupt_acknowledge(vec);
1773 return CYG_ISR_CALL_DSR;
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)
1782 can_channel *chan = (can_channel *)data;
1783 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1784 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1786 cyg_uint8 event_id = FLEXCAN_ERR_EVENT;
1789 // signal CAN event to generic IO CAN driver - it will do any further
1792 chan->callbacks->rcv_event(chan, &event_id);
1795 // reenable bus off interrupts
1797 HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
1798 HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 | FLEXCAN_CTRL0_ERRMASK);
1802 //===========================================================================
1803 // Bus off interrupt handler
1804 //===========================================================================
1805 static cyg_uint32 flexcan_busoff_isr(cyg_vector_t vec, cyg_addrword_t data)
1807 can_channel *chan = (can_channel *)data;
1808 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1809 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1814 // first we disable bus off interrupts - DSR will reenable it later
1816 HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
1817 HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 & ~FLEXCAN_CTRL0_BOFFMSK);
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
1825 HAL_READ_UINT16(&flexcan->ESTAT, estat);
1826 HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_BOFFINT);
1829 // On the mcf5272 there is no need to acknowledge internal
1830 // interrupts, only external ones.
1831 // cyg_drv_interrupt_acknowledge(vec);
1833 return CYG_ISR_CALL_DSR;
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)
1842 can_channel *chan = (can_channel *)data;
1843 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1844 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1846 cyg_uint8 event_id = FLEXCAN_BUSOFF_EVENT;
1849 // signal CAN event to generic IO CAN driver - it will do any further
1852 chan->callbacks->rcv_event(chan, &event_id);
1855 // reenable bus off interrupts
1857 HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
1858 HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 | FLEXCAN_CTRL0_BOFFMSK);
1862 //===========================================================================
1863 // Bus off interrupt handler
1864 //===========================================================================
1865 static cyg_uint32 flexcan_wake_isr(cyg_vector_t vec, cyg_addrword_t data)
1867 can_channel *chan = (can_channel *)data;
1868 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1869 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1873 // first we disable wake interrupts - we set the mcr register to
1874 // zero in order to bring it back to normal state
1876 HAL_WRITE_UINT16(&flexcan->CANMCR, 0);
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
1884 HAL_READ_UINT16(&flexcan->ESTAT, estat);
1885 HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_WAKEINT);
1888 // On the mcf5272 there is no need to acknowledge internal
1889 // interrupts, only external ones.
1890 // cyg_drv_interrupt_acknowledge(vec);
1892 return CYG_ISR_CALL_DSR;
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)
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;
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.
1913 chan->callbacks->rcv_event(chan, &event_id);
1916 // for standby we disabled all interrut source so we have to enable
1917 // it here again for normal operation
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));
1925 //===========================================================================
1926 // Flexcan message box isr for rx messages if message filtering is
1928 //===========================================================================
1929 static cyg_uint32 flexcan_mbox_rx_filt_isr(cyg_vector_t vec, cyg_addrword_t data)
1931 can_channel *chan = (can_channel *)data;
1932 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1933 flexcan_regs *flexcan = (flexcan_regs *)info->base;
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
1941 cyg_uint8 mbox = vec - info->isr_vec_mbox0;
1944 // first we disable interrupts of this message box - the DSR will
1945 // reenable it later
1947 flexcan_mboxint_disable(info, mbox);
1948 info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ;
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
1956 HAL_READ_UINT16(&flexcan->IFLAG, iflag);
1957 HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));
1960 // On the mcf5272 there is no need to acknowledge internal
1961 // interrupts, only external ones.
1962 // cyg_drv_interrupt_acknowledge(vec);
1964 return CYG_ISR_CALL_DSR;
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)
1975 can_channel *chan = (can_channel *)data;
1976 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1977 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1979 flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_ext_circbuf);
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
1986 cyg_uint8 mbox = vec - info->isr_vec_mbox0;
1987 if (++prx_mbox_list->count < info->mboxes_ext_cnt)
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
1994 // first we disable interrupts of this message box - the DSR will
1995 // reenable it later
1997 flexcan_mboxint_disable(info, mbox);
2001 prx_mbox_list->count = info->mboxes_ext_cnt;
2002 info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ;
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
2011 HAL_READ_UINT16(&flexcan->IFLAG, iflag);
2012 HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));
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
2021 if (prx_mbox_list->count > 1)
2023 return CYG_ISR_HANDLED;
2027 return CYG_ISR_CALL_DSR;
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)
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);
2044 // we do not process the message box we received as event_id
2045 // we take the message boxes from the ring buffer
2050 mbox_cnt = --prx_mbox_list->count;
2051 cyg_drv_isr_unlock();
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);
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
2062 if (mbox_cnt == (info->mboxes_ext_cnt - 1))
2064 cyg_uint8 active_mbox;
2065 cyg_uint8 next_mbox;
2066 flexcan_regs *flexcan = (flexcan_regs *)info->base;
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();
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);
2083 #endif // #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
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)
2093 can_channel *chan = (can_channel *)data;
2094 flexcan_info *info = (flexcan_info *)chan->dev_priv;
2095 flexcan_regs *flexcan = (flexcan_regs *)info->base;
2097 flexcan_rxmbox_circbuf *prx_mbox_list = &(info->rxmbox_std_circbuf);
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
2104 cyg_uint8 mbox = vec - info->isr_vec_mbox0;
2105 if (++prx_mbox_list->count < info->mboxes_std_cnt)
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
2112 // first we disable interrupts of this message box - the DSR will
2113 // reenable it later
2115 flexcan_mboxint_disable(info, mbox);
2119 prx_mbox_list->count = info->mboxes_std_cnt;
2120 info->mboxes[mbox].ctrlstat_shadow = FLEXCAN_CTRLSTAT_NOT_READ;
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
2129 HAL_READ_UINT16(&flexcan->IFLAG, iflag);
2130 HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));
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
2139 if (prx_mbox_list->count > 1)
2141 return CYG_ISR_HANDLED;
2145 return CYG_ISR_CALL_DSR;
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)
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);
2162 // we do not process the message box we received as event_id
2163 // we take the message boxes from the ring buffer
2168 mbox_cnt = --prx_mbox_list->count;
2169 cyg_drv_isr_unlock();
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);
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
2180 if (mbox_cnt == (info->mboxes_std_cnt - 1))
2182 cyg_uint8 active_mbox;
2183 cyg_uint8 next_mbox;
2184 flexcan_regs *flexcan = (flexcan_regs *)info->base;
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();
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);
2198 #endif // CYGOPT_IO_CAN_STD_CAN_ID
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)
2206 can_channel *chan = (can_channel *)data;
2207 flexcan_info *info = (flexcan_info *)chan->dev_priv;
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
2214 cyg_uint8 mbox = vec - info->isr_vec_mbox0;
2217 // signal CAN event to generic IO CAN driver - it will do any further
2220 chan->callbacks->rcv_event(chan, &mbox);
2223 // reenable interrupts for the message box that caused the DSR to run
2225 flexcan_mboxint_enable(info, mbox);
2228 //===========================================================================
2229 // Flexcan message box isr
2230 //===========================================================================
2231 static cyg_uint32 flexcan_mbox_tx_isr(cyg_vector_t vec, cyg_addrword_t data)
2233 can_channel *chan = (can_channel *)data;
2234 flexcan_info *info = (flexcan_info *)chan->dev_priv;
2235 flexcan_regs *flexcan = (flexcan_regs *)info->base;
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
2242 cyg_uint8 mbox = vec - info->isr_vec_mbox0;
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.
2251 HAL_WRITE_UINT8(&flexcan->mbox[mbox].ctrlstat, MBOX_TXCODE_NOT_READY);
2254 // first we disable interrupts of this message box - the DSR will
2255 // reenable it later
2257 flexcan_mboxint_disable(info, mbox);
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
2265 HAL_READ_UINT16(&flexcan->IFLAG, iflag);
2266 HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));
2269 // On the mcf5272 there is no need to acknowledge internal
2270 // interrupts, only external ones.
2271 // cyg_drv_interrupt_acknowledge(vec);
2273 return CYG_ISR_CALL_DSR;
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)
2282 can_channel *chan = (can_channel *)data;
2283 flexcan_info *info = (flexcan_info *)chan->dev_priv;
2284 flexcan_mbox_info *pmbox;
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
2291 cyg_uint8 mbox = vec - info->isr_vec_mbox0;
2292 pmbox = &info->mboxes[mbox];
2294 #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT
2296 // signal CAN TX event to generic IO CAN driver - it will do any further
2299 chan->callbacks->rcv_event(chan, &mbox);
2302 pmbox->busy = false;
2305 // send next message
2307 chan->callbacks->xmt_msg(chan, &mbox);
2310 // reenable interrupts for the message box that caused the DSR to run
2312 flexcan_mboxint_enable(info, mbox);
2316 //===========================================================================
2317 // Start FlexCAN modul
2318 //===========================================================================
2319 static void flexcan_start_chip(can_channel *chan)
2321 flexcan_info *info = (flexcan_info *)chan->dev_priv;
2322 flexcan_regs *flexcan = (flexcan_regs *)info->base;
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));
2333 //===========================================================================
2334 // Stop FlexCAN modul
2335 //===========================================================================
2336 static void flexcan_stop_chip(can_channel *chan)
2338 flexcan_info *info = (flexcan_info *)chan->dev_priv;
2339 flexcan_regs *flexcan = (flexcan_regs *)info->base;
2342 info->state = CYGNUM_CAN_STATE_STOPPED;
2343 HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
2344 HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 | FLEXCAN_MCR_HALT);
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)
2356 flexcan_info *info = (flexcan_info *)chan->dev_priv;
2357 flexcan_regs *flexcan = (flexcan_regs *)info->base;
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
2368 HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
2369 HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 & ~(FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
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
2376 HAL_WRITE_UINT16(&flexcan->IMASK, 0);
2378 HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
2380 tmp16 |= FLEXCAN_MCR_STOP;
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
2388 tmp16 |= FLEXCAN_MCR_SELFWAKE;
2391 HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16);
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
2398 for (i = 0; i < 10; ++i)
2400 HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
2402 if (tmp16 & FLEXCAN_MCR_STOPACK)
2404 info->state = CYGNUM_CAN_STATE_STANDBY;
2411 // if we are not in low power stop mode then we have to reenable interrupts
2415 HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
2416 HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 | (FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
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
2426 HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
2427 HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 | FLEXCAN_MCR_WAKEMSK);
2433 //===========================================================================
2434 // Leave standby mode
2435 //===========================================================================
2436 static void flexcan_leave_standby(can_channel *chan)
2438 flexcan_info *info = (flexcan_info *)chan->dev_priv;
2439 flexcan_regs *flexcan = (flexcan_regs *)info->base;
2443 HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
2444 HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 & ~(FLEXCAN_MCR_STOP | FLEXCAN_MCR_SELFWAKE));
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
2451 for (i = 0; i < 10; ++i)
2453 HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
2455 if (!(tmp16 & FLEXCAN_MCR_STOPACK))
2457 HAL_WRITE_UINT16(&flexcan->IMASK, info->imask_shadow);
2458 info->state = CYGNUM_CAN_STATE_ACTIVE;
2462 } // for (i = 0; i < 10; ++i)
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)
2473 // 32 bit access to RXMASK filters is broken so we use 16 Bit
2476 if (CYGNUM_CAN_ID_EXT == ext)
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);
2482 id = (mask << 1) & 0xFFFE;
2483 HAL_WRITE_UINT16(&rxmask_reg[1], id);
2485 else // (CYGNUM_CAN_ID_STD == ext)
2487 id = ((mask << 5) & 0xFFE0);
2488 HAL_WRITE_UINT16(&rxmask_reg[0], id);
2489 HAL_WRITE_UINT16(&rxmask_reg[1], 0xFFFF);
2496 //===========================================================================
2497 // Configure message box for transmission
2498 //===========================================================================
2499 static bool flexcan_cfg_mbox_tx(flexcan_mbox *pmbox,
2500 cyg_can_message *pmsg,
2505 HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_NOT_READY);
2507 if (CYGNUM_CAN_ID_EXT == pmsg->ext)
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);
2514 id = ((pmsg->id << 1) & 0xFFFE);
2518 id |= MBOX_CFG_RTR_EXT;
2521 HAL_WRITE_UINT16(&pmbox->id_lo, id);
2525 id = ((pmsg->id << 5) & 0xFFE0);
2528 id |= MBOX_CFG_RTR_STD; // set rtr bit for standard ID
2530 HAL_WRITE_UINT16(&pmbox->id_hi, id);
2531 HAL_WRITE_UINT16(&pmbox->id_lo, 0);
2534 pmsg->dlc %= 9; // limit data length to 8 bytes
2537 // Now copy data bytes into buffer and start transmission
2539 HAL_WRITE_UINT8_VECTOR(&pmbox->data, pmsg->data.bytes, pmsg->dlc, 1);
2544 HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_RESPONSE | pmsg->dlc);
2548 HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_TRANSMIT | pmsg->dlc);
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,
2565 HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_NOT_ACTIVE);
2567 if (CYGNUM_CAN_ID_EXT == pmsg->ext)
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
2574 id = ((pmsg->id << 1) & 0xFFFE);
2576 HAL_WRITE_UINT16(&pmbox->id_lo, id);// write ID low
2580 id = ((pmsg->id << 5) & 0xFFE0);
2582 HAL_WRITE_UINT16(&pmbox->id_hi, id);
2583 HAL_WRITE_UINT16(&pmbox->id_lo, 0);
2588 HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY);
2593 //===========================================================================
2594 // Read date from a message box
2595 //==========================================================================
2596 static void flexcan_read_from_mbox(can_channel *chan,
2598 cyg_can_event *pevent,
2599 cyg_uint8 *ctrlstat)
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;
2606 bool enable_mbox = false;
2609 // If controlstat was not read, then read it now
2611 if (FLEXCAN_CTRLSTAT_NOT_READ == *ctrlstat)
2613 HAL_READ_UINT8(&pmbox->ctrlstat, *ctrlstat); // this read will lock the mbox
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
2622 if (*ctrlstat & MBOX_RXCODE_BUSY)
2627 pmsg->dlc = (*ctrlstat & MBOX_CFG_DLC_MASK); // store received data len
2629 HAL_READ_UINT16(&pmbox->id_hi, id); // read ID high
2631 if (id & MBOX_CFG_IDE)
2633 pmsg->ext = CYGNUM_CAN_ID_EXT;
2634 pmsg->id = (id & 0xFFE0) << 13;
2635 pmsg->id |= (id & 0x07) << 15;
2637 HAL_READ_UINT16(&pmbox->id_lo, id);
2638 pmsg->id |= (id & 0xFFFE) >> 1;
2640 if (id & MBOX_CFG_RTR_EXT)
2642 pmsg->rtr = CYGNUM_CAN_FRAME_RTR;
2646 pmsg->rtr = CYGNUM_CAN_FRAME_DATA;
2651 pmsg->ext = CYGNUM_CAN_ID_STD;
2652 pmsg->id = (id & 0xFFE0) >> 5;
2654 if (id & MBOX_CFG_RTR_STD)
2656 pmsg->rtr = CYGNUM_CAN_FRAME_RTR;
2660 pmsg->rtr = CYGNUM_CAN_FRAME_DATA;
2665 // now finally copy data
2667 HAL_READ_UINT8_VECTOR(&pmbox->data, pmsg->data.bytes, pmsg->dlc, 1);
2670 // now mark this mbox as empty and read the free running timer
2671 // to unlock this mbox
2675 HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY);
2676 HAL_READ_UINT16(&flexcan->TIMER, id);
2678 #ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP
2679 pevent->timestamp = id;
2684 //===========================================================================
2685 // INIT CAN BAUD RATE
2686 //===========================================================================
2687 static bool flexcan_set_baud(can_channel *chan, cyg_uint16 baud)
2689 flexcan_info *info = (flexcan_info *)chan->dev_priv;
2690 flexcan_regs *flexcan = (flexcan_regs *)info->base;
2696 cyg_uint16 baudrate = flexcan_baud_rates[baud];
2699 // Get bit timings from HAL because bit timings depend on sysclock
2701 HAL_MCF52xx_FLEXCAN_GET_BIT_TIMINGS(&baudrate, &presdiv, &propseg, &pseg1_2);
2704 // return false if baudrate is not supported
2712 // For setting the bit timings we have to stop the flexcan modul
2714 HAL_READ_UINT16(&flexcan->CANMCR, mcr_bck);
2715 HAL_WRITE_UINT16(&flexcan->CANMCR, mcr_bck | FLEXCAN_MCR_HALT);
2718 // now we setup bit timings
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);
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
2730 HAL_WRITE_UINT16(&flexcan->CANMCR, mcr_bck);
2735 //---------------------------------------------------------------------------
2736 // end of can_mcf_flexcan.c