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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [sh/] [sh3/] [current/] [src/] [sh3_scif.c] - Blame information for rev 838

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

Line No. Rev Author Line
1 786 skrzyp
//=============================================================================
2
//
3
//      sh3_scif.c
4
//
5
//      Simple driver for the SH3 Serial Communication Interface with FIFO
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):   jskov
43
// Contributors:jskov
44
// Date:        2000-03-30
45
// Description: Simple driver for the SH Serial Communication Interface
46
//              The driver can be used for either the SCIF or the IRDA
47
//              modules (the latter can act as the former).
48
//              Clients of this file can configure the behavior with:
49
//              CYGNUM_SCIF_PORTS: number of SCI ports
50
//
51
// Note:        It should be possible to configure a channel to IRDA mode.
52
//              Worry about that when some board needs it.
53
//
54
//####DESCRIPTIONEND####
55
//
56
//=============================================================================
57
 
58
#include <pkgconf/hal.h>
59
 
60
#ifdef CYGNUM_HAL_SH_SH3_SCIF_PORTS
61
 
62
#include <cyg/hal/hal_io.h>             // IO macros
63
#include <cyg/hal/drv_api.h>            // CYG_ISR_HANDLED
64
#include <cyg/hal/hal_misc.h>           // Helper functions
65
#include <cyg/hal/hal_intr.h>           // HAL_ENABLE/MASK/UNMASK_INTERRUPTS
66
#include <cyg/hal/hal_arch.h>           // SAVE/RESTORE GP
67
#include <cyg/hal/hal_if.h>             // Calling-if API
68
#include <cyg/hal/sh_regs.h>            // serial register definitions
69
#include <cyg/hal/sh_stub.h>            // target_register_t
70
 
71
#define CYGPRI_HAL_SH_SH3_SCIF_PRIVATE
72
#include <cyg/hal/sh3_scif.h>           // our header
73
 
74
//--------------------------------------------------------------------------
75
 
76
void
77
cyg_hal_plf_scif_init_channel(channel_data_t* chan)
78
{
79
    cyg_uint8* base = chan->base;
80
    cyg_uint8 tmp;
81
    cyg_uint16 sr;
82
 
83
    // Disable everything.
84
    HAL_WRITE_UINT8(base+_REG_SCSCR, 0);
85
 
86
    // Reset FIFO.
87
    HAL_WRITE_UINT8(base+_REG_SCFCR,
88
                    CYGARC_REG_SCIF_SCFCR_TFRST|CYGARC_REG_SCIF_SCFCR_RFRST);
89
 
90
    // 8-1-no parity.
91
    HAL_WRITE_UINT8(base+_REG_SCSMR, 0);
92
 
93
    // Set speed to CYGNUM_HAL_SH_SH3_SCIF_DEFAULT_BAUD_RATE
94
    HAL_READ_UINT8(base+_REG_SCSMR, tmp);
95
    tmp &= ~CYGARC_REG_SCIF_SCSMR_CKSx_MASK;
96
    tmp |= CYGARC_SCBRR_CKSx(CYGNUM_HAL_SH_SH3_SCIF_BAUD_RATE);
97
    HAL_WRITE_UINT8(base+_REG_SCSMR, tmp);
98
    HAL_WRITE_UINT8(base+_REG_SCBRR, CYGARC_SCBRR_N(CYGNUM_HAL_SH_SH3_SCIF_BAUD_RATE));
99
 
100
    // Let things settle: Here we should should wait the equivalent of
101
    // one bit interval,
102
    // i.e. 1/CYGNUM_HAL_SH_SH3_SCIF_DEFAULT_BAUD_RATE second, but
103
    // until we have something like the Linux delay loop, it's hard to
104
    // do reliably. So just move on and hope for the best (this is
105
    // unlikely to cause problems since the CPU has just come out of
106
    // reset anyway).
107
 
108
    // Clear status register (read back first).
109
    HAL_READ_UINT16(base+_REG_SCSSR, sr);
110
    HAL_WRITE_UINT16(base+_REG_SCSSR, 0);
111
 
112
    // Bring FIFO out of reset and set to trigger on every char in
113
    // FIFO (or C-c input would not be processed).
114
    HAL_WRITE_UINT8(base+_REG_SCFCR,
115
                    CYGARC_REG_SCIF_SCFCR_RTRG_1|CYGARC_REG_SCIF_SCFCR_TTRG_1);
116
 
117
    // Leave Tx/Rx interrupts disabled, but enable Tx/Rx
118
    HAL_WRITE_UINT8(base+_REG_SCSCR,
119
                    CYGARC_REG_SCIF_SCSCR_TE|CYGARC_REG_SCIF_SCSCR_RE);
120
}
121
 
122
//static 
123
cyg_bool
124
cyg_hal_plf_scif_getc_nonblock(void* __ch_data, cyg_uint8* ch)
125
{
126
    cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
127
    cyg_uint16 fdr, sr;
128
 
129
    HAL_READ_UINT16(base+_REG_SCFDR, fdr);
130
    if (0 == (fdr & CYGARC_REG_SCIF_SCFDR_RCOUNT_MASK))
131
        return false;
132
 
133
    HAL_READ_UINT8(base+_REG_SCFRDR, *ch);
134
 
135
    // Clear DR/RDF flags
136
    HAL_READ_UINT16(base+_REG_SCSSR, sr);
137
    HAL_WRITE_UINT16(base+_REG_SCSSR,
138
                     CYGARC_REG_SCIF_SCSSR_CLEARMASK & ~(CYGARC_REG_SCIF_SCSSR_RDF | CYGARC_REG_SCIF_SCSSR_DR));
139
 
140
    return true;
141
}
142
 
143
cyg_uint8
144
cyg_hal_plf_scif_getc(void* __ch_data)
145
{
146
    cyg_uint8 ch;
147
    CYGARC_HAL_SAVE_GP();
148
 
149
    while(!cyg_hal_plf_scif_getc_nonblock(__ch_data, &ch));
150
 
151
    CYGARC_HAL_RESTORE_GP();
152
    return ch;
153
}
154
 
155
void
156
cyg_hal_plf_scif_putc(void* __ch_data, cyg_uint8 c)
157
{
158
    cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
159
    cyg_uint16 fdr, sr;
160
    CYGARC_HAL_SAVE_GP();
161
 
162
    do {
163
        HAL_READ_UINT16(base+_REG_SCFDR, fdr);
164
    } while (((fdr & CYGARC_REG_SCIF_SCFDR_TCOUNT_MASK) >> CYGARC_REG_SCIF_SCFDR_TCOUNT_shift) == 16);
165
 
166
    HAL_WRITE_UINT8(base+_REG_SCFTDR, c);
167
 
168
    // Clear FIFO-empty/transmit end flags (read back SR first)
169
    HAL_READ_UINT16(base+_REG_SCSSR, sr);
170
    HAL_WRITE_UINT16(base+_REG_SCSSR, CYGARC_REG_SCIF_SCSSR_CLEARMASK
171
                     & ~(CYGARC_REG_SCIF_SCSSR_TDFE | CYGARC_REG_SCIF_SCSSR_TEND ));
172
 
173
    // Hang around until the character has been safely sent.
174
    do {
175
        HAL_READ_UINT16(base+_REG_SCFDR, fdr);
176
    } while ((fdr & CYGARC_REG_SCIF_SCFDR_TCOUNT_MASK) != 0);
177
 
178
    CYGARC_HAL_RESTORE_GP();
179
}
180
 
181
 
182
static channel_data_t channels[CYGNUM_HAL_SH_SH3_SCIF_PORTS];
183
 
184
static void
185
cyg_hal_plf_scif_write(void* __ch_data, const cyg_uint8* __buf,
186
                         cyg_uint32 __len)
187
{
188
    CYGARC_HAL_SAVE_GP();
189
 
190
    while(__len-- > 0)
191
        cyg_hal_plf_scif_putc(__ch_data, *__buf++);
192
 
193
    CYGARC_HAL_RESTORE_GP();
194
}
195
 
196
static void
197
cyg_hal_plf_scif_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
198
{
199
    CYGARC_HAL_SAVE_GP();
200
 
201
    while(__len-- > 0)
202
        *__buf++ = cyg_hal_plf_scif_getc(__ch_data);
203
 
204
    CYGARC_HAL_RESTORE_GP();
205
}
206
 
207
cyg_bool
208
cyg_hal_plf_scif_getc_timeout(void* __ch_data, cyg_uint8* ch)
209
{
210
    channel_data_t* chan = (channel_data_t*)__ch_data;
211
    int delay_count;
212
    cyg_bool res;
213
    CYGARC_HAL_SAVE_GP();
214
 
215
    delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
216
 
217
    for(;;) {
218
        res = cyg_hal_plf_scif_getc_nonblock(__ch_data, ch);
219
        if (res || 0 == delay_count--)
220
            break;
221
 
222
        CYGACC_CALL_IF_DELAY_US(100);
223
    }
224
 
225
    CYGARC_HAL_RESTORE_GP();
226
    return res;
227
}
228
 
229
static int
230
cyg_hal_plf_scif_control(void *__ch_data, __comm_control_cmd_t __func, ...)
231
{
232
    static int irq_state = 0;
233
    channel_data_t* chan = (channel_data_t*)__ch_data;
234
    cyg_uint8 scr;
235
    int ret = 0;
236
    CYGARC_HAL_SAVE_GP();
237
 
238
    switch (__func) {
239
    case __COMMCTL_IRQ_ENABLE:
240
        irq_state = 1;
241
        HAL_INTERRUPT_UNMASK(chan->isr_vector);
242
        HAL_READ_UINT8(chan->base+_REG_SCSCR, scr);
243
        scr |= CYGARC_REG_SCIF_SCSCR_RIE;
244
        HAL_WRITE_UINT8(chan->base+_REG_SCSCR, scr);
245
        break;
246
    case __COMMCTL_IRQ_DISABLE:
247
        ret = irq_state;
248
        irq_state = 0;
249
        HAL_INTERRUPT_UNMASK(chan->isr_vector);
250
        HAL_READ_UINT8(chan->base+_REG_SCSCR, scr);
251
        scr &= ~CYGARC_REG_SCIF_SCSCR_RIE;
252
        HAL_WRITE_UINT8(chan->base+_REG_SCSCR, scr);
253
        break;
254
    case __COMMCTL_DBG_ISR_VECTOR:
255
        ret = chan->isr_vector;
256
        break;
257
    case __COMMCTL_SET_TIMEOUT:
258
    {
259
        va_list ap;
260
 
261
        va_start(ap, __func);
262
 
263
        ret = chan->msec_timeout;
264
        chan->msec_timeout = va_arg(ap, cyg_uint32);
265
 
266
        va_end(ap);
267
    }
268
    default:
269
        break;
270
    }
271
    CYGARC_HAL_RESTORE_GP();
272
    return ret;
273
}
274
 
275
static int
276
cyg_hal_plf_scif_isr(void *__ch_data, int* __ctrlc,
277
                     CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
278
{
279
    cyg_uint8 c;
280
    cyg_uint16 fdr, sr;
281
    cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
282
    int res = 0;
283
    CYGARC_HAL_SAVE_GP();
284
 
285
    *__ctrlc = 0;
286
    HAL_READ_UINT16(base+_REG_SCFDR, fdr);
287
    if ((fdr & CYGARC_REG_SCIF_SCFDR_RCOUNT_MASK) != 0) {
288
        HAL_READ_UINT8(base+_REG_SCFRDR, c);
289
 
290
        // Clear buffer full flag (read back first).
291
        HAL_READ_UINT16(base+_REG_SCSSR, sr);
292
        HAL_WRITE_UINT16(base+_REG_SCSSR,
293
                         CYGARC_REG_SCIF_SCSSR_CLEARMASK & ~CYGARC_REG_SCIF_SCSSR_RDF);
294
 
295
        if( cyg_hal_is_break( &c , 1 ) )
296
            *__ctrlc = 1;
297
 
298
        res = CYG_ISR_HANDLED;
299
    }
300
 
301
    CYGARC_HAL_RESTORE_GP();
302
    return res;
303
}
304
 
305
void
306
cyg_hal_plf_scif_init(int scif_index, int comm_index,
307
                      int rcv_vect, cyg_uint8* base)
308
{
309
    channel_data_t* chan = &channels[scif_index];
310
    hal_virtual_comm_table_t* comm;
311
    int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
312
 
313
    // Initialize channel table
314
    chan->base = base;
315
    chan->isr_vector = rcv_vect;
316
    chan->msec_timeout = 1000;
317
 
318
    // Disable interrupts.
319
    HAL_INTERRUPT_MASK(chan->isr_vector);
320
 
321
    // Init channel
322
    cyg_hal_plf_scif_init_channel(chan);
323
 
324
    // Setup procs in the vector table
325
 
326
    // Initialize channel procs
327
    CYGACC_CALL_IF_SET_CONSOLE_COMM(comm_index);
328
    comm = CYGACC_CALL_IF_CONSOLE_PROCS();
329
    CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
330
    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_scif_write);
331
    CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_scif_read);
332
    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_scif_putc);
333
    CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_scif_getc);
334
    CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_scif_control);
335
    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_scif_isr);
336
    CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_scif_getc_timeout);
337
 
338
    // Restore original console
339
    CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
340
}
341
 
342
#endif // CYGNUM_HAL_SH_SH3_SCIF_PORTS
343
 
344
//-----------------------------------------------------------------------------
345
// end of sh3_scif.c

powered by: WebSVN 2.1.0

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