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
166 //---------------------------------------------------------------------------
167 // message buffer cfg bits
169 #define MBOX_RXCODE_NOT_ACTIVE 0x00
170 #define MBOX_RXCODE_BUSY 0x10
171 #define MBOX_RXCODE_EMPTY 0x40
172 #define MBOX_RXCODE_FULL 0x20
173 #define MBOX_RXCODE_OVERRUN 0x60
175 #define MBOX_TXCODE_NOT_READY 0x80
176 #define MBOX_TXCODE_TRANSMIT 0xC0
177 #define MBOX_TXCODE_RESPONSE 0xA0
179 #define MBOX_DATA_FRAME 0x00 // data frame
180 #define MBOX_REMOTE_FRAME 0x01 // remote frame
181 #define MBOX_STD_ID 0x00 // standard identifier
182 #define MBOX_EXT_ID 0x01 // remote identifier
183 #define MBOX_TX 0x08 // tx message box
184 #define MBOX_RX 0x00 // rx messge box
186 #define MBOX_CFG_IDE 0x08
187 #define MBOX_CFG_RTR_EXT 0x01
188 #define MBOX_CFG_RTR_STD 0x10
189 #define MBOX_CFG_SSR 0x10
190 #define MBOX_CFG_DLC_MASK 0x0F
191 #define MBOX_CFG_STAT_MASK 0xF0
194 //===========================================================================
196 //===========================================================================
198 // configuration info for flexcan message buffer
200 typedef struct flexcan_mbox_info_st
202 cyg_vector_t isr_vec;
204 cyg_interrupt interrupt;
205 cyg_handle_t interrupt_handle;
210 // flexcan interrupt (busoff, err, wake) data
212 typedef struct flexcan_int_st
214 cyg_vector_t isr_vec;
216 cyg_interrupt interrupt;
217 cyg_handle_t interrupt_handle;
221 // flexcan message box initialisation
223 #define FLEXCAN_MBOX_INIT(_mbox0_vec, _prio, _mbox_no) { \
224 isr_vec : (_mbox0_vec) + (_mbox_no), \
225 isr_priority : (_prio), \
230 // Interrupt initialisation
232 #define FLEXCAN_INT_INIT(_vec, _prio) \
235 isr_priority : (_prio) \
239 // flexcan configuration
241 typedef struct flexcan_info
243 cyg_uint8 *base; // base address of flexcan modul
244 cyg_vector_t isr_vec_mbox0; // vector number of ISR vector of first message box
245 flexcan_mbox_info rx_mbox; // rx message box interrupt
246 flexcan_mbox_info tx_mbox; // tx message box interrupt
247 cyg_uint32 last_tx_id; // last transmitted message
248 bool tx_busy; // indicates if transmit process ic currently running
250 cyg_uint32 rxgmask; // acceptance filter for message box 0 - 13
251 cyg_uint32 rx14mask; // acceptance filter for message box 14
252 cyg_uint32 rx15mask; // acceptance filter for message box 15
254 flexcan_int boff_int; // bus off interrupt data
255 flexcan_int err_int; // error interrupt data
257 cyg_uint32 timeout_rd;
258 cyg_uint32 timeout_wr;
259 cyg_uint16 mbox_alloc_flags;// these bits are used to indicate which message buffers are already alloceted and which ones are free
260 #ifdef FLEXCAN_CAN_STATS
261 cyg_uint32 isr_count;
262 cyg_uint32 dsr_count;
265 cyg_uint32 rx_errors;
271 // flexcan info initialisation
273 #define FLEXCAN_INFO(_l, \
276 _rx_mbox_no, _rx_isr_prio, \
277 _tx_mbox_no, _tx_isr_prio, \
278 _boff_isr_vec, _boff_isr_prio, \
279 _err_isr_vec, _err_isr_prio) \
280 flexcan_info _l = { \
281 (void *)( _baseaddr), \
283 FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_rx_isr_prio), (_rx_mbox_no)), \
284 FLEXCAN_MBOX_INIT((_isr_vec_mbox0), (_tx_isr_prio), (_tx_mbox_no)), \
287 rxgmask : CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_GLOBAL, \
288 rx14mask : CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_14, \
289 rx15mask : CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_RXMASK_15, \
290 boff_int : FLEXCAN_INT_INIT(_boff_isr_vec, _boff_isr_prio), \
291 err_int : FLEXCAN_INT_INIT(_err_isr_vec, _err_isr_prio) \
295 //===========================================================================
297 //===========================================================================
299 // Note: two levels of macro are required to get proper expansion.
301 #define _FLEXCAN_MBOX_INTPRIO(n) CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_MBOX##n
302 #define FLEXCAN_MBOX_INTPRIO(n) _FLEXCAN_MBOX_INTPRIO(n)
305 // FlexCAN channel initialisation
307 FLEXCAN_INFO(flexcan_can0_info,
308 HAL_MCF52xx_MBAR + HAL_MCF52xx_FLEXCAN0_BASE,
309 HAL_MCF52xx_FLEXCAN0_MBOX0_ISRVEC,
310 CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_RX_MBOX,
311 FLEXCAN_MBOX_INTPRIO(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_RX_MBOX),
312 CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX,
313 FLEXCAN_MBOX_INTPRIO(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_DEFAULT_TX_MBOX),
314 HAL_MCF52xx_FLEXCAN0_BOFF_ISRVEC,
315 CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_BOFFINT,
316 HAL_MCF52xx_FLEXCAN0_ERR_ISRVEC,
317 CYGNUM_DEVS_CAN_MCF52xx_ISR_PRIORITY_FLEXCAN0_ERRINT);
320 // message box structure
322 typedef struct flexcan_mbox
333 // flexcan register layout
335 typedef struct flexcan_regs
337 cyg_uint16 CANMCR; // 0x00
338 cyg_uint16 reserved0[2]; // 0x02
339 cyg_uint8 CANCTRL0; // 0x06
340 cyg_uint8 CANCTRL1; // 0x07
341 cyg_uint8 PRESDIV; // 0x08
342 cyg_uint8 CANCTRL2; // 0x09
343 cyg_uint16 TIMER; // 0x0A
344 cyg_uint16 reserved1[2]; // 0x0C
345 cyg_uint16 RXGMASK_HI; // 0x10
346 cyg_uint16 RXGMASK_LO; // 0x12
347 cyg_uint16 RX14MASK_HI; // 0x14
348 cyg_uint16 RX14MASK_LO; // 0x16
349 cyg_uint16 RX15MASK_HI; // 0x18
350 cyg_uint16 RX15MASK_LO; // 0x1A
351 cyg_uint16 reserved2[2]; // 0x1C
352 cyg_uint16 ESTAT; // 0x20
353 cyg_uint16 IMASK; // 0x22
354 cyg_uint16 IFLAG; // 0x24
355 cyg_uint8 RXERRCNT; // 0x26
356 cyg_uint8 TXERRCNT; // 0x27
357 cyg_uint16 reserved3[44];// 0x28
358 flexcan_mbox mbox[16]; // 0x80
362 //===========================================================================
364 //===========================================================================
365 static cyg_uint16 flexcan_baud_rates[] = {
379 //===========================================================================
381 //===========================================================================
382 static bool flexcan_init(struct cyg_devtab_entry* devtab_entry);
383 static Cyg_ErrNo flexcan_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name);
384 static Cyg_ErrNo flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len);
385 static bool flexcan_putmsg(can_channel *priv, cyg_can_message *pmsg, void *pdata);
386 static bool flexcan_getevent(can_channel *priv, cyg_can_event *pevent, void *pdata);
387 static void flexcan_start_xmit(can_channel* chan);
388 static void flexcan_stop_xmit(can_channel* chan);
391 // TX and RX ISRs and DSRs
393 static cyg_uint32 flexcan_mbox_rx_isr(cyg_vector_t, cyg_addrword_t);
394 static void flexcan_mbox_rx_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
395 static cyg_uint32 flexcan_mbox_tx_isr(cyg_vector_t, cyg_addrword_t);
396 static void flexcan_mbox_tx_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
399 // All other flexcan interrupt handlers
401 static cyg_uint32 flexcan_err_isr(cyg_vector_t, cyg_addrword_t);
402 static void flexcan_err_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
403 static cyg_uint32 flexcan_busoff_isr(cyg_vector_t, cyg_addrword_t);
404 static void flexcan_busoff_dsr(cyg_vector_t, cyg_ucount32, cyg_addrword_t);
407 static bool flexcan_cfg_mbox_tx(flexcan_mbox *pmbox, cyg_can_message *pmsg, bool rtr);
408 static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox, cyg_uint32 canid, cyg_uint8 ext);
409 static void flexcan_read_from_mbox(can_channel *chan, cyg_uint8 mbox, cyg_can_event *pevent, cyg_uint8 *ctrlstat);
410 static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_uint8 ext);
411 static void flexcan_start_chip(can_channel *chan);
412 static bool flexcan_set_baud(can_channel *chan, cyg_uint16 baudrate);
413 static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool init);
416 CAN_LOWLEVEL_FUNS(flexcan_lowlevel_funs,
425 cyg_can_event flexcan_can0_rxbuf[CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX]; // buffer for 32 rx can events
426 cyg_can_message flexcan_can0_txbuf[CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX]; // buffer for 32 tx can messageds
429 CAN_CHANNEL_USING_INTERRUPTS(flexcan_can0_chan,
430 flexcan_lowlevel_funs,
432 CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_KBAUD),
433 flexcan_can0_txbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_TX,
434 flexcan_can0_rxbuf, CYGNUM_DEVS_CAN_MCF52xx_FLEXCAN0_QUEUESIZE_RX
438 DEVTAB_ENTRY(flexcan_devtab,
439 CYGDAT_DEVS_CAN_MCF52xx_FLEXCAN0_NAME,
440 0, // Does not depend on a lower level interface
443 flexcan_lookup, // CAN driver may need initializing
448 //===========================================================================
449 // Lookup the device and return its handle
450 //===========================================================================
452 flexcan_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name)
454 can_channel* chan = (can_channel*) (*tab)->priv;
455 (chan->callbacks->can_init)(chan);
461 //===========================================================================
462 // Set device configuration
463 //===========================================================================
465 flexcan_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
467 Cyg_ErrNo res = ENOERR;
471 case CYG_IO_SET_CONFIG_CAN_INFO:
473 cyg_can_info_t* config = (cyg_can_info_t*) buf;
474 if (*len < sizeof(cyg_can_info_t))
478 *len = sizeof(cyg_can_info_t);
479 if (!flexcan_config(chan, config, false))
486 case CYG_IO_SET_CONFIG_CAN_RTR_BUF:
489 cyg_uint16 alloc_mask = 0x0001;
490 flexcan_info *info = (flexcan_info *)chan->dev_priv;
491 flexcan_regs *flexcan = (flexcan_regs *)info->base;
492 cyg_can_rtr_buf_t *rtr_buf = (cyg_can_rtr_buf_t*) buf;
495 if (*len != sizeof(cyg_can_rtr_buf_t))
499 *len = sizeof(cyg_can_rtr_buf_t);
502 // If we need to create a new remote buffer then we check if there
503 // is one message box free and then setup this box for remote frame
506 if (CYGNUM_CAN_RTR_BUF_INIT == rtr_buf->handle)
508 rtr_buf->handle = CYGNUM_CAN_RTR_BUF_NA;
509 for (i = 0; i < 14; ++i)
511 if (!(info->mbox_alloc_flags & alloc_mask))
514 info->mbox_alloc_flags |= alloc_mask;
519 } // if (CYGNUM_CAN_RTR_BUF_INIT == rtr_buf->handle)
522 // If we have a valid rtr buf handle then we can store data into
525 if ((rtr_buf->handle >= 0) && (rtr_buf->handle < 14))
527 flexcan_cfg_mbox_tx(&flexcan->mbox[rtr_buf->handle], &rtr_buf->msg, true);
543 //===========================================================================
544 // Read one event from can hardware
545 //===========================================================================
546 static bool flexcan_getevent(can_channel *chan, cyg_can_event *pevent, void *pdata)
548 flexcan_info *info = (flexcan_info *)chan->dev_priv;
549 flexcan_regs *flexcan = (flexcan_regs *)info->base;
550 cyg_uint8 mbox_ctrlstat;
552 cyg_uint8 event_id = *((cyg_uint8 *)pdata);
556 // if event_id is 0 - 15 the we have a message box event - if is
558 if (event_id < FLEXCAN_ERR_EVENT)
561 // read data from message box - during processing of this function
562 // the message box is locked and cannot receive further messages
564 flexcan_read_from_mbox(chan, event_id, pevent, &mbox_ctrlstat);
566 #ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT
567 if (pevent->msg.id == info->last_tx_id)
569 pevent->flags = CYGNUM_CAN_EVENT_TX;
573 pevent->flags = CYGNUM_CAN_EVENT_RX;
575 #else // !CYGOPT_IO_CAN_TX_EVENT_SUPPORT
577 // If tx events are not supported and we received a self transmitted frame
578 // then this is not really an rx event and we return false. We rely on the
579 // fact here that two devices in network do not send the same identifier
581 if (pevent->msg.id == info->last_tx_id) {
582 info->last_tx_id = 0xFFFFFFFF; // set last received ID to an invalid value
586 pevent->flags = CYGNUM_CAN_EVENT_RX;
590 // check if an overun occured in this message box
592 if ((mbox_ctrlstat & MBOX_RXCODE_OVERRUN) == MBOX_RXCODE_OVERRUN)
594 pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX;
597 else // (event_id >= FLEXCAN_ERR_EVENT)
600 // We have an status event - check if it is an bus off interrupt or an
601 // error interrupt and provide error information to upper layer
603 HAL_READ_UINT16(&flexcan->ESTAT, estat);
604 pevent->msg.data[0] = estat & 0xFF;
605 pevent->msg.data[1] = (estat >> 8) & 0xFF;
606 HAL_READ_UINT8(&flexcan->RXERRCNT, pevent->msg.data[2]);
607 HAL_READ_UINT8(&flexcan->TXERRCNT, pevent->msg.data[3]);
610 case FLEXCAN_ERR_EVENT :
612 // indicate error passive event and provide content of estat register
613 // for a more precise error information
615 if (estat & FLEXCAN_ESTAT_FCS_ERROR_PASSIVE)
617 pevent->flags = CYGNUM_CAN_EVENT_ERR_PASSIVE;
620 // If we are not in error passive state then we check if the
621 // error counters reached the warning level
626 // indicate tx error counter warning level reached
628 if (estat & FLEXCAN_ESTAT_TXWARN)
630 pevent->flags |= CYGNUM_CAN_EVENT_WARNING_TX;
634 // indicate rx error counter warning level reached
636 if (estat & FLEXCAN_ESTAT_RXWARN)
638 pevent->flags |= CYGNUM_CAN_EVENT_WARNING_RX;
643 case FLEXCAN_BUSOFF_EVENT:
644 pevent->flags = CYGNUM_CAN_EVENT_BUS_OFF;
646 } // switch (event_id)
653 //===========================================================================
654 // Send one CAN message to CAN hardware
655 //===========================================================================
656 static bool flexcan_putmsg(can_channel *chan, cyg_can_message *pmsg, void *pdata)
658 flexcan_info *info = (flexcan_info *)chan->dev_priv;
659 flexcan_regs *flexcan = (flexcan_regs *)info->base;
660 cyg_uint8 mbox = *((cyg_uint8 *)pdata);
663 HAL_READ_UINT16(&flexcan->IFLAG, iflag);
666 // check if device is busy sending a message
671 // if devise is busy and the interrupt flag is set, then we know
672 // that device is not busy any longer - if more message boxes are
673 // used for transmitting then tx_busy should be part of a message box
674 // structure to keep track of the state of different message boxes
676 if (iflag & (0x0001 << mbox))
678 HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));
686 info->tx_busy = true; // mark transmitter as busy
687 info->last_tx_id = pmsg->id; // store message in order to identify self recieved frames
688 flexcan_cfg_mbox_tx(&flexcan->mbox[mbox], pmsg, false);
694 //===========================================================================
695 // Flexcan start xmit
696 //===========================================================================
697 static void flexcan_start_xmit(can_channel* chan)
699 flexcan_info *info = (flexcan_info *)chan->dev_priv;
700 flexcan_regs *flexcan = (flexcan_regs *)info->base;
702 CYG_INTERRUPT_STATE saved_state;
704 HAL_DISABLE_INTERRUPTS(saved_state);
707 // Now enable message box 15 interrupts
709 HAL_READ_UINT16(&flexcan->IMASK, imask);
710 HAL_WRITE_UINT16(&flexcan->IMASK, imask | (0x0001 << info->tx_mbox.num));
715 chan->callbacks->xmt_msg(chan, &info->tx_mbox.num); // Kick transmitter (if necessary)
717 HAL_RESTORE_INTERRUPTS(saved_state);
721 //===========================================================================
722 // Flexcan start xmit
723 //===========================================================================
724 static void flexcan_stop_xmit(can_channel* chan)
726 flexcan_info *info = (flexcan_info *)chan->dev_priv;
727 flexcan_regs *flexcan = (flexcan_regs *)info->base;
729 CYG_INTERRUPT_STATE saved_state;
731 HAL_DISABLE_INTERRUPTS(saved_state);
734 // Now disable message box 15 interrupts
736 HAL_READ_UINT16(&flexcan->IMASK, imask);
737 HAL_WRITE_UINT16(&flexcan->IMASK, imask & ~(0x0001 << info->tx_mbox.num));
739 HAL_RESTORE_INTERRUPTS(saved_state);
743 //===========================================================================
744 // Configure flexcan channel
745 //===========================================================================
746 static bool flexcan_config(can_channel* chan, cyg_can_info_t* config, cyg_bool init)
748 flexcan_info *info = (flexcan_info *)chan->dev_priv;
749 flexcan_regs *flexcan = (flexcan_regs *)info->base;
756 #if defined(CYGPKG_DEVS_CAN_MCF52xx_FLEXCAN0) && defined(HAL_MCF52xx_FLEXCAN0_PROC_INIT)
757 if (info == &flexcan_can0_info) {
758 HAL_MCF52xx_FLEXCAN0_PROC_INIT();
763 // Issue a reset in order to go into halt mode. The reset will set the
764 // the halt bit in mcr
766 HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
767 tmp16 &= ~FLEXCAN_MCR_FRZ;
768 HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16);
769 tmp16 |= FLEXCAN_MCR_SOFTRST;
770 HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16);
774 // Check reset status
776 HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
777 if (tmp16 & FLEXCAN_MCR_SOFTRST)
783 // Initialize the transmit and receive pin modes
785 HAL_WRITE_UINT8(&flexcan->CANCTRL0 , (FLEXCAN_CTRL0_TXMODE_FULL_0_DOMINANT
786 | FLEXCAN_CTRL0_RXMODE_0_DOMINANT)
787 & ~FLEXCAN_CTRL0_BOFFMSK
788 & ~FLEXCAN_CTRL0_ERRMASK);
791 // setup message box acceptance filter
793 flexcan_set_acceptance_mask(&flexcan->RXGMASK_HI, info->rxgmask, 0);
794 flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, info->rx14mask, 0);
795 flexcan_set_acceptance_mask(&flexcan->RX15MASK_HI, info->rx15mask, 0);
801 HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
802 HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16 | FLEXCAN_MCR_HALT);
805 // deactivate all message buffers - this is mandatory for configuration
806 // of message buffers
808 for (i = 0; i < 16; ++i)
810 HAL_WRITE_UINT16(&flexcan->mbox[i], MBOX_RXCODE_NOT_ACTIVE);
813 // mask all interrupts
815 HAL_WRITE_UINT16(&flexcan->IMASK, 0x0000);
816 HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
817 HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 & ~(FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
819 flexcan_set_baud(chan, config->baud);
822 // setup bus arbitration mode - the LBUF bit defines the
823 // transmit-first scheme 0 = message buffer with lowest ID
824 // 1 = message buffer with lowest number. We use lowest ID here
826 HAL_READ_UINT8(&flexcan->CANCTRL1, tmp8);
827 HAL_WRITE_UINT8(&flexcan->CANCTRL1, (tmp8 & ~FLEXCAN_CTRL1_LBUF));
829 info->mbox_alloc_flags = 0; // no buffers used yet
832 // Message box 14 is our receiv message box. We configure it for
833 // reception of any message
835 flexcan_cfg_mbox_rx(&flexcan->mbox[info->rx_mbox.num], 0x100, 0);
836 flexcan_set_acceptance_mask(&flexcan->RX14MASK_HI, 0, 0);
837 info->mbox_alloc_flags |= (0x0001 << info->rx_mbox.num); // mark rx mbox flag as used
838 info->mbox_alloc_flags |= (0x0001 << info->tx_mbox.num); // mark tx mbox flag as used
841 // enable the rx interrupt for mbox 0 (tx interrupt are enabled in start xmit)
842 // bus off interrupt and error interrupt
844 HAL_WRITE_UINT16(&flexcan->IMASK, (0x0001 << info->rx_mbox.num));
845 HAL_READ_UINT8(&flexcan->CANCTRL0, tmp8);
846 HAL_WRITE_UINT8(&flexcan->CANCTRL0, tmp8 | (FLEXCAN_CTRL0_BOFFMSK | FLEXCAN_CTRL0_ERRMASK));
849 // now we can start the chip
851 flexcan_start_chip(chan);
854 // store new config values
856 if (config != &chan->config)
858 chan->config = *config;
864 //===========================================================================
867 /// First initialisation and reset of CAN modul.
868 //===========================================================================
869 static bool flexcan_init(struct cyg_devtab_entry* devtab_entry)
871 can_channel *chan = (can_channel*)devtab_entry->priv;
872 flexcan_info *info = (flexcan_info *)chan->dev_priv;
874 if (!flexcan_config(chan, &chan->config, true))
880 // prepare message box interrupt for message box 0 - the rx message box
882 cyg_drv_interrupt_create(info->rx_mbox.isr_vec,
883 info->rx_mbox.isr_priority,
884 (cyg_addrword_t) chan,
885 &flexcan_mbox_rx_isr,
886 &flexcan_mbox_rx_dsr,
887 &(info->rx_mbox.interrupt_handle),
888 &(info->rx_mbox.interrupt));
889 cyg_drv_interrupt_attach(info->rx_mbox.interrupt_handle);
890 cyg_drv_interrupt_unmask(info->rx_mbox.isr_vec);
893 // prepare message box interrupt for message box 15 - the tx message box
895 cyg_drv_interrupt_create(info->tx_mbox.isr_vec,
896 info->tx_mbox.isr_priority,
897 (cyg_addrword_t) chan,
898 &flexcan_mbox_tx_isr,
899 &flexcan_mbox_tx_dsr,
900 &(info->tx_mbox.interrupt_handle),
901 &(info->tx_mbox.interrupt));
902 cyg_drv_interrupt_attach(info->tx_mbox.interrupt_handle);
903 cyg_drv_interrupt_unmask(info->tx_mbox.isr_vec);
906 // prepare error interrupt
908 cyg_drv_interrupt_create(info->err_int.isr_vec,
909 info->err_int.isr_priority,
910 (cyg_addrword_t) chan,
913 &(info->err_int.interrupt_handle),
914 &(info->err_int.interrupt));
915 cyg_drv_interrupt_attach(info->err_int.interrupt_handle);
916 cyg_drv_interrupt_unmask(info->err_int.isr_vec);
919 // prepare busoff interrupt
921 cyg_drv_interrupt_create(info->boff_int.isr_vec,
922 info->boff_int.isr_priority,
923 (cyg_addrword_t) chan,
926 &(info->boff_int.interrupt_handle),
927 &(info->boff_int.interrupt));
928 cyg_drv_interrupt_attach(info->boff_int.interrupt_handle);
929 cyg_drv_interrupt_unmask(info->boff_int.isr_vec);
935 //===========================================================================
936 // Flexcan error interrupt handler
937 //===========================================================================
938 static cyg_uint32 flexcan_err_isr(cyg_vector_t vec, cyg_addrword_t data)
940 can_channel *chan = (can_channel *)data;
941 flexcan_info *info = (flexcan_info *)chan->dev_priv;
942 flexcan_regs *flexcan = (flexcan_regs *)info->base;
947 // first we disable error interrupts - DSR will reenable it later
949 HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
950 HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 & ~FLEXCAN_CTRL0_ERRMASK);
953 // for clearing the interrupt we first read the flag register as 1
954 // and then write it as 1 (and not as zero like the manual stated)
955 // we clear only the flag of this interrupt and leave all other
956 // message box interrupts untouched
958 HAL_READ_UINT16(&flexcan->ESTAT, estat);
959 HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_ERRINT);
962 // On the mcf5272 there is no need to acknowledge internal
963 // interrupts, only external ones.
964 // cyg_drv_interrupt_acknowledge(vec);
966 return CYG_ISR_CALL_DSR;
970 //===========================================================================
971 // DSR for all interrupts that are no message box interrupts
972 //===========================================================================
973 static void flexcan_err_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
975 can_channel *chan = (can_channel *)data;
976 flexcan_info *info = (flexcan_info *)chan->dev_priv;
977 flexcan_regs *flexcan = (flexcan_regs *)info->base;
979 cyg_uint8 event_id = FLEXCAN_ERR_EVENT;
982 // signal CAN event to generic IO CAN driver - it will do any further
985 chan->callbacks->rcv_event(chan, &event_id);
988 // reenable bus off interrupts
990 HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
991 HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 | FLEXCAN_CTRL0_ERRMASK);
995 //===========================================================================
996 // Bus off interrupt handler
997 //===========================================================================
998 static cyg_uint32 flexcan_busoff_isr(cyg_vector_t vec, cyg_addrword_t data)
1000 can_channel *chan = (can_channel *)data;
1001 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1002 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1007 // first we disable bus off interrupts - DSR will reenable it later
1009 HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
1010 HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 & ~FLEXCAN_CTRL0_BOFFMSK);
1013 // for clearing the interrupt we first read the flag register as 1
1014 // and then write it as 1 (and not as zero like the manual stated)
1015 // we clear only the flag of this interrupt and leave all other
1016 // message box interrupts untouched
1018 HAL_READ_UINT16(&flexcan->ESTAT, estat);
1019 HAL_WRITE_UINT16(&flexcan->ESTAT, FLEXCAN_ESTAT_BOFFINT);
1022 // On the mcf5272 there is no need to acknowledge internal
1023 // interrupts, only external ones.
1024 // cyg_drv_interrupt_acknowledge(vec);
1026 return CYG_ISR_CALL_DSR;
1030 //===========================================================================
1031 // DSR for all interrupts that are no message box interrupts
1032 //===========================================================================
1033 static void flexcan_busoff_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
1035 can_channel *chan = (can_channel *)data;
1036 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1037 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1039 cyg_uint8 event_id = FLEXCAN_BUSOFF_EVENT;
1042 // signal CAN event to generic IO CAN driver - it will do any further
1045 chan->callbacks->rcv_event(chan, &event_id);
1048 // reenable bus off interrupts
1050 HAL_READ_UINT8(&flexcan->CANCTRL0, ctrl0);
1051 HAL_WRITE_UINT8(&flexcan->CANCTRL0, ctrl0 | FLEXCAN_CTRL0_BOFFMSK);
1055 //===========================================================================
1056 // Flexcan message box isr
1057 //===========================================================================
1058 static cyg_uint32 flexcan_mbox_rx_isr(cyg_vector_t vec, cyg_addrword_t data)
1060 can_channel *chan = (can_channel *)data;
1061 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1062 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1067 // number of message box can be calculated from vector that cause
1068 // interrupt - we pass this message box number as additional data to the
1069 // callback because it is required in the receive event function later
1071 cyg_uint8 mbox = vec - info->isr_vec_mbox0;
1074 // first we disable interrupts of this message box - the DSR will
1075 // reenable it later
1077 HAL_READ_UINT16(&flexcan->IMASK, imask);
1078 HAL_WRITE_UINT16(&flexcan->IMASK, imask & ~(0x0001 << mbox));
1081 // for clearing the interrupt we first read the flag register as 1
1082 // and then write it as 1 (and not as zero like the manual stated)
1083 // we clear only the flag of this interrupt and leave all other
1084 // message box interrupts untouched
1086 HAL_READ_UINT16(&flexcan->IFLAG, iflag);
1087 HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));
1090 // On the mcf5272 there is no need to acknowledge internal
1091 // interrupts, only external ones.
1092 // cyg_drv_interrupt_acknowledge(vec);
1094 return CYG_ISR_CALL_DSR;
1098 //===========================================================================
1099 // Flexcan message box dsr
1100 //===========================================================================
1101 static void flexcan_mbox_rx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
1103 can_channel *chan = (can_channel *)data;
1104 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1105 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1109 // number of message box can be calculated from vector that caused
1110 // interrupt - we pass this message box number as additional data to the
1113 cyg_uint8 mbox = vec - info->isr_vec_mbox0;
1116 // signal CAN event to generic IO CAN driver - it will do any further
1119 chan->callbacks->rcv_event(chan, &mbox);
1122 // reenable interrupts for the message box that caused the DSR to run
1124 HAL_READ_UINT16(&flexcan->IMASK, imask);
1125 HAL_WRITE_UINT16(&flexcan->IMASK, imask | (0x0001 << mbox));
1128 //===========================================================================
1129 // Flexcan message box isr
1130 //===========================================================================
1131 static cyg_uint32 flexcan_mbox_tx_isr(cyg_vector_t vec, cyg_addrword_t data)
1133 can_channel *chan = (can_channel *)data;
1134 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1135 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1139 // number of message box can be calculated from vector that cause
1140 // interrupt - we pass this message box number as additional data to the
1143 cyg_uint8 mbox = vec - info->isr_vec_mbox0;
1146 // the first thing we do here is to disable this message box. we do this
1147 // because if we just sent a remote transmission request with this message
1148 // box then the FLEXCAN modul will automatically set up this message box
1149 // for reception of the requested data frame. But we won't receive messages
1150 // with the TX message box and deactivate it here immediatelly.
1152 HAL_WRITE_UINT8(&flexcan->mbox[mbox].ctrlstat, MBOX_TXCODE_NOT_READY);
1155 // first we disable interrupts of this message box - the DSR will
1156 // reenable it later
1158 HAL_READ_UINT16(&flexcan->IMASK, imask);
1159 HAL_WRITE_UINT16(&flexcan->IMASK, imask & ~(0x0001 << mbox));
1162 // for clearing the interrupt we first read the flag register as 1
1163 // and then write it as 1 (and not as zero like the manual stated)
1164 // we clear only the flag of this interrupt and leave all other
1165 // message box interrupts untouched
1167 HAL_READ_UINT16(&flexcan->IFLAG, iflag);
1168 HAL_WRITE_UINT16(&flexcan->IFLAG, (0x0001 << mbox));
1169 info->tx_busy = false;
1172 // On the mcf5272 there is no need to acknowledge internal
1173 // interrupts, only external ones.
1174 // cyg_drv_interrupt_acknowledge(vec);
1176 return CYG_ISR_CALL_DSR;
1180 //===========================================================================
1181 // Flexcan message box dsr
1182 //===========================================================================
1183 static void flexcan_mbox_tx_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data)
1185 can_channel *chan = (can_channel *)data;
1186 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1187 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1191 // number of message box can be calculated from vector that caused
1192 // interrupt - we pass this message box number as additional data to the
1195 cyg_uint8 mbox = vec - info->isr_vec_mbox0;
1198 // send next message
1200 chan->callbacks->xmt_msg(chan, &mbox);
1203 // reenable interrupts for the message box that caused the DSR to run
1205 HAL_READ_UINT16(&flexcan->IMASK, imask);
1206 HAL_WRITE_UINT16(&flexcan->IMASK, imask | (0x0001 << mbox));
1210 //===========================================================================
1211 // START FLEXCAN MODUL
1212 //===========================================================================
1213 static void flexcan_start_chip(can_channel *chan)
1215 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1216 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1219 HAL_READ_UINT16(&flexcan->CANMCR, tmp16);
1220 HAL_WRITE_UINT16(&flexcan->CANMCR, tmp16
1221 & ~(FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT));
1225 //===========================================================================
1226 // SET ACCEPTANCE MASK
1227 //===========================================================================
1228 static void flexcan_set_acceptance_mask(cyg_uint16 *rxmask_reg, cyg_uint32 mask, cyg_uint8 ext)
1232 // 32 bit access to RXMASK filters is broken so we use 16 Bit
1237 id = ((mask >> 13) & 0xFFE0); // set mask bits 18 - 28
1238 id |= ((mask >> 15) & 0x7); // set mask bits 15 -17
1239 HAL_WRITE_UINT16(&rxmask_reg[0], id);
1241 id = (mask << 1) & 0xFFFE;
1242 HAL_WRITE_UINT16(&rxmask_reg[1], id);
1246 id = ((mask << 5) & 0xFFE0);
1247 HAL_WRITE_UINT16(&rxmask_reg[0], id);
1248 HAL_WRITE_UINT16(&rxmask_reg[1], 0xFFFF);
1255 //===========================================================================
1256 // CONFIGURE MESSAGE BOX FOR TRANSMISSION
1257 //===========================================================================
1258 static bool flexcan_cfg_mbox_tx(flexcan_mbox *pmbox,
1259 cyg_can_message *pmsg,
1264 HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_NOT_READY);
1268 id = ((pmsg->id >> 13) & 0xFFE0); // setup id bits 18 - 28
1269 id |= (MBOX_CFG_IDE | MBOX_CFG_SSR); // set SSR and IDE bit to 1
1270 id |= ((pmsg->id >> 15) & 0x7); // set id bits 15 - 17
1271 HAL_WRITE_UINT16(&pmbox->id_hi, id);
1273 id = ((pmsg->id << 1) & 0xFFFE);
1277 id |= MBOX_CFG_RTR_EXT;
1280 HAL_WRITE_UINT16(&pmbox->id_lo, id);
1284 id = ((pmsg->id << 5) & 0xFFE0);
1287 id |= MBOX_CFG_RTR_STD; // set rtr bit for standard ID
1289 HAL_WRITE_UINT16(&pmbox->id_hi, id);
1290 HAL_WRITE_UINT16(&pmbox->id_lo, 0);
1293 pmsg->dlc %= 9; // limit data length to 8 bytes
1296 // Now copy data bytes into buffer and start transmission
1298 HAL_WRITE_UINT8_VECTOR(&pmbox->data, pmsg->data, pmsg->dlc, 1);
1302 HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_RESPONSE | pmsg->dlc);
1306 HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_TXCODE_TRANSMIT | pmsg->dlc);
1314 //===========================================================================
1315 // CONFIGURE MESSAGE BOX FOR RECEPTION OF FRAMES
1316 //===========================================================================
1317 static void flexcan_cfg_mbox_rx(flexcan_mbox *pmbox,
1323 HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_NOT_ACTIVE);
1327 id = ((canid >> 13) & 0xFFE0); // setup id bits 18 - 28
1328 id |= (MBOX_CFG_IDE | MBOX_CFG_SSR); // set SSR and IDE bit to 1
1329 id |= ((canid >> 15) & 0x7); // set id bits 15 - 17
1330 HAL_WRITE_UINT16(&pmbox->id_hi, id); // write ID high
1332 id = ((canid << 1) & 0xFFFE);
1334 HAL_WRITE_UINT16(&pmbox->id_lo, id);// write ID low
1338 id = ((canid << 5) & 0xFFE0);
1340 HAL_WRITE_UINT16(&pmbox->id_hi, id);
1341 HAL_WRITE_UINT16(&pmbox->id_lo, 0);
1344 HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY);
1348 //===========================================================================
1349 // READ DATA FROM MESSAGE BOX
1350 //==========================================================================
1351 static void flexcan_read_from_mbox(can_channel *chan,
1353 cyg_can_event *pevent,
1354 cyg_uint8 *ctrlstat)
1356 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1357 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1358 flexcan_mbox *pmbox = &flexcan->mbox[mbox];
1359 cyg_can_message *pmsg = &pevent->msg;
1363 HAL_READ_UINT8(&pmbox->ctrlstat, *ctrlstat); // this read will lock the mbox
1366 // If message buffer is busy then it is now beeing filled with a new message
1367 // This condition will be cleared within 20 cycles - wi simply do a 20 us
1368 // delay here, that should be enougth
1370 if (*ctrlstat & MBOX_RXCODE_BUSY)
1375 pmsg->dlc = (*ctrlstat & MBOX_CFG_DLC_MASK); // store received data len
1378 HAL_READ_UINT16(&pmbox->id_hi, id); // read ID high
1380 if (id & MBOX_CFG_IDE)
1383 pmsg->id = (id & 0xFFE0) << 13;
1385 HAL_READ_UINT16(&pmbox->id_lo, id);
1386 pmsg->id |= (id & 0xFFFE) >> 1;
1391 pmsg->id = (id & 0xFFE0) >> 5;
1395 // now finally copy data
1397 HAL_READ_UINT8_VECTOR(&pmbox->data, pmsg->data, pmsg->dlc, 1);
1400 // now zero out the remaining bytes in can message in order
1401 // to deliver a defined state
1403 for (i = pmsg->dlc; i < 8; ++i)
1409 // now mark this mbox as empty and read the free running timer
1410 // to unlock this mbox
1412 HAL_WRITE_UINT8(&pmbox->ctrlstat, MBOX_RXCODE_EMPTY);
1413 HAL_READ_UINT16(&flexcan->TIMER, id);
1414 #ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP
1415 pevent->timestamp = id;
1420 //===========================================================================
1421 // INIT CAN BAUD RATE
1422 //===========================================================================
1423 static bool flexcan_set_baud(can_channel *chan, cyg_uint16 baud)
1425 flexcan_info *info = (flexcan_info *)chan->dev_priv;
1426 flexcan_regs *flexcan = (flexcan_regs *)info->base;
1432 cyg_uint16 baudrate = flexcan_baud_rates[baud];
1435 // Get bit timings from HAL because bit timings depend on sysclock
1437 HAL_MCF52xx_FLEXCAN_GET_BIT_TIMINGS(&baudrate, &presdiv, &propseg, &pseg1_2);
1440 // return false if baudrate is not supported
1448 // For setting the bit timings we have to stop the flexcan modul
1450 HAL_READ_UINT16(&flexcan->CANMCR, mcr_bck);
1451 HAL_WRITE_UINT16(&flexcan->CANMCR, mcr_bck | FLEXCAN_MCR_HALT);
1454 // now we setup bit timings
1456 HAL_WRITE_UINT8(&flexcan->PRESDIV, presdiv);
1457 HAL_READ_UINT8(&flexcan->CANCTRL1, tmp8);
1458 HAL_WRITE_UINT8(&flexcan->CANCTRL1, (tmp8 & 0xF8) | propseg);
1459 HAL_READ_UINT8(&flexcan->CANCTRL2, tmp8);
1460 HAL_WRITE_UINT8(&flexcan->CANCTRL2, (tmp8 & 0xC0) | pseg1_2);
1463 // Now restore the previous state - if the modul was started then
1464 // it will no be started again, if it was stopped, then it remains stopped
1466 HAL_WRITE_UINT16(&flexcan->CANMCR, mcr_bck);
1471 //---------------------------------------------------------------------------
1472 // end of can_mcf_flexcan.c