OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [can/] [arm/] [at91/] [at91sam7/] [current/] [src/] [can_at91sam7.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      devs/can/arm/at91sam7x/current/src/can_at91sam7x.c
4
//
5
//      CAN driver for Atmel AT91SAM7X microcontrollers
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    Uwe Kindler
43
// Contributors: Uwe Kindler
44
// Date:         2007-01-06
45
// Purpose:      Support at91sam7 on-chip CAN moduls
46
// Description: 
47
//
48
//####DESCRIPTIONEND####
49
//
50
//==========================================================================
51
 
52
 
53
//==========================================================================
54
//                              INCLUDES
55
//==========================================================================
56
#include <pkgconf/system.h>
57
#include <pkgconf/io_can.h>
58
#include <pkgconf/io.h>
59
#include <pkgconf/devs_can_at91sam7.h>
60
 
61
#include <cyg/infra/diag.h>
62
 
63
#include <cyg/io/io.h>
64
#include <cyg/io/devtab.h>
65
#include <cyg/io/can.h>
66
 
67
#include <cyg/hal/hal_arch.h>
68
#include <cyg/hal/hal_intr.h>
69
#include <cyg/hal/hal_io.h>
70
 
71
#include <cyg/hal/hal_diag.h>
72
#include <cyg/infra/cyg_ass.h>
73
 
74
 
75
//===========================================================================
76
//                                DEFINES  
77
//===========================================================================
78
 
79
//
80
// Support debug output if this option is enabled in CDL file
81
//
82
#ifdef CYGDBG_DEVS_CAN_AT91SAM7_DEBUG
83
#define AT91SAM7_DBG_PRINT diag_printf
84
#else
85
#define AT91SAM7_DBG_PRINT( fmt, ... )
86
#endif
87
 
88
 
89
//
90
// we define our own set of register bits in order to be independent from
91
// platform specific names
92
//
93
 
94
//---------------------------------------------------------------------------
95
// Mailbox bits
96
//
97
#define BIT_MB0            (0x01 << 0)
98
#define BIT_MB1            (0x01 << 1)
99
#define BIT_MB2            (0x01 << 2)
100
#define BIT_MB3            (0x01 << 3)
101
#define BIT_MB4            (0x01 << 4)
102
#define BIT_MB5            (0x01 << 5)
103
#define BIT_MB6            (0x01 << 6)
104
#define BIT_MB7            (0x01 << 7)
105
 
106
 
107
//---------------------------------------------------------------------------
108
// CAN Mode Register bits (CAN_MR)
109
//
110
#define MR_CAN_ENABLE      (0x01 << 0)
111
#define MR_LOW_POWER       (0x01 << 1)
112
#define MR_AUTOBAUD        (0x01 << 2)
113
#define MR_OVERLOAD        (0x01 << 3)
114
#define MR_TIMESTAMP_EOF   (0x01 << 4)
115
#define MR_TIME_TRIG       (0x01 << 5)
116
#define MR_TIMER_FREEZE    (0x01 << 6)
117
#define MR_DISABLE_REPEAT  (0x01 << 7)
118
 
119
 
120
//---------------------------------------------------------------------------
121
// CAN Interrupt Enable/Disable, Mask and Status Register bits (CAN_IER, CAN_IDR, CAN_IMR)
122
//
123
#define INT_ERR_ACTIVE     (0x01 << 16)
124
#define INT_WARN           (0x01 << 17)
125
#define INT_ERR_PASSIVE    (0x01 << 18)
126
#define INT_BUS_OFF        (0x01 << 19)
127
#define INT_SLEEP          (0x01 << 20)
128
#define INT_WAKEUP         (0x01 << 21)
129
#define INT_TMR_OVF        (0x01 << 22)
130
#define INT_TIMESTAMP      (0x01 << 23)
131
#define INT_CRC_ERR        (0x01 << 24)
132
#define INT_STUFF_ERR      (0x01 << 25)
133
#define INT_ACKN_ERR       (0x01 << 26)
134
#define INT_FORM_ERR       (0x01 << 27)
135
#define INT_BIT_ERR        (0x01 << 28)
136
#define INT_MB              0xFF        // message box intterupt (mbox 1 - 8)
137
#define INT_MB_RX           0x7F        // rx message box interrupts
138
#define INT_MB_TX           0x80        // tx message box interrupts
139
 
140
//
141
// We do not enable INT_WARN by default because this flug is buggy and causes interrupts
142
// event if no counter reached warning level.
143
//
144
#define INT_ALL_ERR        (INT_CRC_ERR | INT_STUFF_ERR | INT_ACKN_ERR | INT_FORM_ERR | INT_BIT_ERR)
145
#define INT_DEFAULT        (INT_ERR_PASSIVE | INT_BUS_OFF | INT_SLEEP | INT_WAKEUP | INT_ALL_ERR)
146
 
147
 
148
//
149
// these bits are only in status register (CAN_SR)
150
//
151
#define SR_RX_BUSY         (0x01 << 29)
152
#define SR_TX_BUSY         (0x01 << 30)
153
#define SR_OVL_BUSY        (0x01 << 31)
154
 
155
 
156
//---------------------------------------------------------------------------
157
// CAN Baudrate Register (CAN_BR)
158
//
159
#define BR_PHASE2_BITMASK  0x00000007
160
#define BR_PHASE1_BITMASK  0x00000070
161
#define BR_PROPAG_BITMASK  0x00000700
162
#define BR_SJW_BITMASK     0x00003000
163
#define BR_BRP_BITMASK     0x007F0000
164
#define BR_SMP_BITMASK     0x01000000
165
 
166
 
167
//---------------------------------------------------------------------------
168
// CAN Error Counter Register (CAN_ECR)
169
//
170
#define ECR_GET_TEC(_ecr_) (((_ecr_) >> 16) & 0xFF)
171
#define ECR_GET_REC(_ecr_) ((_ecr_) & 0xFF)
172
 
173
 
174
//---------------------------------------------------------------------------
175
// CAN Transfer Command Resgister (CAN_TCR)
176
//
177
#define TCR_TMR_RESET      0x80000000
178
 
179
 
180
//---------------------------------------------------------------------------
181
// CAN Message Mode Register (CAN_MMRx)
182
//
183
#define MMR_TIMEMARK_BITMASK 0x0000FFFF
184
#define MMR_PRIOR_BITMASK    0x000F0000
185
 
186
#define MMR_MB_SHIFTER       24
187
#define MMR_MB_TYPE_BITMASK  (0x07 << MMR_MB_SHIFTER) // mask the mot bits
188
#define MMR_MB_TYPE_DISABLED (0x00 << MMR_MB_SHIFTER) // message box disabled
189
#define MMR_MB_TYPE_RX       (0x01 << MMR_MB_SHIFTER) // rx message box
190
#define MMR_MB_TYPE_RX_OVW   (0x02 << MMR_MB_SHIFTER) // rx message box with overwrite
191
#define MMR_MB_TYPE_TX       (0x03 << MMR_MB_SHIFTER) // tx message box
192
#define MMR_MB_TYPE_CONSUME  (0x04 << MMR_MB_SHIFTER) // consumer - receives RTR and sends its content
193
#define MMR_MB_TYPE_PRODUCE  (0x05 << MMR_MB_SHIFTER) // producer - sends a RTR and waits for answer
194
#define MMR_MB_GET_TYPE(_mb_) ((_mb_) &  MMR_MB_TYPE_BITMASK)
195
 
196
//---------------------------------------------------------------------------
197
// CAN Message Acceptance Mask/ID Register (CAN_MAMx, CAN_MIDx)
198
//
199
#define MID_MIDvB_BITMASK    0x0003FFFF
200
#define MID_MIDvA_BITMASK    0x1FFC0000
201
#define MID_MIDE             0x20000000
202
#define MID_MIDvA_SHIFTER    18
203
#define MID_SET_STD(_id_)    (((_id_) << MID_MIDvA_SHIFTER) & MID_MIDvA_BITMASK)
204
#define MID_SET_EXT(_id_)    ((_id_) | MID_MIDE)
205
#define MAM_SET_STD          ((((0x7FF << MID_MIDvA_SHIFTER) & MID_MIDvA_BITMASK) | MID_MIDE))
206
#define MAM_SET_EXT          0xFFFFFFFF
207
#define MID_GET_STD(_mid_)   (((_mid_) >> MID_MIDvA_SHIFTER) &  CYG_CAN_STD_ID_MASK)
208
#define MID_GET_EXT(_mid_)   ((_mid_) & CYG_CAN_EXT_ID_MASK)
209
 
210
 
211
//---------------------------------------------------------------------------
212
// CAN Message Status Register (CAN_MSRx)
213
//
214
#define MSR_TIMESTAMP      0x0000FFFF
215
#define MSR_DLC            0x000F0000
216
#define MSR_RTR            0x00100000
217
#define MSR_MSG_ABORT      0x00400000
218
#define MSR_RDY            0x00800000
219
#define MSR_MSG_IGNORED    0x01000000
220
#define MSR_DLC_SHIFTER    16
221
#define MSR_DLC_GET(_msr_) (((_msr_) >> 16) & 0x0F)
222
 
223
//---------------------------------------------------------------------------
224
// CAN Message Control Register (CAN_MCRx)
225
//
226
#define MCR_DLC          0x000F0000 // MDLC
227
#define MCR_RTR          0x00100000 // MRTR
228
#define MCR_MSG_ABORT    0x00400000 // MACR
229
#define MCR_TRANSFER_CMD 0x00800000 // MTCR
230
#define MCR_DLC_SHIFTER 16
231
#define MCR_DLC_CREATE(_len_) ((_len_) << MCR_DLC_SHIFTER)
232
 
233
//---------------------------------------------------------------------------
234
// CAN Module Register Layout
235
//
236
#define CANREG_MR         0x0000
237
#define CANREG_IER        0x0004
238
#define CANREG_IDR        0x0008
239
#define CANREG_IMR        0x000C
240
#define CANREG_SR         0x0010
241
#define CANREG_BR         0x0014
242
#define CANREG_TIM        0x0018
243
#define CANREG_TIMESTAMP  0x001C
244
#define CANREG_ECR        0x0020
245
#define CANREG_TCR        0x0024
246
#define CANREG_ACR        0x0028
247
 
248
#define CANREG_MB_BASE    0x0200
249
 
250
//
251
// Register layout of message box relativ to base register of a certain
252
// message box
253
//
254
#define CANREG_MMR     0x0000
255
#define CANREG_MAM     0x0004
256
#define CANREG_MID     0x0008
257
#define CANREG_MFID    0x000C
258
#define CANREG_MSR     0x0010
259
#define CANREG_MDL     0x0014
260
#define CANREG_MDH     0x0018
261
#define CANREG_MCR     0x001C
262
 
263
 
264
#define AT91SAM7_CAN_PERIPHERAL_ID 15
265
#define CAN_MBOX_MIN                0
266
#define CAN_MBOX_MAX                7
267
#define CAN_MBOX_CNT                8
268
#define CAN_MBOX_RX_MIN             0
269
#define CAN_MBOX_RX_MAX             (CAN_MBOX_MAX - 1) // one message box is tx
270
#define CAN_MBOX_RX_CNT             (CAN_MBOX_CNT - 1) // one message box is tx 
271
 
272
#define CAN_MR(_extra_)         (CAN_BASE(_extra_) + CANREG_MR)
273
#define CAN_IER(_extra_)        (CAN_BASE(_extra_) + CANREG_IER)
274
#define CAN_IDR(_extra_)        (CAN_BASE(_extra_) + CANREG_IDR)
275
#define CAN_IMR(_etxra_)        (CAN_BASE(_extra_) + CANREG_IMR)
276
#define CAN_SR(_etxra_)         (CAN_BASE(_extra_) + CANREG_SR)
277
#define CAN_BR(_etxra_)         (CAN_BASE(_extra_) + CANREG_BR)
278
#define CAN_TIM(_etxra_)        (CAN_BASE(_extra_) + CANREG_TIM)
279
#define CAN_TIMESTAMP(_etxra_)  (CAN_BASE(_extra_) + CANREG_TIMESTAMP)
280
#define CAN_ECR(_etxra_)        (CAN_BASE(_extra_) + CANREG_ECR)
281
#define CAN_TCR(_etxra_)        (CAN_BASE(_extra_) + CANREG_TCR)
282
#define CAN_ACR(_etxra_)        (CAN_BASE(_extra_) + CANREG_ACR) 
283
 
284
//
285
// Message box registers
286
//
287
#define CAN_MB_BASE(_extra_)       (CAN_BASE(_extra_) + CANREG_MB_BASE)
288
#define CAN_MB_MMR(_extra_, _mb_)  (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MMR)
289
#define CAN_MB_MAM(_extra_, _mb_)  (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MAM)
290
#define CAN_MB_MID(_extra_, _mb_)  (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MID)
291
#define CAN_MB_MFID(_extra_, _mb_) (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MFID)
292
#define CAN_MB_MSR(_extra_, _mb_)  (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MSR)
293
#define CAN_MB_MDL(_extra_, _mb_)  (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MDL)
294
#define CAN_MB_MDH(_extra_, _mb_)  (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MDH)
295
#define CAN_MB_MCR(_extra_, _mb_)  (CAN_MB_BASE(_extra_) + 0x0020 * (_mb_) + CANREG_MCR)
296
 
297
 
298
//---------------------------------------------------------------------------
299
// Optimize for the case of a single CAN channel, while still allowing
300
// multiple channels. At the moment only AT91SAM7 controllers with one
301
// CAN channel are known.
302
//
303
#if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1
304
 
305
#define CAN_PID(_extra_)            AT91SAM7_CAN_PERIPHERAL_ID
306
#define CAN_ISRVEC(_extra_)         CAN_PID(_extra_)
307
#define CAN_ISRPRIO(_extra_)        CYGNUM_DEVS_CAN_AT91SAM7_CAN0_ISR_PRIORITY
308
#define CAN_BASE(_extra_)           AT91_CAN
309
#define CAN_DECLARE_INFO(_chan_)
310
#define CAN_MBOX_TX(_extra_)        CYGNUM_DEVS_CAN_AT91SAM7_CAN0_DEFAULT_TX_MBOX
311
#define CAN_MBOX_STD_CNT(_extra_)   CYGNUM_DEVS_CAN_AT91SAM7_CAN0_STD_MBOXES
312
#define CAN_MBOX_EXT_CNT(_extra_)   CYGNUM_DEVS_CAN_AT91SAM7_CAN0_EXT_MBOXES
313
#define CAN_MBOX_RX_ALL_CNT(_extra) (CAN_MBOX_STD_CNT(_extra_) + CAN_MBOX_EXT_CNT(_extra_))
314
 
315
#ifndef CYGNUM_DEVS_CAN_AT91SAM7_CAN0_STD_MBOXES
316
#define CYGNUM_DEVS_CAN_AT91SAM7_CAN0_STD_MBOXES 0
317
#endif
318
 
319
#ifndef CYGNUM_DEVS_CAN_AT91SAM7_CAN0_EXT_MBOXES
320
#define CYGNUM_DEVS_CAN_AT91SAM7_CAN0_EXT_MBOXES 0
321
#endif
322
 
323
#else  // #if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1
324
 
325
#define CAN_PID(_extra_)            ((_extra_)->isrvec)
326
#define CAN_ISRVEC(_extra_)         ((_extra_)->isrvec)
327
#define CAN_ISRPRIO(_extra_)        ((_extra_)->isrprio)
328
#define CAN_BASE(_extra_)           ((_extra_)->base)
329
#define CAN_DECLARE_INFO(_chan_)    at91sam7_can_info_t *info = (at91sam7_can_info_t *)chan->dev_priv;
330
#define CAN_MBOX_TX(_extra_)        7 // normally it is always the last mailbox
331
#define CAN_MBOX_STD_CNT(_extra_)   ((_extra_)->mboxes_std_cnt)
332
#define CAN_MBOX_EXT_CNT(_extra_)   ((_extra_)->mboxes_ext_cnt)
333
#define CAN_MBOX_RX_ALL_CNT(_extra) ((_extra_)->mboxes_rx_all_cnt)
334
 
335
#endif // #if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1
336
 
337
 
338
//===========================================================================
339
//                              DATA TYPES
340
//===========================================================================
341
typedef struct at91sam7_can_info_t
342
{
343
    cyg_interrupt      interrupt;
344
    cyg_handle_t       interrupt_handle;
345
    cyg_uint32         stat;             // buffers status register value between ISR and DSR
346
    cyg_uint8          free_mboxes;      // number of free message boxes for msg filters and rtr buffers
347
    bool               rx_all;           // true if reception of call can messages is active
348
    cyg_can_state      state;            // state of CAN controller      
349
 
350
#if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS > 1
351
    cyg_uint32         base;             // Per-bus h/w details
352
    cyg_uint8          isrpri;           // ISR priority
353
    cyg_uint8          isrvec;           // ISR vector (peripheral id)
354
    cyg_uint8          mboxes_std_cnt;   // contains number of standard message boxes available
355
    cyg_uint8          mboxes_ext_cnt;   // number of message boxes with ext id
356
    cyg_uint8          mboxes_rx_all_cnt;// number of all available mboxes
357
#endif
358
} at91sam7_can_info_t;
359
 
360
 
361
//
362
// at91sam7 info initialisation
363
//
364
#if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS > 1
365
#define AT91SAM7_CAN_INFO(_l, _base, _isrpri, _isrvec, _std_mboxes, _ext_mboxes) \
366
at91sam7_can_info_t _l {                                                         \
367
    state             : CYGNUM_CAN_STATE_STOPPED,                                \
368
    base              : (_base),                                                 \
369
    isrpri            : (_isrpri),                                               \
370
    isrvec            : (_isrvec),                                               \
371
    mboxes_std_cnt    : (_std_mboxes),                                           \
372
    mboxes_ext_cnt    : (_ext_mboxes),                                           \
373
    mboxes_rx_all_cnt : ((_std_mboxes) + (_ext_mboxes)),                         \
374
};
375
#else
376
#define AT91SAM7_CAN_INFO(_l)              \
377
at91sam7_can_info_t _l = {                 \
378
    state      : CYGNUM_CAN_STATE_STOPPED, \
379
};
380
#endif
381
 
382
 
383
//===========================================================================
384
//                          GLOBAL DATA
385
//===========================================================================
386
#if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS > 1
387
//
388
// ToDo - Initialisation of individual CAN channels if more than one channel
389
// is supported
390
//
391
#else // CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1
392
//
393
// Only one single CAN channel supported by SAM7 chip
394
//
395
AT91SAM7_CAN_INFO(at91sam7_can0_info);
396
#endif
397
 
398
 
399
//===========================================================================
400
//                          LOCAL DATA
401
//===========================================================================
402
//
403
// Macro for creation of CAN_BR value for baudrate tbl
404
//
405
 
406
#define CAN_BR_TBL_ENTRY(_brp_, _propag_, _phase1_, _phase2_, _sjw_) \
407
   ((_brp_ << 16) | (_propag_ << 8) | (_phase2_) | (_phase1_ << 4) | (_sjw_ << 12))
408
 
409
//
410
// Table with register values for baudrates at main clock of 48 MHz
411
//
412
static const cyg_uint32 at91sam7_br_tbl[] =
413
{
414
    CAN_BR_TBL_ENTRY(0xef, 0x07, 0x07, 0x02, 0), // 10  kbaud
415
    CAN_BR_TBL_ENTRY(0x95, 0x04, 0x07, 0x01, 0), // 20  kbaud
416
    CAN_BR_TBL_ENTRY(0x3b, 0x04, 0x07, 0x01, 0), // 50  kbaud
417
    CAN_BR_TBL_ENTRY(0x1d, 0x04, 0x07, 0x01, 0), // 100 kbaud
418
    CAN_BR_TBL_ENTRY(0x17, 0x04, 0x07, 0x01, 0), // 125 kbaud
419
    CAN_BR_TBL_ENTRY(0x0b, 0x04, 0x07, 0x01, 0), // 250 kbaud
420
    CAN_BR_TBL_ENTRY(0x05, 0x04, 0x07, 0x01, 0), // 500 kbaud
421
    CAN_BR_TBL_ENTRY(0x03, 0x03, 0x07, 0x01, 0), // 800 kbaud
422
    CAN_BR_TBL_ENTRY(0x02, 0x04, 0x07, 0x01, 0), // 1000 kbaud
423
    CAN_BR_TBL_ENTRY(0x00, 0x00, 0x00, 0x00, 0), // Autobaud
424
};
425
 
426
//
427
// Macro fills baudrate register value depending on selected baudrate
428
// For a standard AT91 clock speed of 48 MHz we provide a pre calculated
429
// baudrate table. If the board uses another clock speed, then the platform 
430
// HAL needs to provide an own HAL_AT91SAM7_GET_CAN_BR() macro that returns 
431
// valid baudrate register values
432
//
433
#ifdef CYGNUM_HAL_ARM_AT91_CLOCK_SPEED_48000000
434
#define HAL_AT91SAM7_GET_CAN_BR(_baudrate_, _br_)                \
435
CYG_MACRO_START                                                  \
436
    _br_ = at91sam7_br_tbl[(_baudrate_) - CYGNUM_CAN_KBAUD_10];  \
437
CYG_MACRO_END
438
#endif
439
 
440
 
441
//===========================================================================
442
//                              PROTOTYPES
443
//===========================================================================
444
 
445
//--------------------------------------------------------------------------
446
// Device driver interface functions
447
//
448
static bool        at91sam7_can_init(struct cyg_devtab_entry* devtab_entry);
449
static Cyg_ErrNo   at91sam7_can_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name);
450
static Cyg_ErrNo   at91sam7_can_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len);
451
static Cyg_ErrNo   at91sam7_can_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len);
452
static bool        at91sam7_can_putmsg(can_channel *priv, CYG_CAN_MSG_T *pmsg, void *pdata);
453
static bool        at91sam7_can_getevent(can_channel *priv, CYG_CAN_EVENT_T *pevent, void *pdata);
454
static void        at91sam7_can_start_xmit(can_channel* chan);
455
static void        at91sam7_can_stop_xmit(can_channel* chan);
456
 
457
 
458
//--------------------------------------------------------------------------
459
// ISRs and DSRs
460
//
461
static cyg_uint32 at91sam7_can_ISR(cyg_vector_t vector, cyg_addrword_t data);
462
static void       at91sam7_can_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
463
 
464
 
465
//--------------------------------------------------------------------------
466
// Private utility functions
467
//
468
static bool at91sam7_can_config_channel(can_channel* chan, cyg_can_info_t* config, cyg_bool init);
469
static bool at91sam7_can_set_baud(can_channel *chan, cyg_can_baud_rate_t *baudrate);
470
static void at91sam7_can_mbox_config_rx_all(can_channel *chan);
471
static void at91sam7_can_setup_mbox(can_channel *chan,    // channel 
472
                                    cyg_uint8    mbox,    // message box number (0 -7)
473
                                    cyg_uint32   mid,     // message identifier
474
                                    cyg_uint32   mam,     // acceptance mask for this message box
475
                                    cyg_uint32   rxtype); // RX or RX with overwrite are valid values
476
static void at91sam7_enter_lowpower_mode(can_channel *chan);
477
static void at91sam7_start_module(can_channel *chan);
478
static cyg_can_state at91sam7_get_state(at91sam7_can_info_t *info);
479
 
480
#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
481
static void at91sam7_can_config_rx_none(can_channel *chan);
482
static Cyg_ErrNo at91sam7_can_set_config_msgbuf(can_channel *chan, cyg_can_msgbuf_cfg *buf);
483
#endif
484
 
485
 
486
 
487
 
488
//===========================================================================
489
//                   GENERIC CAN IO DATA INITIALISATION
490
//===========================================================================
491
CAN_LOWLEVEL_FUNS(at91sam7_can_lowlevel_funs,
492
                  at91sam7_can_putmsg,
493
                  at91sam7_can_getevent,
494
                  at91sam7_can_get_config,
495
                  at91sam7_can_set_config,
496
                  at91sam7_can_start_xmit,
497
                  at91sam7_can_stop_xmit
498
     );
499
 
500
 
501
CYG_CAN_EVENT_T  at91sam7_can0_rxbuf[CYGNUM_DEVS_CAN_AT91SAM7_CAN0_QUEUESIZE_RX]; // buffer for RX can events
502
CYG_CAN_MSG_T    at91sam7_can0_txbuf[CYGNUM_DEVS_CAN_AT91SAM7_CAN0_QUEUESIZE_TX]; // buffer for TX can messages
503
 
504
 
505
CAN_CHANNEL_USING_INTERRUPTS(at91sam7_can0_chan,
506
                             at91sam7_can_lowlevel_funs,
507
                             at91sam7_can0_info,
508
                             CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_AT91SAM7_CAN0_KBAUD),
509
                             at91sam7_can0_txbuf, CYGNUM_DEVS_CAN_AT91SAM7_CAN0_QUEUESIZE_TX,
510
                             at91sam7_can0_rxbuf, CYGNUM_DEVS_CAN_AT91SAM7_CAN0_QUEUESIZE_RX
511
    );
512
 
513
 
514
DEVTAB_ENTRY(at91sam7_can_devtab,
515
             CYGPKG_DEVS_CAN_AT91SAM7_CAN0_NAME,
516
             0,                     // Does not depend on a lower level interface
517
             &cyg_io_can_devio,
518
             at91sam7_can_init,
519
             at91sam7_can_lookup,  // CAN driver may need initializing
520
             &at91sam7_can0_chan
521
    );
522
 
523
 
524
//===========================================================================
525
//                            IMPLEMENTATION
526
//===========================================================================
527
 
528
 
529
 
530
//===========================================================================
531
/// First initialisation and reset of CAN modul.
532
//===========================================================================
533
static bool at91sam7_can_init(struct cyg_devtab_entry* devtab_entry)
534
{
535
    can_channel          *chan    = (can_channel*)devtab_entry->priv;
536
    at91sam7_can_info_t *info    = (at91sam7_can_info_t *)chan->dev_priv;
537
 
538
#ifdef CYGDBG_IO_INIT
539
    diag_printf("AT91 CAN init\n");
540
#endif   
541
    cyg_drv_interrupt_create(CAN_ISRVEC(info),
542
                             CAN_ISRPRIO(info),        // Priority
543
                             (cyg_addrword_t)chan,     // Data item passed to interrupt handler
544
                             at91sam7_can_ISR,
545
                             at91sam7_can_DSR,
546
                             &info->interrupt_handle,
547
                             &info->interrupt);
548
    cyg_drv_interrupt_attach(info->interrupt_handle);
549
    cyg_drv_interrupt_unmask(CAN_ISRVEC(info));
550
 
551
    return at91sam7_can_config_channel(chan, &chan->config, true);
552
}
553
 
554
 
555
//===========================================================================
556
//  Lookup the device and return its handle
557
//===========================================================================
558
static Cyg_ErrNo at91sam7_can_lookup(struct cyg_devtab_entry** tab, struct cyg_devtab_entry* sub_tab, const char* name)
559
{
560
    can_channel* chan    = (can_channel*) (*tab)->priv;
561
    CAN_DECLARE_INFO(chan);
562
 
563
    chan->callbacks->can_init(chan);
564
    HAL_WRITE_UINT32(CAN_IER(info), INT_DEFAULT);                  // enable wakeup and error interrupts
565
    HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCER, 1 << CAN_PID(info));  // Enable the peripheral clock to the device      
566
 
567
    //
568
    // It is important to setup the message buffer configuration after enabling the 
569
    // peripheral clock. This is nowhere documented in the at91sam7 hardware manual.
570
    // If the message buffer configuration is set before the peripheral clock is
571
    // enabled, then message buffers that receive extended frames might not work
572
    // properly
573
    //
574
    at91sam7_can_mbox_config_rx_all(chan);
575
 
576
    return ENOERR;
577
}
578
 
579
 
580
#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
581
//===========================================================================
582
// Setup AT91SAM7 CAN module in a state where all message boxes are disabled
583
// After this callit is possible to add single message buffers and filters
584
//===========================================================================
585
static void at91sam7_can_config_rx_none(can_channel *chan)
586
{
587
    at91sam7_can_info_t *info = (at91sam7_can_info_t *)chan->dev_priv;
588
    cyg_uint8 i;
589
 
590
    //
591
    // setup all RX messages moxes into a disabled state and disable all
592
    // interrupts - maybe we have to abort pending transfers before $$$$
593
    //
594
    HAL_WRITE_UINT32(CAN_IDR(info), INT_MB_RX);
595
    for (i = 0; i < CAN_MBOX_RX_CNT; ++i)
596
    {
597
        HAL_WRITE_UINT32(CAN_MB_MMR(info, i), MMR_MB_TYPE_DISABLED); // first disable message box
598
    }
599
 
600
    info->free_mboxes = CAN_MBOX_RX_CNT;
601
    info->rx_all = false;
602
}
603
 
604
 
605
//===========================================================================
606
// Add single message filter - setupm message box and enable interrupt
607
//===========================================================================
608
static void at91sam7_can_add_rx_filter(can_channel *chan, cyg_uint8 mbox, cyg_can_message *msg)
609
{
610
    CAN_DECLARE_INFO(chan);
611
 
612
    if (msg->ext)
613
    {
614
        at91sam7_can_setup_mbox(chan, mbox, MID_SET_EXT(msg->id), MAM_SET_EXT, MMR_MB_TYPE_RX);
615
    }
616
    else
617
    {
618
        at91sam7_can_setup_mbox(chan, mbox, MID_SET_STD(msg->id), MAM_SET_STD, MMR_MB_TYPE_RX);
619
    }
620
    HAL_WRITE_UINT32(CAN_IER(info), 0x01 << mbox);
621
}
622
#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
623
 
624
 
625
#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
626
//===========================================================================
627
// Allocate message box
628
// Try to find a free message box and return its ID
629
//===========================================================================
630
static cyg_int8 at91sam7_can_alloc_mbox(at91sam7_can_info_t *info)
631
{
632
    cyg_uint8     i;
633
    cyg_int8      res = CYGNUM_CAN_MSGBUF_NA;
634
 
635
    if (info->free_mboxes)
636
    {
637
        for (i = (CAN_MBOX_RX_CNT - info->free_mboxes); i <= CAN_MBOX_RX_MAX; ++i)
638
        {
639
            cyg_uint32 mmr;
640
            HAL_READ_UINT32(CAN_MB_MMR(info, i), mmr);
641
            if ((mmr & MMR_MB_TYPE_BITMASK) == MMR_MB_TYPE_DISABLED)
642
            {
643
                info->free_mboxes--;
644
                res = i;
645
                break;
646
            }
647
        }
648
    } // if (info->free_mboxes)
649
 
650
    return res;
651
}
652
#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
653
 
654
 
655
#ifdef CYGOPT_IO_CAN_REMOTE_BUF
656
//===========================================================================
657
// Setup a RTR response message box
658
//===========================================================================
659
static bool at91sam7_can_setup_rtrmbox(can_channel      *chan,
660
                                       cyg_uint32        mbox,
661
                                       cyg_can_message  *pmsg,
662
                                       bool              init)
663
{
664
    CAN_DECLARE_INFO(chan);
665
    cyg_uint32 mcr;
666
 
667
    //
668
    // To prevent concurrent access with the internal CAN core, the application
669
    // must disable the mailbox before writing to CAN_MIDx registers - so we
670
    // do this here
671
    //
672
    if (init)
673
    {
674
        if (pmsg->ext)
675
        {
676
            at91sam7_can_setup_mbox(chan, mbox, MID_SET_EXT(pmsg->id), MAM_SET_EXT, MMR_MB_TYPE_PRODUCE);
677
        }
678
        else
679
        {
680
            at91sam7_can_setup_mbox(chan, mbox, MID_SET_STD(pmsg->id), MAM_SET_STD, MMR_MB_TYPE_PRODUCE);
681
        }
682
        HAL_WRITE_UINT32(CAN_IER(info), 0x01 << mbox); // enable interrupt
683
    }
684
    else
685
    {
686
        cyg_uint32 msr;
687
        //
688
        // Check if this message box is ready for transmission or if it still transmits
689
        // a message - we read the MSR register to check the ready flag
690
        //
691
        HAL_READ_UINT32(CAN_MB_MSR(info, mbox), msr);
692
        if (!(msr & MSR_RDY))
693
        {
694
            AT91SAM7_DBG_PRINT("(RTR) !MSR_RDY\n");
695
            return false;
696
        }
697
    }
698
 
699
    HAL_WRITE_UINT32(CAN_MB_MDL(info, mbox), pmsg->data.dwords[0]); // set data
700
    HAL_WRITE_UINT32(CAN_MB_MDH(info, mbox), pmsg->data.dwords[1]); // set data
701
    mcr = (pmsg->dlc << MCR_DLC_SHIFTER) | MCR_TRANSFER_CMD;        // set data lengt and transfer request
702
    HAL_WRITE_UINT32(CAN_MB_MCR(info, mbox), mcr);                  // transfer request    
703
    return true;
704
}
705
#endif // CYGOPT_IO_CAN_REMOTE_BUF
706
 
707
 
708
#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
709
//===========================================================================
710
// Configure message buffers
711
//===========================================================================
712
static Cyg_ErrNo at91sam7_can_set_config_msgbuf(can_channel *chan, cyg_can_msgbuf_cfg *buf)
713
{
714
    Cyg_ErrNo             res  = ENOERR;
715
    at91sam7_can_info_t *info = (at91sam7_can_info_t *)chan->dev_priv;
716
 
717
    switch (buf->cfg_id)
718
    {
719
        //
720
        // clear all message filters and remote buffers - prepare for message buffer
721
        // configuration
722
        //
723
        case CYGNUM_CAN_MSGBUF_RESET_ALL :
724
             {
725
                 at91sam7_can_config_rx_none(chan);
726
             }
727
             break;
728
 
729
        //
730
        // setup AT91SAM7 CAN module for reception of all standard and extended messages
731
        //
732
        case CYGNUM_CAN_MSGBUF_RX_FILTER_ALL :
733
             {
734
                 if (!info->rx_all) // if rx_all is enabled we do not need to do anything
735
                 {
736
                    at91sam7_can_mbox_config_rx_all(chan);  // setup RX all state
737
                 }
738
             }
739
             break;
740
 
741
        //
742
        // add single message filter, message with filter ID will be received
743
        //     
744
        case CYGNUM_CAN_MSGBUF_RX_FILTER_ADD :
745
             {
746
                 cyg_can_filter *filter   = (cyg_can_filter*) buf;
747
 
748
                 //
749
                 // if AT91SAM7 CAN module is configured to receive all messages then 
750
                 // it is not allowed to add single message filters because then more 
751
                 // than one message buffer would receive the same CAN id
752
                 //
753
                 if (info->rx_all)
754
                 {
755
                    return -EPERM;
756
                 }
757
 
758
                 //
759
                 // try to allocate a free message box - if we have a free one
760
                 // then we can prepare the message box for reception of the
761
                 // desired message id
762
                 //
763
                 filter->handle = at91sam7_can_alloc_mbox(info);
764
                 if (filter->handle > CYGNUM_CAN_MSGBUF_NA)
765
                 {
766
                     at91sam7_can_add_rx_filter(chan, filter->handle, &filter->msg);
767
                 }
768
             }
769
             break; //CYGNUM_CAN_MSGBUF_RX_FILTER_ADD
770
 
771
 
772
#ifdef CYGOPT_IO_CAN_REMOTE_BUF
773
        //
774
        // Try to add a new RTR response message buffer for automatic transmisson
775
        // of data frame on reception of a remote frame
776
        //
777
        case CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD :
778
             {
779
                 cyg_can_remote_buf *rtr_buf    = (cyg_can_remote_buf*) buf;
780
                 rtr_buf->handle = at91sam7_can_alloc_mbox(info);
781
 
782
                 if (rtr_buf->handle > CYGNUM_CAN_MSGBUF_NA)
783
                 {
784
                     //
785
                     // if we have a free message buffer then we setup this buffer
786
                     // for remote frame reception
787
                     //
788
                     at91sam7_can_setup_rtrmbox(chan, rtr_buf->handle, &rtr_buf->msg, true);
789
                 }
790
             }
791
             break;
792
 
793
        //
794
        // write data into remote response buffer
795
        //
796
        case CYGNUM_CAN_MSGBUF_REMOTE_BUF_WRITE :
797
             {
798
                 cyg_can_remote_buf *rtr_buf    = (cyg_can_remote_buf*) buf;
799
                 //
800
                 // If we have a valid rtr buf handle then we can store data into
801
                 // rtr message box
802
                 // 
803
                 if ((rtr_buf->handle >= 0) && (rtr_buf->handle <= CAN_MBOX_RX_MAX))
804
                 {
805
                      if (!at91sam7_can_setup_rtrmbox(chan, rtr_buf->handle, &rtr_buf->msg, false))
806
                      {
807
                          res = -EAGAIN;
808
                      }
809
                 }
810
                 else
811
                 {
812
                    res = -EINVAL;
813
                 }
814
             }
815
             break;
816
#endif // #ifdef CYGOPT_IO_CAN_REMOTE_BUF
817
    } // switch (buf->cfg_id)
818
 
819
    return res;
820
}
821
#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
822
 
823
 
824
//===========================================================================
825
// Read state of CAN controller
826
// The CAN state variable for each channel is modiefied by DSR so if we 
827
// read the state we need to lock DSRs to protect the data access
828
//===========================================================================
829
static cyg_can_state at91sam7_get_state(at91sam7_can_info_t *info)
830
{
831
    cyg_can_state result;
832
 
833
    cyg_drv_dsr_lock();
834
    result = info->state;
835
    cyg_drv_dsr_unlock();
836
 
837
    return result;
838
}
839
 
840
 
841
//===========================================================================
842
// Enter low power mode
843
// Before stopping the CAN clock (PMC), the CAN Controller must be in 
844
// Low-power Mode to complete the current transfer. After restarting the 
845
// clock, the application must disable the Low-power Mode of the 
846
// CAN controller. If the power mode is entered, a sleep interrupt is 
847
// generated.
848
//===========================================================================
849
static void at91sam7_enter_lowpower_mode(can_channel *chan)
850
{
851
    CAN_DECLARE_INFO(chan);
852
 
853
 
854
    cyg_uint32 mr;
855
    HAL_READ_UINT32(CAN_MR(info), mr);
856
    HAL_WRITE_UINT32(CAN_MR(info), mr | MR_LOW_POWER);
857
    HAL_WRITE_UINT32(CAN_IER(info), INT_SLEEP);
858
}
859
 
860
 
861
//===========================================================================
862
// Start CAN module (or leave the low power mode)
863
// If the CAN module is in STANDBY state then we enable the module clock
864
// and leave the low power mode by clearing the low power flag.
865
//===========================================================================
866
static void at91sam7_start_module(can_channel *chan)
867
{
868
    CAN_DECLARE_INFO(chan);
869
    cyg_uint32           mr;
870
 
871
    HAL_WRITE_UINT32(CAN_IER(info), INT_DEFAULT);                  // enable wakeup interrupt 
872
    HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCER, 1 << CAN_PID(info));  // restart peripheral clock
873
    HAL_READ_UINT32(CAN_MR(info), mr);
874
    mr &= ~MR_LOW_POWER ;
875
    HAL_WRITE_UINT32(CAN_MR(info), mr | MR_CAN_ENABLE);            // clear the low power flag to leave standby     
876
}
877
 
878
//===========================================================================
879
// Change device configuration
880
//===========================================================================
881
static Cyg_ErrNo at91sam7_can_set_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
882
{
883
    Cyg_ErrNo  res = ENOERR;
884
 
885
    switch (key)
886
    {
887
        //
888
        // Setup a new CAN configuration. This will i.e. setup a new baud rate
889
        //
890
        case CYG_IO_SET_CONFIG_CAN_INFO:
891
             {
892
                 cyg_can_info_t*  config = (cyg_can_info_t*) buf;
893
                 if (*len < sizeof(cyg_can_info_t))
894
                 {
895
                     return -EINVAL;
896
                 }
897
                 *len = sizeof(cyg_can_info_t);
898
                 if (!at91sam7_can_config_channel(chan, config, false))
899
                 {
900
                     return -EINVAL;
901
                 }
902
             }
903
             break;
904
 
905
#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG            
906
        //
907
        // configure message buffers
908
        //
909
        case CYG_IO_SET_CONFIG_CAN_MSGBUF :
910
             {
911
                cyg_can_msgbuf_cfg *msg_buf = (cyg_can_msgbuf_cfg *)buf;
912
 
913
                if (*len != sizeof(cyg_can_msgbuf_cfg))
914
                {
915
                    return -EINVAL;
916
                }
917
 
918
                res = at91sam7_can_set_config_msgbuf(chan, msg_buf);
919
             }
920
             break;
921
#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
922
 
923
        //
924
        // Change CAN state of AT91SAM7 CAN module
925
        //    
926
        case CYG_IO_SET_CONFIG_CAN_MODE :
927
             {
928
                cyg_can_mode   *can_mode  = (cyg_can_mode*) buf;
929
 
930
                if (*len != sizeof(cyg_can_mode))
931
                {
932
                    return -EINVAL;
933
                }
934
                *len = sizeof(cyg_can_mode);
935
 
936
                //
937
                // decide what to do acording to mode
938
                //
939
                switch (*can_mode)
940
                {
941
                    //
942
                    // The controller does not support a stopped and standby state so we
943
                    // simply enter the low power state here. This state is also safe for
944
                    // message buffer configuration
945
                    //
946
                    case CYGNUM_CAN_MODE_STOP :    at91sam7_enter_lowpower_mode(chan); break;
947
                    case CYGNUM_CAN_MODE_START :   at91sam7_start_module(chan);        break;
948
                    case CYGNUM_CAN_MODE_STANDBY : at91sam7_enter_lowpower_mode(chan); break;
949
                    case CYGNUM_CAN_MODE_CONFIG :  at91sam7_enter_lowpower_mode(chan); break;
950
                    case CYGNUM_CAN_MODE_LISTEN_ONLY_ENTER: return -EINVAL;
951
                    case CYGNUM_CAN_MODE_LISTEN_ONLY_EXIT: return -EINVAL;
952
                }
953
             }
954
             break; // case CYG_IO_SET_CONFIG_CAN_MODE :         
955
    } // switch (key)
956
 
957
    return res;
958
}
959
 
960
 
961
//===========================================================================
962
// Query device configuration
963
//===========================================================================
964
static Cyg_ErrNo at91sam7_can_get_config(can_channel *chan, cyg_uint32 key, const void* buf, cyg_uint32* len)
965
{
966
    Cyg_ErrNo            res  = ENOERR;
967
    at91sam7_can_info_t *info = (at91sam7_can_info_t *)chan->dev_priv;
968
 
969
    switch(key)
970
    {
971
        //
972
        // query state of CAN controller
973
        //
974
        case CYG_IO_GET_CONFIG_CAN_STATE :
975
             {
976
                cyg_can_state *can_state  = (cyg_can_state*) buf;
977
 
978
                if (*len != sizeof(cyg_can_state))
979
                {
980
                    return -EINVAL;
981
                }
982
                *len = sizeof(cyg_can_state);
983
                *can_state = at91sam7_get_state(info);
984
             }
985
             break;
986
 
987
#ifdef CYGOPT_IO_CAN_RUNTIME_MBOX_CFG       
988
        //
989
        // Query message box information - returns available and free message
990
        // boxes
991
        //     
992
        case CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO :
993
             {
994
                 cyg_can_msgbuf_info *mbox_info  = (cyg_can_msgbuf_info*) buf;
995
 
996
                 if (*len != sizeof(cyg_can_msgbuf_info))
997
                 {
998
                     return -EINVAL;
999
                 }
1000
                *len = sizeof(cyg_can_msgbuf_info);
1001
 
1002
                 mbox_info->count = CAN_MBOX_RX_CNT;
1003
                 mbox_info->free  = info->free_mboxes;
1004
             }
1005
             break;
1006
#endif // CYGOPT_IO_CAN_RUNTIME_MBOX_CFG
1007
 
1008
 
1009
        //
1010
        // Query hardware description of FlexCAN device driver
1011
        //     
1012
        case CYG_IO_GET_CONFIG_CAN_HDI :
1013
             {
1014
                cyg_can_hdi *hdi = (cyg_can_hdi *)buf;
1015
                //
1016
                // comes from high level driver so we do not need to
1017
                // check buffer size here
1018
                //             
1019
                hdi->support_flags = CYGNUM_CAN_HDI_FRAMETYPE_EXT_ACTIVE
1020
                                   | CYGNUM_CAN_HDI_FULLCAN
1021
                                   | CYGNUM_CAN_HDI_AUTBAUD;
1022
#ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP 
1023
                hdi->support_flags |= CYGNUM_CAN_HDI_TIMESTAMP;
1024
#endif
1025
             }
1026
             break;
1027
 
1028
        default :
1029
            res = -EINVAL;
1030
    }// switch(key)
1031
 
1032
    return res;
1033
}
1034
 
1035
 
1036
//===========================================================================
1037
// Send single message
1038
//===========================================================================
1039
static bool at91sam7_can_putmsg(can_channel *priv, CYG_CAN_MSG_T *pmsg, void *pdata)
1040
{
1041
    CAN_DECLARE_INFO(priv);
1042
    cyg_uint32            msr;
1043
    cyg_uint32            mcr = 0;
1044
 
1045
    //
1046
    // First check if this message box is ready fro transmission or if it still transmits
1047
    // a message - we read the MSR register to check the ready flag
1048
    //
1049
    HAL_READ_UINT32(CAN_MB_MSR(info, CAN_MBOX_TX(info)), msr);
1050
    if (!(msr & MSR_RDY))
1051
    {
1052
        AT91SAM7_DBG_PRINT("!MSR_RDY\n");
1053
        return false;
1054
    }
1055
 
1056
    //
1057
    // To prevent concurrent access with the internal CAN core, the application must disable 
1058
    // the mailbox before writing to CAN_MIDx registers - so we do this now
1059
    // 
1060
    HAL_WRITE_UINT32(CAN_MB_MMR(info, CAN_MBOX_TX(info)), MMR_MB_TYPE_DISABLED);
1061
 
1062
    //
1063
    // Setup the message identifier - this depends on the frame type (standard or extended)
1064
    //
1065
#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
1066
    if (AT91SAM7_CAN_IS_EXT(*pmsg))
1067
    {
1068
        HAL_WRITE_UINT32(CAN_MB_MID(info, CAN_MBOX_TX(info)),
1069
                         pmsg->id | MID_MIDE);                                   // set extended message id
1070
    }
1071
    else
1072
#endif // CYGOPT_IO_CAN_EXT_CAN_ID
1073
    {
1074
#ifdef CYGOPT_IO_CAN_STD_CAN_ID
1075
        HAL_WRITE_UINT32(CAN_MB_MID(info, CAN_MBOX_TX(info)),
1076
                        (pmsg->id << MID_MIDvA_SHIFTER) & MID_MIDvA_BITMASK);    // set standard message id
1077
#endif // CYGOPT_IO_CAN_STD_CAN_ID  
1078
    }
1079
 
1080
    HAL_WRITE_UINT32(CAN_MB_MDL(info, CAN_MBOX_TX(info)), pmsg->data.dwords[0]); // set data
1081
    HAL_WRITE_UINT32(CAN_MB_MDH(info, CAN_MBOX_TX(info)), pmsg->data.dwords[1]); // set data
1082
    HAL_WRITE_UINT32(CAN_MB_MMR(info, CAN_MBOX_TX(info)), MMR_MB_TYPE_TX);       // reenable the message box
1083
    mcr = (AT91SAM7_CAN_GET_DLC(*pmsg) << MCR_DLC_SHIFTER) | MCR_TRANSFER_CMD;   // set data lengt and transfer request
1084
 
1085
    if (AT91SAM7_CAN_IS_RTR(*pmsg))
1086
    {
1087
        mcr |= MCR_RTR;
1088
    }
1089
 
1090
    HAL_WRITE_UINT32(CAN_MB_MCR(info, CAN_MBOX_TX(info)), mcr);
1091
    return true;
1092
}
1093
 
1094
 
1095
//===========================================================================
1096
// Read event from device driver
1097
//===========================================================================
1098
static bool at91sam7_can_getevent(can_channel *chan, CYG_CAN_EVENT_T *pevent, void *pdata)
1099
{
1100
    at91sam7_can_info_t  *info       = (at91sam7_can_info_t *)chan->dev_priv;
1101
    cyg_uint32*           pstat      = (cyg_uint32 *)pdata;
1102
    cyg_uint8             mboxflags  = (*pstat & INT_MB_RX);
1103
    cyg_uint8             mbox       = 0;
1104
    bool                  res        = true;
1105
 
1106
    //
1107
    // First check if a message box interrupt occured if a message box interrupt
1108
    // occured process the lowest message box that caused an interrupt
1109
    //
1110
    if (mboxflags)
1111
    {
1112
        cyg_uint32 msr;
1113
        cyg_uint32 mid;
1114
        cyg_uint32 mmr;
1115
 
1116
        while (!(mboxflags & 0x01))
1117
        {
1118
            mboxflags >>= 1;
1119
            mbox++;
1120
        }
1121
 
1122
        //
1123
        // If the message box that caused the interrupt is an PRODUCER message box,
1124
        // then we received an remote request message, if not, then this is a normal
1125
        // RX message
1126
        //
1127
        HAL_READ_UINT32(CAN_MB_MMR(info, mbox), mmr);
1128
        HAL_READ_UINT32(CAN_MB_MSR(info, mbox), msr);
1129
       *pstat &= ~(0x01 << mbox);                                 // clear flag
1130
 
1131
        if (MMR_MB_GET_TYPE(mmr) != MMR_MB_TYPE_PRODUCE)
1132
        {
1133
            HAL_READ_UINT32(CAN_MB_MID(info, mbox), mid);
1134
            pevent->flags |= CYGNUM_CAN_EVENT_RX;
1135
            if (msr & MSR_MSG_IGNORED)
1136
            {
1137
                pevent->flags |= CYGNUM_CAN_EVENT_OVERRUN_RX_HW;
1138
            }
1139
 
1140
            //
1141
            // It is important to set the DLC first because this also clears the ctrl
1142
            // field if extended identifiers are supported
1143
            //
1144
            AT91SAM7_CAN_SET_DLC(pevent->msg, MSR_DLC_GET(msr));
1145
 
1146
#ifdef CYGOPT_IO_CAN_EXT_CAN_ID     
1147
            if (mid & MID_MIDE)
1148
            {
1149
                pevent->msg.id = MID_GET_EXT(mid);
1150
                AT91SAM7_CAN_SET_EXT(pevent->msg);
1151
            }
1152
            else
1153
#endif // CYGOPT_IO_CAN_EXT_CAN_ID
1154
            {
1155
#ifdef CYGOPT_IO_CAN_STD_CAN_ID
1156
                pevent->msg.id = MID_GET_STD(mid);
1157
#endif // CYGOPT_IO_CAN_STD_CAN_ID
1158
            }
1159
 
1160
            if (msr & MSR_RTR)
1161
            {
1162
                AT91SAM7_CAN_SET_RTR(pevent->msg);
1163
            }
1164
            else
1165
            {
1166
                HAL_READ_UINT32(CAN_MB_MDL(info, mbox), pevent->msg.data.dwords[0]);
1167
                HAL_READ_UINT32(CAN_MB_MDH(info, mbox), pevent->msg.data.dwords[1]);
1168
            }
1169
#ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP 
1170
            pevent->timestamp = msr & MSR_TIMESTAMP;
1171
#endif
1172
 
1173
            HAL_WRITE_UINT32(CAN_MB_MCR(info, mbox), MCR_TRANSFER_CMD);                  // transfer request        
1174
            AT91SAM7_DBG_PRINT("RXID: %x\n", AT91SAM7_CAN_GET_ID(pevent->msg));
1175
        } // if (!(mbox & info->rtr_mboxes)
1176
        else
1177
        {
1178
            HAL_WRITE_UINT32(CAN_MB_MCR(info, mbox), (msr & MSR_DLC) | MCR_TRANSFER_CMD); // transfer request 
1179
            //
1180
            // We do not need to store an event into receive queue if the stat field does
1181
            // not contain any further event flags. If stat is empty we can set res
1182
            // to false and no event will bestore
1183
            //
1184
            res = !(*pstat == 0);
1185
        }
1186
 
1187
        HAL_WRITE_UINT32(CAN_IER(info), 0x01 << mbox);                  // enable interruptfor this message box
1188
    } // if (mboxflags)
1189
 
1190
    //
1191
    // Now check if additional events occured
1192
    //
1193
    if (*pstat)
1194
    {
1195
        if (*pstat & INT_WAKEUP)
1196
        {
1197
            AT91SAM7_DBG_PRINT("WAKE\n");
1198
            pevent->flags |= CYGNUM_CAN_EVENT_LEAVING_STANDBY;
1199
            *pstat &= ~INT_WAKEUP;
1200
            info->state = CYGNUM_CAN_STATE_ACTIVE;
1201
        }
1202
 
1203
        if (*pstat & INT_ERR_PASSIVE)
1204
        {
1205
            AT91SAM7_DBG_PRINT("ERRP\n");
1206
            pevent->flags |= CYGNUM_CAN_EVENT_ERR_PASSIVE;
1207
            *pstat &= ~INT_ERR_PASSIVE;
1208
            info->state = CYGNUM_CAN_STATE_ERR_PASSIVE;
1209
            HAL_WRITE_UINT32(CAN_IER(info), INT_WAKEUP);
1210
        }
1211
 
1212
        if (*pstat & INT_WARN)
1213
        {
1214
            //
1215
            // check which counter reached its warning level (> 96)
1216
            //
1217
            cyg_uint8 ecr;
1218
            HAL_READ_UINT32(CAN_ECR(info), ecr);
1219
            if (ECR_GET_REC(ecr) > 96)
1220
            {
1221
                pevent->flags |= CYGNUM_CAN_EVENT_WARNING_RX;
1222
                AT91SAM7_DBG_PRINT("WARN TX\n");
1223
            }
1224
            if (ECR_GET_TEC(ecr) > 96)
1225
            {
1226
                pevent->flags |= CYGNUM_CAN_EVENT_WARNING_TX;
1227
                AT91SAM7_DBG_PRINT("WARN RX\n");
1228
            }
1229
            *pstat &= ~INT_WARN;
1230
            info->state = CYGNUM_CAN_STATE_BUS_WARN;
1231
            HAL_WRITE_UINT32(CAN_IER(info), INT_ERR_PASSIVE | INT_BUS_OFF);
1232
        }
1233
 
1234
        if (*pstat & INT_BUS_OFF)
1235
        {
1236
            pevent->flags |= CYGNUM_CAN_EVENT_BUS_OFF;
1237
            AT91SAM7_DBG_PRINT("BOFF\n");
1238
            *pstat &= ~INT_BUS_OFF;
1239
            info->state = CYGNUM_CAN_STATE_BUS_OFF;
1240
            HAL_WRITE_UINT32(CAN_IER(info), INT_WAKEUP);
1241
        }
1242
 
1243
        if (*pstat & INT_SLEEP)
1244
        {
1245
            pevent->flags |= CYGNUM_CAN_EVENT_ENTERING_STANDBY;
1246
            AT91SAM7_DBG_PRINT("SLEEP\n");
1247
            *pstat &= ~INT_SLEEP;
1248
            HAL_WRITE_UINT32(AT91_PMC+AT91_PMC_PCDR, 1 << CAN_PID(info)); // disable module clock
1249
            info->state = CYGNUM_CAN_STATE_STANDBY;                       // set state variable
1250
            HAL_WRITE_UINT32(CAN_IER(info), INT_WAKEUP);                  // enable wakeup interrupt
1251
        }
1252
 
1253
        if (*pstat & (INT_CRC_ERR | INT_STUFF_ERR | INT_ACKN_ERR | INT_FORM_ERR | INT_BIT_ERR))
1254
        {
1255
            pevent->flags |= CYGNUM_CAN_EVENT_CAN_ERR;
1256
            AT91SAM7_DBG_PRINT("CERR\n");
1257
            *pstat &= ~(INT_CRC_ERR | INT_STUFF_ERR | INT_ACKN_ERR | INT_FORM_ERR | INT_BIT_ERR);
1258
        }
1259
    } // if (*pstat)
1260
 
1261
    return res;
1262
}
1263
 
1264
 
1265
//===========================================================================
1266
// Kick transmitter
1267
//===========================================================================
1268
static void at91sam7_can_start_xmit(can_channel* chan)
1269
{
1270
    CAN_DECLARE_INFO(chan);
1271
 
1272
    AT91SAM7_DBG_PRINT("start_xmit\n");
1273
    cyg_drv_dsr_lock();
1274
    HAL_WRITE_UINT32(CAN_IER(info), 0x01 << CAN_MBOX_TX(info)); // enable tx interrupt
1275
    cyg_drv_dsr_unlock();
1276
}
1277
 
1278
 
1279
//===========================================================================
1280
// Stop transmitter
1281
//===========================================================================
1282
static void at91sam7_can_stop_xmit(can_channel* chan)
1283
{
1284
     CAN_DECLARE_INFO(chan);
1285
 
1286
     HAL_WRITE_UINT32(CAN_IDR(info), 0x01 << CAN_MBOX_TX(info)); // disable tx interrupt 
1287
     AT91SAM7_DBG_PRINT("stop_xmit\n");
1288
}
1289
 
1290
 
1291
//===========================================================================
1292
// Configure can channel
1293
//===========================================================================
1294
static bool at91sam7_can_config_channel(can_channel* chan, cyg_can_info_t* config, cyg_bool init)
1295
{
1296
    CAN_DECLARE_INFO(chan);
1297
    cyg_uint32 temp32;
1298
    bool       res = true;
1299
 
1300
    if (init)
1301
    {
1302
        //
1303
        // If the platform that uses the driver needs to do some platform specific
1304
        // initialisation steps, it can do it inside of this macro. I.e. some platforms
1305
        // need to setup the CAN transceiver properly here (this is necessary for the
1306
        // Atmel AT91SAM7X-EK)
1307
        //
1308
#if CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1 && defined(HAL_AT91SAM7_CAN0_PLF_INIT)
1309
        HAL_AT91SAM7_CAN0_PLF_INIT();
1310
#else // CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS > 1
1311
#if defined(CYGPKG_DEVS_CAN_AT91SAM7_CAN0) && defined(HAL_AT91SAM7_CAN0_PLF_INIT)
1312
        if (info == &at91sam7_can0_info) {
1313
            HAL_AT91SAM7_CAN0_PLF_INIT();
1314
        }
1315
#endif // defined(CYGPKG_DEVS_CAN_AT91SAM7_CAN0) && defined(HAL_AT91SAM7_CAN0_PLF_INIT)
1316
#if defined(CYGPKG_DEVS_CAN_AT91SAM7_CAN1) && defined(HAL_AT91SAM7_CAN1_PLF_INIT)
1317
        if (info == &at91sam7_can1_info) {
1318
            HAL_AT91SAM7_CAN1_PLF_INIT();
1319
        }
1320
#endif // defined(CYGPKG_DEVS_CAN_AT91SAM7_CAN0) && defined(HAL_AT91SAM7_CAN0_PLF_INIT)
1321
#endif // CYGINT_DEVS_CAN_AT91SAM7_CAN_CHANNELS == 1
1322
 
1323
        HAL_WRITE_UINT32(CAN_IDR(info), 0xFFFFFFFF);   // disable all interrupts
1324
        HAL_WRITE_UINT32(CAN_MR(info), 0x00);          // disable CAN module
1325
        HAL_ARM_AT91_PIO_CFG(AT91_CAN_CANRX);          // Enable the CAN module to drive the CAN port pins
1326
        HAL_ARM_AT91_PIO_CFG(AT91_CAN_CANTX);
1327
 
1328
        HAL_WRITE_UINT32(CAN_MB_MMR(info, CAN_MBOX_TX(info)), MMR_MB_TYPE_DISABLED); // first disable tx message box
1329
        HAL_WRITE_UINT32(CAN_MB_MAM(info, CAN_MBOX_TX(info)), 0x00000000);           // set acceptance mask once
1330
        HAL_WRITE_UINT32(CAN_MB_MMR(info, CAN_MBOX_TX(info)), MMR_MB_TYPE_TX);       // setup as tx message box
1331
 
1332
        HAL_WRITE_UINT32(CAN_MR(info), MR_CAN_ENABLE); // enable CAN module  
1333
 
1334
        //
1335
        // The device should go into error active state right after enabling it
1336
        //
1337
        HAL_READ_UINT32(CAN_SR(info), temp32);
1338
        if (!(temp32 & INT_ERR_ACTIVE))
1339
        {
1340
            res = false;
1341
        }
1342
    } // if (init)
1343
 
1344
    res = at91sam7_can_set_baud(chan, &config->baud);        // set baudrate
1345
 
1346
    //
1347
    // store new config values
1348
    //
1349
    if (config != &chan->config)
1350
    {
1351
        chan->config = *config;
1352
    }
1353
 
1354
    return res;
1355
}
1356
 
1357
 
1358
//===========================================================================
1359
// Low level interrupt handler
1360
//===========================================================================
1361
static cyg_uint32 at91sam7_can_ISR(cyg_vector_t vector, cyg_addrword_t data)
1362
{
1363
    can_channel                 *chan    = (can_channel *)data;
1364
    at91sam7_can_info_t * const info = (at91sam7_can_info_t *)chan->dev_priv;
1365
    cyg_uint32                   sr;
1366
    cyg_uint32                   imr;
1367
 
1368
 
1369
    HAL_READ_UINT32(CAN_IMR(info), imr);
1370
    HAL_READ_UINT32(CAN_SR(info), sr);
1371
    AT91SAM7_DBG_PRINT("CAN_ISR SR %x\n", sr);
1372
    sr &= imr;
1373
    HAL_WRITE_UINT32(CAN_IDR(info), sr);
1374
 
1375
    info->stat |= sr;
1376
    cyg_drv_interrupt_acknowledge(vector);
1377
    return CYG_ISR_CALL_DSR;
1378
}
1379
 
1380
 
1381
//===========================================================================
1382
// High level interrupt handler
1383
//===========================================================================
1384
static void at91sam7_can_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
1385
{
1386
    can_channel                 *chan    = (can_channel *)data;
1387
    at91sam7_can_info_t * const info = (at91sam7_can_info_t *)chan->dev_priv;
1388
    cyg_uint32                   stat = 0;
1389
 
1390
    do
1391
    {
1392
        //
1393
        // If a number of events occured then we process all events now in
1394
        // in this DSR the get_event() function clears the flags in the stat
1395
        // field
1396
        //
1397
        while (stat)
1398
        {
1399
            if (stat & (0x01 << CAN_MBOX_TX(info)))
1400
            {
1401
                AT91SAM7_DBG_PRINT("TX_DSR\n");
1402
                chan->callbacks->xmt_msg(chan, 0);   // send next message 
1403
                stat &= ~INT_MB_TX;                  // clear flag
1404
            }
1405
            else if (stat)
1406
            {
1407
                AT91SAM7_DBG_PRINT("EVENT_DSR\n");
1408
                chan->callbacks->rcv_event(chan, &stat);
1409
            }
1410
        }
1411
 
1412
        //
1413
        // We check, if a new event occured while we processed other events. If new events
1414
        // occured, then we process the new events
1415
        //
1416
        cyg_drv_interrupt_mask(vector);
1417
        stat = info->stat;
1418
        info->stat = 0;
1419
        cyg_drv_interrupt_unmask(vector);
1420
    } while (stat);
1421
}
1422
 
1423
 
1424
//===========================================================================
1425
// Set baudrate of certain can channel
1426
//===========================================================================
1427
static bool at91sam7_can_set_baud(can_channel *chan, cyg_can_baud_rate_t *baudrate)
1428
{
1429
    bool                  res = true;
1430
    cyg_uint32            mrbck;
1431
    cyg_uint32            canbr;
1432
    CAN_DECLARE_INFO(chan);
1433
 
1434
 
1435
#ifdef CYGOPT_IO_CAN_AUTOBAUD  
1436
    if (CYGNUM_CAN_KBAUD_AUTO == *baudrate)
1437
    {
1438
        cyg_can_baud_rate_t   i;
1439
        cyg_uint8             j;
1440
        cyg_uint32            sr;
1441
 
1442
        res = false;
1443
        for (i = CYGNUM_CAN_KBAUD_10; i <= CYGNUM_CAN_KBAUD_1000; ++i)
1444
        {
1445
            HAL_AT91SAM7_GET_CAN_BR(i, canbr);
1446
            if (0 == canbr)
1447
            {
1448
                continue;
1449
            }
1450
 
1451
            HAL_READ_UINT32(CAN_SR(info), sr);
1452
            HAL_WRITE_UINT32(CAN_MR(info), 0);                            // disable the module
1453
            HAL_WRITE_UINT32(CAN_BR(info), canbr);                        // write baudrate register
1454
            HAL_WRITE_UINT32(CAN_MR(info), MR_CAN_ENABLE | MR_AUTOBAUD);  // enable controller in auto aud mode
1455
            for(j = 0; j < 200; ++j)
1456
            {
1457
                HAL_DELAY_US(1000);                                       // wait at least 11 bit times for synchronization
1458
            }
1459
            HAL_READ_UINT32(CAN_SR(info), sr);                            // read status register
1460
            if (!(sr & INT_ALL_ERR) && (sr & INT_WAKEUP))
1461
            {
1462
                HAL_WRITE_UINT32(CAN_MR(info), 0);                        // disable the module 
1463
                HAL_WRITE_UINT32(CAN_MR(info), MR_CAN_ENABLE);            // enable controller
1464
                *baudrate = i;                                            // store baudrate
1465
                return true;
1466
            } // if (!(sr & INT_ALL_ERR))         
1467
        }
1468
    }
1469
    else
1470
#endif // CYGOPT_IO_CAN_AUTOBAUD 
1471
    {
1472
        //
1473
        // Get bit timings from HAL because bit timings depend on sysclock
1474
        // For main clock of 48 MHz this macro is implemented in this device
1475
        // driver. If the macro fills the canbr value with 0 then the baudrate
1476
        // is not supported and the function returns false
1477
        //
1478
        HAL_AT91SAM7_GET_CAN_BR(*baudrate, canbr);
1479
        if (0 == canbr)
1480
        {
1481
            return false;
1482
        }
1483
 
1484
        //
1485
        // Any modificatons to the baudrate register must be done while CAN
1486
        // module is disabled. So we first disable CAN module, then we set
1487
        // baudrate and then we reenable the CAN module by setting the CAN enable
1488
        // flag
1489
        //
1490
        HAL_READ_UINT32(CAN_MR(info), mrbck);                   // backup value of mode register
1491
        HAL_WRITE_UINT32(CAN_MR(info), mrbck &~MR_CAN_ENABLE);  // disable controller
1492
        HAL_WRITE_UINT32(CAN_BR(info), canbr);                  // write baudrate register
1493
 
1494
        //
1495
        // Now restore the previous state - if the module was started then
1496
        // it will no be started again, if it was stopped, then it remains stopped
1497
        //
1498
        HAL_WRITE_UINT32(CAN_MR(info), mrbck);
1499
    }
1500
 
1501
    return res;
1502
}
1503
 
1504
 
1505
//===========================================================================
1506
// Setup one single message box for reception of can message
1507
//===========================================================================
1508
static void at91sam7_can_setup_mbox(can_channel *chan, cyg_uint8 mbox, cyg_uint32 mid, cyg_uint32 mam, cyg_uint32 rxtype)
1509
{
1510
    CAN_DECLARE_INFO(chan);
1511
    CYG_ASSERT(mbox < 7, "invalid rx mbox number");
1512
 
1513
 
1514
    //
1515
    // To prevent concurrent access with the internal CAN core, the application
1516
    // must disable the mailbox before writing to CAN_MIDx registers - so we
1517
    // do this here
1518
    //
1519
    HAL_WRITE_UINT32(CAN_MB_MMR(info, mbox), MMR_MB_TYPE_DISABLED); // first disable message box
1520
    HAL_WRITE_UINT32(CAN_MB_MAM(info, mbox), mam);                  // set acceptance mask
1521
    HAL_WRITE_UINT32(CAN_MB_MID(info, mbox), mid);                  // set message identifier                          
1522
    HAL_WRITE_UINT32(CAN_MB_MMR(info, mbox), rxtype);               // setup message box as rx message box (with or without overwrite)
1523
    HAL_WRITE_UINT32(CAN_MB_MCR(info, mbox), MCR_TRANSFER_CMD);     // transfer request - we do not enable interrupts here
1524
}
1525
 
1526
 
1527
//===========================================================================
1528
// Configure message boxes for reception of any CAN message
1529
//===========================================================================
1530
static void at91sam7_can_mbox_config_rx_all(can_channel *chan)
1531
{
1532
    at91sam7_can_info_t * const info = (at91sam7_can_info_t *)chan->dev_priv;
1533
    cyg_uint8  i;
1534
    cyg_uint8  mbox_int_mask    = 0;
1535
    cyg_uint8  mbox_rx_all_cnt  = CAN_MBOX_RX_ALL_CNT(info);
1536
#ifdef CYGOPT_IO_CAN_STD_CAN_ID 
1537
    cyg_uint8  last_std_rx_mbox = CAN_MBOX_STD_CNT(info) - 1;
1538
#endif // CYGOPT_IO_CAN_STD_CAN_ID
1539
#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
1540
    cyg_uint8  last_ext_rx_mbox = mbox_rx_all_cnt - 1;
1541
#endif// CYGOPT_IO_CAN_EXT_CAN_ID 
1542
 
1543
    //
1544
    // Now setup all rx message boxes. One message box (the last one - no 8) is
1545
    // used for transmission so we have 7 message boxes for reception of can messages
1546
    // We setup the message boxes 0 - 5 as RX mboxes and message box 6 as RX mbox with
1547
    // overwrite. 
1548
    //    
1549
    for (i = 0; i < mbox_rx_all_cnt; ++i)
1550
    {
1551
#ifdef CYGOPT_IO_CAN_STD_CAN_ID     
1552
        if (i < CAN_MBOX_STD_CNT(info))
1553
        {
1554
            //
1555
            // setup message boxes for standard frames
1556
            //
1557
            if (i < last_std_rx_mbox)
1558
            {
1559
                at91sam7_can_setup_mbox(chan, i, 0, MID_MIDE, MMR_MB_TYPE_RX);
1560
            }
1561
            else
1562
            {
1563
                at91sam7_can_setup_mbox(chan, i, 0, MID_MIDE, MMR_MB_TYPE_RX_OVW);
1564
            }
1565
        }
1566
        else
1567
#endif // CYGOPT_IO_CAN_STD_CAN_ID 
1568
        {
1569
#ifdef CYGOPT_IO_CAN_EXT_CAN_ID
1570
            //
1571
            // setup message boxes for extended frames
1572
            //
1573
            if (i < last_ext_rx_mbox)
1574
            {
1575
                at91sam7_can_setup_mbox(chan, i, MID_MIDE, MID_MIDE, MMR_MB_TYPE_RX);
1576
            }
1577
            else
1578
            {
1579
                at91sam7_can_setup_mbox(chan, i, MID_MIDE, MID_MIDE, MMR_MB_TYPE_RX_OVW);
1580
            }
1581
#endif// CYGOPT_IO_CAN_EXT_CAN_ID 
1582
        } // if (i < CAN_MBOX_STD_CNT(info))
1583
 
1584
        mbox_int_mask = (mbox_int_mask << 1) | 0x01; // enable interrupt 
1585
    } // for (i = 0; i < CAN_MBOX_RX_CNT; ++i)*/
1586
 
1587
    info->free_mboxes = CAN_MBOX_RX_CNT - mbox_rx_all_cnt;
1588
    info->rx_all      = true;
1589
    HAL_WRITE_UINT32(CAN_IER(info), mbox_int_mask); // Now finally enable the interrupts for als RX mboxes
1590
}
1591
 
1592
 
1593
//---------------------------------------------------------------------------
1594
// EOF can_at91am7.c

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.