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>
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
59 #include <cyg/hal/hal_arch.h> // SAVE/RESTORE GP macros
60 #include <cyg/hal/hal_io.h> // IO macros
61 #include <cyg/hal/hal_if.h> // interface API
62 #include <cyg/hal/hal_intr.h> // HAL_ENABLE/MASK/UNMASK_INTERRUPTS
63 #include <cyg/hal/hal_misc.h> // Helper functions
64 #include <cyg/hal/drv_api.h> // CYG_ISR_HANDLED
66 /*---------------------------------------------------------------------------*/
67 // AEB Serial Port (UART1) for Debug
69 /*---------------------------------------------------------------------------*/
70 /* From serial_16550.h */
72 // UART1, 38400 (Using raw 24MHz system clock)
73 #define CYG_DEVICE_SERIAL_RS232_BAUD_MSB (0)
74 #define CYG_DEVICE_SERIAL_RS232_BAUD_LSB (13*3)
75 // This is the base address of UART1
76 #define CYG_DEV_UART1_BASE 0xFFFF0400
78 // Interrupt Enable Register
79 #define SIO_IER_RCV 0x01
80 #define SIO_IER_XMT 0x02
81 #define SIO_IER_LS 0x04
82 #define SIO_IER_MS 0x08
84 // Define the serial registers.
85 #define CYG_DEV_RBR 0x00 // receiver buffer register, read, dlab = 0
86 #define CYG_DEV_THR 0x00 // transmitter holding register, write, dlab = 0
87 #define CYG_DEV_DLL 0x00 // divisor latch (LS), read/write, dlab = 1
88 #define CYG_DEV_IER 0x04 // interrupt enable register, read/write, dlab = 0
89 #define CYG_DEV_DLM 0x04 // divisor latch (MS), read/write, dlab = 1
90 #define CYG_DEV_IIR 0x08 // interrupt identification register, read, dlab = 0
91 #define CYG_DEV_FCR 0x08 // fifo control register, write, dlab = 0
92 #define CYG_DEV_LCR 0x0C // line control register, read/write
93 #define CYG_DEV_MCR 0x10 // modem control register, read/write
94 #define CYG_DEV_LSR 0x14 // line status register, read
95 #define CYG_DEV_MSR 0x18 // modem status register, read
97 // The line status register bits.
98 #define SIO_LSR_DR 0x01 // data ready
99 #define SIO_LSR_OE 0x02 // overrun error
100 #define SIO_LSR_PE 0x04 // parity error
101 #define SIO_LSR_FE 0x08 // framing error
102 #define SIO_LSR_BI 0x10 // break interrupt
103 #define SIO_LSR_THRE 0x20 // transmitter holding register empty
104 #define SIO_LSR_TEMT 0x40 // transmitter register empty
105 #define SIO_LSR_ERR 0x80 // any error condition
107 // The modem status register bits.
108 #define SIO_MSR_DCTS 0x01 // delta clear to send
109 #define SIO_MSR_DDSR 0x02 // delta data set ready
110 #define SIO_MSR_TERI 0x04 // trailing edge ring indicator
111 #define SIO_MSR_DDCD 0x08 // delta data carrier detect
112 #define SIO_MSR_CTS 0x10 // clear to send
113 #define SIO_MSR_DSR 0x20 // data set ready
114 #define SIO_MSR_RI 0x40 // ring indicator
115 #define SIO_MSR_DCD 0x80 // data carrier detect
117 // The line control register bits.
118 #define SIO_LCR_WLS0 0x01 // word length select bit 0
119 #define SIO_LCR_WLS1 0x02 // word length select bit 1
120 #define SIO_LCR_STB 0x04 // number of stop bits
121 #define SIO_LCR_PEN 0x08 // parity enable
122 #define SIO_LCR_EPS 0x10 // even parity select
123 #define SIO_LCR_SP 0x20 // stick parity
124 #define SIO_LCR_SB 0x40 // set break
125 #define SIO_LCR_DLAB 0x80 // divisor latch access bit
127 // Modem Control Register
128 #define SIO_MCR_DTR 0x01
129 #define SIO_MCR_RTS 0x02
130 #define SIO_MCR_INT 0x08 // Enable interrupts
133 //-----------------------------------------------------------------------------
136 cyg_int32 msec_timeout;
140 //-----------------------------------------------------------------------------
143 cyg_hal_plf_serial_init_channel(void* __ch_data)
145 cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
146 cyg_uint8 lcr, dll, dlm;
149 HAL_WRITE_UINT8(base+CYG_DEV_LCR, SIO_LCR_WLS0 | SIO_LCR_WLS1);
151 HAL_READ_UINT8(base+CYG_DEV_LCR, lcr);
153 HAL_WRITE_UINT8(base+CYG_DEV_LCR, lcr);
154 HAL_READ_UINT8(base+CYG_DEV_DLL, dll);
155 HAL_READ_UINT8(base+CYG_DEV_DLM, dlm);
156 HAL_WRITE_UINT8 (base+CYG_DEV_DLL, CYG_DEVICE_SERIAL_RS232_BAUD_LSB);
157 HAL_WRITE_UINT8 (base+CYG_DEV_DLM, CYG_DEVICE_SERIAL_RS232_BAUD_MSB);
158 lcr &= ~SIO_LCR_DLAB;
159 HAL_WRITE_UINT8 (base+CYG_DEV_LCR, lcr);
160 HAL_WRITE_UINT8 (base+CYG_DEV_FCR, 0x07); // Enable & clear FIFO
164 cyg_hal_plf_serial_putc(void *__ch_data, char c)
166 cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
168 CYGARC_HAL_SAVE_GP();
171 HAL_READ_UINT8(base+CYG_DEV_LSR, lsr);
172 } while ((lsr & SIO_LSR_THRE) == 0);
174 HAL_WRITE_UINT8(base+CYG_DEV_THR, c);
176 CYGARC_HAL_RESTORE_GP();
180 cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch)
182 cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
185 HAL_READ_UINT8(base+CYG_DEV_LSR, lsr);
186 if ((lsr & SIO_LSR_DR) == 0)
189 HAL_READ_UINT8(base+CYG_DEV_RBR, *ch);
195 cyg_hal_plf_serial_getc(void* __ch_data)
198 CYGARC_HAL_SAVE_GP();
200 while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch));
202 CYGARC_HAL_RESTORE_GP();
207 cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf,
210 CYGARC_HAL_SAVE_GP();
213 cyg_hal_plf_serial_putc(__ch_data, *__buf++);
215 CYGARC_HAL_RESTORE_GP();
219 cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
221 CYGARC_HAL_SAVE_GP();
224 *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
226 CYGARC_HAL_RESTORE_GP();
230 cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
233 channel_data_t* chan = (channel_data_t*)__ch_data;
235 CYGARC_HAL_SAVE_GP();
237 delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
240 res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch);
241 if (res || 0 == delay_count--)
244 CYGACC_CALL_IF_DELAY_US(100);
247 CYGARC_HAL_RESTORE_GP();
252 cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...)
254 static int irq_state = 0;
255 channel_data_t* chan = (channel_data_t*)__ch_data;
257 CYGARC_HAL_SAVE_GP();
260 case __COMMCTL_IRQ_ENABLE:
263 HAL_WRITE_UINT8(chan->base+CYG_DEV_IER, SIO_IER_RCV);
264 HAL_WRITE_UINT8(chan->base+CYG_DEV_MCR, SIO_MCR_INT|SIO_MCR_DTR|SIO_MCR_RTS);
266 HAL_INTERRUPT_UNMASK(chan->isr_vector);
268 case __COMMCTL_IRQ_DISABLE:
272 HAL_WRITE_UINT8(chan->base+CYG_DEV_IER, 0);
273 HAL_WRITE_UINT8(chan->base+CYG_DEV_MCR, SIO_MCR_INT|SIO_MCR_DTR|SIO_MCR_RTS);
275 HAL_INTERRUPT_MASK(chan->isr_vector);
277 case __COMMCTL_DBG_ISR_VECTOR:
278 ret = chan->isr_vector;
280 case __COMMCTL_SET_TIMEOUT:
284 va_start(ap, __func);
286 ret = chan->msec_timeout;
287 chan->msec_timeout = va_arg(ap, cyg_uint32);
294 CYGARC_HAL_RESTORE_GP();
299 cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc,
300 CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
303 channel_data_t* chan = (channel_data_t*)__ch_data;
306 CYGARC_HAL_SAVE_GP();
308 cyg_drv_interrupt_acknowledge(chan->isr_vector);
312 HAL_READ_UINT8(chan->base+CYG_DEV_LSR, lsr);
313 if ( (lsr & SIO_LSR_DR) != 0 ) {
315 HAL_READ_UINT8(chan->base+CYG_DEV_RBR, c);
316 if( cyg_hal_is_break( &c , 1 ) )
319 res = CYG_ISR_HANDLED;
322 CYGARC_HAL_RESTORE_GP();
326 static channel_data_t aeb_ser_channels[1];
329 cyg_hal_plf_serial_init(void)
331 hal_virtual_comm_table_t* comm;
332 int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
333 channel_data_t* chan;
335 chan = &aeb_ser_channels[0];
336 chan->base = (cyg_uint8*)CYG_DEV_UART1_BASE;
337 chan->isr_vector = CYGNUM_HAL_INTERRUPT_UART1;
338 chan->msec_timeout = 1000;
341 cyg_hal_plf_serial_init_channel(chan);
343 // Setup procs in the vector table
346 CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
347 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
348 CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
349 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
350 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
351 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
352 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
353 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
354 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
355 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
357 // Restore original console
358 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
362 cyg_hal_plf_comms_init(void)
364 static int initialized = 0;
371 cyg_hal_plf_serial_init();
374 //=============================================================================
375 // Compatibility with older stubs
376 //=============================================================================
378 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
380 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
381 #include <cyg/hal/drv_api.h>
382 #include <cyg/hal/hal_stub.h> // cyg_hal_gdb_interrupt
385 // Assumption: all diagnostic output must be GDB packetized unless this is a ROM (i.e.
386 // totally stand-alone) system.
388 #if defined(CYG_HAL_STARTUP_ROM) || !defined(CYGDBG_HAL_DIAG_TO_DEBUG_CHAN)
389 #define HAL_DIAG_USES_HARDWARE
393 static channel_data_t aeb_ser_channel = {(cyg_uint8*)CYG_DEV_UART1_BASE, 0, 0};
395 #ifdef HAL_DIAG_USES_HARDWARE
397 void hal_diag_init(void)
400 char *msg = "\n\rAEB-1 eCos\n\r";
404 cyg_hal_plf_serial_init_channel(&aeb_ser_channel);
406 while (*msg) cyg_hal_plf_serial_putc(&aeb_ser_channel, *msg++);
410 #if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
411 #define DIAG_BUFSIZE 32
413 #define DIAG_BUFSIZE 2048
415 static char diag_buffer[DIAG_BUFSIZE];
416 static int diag_bp = 0;
419 void hal_diag_write_char(char c)
423 cyg_hal_plf_serial_putc(&aeb_ser_channel, c);
426 diag_buffer[diag_bp++] = c;
427 if (diag_bp == DIAG_BUFSIZE) diag_bp = 0;
431 void hal_diag_read_char(char *c)
433 *c = cyg_hal_plf_serial_getc(&aeb_ser_channel);
436 #else // HAL_DIAG relies on GDB
438 // Initialize diag port - assume GDB channel is already set up
439 void hal_diag_init(void)
441 if (0) cyg_hal_plf_serial_init_channel(&aeb_ser_channel); // avoid warning
444 // Actually send character down the wire
446 hal_diag_write_char_serial(char c)
450 cyg_hal_plf_serial_putc(&aeb_ser_channel, c);
454 hal_diag_read_serial(char *c)
456 long timeout = 1000000000; // A long time...
457 while (!cyg_hal_plf_serial_getc_nonblock(&aeb_ser_channel, c))
458 if (0 == --timeout) return false;
464 hal_diag_read_char(char *c)
466 while (!hal_diag_read_serial(c)) ;
470 hal_diag_write_char(char c)
472 static char line[100];
475 // No need to send CRs
476 if( c == '\r' ) return;
480 if( c == '\n' || pos == sizeof(line) )
483 CYG_INTERRUPT_STATE old;
485 // Disable interrupts. This prevents GDB trying to interrupt us
486 // while we are in the middle of sending a packet. The serial
487 // receive interrupt will be seen when we re-enable interrupts
490 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
491 CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old);
493 HAL_DISABLE_INTERRUPTS(old);
498 static char hex[] = "0123456789ABCDEF";
503 hal_diag_write_char_serial('$');
504 hal_diag_write_char_serial('O');
506 for( i = 0; i < pos; i++ )
509 char h = hex[(ch>>4)&0xF];
510 char l = hex[ch&0xF];
511 hal_diag_write_char_serial(h);
512 hal_diag_write_char_serial(l);
516 hal_diag_write_char_serial('#');
517 hal_diag_write_char_serial(hex[(csum>>4)&0xF]);
518 hal_diag_write_char_serial(hex[csum&0xF]);
520 // Wait for the ACK character '+' from GDB here and handle
521 // receiving a ^C instead. This is the reason for this clause
523 if (!hal_diag_read_serial(&c1))
524 continue; // No response - try sending packet again
527 break; // a good acknowledge
529 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
530 cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_UART1);
532 // Ctrl-C: breakpoint.
533 cyg_hal_gdb_interrupt (__builtin_return_address(0));
537 // otherwise, loop round again
543 // And re-enable interrupts
544 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
545 CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old);
547 HAL_RESTORE_INTERRUPTS(old);
554 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
557 /*---------------------------------------------------------------------------*/
558 /* End of hal_diag.c */