1 //==========================================================================
3 // devs/can/arm/lpc2xxx/current/src/can_lpc2xxx.c
5 // CAN driver for LPC2xxx microcontrollers
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2003 Gary Thomas
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
44 // Author(s): Uwe Kindler
45 // Contributors: Uwe Kindler
47 // Purpose: Support LPC2xxx on-chip CAN moduls
50 //####DESCRIPTIONEND####
52 //==========================================================================
55 //==========================================================================
57 //==========================================================================
58 #include <pkgconf/system.h>
59 #include <pkgconf/io_can.h>
60 #include <pkgconf/io.h>
61 #include <pkgconf/devs_can_lpc2xxx.h>
63 #include <cyg/infra/diag.h>
65 #include <cyg/hal/hal_arch.h>
66 #include <cyg/hal/hal_intr.h>
67 #include <cyg/hal/hal_io.h>
69 #include <cyg/hal/hal_diag.h>
70 #include <cyg/infra/cyg_ass.h>
72 #include <cyg/io/io.h>
73 #include <cyg/io/devtab.h>
74 #include <cyg/io/can.h>
75 #include <cyg/io/can_lpc2xxx.h>
76 #include <cyg/io/can_lpc2xxx_baudrates.h>
81 //===========================================================================
83 //===========================================================================
85 // Check if the macro HAL_LPC2XXX_GET_CAN_BR is provided
87 #ifndef HAL_LPC2XXX_GET_CAN_BR
88 #error "Macro HAL_LPC2XXX_GET_CAN_BR() missing"
92 // Support debug output if this option is enabled in CDL file
94 #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
95 #define LPC2XXX_DBG_PRINT diag_printf
97 #define LPC2XXX_DBG_PRINT( fmt, ... )
101 //---------------------------------------------------------------------------
102 // we define our own set of register bits in order to be independent from
103 // platform specific names
106 //---------------------------------------------------------------------------
107 // Memory map of CAN block
109 #define CAN_ACCFILT_RAM_BASE 0xE0038000
110 #define CAN_ACCFILT_REG_BASE 0xE003C000
111 #define CAN_CENTRAL_REG_BASE 0xE0040000
112 #define CAN_CTRL_1_REG_BASE 0xE0044000
113 #define CAN_CTRL_2_REG_BASE 0xE0048000
114 #define CAN_CTRL_3_REG_BASE 0xE004C000
115 #define CAN_CTRL_4_REG_BASE 0xE0050000
118 //---------------------------------------------------------------------------
119 // CAN Acceptance Filter register layout
121 #define CAN_ACCFILT_AFMR (CAN_ACCFILT_REG_BASE + 0x0000)
122 #define CAN_ACCFILT_SFF_SA (CAN_ACCFILT_REG_BASE + 0x0004)
123 #define CAN_ACCFILT_SFF_GRP_SA (CAN_ACCFILT_REG_BASE + 0x0008)
124 #define CAN_ACCFILT_EFF_SA (CAN_ACCFILT_REG_BASE + 0x000C)
125 #define CAN_ACCFILT_EFF_GRP_SA (CAN_ACCFILT_REG_BASE + 0x0010)
126 #define CAN_ACCFILT_ENDOFTABLE (CAN_ACCFILT_REG_BASE + 0x0014)
127 #define CAN_ACCFILT_LUT_ERR_ADDR (CAN_ACCFILT_REG_BASE + 0x0018)
128 #define CAN_ACCFILT_LUT_ERR (CAN_ACCFILT_REG_BASE + 0x001C)
130 //---------------------------------------------------------------------------
131 // CAN_ACCFILT_AFMR Bits
133 #define AFMR_OFF 0x00000001 // 1 = Acceptance filter is not operational
134 #define AFMR_BYPASS 0x00000002 // 1 = all Rx messages are accepted on enabled CAN controllers.
135 #define AFMR_FULLCAN 0x00000004 // 1 = FullCAN mode
136 #define AFMR_ON 0x00000000 // Acceptance filter on
137 #define ACCFILT_RAM_SIZE 2048 // size of acceptance filter ram
140 //---------------------------------------------------------------------------
141 // Acceptance filter tool macros
143 #define ACCFILT_STD_ID_MASK 0x7FF
144 #define ACCFILT_EXT_ID_MASK 0x1FFFFFFF
145 #define ACCFILT_STD_DIS 0x1000
146 #define ACCFILT_STD_CTRL_MASK 0xE000
147 #define ACCFILT_EXT_CTRL_MASK 0xE0000000
148 #define ACCFILT_STD_GET_CTRL(_entry_) (((_entry_) >> 13) & 0x7)
149 #define ACCFILT_STD_GET_CTRL_LOWER(_entry_) (((_entry_) >> 29) & 0x7)
150 #define ACCFILT_STD_GET_CTRL_UPPER(_entry_) (((_entry_) >> 13) & 0x7)
151 #define ACCFILT_STD_GET_ID(_entry_) ((_entry_) & ACCFILT_STD_ID_MASK)
152 #define ACCFILT_EXT_GET_ID(_entry_) ((_entry_) & ACCFILT_EXT_ID_MASK)
153 #define ACCFILT_EXT_GET_CTRL(_entry_) (((_entry_) >> 29) & 0x7)
154 #define ACCFILT_EXT_SET_CTRL(_entry_, _ctrl_) ((_entry_ & 0xE0000000) | ((_ctrl_) << 29))
157 //---------------------------------------------------------------------------
158 // CAN Central CAN Registers register layout
160 #define CAN_CENTRAL_TXSR (CAN_CENTRAL_REG_BASE + 0x0000)
161 #define CAN_CENTRAL_RXSR (CAN_CENTRAL_REG_BASE + 0x0004)
162 #define CAN_CENTRAL_MSR (CAN_CENTRAL_REG_BASE + 0x0008)
165 //---------------------------------------------------------------------------
166 // CAN Controller register offsets
167 // Registers are offsets from base CAN module control register
169 #define CANREG_MOD 0x0000
170 #define CANREG_CMR 0x0004
171 #define CANREG_GSR 0x0008
172 #define CANREG_ICR 0x000C
173 #define CANREG_IER 0x0010
174 #define CANREG_BTR 0x0014
175 #define CANREG_EWL 0x0018
176 #define CANREG_SR 0x001C
177 #define CANREG_RFS 0x0020
178 #define CANREG_RID 0x0024
179 #define CANREG_RDA 0x0028
180 #define CANREG_RDB 0x002C
181 #define CANREG_TFI1 0x0030
182 #define CANREG_TID1 0x0034
183 #define CANREG_TDA1 0x0038
184 #define CANREG_TDB1 0x003C
185 #define CANREG_TFI2 0x0040
186 #define CANREG_TID2 0x0044
187 #define CANREG_TDA2 0x0048
188 #define CANREG_TDB2 0x004C
189 #define CANREG_TFI3 0x0050
190 #define CANREG_TID3 0x0054
191 #define CANREG_TDA3 0x0058
192 #define CANREG_TDB3 0x005C
195 //---------------------------------------------------------------------------
196 // CAN Controller register layout
198 #define CAN_CTRL_MOD(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_MOD)
199 #define CAN_CTRL_CMR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_CMR)
200 #define CAN_CTRL_GSR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_GSR)
201 #define CAN_CTRL_ICR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_ICR)
202 #define CAN_CTRL_IER(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_IER)
203 #define CAN_CTRL_BTR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_BTR)
204 #define CAN_CTRL_EWL(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_EWL)
205 #define CAN_CTRL_SR(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_SR)
206 #define CAN_CTRL_RFS(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_RFS)
207 #define CAN_CTRL_RID(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_RID)
208 #define CAN_CTRL_RDA(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_RDA)
209 #define CAN_CTRL_RDB(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_RDB)
210 #define CAN_CTRL_TFI1(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TFI1)
211 #define CAN_CTRL_TID1(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TID1)
212 #define CAN_CTRL_TDA1(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDA1)
213 #define CAN_CTRL_TDB1(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDB1)
214 #define CAN_CTRL_TFI2(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TFI2)
215 #define CAN_CTRL_TID2(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TID2)
216 #define CAN_CTRL_TDA2(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDA2)
217 #define CAN_CTRL_TDB2(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDB2)
218 #define CAN_CTRL_TFI3(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TFI3)
219 #define CAN_CTRL_TID3(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TID3)
220 #define CAN_CTRL_TDA3(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDA3)
221 #define CAN_CTRL_TDB3(_extra_) (CAN_CTRL_BASE(_extra_) + CANREG_TDB3)
224 //---------------------------------------------------------------------------
225 // CAN_CTRL_ICR register bits
227 #define ICR_RX 0x00000001
228 #define ICR_TX1 0x00000002
229 #define ICR_ERR_WARN 0x00000004
230 #define ICR_DATA_OVR 0x00000008
231 #define ICR_WAKE_UP 0x00000010
232 #define ICR_ERR_PASSIVE 0x00000020
233 #define ICR_ARBITR_LOST 0x00000040
234 #define ICR_BUS_ERR 0x00000080
235 #define ICR_ID_READY 0x00000100
236 #define ICR_TX2 0x00000200
237 #define ICR_TX3 0x00000400
238 #define ICR_LUT_ERR 0x00000800
239 #define ICR_GET_ERRBIT(_icr_) (((_icr_) >> 16) & 0x1F)
240 #define ICR_ERR_DIRECTION 0x00200000
241 #define ICR_GET_ERRCODE(_icr_) (((_icr_) >> 22) & 0x03)
242 #define ICR_GET_ALCBIT(_icr_) (((_icr_) >> 24) & 0x1F)
244 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_ALIE
245 #define CAN_ALL_ERR_INT (ICR_ERR_PASSIVE | ICR_ARBITR_LOST | ICR_BUS_ERR | ICR_ERR_WARN)
247 #define CAN_ALL_ERR_INT (ICR_ERR_PASSIVE | ICR_BUS_ERR | ICR_ERR_WARN)
249 #define CAN_MISC_INT (CAN_ALL_ERR_INT | ICR_WAKE_UP)
252 //---------------------------------------------------------------------------
253 // CAN_CTRL_ICR register bits
255 #define ICR_ERRCODE_BIT_ERR 0x00
256 #define ICR_ERRCODE_FORM_ERR 0x01
257 #define ICR_ERRCODE_STUFF_ERR 0x02
258 #define ICR_ERRCODE_OTHER_ERR 0x03
261 //---------------------------------------------------------------------------
262 // CAN_CTRL_RFS register bits
264 #define RFS_ACCFILT_INDEX_MASK 0x000003FF
265 #define RFS_RECEIVED_IN_BYPASS_MODE 0x00000400
266 #define RFS_DLC_MASK 0x000F0000
267 #define RFS_RTR 0x40000000
268 #define RFS_EXT 0x80000000
269 #define RFS_GET_DLC(_regval_) (((_regval_) >> 16) & 0xF)
271 //---------------------------------------------------------------------------
272 // CAN_CTRL_CMR register bits
274 #define CMR_TX_REQ 0x00000001
275 #define CMR_TX_ABORT 0x00000002
276 #define CMR_RX_RELEASE_BUF 0x00000004
277 #define CMR_CLEAR_DATA_OVR 0x00000008
278 #define CMR_SELF_RX_REQ 0x00000010
279 #define CMR_SEND_TX_BUF1 0x00000020
280 #define CMR_SEND_TX_BUF2 0x00000040
281 #define CMR_SEND_TX_BUF3 0x00000080
284 //---------------------------------------------------------------------------
285 // CAN_CTRL_TFI register bits
287 #define TFI_PRIO_MASK 0x000000FF
288 #define TFI_DLC_MASK 0x000F0000
289 #define TFI_DLC_RTR 0x40000000
290 #define TFI_DLC_EXT 0x80000000
293 //---------------------------------------------------------------------------
294 // CAN_CTRL_MOD register bits
296 #define CANMOD_OPERATIONAL 0x00000000
297 #define CANMOD_RESET 0x00000001
298 #define CANMOD_LISTEN_ONLY 0x00000002
299 #define CANMOD_SELF_TEST 0x00000004
300 #define CANMOD_TX_BUF_CFG 0x00000008
301 #define CANMOD_SLEEP 0x00000010
302 #define CANMOD_REV_POLARITY 0x00000020
303 #define CANMOD_TEST 0x00000040
306 //---------------------------------------------------------------------------
307 // CAN_CTRL_IER register bits
309 #define IER_RX 0x00000001
310 #define IER_TX1 0x00000002
311 #define IER_ERR_WARN 0x00000004
312 #define IER_DATA_OVR 0x00000008
313 #define IER_WAKE_UP 0x00000010
314 #define IER_ERR_PASSIVE 0x00000020
315 #define IER_ARBITR_LOST 0x00000040
316 #define IER_BUS_ERR 0x00000080
317 #define IER_ID_READY 0x00000100
318 #define IER_TX2 0x00000200
319 #define IER_TX3 0x00000400
322 //---------------------------------------------------------------------------
323 // CAN_CTRL_GSR register bits
325 #define GSR_RX_MSG_AVAILABLE 0x00000001
326 #define GSR_DATA_OVR 0x00000002
327 #define GSR_TX_NOT_PENDING 0x00000004
328 #define GSR_ALL_TX_COMPLETE 0x00000008
329 #define GSR_RECEIVING_ACTIVE 0x00000010
330 #define GSR_SENDING_ACTIVE 0x00000020
331 #define GSR_ERR 0x00000040
332 #define GSR_BUS_OFF 0x00000080
333 #define GSR_RXERR_CNT(_reg_) (((_reg_) >> 16) & 0xFF)
334 #define GSR_TXERR_CNT(_reg_) (((_reg_) >> 24) & 0xFF)
337 //---------------------------------------------------------------------------
338 // CAN_CTRL_SR register bits
340 #define SR_RX_MSG_AVAILABLE 0x01
341 #define SR_DATA_OVR 0x02
342 #define SR_TX_BUF_WRITE_OK 0x04 // TBS1, TBS2, TBS3 (Bit 2, 10, 18)
343 #define SR_TX_COMPLETE 0x08 // TCS1, TCS2, TCS3 (Bit 3, 11, 19)
344 #define SR_RECEIVING_ACTIVE 0x10
345 #define SR_SENDING_ACTIVE 0x20 // TS1, TS2, TS3 (5, 13, 21)
347 #define SR_BUS_OFF 0x80
350 //---------------------------------------------------------------------------
351 // Optimize for the case of a single CAN channel, while still allowing
352 // multiple channels.
354 #if CYGINT_IO_CAN_CHANNELS == 1
355 #define CAN_CTRL_BASE(_extra_) CAN_CTRL_SINGLETON_BASE
356 #define CAN_ISRVEC(_extra_) CAN_SINGLETON_ISRVEC
357 #define CAN_CHAN_NO(_extra_) CAN_SINGLETON_CHAN_NO
358 #define CAN_DECLARE_INFO(_chan_)
359 #define CAN_DECLARE_CHAN(_data_)
361 #define CAN_CTRL_BASE(_extra_) ((_extra_)->base)
362 #define CAN_ISRVEC(_extra_) ((_extra_)->isrvec)
363 #define CAN_CHAN_NO(_extra_) ((_extra_)->chan_no)
364 #define CAN_DECLARE_INFO(_chan_) lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
365 #define CAN_DECLARE_CHAN(_data_) can_channel *chan = (can_channel *)data;
366 #endif // CYGINT_IO_CAN_CHANNELS == 1
369 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_CAN0_ACCFILT_STARTUP_CFG_RX_ALL
370 #define CAN0_FLAG_STARTUP_ACCFILT_SETUP INFO_FLAG_STARTUP_RX_ALL
372 #define CAN0_FLAG_STARTUP_ACCFILT_SETUP 0x00
375 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_CAN1_ACCFILT_STARTUP_CFG_RX_ALL
376 #define CAN1_FLAG_STARTUP_ACCFILT_SETUP INFO_FLAG_STARTUP_RX_ALL
378 #define CAN1_FLAG_STARTUP_ACCFILT_SETUP 0x00
381 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_CAN2_ACCFILT_STARTUP_CFG_RX_ALL
382 #define CAN2_FLAG_STARTUP_ACCFILT_SETUP INFO_FLAG_STARTUP_RX_ALL
384 #define CAN2_FLAG_STARTUP_ACCFILT_SETUP 0x00
387 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_CAN3_ACCFILT_STARTUP_CFG_RX_ALL
388 #define CAN3_FLAG_STARTUP_ACCFILT_SETUP INFO_FLAG_STARTUP_RX_ALL
390 #define CAN3_FLAG_STARTUP_ACCFILT_SETUP 0x00
394 //===========================================================================
396 //===========================================================================
398 // Structure stores LPC2xxx CAN channel related stuff
401 // If we use Self Reception Request command instead of the Transmission Request
402 // we must add last transmit message id in order to reject it in rx_ISR
403 // There are two last_tx_id because tx interrupt (and so transmission of next
404 // message) happens before rx interrupt (which uses last_tx_id for rejecting))
406 // Format of last_tx_id:
407 // (bits: 28:0-ID, 29-Validation, 30-RTR, 31-EXT)
408 // if last_tx_id == 0xFFFFFFFF (Validation == 1) then last id is not valid
409 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_USE_SELF_RECEPTION
410 #define LPC2XXX_CAN_INFO_LAST_TX_ID_IDMASK 0x1FFFFFFF
411 #define LPC2XXX_CAN_INFO_LAST_TX_ID_FLMASK 0xC0000000
412 #define LPC2XXX_CAN_INFO_LAST_TX_ID_NOVALID 0xFFFFFFFF
414 #define LPC2XXX_CAN_INFO_LAST_TX_ID_DECL cyg_uint8 last_tx_index; \
415 cyg_uint32 last_tx_id[2];
416 #define LPC2XXX_CAN_INFO_LAST_TX_ID_INIT last_tx_index : 0, \
417 last_tx_id : {LPC2XXX_CAN_INFO_LAST_TX_ID_NOVALID, LPC2XXX_CAN_INFO_LAST_TX_ID_NOVALID},
419 #define LPC2XXX_CAN_INFO_LAST_TX_ID_DECL
420 #define LPC2XXX_CAN_INFO_LAST_TX_ID_INIT
423 typedef struct lpc2xxx_can_info_st
426 // Newer LPC2xxx variants like the LPC2468 do not support per channel
427 // interrupts. They provide only one single interrupt vector for all
430 #ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
431 cyg_interrupt tx_interrupt;
432 cyg_handle_t tx_interrupt_handle;
433 cyg_uint8 tx_interrupt_priority;
434 cyg_interrupt rx_interrupt;
435 cyg_handle_t rx_interrupt_handle;
436 cyg_uint8 rx_interrupt_priority;
437 #endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
438 cyg_can_state state; // state of CAN controller
439 cyg_uint8 flags; // flags indicating several states
440 LPC2XXX_CAN_INFO_LAST_TX_ID_DECL // last transmitted messages ids
441 #if CYGINT_IO_CAN_CHANNELS > 1
442 cyg_uint32 base; // Per-bus h/w details
443 #ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
444 cyg_uint8 isrvec; // ISR vector (peripheral id)
445 #endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
446 cyg_uint8 chan_no; // number of CAN channel
447 #endif // CYGINT_IO_CAN_CHANNELS > 1
448 } lpc2xxx_can_info_t;
451 #define INFO_FLAG_RX_ALL 0x01 // this bit indicates that channel receives all CAN messages - no filtering active
452 #define INFO_FLAG_STARTUP_RX_ALL 0x02 // this bit indicates filter state at startup
456 // lpc2xxx info initialisation
458 #define LPC2XXX_CTRL_NOT_INITIALIZED 0xFF
460 #ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
461 #if CYGINT_IO_CAN_CHANNELS > 1
462 #define LPC2XXX_CAN_INFO(_l, _base, _isrvec, _chan_no_, _tx_priority, _rx_priority, _flags) \
463 lpc2xxx_can_info_t _l = { \
464 state : LPC2XXX_CTRL_NOT_INITIALIZED, \
466 isrvec : (_isrvec), \
467 chan_no : (_chan_no_), \
468 tx_interrupt_priority : (_tx_priority), \
469 rx_interrupt_priority : (_rx_priority), \
471 LPC2XXX_CAN_INFO_LAST_TX_ID_INIT \
473 #else // CYGINT_IO_CAN_CHANNELS == 1
474 #define LPC2XXX_CAN_INFO(_l, _tx_priority, _rx_priority, _flags) \
475 lpc2xxx_can_info_t _l = { \
476 state : CYGNUM_CAN_STATE_STOPPED, \
477 tx_interrupt_priority : (_tx_priority), \
478 rx_interrupt_priority : (_rx_priority), \
480 LPC2XXX_CAN_INFO_LAST_TX_ID_INIT \
482 #endif // CYGINT_IO_CAN_CHANNELS == 1
483 #else // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
485 // Newer devices support only one global CAN interrupt. We do not need
486 // per channel interrupt data an ignore the values during initialisation
488 #if CYGINT_IO_CAN_CHANNELS > 1
489 #define LPC2XXX_CAN_INFO(_l, _base, _isrvec, _chan_no_, _tx_priority, _rx_priority, _flags) \
490 lpc2xxx_can_info_t _l = { \
491 state : LPC2XXX_CTRL_NOT_INITIALIZED, \
493 chan_no : (_chan_no_), \
495 LPC2XXX_CAN_INFO_LAST_TX_ID_INIT \
497 #else // CYGINT_IO_CAN_CHANNELS == 1
498 #define LPC2XXX_CAN_INFO(_l, _tx_priority, _rx_priority, _flags) \
499 lpc2xxx_can_info_t _l = { \
500 state : CYGNUM_CAN_STATE_STOPPED, \
502 LPC2XXX_CAN_INFO_LAST_TX_ID_INIT \
504 #endif // CYGINT_IO_CAN_CHANNELS == 1
507 // The following defines are only dummies required for proper
508 // initialisation of can channel data structures
510 #define CYGNUM_HAL_INTERRUPT_CAN1_TX
511 #define CYGNUM_DEVS_CAN_LPC2XXX_CAN0_TX_INT_PRIORITY
512 #define CYGNUM_DEVS_CAN_LPC2XXX_CAN0_RX_INT_PRIORITY
513 #define CYGNUM_HAL_INTERRUPT_CAN2_TX
514 #define CYGNUM_DEVS_CAN_LPC2XXX_CAN1_TX_INT_PRIORITY
515 #define CYGNUM_DEVS_CAN_LPC2XXX_CAN1_RX_INT_PRIORITY
516 #define CYGNUM_HAL_INTERRUPT_CAN3_TX
517 #define CYGNUM_DEVS_CAN_LPC2XXX_CAN2_TX_INT_PRIORITY
518 #define CYGNUM_DEVS_CAN_LPC2XXX_CAN2_RX_INT_PRIORITY
519 #define CYGNUM_HAL_INTERRUPT_CAN4_TX
520 #define CYGNUM_DEVS_CAN_LPC2XXX_CAN3_TX_INT_PRIORITY
521 #define CYGNUM_DEVS_CAN_LPC2XXX_CAN3_RX_INT_PRIORITY
522 #endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
526 // Acceptance filter data
528 typedef struct lpc2xxx_global_can_info_st
530 cyg_interrupt interrupt; // common CAN interrupt
531 cyg_handle_t interrupt_handle; // common CAN interrupt handle
532 cyg_uint16 free_filters; // number of free message filter
533 #if CYGINT_IO_CAN_CHANNELS > 1 // optimize for single channel
534 cyg_uint8 init_cnt; // counts number of initialized channels
535 can_channel* active_channels[5]; // stores pointers to active channels - the last entry is just a delimiter
536 #else // CYGINT_IO_CAN_CHANNELS > 1
537 can_channel* active_channels[1]; // optimize for one single channel
538 #endif // CYGINT_IO_CAN_CHANNELS > 1
539 } lpc2xxx_global_can_info_t;
542 #if CYGINT_IO_CAN_CHANNELS > 1
543 #define LPC2XXX_GET_CAN_CHANNEL(_can_info_, _chan_no_) ((can_channel*)(_can_info_).active_channels[_chan_no_])
545 #define LPC2XXX_GET_CAN_CHANNEL(_can_info_, _chan_no_) ((can_channel*)(_can_info_).active_channels[0])
549 // The number of available message filters depends on the size of the
550 // acceptance filter RAM and on the size of one entry. The size of
551 // one entry is 4 byte (standard ID only 2 byte, extended groups 8 byte)
553 #define ACCFILT_COMMON_ENTRY_SIZE 4
554 #define LPC2XXX_CAN_MSG_FILTERS_MAX (ACCFILT_RAM_SIZE / ACCFILT_COMMON_ENTRY_SIZE)
555 lpc2xxx_global_can_info_t lpc2xxx_global_can_info =
557 .free_filters = LPC2XXX_CAN_MSG_FILTERS_MAX,
558 #if CYGINT_IO_CAN_CHANNELS > 1 // optimize for single channel
560 .active_channels = {0, 0, 0, 0, 0},
561 #endif // #if CYGINT_IO_CAN_CHANNELS > 1
567 // Data type for access of single bytes/words of an dword value
569 typedef union lsc_buf_u
580 cyg_uint16 upper; // uppper column of acceptance filter ram
581 cyg_uint16 lower; // lower column of acceptance filter ram
588 //===========================================================================
590 //===========================================================================
591 #if CYGINT_IO_CAN_CHANNELS > 1
592 #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN0
593 LPC2XXX_CAN_INFO(lpc2xxx_can0_info,
595 CYGNUM_HAL_INTERRUPT_CAN1_TX,
597 CYGNUM_DEVS_CAN_LPC2XXX_CAN0_TX_INT_PRIORITY,
598 CYGNUM_DEVS_CAN_LPC2XXX_CAN0_RX_INT_PRIORITY,
599 CAN0_FLAG_STARTUP_ACCFILT_SETUP);
602 #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN1
603 LPC2XXX_CAN_INFO(lpc2xxx_can1_info,
605 CYGNUM_HAL_INTERRUPT_CAN2_TX,
607 CYGNUM_DEVS_CAN_LPC2XXX_CAN1_TX_INT_PRIORITY,
608 CYGNUM_DEVS_CAN_LPC2XXX_CAN1_RX_INT_PRIORITY,
609 CAN1_FLAG_STARTUP_ACCFILT_SETUP);
612 #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN2
613 LPC2XXX_CAN_INFO(lpc2xxx_can2_info,
615 CYGNUM_HAL_INTERRUPT_CAN3_TX,
617 CYGNUM_DEVS_CAN_LPC2XXX_CAN2_TX_INT_PRIORITY,
618 CYGNUM_DEVS_CAN_LPC2XXX_CAN2_RX_INT_PRIORITY,
619 CAN2_FLAG_STARTUP_ACCFILT_SETUP);
622 #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN3
623 LPC2XXX_CAN_INFO(lpc2xxx_can3_info,
625 CYGNUM_HAL_INTERRUPT_CAN4_TX,
627 CYGNUM_DEVS_CAN_LPC2XXX_CAN3_TX_INT_PRIORITY,
628 CYGNUM_DEVS_CAN_LPC2XXX_CAN3_RX_INT_PRIORITY,
629 CAN3_FLAG_STARTUP_ACCFILT_SETUP);
631 #else // CYGINT_IO_CAN_CHANNELS == 1
632 #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN0
633 LPC2XXX_CAN_INFO(lpc2xxx_can0_info,
634 CYGNUM_DEVS_CAN_LPC2XXX_CAN0_TX_INT_PRIORITY,
635 CYGNUM_DEVS_CAN_LPC2XXX_CAN0_RX_INT_PRIORITY,
636 CAN0_FLAG_STARTUP_ACCFILT_SETUP);
637 #define CAN_CTRL_SINGLETON_BASE CAN_CTRL_1_REG_BASE
638 #define CAN_SINGLETON_ISRVEC CYGNUM_HAL_INTERRUPT_CAN1_TX
639 #define CAN_SINGLETON_CHAN_NO 0
642 #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN1
643 LPC2XXX_CAN_INFO(lpc2xxx_can1_info,
644 CYGNUM_DEVS_CAN_LPC2XXX_CAN1_TX_INT_PRIORITY,
645 CYGNUM_DEVS_CAN_LPC2XXX_CAN1_RX_INT_PRIORITY,
646 CAN1_FLAG_STARTUP_ACCFILT_SETUP);
647 #define CAN_CTRL_SINGLETON_BASE CAN_CTRL_2_REG_BASE
648 #define CAN_SINGLETON_ISRVEC CYGNUM_HAL_INTERRUPT_CAN2_TX
649 #define CAN_SINGLETON_CHAN_NO 1
652 #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN2
653 LPC2XXX_CAN_INFO(lpc2xxx_can2_info,
654 CYGNUM_DEVS_CAN_LPC2XXX_CAN2_TX_INT_PRIORITY,
655 CYGNUM_DEVS_CAN_LPC2XXX_CAN2_RX_INT_PRIORITY,
656 CAN2_FLAG_STARTUP_ACCFILT_SETUP);
657 #define CAN_CTRL_SINGLETON_BASE CAN_CTRL_3_REG_BASE
658 #define CAN_SINGLETON_ISRVEC CYGNUM_HAL_INTERRUPT_CAN3_TX
659 #define CAN_SINGLETON_CHAN_NO 2
662 #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN3
663 LPC2XXX_CAN_INFO(lpc2xxx_can3_info,
664 CYGNUM_DEVS_CAN_LPC2XXX_CAN3_TX_INT_PRIORITY,
665 CYGNUM_DEVS_CAN_LPC2XXX_CAN3_RX_INT_PRIORITY,
666 CAN3_FLAG_STARTUP_ACCFILT_SETUP);
667 #define CAN_CTRL_SINGLETON_BASE CAN_CTRL_4_REG_BASE
668 #define CAN_SINGLETON_ISRVEC CYGNUM_HAL_INTERRUPT_CAN4_TX
669 #define CAN_SINGLETON_CHAN_NO 3
672 #endif // #if CYGINT_IO_CAN_CHANNELS > 1
675 //===========================================================================
677 //===========================================================================
679 //--------------------------------------------------------------------------
680 // Device driver interface functions
682 static bool lpc2xxx_can_init(struct cyg_devtab_entry* devtab_entry);
683 static Cyg_ErrNo lpc2xxx_can_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name);
684 static Cyg_ErrNo lpc2xxx_can_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len);
685 static Cyg_ErrNo lpc2xxx_can_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len);
686 static bool lpc2xxx_can_putmsg(can_channel *priv, CYG_CAN_MSG_T *pmsg, void *pdata);
687 static bool lpc2xxx_can_getevent(can_channel *priv, CYG_CAN_EVENT_T *pevent, void *pdata);
688 static void lpc2xxx_can_start_xmit(can_channel* chan);
689 static void lpc2xxx_can_stop_xmit(can_channel* chan);
692 //--------------------------------------------------------------------------
695 #ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
696 static cyg_uint32 lpc2xxx_can_tx_ISR(cyg_vector_t vector, cyg_addrword_t data);
697 static void lpc2xxx_can_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
698 static cyg_uint32 lpc2xxx_can_rx_ISR(cyg_vector_t vector, cyg_addrword_t data);
699 static void lpc2xxx_can_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
700 #endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
701 static cyg_uint32 lpc2xxx_can_ISR(cyg_vector_t vector, cyg_addrword_t data);
702 static void lpc2xxx_can_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
705 //--------------------------------------------------------------------------
706 // Private utility functions
708 static bool lpc2xxx_can_config_channel(can_channel* chan, cyg_can_info_t* config, cyg_bool init);
709 static bool lpc2xxx_can_set_baud(can_channel *chan, cyg_can_baud_rate_t *baudrate);
710 static Cyg_ErrNo lpc2xxx_enter_lowpower_mode(can_channel *chan);
711 static void lpc2xxx_start_module(can_channel *chan);
712 static cyg_can_state lpc2xxx_get_state(lpc2xxx_can_info_t *info);
713 static void lpc2xxx_set_state(lpc2xxx_can_info_t *info, cyg_can_state state);
716 //--------------------------------------------------------------------------
717 // Message box configuration
719 static void lpc2xxx_can_config_rx_all(can_channel *chan);
720 #ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
721 static void lpc2xxx_can_config_rx_none(can_channel *chan);
722 static bool lpc2xxx_can_add_rx_filter(lpc2xxx_can_info_t *info, cyg_can_filter *filter);
723 #endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
726 #include "can_accfilt_lpc2xxx.c"
728 //===========================================================================
729 // GENERIC CAN IO DATA INITIALISATION
730 //===========================================================================
731 CAN_LOWLEVEL_FUNS(lpc2xxx_can_lowlevel_funs,
733 lpc2xxx_can_getevent,
734 lpc2xxx_can_get_config,
735 lpc2xxx_can_set_config,
736 lpc2xxx_can_start_xmit,
737 lpc2xxx_can_stop_xmit
741 //---------------------------------------------------------------------------
744 #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN0
745 CYG_CAN_EVENT_T lpc2xxx_can0_rxbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN0_QUEUESIZE_RX]; // buffer for RX can events
746 CYG_CAN_MSG_T lpc2xxx_can0_txbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN0_QUEUESIZE_TX]; // buffer for TX can messages
749 CAN_CHANNEL_USING_INTERRUPTS(lpc2xxx_can0_chan,
750 lpc2xxx_can_lowlevel_funs,
752 CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LPC2XXX_CAN0_KBAUD),
753 lpc2xxx_can0_txbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN0_QUEUESIZE_TX,
754 lpc2xxx_can0_rxbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN0_QUEUESIZE_RX
758 DEVTAB_ENTRY(lpc2xxx_can0_devtab,
759 CYGPKG_DEVS_CAN_LPC2XXX_CAN0_NAME,
760 0, // Does not depend on a lower level interface
763 lpc2xxx_can_lookup, // CAN driver may need initializing
766 #endif // CYGPKG_DEVS_CAN_LPC2XXX_CAN0
769 //---------------------------------------------------------------------------
772 #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN1
773 CYG_CAN_EVENT_T lpc2xxx_can1_rxbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN1_QUEUESIZE_RX]; // buffer for RX can events
774 CYG_CAN_MSG_T lpc2xxx_can1_txbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN1_QUEUESIZE_TX]; // buffer for TX can messages
777 CAN_CHANNEL_USING_INTERRUPTS(lpc2xxx_can1_chan,
778 lpc2xxx_can_lowlevel_funs,
780 CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LPC2XXX_CAN1_KBAUD),
781 lpc2xxx_can1_txbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN1_QUEUESIZE_TX,
782 lpc2xxx_can1_rxbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN1_QUEUESIZE_RX
786 DEVTAB_ENTRY(lpc2xxx_can1_devtab,
787 CYGPKG_DEVS_CAN_LPC2XXX_CAN1_NAME,
788 0, // Does not depend on a lower level interface
791 lpc2xxx_can_lookup, // CAN driver may need initializing
794 #endif // CYGPKG_DEVS_CAN_LPC2XXX_CAN1
797 //---------------------------------------------------------------------------
800 #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN2
801 CYG_CAN_EVENT_T lpc2xxx_can2_rxbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN2_QUEUESIZE_RX]; // buffer for RX can events
802 CYG_CAN_MSG_T lpc2xxx_can2_txbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN2_QUEUESIZE_TX]; // buffer for TX can messages
805 CAN_CHANNEL_USING_INTERRUPTS(lpc2xxx_can2_chan,
806 lpc2xxx_can_lowlevel_funs,
808 CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LPC2XXX_CAN2_KBAUD),
809 lpc2xxx_can2_txbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN2_QUEUESIZE_TX,
810 lpc2xxx_can2_rxbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN2_QUEUESIZE_RX
814 DEVTAB_ENTRY(lpc2xxx_can2_devtab,
815 CYGPKG_DEVS_CAN_LPC2XXX_CAN2_NAME,
816 0, // Does not depend on a lower level interface
819 lpc2xxx_can_lookup, // CAN driver may need initializing
822 #endif // CYGPKG_DEVS_CAN_LPC2XXX_CAN2
825 //---------------------------------------------------------------------------
828 #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN3
829 CYG_CAN_EVENT_T lpc2xxx_can3_rxbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN3_QUEUESIZE_RX]; // buffer for RX can events
830 CYG_CAN_MSG_T lpc2xxx_can3_txbuf[CYGNUM_DEVS_CAN_LPC2XXX_CAN3_QUEUESIZE_TX]; // buffer for TX can messages
833 CAN_CHANNEL_USING_INTERRUPTS(lpc2xxx_can3_chan,
834 lpc2xxx_can_lowlevel_funs,
836 CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LPC2XXX_CAN3_KBAUD),
837 lpc2xxx_can3_txbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN3_QUEUESIZE_TX,
838 lpc2xxx_can3_rxbuf, CYGNUM_DEVS_CAN_LPC2XXX_CAN3_QUEUESIZE_RX
842 DEVTAB_ENTRY(lpc2xxx_can3_devtab,
843 CYGPKG_DEVS_CAN_LPC2XXX_CAN3_NAME,
844 0, // Does not depend on a lower level interface
847 lpc2xxx_can_lookup, // CAN driver may need initializing
850 #endif // CYGPKG_DEVS_CAN_LPC2XXX_CAN3
853 //===========================================================================
855 //===========================================================================
859 //===========================================================================
860 /// First initialisation and reset of CAN modul.
861 //===========================================================================
862 static bool lpc2xxx_can_init(struct cyg_devtab_entry* devtab_entry)
864 can_channel *chan = (can_channel*)devtab_entry->priv;
867 #ifdef CYGDBG_IO_INIT
868 diag_printf("LPC2XXX CAN init\n");
872 // Newer LPC2xxx variants do not support individual interrupt
873 // sources for CAN on chip peripherals
875 #ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
876 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
878 // Create TX interrupt
880 cyg_drv_interrupt_create(CAN_ISRVEC(info),
881 info->tx_interrupt_priority,
882 (cyg_addrword_t)chan, // Data item passed to interrupt handler
885 &info->tx_interrupt_handle,
886 &info->tx_interrupt);
887 cyg_drv_interrupt_attach(info->tx_interrupt_handle);
888 cyg_drv_interrupt_unmask(CAN_ISRVEC(info));
891 // Create RX interrupt
893 cyg_drv_interrupt_create(CAN_ISRVEC(info) + 6,
894 info->rx_interrupt_priority,
895 (cyg_addrword_t)chan, // Data item passed to interrupt handler
898 &info->rx_interrupt_handle,
899 &info->rx_interrupt);
900 cyg_drv_interrupt_attach(info->rx_interrupt_handle);
901 cyg_drv_interrupt_unmask(CAN_ISRVEC(info) + 6);
902 #endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
905 // Now create and enable global CAN interrupt. This interrupt is
906 // global for all channels and so we need to call it only one times -
907 // when the first channel is initialized
909 #if CYGINT_IO_CAN_CHANNELS > 1
910 if (!lpc2xxx_global_can_info.init_cnt)
911 #endif // #if CYGINT_IO_CAN_CHANNELS > 1
914 // Create err interrupt
916 cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_CAN,
917 #ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
918 CYGNUM_DEVS_CAN_LPC2XXX_ERR_INT_PRIORITY,
919 #else // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
920 CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY,
921 #endif // CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
922 0, // Data item passed to interrupt handler
925 &lpc2xxx_global_can_info.interrupt_handle,
926 &lpc2xxx_global_can_info.interrupt);
927 cyg_drv_interrupt_attach(lpc2xxx_global_can_info.interrupt_handle);
928 cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_CAN);
931 res = lpc2xxx_can_config_channel(chan, &chan->config, true);
932 #if CYGINT_IO_CAN_CHANNELS > 1
933 lpc2xxx_global_can_info.active_channels[lpc2xxx_global_can_info.init_cnt++] = chan;
934 #else // CYGINT_IO_CAN_CHANNELS > 1
935 lpc2xxx_global_can_info.active_channels[0] = chan;
941 //===========================================================================
942 // Configure can channel
943 //===========================================================================
944 static bool lpc2xxx_can_config_channel(can_channel* chan, cyg_can_info_t* config, cyg_bool init)
946 CAN_DECLARE_INFO(chan);
952 // In case platform needs extra initialization (i.e. setup of
953 // CAN transceivers) it should implement this macro
955 #ifdef CYGPRI_IO_CAN_LPC2XXX_PLF_INIT_HOOK
956 CYGPRI_IO_CAN_LPC2XXX_PLF_INIT_HOOK(chan, config);
959 HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_OFF); // Acceptance Filter Mode Register = off
960 HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_RESET); // Go into reset mode
961 HAL_WRITE_UINT32(CAN_CTRL_IER(info), 0); // disable all interrupts
962 HAL_WRITE_UINT32(CAN_CTRL_GSR(info), 0); // Clear Status register - clears error counters
965 // Perform platform/variant specific initialisation here.
966 // The variant/ platform should setup the pin configuration to support
969 HAL_LPC2XXX_INIT_CAN(CAN_CHAN_NO(info));
972 // If this is the first channel to initialize then we reset the CAN
973 // registers and setup the CAN I/O pins
975 #if CYGINT_IO_CAN_CHANNELS > 1
976 if (!lpc2xxx_global_can_info.init_cnt)
977 #endif // #if CYGINT_IO_CAN_CHANNELS > 1
979 lpc2xxx_can_accfilt_reset();
983 res = lpc2xxx_can_set_baud(chan, &config->baud); // set baudrate
984 // $$$$ enable receive interrupt?
985 HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_OPERATIONAL); // enter normal operating mode
988 // store new config values
990 if (config != &chan->config)
992 chan->config = *config;
999 //===========================================================================
1000 // Set baudrate of certain can channel
1001 //===========================================================================
1002 static bool lpc2xxx_can_set_baud(can_channel *chan, cyg_can_baud_rate_t *baudrate)
1007 CAN_DECLARE_INFO(chan);
1010 // Get bit timings from HAL because bit timings depend on sysclock
1011 // If the macro fills the canbtr value with 0 then the baudrate
1012 // is not supported and the function returns false
1014 HAL_LPC2XXX_GET_CAN_BR(*baudrate, canbtr);
1021 // Any modificatons to the baudrate register must be done while CAN
1022 // module is in reset mode. So we first set the CAN module in reset
1023 // mode, then we set baudrate and then we restore content of CANMOD
1026 HAL_READ_UINT32(CAN_CTRL_MOD(info), canmod); // backup canmod register
1027 HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_RESET); // Go into reset mode
1028 HAL_WRITE_UINT32(CAN_CTRL_BTR(info), canbtr); // write baudrate value
1029 HAL_WRITE_UINT32(CAN_CTRL_MOD(info), canmod); // restore previous value
1035 //===========================================================================
1036 // Lookup the device and return its handle
1037 //===========================================================================
1038 static Cyg_ErrNo lpc2xxx_can_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name)
1040 can_channel* chan = (can_channel*) (*tab)->priv;
1041 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
1044 chan->callbacks->can_init(chan);
1047 // If runtime acceptance filter configuration is supported then we only
1048 // configure RX ALL if the user selected the RX ALL setup in config utility
1050 #ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
1051 if (info->flags & INFO_FLAG_STARTUP_RX_ALL)
1052 #endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
1054 lpc2xxx_can_config_rx_all(chan);
1057 HAL_WRITE_UINT32(CAN_ACCFILT_AFMR, AFMR_ON); // Activate acceptance filter
1058 HAL_READ_UINT32(CAN_CTRL_IER(info), regval);
1059 regval = regval | IER_RX | CAN_MISC_INT; // enable all interrupts
1060 HAL_WRITE_UINT32(CAN_CTRL_IER(info), regval);
1066 #ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
1067 //===========================================================================
1068 // Setup LPC2XXX CAN module in a state where all message boxes are disabled
1069 // After this call it is possible to add single message buffers and filters
1070 //===========================================================================
1071 static void lpc2xxx_can_config_rx_none(can_channel *chan)
1073 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
1076 // Remove all acceptance filters
1077 // $$$$ maybe we should also abort any pending transfers and
1078 // disable receive interrupts ?
1080 lpc2xxx_can_accfilt_remove_all_ctrl_entries(info);
1081 info->flags &= ~INFO_FLAG_RX_ALL;
1082 #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
1083 lpc2xxx_can_accfilt_dbg_dump();
1088 //===========================================================================
1089 // Add one single message filter to acceptance filter
1090 //===========================================================================
1091 static bool lpc2xxx_can_add_rx_filter(lpc2xxx_can_info_t *info, cyg_can_filter *filter)
1095 res = lpc2xxx_can_accfilt_add(info, filter->msg.id, 0, filter->msg.ext);
1098 filter->handle = CYGNUM_CAN_MSGBUF_NA;
1100 #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
1101 lpc2xxx_can_accfilt_dbg_dump();
1105 #endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
1109 #ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
1110 //===========================================================================
1111 // Configure message buffers
1112 //===========================================================================
1113 static Cyg_ErrNo lpc2xxx_can_config_msgbuf(can_channel *chan, const void* buf, cyg_uint32* len)
1115 Cyg_ErrNo res = ENOERR;
1116 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
1117 cyg_can_msgbuf_cfg *msg_buf = (cyg_can_msgbuf_cfg *)buf;
1119 if (*len != sizeof(cyg_can_msgbuf_cfg))
1124 switch (msg_buf->cfg_id)
1127 // clear all message filters and remote buffers - prepare for message buffer
1130 case CYGNUM_CAN_MSGBUF_RESET_ALL :
1132 lpc2xxx_can_config_rx_none(chan);
1137 // setup driver for reception of all standard and extended messages
1139 case CYGNUM_CAN_MSGBUF_RX_FILTER_ALL :
1141 if (!(info->flags & INFO_FLAG_RX_ALL)) // if rx_all is enabled we do not need to do anything
1143 lpc2xxx_can_config_rx_all(chan); // setup RX all state
1149 // add single message filter, message with filter ID will be received
1151 case CYGNUM_CAN_MSGBUF_RX_FILTER_ADD :
1153 cyg_can_filter *filter = (cyg_can_filter*) buf;
1156 // if the acceptance filter is configured to receive all messages then
1157 // it is not allowed to add single message filters because then more
1158 // than one acceptance filter would receive the same CAN id
1160 if (info->flags & INFO_FLAG_RX_ALL)
1166 // try to allocate a free acceptance filter entry - if we have a free one
1167 // then we can prepare the acceptance filter table for reception of
1170 if (!lpc2xxx_can_add_rx_filter(info, filter))
1175 break; //CYGNUM_CAN_MSGBUF_RX_FILTER_ADD
1178 #ifdef CYGOPT_IO_CAN_REMOTE_BUF
1180 // Try to add a new RTR response message buffer for automatic
1181 // transmission of data frame on reception of a remote frame
1183 case CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD :
1185 // $$$$ TODO implement remote response buffers in software
1191 // write data into remote response buffer
1193 case CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE :
1195 // $$$$ TODO implement remote response buffers in software
1199 #endif // #ifdef CYGOPT_IO_CAN_REMOTE_BUF
1202 } // switch (buf->cfg_id)
1206 #endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
1209 //===========================================================================
1210 // Read state of CAN controller
1211 // The CAN state variable for each channel is modified by DSR so if we
1212 // read the state we need to lock DSRs to protect the data access
1213 //===========================================================================
1214 static cyg_can_state lpc2xxx_get_state(lpc2xxx_can_info_t *info)
1216 cyg_can_state result;
1219 result = info->state;
1220 cyg_drv_dsr_unlock();
1226 //===========================================================================
1227 // Set state of CAN controller
1228 // The CAN state variable for each channel is modified by DSR so if we
1229 // write the state we need to lock DSRs to protect the data access
1230 //===========================================================================
1231 static void lpc2xxx_set_state(lpc2xxx_can_info_t *info, cyg_can_state state)
1234 info->state = state;
1235 cyg_drv_dsr_unlock();
1239 //===========================================================================
1240 // Enter low power mode
1241 //===========================================================================
1242 static Cyg_ErrNo lpc2xxx_enter_lowpower_mode(can_channel *chan)
1245 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
1248 // Before we enter low power mode, we have to enable wake up interrupt
1249 // Normally this interrupt is always enabled so we do not need to do
1252 HAL_READ_UINT32(CAN_CTRL_MOD(info), regval);
1255 // Software can only set SM when RM in the CAN Mode register is 0
1257 if (regval & CANMOD_RESET)
1262 //regval &= CANMOD_SLEEP;
1263 lpc2xxx_set_state(info, CYGNUM_CAN_STATE_STANDBY);
1264 HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_SLEEP);
1269 //===========================================================================
1270 // Start CAN module - set CANMOD operational and enable all interrupts
1271 //===========================================================================
1272 static void lpc2xxx_start_module(can_channel *chan)
1275 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
1277 HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_OPERATIONAL);
1279 // The interrupt enable register is also modified by ISR and DSR so
1280 // we need to protect acces here
1283 HAL_READ_UINT32(CAN_CTRL_IER(info), regval);
1284 regval = regval | IER_RX | CAN_MISC_INT; // enable all interrupts
1285 HAL_WRITE_UINT32(CAN_CTRL_IER(info), regval);
1286 info->state = CYGNUM_CAN_STATE_ACTIVE;
1287 cyg_drv_isr_unlock();
1291 //===========================================================================
1293 //===========================================================================
1294 static void lpc2xxx_enter_reset_mode(can_channel *chan)
1296 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
1298 info->state = CYGNUM_CAN_STATE_STOPPED;
1299 HAL_WRITE_UINT32(CAN_CTRL_MOD(info), CANMOD_RESET);
1303 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS
1304 //===========================================================================
1305 // Add message filter group
1306 //===========================================================================
1307 static Cyg_ErrNo lpc2xxx_can_config_accfilt_group(can_channel *chan, const void* buf, cyg_uint32* len)
1310 cyg_can_filtergroup_cfg *filter_grp = (cyg_can_filtergroup_cfg *)buf;
1311 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
1314 if (*len != sizeof(cyg_can_filtergroup_cfg))
1319 if (filter_grp->lower_id_bound >= filter_grp->upper_id_bound)
1325 // if the acceptance filter is configured to receive all messages then
1326 // it is not allowed to add single message filter groups because then more
1327 // than one acceptance filter would receive the same CAN id
1329 if (info->flags & INFO_FLAG_RX_ALL)
1334 res = lpc2xxx_can_accfilt_add(info,
1335 filter_grp->lower_id_bound,
1336 filter_grp->upper_id_bound,
1339 #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
1340 lpc2xxx_can_accfilt_dbg_dump();
1342 return res ? ENOERR : -EPERM;
1344 #endif // CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS
1347 //===========================================================================
1348 // Change device configuration
1349 //===========================================================================
1350 static Cyg_ErrNo lpc2xxx_can_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
1352 Cyg_ErrNo res = ENOERR;
1357 // Setup a new CAN configuration. This will i.e. setup a new baud rate
1359 case CYG_IO_SET_CONFIG_CAN_INFO:
1361 cyg_can_info_t* config = (cyg_can_info_t*) buf;
1362 if (*len < sizeof(cyg_can_info_t))
1366 *len = sizeof(cyg_can_info_t);
1367 if (!lpc2xxx_can_config_channel(chan, config, false))
1374 #ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
1376 // configure message buffers
1378 case CYG_IO_SET_CONFIG_CAN_MSGBUF :
1380 res = lpc2xxx_can_config_msgbuf(chan, buf, len);
1383 #endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
1385 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS
1387 // Add message filter group to acceptance filter
1389 case CYG_IO_SET_CONFIG_LPC2XXX_ACCFILT_GROUP :
1391 return lpc2xxx_can_config_accfilt_group(chan, buf, len);
1394 #endif // CYGOPT_DEVS_CAN_LPC2XXX_EXTENDED_CFG_KEYS
1397 // Change CAN state of CAN module
1399 case CYG_IO_SET_CONFIG_CAN_MODE :
1401 cyg_can_mode *can_mode = (cyg_can_mode*) buf;
1403 if (*len != sizeof(cyg_can_mode))
1407 *len = sizeof(cyg_can_mode);
1410 // decide what to do according to mode
1415 // The controller does not support a stopped and standby state so we
1416 // simply enter the low power state here. This state is also safe for
1417 // message buffer configuration
1419 case CYGNUM_CAN_MODE_STOP : lpc2xxx_enter_reset_mode(chan); break;
1420 case CYGNUM_CAN_MODE_START : lpc2xxx_start_module(chan); break;
1421 case CYGNUM_CAN_MODE_STANDBY : lpc2xxx_enter_lowpower_mode(chan); break;
1422 case CYGNUM_CAN_MODE_CONFIG : lpc2xxx_enter_reset_mode(chan); break;
1425 break; // case CYG_IO_SET_CONFIG_CAN_MODE :
1427 // Unknown config key - indicate this by returning -EINVAL
1437 //===========================================================================
1438 // Query device configuration
1439 //===========================================================================
1440 static Cyg_ErrNo lpc2xxx_can_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
1442 Cyg_ErrNo res = ENOERR;
1443 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
1448 // query state of CAN controller
1450 case CYG_IO_GET_CONFIG_CAN_STATE :
1452 cyg_can_state *can_state = (cyg_can_state*) buf;
1454 if (*len != sizeof(cyg_can_state))
1458 *len = sizeof(cyg_can_state);
1459 *can_state = lpc2xxx_get_state(info);
1463 #ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
1465 // Query message box information - returns available and free message
1468 case CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO :
1470 cyg_can_msgbuf_info *mbox_info = (cyg_can_msgbuf_info*) buf;
1472 if (*len != sizeof(cyg_can_msgbuf_info))
1476 cyg_uint32 end_of_table;
1477 *len = sizeof(cyg_can_msgbuf_info);
1479 HAL_READ_UINT32(CAN_ACCFILT_ENDOFTABLE, end_of_table);
1480 mbox_info->count = LPC2XXX_CAN_MSG_FILTERS_MAX;
1481 mbox_info->free = (ACCFILT_RAM_SIZE - end_of_table) / ACCFILT_COMMON_ENTRY_SIZE;
1484 #endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
1488 // Query hardware description of FlexCAN device driver
1490 case CYG_IO_GET_CONFIG_CAN_HDI :
1492 cyg_can_hdi *hdi = (cyg_can_hdi *)buf;
1494 // comes from high level driver so we do not need to
1495 // check buffer size here
1497 hdi->support_flags = CYGNUM_CAN_HDI_FRAMETYPE_EXT_ACTIVE
1498 | CYGNUM_CAN_HDI_FULLCAN;
1510 //===========================================================================
1511 // Send single message
1512 //===========================================================================
1513 static bool lpc2xxx_can_putmsg(can_channel *chan, CYG_CAN_MSG_T *pmsg, void *pdata)
1516 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_USE_SELF_RECEPTION
1517 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *) chan->dev_priv;
1519 CAN_DECLARE_INFO(info);
1523 // We use only one single transmit buffer of the three available buffers
1524 // We use buffer 1 (buffer 2 and 3 are unused)
1526 // The errata sheet tells the following about the transmit buffers:
1527 // Problem: The Triple Transmit Buffer function cannot be used.
1528 // Work-around: Use any one Transmit buffer only (Use either Transmit Buffer 1,
1529 // Transmit Buffer 2 or Transmit Buffer 3 exclusively). The buffer you decided
1530 // to use should be loaded only when there is no pending transmission.
1532 HAL_READ_UINT32(CAN_CTRL_SR(info), regval);
1533 if (!(regval & SR_TX_BUF_WRITE_OK))
1538 regval = pmsg->dlc << 16;
1541 regval |= TFI_DLC_RTR;
1544 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
1547 regval |= TFI_DLC_EXT;
1549 #endif // #define CYGOPT_IO_CAN_EXT_CAN_ID
1550 HAL_WRITE_UINT32(CAN_CTRL_TFI1(info), regval); // write DLC
1551 HAL_WRITE_UINT32(CAN_CTRL_TID1(info), pmsg->id); // write ID
1552 HAL_WRITE_UINT32(CAN_CTRL_TDA1(info), pmsg->data.dwords[0]); // write first 4 data bytes
1553 HAL_WRITE_UINT32(CAN_CTRL_TDB1(info), pmsg->data.dwords[1]); // write second 4 data bytes
1556 // Request transmission of message
1557 // The errata sheet tells the following about tx request:
1558 // Introduction: The CAN module can lose arbitration to another CAN node during an
1559 // attempt to transmit a CAN message. The message of the CAN node the arbitration was
1560 // lost to is supposed to be received correctly by the CAN module.
1561 // Problem: Messages might not be received correctly if during a CAN Transmission the
1562 // CAN bus arbitration is lost to another CAN node.
1563 // Work-around: Use the Self Reception Request command instead of the Transmission
1564 // Request command. However, it has to be taken into account that now all transmitted
1565 // messages may be received if not prevented by appropriate Acceptance Filter settings.
1566 // (Don't set up Acceptance Filter Message Identifiers for the messages you are
1567 // transmitting yourself.)
1569 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_USE_SELF_RECEPTION
1571 regval = pmsg->id | (regval & LPC2XXX_CAN_INFO_LAST_TX_ID_FLMASK);
1573 // Save last message id to next last_tx_id
1574 info->last_tx_index = info->last_tx_index == 0 ? 1 : 0;
1575 info->last_tx_id[info->last_tx_index] = regval;
1577 // Write self transmission request
1578 HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_SELF_RX_REQ | CMR_SEND_TX_BUF1);
1580 // Write transmission request
1581 HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_TX_REQ | CMR_SEND_TX_BUF1);
1588 //===========================================================================
1589 // Read event from device driver
1590 //===========================================================================
1591 static bool lpc2xxx_can_getevent(can_channel *chan, CYG_CAN_EVENT_T *pevent, void *pdata)
1593 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
1596 cyg_uint32 event = *((cyg_uint32*)pdata);
1606 pevent->flags |= CYGNUM_CAN_EVENT_RX;
1607 HAL_READ_UINT32(CAN_CTRL_RFS(info), regval);
1608 HAL_READ_UINT32(CAN_CTRL_RID(info), id);
1610 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
1611 if (regval & RFS_EXT)
1613 pevent->msg.ext = CYGNUM_CAN_ID_EXT;
1614 pevent->msg.id = id & 0x1FFFFFFF;
1617 #endif // #define CYGOPT_IO_CAN_EXT_CAN_ID
1619 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
1620 pevent->msg.ext = CYGNUM_CAN_ID_STD;
1621 pevent->msg.id = id & 0x7FF;
1622 #endif // #ifdef CYGOPT_IO_CAN_STD_CAN_ID
1623 } // if (regval & RFS_EXT)
1625 if (regval & RFS_RTR)
1627 pevent->msg.rtr = CYGNUM_CAN_FRAME_RTR;
1631 pevent->msg.rtr = CYGNUM_CAN_FRAME_DATA;
1632 HAL_READ_UINT32(CAN_CTRL_RDA(info), pevent->msg.data.dwords[0]);
1633 HAL_READ_UINT32(CAN_CTRL_RDB(info), pevent->msg.data.dwords[1]);
1634 } //if (regval & RFS_RTR)
1635 pevent->msg.dlc = RFS_GET_DLC(regval);
1637 // Release the message buffer. Now this buffer can receive the next message
1639 HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_RX_RELEASE_BUF);
1642 // Now check if an data overrun occurred - a message was lost
1643 // because the preceding message to this CAN controller was not read
1644 // and released quickly enough. After reading the status we clear
1647 HAL_READ_UINT32(CAN_CTRL_GSR(info), regval);
1648 if (regval & GSR_DATA_OVR)
1650 pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX;
1651 HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_CLEAR_DATA_OVR);
1658 #ifndef CYGOPT_IO_CAN_TX_EVENT_SUPPORT
1659 if (event & ICR_TX1)
1661 pevent->flags |= CYGNUM_CAN_EVENT_TX;
1666 // Handle all other events
1668 if (event & (CAN_MISC_INT | ICR_LUT_ERR))
1670 HAL_READ_UINT32(CAN_CTRL_GSR(info), data.dword);
1673 // 1: Error Warning Interrupt -- this bit is set on every change (set or clear) of the Error
1674 // Status or Bus Status bit in CANSR, if the EIE bit in CAN is 1 at the time of the
1677 if (event & ICR_ERR_WARN)
1680 // If one of the warning counters is above 96 then the controller is in bus warning
1681 // state. If both counters are below 96 the this interrupt indicates that the
1682 // controller has left the bus warning state and is error active again
1684 if (data.bytes[2] >= 96)
1686 pevent->flags |= CYGNUM_CAN_EVENT_WARNING_RX;
1687 info->state = CYGNUM_CAN_STATE_BUS_WARN;
1689 else if (data.bytes[3] >= 96)
1691 pevent->flags |= CYGNUM_CAN_EVENT_WARNING_TX;
1692 info->state = CYGNUM_CAN_STATE_BUS_WARN;
1696 info->state = CYGNUM_CAN_STATE_ACTIVE;
1698 LPC2XXX_DBG_PRINT("ICR_ERR_WARN (%p)\n", (void*) chan);
1702 // 1: Wake-Up Interrupt: this bit is set if the CAN controller is sleeping and bus activity
1703 // is detected, if the WUIE bit in CANIE is 1.
1705 if (event & ICR_WAKE_UP)
1707 pevent->flags |= CYGNUM_CAN_EVENT_LEAVING_STANDBY;
1708 info->state = CYGNUM_CAN_STATE_ACTIVE;
1709 LPC2XXX_DBG_PRINT("ICR_WAKE_UP (%p)\n", (void*) chan);
1713 // Error Passive Interrupt -- this bit is set if the EPIE bit in CANIE is 1, and the CAN
1714 // controller switches between Error Passive and Error Active mode in either
1715 // direction. We have to check if the ERR bit is set in global status register.
1716 // If it is set, then it is a switch to error passive else it is a switch to
1717 // error active state
1719 if (event & ICR_ERR_PASSIVE)
1721 if (data.dword & GSR_ERR)
1723 pevent->flags |= CYGNUM_CAN_EVENT_ERR_PASSIVE;
1724 info->state = CYGNUM_CAN_STATE_ERR_PASSIVE;
1728 info->state = CYGNUM_CAN_STATE_ACTIVE;
1730 LPC2XXX_DBG_PRINT("ICR_ERR_PASSIVE (%p)\n", (void*) chan);
1733 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_ALIE
1735 // Arbitration Lost Interrupt -- this bit is set if the ALIE bit in CANIE is 1, and the
1736 // CAN controller loses arbitration while attempting to transmit.
1738 if (event & ICR_ARBITR_LOST)
1740 pevent->flags |= CYGNUM_CAN_EVENT_ARBITRATION_LOST;
1741 LPC2XXX_DBG_PRINT("ICR_ARBITR_LOST (%p)\n", (void*) chan);
1743 #endif // CYGOPT_DEVS_CAN_LPC2XXX_ALIE
1746 // 1: Bus Error Interrupt -- this bit is set if the BEIE bit in CANIE is 1, and the CAN
1747 // controller detects an error on the bus.
1749 if (event & ICR_BUS_ERR)
1751 pevent->flags |= CYGNUM_CAN_EVENT_BUS_OFF;
1752 LPC2XXX_DBG_PRINT("ICR_BUS_ERR (%p)\n", (void*) chan);
1755 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
1757 // LUT error interrupt -- this bit is set if bit 0 in LUTerr is 1 and LUTerrAd
1758 // points to entry in filter table for this CAN controller
1760 if(event & ICR_LUT_ERR)
1762 pevent->flags |= CYGNUM_CAN_EVENT_FILTER_ERR;
1763 LPC2XXX_DBG_PRINT("ICR_LUT_ERR (%p)\n", (void*) chan);
1765 #endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
1767 } // if (event & (CAN_MISC_INT | ICR_LUT_ERR))
1773 //===========================================================================
1775 //===========================================================================
1776 static void lpc2xxx_can_start_xmit(can_channel* chan)
1779 CAN_DECLARE_INFO(chan);
1781 LPC2XXX_DBG_PRINT("start_xmit (%p)\n", (void*) chan);
1784 HAL_READ_UINT32(CAN_CTRL_IER(info), regval);
1785 regval |= IER_TX1; // enable tx interrupt for tx buf 1
1786 HAL_WRITE_UINT32(CAN_CTRL_IER(info), regval);
1787 cyg_drv_dsr_unlock();
1792 chan->callbacks->xmt_msg(chan, 0); // Kick transmitter (if necessary)
1796 //===========================================================================
1798 //===========================================================================
1799 static void lpc2xxx_can_stop_xmit(can_channel* chan)
1802 CAN_DECLARE_INFO(chan);
1804 LPC2XXX_DBG_PRINT("stop_xmit (%p)\n", (void*) chan);
1807 HAL_READ_UINT32(CAN_CTRL_IER(info), regval);
1808 regval &= ~IER_TX1; // disable tx interrupt for tx buf 1
1809 HAL_WRITE_UINT32(CAN_CTRL_IER(info), regval);
1810 cyg_drv_dsr_unlock();
1814 #ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
1815 //===========================================================================
1816 // Low level transmit interrupt handler
1817 //===========================================================================
1818 static cyg_uint32 lpc2xxx_can_tx_ISR(cyg_vector_t vector, cyg_addrword_t data)
1821 // Now read input capture register - this clears all interrupt bits in this
1822 // register and also acknowledges the interrupt - any further processing is done
1825 cyg_drv_interrupt_mask(vector);
1826 cyg_drv_interrupt_acknowledge(vector);
1827 LPC2XXX_DBG_PRINT("tx_ISR (%p)\n", (void*) data);
1828 return CYG_ISR_CALL_DSR;
1832 //===========================================================================
1833 // High level transmit interrupt handler
1834 //===========================================================================
1835 static void lpc2xxx_can_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
1837 can_channel *chan = (can_channel *)data;
1839 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
1842 // First read the ICR register to acknowledge all interrupts and
1843 // get all captured interrupts
1845 HAL_READ_UINT32(CAN_CTRL_ICR(info), regval);
1848 // If TX events are supported then only call the rcv_event() callback
1849 // if any other event occurred - pass the event field to the getevent function
1850 // to indicate the events
1852 #ifndef CYGOPT_IO_CAN_TX_EVENT_SUPPORT
1853 if (regval & ~ICR_TX1)
1856 chan->callbacks->rcv_event(chan, ®val);
1860 // Now transmit next message and reenable interrupts
1862 chan->callbacks->xmt_msg(chan, 0); // send next message
1863 LPC2XXX_DBG_PRINT("tx_DSR (%p)\n", (void*) data);
1864 cyg_drv_interrupt_unmask(vector);
1868 //===========================================================================
1869 // Low level receive interrupt handler
1870 //===========================================================================
1871 static cyg_uint32 lpc2xxx_can_rx_ISR(cyg_vector_t vector, cyg_addrword_t data)
1873 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_USE_SELF_RECEPTION
1875 can_channel* chan = (can_channel*)data;
1876 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *) chan->dev_priv;
1880 // We have to reject self tx message, so read message id
1881 HAL_READ_UINT32(CAN_CTRL_RID(info), id);
1882 HAL_READ_UINT32(CAN_CTRL_RFS(info), regval);
1883 id |= (regval & LPC2XXX_CAN_INFO_LAST_TX_ID_FLMASK);
1886 for(index = 0; index < 2; index++)
1888 if(id == info->last_tx_id[index])
1891 info->last_tx_id[index] = LPC2XXX_CAN_INFO_LAST_TX_ID_NOVALID;
1893 // Clear receive buffer
1894 HAL_WRITE_UINT32(CAN_CTRL_CMR(info), CMR_RX_RELEASE_BUF);
1896 // Acknowledge a vector
1897 cyg_drv_interrupt_acknowledge(vector);
1899 // Exit without calling DSR
1900 LPC2XXX_DBG_PRINT("self_rx_ISR (%p)\n", (void*) data);
1901 return CYG_ISR_HANDLED;
1907 // The ISR only disables and acknowledges the RX interrupt
1908 // any further processing is done by DSR. We also need to mask the
1909 // global CAN status interrupt here because the interrupt flag
1910 // in ICR is not cleared yet and may still cause a status
1913 cyg_drv_interrupt_mask(vector);
1914 cyg_drv_interrupt_acknowledge(vector);
1915 LPC2XXX_DBG_PRINT("rx_ISR (%p)\n", (void*) data);
1917 return CYG_ISR_CALL_DSR;
1921 //===========================================================================
1922 // High level receive interrupt handler
1923 //===========================================================================
1924 static void lpc2xxx_can_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
1926 can_channel *chan = (can_channel *)data;
1927 cyg_uint32 icr = ICR_RX;
1930 // Read the event, the receive buffer will be released by the
1931 // get_event() function
1933 chan->callbacks->rcv_event(chan, &icr);
1934 LPC2XXX_DBG_PRINT("rx_DSR (%p)\n", (void*) data);
1935 cyg_drv_interrupt_unmask(vector);
1940 //===========================================================================
1941 // status ISR handler
1942 //===========================================================================
1943 static cyg_uint32 lpc2xxx_can_ISR(cyg_vector_t vector, cyg_addrword_t data)
1946 // Acknowledge and disable the interrupt - any further processing is
1949 cyg_drv_interrupt_mask(vector);
1950 cyg_drv_interrupt_acknowledge(vector);
1951 LPC2XXX_DBG_PRINT("err_ISR\n");
1952 return CYG_ISR_CALL_DSR;
1956 //===========================================================================
1957 // status ISR handler
1958 //===========================================================================
1959 static void lpc2xxx_can_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
1961 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
1962 // If we use acceptance filter we can get LUT error
1964 cyg_uint8 luterr_chan0 = 0; // Init to avoid warnings
1965 cyg_uint8 luterr_chan1 = 0; // Init to avoid warnings
1967 // Read LUT error flag
1968 HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR, luterr);
1976 // Read address of failed entry (it clears interrupt flag)
1977 HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR_ADDR, lutaddr);
1979 // Read address of extended id individual table
1980 HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, eff_sa);
1983 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + lutaddr, errentry.dword);
1985 // If err entry from standard id tables then read two
1986 // controllers numbers
1987 if(lutaddr < eff_sa)
1989 // Calc CAN controllers numbers
1990 luterr_chan0 = (cyg_uint8) ACCFILT_STD_GET_CTRL_UPPER(errentry.dword);
1992 if(errentry.column.lower & ACCFILT_STD_DIS)
1994 luterr_chan1 = luterr_chan0;
1998 luterr_chan1 = (cyg_uint8) ACCFILT_STD_GET_CTRL_LOWER(errentry.dword);
2003 // Calc CAN controller number
2004 luterr_chan0 = luterr_chan1 = (cyg_uint8) ACCFILT_EXT_GET_CTRL(errentry.dword);
2007 #endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
2010 // Loop through all channels - we need to do this only if we have more
2011 // than one channel so we can optimize here for single channel
2013 #if CYGINT_IO_CAN_CHANNELS > 1
2015 while (lpc2xxx_global_can_info.active_channels[i])
2019 can_channel *chan = LPC2XXX_GET_CAN_CHANNEL(lpc2xxx_global_can_info, i++);
2020 CAN_DECLARE_INFO(chan);
2022 HAL_READ_UINT32(CAN_CTRL_ICR(info), regval);
2023 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
2024 // Set ICR_LUT_ERR flag only for controller which cause LUT error
2025 if ((luterr & 1) && ((luterr_chan0 == i) || (luterr_chan1 == i)))
2027 regval |= ICR_LUT_ERR;
2029 #endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
2030 regval &= CAN_MISC_INT; // don't care about RX and TX events here
2033 chan->callbacks->rcv_event(chan, ®val);
2035 } // while (lpc2xxx_global_can_info.active_channels[i])
2037 LPC2XXX_DBG_PRINT("err_DSR\n");
2038 cyg_drv_interrupt_unmask(vector);
2040 #else // #ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
2043 //===========================================================================
2044 // Global CAN interrupt handler
2045 //===========================================================================
2046 static cyg_uint32 lpc2xxx_can_ISR(cyg_vector_t vector, cyg_addrword_t data)
2049 // Disable interrupts, the DSR will enable it as soon as it processed
2050 // the current interrupt
2052 cyg_drv_interrupt_mask(vector);
2053 cyg_drv_interrupt_acknowledge(vector);
2054 LPC2XXX_DBG_PRINT("CAN_ISR\n");
2055 return CYG_ISR_CALL_DSR;
2058 //===========================================================================
2060 //===========================================================================
2061 static void lpc2xxx_can_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
2063 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
2064 // If we use acceptance filter we can get LUT error
2066 cyg_uint8 luterr_chan0 = 0xFF; // Init to avoid warnings
2067 cyg_uint8 luterr_chan1 = 0xFF; // Init to avoid warnings
2069 // Read LUT error flag
2070 HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR, luterr);
2078 // Read address of failed entry (it clears interrupt flag)
2079 HAL_READ_UINT32(CAN_ACCFILT_LUT_ERR_ADDR, lutaddr);
2081 // Read address of extended id individual table
2082 HAL_READ_UINT32(CAN_ACCFILT_EFF_SA, eff_sa);
2085 HAL_READ_UINT32(CAN_ACCFILT_RAM_BASE + lutaddr, errentry.dword);
2087 // If errentry from standard id tables then read two controllers numbers
2088 if(lutaddr < eff_sa)
2090 // Calc CAN controllers numbers
2091 luterr_chan0 = (cyg_uint8) ACCFILT_STD_GET_CTRL_UPPER(errentry.dword);
2093 if(errentry.column.lower & ACCFILT_STD_DIS)
2095 luterr_chan1 = luterr_chan0;
2099 luterr_chan1 = (cyg_uint8) ACCFILT_STD_GET_CTRL_LOWER(errentry.dword);
2104 // Calc CAN controller number
2105 luterr_chan0 = luterr_chan1 = (cyg_uint8) ACCFILT_EXT_GET_CTRL(errentry.dword);
2108 #endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
2111 // Walk through list of active CAN channels and process interrupts
2112 // of all channels - we need to loop only if we have more than one CAN channel so
2113 // we can optimize for single CAN channel here
2115 #if CYGINT_IO_CAN_CHANNELS > 1
2117 while (lpc2xxx_global_can_info.active_channels[i])
2118 #endif // CYGINT_IO_CAN_CHANNELS > 1
2121 can_channel *chan = LPC2XXX_GET_CAN_CHANNEL(lpc2xxx_global_can_info, i++);
2122 CAN_DECLARE_INFO(chan);
2124 HAL_READ_UINT32(CAN_CTRL_ICR(info), icr); // this read clears ICR
2125 #ifdef CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
2126 // Set ICR_LUT_ERR flag only for controller which cause LUT error
2127 if ((luterr_chan0 == i) || (luterr_chan1 == i))
2131 #endif // CYGOPT_DEVS_CAN_LPC2XXX_LUT_ERR_SUPP
2133 // If TX events are supported then we simply call the rcv_event()
2134 // callback to store the event. If TX events are not supported then
2135 // we only call the rcv_event() function if any other interrupt than
2136 // the TX interrupt was captured
2138 #ifndef CYGOPT_IO_CAN_TX_EVENT_SUPPORT
2140 #endif // CYGOPT_IO_CAN_TX_EVENT_SUPPORT
2142 chan->callbacks->rcv_event(chan, &icr);
2145 // If this was an TX interrupt then transmit next message now
2149 chan->callbacks->xmt_msg(chan, 0); // send next message
2151 } // while (lpc2xxx_global_can_info.active_channels[i])
2152 LPC2XXX_DBG_PRINT("CAN_DSR\n");
2153 cyg_drv_interrupt_unmask(vector);
2155 #endif // #ifndef CYGNUM_DEVS_CAN_LPC2XXX_INT_PRIORITY
2158 #ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
2159 //===========================================================================
2160 // Configure message boxes for reception of any CAN message
2161 //===========================================================================
2162 static void lpc2xxx_can_config_rx_all(can_channel *chan)
2164 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
2166 // First clear all acceptance filter entries and then insert the
2167 // two RX all groups
2169 lpc2xxx_can_config_rx_none(chan);
2170 #ifdef CYGOPT_IO_CAN_STD_CAN_ID
2171 lpc2xxx_can_accfilt_add(info, 0x000, 0x7FF, CYGNUM_CAN_ID_STD);
2172 #endif // CYGOPT_IO_CAN_STD_CAN_ID
2173 #ifdef CYGOPT_IO_CAN_EXT_CAN_ID
2174 lpc2xxx_can_accfilt_add(info, 0x000, 0x1FFFFFFF, CYGNUM_CAN_ID_EXT);
2175 #endif // CYGOPT_IO_CAN_EXT_CAN_ID
2177 info->flags |= INFO_FLAG_RX_ALL;
2178 #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
2179 lpc2xxx_can_accfilt_dbg_dump();
2180 #endif // CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
2182 #endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
2185 #ifndef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
2186 //===========================================================================
2187 // Configure message boxes for reception of any CAN message
2188 //===========================================================================
2189 static void lpc2xxx_can_config_rx_all(can_channel *chan)
2191 lpc2xxx_can_info_t *info = (lpc2xxx_can_info_t *)chan->dev_priv;
2193 lpc2xxx_can_accfilt_simple_rx_all();
2194 info->flags |= INFO_FLAG_RX_ALL;
2196 #ifdef CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
2197 lpc2xxx_can_accfilt_dbg_dump();
2198 #endif // CYGDBG_DEVS_CAN_LPC2XXX_DEBUG
2200 #endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
2203 //---------------------------------------------------------------------------
2204 // EOF can_lpc2xxx.c