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

📄 hal_stub.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 2 页
字号:
//=============================================================================////      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 statetarget_register_t * _registers = registers;                 // Pointer to current set of registers#ifndef CYGPKG_REDBOOTtarget_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_TEXTstatic 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_CHECKINGint 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.intget_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_CYGMONextern 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 channelvoidhal_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"#endiftypedef 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 voidinterruptible(int state){    static int __interrupts_suspended = 0;    if (state) {        __interrupts_suspended--;        if (0 >= __interrupts_suspended) {            __interrupts_suspended = 0;#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away            {                hal_virtual_comm_table_t* __chan;                __chan = CYGACC_CALL_IF_DEBUG_PROCS();                CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE);            }#else                            if (__interruptible_control)                __interruptible_control(1);#endif        }    } else {        __interrupts_suspended++;        if (1 == __interrupts_suspended)#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away            {                hal_virtual_comm_table_t* __chan;                __chan = CYGACC_CALL_IF_DEBUG_PROCS();                CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE);            }#else                            if (__interruptible_control)                __interruptible_control(0);#endif    }}//-----------------------------------------------------------------------------// eCos stub entry and exit magic.#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORTint cyg_hal_gdb_break;#endif#ifdef CYGPKG_REDBOOT// Trampoline for returning to RedBoot from exception/stub codestatic voidreturn_from_stub(int exit_status){    CYGACC_CALL_IF_MONITOR_RETURN(exit_status);}#endif// Called at stub *kill*static void handle_exception_exit( void ){#ifdef CYGPKG_REDBOOT#ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF    {   // Reset the timer to default and cancel any callback	extern void sys_profile_reset(void);	sys_profile_reset();    }#endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF    set_pc((target_register_t)return_from_stub);#else    int i;    for (i = 0; i < (sizeof(registers)/sizeof(registers[0])); i++)	registers[i] = orig_registers[i];#endif}// Called at stub *entry*static void handle_exception_cleanup( void ){#ifndef CYGPKG_REDBOOT    static int orig_registers_set = 0;#endif    interruptible(0);    // Expand the HAL_SavedRegisters structure into the GDB register    // array format.    HAL_GET_GDB_REGISTERS(&registers[0], _hal_registers);    _registers = &registers[0];#ifndef CYGPKG_REDBOOT    if (!orig_registers_set) {	int i;	for (i = 0; i < (sizeof(registers)/sizeof(registers[0])); i++)	    orig_registers[i] = registers[i];	_registers = &orig_registers[0];	if (__is_breakpoint_function ())	    __skipinst ();	_registers = &registers[0];	orig_registers_set = 1;    }#endif	#ifdef HAL_STUB_PLATFORM_STUBS_FIXUP    // Some architectures may need to fix the PC in case of a partial    // or fully executed trap instruction. GDB only takes correct action    // when the PC is pointing to the breakpoint instruction it set.    //     // Most architectures would leave PC pointing at the trap    // instruction itself though, and so do not need to do anything    // special.    HAL_STUB_PLATFORM_STUBS_FIXUP();#endif#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT    // If we continued instead of stepping, when there was a break set    // ie. we were stepping within a critical region, clear the break, and    // that flag.  If we stopped for some other reason, this has no effect.    if ( cyg_hal_gdb_running_step ) {        cyg_hal_gdb_running_step = 0;        cyg_hal_gdb_remove_break(get_register (PC));    }    // FIXME: (there may be a better way to do this)    // If we hit a breakpoint set by the gdb interrupt stub, make it    // seem like an interrupt rather than having hit a breakpoint.    cyg_hal_gdb_break = cyg_hal_gdb_remove_break(get_register (PC));#endif#if defined(HAL_STUB_HW_WATCHPOINT) || defined(HAL_STUB_HW_BREAKPOINT)    // For HW watchpoint/breakpoint support, we need to know if we    // stopped because of watchpoint or hw break. We do that here    // before GDB has a chance to remove the watchpoints and save    // the information for later use in building response packets.    _hw_stop_reason = HAL_STUB_IS_STOPPED_BY_HARDWARE(_watch_data_addr);#endif    }// Called at stub *exit*static void handle_exception_init( void ){    // Compact register array again.    HAL_SET_GDB_REGISTERS(_hal_registers, &registers[0]);    interruptible(1);}//-----------------------------------------------------------------------------// Initialization.// Signal handler.int cyg_hal_process_signal (int signal){    // We don't care about the signal (atm).    return 0;}// Install the standard set of trap handlers for the stub.void __install_traps (void){    // Set signal handling vector so we can treat 'C<signum>' as 'c'.    __process_signal_vec = &cyg_hal_process_signal;    __process_exit_vec = &handle_exception_exit;    __cleanup_vec = &handle_exception_cleanup;    __init_vec    = &handle_exception_init;#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT    // Control of GDB interrupts.    __interruptible_control = HAL_STUB_PLATFORM_INTERRUPTIBLE;#endif#endif    // Nothing further to do, handle_exception will be called when an    // exception occurs.}// Initialize the hardware.

⌨️ 快捷键说明

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