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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [h8300/] [arch/] [current/] [src/] [sci.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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