⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hal_stub.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
//=============================================================================
//
//      hal_stub.c
//
//      Helper functions for stub, specific to eCos HAL
//
//=============================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 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):   jskov (based on powerpc/cogent hal_stub.c)
// Contributors:jskov, dmoseley
// Date:        1999-02-12
// Purpose:     Helper functions for stub, specific to eCos HAL
// Description: Parts of the GDB stub requirements are provided by
//              the eCos HAL, rather than target and/or board specific
//              code. 
//
//####DESCRIPTIONEND####
//
//=============================================================================

#include <pkgconf/hal.h>
#ifdef CYGPKG_CYGMON
#include <pkgconf/cygmon.h>
#endif

#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS

#include <cyg/hal/hal_stub.h>           // Our header

#include <cyg/hal/hal_arch.h>           // HAL_BREAKINST
#include <cyg/hal/hal_cache.h>          // HAL_xCACHE_x
#include <cyg/hal/hal_intr.h>           // interrupt disable/restore

#include <cyg/hal/hal_if.h>             // ROM calling interface
#include <cyg/hal/hal_misc.h>           // Helper functions

#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT
#include <cyg/hal/dbg-threads-api.h>    // dbg_currthread_id
#endif

#ifdef USE_LONG_NAMES_FOR_ENUM_REGNAMES
#ifndef PC
#define PC REG_PC
#endif
#ifndef SP
#define SP REG_SP
#endif
#endif

//-----------------------------------------------------------------------------
// Extra eCos data.

// Some architectures use registers of different sizes, so NUMREGS
// alone is not suffucient to size the register save area. For those
// architectures, HAL_STUB_REGISTERS_SIZE is defined as the number
// of target_register_t sized elements in the register save area.
#ifndef HAL_STUB_REGISTERS_SIZE
#define HAL_STUB_REGISTERS_SIZE NUMREGS
#endif

// Saved registers.
HAL_SavedRegisters *_hal_registers;
target_register_t registers[HAL_STUB_REGISTERS_SIZE];
target_register_t alt_registers[HAL_STUB_REGISTERS_SIZE] ;  // Thread or saved process state
target_register_t * _registers = registers;                 // Pointer to current set of registers
#ifndef CYGPKG_REDBOOT
target_register_t orig_registers[HAL_STUB_REGISTERS_SIZE];  // Registers to get back to original state
#endif

#if defined(HAL_STUB_HW_WATCHPOINT) || defined(HAL_STUB_HW_BREAKPOINT)
static int  _hw_stop_reason;   // Reason we were stopped by hw.

//#define HAL_STUB_HW_SEND_STOP_REASON_TEXT
#ifdef CYGINT_HAL_ARM_ARCH_XSCALE
#define HAL_STUB_HW_SEND_STOP_REASON_TEXT
#endif

#ifdef HAL_STUB_HW_SEND_STOP_REASON_TEXT
// strings indexed by hw stop reasons defined in hal_stub.h

// Not all GDBs understand this.
static const char * const _hw_stop_str[] = {
    "",
    "hbreak",
    "watch",
    "rwatch",
    "awatch"
};
#endif // HAL_STUB_HW_SEND_STOP_REASON_TEXT

static void *_watch_data_addr; // The data address if stopped by watchpoint
#endif // defined(HAL_STUB_HW_WATCHPOINT) || defined(HAL_STUB_HW_BREAKPOINT)

// Register validity checking
#ifdef CYGHWR_REGISTER_VALIDITY_CHECKING
int registers_valid[NUMREGS];
int *_registers_valid = registers_valid;
#endif

#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away
// Interrupt control.
static volatile __PFI __interruptible_control;
#endif

// Some architectures need extras regs reported in T packet
#ifndef HAL_STUB_ARCH_T_PACKET_EXTRAS
#define HAL_STUB_ARCH_T_PACKET_EXTRAS(x)
#endif

//-----------------------------------------------------------------------------
// Register access

#ifndef CYGARC_STUB_REGISTER_ACCESS_DEFINED
// Return the currently-saved value corresponding to register REG of
// the exception context.
target_register_t 
get_register (regnames_t reg)
{
    return _registers[reg];
}
#endif

#ifdef CYGHWR_REGISTER_VALIDITY_CHECKING
// Return the validity of register REG.
int
get_register_valid (regnames_t reg)
{
    return _registers_valid[reg];
}
#endif

#ifndef CYGARC_STUB_REGISTER_ACCESS_DEFINED
// Store VALUE in the register corresponding to WHICH in the exception
// context.
void 
put_register (regnames_t which, target_register_t value)
{
#ifdef CYGPKG_HAL_MIPS_VR4300
    // This is a rather nasty kludge to compensate for the fact that
    // the VR4300 GDB is rather old and does not support proper 64 bit
    // registers. The only time this really matters is when setting
    // the PC after loading an executable. So here we detect this case
    // and artificially sign extend it. 
    
    if( which == PC && (value & 0x0000000080000000ULL ) )
    {
        value |= 0xFFFFFFFF00000000ULL;
    }
#endif    
    _registers[which] = value;
}
#endif // CYGARC_STUB_REGISTER_ACCESS_DEFINED

//-----------------------------------------------------------------------------
// Serial stuff
#ifdef CYGPKG_CYGMON
extern void ecos_bsp_console_putc(char);
extern char ecos_bsp_console_getc(void);
#endif

// Write C to the current serial port.
void 
putDebugChar (int c)
{
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
    __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS();
    CYGACC_COMM_IF_PUTC(*__debug_procs, c);
#elif defined(CYGPKG_CYGMON)
    ecos_bsp_console_putc(c);
#else
    HAL_STUB_PLATFORM_PUT_CHAR(c);
#endif
}

// Read one character from the current serial port.
int 
getDebugChar (void)
{
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
    __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS();
    return CYGACC_COMM_IF_GETC(*__debug_procs);
#elif defined(CYGPKG_CYGMON)
    return ecos_bsp_console_getc();
#else
    return HAL_STUB_PLATFORM_GET_CHAR();
#endif
}

// Flush output channel
void
hal_flush_output(void)
{
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
    __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS();
    CYGACC_COMM_IF_CONTROL(*__debug_procs, __COMMCTL_FLUSH_OUTPUT);
#endif
}


// Set the baud rate for the current serial port.
void 
__set_baud_rate (int baud) 
{
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
    __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS();
    CYGACC_COMM_IF_CONTROL(*__debug_procs, __COMMCTL_SETBAUD, baud);
#elif defined(CYGPKG_CYGMON)
    // FIXME!
#else
    HAL_STUB_PLATFORM_SET_BAUD_RATE(baud);
#endif
}

//-----------------------------------------------------------------------------
// GDB interrupt (BREAK) support.

#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT

#ifndef CYGPKG_HAL_ARM

#if (HAL_BREAKINST_SIZE == 1)
typedef cyg_uint8 t_inst;
#elif (HAL_BREAKINST_SIZE == 2)
typedef cyg_uint16 t_inst;
#elif (HAL_BREAKINST_SIZE == 4)
typedef cyg_uint32 t_inst;
#else
#error "Don't know how to handle that size"
#endif

typedef struct
{
  t_inst *targetAddr;
  t_inst savedInstr;
} instrBuffer;

static instrBuffer break_buffer;

volatile int cyg_hal_gdb_running_step = 0;

void 
cyg_hal_gdb_place_break (target_register_t pc)
{
    cyg_hal_gdb_interrupt( pc ); // Let's hope this becomes a drop-through:
}

void 
cyg_hal_gdb_interrupt (target_register_t pc)
{
    CYGARC_HAL_SAVE_GP();

    // Clear flag that we Continued instead of Stepping
    cyg_hal_gdb_running_step = 0;
    // and override existing break? So that a ^C takes effect...
    if (NULL != break_buffer.targetAddr)
        cyg_hal_gdb_remove_break( (target_register_t)break_buffer.targetAddr );

    if (NULL == break_buffer.targetAddr) {
        break_buffer.targetAddr = (t_inst*) pc;
        break_buffer.savedInstr = *(t_inst*)pc;
        *(t_inst*)pc = (t_inst)HAL_BREAKINST;

        __data_cache(CACHE_FLUSH);
        __instruction_cache(CACHE_FLUSH);
    }

    CYGARC_HAL_RESTORE_GP();
}

int 
cyg_hal_gdb_remove_break (target_register_t pc)
{
    if ( cyg_hal_gdb_running_step )
        return 0;

    if ((t_inst*)pc == break_buffer.targetAddr) {
        *(t_inst*)pc = break_buffer.savedInstr;
        break_buffer.targetAddr = NULL;

        __data_cache(CACHE_FLUSH);
        __instruction_cache(CACHE_FLUSH);
        return 1;
    }
    return 0;
}

int 
cyg_hal_gdb_break_is_set (void)
{
    if (NULL != break_buffer.targetAddr) {
        return 1;
    }
    return 0;
}

#endif // CYGPKG_HAL_ARM

#endif // CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT

// Use this function to disable serial interrupts whenever reply
// characters are expected from GDB.  The reason we want to control
// whether the target can be interrupted or not is simply that GDB on
// the host will be sending acknowledge characters/commands while the
// stub is running - if serial interrupts were still active, the
// characters would never reach the (polling) getDebugChar.
static void
interruptible(int state)
{
    static int __interrupts_suspended = 0;

    if (state) {
        __interrupts_suspended--;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -