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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [arm/] [sa11x0/] [var/] [v2_0/] [src/] [hal_diag.c] - Blame information for rev 249

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

Line No. Rev Author Line
1 27 unneback
/*=============================================================================
2
//
3
//      hal_diag.c
4
//
5
//      HAL diagnostic output 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 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):   gthomas
44
// Contributors:nickg, gthomas, dmoseley
45
//              Travis C. Furrer <furrer@mit.edu>
46
// Date:        2000-05-08
47
// Purpose:     HAL diagnostic output
48
// Description: Implementations of HAL diagnostic output support.
49
//
50
//####DESCRIPTIONEND####
51
//
52
//===========================================================================*/
53
 
54
#include <pkgconf/hal.h>
55
#include <pkgconf/system.h>
56
#include CYGBLD_HAL_PLATFORM_H
57
 
58
#include <cyg/infra/cyg_type.h>         // base types
59
#include <cyg/infra/cyg_trac.h>         // tracing macros
60
#include <cyg/infra/cyg_ass.h>          // assertion macros
61
 
62
#include <cyg/hal/hal_arch.h>           // basic machine info
63
#include <cyg/hal/hal_intr.h>           // interrupt macros
64
#include <cyg/hal/hal_io.h>             // IO macros
65
#include <cyg/hal/hal_if.h>             // Calling interface definitions
66
#include <cyg/hal/hal_diag.h>
67
#include <cyg/hal/drv_api.h>            // cyg_drv_interrupt_acknowledge
68
#include <cyg/hal/hal_misc.h>           // Helper functions
69
#include <cyg/hal/hal_sa11x0.h>         // Hardware definitions
70
 
71
struct sa11x0_serial {
72
  volatile cyg_uint32 utcr0;
73
  volatile cyg_uint32 utcr1;
74
  volatile cyg_uint32 utcr2;
75
  volatile cyg_uint32 utcr3;
76
  volatile cyg_uint32 pad0010;
77
  volatile cyg_uint32 utdr;
78
  volatile cyg_uint32 pad0018;
79
  volatile cyg_uint32 utsr0;
80
  volatile cyg_uint32 utsr1;
81
};
82
 
83
//-----------------------------------------------------------------------------
84
typedef struct {
85
    volatile struct sa11x0_serial* base;
86
    cyg_int32 msec_timeout;
87
    int isr_vector;
88
    int baud_rate;
89
} channel_data_t;
90
 
91
/*---------------------------------------------------------------------------*/
92
// SA11x0 Serial Port (UARTx) for Debug
93
 
94
static void
95
init_channel(channel_data_t* __ch_data)
96
{
97
    volatile struct sa11x0_serial* base = __ch_data->base;
98
    cyg_uint32 brd;
99
 
100
    // Disable Receiver and Transmitter (clears FIFOs)
101
    base->utcr3 = SA11X0_UART_RX_DISABLED | SA11X0_UART_TX_DISABLED;
102
 
103
    // Clear sticky (writable) status bits.
104
    base->utsr0 = SA11X0_UART_RX_IDLE | SA11X0_UART_RX_BEGIN_OF_BREAK |
105
                  SA11X0_UART_RX_END_OF_BREAK;
106
 
107
#if defined(CYGPKG_HAL_ARM_SA11X0_SA1100MM) || defined(CYGPKG_HAL_ARM_SA11X0_BRUTUS)
108
   // This setup is specific to only a few boards.
109
   if (SA11X0_UART1_BASE == (volatile unsigned long *)base) {
110
        cyg_uint32 pdr, afr, par;
111
 
112
        HAL_READ_UINT32(SA11X0_GPIO_PIN_DIRECTION, pdr);
113
        HAL_READ_UINT32(SA11X0_GPIO_ALTERNATE_FUNCTION, afr);
114
        HAL_READ_UINT32(SA11X0_PPC_PIN_ASSIGNMENT, par);
115
 
116
        //Set pin 14 as an output (Tx) and pin 15 as in input (Rx).
117
        HAL_WRITE_UINT32(SA11X0_GPIO_PIN_DIRECTION, ((pdr | SA11X0_GPIO_PIN_14) & ~SA11X0_GPIO_PIN_15));
118
 
119
        // Use GPIO 14 & 15 pins for serial port 1.
120
        HAL_WRITE_UINT32(SA11X0_GPIO_ALTERNATE_FUNCTION, afr | SA11X0_GPIO_PIN_14 | SA11X0_GPIO_PIN_15);
121
 
122
        // Pin reassignment for serial port 1.
123
        HAL_WRITE_UINT32(SA11X0_PPC_PIN_ASSIGNMENT, par | SA11X0_PPC_UART_PIN_REASSIGNMENT_MASK);
124
    }
125
#endif
126
 
127
    // Set UART to 8N1 (8 data bits, no partity, 1 stop bit)
128
    base->utcr0 = SA11X0_UART_PARITY_DISABLED | SA11X0_UART_STOP_BITS_1 |
129
                  SA11X0_UART_DATA_BITS_8;
130
 
131
    // Set the desired baud rate.
132
    brd = SA11X0_UART_BAUD_RATE_DIVISOR(__ch_data->baud_rate);
133
    base->utcr1 = (brd >> 8) & SA11X0_UART_H_BAUD_RATE_DIVISOR_MASK;
134
    base->utcr2 = brd & SA11X0_UART_L_BAUD_RATE_DIVISOR_MASK;
135
 
136
    // Enable the receiver and the transmitter.
137
    base->utcr3 = SA11X0_UART_RX_ENABLED | SA11X0_UART_TX_ENABLED;
138
 
139
    // All done
140
}
141
 
142
void
143
cyg_hal_plf_serial_putc(void *__ch_data, char c)
144
{
145
    volatile struct sa11x0_serial* base = ((channel_data_t*)__ch_data)->base;
146
    CYGARC_HAL_SAVE_GP();
147
 
148
    // Wait for Tx FIFO not full
149
    while ((base->utsr1 & SA11X0_UART_TX_FIFO_NOT_FULL) == 0)
150
        ;
151
    base->utdr = c;
152
 
153
    CYGARC_HAL_RESTORE_GP();
154
}
155
 
156
// FIXME: shouldn't we check for PARITY_ERROR, FRAMING_ERROR, or
157
// RECEIVE_FIFO_OVERRUN_ERROR in the received data?  This
158
// means check the appropriate bits in UTSR1.
159
 
160
static cyg_bool
161
cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch)
162
{
163
    volatile struct sa11x0_serial* base = ((channel_data_t*)__ch_data)->base;
164
 
165
    // If receive fifo is empty, return false
166
    if ((base->utsr1 & SA11X0_UART_RX_FIFO_NOT_EMPTY) == 0)
167
        return false;
168
 
169
    *ch = (char)base->utdr;
170
 
171
    // Clear receiver idle status bit, to allow another interrupt to
172
    // occur in the case where the receive fifo is almost empty.
173
    base->utsr0 = SA11X0_UART_RX_IDLE;
174
 
175
    return true;
176
}
177
 
178
cyg_uint8
179
cyg_hal_plf_serial_getc(void* __ch_data)
180
{
181
    cyg_uint8 ch;
182
    CYGARC_HAL_SAVE_GP();
183
 
184
    while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch));
185
 
186
    CYGARC_HAL_RESTORE_GP();
187
    return ch;
188
}
189
 
190
static channel_data_t ser_channels[] = {
191
#if CYGHWR_HAL_ARM_SA11X0_UART1 != 0
192
    { (volatile struct sa11x0_serial*)SA11X0_UART1_BASE, 1000,
193
      CYGNUM_HAL_INTERRUPT_UART1, CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD },
194
#endif
195
#if CYGHWR_HAL_ARM_SA11X0_UART3 != 0
196
    { (volatile struct sa11x0_serial*)SA11X0_UART3_BASE, 1000,
197
      CYGNUM_HAL_INTERRUPT_UART3, CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD },
198
#endif
199
};
200
 
201
static void
202
cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf,
203
                         cyg_uint32 __len)
204
{
205
    CYGARC_HAL_SAVE_GP();
206
 
207
    while(__len-- > 0)
208
        cyg_hal_plf_serial_putc(__ch_data, *__buf++);
209
 
210
    CYGARC_HAL_RESTORE_GP();
211
}
212
 
213
static void
214
cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
215
{
216
    CYGARC_HAL_SAVE_GP();
217
 
218
    while(__len-- > 0)
219
        *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
220
 
221
    CYGARC_HAL_RESTORE_GP();
222
}
223
 
224
cyg_bool
225
cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
226
{
227
    int delay_count;
228
    channel_data_t* chan = (channel_data_t*)__ch_data;
229
    cyg_bool res;
230
    CYGARC_HAL_SAVE_GP();
231
 
232
    delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
233
 
234
    for(;;) {
235
        res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch);
236
        if (res || 0 == delay_count--)
237
            break;
238
 
239
        CYGACC_CALL_IF_DELAY_US(100);
240
    }
241
 
242
    CYGARC_HAL_RESTORE_GP();
243
    return res;
244
}
245
 
246
static int
247
cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...)
248
{
249
    static int irq_state = 0;
250
    channel_data_t* chan = (channel_data_t*)__ch_data;
251
    int ret = -1;
252
    va_list ap;
253
 
254
    CYGARC_HAL_SAVE_GP();
255
    va_start(ap, __func);
256
 
257
    switch (__func) {
258
    case __COMMCTL_GETBAUD:
259
        ret = chan->baud_rate;
260
        break;
261
    case __COMMCTL_SETBAUD:
262
        chan->baud_rate = va_arg(ap, cyg_int32);
263
        // Should we verify this value here?
264
        init_channel(chan);
265
        ret = 0;
266
        break;
267
    case __COMMCTL_IRQ_ENABLE:
268
        irq_state = 1;
269
 
270
        chan->base->utcr3 |= SA11X0_UART_RX_FIFO_INT_ENABLED;
271
 
272
        HAL_INTERRUPT_UNMASK(chan->isr_vector);
273
        break;
274
    case __COMMCTL_IRQ_DISABLE:
275
        ret = irq_state;
276
        irq_state = 0;
277
 
278
        chan->base->utcr3 &= ~SA11X0_UART_RX_FIFO_INT_ENABLED;
279
 
280
        HAL_INTERRUPT_MASK(chan->isr_vector);
281
        break;
282
    case __COMMCTL_DBG_ISR_VECTOR:
283
        ret = chan->isr_vector;
284
        break;
285
    case __COMMCTL_SET_TIMEOUT:
286
        ret = chan->msec_timeout;
287
        chan->msec_timeout = va_arg(ap, cyg_uint32);
288
        break;
289
    default:
290
        break;
291
    }
292
    va_end(ap);
293
    CYGARC_HAL_RESTORE_GP();
294
    return ret;
295
}
296
 
297
static int
298
cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc,
299
                       CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
300
{
301
    int res = 0;
302
    channel_data_t* chan = (channel_data_t*)__ch_data;
303
    char c;
304
    int reg;
305
    CYGARC_HAL_SAVE_GP();
306
 
307
    reg = chan->base->utsr1;
308
 
309
    // read it anyway just in case - no harm done and we might prevent an
310
    // interrupt loop
311
    c = (char)chan->base->utdr;
312
 
313
    // Clear receiver idle status bit, to allow another interrupt to
314
    // occur in the case where the receive fifo is almost empty.
315
    // Also for a break interrupt; these are sticky and nonmaskable.
316
    chan->base->utsr0 = (SA11X0_UART_RX_IDLE |
317
                         SA11X0_UART_RX_BEGIN_OF_BREAK |
318
                         SA11X0_UART_RX_END_OF_BREAK      );
319
 
320
    cyg_drv_interrupt_acknowledge(chan->isr_vector);
321
 
322
    *__ctrlc = 0;
323
    if ( (reg & SA11X0_UART_RX_FIFO_NOT_EMPTY) != 0 ) {
324
        if( cyg_hal_is_break( &c , 1 ) )
325
            *__ctrlc = 1;
326
 
327
        res = CYG_ISR_HANDLED;
328
    }
329
 
330
    CYGARC_HAL_RESTORE_GP();
331
    return res;
332
}
333
 
334
static void
335
cyg_hal_plf_serial_init(void)
336
{
337
    hal_virtual_comm_table_t* comm;
338
    int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
339
    int i;
340
 
341
    // Init channels
342
#define NUMOF(x) (sizeof(x)/sizeof(x[0]))
343
    for (i = 0;  i < NUMOF(ser_channels);  i++) {
344
        init_channel(&ser_channels[i]);
345
        CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
346
        comm = CYGACC_CALL_IF_CONSOLE_PROCS();
347
        CYGACC_COMM_IF_CH_DATA_SET(*comm, &ser_channels[i]);
348
        CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
349
        CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
350
        CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
351
        CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
352
        CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
353
        CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
354
        CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
355
    }
356
 
357
    // Restore original console
358
    CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
359
}
360
 
361
void
362
cyg_hal_plf_comms_init(void)
363
{
364
    static int initialized = 0;
365
 
366
    if (initialized)
367
        return;
368
 
369
    initialized = 1;
370
 
371
    cyg_hal_plf_serial_init();
372
}
373
 
374
//=============================================================================
375
// Compatibility with older stubs
376
//=============================================================================
377
 
378
#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
379
 
380
#include <cyg/hal/hal_stub.h>           // cyg_hal_gdb_interrupt
381
 
382
#if (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 0)
383
# define __BASE ((void*)SA11X0_UART1_BASE)
384
# define CYGHWR_HAL_GDB_PORT_VECTOR CYGNUM_HAL_INTERRUPT_UART1
385
#else
386
# define __BASE ((void*)SA11X0_UART3_BASE)
387
# define CYGHWR_HAL_GDB_PORT_VECTOR CYGNUM_HAL_INTERRUPT_UART3
388
#endif
389
 
390
#ifdef CYGSEM_HAL_ROM_MONITOR
391
#define CYG_HAL_STARTUP_ROM
392
#undef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
393
#endif
394
 
395
#if defined(CYG_HAL_STARTUP_ROM) && !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
396
#define HAL_DIAG_USES_HARDWARE
397
#elif !defined(CYGDBG_HAL_DIAG_TO_DEBUG_CHAN)
398
#define HAL_DIAG_USES_HARDWARE
399
#elif CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL != CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL
400
#define HAL_DIAG_USES_HARDWARE
401
#endif
402
 
403
static channel_data_t ser_channel = {
404
    (volatile struct sa11x0_serial*)__BASE, 0, CYGHWR_HAL_GDB_PORT_VECTOR
405
};
406
 
407
void
408
hal_diag_init(void)
409
{
410
    // Init serial device
411
    init_channel(&ser_channel);
412
}
413
 
414
#ifdef HAL_DIAG_USES_HARDWARE
415
 
416
#ifdef DEBUG_DIAG
417
#ifndef CYG_HAL_STARTUP_ROM
418
#define DIAG_BUFSIZE 2048
419
static char diag_buffer[DIAG_BUFSIZE];
420
static int diag_bp = 0;
421
#endif
422
#endif
423
 
424
void hal_diag_read_char(char *c)
425
{
426
    *c = cyg_hal_plf_serial_getc(&ser_channel);
427
}
428
 
429
void hal_diag_write_char(char c)
430
{
431
#ifdef DEBUG_DIAG
432
#ifndef CYG_HAL_STARTUP_ROM
433
    diag_buffer[diag_bp++] = c;
434
    if (diag_bp == sizeof(diag_buffer)) diag_bp = 0;
435
#endif
436
#endif
437
    cyg_hal_plf_serial_putc(&ser_channel, c);
438
}
439
 
440
#else // not HAL_DIAG_USES_HARDWARE - it uses GDB protocol
441
 
442
void
443
hal_diag_read_char(char *c)
444
{
445
    *c = cyg_hal_plf_serial_getc(&ser_channel);
446
}
447
 
448
void
449
hal_diag_write_char(char c)
450
{
451
    static char line[100];
452
    static int pos = 0;
453
 
454
    // FIXME: Some LED blinking might be nice right here.
455
 
456
    // No need to send CRs
457
    if( c == '\r' ) return;
458
 
459
    line[pos++] = c;
460
 
461
    if( c == '\n' || pos == sizeof(line) )
462
    {
463
 
464
        CYG_INTERRUPT_STATE old;
465
 
466
        // Disable interrupts. This prevents GDB trying to interrupt us
467
        // while we are in the middle of sending a packet. The serial
468
        // receive interrupt will be seen when we re-enable interrupts
469
        // later.
470
 
471
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
472
        CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old);
473
#else
474
        HAL_DISABLE_INTERRUPTS(old);
475
#endif
476
 
477
        while(1)
478
        {
479
            static char hex[] = "0123456789ABCDEF";
480
            cyg_uint8 csum = 0;
481
            int i;
482
#ifndef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT
483
            char c1;
484
#endif        
485
            cyg_hal_plf_serial_putc(&ser_channel, '$');
486
            cyg_hal_plf_serial_putc(&ser_channel, 'O');
487
            csum += 'O';
488
            for( i = 0; i < pos; i++ )
489
            {
490
                char ch = line[i];
491
                char h = hex[(ch>>4)&0xF];
492
                char l = hex[ch&0xF];
493
                cyg_hal_plf_serial_putc(&ser_channel, h);
494
                cyg_hal_plf_serial_putc(&ser_channel, l);
495
                csum += h;
496
                csum += l;
497
            }
498
            cyg_hal_plf_serial_putc(&ser_channel, '#');
499
            cyg_hal_plf_serial_putc(&ser_channel, hex[(csum>>4)&0xF]);
500
            cyg_hal_plf_serial_putc(&ser_channel, hex[csum&0xF]);
501
 
502
#ifdef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT
503
 
504
            break; // regardless
505
 
506
#else // not CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT Ie. usually...
507
 
508
            // Wait for the ACK character '+' from GDB here and handle
509
            // receiving a ^C instead.  This is the reason for this clause
510
            // being a loop.
511
            c1 = cyg_hal_plf_serial_getc(&ser_channel);
512
 
513
            if( c1 == '+' )
514
                break;              // a good acknowledge
515
 
516
#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
517
            cyg_drv_interrupt_acknowledge(CYGHWR_HAL_GDB_PORT_VECTOR);
518
            if( c1 == 3 ) {
519
                // Ctrl-C: breakpoint.
520
                cyg_hal_gdb_interrupt(
521
                    (target_register_t)__builtin_return_address(0) );
522
                break;
523
            }
524
#endif // CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
525
 
526
#endif // ! CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT
527
            // otherwise, loop round again
528
        }
529
 
530
        pos = 0;
531
 
532
 
533
        // And re-enable interrupts
534
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
535
        CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old);
536
#else
537
        HAL_RESTORE_INTERRUPTS(old);
538
#endif
539
 
540
    }
541
}
542
#endif
543
 
544
#endif // !CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
545
 
546
 
547
/*---------------------------------------------------------------------------*/
548
/* End of hal_diag.c */

powered by: WebSVN 2.1.0

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