Mercurial > flash_v2
diff packages/hal/arm/ebsa285/current/src/hal_diag.c @ 76:435cced73e2f ecos-v1_3_1-release
eCos v1.3.1 merged from eCos master repository on 2000-03-27-23:22:51-BST
| author | jlarmour |
|---|---|
| date | Tue, 28 Mar 2000 14:10:45 +0000 |
| parents | |
| children | 84e4bde58b26 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/hal/arm/ebsa285/current/src/hal_diag.c @@ -0,0 +1,327 @@ +/*============================================================================= +// +// hal_diag.c +// +// HAL diagnostic output code +// +//============================================================================= +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg, gthomas +// Contributors:nickg, gthomas +// Date: 1998-03-02 +// Purpose: HAL diagnostic output +// Description: Implementations of HAL diagnostic output support. +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include <pkgconf/hal.h> +#include <pkgconf/system.h> +#include CYGBLD_HAL_PLATFORM_H + +#include <cyg/infra/cyg_type.h> // base types +#include <cyg/infra/cyg_trac.h> // tracing macros +#include <cyg/infra/cyg_ass.h> // assertion macros + +#include <cyg/hal/hal_arch.h> // basic machine info +#include <cyg/hal/hal_intr.h> // interrupt macros +#include <cyg/hal/hal_io.h> // IO macros +#include <cyg/hal/hal_diag.h> +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#include <cyg/hal/drv_api.h> // cyg_drv_interrupt_acknowledge +#include <cyg/hal/hal_stub.h> // cyg_hal_gdb_interrupt +#endif +#include <cyg/hal/hal_ebsa285.h> // Hardware definitions + +#ifdef CYGSEM_HAL_ROM_MONITOR +#define CYG_HAL_STARTUP_ROM +#undef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#endif + +#if defined(CYG_HAL_STARTUP_ROM) || defined(CYGDBG_HAL_DIAG_DISABLE_GDB_PROTOCOL) +#define HAL_DIAG_USES_HARDWARE +#endif + +/*---------------------------------------------------------------------------*/ +// EBSA285 Serial Port (UARTx) for Debug + +// Actually send character down the wire +static void +hal_diag_write_char_serial(char c) +{ + // Wait for Tx FIFO not full + while ((*SA110_UART_FLAG_REGISTER & SA110_TX_FIFO_STATUS_MASK) == SA110_TX_FIFO_BUSY) + ; + *SA110_UART_DATA_REGISTER = c; +} + +static bool +hal_diag_read_serial(char *c) +{ + long timeout = 1000000000; // A long time... + while ((*SA110_UART_FLAG_REGISTER & SA110_RX_FIFO_STATUS_MASK) == SA110_RX_FIFO_EMPTY) + if ( --timeout == 0 ) + return false; + *c = (char)(*SA110_UART_DATA_REGISTER & 0xFF); + return true; +} + +/* + * Baud rate selection stuff + */ +#if 0 +struct _baud { + int baud; + unsigned short divisor_high, divisor_low; +}; + +const static struct _baud bauds[] = { +#if (FCLK_MHZ == 50) + { 300, 0xA, 0x2B}, /* 2603 = 0x0A2B */ + { 600, 0x5, 0x15}, /* 1301 = 0x0515 */ + { 1200, 0x2, 0x8A}, /* 650 = 0x028A */ + { 2400, 0x1, 0x45}, /* 325 = 0x0145 */ + { 4800, 0x0, 0xA2}, /* 162 = 0x00A2 */ + { 9600, 0x0, 0x50}, /* 80 = 0x0050 */ + { 19200, 0x0, 0x28}, /* 40 = 0x0028 */ + { 38400, 0x0, 0x13}, /* 19 = 0x0013 */ +#elif (FCLK_MHZ == 60) + { 300, 0xC, 0x34}, /* 2603 = 0x0A2B */ + { 600, 0x6, 0x19}, /* 1301 = 0x0515 */ + { 1200, 0x3, 0x0C}, /* 650 = 0x028A */ + { 2400, 0x1, 0x86}, /* 325 = 0x0145 */ + { 4800, 0x0, 0xC2}, /* 162 = 0x00A2 */ + { 9600, 0x0, 0x61}, /* 80 = 0x0050 */ + { 19200, 0x0, 0x30}, /* 40 = 0x0028 */ + { 38400, 0x0, 0x17}, /* 19 = 0x0013 */ +#endif +}; +#endif + +void hal_diag_init(void) +{ + int dummy; + /* + * Make sure everything is off + */ + *SA110_UART_CONTROL_REGISTER = SA110_UART_DISABLED | SA110_SIR_DISABLED; + + /* + * Read the RXStat to drain the fifo + */ + dummy = *SA110_UART_RXSTAT; + + /* + * Set the baud rate - this also turns the uart on. + * + * Note that the ordering of these writes is critical, + * and the writes to the H_BAUD_CONTROL and CONTROL_REGISTER + * are necessary to force the UART to update its register + * contents. + */ + *SA110_UART_L_BAUD_CONTROL = 0x13; // bp->divisor_low; + *SA110_UART_M_BAUD_CONTROL = 0x00; // bp->divisor_high; + *SA110_UART_H_BAUD_CONTROL = SA110_UART_BREAK_DISABLED | + SA110_UART_PARITY_DISABLED | + SA110_UART_STOP_BITS_ONE | + SA110_UART_FIFO_ENABLED | + SA110_UART_DATA_LENGTH_8_BITS; + *SA110_UART_CONTROL_REGISTER = SA110_UART_ENABLED | + SA110_SIR_DISABLED; + // All done +} + +#ifdef HAL_DIAG_USES_HARDWARE + +#ifdef DEBUG_DIAG +#ifndef CYG_HAL_STARTUP_ROM +#define DIAG_BUFSIZE 2048 +static char diag_buffer[DIAG_BUFSIZE]; +static int diag_bp = 0; +#endif +#endif + +void hal_diag_read_char(char *c) +{ + while (!hal_diag_read_serial(c)) ; +} + +void hal_diag_write_char(char c) +{ +#ifdef DEBUG_DIAG +#ifndef CYG_HAL_STARTUP_ROM + diag_buffer[diag_bp++] = c; + if (diag_bp == sizeof(diag_buffer)) diag_bp = 0; +#endif +#endif + hal_diag_write_char_serial(c); +} + +#else // not HAL_DIAG_USES_HARDWARE - it uses GDB protocol + +void +hal_diag_read_char(char *c) +{ + while (!hal_diag_read_serial(c)) ; +} + +void +hal_diag_write_char(char c) +{ + static char line[100]; + static int pos = 0; + +#if 0 + // Do not unconditionally poke the XBUS LED location - XBUS may not be + // available if external arbiter is in use. This fragment may still be + // useful for debugging in the future, so left thus: + { +// int i; + *(cyg_uint32 *)0x40012000 = 7 & (cyg_uint32)c; // LED XBUS location +// for ( i = 0x1000000; i > 0; i-- ) ; + } +#endif + + // No need to send CRs + if( c == '\r' ) return; + + line[pos++] = c; + + if( c == '\n' || pos == sizeof(line) ) + { + + CYG_INTERRUPT_STATE old; + + // Disable interrupts. This prevents GDB trying to interrupt us + // while we are in the middle of sending a packet. The serial + // receive interrupt will be seen when we re-enable interrupts + // later. + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old); +#else + HAL_DISABLE_INTERRUPTS(old); +#endif + + while(1) + { + static char hex[] = "0123456789ABCDEF"; + cyg_uint8 csum = 0; + int i; +#ifndef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT + char c1; +#endif + hal_diag_write_char_serial('$'); + hal_diag_write_char_serial('O'); + csum += 'O'; + for( i = 0; i < pos; i++ ) + { + char ch = line[i]; + char h = hex[(ch>>4)&0xF]; + char l = hex[ch&0xF]; + hal_diag_write_char_serial(h); + hal_diag_write_char_serial(l); + csum += h; + csum += l; + } + hal_diag_write_char_serial('#'); + hal_diag_write_char_serial(hex[(csum>>4)&0xF]); + hal_diag_write_char_serial(hex[csum&0xF]); + +#ifdef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT + + break; // regardless + +#else // not CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT Ie. usually... + + // Wait for the ACK character '+' from GDB here and handle + // receiving a ^C instead. This is the reason for this clause + // being a loop. + if (!hal_diag_read_serial(&c1)) + continue; // No response - try sending packet again + + if( c1 == '+' ) + break; // a good acknowledge + +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + cyg_drv_interrupt_acknowledge(CYG_DIAG_DEV_INT); + if( c1 == 3 ) { + // Ctrl-C: breakpoint. + cyg_hal_gdb_interrupt( + (target_register_t)__builtin_return_address(0) ); + break; + } +#endif // CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + +#endif // ! CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT + // otherwise, loop round again + } + + pos = 0; + + + // And re-enable interrupts +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old); +#else + HAL_RESTORE_INTERRUPTS(old); +#endif + + } +} +#endif + +/*---------------------------------------------------------------------------*/ +#ifndef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#ifdef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT +// This routine is polled from the default ISR - the assumption is that any +// other ISR installed knows what it's going and can handle a ^C correctly. +int hal_ctrlc_isr( CYG_ADDRWORD vector, CYG_ADDRWORD data) +{ + char c; + int reg; + if ( CYG_DIAG_DEV_INT != vector ) + return 0; // not for us + + reg = *SA110_UART_FLAG_REGISTER; + // read it anyway just in case - no harm done and we might prevent an + // interrup loop + c = (char)(*SA110_UART_DATA_REGISTER & 0xFF); + if ( (reg & SA110_RX_FIFO_STATUS_MASK) != SA110_RX_FIFO_EMPTY ) { + if ( 3 == c ) { + HAL_BREAKPOINT( hal_ctrlc_isr_breakinst ); + } + } + return 1; +} +#endif +#endif + +/*---------------------------------------------------------------------------*/ +/* End of hal_diag.c */
