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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [can/] [loop/] [current/] [src/] [loop_can.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      loop_can.c
4
//
5
//      Loopback CAN device driver
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 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:        2005-07-10
45
// Purpose:     Loopback CAN device driver
46
// Description: This device driver implements a pair of CAN lines that are
47
//              connected back-to-back. Data output to one will appear as
48
//              input on the other. This process in part driven by an alarm
49
//              object which provides a degree of separation between the two
50
//              channels.
51
//
52
//####DESCRIPTIONEND####
53
//
54
//==========================================================================
55
 
56
#include <pkgconf/hal.h>
57
#include <pkgconf/io_can.h>
58
#include <pkgconf/devs_can_loop.h>
59
#include <cyg/hal/hal_io.h>
60
 
61
#include <cyg/io/io.h>
62
#include <cyg/io/devtab.h>
63
#include <cyg/io/can.h>
64
#include <cyg/hal/hal_intr.h>
65
#include <cyg/kernel/kapi.h>
66
 
67
#ifdef CYGPKG_DEVS_CAN_LOOP
68
 
69
//-------------------------------------------------------------------------
70
 
71
extern void diag_printf(const char *fmt, ...);
72
 
73
//-------------------------------------------------------------------------
74
// Forward definitions
75
 
76
static bool loop_can_init(struct cyg_devtab_entry *devtab_entry);
77
static bool loop_can_putmsg(can_channel *priv, cyg_can_message *pmsg, void *pdata);
78
static Cyg_ErrNo loop_can_lookup(struct cyg_devtab_entry **tab,
79
                                   struct cyg_devtab_entry *sub_tab,
80
                                   const char *name);
81
static bool loop_can_getevent(can_channel *priv, cyg_can_event *pevent, void *pdata);
82
static Cyg_ErrNo loop_can_set_config(can_channel *chan, cyg_uint32 key,
83
                                     const void *xbuf, cyg_uint32 *len);
84
static Cyg_ErrNo loop_can_get_config(can_channel *chan, cyg_uint32 key,
85
                                     const void*  buf,  cyg_uint32* len);
86
static void loop_can_start_xmit(can_channel *chan);
87
static void loop_can_stop_xmit(can_channel *chan);
88
 
89
static void alarm_handler(cyg_handle_t alarm, cyg_addrword_t data);
90
 
91
 
92
//-------------------------------------------------------------------------
93
// Alarm object for feeding data back into CAN channels
94
 
95
static cyg_alarm alarm_obj;
96
 
97
static cyg_handle_t alarm_handle;
98
 
99
//-------------------------------------------------------------------------
100
// Transfer FIFOs
101
 
102
#define FIFO_SIZE 33
103
 
104
struct fifo
105
{
106
    cyg_bool                tx_enable;
107
    volatile int            head;
108
    volatile int            tail;
109
    volatile int            num;
110
    volatile cyg_can_event  buf[FIFO_SIZE+1];
111
};
112
 
113
static struct fifo fifo0 = { false, 0, 0, 0 };   // from CAN0 to CAN1
114
static struct fifo fifo1 = { false, 0, 0, 0 };   // from CAN1 to CAN0
115
 
116
//-------------------------------------------------------------------------
117
 
118
#define BUFSIZE 128
119
 
120
//-------------------------------------------------------------------------
121
// Info for each serial device controlled
122
 
123
typedef struct loop_can_info {
124
    struct fifo         *write_fifo;
125
    struct fifo         *read_fifo;
126
} loop_can_info;
127
 
128
//-------------------------------------------------------------------------
129
// Callback functions exported by this driver   
130
CAN_LOWLEVEL_FUNS(loop_can_lowlevel_funs,
131
                  loop_can_putmsg,
132
                  loop_can_getevent,
133
                  loop_can_get_config,
134
                  loop_can_set_config,
135
                  loop_can_start_xmit,
136
                  loop_can_stop_xmit
137
     );
138
 
139
//-------------------------------------------------------------------------
140
// Hardware info for each serial line
141
 
142
#ifdef CYGPKG_DEVS_CAN_LOOP_CAN0
143
static loop_can_info loop_can_info0 = {
144
    &fifo0,
145
    &fifo1
146
};
147
 
148
static cyg_can_message  loop_can_txbuf0[CYGNUM_DEVS_CAN_LOOP_CAN0_QUEUESIZE_TX];
149
static cyg_can_event    loop_can_rxbuf0[CYGNUM_DEVS_CAN_LOOP_CAN0_QUEUESIZE_RX];
150
#endif // CYGPKG_IO_SERIAL_LOOP_SERIAL0
151
 
152
#ifdef CYGPKG_DEVS_CAN_LOOP_CAN1
153
static loop_can_info loop_can_info1 = {
154
    &fifo1,
155
    &fifo0
156
};
157
 
158
static cyg_can_message  loop_can_txbuf1[CYGNUM_DEVS_CAN_LOOP_CAN1_QUEUESIZE_TX];
159
static cyg_can_event    loop_can_rxbuf1[CYGNUM_DEVS_CAN_LOOP_CAN1_QUEUESIZE_RX];
160
#endif // CYGPKG_IO_SERIAL_LOOP_SERIAL1
161
 
162
 
163
 
164
//-------------------------------------------------------------------------
165
// Channel descriptions:
166
//
167
#ifdef CYGPKG_DEVS_CAN_LOOP_CAN0
168
CAN_CHANNEL_USING_INTERRUPTS(loop_can0_chan,
169
                             loop_can_lowlevel_funs,
170
                             loop_can_info0,
171
                             CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LOOP_CAN0_KBAUD),
172
                             loop_can_txbuf0, CYGNUM_DEVS_CAN_LOOP_CAN0_QUEUESIZE_TX,
173
                             loop_can_rxbuf0, CYGNUM_DEVS_CAN_LOOP_CAN0_QUEUESIZE_RX
174
    );
175
#endif // CYGPKG_DEVS_CAN_LOOP_CAN1
176
 
177
#ifdef CYGPKG_DEVS_CAN_LOOP_CAN1
178
CAN_CHANNEL_USING_INTERRUPTS(loop_can1_chan,
179
                             loop_can_lowlevel_funs,
180
                             loop_can_info1,
181
                             CYG_CAN_BAUD_RATE(CYGNUM_DEVS_CAN_LOOP_CAN1_KBAUD),
182
                             loop_can_txbuf1, CYGNUM_DEVS_CAN_LOOP_CAN1_QUEUESIZE_TX,
183
                             loop_can_rxbuf1, CYGNUM_DEVS_CAN_LOOP_CAN1_QUEUESIZE_RX
184
    );
185
#endif // CYGPKG_DEVS_CAN_LOOP_CAN1
186
 
187
 
188
 
189
//-------------------------------------------------------------------------
190
// And finally, the device table entries:
191
//
192
#ifdef CYGPKG_DEVS_CAN_LOOP_CAN0
193
DEVTAB_ENTRY(loop_can_io0,
194
             CYGDAT_DEVS_CAN_LOOP_CAN0_NAME,
195
             0,                     // Does not depend on a lower level interface
196
             &cyg_io_can_devio,
197
             loop_can_init,
198
             loop_can_lookup,        // CAN driver may need initializing
199
             &loop_can0_chan
200
    );
201
#endif // CYGPKG_DEVS_CAN_LOOP_CAN0
202
 
203
#ifdef CYGPKG_DEVS_CAN_LOOP_CAN1
204
DEVTAB_ENTRY(loop_can_io1,
205
             CYGDAT_DEVS_CAN_LOOP_CAN1_NAME,
206
             0,                     // Does not depend on a lower level interface
207
             &cyg_io_can_devio,
208
             loop_can_init,
209
             loop_can_lookup,        // CAN driver may need initializing
210
             &loop_can1_chan
211
    );
212
#endif // CYGPKG_DEVS_CAN_LOOP_CAN1
213
 
214
//-------------------------------------------------------------------------
215
 
216
static bool
217
loop_can_config_channel(can_channel *chan, cyg_can_info_t *new_config, bool init)
218
{
219
    if (new_config != &chan->config) {
220
        chan->config = *new_config;
221
    }
222
    return true;
223
}
224
 
225
//-------------------------------------------------------------------------
226
// Function to initialize the device.  Called at bootstrap time.
227
 
228
bool loop_can_init(struct cyg_devtab_entry *tab)
229
{
230
    can_channel *chan = (can_channel *)tab->priv;
231
 
232
    (chan->callbacks->can_init)(chan);
233
 
234
    // Set up alarm for feeding data back into channels
235
 
236
    cyg_alarm_create( cyg_real_time_clock(),
237
                      alarm_handler,
238
                      0,
239
                      &alarm_handle,
240
                      &alarm_obj);
241
 
242
    cyg_alarm_initialize( alarm_handle, 1, 1 );
243
 
244
    loop_can_config_channel(chan, &chan->config, true);
245
 
246
    return true;
247
}
248
 
249
//-------------------------------------------------------------------------
250
// This routine is called when the device is "looked" up (i.e. attached)
251
 
252
static Cyg_ErrNo
253
loop_can_lookup(struct cyg_devtab_entry **tab,
254
                struct cyg_devtab_entry *sub_tab,
255
                const char *name)
256
{
257
    can_channel *chan = (can_channel *)(*tab)->priv;
258
    (chan->callbacks->can_init)(chan);
259
    return ENOERR;
260
}
261
 
262
//-------------------------------------------------------------------------
263
// Return 'true' if message is sent to device
264
 
265
bool
266
loop_can_putmsg(can_channel *chan, cyg_can_message *pmsg, void *pdata)
267
{
268
    loop_can_info *loop_chan = (loop_can_info *)chan->dev_priv;
269
 
270
    struct fifo *fwr = loop_chan->write_fifo;
271
#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT 
272
    struct fifo *frd = loop_chan->read_fifo;
273
#endif
274
 
275
    if( fwr->num == FIFO_SIZE )
276
    {
277
        return false;
278
    }
279
 
280
    fwr->buf[fwr->tail].msg  = *pmsg;
281
    fwr->buf[fwr->tail].flags = CYGNUM_CAN_EVENT_RX;
282
    fwr->num++;
283
    fwr->tail = (fwr->tail + 1) % FIFO_SIZE;
284
 
285
#ifdef CYGOPT_IO_CAN_TX_EVENT_SUPPORT 
286
    //
287
    // if TX events are supported we insert a TX event into read fifo
288
    //
289
    if( frd->num < FIFO_SIZE )
290
    {
291
        frd->buf[frd->tail].msg  = *pmsg;
292
        frd->buf[frd->tail].flags = CYGNUM_CAN_EVENT_TX;
293
        frd->num++;
294
        frd->tail = (frd->tail + 1) % FIFO_SIZE;
295
    }
296
#endif
297
 
298
    return true;
299
}
300
 
301
//-------------------------------------------------------------------------
302
 
303
bool loop_can_getevent(can_channel *chan, cyg_can_event *pevent, void *pdata)
304
{
305
    loop_can_info *loop_chan = (loop_can_info *)chan->dev_priv;
306
 
307
    struct fifo *frd = loop_chan->read_fifo;
308
 
309
    while( frd->num == 0 )
310
    {
311
        continue;
312
    }
313
 
314
    *pevent = frd->buf[frd->head];
315
 
316
 
317
#ifdef CYGOPT_IO_CAN_SUPPORT_TIMESTAMP 
318
    //
319
    // if timestamps are supported then we store a actual timestamp into
320
    // CAN event
321
    // 
322
    pevent->timestamp = cyg_current_time();
323
#endif // CYGOPT_IO_CAN_SUPPORT_TIMESTAMP
324
 
325
    frd->num--;
326
    frd->head = (frd->head + 1) % FIFO_SIZE;
327
 
328
    return true;
329
}
330
 
331
//-------------------------------------------------------------------------
332
 
333
static Cyg_ErrNo
334
loop_can_set_config(can_channel *chan, cyg_uint32 key,
335
                    const void *xbuf, cyg_uint32 *len)
336
{
337
    return ENOERR;
338
}
339
 
340
//-------------------------------------------------------------------------
341
// Query device configuration
342
 
343
static Cyg_ErrNo
344
loop_can_get_config(can_channel *chan, cyg_uint32 key,
345
                    const void*  buf,  cyg_uint32* len)
346
{
347
        return ENOERR;
348
}
349
 
350
 
351
//-------------------------------------------------------------------------
352
// Enable the transmitter on the device
353
 
354
static void
355
loop_can_start_xmit(can_channel *chan)
356
{
357
    loop_can_info *loop_chan = (loop_can_info *)chan->dev_priv;
358
 
359
    loop_chan->write_fifo->tx_enable = true;
360
 
361
    (chan->callbacks->xmt_msg)(chan, 0);
362
}
363
 
364
//-------------------------------------------------------------------------
365
// Disable the transmitter on the device
366
 
367
static void
368
loop_can_stop_xmit(can_channel *chan)
369
{
370
    loop_can_info *loop_chan = (loop_can_info *)chan->dev_priv;
371
 
372
    loop_chan->write_fifo->tx_enable = false;
373
}
374
 
375
//-------------------------------------------------------------------------
376
 
377
static void alarm_handler(cyg_handle_t alarm, cyg_addrword_t data)
378
{
379
    can_channel *chan0 = &loop_can0_chan;
380
    can_channel *chan1 = &loop_can1_chan;
381
 
382
 
383
    while(fifo0.num )
384
    {
385
        (chan1->callbacks->rcv_event)(chan1, 0);
386
 
387
        if(fifo0.tx_enable )
388
        {
389
            (chan0->callbacks->xmt_msg)(chan0, 0);
390
        }
391
    }
392
 
393
    while(fifo1.num )
394
    {
395
        (chan0->callbacks->rcv_event)(chan0, 0);
396
 
397
        if(fifo1.tx_enable )
398
        {
399
            (chan1->callbacks->xmt_msg)(chan1, 0);
400
        }
401
    } // while( fifo1.num )
402
}
403
 
404
 
405
#endif // CYGPKG_IO_CAN_LOOP
406
 
407
//-------------------------------------------------------------------------
408
// EOF loop_can.c

powered by: WebSVN 2.1.0

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