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

Subversion Repositories openrisc

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

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):   nickg, gthomas
44
// Contributors:nickg, gthomas
45
// Date:        1998-03-02
46
// Purpose:     HAL diagnostic output
47
// Description: Implementations of HAL diagnostic output support.
48
//
49
//####DESCRIPTIONEND####
50
//
51
//===========================================================================*/
52
 
53
#include <pkgconf/hal.h>
54
#include <pkgconf/system.h>
55
#include CYGBLD_HAL_PLATFORM_H
56
 
57
#include <cyg/infra/cyg_type.h>         // base types
58
#include <cyg/infra/cyg_trac.h>         // tracing macros
59
#include <cyg/infra/cyg_ass.h>          // assertion macros
60
 
61
#include <cyg/hal/hal_arch.h>           // basic machine info
62
#include <cyg/hal/hal_intr.h>           // interrupt macros
63
#include <cyg/hal/hal_io.h>             // IO macros
64
#include <cyg/hal/hal_if.h>             // calling interface API
65
#include <cyg/hal/hal_misc.h>           // helper functions
66
#include <cyg/hal/hal_diag.h>
67
#include <cyg/hal/drv_api.h>
68
#include <cyg/hal/hal_edb7xxx.h>         // Hardware definitions
69
 
70
//-----------------------------------------------------------------------------
71
 
72
struct edb_serial {
73
    volatile cyg_uint32 ctrl;
74
    cyg_uint32 pad004_040[16-1];
75
    volatile cyg_uint32 stat;
76
    cyg_uint32 pad044_37c[208-1];
77
    union {
78
        volatile cyg_uint8 write;
79
        volatile cyg_uint32 read;    // Need to read 32 bits
80
    } data;
81
    cyg_uint32 pad384_3BC[16-1];
82
    volatile cyg_uint32 blcr;
83
};
84
 
85
//-----------------------------------------------------------------------------
86
typedef struct {
87
    volatile struct edb_serial* base;
88
    cyg_int32 msec_timeout;
89
    int isr_vector;
90
} channel_data_t;
91
 
92
//-----------------------------------------------------------------------------
93
 
94
static void
95
cyg_hal_plf_serial_init_channel(channel_data_t* __ch_data)
96
{
97
    channel_data_t* chan = (channel_data_t*)__ch_data;
98
 
99
    // Enable port
100
    chan->base->ctrl |= SYSCON1_UART1EN;
101
    // Configure
102
    chan->base->blcr = UART_BITRATE(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD) |
103
                       UBLCR_FIFOEN | UBLCR_WRDLEN8;
104
}
105
 
106
 
107
// Call this delay function when polling for serial access - otherwise
108
// the CPU will keep the memory bus busy and thus prevent DRAM refresh
109
// (and the resulting memory corruption).
110
externC void dram_delay_loop(void);
111
 
112
void
113
cyg_hal_plf_serial_putc(void *__ch_data, char c)
114
{
115
    channel_data_t* chan = (channel_data_t*)__ch_data;
116
 
117
    CYGARC_HAL_SAVE_GP();
118
 
119
    // Wait for Tx FIFO not full
120
    while ((chan->base->stat & SYSFLG1_UTXFF1) != 0) ;
121
 
122
    chan->base->data.write = c;
123
 
124
    CYGARC_HAL_RESTORE_GP();
125
}
126
 
127
static cyg_bool
128
cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch)
129
{
130
    channel_data_t* chan = (channel_data_t*)__ch_data;
131
 
132
    if ((chan->base->stat & SYSFLG1_URXFE1) != 0)
133
        return false;
134
 
135
    *ch = (cyg_uint8)(chan->base->data.read & 0xFF);
136
 
137
    return true;
138
}
139
 
140
cyg_uint8
141
cyg_hal_plf_serial_getc(void* __ch_data)
142
{
143
    cyg_uint8 ch;
144
    int delay_timer = 0;
145
 
146
    CYGARC_HAL_SAVE_GP();
147
 
148
    while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch)) {
149
        CYGACC_CALL_IF_DELAY_US(50);  // A reasonable time
150
        // Only delay every 10ms or so
151
        if (++delay_timer == 10*20) {
152
            dram_delay_loop();
153
            delay_timer = 0;
154
        }
155
    }
156
 
157
    CYGARC_HAL_RESTORE_GP();
158
    return ch;
159
}
160
 
161
static channel_data_t edb_ser_channels[2] = {
162
    {(volatile struct edb_serial*)SYSCON1, 1000, CYGNUM_HAL_INTERRUPT_URXINT1},
163
    {(volatile struct edb_serial*)SYSCON2, 1000, CYGNUM_HAL_INTERRUPT_URXINT2}
164
};
165
 
166
static void
167
cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf,
168
                         cyg_uint32 __len)
169
{
170
    CYGARC_HAL_SAVE_GP();
171
 
172
    while(__len-- > 0)
173
        cyg_hal_plf_serial_putc(__ch_data, *__buf++);
174
 
175
    CYGARC_HAL_RESTORE_GP();
176
}
177
 
178
static void
179
cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
180
{
181
    CYGARC_HAL_SAVE_GP();
182
 
183
    while(__len-- > 0)
184
        *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
185
 
186
    CYGARC_HAL_RESTORE_GP();
187
}
188
 
189
cyg_bool
190
cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
191
{
192
    int delay_count;
193
    channel_data_t* chan = (channel_data_t*)__ch_data;
194
    cyg_bool res;
195
    CYGARC_HAL_SAVE_GP();
196
 
197
    delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
198
 
199
    for(;;) {
200
        res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch);
201
        if (res || 0 == delay_count--)
202
            break;
203
 
204
        CYGACC_CALL_IF_DELAY_US(100);
205
    }
206
 
207
    CYGARC_HAL_RESTORE_GP();
208
    return res;
209
}
210
 
211
static int
212
cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...)
213
{
214
    static int irq_state = 0;
215
    channel_data_t* chan = (channel_data_t*)__ch_data;
216
    int ret = 0;
217
    CYGARC_HAL_SAVE_GP();
218
 
219
    switch (__func) {
220
    case __COMMCTL_IRQ_ENABLE:
221
        irq_state = 1;
222
        HAL_INTERRUPT_UNMASK(chan->isr_vector);
223
        break;
224
    case __COMMCTL_IRQ_DISABLE:
225
        ret = irq_state;
226
        irq_state = 0;
227
        HAL_INTERRUPT_MASK(chan->isr_vector);
228
        break;
229
    case __COMMCTL_DBG_ISR_VECTOR:
230
        ret = chan->isr_vector;
231
        break;
232
    case __COMMCTL_SET_TIMEOUT:
233
    {
234
        va_list ap;
235
 
236
        va_start(ap, __func);
237
 
238
        ret = chan->msec_timeout;
239
        chan->msec_timeout = va_arg(ap, cyg_uint32);
240
 
241
        va_end(ap);
242
    }
243
    default:
244
        break;
245
    }
246
    CYGARC_HAL_RESTORE_GP();
247
    return ret;
248
}
249
 
250
static int
251
cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc,
252
                       CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
253
{
254
    int res = 0;
255
    channel_data_t* chan = (channel_data_t*)__ch_data;
256
    char c;
257
    CYGARC_HAL_SAVE_GP();
258
 
259
    cyg_drv_interrupt_acknowledge(chan->isr_vector);
260
 
261
    *__ctrlc = 0;
262
    if ((chan->base->stat & SYSFLG1_URXFE1) == 0) {
263
        c = (cyg_uint8)(chan->base->data.read & 0xFF);
264
        if( cyg_hal_is_break( &c , 1 ) )
265
            *__ctrlc = 1;
266
 
267
        res = CYG_ISR_HANDLED;
268
    }
269
 
270
    CYGARC_HAL_RESTORE_GP();
271
    return res;
272
}
273
 
274
static void
275
cyg_hal_plf_serial_init(void)
276
{
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
    // Disable interrupts.
281
    HAL_INTERRUPT_MASK(edb_ser_channels[0].isr_vector);
282
    HAL_INTERRUPT_MASK(edb_ser_channels[1].isr_vector);
283
 
284
    // Init channels
285
    cyg_hal_plf_serial_init_channel(&edb_ser_channels[0]);
286
    cyg_hal_plf_serial_init_channel(&edb_ser_channels[1]);
287
 
288
    // Setup procs in the vector table
289
 
290
    // Set channel 0
291
    CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
292
    comm = CYGACC_CALL_IF_CONSOLE_PROCS();
293
    CYGACC_COMM_IF_CH_DATA_SET(*comm, &edb_ser_channels[0]);
294
    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
295
    CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
296
    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
297
    CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
298
    CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
299
    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
300
    CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
301
 
302
    // Set channel 1
303
    CYGACC_CALL_IF_SET_CONSOLE_COMM(1);
304
    comm = CYGACC_CALL_IF_CONSOLE_PROCS();
305
    CYGACC_COMM_IF_CH_DATA_SET(*comm, &edb_ser_channels[1]);
306
    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
307
    CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
308
    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
309
    CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
310
    CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
311
    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
312
    CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
313
 
314
    // Restore original console
315
    CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
316
}
317
 
318
void
319
cyg_hal_plf_comms_init(void)
320
{
321
    static int initialized = 0;
322
 
323
    if (initialized)
324
        return;
325
 
326
    initialized = 1;
327
 
328
    cyg_hal_plf_serial_init();
329
}
330
 
331
//=============================================================================
332
// Compatibility with older stubs
333
//=============================================================================
334
 
335
#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
336
 
337
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
338
#include <cyg/hal/hal_stub.h>           // cyg_hal_gdb_interrupt
339
#endif
340
 
341
// Assumption: all diagnostic output must be GDB packetized unless this is a ROM (i.e.
342
// totally stand-alone) system.
343
 
344
#ifdef CYGSEM_HAL_ROM_MONITOR
345
#define CYG_HAL_STARTUP_ROM
346
#undef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
347
#endif
348
 
349
#if defined(CYG_HAL_STARTUP_ROM) && !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
350
#define HAL_DIAG_USES_HARDWARE
351
#else
352
#if !defined(CYGDBG_HAL_DIAG_TO_DEBUG_CHAN)
353
#define HAL_DIAG_USES_HARDWARE
354
#elif CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL != CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL
355
#define HAL_DIAG_USES_HARDWARE
356
#endif
357
#endif
358
 
359
#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 0
360
# define __BASE ((volatile struct edb_serial*)SYSCON1)
361
# define __IRQ  CYGNUM_HAL_INTERRUPT_URXINT1
362
#else
363
# define __BASE ((volatile struct edb_serial*)SYSCON2)
364
# define __IRQ  CYGNUM_HAL_INTERRUPT_URXINT2
365
#endif
366
 
367
static channel_data_t edb_ser_channel = {
368
    __BASE, 0, 0
369
};
370
 
371
/*---------------------------------------------------------------------------*/
372
// EDB7XXX Serial Port (UARTx) for Debug
373
 
374
// Actually send character down the wire
375
static void
376
hal_diag_write_char_serial(char c)
377
{
378
    cyg_hal_plf_serial_putc(&edb_ser_channel, c);
379
}
380
 
381
static bool
382
hal_diag_read_serial(char *c)
383
{
384
    long timeout = 1000000000;  // A long time...
385
 
386
    while (! cyg_hal_plf_serial_getc_nonblock(&edb_ser_channel, c) )
387
        if (--timeout == 0) return false;
388
 
389
    return true;
390
}
391
 
392
#ifdef HAL_DIAG_USES_HARDWARE
393
 
394
void hal_diag_init(void)
395
{
396
    static int init = 0;
397
#ifndef CYG_HAL_STARTUP_ROM
398
    char *msg = "\n\rRAM EDB7XXX eCos\n\r";
399
#endif
400
    if (init++) return;
401
 
402
    cyg_hal_plf_serial_init_channel(&edb_ser_channel);
403
 
404
#ifndef CYG_HAL_STARTUP_ROM
405
    while (*msg) hal_diag_write_char(*msg++);
406
#endif
407
}
408
 
409
#ifdef DEBUG_DIAG
410
#ifndef CYG_HAL_STARTUP_ROM
411
#define DIAG_BUFSIZE 2048
412
static char diag_buffer[DIAG_BUFSIZE];
413
static int diag_bp = 0;
414
#endif
415
#endif
416
 
417
void hal_diag_write_char(char c)
418
{
419
    hal_diag_init();
420
#ifdef DEBUG_DIAG
421
#ifndef CYG_HAL_STARTUP_ROM
422
    diag_buffer[diag_bp++] = c;
423
    if (diag_bp == sizeof(diag_buffer)) diag_bp = 0;
424
#endif
425
#endif
426
    hal_diag_write_char_serial(c);
427
}
428
 
429
void hal_diag_read_char(char *c)
430
{
431
    while (!hal_diag_read_serial(c)) ;
432
}
433
 
434
#else // HAL_DIAG relies on GDB
435
 
436
// Initialize diag port
437
void hal_diag_init(void)
438
{
439
    // Assume port is already setup
440
    if (0) cyg_hal_plf_serial_init_channel(&edb_ser_channel);
441
}
442
 
443
void
444
hal_diag_read_char(char *c)
445
{
446
    while (!hal_diag_read_serial(c)) ;
447
}
448
 
449
void
450
hal_diag_write_char(char c)
451
{
452
    static char line[100];
453
    static int pos = 0;
454
 
455
    // No need to send CRs
456
    if( c == '\r' ) return;
457
 
458
    line[pos++] = c;
459
 
460
    if( c == '\n' || pos == sizeof(line) )
461
    {
462
 
463
        CYG_INTERRUPT_STATE old;
464
 
465
        // Disable interrupts. This prevents GDB trying to interrupt us
466
        // while we are in the middle of sending a packet. The serial
467
        // receive interrupt will be seen when we re-enable interrupts
468
        // later.
469
 
470
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
471
        CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old);
472
#else
473
        HAL_DISABLE_INTERRUPTS(old);
474
#endif
475
 
476
        while(1)
477
        {
478
            static char hex[] = "0123456789ABCDEF";
479
            cyg_uint8 csum = 0;
480
            int i;
481
            char c1;
482
 
483
            hal_diag_write_char_serial('$');
484
            hal_diag_write_char_serial('O');
485
            csum += 'O';
486
            for( i = 0; i < pos; i++ )
487
            {
488
                char ch = line[i];
489
                char h = hex[(ch>>4)&0xF];
490
                char l = hex[ch&0xF];
491
                hal_diag_write_char_serial(h);
492
                hal_diag_write_char_serial(l);
493
                csum += h;
494
                csum += l;
495
            }
496
            hal_diag_write_char_serial('#');
497
            hal_diag_write_char_serial(hex[(csum>>4)&0xF]);
498
            hal_diag_write_char_serial(hex[csum&0xF]);
499
 
500
            // Wait for the ACK character '+' from GDB here and handle
501
            // receiving a ^C instead.  This is the reason for this clause
502
            // being a loop.
503
            if (!hal_diag_read_serial(&c1))
504
                continue;   // No response - try sending packet again
505
 
506
            if( c1 == '+' )
507
                break;              // a good acknowledge
508
 
509
#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
510
            cyg_drv_interrupt_acknowledge(__IRQ);
511
            if( c1 == 3 ) {
512
                // Ctrl-C: breakpoint.
513
                cyg_hal_gdb_interrupt (__builtin_return_address(0));
514
                break;
515
            }
516
#endif
517
            // otherwise, loop round again
518
        }
519
 
520
        pos = 0;
521
 
522
 
523
        // And re-enable interrupts
524
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
525
        CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old);
526
#else
527
        HAL_RESTORE_INTERRUPTS(old);
528
#endif
529
 
530
    }
531
}
532
#endif
533
 
534
#endif // !CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
535
 
536
/*---------------------------------------------------------------------------*/
537
/* 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.