📄 hal_diag.c
字号:
/*=============================================================================
//
// hal_diag.c
//
// HAL diagnostic output code
//
//=============================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//=============================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): nickg
// Contributors: nickg
// Date: 1998-03-02
// Purpose: HAL diagnostic output
// Description: Implementations of HAL diagnostic output support.
//
//####DESCRIPTIONEND####
//
//===========================================================================*/
#include <pkgconf/hal.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_diag.h>
#include <cyg/hal/hal_intr.h>
/*---------------------------------------------------------------------------*/
/* Select default diag channel to use */
//#define CYG_KERNEL_DIAG_ROMART
//#define CYG_KERNEL_DIAG_SERIAL1
//#define CYG_KERNEL_DIAG_SERIAL2
//#define CYG_KERNEL_DIAG_GDB
#if !defined(CYG_KERNEL_DIAG_SERIAL1) && \
!defined(CYG_KERNEL_DIAG_SERIAL2) && \
!defined(CYG_KERNEL_DIAG_ROMART)
# if defined(CYG_HAL_MN10300_AM31_STDEVAL1)
# if defined(CYG_HAL_STARTUP_RAM)
# if defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)
// If loaded into RAM via CYGMON we diag via
// serial 2 using GDB protocol
# define CYG_KERNEL_DIAG_SERIAL2
# define CYG_KERNEL_DIAG_GDB
# elif defined(CYGSEM_HAL_USE_ROM_MONITOR_Sload)
// If loaded into RAM via SLOAD we diag via
// serial 1
# define CYG_KERNEL_DIAG_SERIAL1
# elif defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs)
// If loaded into RAM via GDB STUB ROM we diag via
// serial 1 using GDB protocol
# define CYG_KERNEL_DIAG_SERIAL1
# define CYG_KERNEL_DIAG_GDB
# endif // defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)
# elif defined(CYG_HAL_STARTUP_ROM)
// If we are ROM resident, we diag via serial 1
# define CYG_KERNEL_DIAG_SERIAL1
# endif // defined(CYG_HAL_STARTUP_RAM)
# endif // defined(CYG_HAL_MN10300_AM31_STDEVAL1)
#endif // if ...
/*---------------------------------------------------------------------------*/
// PromICE AI interface
#if defined(CYG_HAL_MN10300_STDEVAL1_ROMART) || defined(CYG_KERNEL_DIAG_ROMART)
#ifdef CYG_HAL_MN10300_AM31_STDEVAL1
#define PROMICE_AILOC 0x40008000
#endif
#define PROMICE_BUS_SIZE 16
#define PROMICE_BURST_SIZE 1
#if PROMICE_BUS_SIZE == 16
typedef volatile struct
{
volatile cyg_uint16 zero;
// cyg_uint16 pad1[PROMICE_BURST_SIZE];
volatile cyg_uint16 one;
// cyg_uint16 pad2[PROMICE_BURST_SIZE];
volatile cyg_uint16 data;
// cyg_uint16 pad3[PROMICE_BURST_SIZE];
volatile cyg_uint16 status;
} AISTRUCT;
#endif
AISTRUCT *AI = (AISTRUCT *)PROMICE_AILOC;
#define PROMICE_STATUS_TDA 0x01
#define PROMICE_STATUS_HDA 0x02
#define PROMICE_STATUS_OVR 0x04
void ai_diag_init()
{
volatile cyg_uint8 junk;
while( AI->status == 0xCC )
continue;
junk = AI->data;
}
static void ai_write_char(cyg_uint8 data)
{
volatile cyg_uint8 junk;
int i;
// Wait for tda == 0
while( (AI->status & PROMICE_STATUS_TDA) == PROMICE_STATUS_TDA )
continue;
// Send start bit
junk = AI->one;
for( i = 0; i < 8; i++ )
{
// send ls bit of data
if( (data & 1) == 1 )
junk = AI->one;
else
junk = AI->zero;
// shift down for next bit
data >>= 1;
}
// Send stop bit
junk = AI->one;
// all done
}
void ai_diag_write_char(char c)
{
ai_write_char((cyg_uint8)c);
}
void ai_diag_drain() {}
void ai_diag_read_char(char *c) { *c = '\n'; }
void ai_writes(char *s)
{
while( *s ) ai_write_char( *s++ );
}
void ai_write_hex( cyg_uint32 x)
{
int i;
ai_writes("0x");
for( i = 28; i >=0 ; i-=4 )
{
char *d = "0123456789ABCDEF";
ai_write_char( d[(x>>i)&0xf] );
}
ai_write_char(' ');
}
#if defined(CYG_KERNEL_DIAG_ROMART)
#define hal_diag_init_serial ai_diag_init
#define hal_diag_write_char_serial ai_diag_write_char
#define hal_diag_drain_serial ai_diag_drain
#define hal_diag_read_char_serial ai_diag_read_char
#endif
#endif
/*---------------------------------------------------------------------------*/
// MN10300 Serial line
#if defined(CYG_HAL_MN10300_STDEVAL1_SERIAL1) || defined(CYG_KERNEL_DIAG_SERIAL1)
// We use serial1 on MN103002
#define SERIAL1_CR ((volatile cyg_uint16 *)0x34000810)
#define SERIAL1_ICR ((volatile cyg_uint8 *) 0x34000814)
#define SERIAL1_TXR ((volatile cyg_uint8 *) 0x34000818)
#define SERIAL1_RXR ((volatile cyg_uint8 *) 0x34000819)
#define SERIAL1_SR ((volatile cyg_uint16 *)0x3400081c)
// Timer 1 provided baud rate divisor
#define TIMER1_MD ((volatile cyg_uint8 *)0x34001001)
#define TIMER1_BR ((volatile cyg_uint8 *)0x34001011)
#define TIMER1_CR ((volatile cyg_uint8 *)0x34001021)
#define PORT3_MD ((volatile cyg_uint8 *)0x36008025)
// Mystery register
#define TMPSCNT ((volatile cyg_uint8 *)0x34001071)
#define SIO1_LSTAT_TRDY 0x20
#define SIO1_LSTAT_RRDY 0x10
void hal_diag_init_serial1(void)
{
// 48 translates to 38400 baud.
*TIMER1_BR = 48;
// Timer1 sourced from IOCLK
*TIMER1_MD = 0x80;
// Mode on PORT3, used for serial line controls.
*PORT3_MD = 0x01;
// No interrupts for now.
*SERIAL1_ICR = 0x00;
// Source from timer 1, 8bit chars, enable tx and rx
*SERIAL1_CR = 0xc084;
}
void hal_diag_write_char_serial1(char c)
{
register volatile cyg_uint16 *volatile tty_status = SERIAL1_SR;
register volatile cyg_uint8 *volatile tty_tx = SERIAL1_TXR;
while( (*tty_status & SIO1_LSTAT_TRDY) != 0 ) continue;
*tty_tx = c;
}
void hal_diag_drain_serial1(void)
{
register volatile cyg_uint16 *volatile tty_status = SERIAL1_SR;
while( (*tty_status & SIO1_LSTAT_TRDY) != 0 ) continue;
}
void hal_diag_read_char_serial1(char *c)
{
register volatile cyg_uint16 *volatile tty_status = SERIAL1_SR;
register volatile cyg_uint8 *volatile tty_rx = SERIAL1_RXR;
while( (*tty_status & SIO1_LSTAT_RRDY) == 0 ) continue;
*c = *tty_rx;
// We must ack the interrupt caused by that read to avoid
// confusing cygmon.
HAL_INTERRUPT_ACKNOWLEDGE( CYGNUM_HAL_INTERRUPT_SERIAL_1_RX );
}
#if defined(CYG_KERNEL_DIAG_SERIAL1)
#define hal_diag_init_serial hal_diag_init_serial1
#define hal_diag_write_char_serial hal_diag_write_char_serial1
#define hal_diag_drain_serial hal_diag_drain_serial1
#define hal_diag_read_char_serial hal_diag_read_char_serial1
#endif
#endif
#if defined(CYG_HAL_MN10300_AM31_STDEVAL1)
void led(int x)
{
*((cyg_uint8 *)0x36008004) = x<<4;
}
#endif
/*---------------------------------------------------------------------------*/
#if defined(CYG_HAL_MN10300_STDEVAL1_SERIAL2) || defined(CYG_KERNEL_DIAG_SERIAL2)
// We use serial2 on MN103002
#define SERIAL2_CR ((volatile cyg_uint16 *)0x34000820)
#define SERIAL2_ICR ((volatile cyg_uint8 *) 0x34000824)
#define SERIAL2_TXR ((volatile cyg_uint8 *) 0x34000828)
#define SERIAL2_RXR ((volatile cyg_uint8 *) 0x34000829)
#define SERIAL2_SR ((volatile cyg_uint8 *)0x3400082c)
#define SERIAL2_TR ((volatile cyg_uint8 *)0x3400082d)
// Timer 2 provided baud rate divisor
#define TIMER2_MD ((volatile cyg_uint8 *)0x34001002)
#define TIMER2_BR ((volatile cyg_uint8 *)0x34001012)
#define TIMER2_CR ((volatile cyg_uint8 *)0x34001022)
#define PORT3_MD ((volatile cyg_uint8 *)0x36008025)
// Mystery register
#define TMPSCNT ((volatile cyg_uint8 *)0x34001071)
#define SIO2_LSTAT_TRDY 0x20
#define SIO2_LSTAT_RRDY 0x10
void hal_diag_init_serial2(void)
{
#if !defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)
// 16 and 22 translate to 38400 baud.
*TIMER2_BR = 16;
*SERIAL2_TR = 22;
// Timer2 sourced from IOCLK
*TIMER2_MD = 0x80;
// Mode on PORT3, used for serial line controls.
*PORT3_MD = 0x01;
// No interrupts for now.
*SERIAL2_ICR = 0x00;
// Source from timer 2, 8bit chars, enable tx and rx
*SERIAL2_CR = 0xc081;
#endif
}
void hal_diag_write_char_serial2(char c)
{
register volatile cyg_uint8 *volatile tty_status = SERIAL2_SR;
register volatile cyg_uint8 *volatile tty_tx = SERIAL2_TXR;
while( (*tty_status & SIO2_LSTAT_TRDY) != 0 ) continue;
*tty_tx = c;
}
void hal_diag_drain_serial2(void)
{
register volatile cyg_uint8 *volatile tty_status = SERIAL2_SR;
while( (*tty_status & SIO2_LSTAT_TRDY) != 0 ) continue;
}
void hal_diag_read_char_serial2(char *c)
{
register volatile cyg_uint8 *volatile tty_status = SERIAL2_SR;
register volatile cyg_uint8 *volatile tty_rx = SERIAL2_RXR;
while( (*tty_status & SIO2_LSTAT_RRDY) == 0 ) continue;
*c = *tty_rx;
#if !defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)
// We must ack the interrupt caused by that read to avoid
// confusing the stubs.
HAL_INTERRUPT_ACKNOWLEDGE( CYGNUM_HAL_INTERRUPT_SERIAL_2_RX );
#endif
}
#if defined(CYG_KERNEL_DIAG_SERIAL2)
#define hal_diag_init_serial hal_diag_init_serial2
#define hal_diag_write_char_serial hal_diag_write_char_serial2
#define hal_diag_drain_serial hal_diag_drain_serial2
#define hal_diag_read_char_serial hal_diag_read_char_serial2
#endif
#endif
/*---------------------------------------------------------------------------*/
void hal_diag_init(void)
{
hal_diag_init_serial();
}
void hal_diag_write_char(char c)
{
#ifdef CYG_KERNEL_DIAG_GDB
static char line[100];
static int pos = 0;
// No need to send CRs
if( c == '\r' ) return;
line[pos++] = c;
if( c == '\n' || pos == sizeof(line) )
{
// 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.
CYG_INTERRUPT_STATE oldstate;
CYG_BYTE wdcr;
HAL_DISABLE_INTERRUPTS(oldstate);
// Beacuse of problems with NT on the testfarm, we also have
// to disable the watchdog here. This only matters in the
// watchdog tests. And yes, this sends my irony meter off the
// scale too.
HAL_READ_UINT8( 0x34004002, wdcr );
HAL_WRITE_UINT8( 0x34004002, wdcr&0x3F );
while(1)
{
static char hex[] = "0123456789ABCDEF";
cyg_uint8 csum = 0;
int i;
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]);
#if !defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)
{
char c1;
hal_diag_read_char_serial( &c1 );
if( c1 == '+' ) break;
if( cyg_hal_is_break( &c1, 1 ) )
cyg_hal_user_break( NULL );
}
#else
// When using Cygmon, the ack character is absorbed by cygmon's
// serial interrupt handler that is looking for Ctrl-Cs.
break;
#endif
}
pos = 0;
// Wait for tx buffer to drain
hal_diag_drain_serial();
// And re-enable interrupts
HAL_RESTORE_INTERRUPTS(oldstate);
HAL_WRITE_UINT8( 0x34004002, wdcr );
}
#else
hal_diag_write_char_serial(c);
#endif
}
void hal_diag_read_char(char *c)
{
hal_diag_read_char_serial(c);
}
/*---------------------------------------------------------------------------*/
/* End of hal_diag.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -