1 /*=============================================================================
5 // HAL diagnostic output code
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.
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.
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
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.
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.
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.
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####
43 // Author(s): nickg, gthomas
44 // Contributors:nickg, gthomas
46 // Purpose: HAL diagnostic output
47 // Description: Implementations of HAL diagnostic output support.
49 //####DESCRIPTIONEND####
51 //===========================================================================*/
53 #include <pkgconf/hal.h>
54 #include <pkgconf/system.h>
55 #include CYGBLD_HAL_PLATFORM_H
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
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
70 //-----------------------------------------------------------------------------
73 volatile cyg_uint32 ctrl;
74 cyg_uint32 pad004_040[16-1];
75 volatile cyg_uint32 stat;
76 cyg_uint32 pad044_37c[208-1];
78 volatile cyg_uint8 write;
79 volatile cyg_uint32 read; // Need to read 32 bits
81 cyg_uint32 pad384_3BC[16-1];
82 volatile cyg_uint32 blcr;
85 //-----------------------------------------------------------------------------
87 volatile struct edb_serial* base;
88 cyg_int32 msec_timeout;
93 //-----------------------------------------------------------------------------
96 cyg_hal_plf_serial_init_channel(channel_data_t* __ch_data)
98 channel_data_t* chan = (channel_data_t*)__ch_data;
101 chan->base->ctrl |= SYSCON1_UART1EN;
103 chan->base->blcr = UART_BITRATE(chan->baud_rate) |
104 UBLCR_FIFOEN | UBLCR_WRDLEN8;
108 // Call this delay function when polling for serial access - otherwise
109 // the CPU will keep the memory bus busy and thus prevent DRAM refresh
110 // (and the resulting memory corruption).
111 externC void dram_delay_loop(void);
114 cyg_hal_plf_serial_putc(void *__ch_data, char c)
116 channel_data_t* chan = (channel_data_t*)__ch_data;
118 CYGARC_HAL_SAVE_GP();
120 // Wait for Tx FIFO not full
121 while ((chan->base->stat & SYSFLG1_UTXFF1) != 0) ;
123 chan->base->data.write = c;
125 CYGARC_HAL_RESTORE_GP();
129 cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch)
131 channel_data_t* chan = (channel_data_t*)__ch_data;
133 if ((chan->base->stat & SYSFLG1_URXFE1) != 0)
136 *ch = (cyg_uint8)(chan->base->data.read & 0xFF);
142 cyg_hal_plf_serial_getc(void* __ch_data)
147 CYGARC_HAL_SAVE_GP();
149 while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch)) {
150 CYGACC_CALL_IF_DELAY_US(50); // A reasonable time
151 // Only delay every 10ms or so
152 if (++delay_timer == 10*20) {
158 CYGARC_HAL_RESTORE_GP();
162 static channel_data_t edb_ser_channels[2] = {
163 {(volatile struct edb_serial*)SYSCON1, 1000, CYGNUM_HAL_INTERRUPT_URXINT1, CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD},
164 {(volatile struct edb_serial*)SYSCON2, 1000, CYGNUM_HAL_INTERRUPT_URXINT2, CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD}
168 cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf,
171 CYGARC_HAL_SAVE_GP();
174 cyg_hal_plf_serial_putc(__ch_data, *__buf++);
176 CYGARC_HAL_RESTORE_GP();
180 cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
182 CYGARC_HAL_SAVE_GP();
185 *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
187 CYGARC_HAL_RESTORE_GP();
191 cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
194 channel_data_t* chan = (channel_data_t*)__ch_data;
196 CYGARC_HAL_SAVE_GP();
198 delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
201 res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch);
202 if (res || 0 == delay_count--)
205 CYGACC_CALL_IF_DELAY_US(100);
208 CYGARC_HAL_RESTORE_GP();
213 cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...)
215 static int irq_state = 0;
216 channel_data_t* chan = (channel_data_t*)__ch_data;
220 CYGARC_HAL_SAVE_GP();
221 va_start(ap, __func);
224 case __COMMCTL_GETBAUD:
225 ret = chan->baud_rate;
227 case __COMMCTL_SETBAUD:
228 chan->baud_rate = va_arg(ap, cyg_int32);
229 // Should we verify this value here?
230 cyg_hal_plf_serial_init_channel(chan);
234 case __COMMCTL_IRQ_ENABLE:
236 HAL_INTERRUPT_UNMASK(chan->isr_vector);
238 case __COMMCTL_IRQ_DISABLE:
241 HAL_INTERRUPT_MASK(chan->isr_vector);
243 case __COMMCTL_DBG_ISR_VECTOR:
244 ret = chan->isr_vector;
246 case __COMMCTL_SET_TIMEOUT:
250 va_start(ap, __func);
252 ret = chan->msec_timeout;
253 chan->msec_timeout = va_arg(ap, cyg_uint32);
262 CYGARC_HAL_RESTORE_GP();
267 cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc,
268 CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
271 channel_data_t* chan = (channel_data_t*)__ch_data;
273 CYGARC_HAL_SAVE_GP();
275 cyg_drv_interrupt_acknowledge(chan->isr_vector);
278 if ((chan->base->stat & SYSFLG1_URXFE1) == 0) {
279 c = (cyg_uint8)(chan->base->data.read & 0xFF);
280 if( cyg_hal_is_break( &c , 1 ) )
283 res = CYG_ISR_HANDLED;
286 CYGARC_HAL_RESTORE_GP();
291 cyg_hal_plf_serial_init(void)
293 hal_virtual_comm_table_t* comm;
294 int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
296 // Disable interrupts.
297 HAL_INTERRUPT_MASK(edb_ser_channels[0].isr_vector);
298 HAL_INTERRUPT_MASK(edb_ser_channels[1].isr_vector);
301 cyg_hal_plf_serial_init_channel(&edb_ser_channels[0]);
302 cyg_hal_plf_serial_init_channel(&edb_ser_channels[1]);
304 // Setup procs in the vector table
307 CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
308 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
309 CYGACC_COMM_IF_CH_DATA_SET(*comm, &edb_ser_channels[0]);
310 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
311 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
312 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
313 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
314 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
315 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
316 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
319 CYGACC_CALL_IF_SET_CONSOLE_COMM(1);
320 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
321 CYGACC_COMM_IF_CH_DATA_SET(*comm, &edb_ser_channels[1]);
322 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
323 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
324 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
325 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
326 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
327 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
328 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
330 // Restore original console
331 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
335 cyg_hal_plf_comms_init(void)
337 static int initialized = 0;
344 cyg_hal_plf_serial_init();
347 //=============================================================================
348 // Compatibility with older stubs
349 //=============================================================================
351 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
353 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
354 #include <cyg/hal/hal_stub.h> // cyg_hal_gdb_interrupt
357 // Assumption: all diagnostic output must be GDB packetized unless this is a ROM (i.e.
358 // totally stand-alone) system.
360 #ifdef CYGSEM_HAL_ROM_MONITOR
361 #define CYG_HAL_STARTUP_ROM
362 #undef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
365 #if defined(CYG_HAL_STARTUP_ROM) && !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
366 #define HAL_DIAG_USES_HARDWARE
368 #if !defined(CYGDBG_HAL_DIAG_TO_DEBUG_CHAN)
369 #define HAL_DIAG_USES_HARDWARE
370 #elif CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL != CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL
371 #define HAL_DIAG_USES_HARDWARE
375 #if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 0
376 # define __BASE ((volatile struct edb_serial*)SYSCON1)
377 # define __IRQ CYGNUM_HAL_INTERRUPT_URXINT1
379 # define __BASE ((volatile struct edb_serial*)SYSCON2)
380 # define __IRQ CYGNUM_HAL_INTERRUPT_URXINT2
383 static channel_data_t edb_ser_channel = {
387 /*---------------------------------------------------------------------------*/
388 // EDB7XXX Serial Port (UARTx) for Debug
390 // Actually send character down the wire
392 hal_diag_write_char_serial(char c)
394 cyg_hal_plf_serial_putc(&edb_ser_channel, c);
398 hal_diag_read_serial(char *c)
400 long timeout = 1000000000; // A long time...
402 while (! cyg_hal_plf_serial_getc_nonblock(&edb_ser_channel, c) )
403 if (--timeout == 0) return false;
408 #ifdef HAL_DIAG_USES_HARDWARE
410 void hal_diag_init(void)
413 #ifndef CYG_HAL_STARTUP_ROM
414 char *msg = "\n\rRAM EDB7XXX eCos\n\r";
418 cyg_hal_plf_serial_init_channel(&edb_ser_channel);
420 #ifndef CYG_HAL_STARTUP_ROM
421 while (*msg) hal_diag_write_char(*msg++);
426 #ifndef CYG_HAL_STARTUP_ROM
427 #define DIAG_BUFSIZE 2048
428 static char diag_buffer[DIAG_BUFSIZE];
429 static int diag_bp = 0;
433 void hal_diag_write_char(char c)
437 #ifndef CYG_HAL_STARTUP_ROM
438 diag_buffer[diag_bp++] = c;
439 if (diag_bp == sizeof(diag_buffer)) diag_bp = 0;
442 hal_diag_write_char_serial(c);
445 void hal_diag_read_char(char *c)
447 while (!hal_diag_read_serial(c)) ;
450 #else // HAL_DIAG relies on GDB
452 // Initialize diag port
453 void hal_diag_init(void)
455 // Assume port is already setup
456 if (0) cyg_hal_plf_serial_init_channel(&edb_ser_channel);
460 hal_diag_read_char(char *c)
462 while (!hal_diag_read_serial(c)) ;
466 hal_diag_write_char(char c)
468 static char line[100];
471 // No need to send CRs
472 if( c == '\r' ) return;
476 if( c == '\n' || pos == sizeof(line) )
479 CYG_INTERRUPT_STATE old;
481 // Disable interrupts. This prevents GDB trying to interrupt us
482 // while we are in the middle of sending a packet. The serial
483 // receive interrupt will be seen when we re-enable interrupts
486 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
487 CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old);
489 HAL_DISABLE_INTERRUPTS(old);
494 static char hex[] = "0123456789ABCDEF";
499 hal_diag_write_char_serial('$');
500 hal_diag_write_char_serial('O');
502 for( i = 0; i < pos; i++ )
505 char h = hex[(ch>>4)&0xF];
506 char l = hex[ch&0xF];
507 hal_diag_write_char_serial(h);
508 hal_diag_write_char_serial(l);
512 hal_diag_write_char_serial('#');
513 hal_diag_write_char_serial(hex[(csum>>4)&0xF]);
514 hal_diag_write_char_serial(hex[csum&0xF]);
516 // Wait for the ACK character '+' from GDB here and handle
517 // receiving a ^C instead. This is the reason for this clause
519 if (!hal_diag_read_serial(&c1))
520 continue; // No response - try sending packet again
523 break; // a good acknowledge
525 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
526 cyg_drv_interrupt_acknowledge(__IRQ);
528 // Ctrl-C: breakpoint.
529 cyg_hal_gdb_interrupt (__builtin_return_address(0));
533 // otherwise, loop round again
539 // And re-enable interrupts
540 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
541 CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old);
543 HAL_RESTORE_INTERRUPTS(old);
550 #endif // !CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
552 /*---------------------------------------------------------------------------*/
553 /* End of hal_diag.c */