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_sci.c] - Blame information for rev 791

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

Line No. Rev Author Line
1 786 skrzyp
//=============================================================================
2
//
3
//      sh3_sci.c
4
//
5
//      Simple driver for the SH Serial Communication Interface (SCI)
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:        1999-05-17
45
// Description: Simple driver for the SH Serial Communication Interface
46
//              Clients of this file can configure the behavior with:
47
//              CYGNUM_SCI_PORTS:  number of SCI ports
48
//
49
//####DESCRIPTIONEND####
50
//
51
//=============================================================================
52
 
53
#include <pkgconf/hal.h>
54
 
55
#ifdef CYGNUM_HAL_SH_SH3_SCI_PORTS
56
 
57
#include <cyg/hal/hal_io.h>             // IO macros
58
#include <cyg/hal/drv_api.h>            // CYG_ISR_HANDLED
59
#include <cyg/hal/hal_misc.h>           // Helper functions
60
#include <cyg/hal/hal_intr.h>           // HAL_ENABLE/MASK/UNMASK_INTERRUPTS
61
#include <cyg/hal/hal_arch.h>           // SAVE/RESTORE GP
62
#include <cyg/hal/hal_if.h>             // Calling-if API
63
#include <cyg/hal/sh_regs.h>            // serial register definitions
64
 
65
#define CYGPRI_HAL_SH_SH3_SCI_PRIVATE
66
#include <cyg/hal/sh3_sci.h>            // our header
67
 
68
//--------------------------------------------------------------------------
69
 
70
void
71
cyg_hal_plf_sci_init_channel(channel_data_t* chan)
72
{
73
    cyg_uint8 tmp;
74
    cyg_uint8* base = chan->base;
75
 
76
    // Disable Tx/Rx interrupts, but enable Tx/Rx
77
    HAL_WRITE_UINT8(base+_REG_SCSCR,
78
                    CYGARC_REG_SCI_SCSCR_TE|CYGARC_REG_SCI_SCSCR_RE);
79
 
80
    // 8-1-no parity.
81
    HAL_WRITE_UINT8(base+_REG_SCSMR, 0);
82
 
83
    // Set speed to CYGNUM_HAL_SH_SH3_SCI_DEFAULT_BAUD_RATE
84
    HAL_READ_UINT8(base+_REG_SCSMR, tmp);
85
    tmp &= ~CYGARC_REG_SCI_SCSMR_CKSx_MASK;
86
    tmp |= CYGARC_SCBRR_CKSx(CYGNUM_HAL_SH_SH3_SCI_BAUD_RATE);
87
    HAL_WRITE_UINT8(base+_REG_SCSMR, tmp);
88
    HAL_WRITE_UINT8(base+_REG_SCBRR, CYGARC_SCBRR_N(CYGNUM_HAL_SH_SH3_SCI_BAUD_RATE));
89
}
90
 
91
static cyg_bool
92
cyg_hal_plf_sci_getc_nonblock(void* __ch_data, cyg_uint8* ch)
93
{
94
    cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
95
    cyg_uint8 sr;
96
 
97
    HAL_READ_UINT8(base+_REG_SCSSR, sr);
98
    if (sr & CYGARC_REG_SCI_SCSSR_ORER) {
99
        // Serial RX overrun. Clear error and let caller try again.
100
        HAL_WRITE_UINT8(base+_REG_SCSSR,
101
                        CYGARC_REG_SCI_SCSSR_CLEARMASK & ~CYGARC_REG_SCI_SCSSR_ORER);
102
        return false;
103
    }
104
 
105
    if ((sr & CYGARC_REG_SCI_SCSSR_RDRF) == 0)
106
        return false;
107
 
108
    HAL_READ_UINT8(base+_REG_SCRDR, *ch);
109
 
110
    // Clear buffer full flag.
111
    HAL_WRITE_UINT8(base+_REG_SCSSR, sr & ~CYGARC_REG_SCI_SCSSR_RDRF);
112
 
113
    return true;
114
}
115
 
116
cyg_uint8
117
cyg_hal_plf_sci_getc(void* __ch_data)
118
{
119
    cyg_uint8 ch;
120
    CYGARC_HAL_SAVE_GP();
121
 
122
    while(!cyg_hal_plf_sci_getc_nonblock(__ch_data, &ch));
123
 
124
    CYGARC_HAL_RESTORE_GP();
125
    return ch;
126
}
127
 
128
void
129
cyg_hal_plf_sci_putc(void* __ch_data, cyg_uint8 c)
130
{
131
    cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
132
    cyg_uint8 sr;
133
    CYGARC_HAL_SAVE_GP();
134
 
135
    do {
136
        HAL_READ_UINT8(base+_REG_SCSSR, sr);
137
    } while ((sr & CYGARC_REG_SCI_SCSSR_TDRE) == 0);
138
 
139
    HAL_WRITE_UINT8(base+_REG_SCTDR, c);
140
 
141
    // Clear empty flag.
142
    HAL_WRITE_UINT8(base+_REG_SCSSR, sr & ~CYGARC_REG_SCI_SCSSR_TDRE);
143
 
144
    // Hang around until the character has been safely sent.
145
    do {
146
        HAL_READ_UINT8(base+_REG_SCSSR, sr);
147
    } while ((sr & CYGARC_REG_SCI_SCSSR_TDRE) == 0);
148
 
149
    CYGARC_HAL_RESTORE_GP();
150
}
151
 
152
 
153
static channel_data_t channels[CYGNUM_HAL_SH_SH3_SCI_PORTS];
154
 
155
static void
156
cyg_hal_plf_sci_write(void* __ch_data, const cyg_uint8* __buf,
157
                         cyg_uint32 __len)
158
{
159
    CYGARC_HAL_SAVE_GP();
160
 
161
    while(__len-- > 0)
162
        cyg_hal_plf_sci_putc(__ch_data, *__buf++);
163
 
164
    CYGARC_HAL_RESTORE_GP();
165
}
166
 
167
static void
168
cyg_hal_plf_sci_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
169
{
170
    CYGARC_HAL_SAVE_GP();
171
 
172
    while(__len-- > 0)
173
        *__buf++ = cyg_hal_plf_sci_getc(__ch_data);
174
 
175
    CYGARC_HAL_RESTORE_GP();
176
}
177
 
178
cyg_bool
179
cyg_hal_plf_sci_getc_timeout(void* __ch_data, cyg_uint8* ch)
180
{
181
    channel_data_t* chan = (channel_data_t*)__ch_data;
182
    int delay_count;
183
    cyg_bool res;
184
    CYGARC_HAL_SAVE_GP();
185
 
186
    delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
187
 
188
    for(;;) {
189
        res = cyg_hal_plf_sci_getc_nonblock(__ch_data, ch);
190
        if (res || 0 == delay_count--)
191
            break;
192
 
193
        CYGACC_CALL_IF_DELAY_US(100);
194
    }
195
 
196
    CYGARC_HAL_RESTORE_GP();
197
    return res;
198
}
199
 
200
static int
201
cyg_hal_plf_sci_control(void *__ch_data, __comm_control_cmd_t __func, ...)
202
{
203
    static int irq_state = 0;
204
    channel_data_t* chan = (channel_data_t*)__ch_data;
205
    cyg_uint8 scr;
206
    int ret = 0;
207
    CYGARC_HAL_SAVE_GP();
208
 
209
    switch (__func) {
210
    case __COMMCTL_IRQ_ENABLE:
211
        irq_state = 1;
212
        HAL_INTERRUPT_UNMASK(chan->isr_vector);
213
        HAL_READ_UINT8(chan->base+_REG_SCSCR, scr);
214
        scr |= CYGARC_REG_SCI_SCSCR_RIE;
215
        HAL_WRITE_UINT8(chan->base+_REG_SCSCR, scr);
216
        break;
217
    case __COMMCTL_IRQ_DISABLE:
218
        ret = irq_state;
219
        irq_state = 0;
220
        HAL_INTERRUPT_UNMASK(chan->isr_vector);
221
        HAL_READ_UINT8(chan->base+_REG_SCSCR, scr);
222
        scr &= ~CYGARC_REG_SCI_SCSCR_RIE;
223
        HAL_WRITE_UINT8(chan->base+_REG_SCSCR, scr);
224
        break;
225
    case __COMMCTL_DBG_ISR_VECTOR:
226
        ret = chan->isr_vector;
227
        break;
228
    case __COMMCTL_SET_TIMEOUT:
229
    {
230
        va_list ap;
231
 
232
        va_start(ap, __func);
233
 
234
        ret = chan->msec_timeout;
235
        chan->msec_timeout = va_arg(ap, cyg_uint32);
236
 
237
        va_end(ap);
238
    }
239
    default:
240
        break;
241
    }
242
    CYGARC_HAL_RESTORE_GP();
243
    return ret;
244
}
245
 
246
static int
247
cyg_hal_plf_sci_isr(void *__ch_data, int* __ctrlc,
248
                    CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
249
{
250
    cyg_uint8 c, sr;
251
    cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
252
    int res = 0;
253
    CYGARC_HAL_SAVE_GP();
254
 
255
    *__ctrlc = 0;
256
    HAL_READ_UINT8(base+_REG_SCSSR, sr);
257
    if (sr & CYGARC_REG_SCI_SCSSR_ORER) {
258
        // Serial RX overrun. Clear error and hope protocol recovers.
259
        HAL_WRITE_UINT8(base+_REG_SCSSR,
260
                        CYGARC_REG_SCI_SCSSR_CLEARMASK & ~CYGARC_REG_SCI_SCSSR_ORER);
261
        res = CYG_ISR_HANDLED;
262
    } else if (sr & CYGARC_REG_SCI_SCSSR_RDRF) {
263
        // Received character
264
        HAL_READ_UINT8(base+_REG_SCRDR, c);
265
 
266
        // Clear buffer full flag.
267
        HAL_WRITE_UINT8(base+_REG_SCSSR,
268
                        CYGARC_REG_SCI_SCSSR_CLEARMASK & ~CYGARC_REG_SCI_SCSSR_RDRF);
269
 
270
        if( cyg_hal_is_break( &c , 1 ) )
271
            *__ctrlc = 1;
272
 
273
        res = CYG_ISR_HANDLED;
274
    }
275
 
276
    CYGARC_HAL_RESTORE_GP();
277
    return res;
278
}
279
 
280
void
281
cyg_hal_plf_sci_init(int sci_index, int comm_index,
282
                     int rcv_vect, cyg_uint8* base)
283
{
284
    channel_data_t* chan = &channels[sci_index];
285
    hal_virtual_comm_table_t* comm;
286
    int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
287
 
288
    // Initialize channel table
289
    chan->base = base;
290
    chan->isr_vector = rcv_vect;
291
    chan->msec_timeout = 1000;
292
 
293
    // Disable interrupts.
294
    HAL_INTERRUPT_MASK(chan->isr_vector);
295
 
296
    // Init channel
297
 
298
    cyg_hal_plf_sci_init_channel(chan);
299
 
300
    // Setup procs in the vector table
301
 
302
    // Initialize channel procs
303
    CYGACC_CALL_IF_SET_CONSOLE_COMM(comm_index);
304
    comm = CYGACC_CALL_IF_CONSOLE_PROCS();
305
    CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
306
    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_sci_write);
307
    CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_sci_read);
308
    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_sci_putc);
309
    CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_sci_getc);
310
    CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_sci_control);
311
    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_sci_isr);
312
    CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_sci_getc_timeout);
313
 
314
    // Restore original console
315
    CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
316
}
317
 
318
#endif // CYGNUM_HAL_SH_SH3_SCI_PORTS
319
 
320
//-----------------------------------------------------------------------------
321
// end of sh_sci.c

powered by: WebSVN 2.1.0

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