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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [powerpc/] [ppc40x/] [current/] [src/] [hal_diag.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//=============================================================================
2
//
3
//      hal_diag.c
4
//
5
//      HAL diagnostic I/O code
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, 2003, 2004 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):   hmt
43
// Contributors:hmt, gthomas
44
// Date:        1999-06-08
45
// Purpose:     HAL diagnostic output
46
// Description: Implementations of HAL diagnostic I/O support.
47
//
48
//####DESCRIPTIONEND####
49
//
50
//=============================================================================
51
 
52
#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS
53
#include <pkgconf/hal.h>
54
 
55
#include <cyg/infra/cyg_type.h>         // base types
56
#include <cyg/infra/cyg_trac.h>         // tracing macros
57
#include <cyg/infra/cyg_ass.h>          // assertion macros
58
 
59
#include <cyg/hal/hal_io.h>             // IO macros
60
#include <cyg/hal/hal_diag.h>
61
#include <cyg/hal/hal_intr.h>           // Interrupt macros
62
#include <cyg/hal/drv_api.h>
63
 
64
#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
65
#include <cyg/hal/hal_stub.h>           // hal_output_gdb_string
66
#endif
67
 
68
#include <cyg/hal/ppc_regs.h>
69
 
70
//=============================================================================
71
// Serial driver
72
//=============================================================================
73
 
74
//-----------------------------------------------------------------------------
75
// There are two serial ports.
76
#if defined(CYGHWR_HAL_POWERPC_PPC4XX_405) || defined(CYGHWR_HAL_POWERPC_PPC4XX_405GP)
77
#define CYG_DEV_SERIAL_BASE_A    _PPC405GP_UART0
78
#define CYG_DEV_SERIAL_BASE_B    _PPC405GP_UART1
79
#endif
80
#if defined(CYGHWR_HAL_POWERPC_PPC4XX_405EP)
81
#define CYG_DEV_SERIAL_BASE_A    _PPC405EP_UART0
82
#define CYG_DEV_SERIAL_BASE_B    _PPC405EP_UART1
83
#endif
84
//-----------------------------------------------------------------------------
85
// Define the serial registers. The PPC405GP has 16552 UART(s) builtin.
86
// The PPC405EP has 16750 UART(s) builtin
87
#define CYG_DEV_SERIAL_RBR   0x00  // receiver buffer register, read, dlab = 0
88
#define CYG_DEV_SERIAL_THR   0x00 // transmitter holding register, write, dlab = 0
89
#define CYG_DEV_SERIAL_DLL   0x00 // divisor latch (LS), read/write, dlab = 1
90
#define CYG_DEV_SERIAL_IER   0x01 // interrupt enable register, read/write, dlab = 0
91
#define CYG_DEV_SERIAL_DLM   0x01 // divisor latch (MS), read/write, dlab = 1
92
#define CYG_DEV_SERIAL_IIR   0x02 // interrupt identification register, read, dlab = 0
93
#define CYG_DEV_SERIAL_FCR   0x02 // fifo control register, write, dlab = 0
94
#define CYG_DEV_SERIAL_AFR   0x02 // alternate function register, read/write, dlab = 1
95
#define CYG_DEV_SERIAL_LCR   0x03 // line control register, read/write
96
#define CYG_DEV_SERIAL_MCR   0x04
97
#define CYG_DEV_SERIAL_MCR_A 0x04
98
#define CYG_DEV_SERIAL_MCR_B 0x04
99
#define CYG_DEV_SERIAL_LSR   0x05 // line status register, read
100
#define CYG_DEV_SERIAL_MSR   0x06 // modem status register, read
101
#define CYG_DEV_SERIAL_SCR   0x07 // scratch pad register
102
 
103
// The interrupt enable register bits.
104
#define SIO_IER_ERDAI   0x01            // enable received data available irq
105
#define SIO_IER_ETHREI  0x02            // enable THR empty interrupt
106
#define SIO_IER_ELSI    0x04            // enable receiver line status irq
107
#define SIO_IER_EMSI    0x08            // enable modem status interrupt
108
 
109
// The interrupt identification register bits.
110
#define SIO_IIR_IP      0x01            // 0 if interrupt pending
111
#define SIO_IIR_ID_MASK 0x0e            // mask for interrupt ID bits
112
#define ISR_Tx  0x02
113
#define ISR_Rx  0x04
114
 
115
// The line status register bits.
116
#define SIO_LSR_DR      0x01            // data ready
117
#define SIO_LSR_OE      0x02            // overrun error
118
#define SIO_LSR_PE      0x04            // parity error
119
#define SIO_LSR_FE      0x08            // framing error
120
#define SIO_LSR_BI      0x10            // break interrupt
121
#define SIO_LSR_THRE    0x20            // transmitter holding register empty
122
#define SIO_LSR_TEMT    0x40            // transmitter register empty
123
#define SIO_LSR_ERR     0x80            // any error condition
124
 
125
// Modem control register
126
#define SIO_MCR_DTR     0x01            // [inverted] DTR
127
#define SIO_MCR_RTS     0x02            // [inverted] RTS
128
 
129
// The modem status register bits.
130
#define SIO_MSR_DCTS  0x01              // delta clear to send
131
#define SIO_MSR_DDSR  0x02              // delta data set ready
132
#define SIO_MSR_TERI  0x04              // trailing edge ring indicator
133
#define SIO_MSR_DDCD  0x08              // delta data carrier detect
134
#define SIO_MSR_CTS   0x10              // clear to send
135
#define SIO_MSR_DSR   0x20              // data set ready
136
#define SIO_MSR_RI    0x40              // ring indicator
137
#define SIO_MSR_DCD   0x80              // data carrier detect
138
 
139
// The line control register bits.
140
#define SIO_LCR_WLS0   0x01             // word length select bit 0
141
#define SIO_LCR_WLS1   0x02             // word length select bit 1
142
#define SIO_LCR_STB    0x04             // number of stop bits
143
#define SIO_LCR_PEN    0x08             // parity enable
144
#define SIO_LCR_EPS    0x10             // even parity select
145
#define SIO_LCR_SP     0x20             // stick parity
146
#define SIO_LCR_SB     0x40             // set break
147
#define SIO_LCR_DLAB   0x80             // divisor latch access bit
148
 
149
// The FIFO control register
150
#define SIO_FCR_FCR0   0x01             // enable xmit and rcvr fifos
151
#define SIO_FCR_FCR1   0x02             // clear RCVR FIFO
152
#define SIO_FCR_FCR2   0x04             // clear XMIT FIFO
153
 
154
 
155
//-----------------------------------------------------------------------------
156
typedef struct {
157
    cyg_uint8* base;
158
    cyg_int32 msec_timeout;
159
    int isr_vector;
160
} channel_data_t;
161
 
162
int
163
cyg_var_baud_generator(int baud)
164
{
165
    int clock_rate, baud_clock, clock_divisor;
166
    unsigned int cr0;
167
 
168
    // Calculate baud rate clock divisor
169
    CYGARC_MFDCR(DCR_CPC0_CR0, cr0);
170
    clock_divisor = ((cr0 & 0x3E) >> 1) + 1;
171
    clock_rate = ((CYGHWR_HAL_POWERPC_CPU_SPEED*1000000)/clock_divisor);
172
    baud_clock = ((clock_rate)/16)/baud;
173
    return baud_clock;
174
}
175
 
176
 
177
//-----------------------------------------------------------------------------
178
static void
179
init_serial_channel(const channel_data_t* __ch_data)
180
{
181
    cyg_uint8* base = __ch_data->base;
182
    cyg_uint8 lcr;
183
    int baud_clock = cyg_var_baud_generator(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD);
184
 
185
    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_IER, 0);
186
 
187
    // Disable and clear FIFOs (need to enable to clear).
188
    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_FCR,
189
                    (SIO_FCR_FCR0 | SIO_FCR_FCR1 | SIO_FCR_FCR2));
190
    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_FCR, 0);
191
 
192
    // 8-1-no parity.
193
    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, SIO_LCR_WLS0 | SIO_LCR_WLS1);
194
 
195
    // Set speed to the default baud rate
196
    HAL_READ_UINT8(base+CYG_DEV_SERIAL_LCR, lcr);
197
    lcr |= SIO_LCR_DLAB;
198
    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, lcr);
199
 
200
    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_DLL, baud_clock & 0xFF);
201
    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_DLM, (baud_clock >> 8) & 0xFF);
202
    lcr &= ~SIO_LCR_DLAB;
203
    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_LCR, lcr);
204
 
205
    // Enable FIFOs (and clear them).
206
    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_FCR,
207
                    (SIO_FCR_FCR0 | SIO_FCR_FCR1 | SIO_FCR_FCR2));
208
 
209
    // Assert handshake signals
210
    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_MCR, (SIO_MCR_DTR|SIO_MCR_RTS));
211
}
212
 
213
static cyg_bool
214
cyg_hal_var_serial_getc_nonblock(char* __ch_data, cyg_uint8* ch)
215
{
216
    cyg_uint8* base/* = ((channel_data_t*)__ch_data)->base*/;
217
    cyg_uint8 lsr;
218
 
219
    base = ((channel_data_t*)__ch_data)->base;
220
 
221
    HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr);
222
    if ((lsr & SIO_LSR_DR) == 0)
223
        return false;
224
 
225
    HAL_READ_UINT8(base+CYG_DEV_SERIAL_RBR, *ch);
226
 
227
    return true;
228
}
229
 
230
 
231
cyg_uint8
232
cyg_hal_var_serial_getc(void* __ch_data)
233
{
234
    cyg_uint8 ch;
235
 
236
    while(!cyg_hal_var_serial_getc_nonblock(__ch_data, &ch));
237
 
238
    return ch;
239
}
240
 
241
void
242
cyg_hal_var_serial_putc(void* __ch_data, cyg_uint8 c)
243
{
244
    cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
245
    cyg_uint8 lsr;
246
 
247
    do {
248
        HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr);
249
    } while ((lsr & SIO_LSR_THRE) == 0);
250
 
251
    HAL_WRITE_UINT8(base+CYG_DEV_SERIAL_THR, c);
252
 
253
    // Hang around until the character has been safely sent.
254
    do {
255
        HAL_READ_UINT8(base+CYG_DEV_SERIAL_LSR, lsr);
256
    } while ((lsr & SIO_LSR_THRE) == 0);
257
}
258
 
259
static const channel_data_t channels[2] = {
260
    { (cyg_uint8*)CYG_DEV_SERIAL_BASE_A, 1000, CYGNUM_HAL_INTERRUPT_UART0},
261
#if (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 1)
262
    { (cyg_uint8*)CYG_DEV_SERIAL_BASE_B, 1000, CYGNUM_HAL_INTERRUPT_UART1},
263
#endif
264
};
265
 
266
static void
267
cyg_hal_var_serial_write(void* __ch_data, const cyg_uint8* __buf,
268
                         cyg_uint32 __len)
269
{
270
    while(__len-- > 0)
271
        cyg_hal_var_serial_putc(__ch_data, *__buf++);
272
}
273
 
274
static void
275
cyg_hal_var_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
276
{
277
    while(__len-- > 0)
278
        *__buf++ = cyg_hal_var_serial_getc(__ch_data);
279
}
280
 
281
cyg_bool
282
cyg_hal_var_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
283
{
284
    int delay_count;
285
    channel_data_t* chan = (channel_data_t*)__ch_data;
286
    cyg_bool res;
287
 
288
    delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
289
    for(;;) {
290
        res = cyg_hal_var_serial_getc_nonblock(__ch_data, ch);
291
        if (res || 0 == delay_count--)
292
            break;
293
 
294
        CYGACC_CALL_IF_DELAY_US(100);
295
    }
296
    return res;
297
}
298
 
299
static int
300
cyg_hal_var_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...)
301
{
302
    static int irq_state = 0;
303
    channel_data_t* chan = (channel_data_t*)__ch_data;
304
    cyg_uint8 ier;
305
    int ret = 0;
306
 
307
    switch (__func) {
308
    case __COMMCTL_IRQ_ENABLE:
309
        HAL_INTERRUPT_UNMASK(chan->isr_vector);
310
        HAL_INTERRUPT_SET_LEVEL(chan->isr_vector, 1);
311
        HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier);
312
        ier |= SIO_IER_ERDAI;
313
        HAL_WRITE_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier);
314
        irq_state = 1;
315
        break;
316
    case __COMMCTL_IRQ_DISABLE:
317
        ret = irq_state;
318
        irq_state = 0;
319
        HAL_INTERRUPT_MASK(chan->isr_vector);
320
        HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier);
321
        ier &= ~SIO_IER_ERDAI;
322
        HAL_WRITE_UINT8(chan->base+CYG_DEV_SERIAL_IER, ier);
323
        break;
324
    case __COMMCTL_DBG_ISR_VECTOR:
325
        ret = chan->isr_vector;
326
        break;
327
    case __COMMCTL_SET_TIMEOUT:
328
    {
329
        va_list ap;
330
 
331
        va_start(ap, __func);
332
 
333
        ret = chan->msec_timeout;
334
        chan->msec_timeout = va_arg(ap, cyg_uint32);
335
 
336
        va_end(ap);
337
    }
338
    default:
339
        break;
340
    }
341
    return ret;
342
}
343
 
344
static int
345
cyg_hal_var_serial_isr(void *__ch_data, int* __ctrlc,
346
                       CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
347
{
348
    channel_data_t* chan = (channel_data_t*)__ch_data;
349
    cyg_uint8 _iir;
350
    int res = 0;
351
 
352
    HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_IIR, _iir);
353
    _iir &= SIO_IIR_ID_MASK;
354
 
355
    *__ctrlc = 0;
356
    if ( ISR_Rx == _iir ) {
357
        cyg_uint8 c, lsr;
358
        HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_LSR, lsr);
359
        if (lsr & SIO_LSR_DR) {
360
 
361
            HAL_READ_UINT8(chan->base+CYG_DEV_SERIAL_RBR, c);
362
 
363
            if( cyg_hal_is_break( &c , 1 ) )
364
                *__ctrlc = 1;
365
        }
366
 
367
        // Acknowledge the interrupt
368
        HAL_INTERRUPT_ACKNOWLEDGE(chan->isr_vector);
369
        res = CYG_ISR_HANDLED;
370
    }
371
    return res;
372
}
373
 
374
void
375
cyg_hal_var_serial_init(void)
376
{
377
    hal_virtual_comm_table_t* comm;
378
    int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
379
 
380
    // Disable interrupts.
381
    HAL_INTERRUPT_MASK(channels[0].isr_vector);
382
#if (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 1)
383
    HAL_INTERRUPT_MASK(channels[1].isr_vector);
384
#endif
385
 
386
    // Init channels
387
    init_serial_channel(&channels[0]);
388
#if (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 1)
389
    init_serial_channel(&channels[1]);
390
#endif
391
 
392
    // Setup procs in the vector table
393
 
394
    // Set channel 0
395
    CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
396
    comm = CYGACC_CALL_IF_CONSOLE_PROCS();
397
    CYGACC_COMM_IF_CH_DATA_SET(*comm, &channels[0]);
398
    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_var_serial_write);
399
    CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_var_serial_read);
400
    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_var_serial_putc);
401
    CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_var_serial_getc);
402
    CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_var_serial_control);
403
    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_var_serial_isr);
404
    CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_var_serial_getc_timeout);
405
 
406
#if (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 1)
407
    // Set channel 1
408
    CYGACC_CALL_IF_SET_CONSOLE_COMM(1);
409
    comm = CYGACC_CALL_IF_CONSOLE_PROCS();
410
    CYGACC_COMM_IF_CH_DATA_SET(*comm, &channels[1]);
411
    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_var_serial_write);
412
    CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_var_serial_read);
413
    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_var_serial_putc);
414
    CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_var_serial_getc);
415
    CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_var_serial_control);
416
    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_var_serial_isr);
417
    CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_var_serial_getc_timeout);
418
#endif
419
 
420
    // Restore original console
421
    CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
422
}
423
 
424
// EOF hal_diag.c

powered by: WebSVN 2.1.0

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