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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [devs/] [serial/] [arm/] [e7t/] [v2_0/] [src/] [e7t_serial.c] - Blame information for rev 27

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      io/serial/arm/e7t_serial.c
4
//
5
//      ARM AEB-2 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 Red Hat, 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 version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
// ====================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    Lars.Lindqvist@combitechsystems.com
44
// Contributors: jlarmour
45
// Date:         2001-10-19
46
// Purpose:      ARM AEB-2 Serial I/O Interface Module (interrupt driven)
47
// Description:
48
//
49
//####DESCRIPTIONEND####
50
//
51
// ====================================================================
52
 
53
#include <pkgconf/system.h>
54
#include <pkgconf/io_serial.h>
55
#include <pkgconf/io.h>
56
#include <cyg/io/io.h>
57
#include <cyg/hal/hal_intr.h>
58
#include <cyg/io/devtab.h>
59
#include <cyg/io/serial.h>
60
#include <cyg/io/serialio.h>
61
#include <cyg/infra/diag.h>
62
 
63
#ifdef CYGPKG_IO_SERIAL_ARM_E7T
64
 
65
#include "e7t_serial.h"
66
 
67
typedef struct e7t_serial_info {
68
    CYG_ADDRWORD   base;
69
    CYG_WORD       tx_int_num;
70
    CYG_WORD       rx_int_num;
71
    cyg_interrupt  serial_tx_interrupt;
72
    cyg_interrupt  serial_rx_interrupt;
73
    cyg_handle_t   serial_tx_interrupt_handle;
74
    cyg_handle_t   serial_rx_interrupt_handle;
75
    bool           tx_enabled;
76
} e7t_serial_info;
77
 
78
static bool e7t_serial_init(struct cyg_devtab_entry *tab);
79
static bool e7t_serial_putc(serial_channel *chan, unsigned char c);
80
static Cyg_ErrNo e7t_serial_lookup(struct cyg_devtab_entry **tab,
81
                                   struct cyg_devtab_entry *sub_tab,
82
                                   const char *name);
83
static unsigned char e7t_serial_getc(serial_channel *chan);
84
static Cyg_ErrNo e7t_serial_set_config(serial_channel *chan,
85
                                       cyg_uint32 key,
86
                                       const void *xbuf, cyg_uint32 *len);
87
static void e7t_serial_start_xmit(serial_channel *chan);
88
static void e7t_serial_stop_xmit(serial_channel *chan);
89
 
90
static cyg_uint32 e7t_serial_tx_ISR(cyg_vector_t vector, cyg_addrword_t data);
91
static void       e7t_serial_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
92
static cyg_uint32 e7t_serial_rx_ISR(cyg_vector_t vector, cyg_addrword_t data);
93
static void       e7t_serial_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
94
 
95
static SERIAL_FUNS(e7t_serial_funs,
96
                   e7t_serial_putc,
97
                   e7t_serial_getc,
98
                   e7t_serial_set_config,
99
                   e7t_serial_start_xmit,
100
                   e7t_serial_stop_xmit
101
    );
102
 
103
#ifdef CYGPKG_IO_SERIAL_ARM_E7T_SERIAL0
104
static e7t_serial_info e7t_serial_info0 = {0x07FFd000,
105
                                           CYGNUM_HAL_INTERRUPT_UART0_TX,
106
                                           CYGNUM_HAL_INTERRUPT_UART0_RX};
107
#if CYGNUM_IO_SERIAL_ARM_E7T_SERIAL0_BUFSIZE > 0
108
static unsigned char e7t_serial_out_buf0[CYGNUM_IO_SERIAL_ARM_E7T_SERIAL0_BUFSIZE];
109
static unsigned char e7t_serial_in_buf0[CYGNUM_IO_SERIAL_ARM_E7T_SERIAL0_BUFSIZE];
110
 
111
static SERIAL_CHANNEL_USING_INTERRUPTS(e7t_serial_channel0,
112
                                       e7t_serial_funs,
113
                                       e7t_serial_info0,
114
                                       CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_E7T_SERIAL0_BAUD),
115
                                       CYG_SERIAL_STOP_DEFAULT,
116
                                       CYG_SERIAL_PARITY_DEFAULT,
117
                                       CYG_SERIAL_WORD_LENGTH_DEFAULT,
118
                                       CYG_SERIAL_FLAGS_DEFAULT,
119
                                       &e7t_serial_out_buf0[0], sizeof(e7t_serial_out_buf0),
120
                                       &e7t_serial_in_buf0[0], sizeof(e7t_serial_in_buf0)
121
    );
122
#else                                           CYGNUM_HAL_INTERRUPT_UART0_TX
123
static SERIAL_CHANNEL(e7t_serial_channel0,
124
                      e7t_serial_funs,
125
                      e7t_serial_info0,
126
                      CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_E7T_SERIAL0_BAUD),
127
                      CYG_SERIAL_STOP_DEFAULT,
128
                      CYG_SERIAL_PARITY_DEFAULT,
129
                      CYG_SERIAL_WORD_LENGTH_DEFAULT,
130
                      CYG_SERIAL_FLAGS_DEFAULT
131
    );
132
#endif
133
 
134
DEVTAB_ENTRY(e7t_serial_io0,
135
             CYGDAT_IO_SERIAL_ARM_E7T_SERIAL0_NAME,
136
             0,                     // Does not depend on a lower level interface
137
             &cyg_io_serial_devio,
138
             e7t_serial_init,
139
             e7t_serial_lookup,     // Serial driver may need initializing
140
             &e7t_serial_channel0
141
    );
142
#endif //  CYGPKG_IO_SERIAL_ARM_E7T_SERIAL0
143
 
144
#ifdef CYGPKG_IO_SERIAL_ARM_E7T_SERIAL1
145
static e7t_serial_info e7t_serial_info1 = {0x07FFe000,
146
                                           CYGNUM_HAL_INTERRUPT_UART1_TX,
147
                                           CYGNUM_HAL_INTERRUPT_UART1_RX};
148
#if CYGNUM_IO_SERIAL_ARM_E7T_SERIAL1_BUFSIZE > 0
149
static unsigned char e7t_serial_out_buf1[CYGNUM_IO_SERIAL_ARM_E7T_SERIAL1_BUFSIZE];
150
static unsigned char e7t_serial_in_buf1[CYGNUM_IO_SERIAL_ARM_E7T_SERIAL1_BUFSIZE];
151
 
152
static SERIAL_CHANNEL_USING_INTERRUPTS(e7t_serial_channel1,
153
                                       e7t_serial_funs,
154
                                       e7t_serial_info1,
155
                                       CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_E7T_SERIAL1_BAUD),
156
                                       CYG_SERIAL_STOP_DEFAULT,
157
                                       CYG_SERIAL_PARITY_DEFAULT,
158
                                       CYG_SERIAL_WORD_LENGTH_DEFAULT,
159
                                       CYG_SERIAL_FLAGS_DEFAULT,
160
                                       &e7t_serial_out_buf1[0], sizeof(e7t_serial_out_buf1),
161
                                       &e7t_serial_in_buf1[0], sizeof(e7t_serial_in_buf1)
162
    );
163
#else
164
static SERIAL_CHANNEL(e7t_serial_channel1,
165
                      e7t_serial_funs,
166
                      e7t_serial_info1,
167
                      CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_E7T_SERIAL1_BAUD),
168
                      CYG_SERIAL_STOP_DEFAULT,
169
                      CYG_SERIAL_PARITY_DEFAULT,
170
                      CYG_SERIAL_WORD_LENGTH_DEFAULT,
171
                      CYG_SERIAL_FLAGS_DEFAULT
172
    );
173
#endif
174
 
175
DEVTAB_ENTRY(e7t_serial_io1,
176
             CYGDAT_IO_SERIAL_ARM_E7T_SERIAL1_NAME,
177
             0,                     // Does not depend on a lower level interface
178
             &cyg_io_serial_devio,
179
             e7t_serial_init,
180
             e7t_serial_lookup,     // Serial driver may need initializing
181
             &e7t_serial_channel1
182
    );
183
#endif //  CYGPKG_IO_SERIAL_ARM_E7T_SERIAL1
184
 
185
// Internal function to actually configure the hardware to desired baud rate, etc.
186
static bool
187
e7t_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init)
188
{
189
  e7t_serial_info *e7t_chan = (e7t_serial_info *)chan->dev_priv;
190
  volatile struct serial_port *port = (volatile struct serial_port *)e7t_chan->base;
191
  cyg_uint32 word_length = select_word_length[(new_config->word_length)-CYGNUM_SERIAL_WORD_LENGTH_5];
192
  cyg_uint32 stop_bits = select_stop_bits[(new_config->stop)-CYGNUM_SERIAL_STOP_1];
193
  cyg_uint32 parity_mode = select_parity[(new_config->parity)-CYGNUM_SERIAL_PARITY_NONE];
194
  cyg_uint32 baud_divisor = select_baud[(new_config->baud)-CYGNUM_SERIAL_BAUD_50];
195
  cyg_uint32 res = word_length | stop_bits | parity_mode | ULCON_SCI | ULCON_IROFF;
196
  if ((word_length|stop_bits|parity_mode|baud_divisor) == U_NOT_SUPP) {
197
    return false;
198
  };
199
  port->REG_ULCON = res;
200
  port->REG_UCON = UCON_RXMINT | UCON_RXSIOFF | UCON_TXMINT | UCON_DSROFF | UCON_SBKOFF | UCON_LPBOFF;
201
  port->REG_UBRDIV = baud_divisor;
202
  if (new_config != &chan->config) {
203
    chan->config = *new_config;
204
  };
205
  return true;
206
}
207
 
208
// Function to initialize the device.  Called at bootstrap time.
209
static bool
210
e7t_serial_init(struct cyg_devtab_entry *tab)
211
{
212
    serial_channel *chan = (serial_channel *)tab->priv;
213
    e7t_serial_info *e7t_chan = (e7t_serial_info *)chan->dev_priv;
214
#ifdef CYGDBG_IO_INIT
215
    diag_printf("E7T SERIAL init - dev: %x.%d.%d\n", e7t_chan->base, e7t_chan->tx_int_num, e7t_chan->rx_int_num);
216
#endif
217
    (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
218
    if (chan->out_cbuf.len != 0) {         // If bufferlength > 0 then interrupts are used for tx
219
        cyg_drv_interrupt_create(e7t_chan->tx_int_num,
220
                                 99,                     // Priority - unused
221
                                 (cyg_addrword_t)chan,   //  Data item passed to interrupt handler
222
                                 e7t_serial_tx_ISR,
223
                                 e7t_serial_tx_DSR,
224
                                 &e7t_chan->serial_tx_interrupt_handle,
225
                                 &e7t_chan->serial_tx_interrupt);
226
        cyg_drv_interrupt_attach(e7t_chan->serial_tx_interrupt_handle);
227
        cyg_drv_interrupt_mask(e7t_chan->tx_int_num);
228
        e7t_chan->tx_enabled = false;
229
    }
230
    if (chan->in_cbuf.len != 0) {         // If bufferlength > 0 then interrupts are used for rx
231
        cyg_drv_interrupt_create(e7t_chan->rx_int_num,
232
                                 99,                     // Priority - unused
233
                                 (cyg_addrword_t)chan,   //  Data item passed to interrupt handler
234
                                 e7t_serial_rx_ISR,
235
                                 e7t_serial_rx_DSR,
236
                                 &e7t_chan->serial_rx_interrupt_handle,
237
                                 &e7t_chan->serial_rx_interrupt);
238
        cyg_drv_interrupt_attach(e7t_chan->serial_rx_interrupt_handle);
239
        cyg_drv_interrupt_unmask(e7t_chan->rx_int_num);
240
    }
241
    e7t_serial_config_port(chan, &chan->config, true);
242
    return true;
243
}
244
 
245
// This routine is called when the device is "looked" up (i.e. attached)
246
static Cyg_ErrNo
247
e7t_serial_lookup(struct cyg_devtab_entry **tab,
248
                  struct cyg_devtab_entry *sub_tab,
249
                  const char *name)
250
{
251
    serial_channel *chan = (serial_channel *)(*tab)->priv;
252
    (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
253
    return ENOERR;
254
}
255
 
256
// Send a character to the device output buffer.
257
// Return 'true' if character is sent to device
258
static bool
259
e7t_serial_putc(serial_channel *chan, unsigned char c)
260
{
261
    e7t_serial_info *e7t_chan = (e7t_serial_info *)chan->dev_priv;
262
    volatile struct serial_port *port = (volatile struct serial_port *)e7t_chan->base;
263
 
264
    if (port->REG_USTAT & USTAT_TBE) {
265
      // Transmit buffer is empty
266
      port->REG_UTXBUF = c;
267
      return true;
268
    } else {
269
      // No space
270
      return false;
271
    }
272
}
273
 
274
// Fetch a character from the device input buffer, waiting if necessary
275
static unsigned char
276
e7t_serial_getc(serial_channel *chan)
277
{
278
    unsigned char c;
279
    e7t_serial_info *e7t_chan = (e7t_serial_info *)chan->dev_priv;
280
    volatile struct serial_port *port = (volatile struct serial_port *)e7t_chan->base;
281
    while ((port->REG_USTAT & USTAT_RDR) == 0) ;   // Wait for char
282
    c = port->REG_URXBUF;
283
    return c;
284
}
285
 
286
// Set up the device characteristics; baud rate, etc.
287
static Cyg_ErrNo
288
e7t_serial_set_config(serial_channel *chan, cyg_uint32 key,
289
                      const void *xbuf, cyg_uint32 *len)
290
{
291
    switch (key) {
292
    case CYG_IO_SET_CONFIG_SERIAL_INFO:
293
      {
294
        cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf;
295
        if ( *len < sizeof(cyg_serial_info_t) ) {
296
            return -EINVAL;
297
        }
298
        *len = sizeof(cyg_serial_info_t);
299
        if ( true != e7t_serial_config_port(chan, config, false) )
300
            return -EINVAL;
301
      }
302
      break;
303
    default:
304
        return -EINVAL;
305
    }
306
    return ENOERR;
307
}
308
 
309
// Enable the transmitter on the device
310
static void
311
e7t_serial_start_xmit(serial_channel *chan)
312
{
313
    e7t_serial_info *e7t_chan = (e7t_serial_info *)chan->dev_priv;
314
    e7t_chan->tx_enabled = true;
315
    cyg_drv_interrupt_unmask(e7t_chan->tx_int_num);
316
}
317
 
318
// Disable the transmitter on the device
319
static void
320
e7t_serial_stop_xmit(serial_channel *chan)
321
{
322
    e7t_serial_info *e7t_chan = (e7t_serial_info *)chan->dev_priv;
323
    cyg_drv_interrupt_mask(e7t_chan->tx_int_num);
324
    e7t_chan->tx_enabled = false;
325
}
326
 
327
// Serial I/O - low level tx interrupt handler (ISR)
328
static cyg_uint32
329
e7t_serial_tx_ISR(cyg_vector_t vector, cyg_addrword_t data)
330
{
331
    serial_channel *chan = (serial_channel *)data;
332
    e7t_serial_info *e7t_chan = (e7t_serial_info *)chan->dev_priv;
333
    cyg_drv_interrupt_mask(e7t_chan->tx_int_num);
334
    cyg_drv_interrupt_acknowledge(e7t_chan->tx_int_num);
335
    return CYG_ISR_CALL_DSR;  // Cause DSR to be run
336
}
337
 
338
// Serial I/O - high level tx interrupt handler (DSR)
339
static void
340
e7t_serial_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
341
{
342
    serial_channel *chan = (serial_channel *)data;
343
    e7t_serial_info *e7t_chan = (e7t_serial_info *)chan->dev_priv;
344
    (chan->callbacks->xmt_char)(chan);
345
    if (e7t_chan->tx_enabled) {
346
        cyg_drv_interrupt_unmask(e7t_chan->tx_int_num);
347
    }
348
}
349
 
350
// Serial I/O - low level rx interrupt handler (ISR)
351
static cyg_uint32
352
e7t_serial_rx_ISR(cyg_vector_t vector, cyg_addrword_t data)
353
{
354
    serial_channel *chan = (serial_channel *)data;
355
    e7t_serial_info *e7t_chan = (e7t_serial_info *)chan->dev_priv;
356
    cyg_drv_interrupt_mask(e7t_chan->rx_int_num);
357
    cyg_drv_interrupt_acknowledge(e7t_chan->rx_int_num);
358
    return CYG_ISR_CALL_DSR;  // Cause DSR to be run
359
}
360
 
361
// Serial I/O - high level rx interrupt handler (DSR)
362
static void
363
e7t_serial_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
364
{
365
    serial_channel *chan = (serial_channel *)data;
366
    e7t_serial_info *e7t_chan = (e7t_serial_info *)chan->dev_priv;
367
    volatile struct serial_port *port = (volatile struct serial_port *)e7t_chan->base;
368
    (chan->callbacks->rcv_char)(chan, port->REG_URXBUF);
369
    cyg_drv_interrupt_unmask(e7t_chan->rx_int_num);
370
}
371
 
372
#endif // CYGPKG_IO_SERIAL_ARM_E7T
373
 
374
// EOF e7t_serial.c

powered by: WebSVN 2.1.0

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