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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [serial/] [freescale/] [esci/] [drv/] [current/] [src/] [ser_esci.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      ser_esci.c
4
//
5
//      Freescale sSCI Serial I/O Interface Module (interrupt driven)
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):   Ilija Koco <ilijak@siva.com.mk>
43
// Contributors:
44
// Date:        2006-04-20
45
// Purpose:     eSCI Serial I/O module (interrupt driven version)
46
// Description: 
47
//
48
//   
49
//####DESCRIPTIONEND####
50
//==========================================================================
51
#include <pkgconf/io_serial.h>
52
#include <pkgconf/io.h>
53
 
54
#include <cyg/io/io.h>
55
#include <cyg/hal/hal_intr.h>
56
#include <cyg/hal/hal_arbiter.h>
57
#include <cyg/hal/var_io.h>
58
#include <cyg/io/devtab.h>
59
#include <cyg/infra/diag.h>
60
#include <cyg/io/serial.h>
61
#include <cyg/devs/ser_esci.h>
62
 
63
// Only build this driver for if ESCI is needed.
64
#ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI
65
 
66
typedef struct esci_serial_info {
67
    CYG_ADDRWORD   esci_base;          // Base address of the esci port
68
    CYG_WORD       interrupt_num;      // INTC interrupt vector
69
    cyg_priority_t interrupt_priority; // INTC interupt priority
70
    cyg_interrupt  interrupt_obj;      // Interrupt object
71
    cyg_handle_t   interrupt_handle;   // Interrupt handle
72
} esci_serial_info;
73
 
74
static bool esci_serial_init(struct cyg_devtab_entry * tab);
75
static bool esci_serial_putc(serial_channel * chan, unsigned char c);
76
static Cyg_ErrNo esci_serial_lookup(struct cyg_devtab_entry ** tab,
77
                                    struct cyg_devtab_entry * sub_tab,
78
                                    const char * name);
79
static unsigned char esci_serial_getc(serial_channel *chan);
80
static Cyg_ErrNo esci_serial_set_config(serial_channel *chan, cyg_uint32 key,
81
                                        const void *xbuf, cyg_uint32 *len);
82
static void esci_serial_start_xmit(serial_channel *chan);
83
static void esci_serial_stop_xmit(serial_channel *chan);
84
 
85
// Interrupt servers
86
static cyg_uint32 esci_serial_ISR(cyg_vector_t vector, cyg_addrword_t data);
87
static void       esci_serial_DSR(cyg_vector_t vector, cyg_ucount32 count,
88
                                  cyg_addrword_t data);
89
 
90
static SERIAL_FUNS(esci_serial_funs,
91
                   esci_serial_putc,
92
                   esci_serial_getc,
93
                   esci_serial_set_config,
94
                   esci_serial_start_xmit,
95
                   esci_serial_stop_xmit);
96
 
97
// Available baud rates
98
static unsigned short select_baud[] = {
99
    0,                            // Unused
100
    0,                            // 50     bps unsupported
101
    0,                            // 75     bps unsupported
102
    0,                            // 110    bps unsupported
103
    0,                            // 134_5  bps unsupported
104
    0,                            // 150    bps unsupported
105
    0,                            // 200    bps unsupported
106
    FREESCALE_ESCI_BAUD(300),     // 300    bps
107
    FREESCALE_ESCI_BAUD(600),     // 600    bps
108
    FREESCALE_ESCI_BAUD(1200),    // 1200   bps
109
    0,                            // 1800   bps unsupported
110
    FREESCALE_ESCI_BAUD(2400),    // 2400   bps
111
    0,                            // 3600   bps unsupported
112
    FREESCALE_ESCI_BAUD(4800),    // 4800   bps
113
    0,                            // 7200   bps unsupported
114
    FREESCALE_ESCI_BAUD(9600),    // 9600   bps
115
    FREESCALE_ESCI_BAUD(14400),   // 14400  bps
116
    FREESCALE_ESCI_BAUD(19200),   // 19200  bps
117
    FREESCALE_ESCI_BAUD(38400),   // 38400  bps
118
    FREESCALE_ESCI_BAUD(57600),   // 57600  bps
119
    FREESCALE_ESCI_BAUD(115200),  // 115200 bps
120
 
121
};
122
 
123
#if defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_A
124
static esci_serial_info esci_serial_info0 = {
125
    esci_base          : CYGADDR_IO_SERIAL_FREESCALE_ESCI_A_BASE,
126
    interrupt_num      : CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_INT_VECTOR,
127
    interrupt_priority : CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_INT_PRIORITY
128
};
129
#if CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BUFSIZE > 0
130
static unsigned char
131
    esci_serial_out_buf0[CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BUFSIZE];
132
static unsigned char
133
    esci_serial_in_buf0[CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BUFSIZE];
134
 
135
static
136
SERIAL_CHANNEL_USING_INTERRUPTS(
137
                                esci_serial_channel0,
138
                                esci_serial_funs,
139
                                esci_serial_info0,
140
                                CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BAUD),
141
                                CYG_SERIAL_STOP_DEFAULT,
142
                                CYG_SERIAL_PARITY_DEFAULT,
143
                                CYG_SERIAL_WORD_LENGTH_DEFAULT,
144
                                CYG_SERIAL_FLAGS_DEFAULT,
145
                                &esci_serial_out_buf0[0],
146
                                sizeof(esci_serial_out_buf0),
147
                                &esci_serial_in_buf0[0],
148
                                sizeof(esci_serial_in_buf0));
149
#else 
150
static
151
SERIAL_CHANNEL(esci_serial_channel0,
152
               esci_serial_funs,
153
               esci_serial_info0,
154
               CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_A_BAUD),
155
               CYG_SERIAL_STOP_DEFAULT,
156
               CYG_SERIAL_PARITY_DEFAULT,
157
               CYG_SERIAL_WORD_LENGTH_DEFAULT,
158
               CYG_SERIAL_FLAGS_DEFAULT);
159
#endif
160
DEVTAB_ENTRY(esci_serial_io0,
161
             CYGDAT_IO_SERIAL_FREESCALE_ESCI_A_NAME,
162
             0, // does not depend on a lower level device driver
163
             &cyg_io_serial_devio,
164
             esci_serial_init,
165
             esci_serial_lookup,
166
             &esci_serial_channel0);
167
#endif // ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI_A
168
 
169
#if defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_B
170
static esci_serial_info esci_serial_info1 = {
171
    esci_base          : CYGADDR_IO_SERIAL_FREESCALE_ESCI_B_BASE,
172
    interrupt_num      : CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_INT_VECTOR,
173
    interrupt_priority : CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_INT_PRIORITY
174
};
175
#if CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BUFSIZE > 0
176
static unsigned char
177
    esci_serial_out_buf1[CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BUFSIZE];
178
static unsigned char
179
    esci_serial_in_buf1[CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BUFSIZE];
180
 
181
static
182
SERIAL_CHANNEL_USING_INTERRUPTS(esci_serial_channel1,
183
                                esci_serial_funs,
184
                                esci_serial_info1,
185
                                CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BAUD),
186
                                CYG_SERIAL_STOP_DEFAULT,
187
                                CYG_SERIAL_PARITY_DEFAULT,
188
                                CYG_SERIAL_WORD_LENGTH_DEFAULT,
189
                                CYG_SERIAL_FLAGS_DEFAULT,
190
                                &esci_serial_out_buf1[0],
191
                                sizeof(esci_serial_out_buf1),
192
                                &esci_serial_in_buf1[0],
193
                                sizeof(esci_serial_in_buf1));
194
#else 
195
static
196
SERIAL_CHANNEL(esci_serial_channel1,
197
               esci_serial_funs,
198
               esci_serial_info1,
199
               CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_B_BAUD),
200
               CYG_SERIAL_STOP_DEFAULT,
201
               CYG_SERIAL_PARITY_DEFAULT,
202
               CYG_SERIAL_WORD_LENGTH_DEFAULT,
203
               CYG_SERIAL_FLAGS_DEFAULT);
204
#endif
205
DEVTAB_ENTRY(esci_serial_io1,
206
             CYGDAT_IO_SERIAL_FREESCALE_ESCI_B_NAME,
207
             0, // does not depend on a lower level device driver
208
             &cyg_io_serial_devio,
209
             esci_serial_init,
210
             esci_serial_lookup,
211
             &esci_serial_channel1);
212
#endif // ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI_B
213
 
214
#if defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_C
215
static esci_serial_info esci_serial_info2 = {
216
    esci_base          : CYGADDR_IO_SERIAL_FREESCALE_ESCI_C_BASE,
217
    interrupt_num      : CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_INT_VECTOR,
218
    interrupt_priority : CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_INT_PRIORITY
219
};
220
#if CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BUFSIZE > 0
221
static unsigned char
222
    esci_serial_out_buf2[CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BUFSIZE];
223
static unsigned char
224
    esci_serial_in_buf2[CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BUFSIZE];
225
 
226
static
227
SERIAL_CHANNEL_USING_INTERRUPTS(esci_serial_channel2,
228
                                esci_serial_funs,
229
                                esci_serial_info2,
230
                                CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BAUD),
231
                                CYG_SERIAL_STOP_DEFAULT,
232
                                CYG_SERIAL_PARITY_DEFAULT,
233
                                CYG_SERIAL_WORD_LENGTH_DEFAULT,
234
                                CYG_SERIAL_FLAGS_DEFAULT,
235
                                &esci_serial_out_buf2[0],
236
                                sizeof(esci_serial_out_buf2),
237
                                &esci_serial_in_buf2[0],
238
                                sizeof(esci_serial_in_buf2));
239
#else 
240
static
241
SERIAL_CHANNEL(esci_serial_channel2,
242
               esci_serial_funs,
243
               esci_serial_info2,
244
               CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_C_BAUD),
245
               CYG_SERIAL_STOP_DEFAULT,
246
               CYG_SERIAL_PARITY_DEFAULT,
247
               CYG_SERIAL_WORD_LENGTH_DEFAULT,
248
               CYG_SERIAL_FLAGS_DEFAULT);
249
#endif
250
DEVTAB_ENTRY(esci_serial_io2,
251
             CYGDAT_IO_SERIAL_FREESCALE_ESCI_C_NAME,
252
             0, // does not depend on a lower level device driver
253
             &cyg_io_serial_devio,
254
             esci_serial_init,
255
             esci_serial_lookup,
256
             &esci_serial_channel2);
257
#endif // ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI_C
258
 
259
 
260
#if defined CYGPKG_IO_SERIAL_FREESCALE_ESCI_D
261
static esci_serial_info esci_serial_info3 = {
262
    esci_base          : CYGADDR_IO_SERIAL_FREESCALE_ESCI_D_BASE,
263
    interrupt_num      : CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_INT_VECTOR,
264
    interrupt_priority : CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_INT_PRIORITY
265
};
266
#if CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BUFSIZE > 0
267
static unsigned char
268
    esci_serial_out_buf3[CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BUFSIZE];
269
static unsigned char
270
    esci_serial_in_buf3[CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BUFSIZE];
271
 
272
static
273
SERIAL_CHANNEL_USING_INTERRUPTS(esci_serial_channel3,
274
                                esci_serial_funs,
275
                                esci_serial_info3,
276
                                CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BAUD),
277
                                CYG_SERIAL_STOP_DEFAULT,
278
                                CYG_SERIAL_PARITY_DEFAULT,
279
                                CYG_SERIAL_WORD_LENGTH_DEFAULT,
280
                                CYG_SERIAL_FLAGS_DEFAULT,
281
                                &esci_serial_out_buf3[0],
282
                                sizeof(esci_serial_out_buf3),
283
                                &esci_serial_in_buf3[0],
284
                                sizeof(esci_serial_in_buf3));
285
#else 
286
static
287
SERIAL_CHANNEL(esci_serial_channel3,
288
               esci_serial_funs,
289
               esci_serial_info3,
290
               CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_FREESCALE_ESCI_D_BAUD),
291
               CYG_SERIAL_STOP_DEFAULT,
292
               CYG_SERIAL_PARITY_DEFAULT,
293
               CYG_SERIAL_WORD_LENGTH_DEFAULT,
294
               CYG_SERIAL_FLAGS_DEFAULT);
295
#endif
296
DEVTAB_ENTRY(esci_serial_io3,
297
             CYGDAT_IO_SERIAL_FREESCALE_ESCI_D_NAME,
298
             0, // does not depend on a lower level device driver
299
             &cyg_io_serial_devio,
300
             esci_serial_init,
301
             esci_serial_lookup,
302
             &esci_serial_channel3);
303
#endif // ifdef CYGPKG_IO_SERIAL_FREESCALE_ESCI_D
304
 
305
//----------------------------------------------------------------------------
306
// Internal function to actually configure the hardware to desired
307
// baud rate, etc.
308
//----------------------------------------------------------------------------
309
static bool
310
esci_serial_config_port(serial_channel * chan, cyg_serial_info_t * new_config,
311
                        bool init)
312
{
313
    esci_serial_info * esci_chan = (esci_serial_info *)(chan->dev_priv);
314
    cyg_addrword_t esci_base = esci_chan->esci_base;
315
    cyg_uint16 baud_rate = ((new_config->baud >= 0) &&
316
                            (new_config->baud < (sizeof(select_baud)/
317
                                                 sizeof(select_baud[0]))))
318
      ? select_baud[new_config->baud] : 0;
319
 
320
    cyg_uint16 esci_cr12=0, esci_cr12_old;
321
 
322
    HAL_WRITE_UINT8(FREESCALE_ESCI_CR3(esci_base), 0);
323
    HAL_WRITE_UINT16(FREESCALE_ESCI_LINCTRL(esci_base), 0);
324
    HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(esci_base), 0);
325
 
326
    if(!baud_rate) return false;    // Invalid baud rate selected
327
 
328
    switch(new_config->word_length){
329
    case 8: break;
330
    default: return false;
331
    }
332
 
333
    switch(new_config->parity){
334
    case CYGNUM_SERIAL_PARITY_ODD:
335
        esci_cr12 |= FREESCALE_ESCI_CR12_PT;
336
    case CYGNUM_SERIAL_PARITY_EVEN:
337
        esci_cr12 |= FREESCALE_ESCI_CR12_PE;
338
    case CYGNUM_SERIAL_PARITY_NONE:
339
        break;
340
    default: return false;
341
    }
342
 
343
    if(new_config->stop!=CYGNUM_SERIAL_STOP_1) return false;
344
 
345
    // Enable the device
346
    esci_cr12 |= FREESCALE_ESCI_CR12_TE | FREESCALE_ESCI_CR12_RE;
347
 
348
    if(init){ // Enable the receiver interrupt
349
        esci_cr12 |= FREESCALE_ESCI_CR12_RIE;
350
    }else{    // Restore the old interrupt state
351
        HAL_READ_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12_old);
352
        esci_cr12 |= (esci_cr12_old & FREESCALE_ESCI_CR12_RIE);
353
    }
354
    HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12);
355
 
356
    if(new_config != &chan->config)
357
        chan->config = *new_config;
358
 
359
    return true;
360
}
361
 
362
//--------------------------------------------------------------
363
// Function to initialize the device.  Called at bootstrap time.
364
//--------------------------------------------------------------
365
static bool
366
esci_serial_init(struct cyg_devtab_entry * tab)
367
{
368
    serial_channel * chan = (serial_channel *)tab->priv;
369
    esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv;
370
 
371
    // Really only required for interrupt driven devices
372
    (chan->callbacks->serial_init)(chan);
373
    if(chan->out_cbuf.len != 0){
374
        cyg_drv_interrupt_create(esci_chan->interrupt_num,
375
                                 esci_chan->interrupt_priority,
376
                                 // Data item passed to interrupt handler
377
                                 (cyg_addrword_t)chan,
378
                                 esci_serial_ISR,
379
                                 esci_serial_DSR,
380
                                 &esci_chan->interrupt_handle,
381
                                 &esci_chan->interrupt_obj);
382
 
383
        cyg_drv_interrupt_attach(esci_chan->interrupt_handle);
384
        cyg_drv_interrupt_unmask(esci_chan->interrupt_num);
385
    }
386
    return esci_serial_config_port(chan, &chan->config, true);
387
}
388
 
389
//----------------------------------------------------------------------
390
// This routine is called when the device is "looked" up (i.e. attached)
391
//----------------------------------------------------------------------
392
static Cyg_ErrNo
393
esci_serial_lookup(struct cyg_devtab_entry ** tab,
394
                   struct cyg_devtab_entry * sub_tab, const char * name)
395
{
396
    serial_channel * chan = (serial_channel *)(*tab)->priv;
397
    // Really only required for interrupt driven devices
398
    (chan->callbacks->serial_init)(chan);
399
 
400
    return ENOERR;
401
}
402
 
403
//-----------------------------------------------------------------
404
// Send a character to Tx
405
//-----------------------------------------------------------------
406
static bool
407
esci_serial_putc(serial_channel * chan, unsigned char ch_out)
408
{
409
    esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv;
410
    cyg_addrword_t esci_base = esci_chan->esci_base;
411
    cyg_uint16 esci_sr;
412
 
413
    HAL_READ_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr);
414
    if(esci_sr & FREESCALE_ESCI_SR_TDRE){
415
        HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), FREESCALE_ESCI_SR_TDRE);
416
        HAL_WRITE_UINT8(FREESCALE_ESCI_DRL(esci_base), ch_out);
417
        return true;
418
    }else
419
        return false;
420
}
421
 
422
//---------------------------------------------------------------------
423
// Fetch a character Rx (for polled operation only)
424
//---------------------------------------------------------------------
425
static unsigned char
426
esci_serial_getc(serial_channel * chan)
427
{
428
    cyg_uint8 ch_in;
429
    esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv;
430
    cyg_addrword_t esci_base = esci_chan->esci_base;
431
 
432
    cyg_uint16 esci_sr;
433
 
434
    do{
435
        HAL_READ_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr);
436
    }while(esci_sr & FREESCALE_ESCI_SR_RDRF);
437
 
438
    HAL_READ_UINT8(FREESCALE_ESCI_DRL(esci_base), ch_in);
439
    HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), FREESCALE_ESCI_SR_RDRF);
440
 
441
    return ch_in;
442
}
443
 
444
//---------------------------------------------------
445
// Set up the device characteristics; baud rate, etc.
446
//---------------------------------------------------
447
static bool
448
esci_serial_set_config(serial_channel * chan, cyg_uint32 key,
449
                       const void *xbuf, cyg_uint32 * len)
450
{
451
    switch(key) {
452
    case CYG_IO_SET_CONFIG_SERIAL_INFO:{
453
            cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf;
454
            if(*len < sizeof(cyg_serial_info_t)) {
455
                return -EINVAL;
456
            }
457
            *len = sizeof(cyg_serial_info_t);
458
            if(true != esci_serial_config_port(chan, config, false))
459
            return -EINVAL;
460
        }
461
        break;
462
    default:
463
        return -EINVAL;
464
    }
465
    return ENOERR;
466
}
467
 
468
//-------------------------------------
469
// Enable the transmitter on the device
470
//-------------------------------------
471
static void esci_serial_start_xmit(serial_channel * chan)
472
{
473
    esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv;
474
    cyg_addrword_t esci_base = esci_chan->esci_base;
475
    cyg_uint16 esci_cr12;
476
 
477
    HAL_READ_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12);
478
    esci_cr12 |= FREESCALE_ESCI_CR12_TIE;
479
    HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12);
480
}
481
 
482
//--------------------------------------
483
// Disable the transmitter on the device
484
//--------------------------------------
485
static void esci_serial_stop_xmit(serial_channel * chan)
486
{
487
    esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv;
488
 
489
    cyg_addrword_t esci_base = esci_chan->esci_base;
490
    cyg_uint16 esci_cr12;
491
 
492
    HAL_READ_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12);
493
    esci_cr12 &= ~FREESCALE_ESCI_CR12_TIE;
494
    HAL_WRITE_UINT16(FREESCALE_ESCI_CR12(esci_base), esci_cr12);
495
}
496
 
497
//-----------------------------------------
498
// The low level interrupt handler
499
//-----------------------------------------
500
static
501
cyg_uint32 esci_serial_ISR(cyg_vector_t vector, cyg_addrword_t data)
502
{
503
    serial_channel * chan = (serial_channel *)data;
504
    esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv;
505
 
506
    cyg_drv_interrupt_mask(esci_chan->interrupt_num);
507
    cyg_drv_interrupt_acknowledge(esci_chan->interrupt_num);
508
 
509
    return CYG_ISR_CALL_DSR; // cause the DSR to run
510
}
511
 
512
 
513
//------------------------------------------
514
// The high level interrupt handler
515
//------------------------------------------
516
 
517
#define FREESCALE_ESCI_SR_ERRORS (FREESCALE_ESCI_SR_OR | \
518
                                  FREESCALE_ESCI_SR_NF | \
519
                                  FREESCALE_ESCI_SR_FE | \
520
                                  FREESCALE_ESCI_SR_PF)
521
 
522
static void
523
esci_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
524
{
525
    serial_channel * chan = (serial_channel *)data;
526
    esci_serial_info * esci_chan = (esci_serial_info *)chan->dev_priv;
527
    cyg_addrword_t esci_base = esci_chan->esci_base;
528
    cyg_uint16 esci_sr;
529
    cyg_uint8 esci_dr;
530
 
531
    HAL_READ_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr);
532
    if(esci_sr & FREESCALE_ESCI_SR_RDRF){ // Receiver full
533
        HAL_READ_UINT8(FREESCALE_ESCI_DRL(esci_base), esci_dr);
534
        HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), FREESCALE_ESCI_SR_RDRF);
535
        if(esci_sr &= (cyg_uint16)FREESCALE_ESCI_SR_ERRORS){
536
            HAL_WRITE_UINT16(FREESCALE_ESCI_SR(esci_base), esci_sr);
537
        }else{
538
            (chan->callbacks->rcv_char)(chan, (cyg_uint8)esci_dr);
539
        }
540
    }else if(esci_sr & FREESCALE_ESCI_SR_TDRE){ //Transmitter empty
541
        (chan->callbacks->xmt_char)(chan);
542
    }
543
 
544
    cyg_drv_interrupt_unmask(esci_chan->interrupt_num);
545
}
546
 
547
#endif // CYGPKG_IO_SERIAL_FREESCALE_ESCI_[ABCD]
548
// EOF ser_esci.c

powered by: WebSVN 2.1.0

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