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

📄 hal_if.c

📁 ecos实时嵌入式操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
//=============================================================================////      hal_if.c////      ROM/RAM interfacing functions////=============================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2002 Gary Thomas//// 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// Contributors:jskov// Date:        2000-06-07////####DESCRIPTIONEND####////=============================================================================#include <pkgconf/hal.h>#ifdef CYGPKG_KERNEL# include <pkgconf/kernel.h>#endif#include <cyg/infra/cyg_ass.h>          // assertions#include <cyg/hal/hal_arch.h>           // set/restore GP#include <cyg/hal/hal_io.h>             // IO macros#include <cyg/hal/hal_if.h>             // our interface#include <cyg/hal/hal_diag.h>           // Diag IO#include <cyg/hal/hal_misc.h>           // User break#include <cyg/hal/hal_stub.h>           // stub functionality#include <cyg/hal/hal_intr.h>           // hal_vsr_table and others#ifdef CYGPKG_REDBOOT#include <pkgconf/redboot.h>#ifdef CYGSEM_REDBOOT_FLASH_CONFIG#include <redboot.h>#include <flash_config.h>#endif#endif//--------------------------------------------------------------------------externC void patch_dbg_syscalls(void * vector);externC void init_thread_syscall(void * vector);//--------------------------------------------------------------------------// Implementations and function wrappers for monitor services// flash config state queries#ifdef CYGSEM_REDBOOT_FLASH_CONFIGstatic __call_if_flash_cfg_op_fn_t flash_config_op;static cyg_boolflash_config_op( int op, char * key, void *val, int type){    cyg_bool res = false;    CYGARC_HAL_SAVE_GP();    switch ( op ) {    case CYGNUM_CALL_IF_FLASH_CFG_GET:        res = flash_get_config( key, val, type );        break;    default:        // nothing else supported yet - though it is expected that "set"        // will fit the same set of arguments, potentially.        break;    }    CYGARC_HAL_RESTORE_GP();    return res;}#endif//----------------------------// Delay uS#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_USstatic __call_if_delay_us_t delay_us;static voiddelay_us(cyg_int32 usecs){    CYGARC_HAL_SAVE_GP();#ifdef CYGPKG_KERNEL    {        cyg_int32 start, elapsed;        cyg_int32 usec_ticks, slice;        // How many ticks total we should wait for.        usec_ticks = usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;        usec_ticks /= CYGNUM_HAL_RTC_NUMERATOR/CYGNUM_HAL_RTC_DENOMINATOR/1000;        do {            // Spin in slices of 1/2 the RTC period. Allows interrupts            // time to run without messing up the algorithm. If we spun            // for 1 period (or more) of the RTC, there'd be also problems            // figuring out when the timer wrapped.  We may lose a tick or            // two for each cycle but it shouldn't matter much.            slice = usec_ticks % (CYGNUM_KERNEL_COUNTERS_RTC_PERIOD / 2);                HAL_CLOCK_READ(&start);            do {                HAL_CLOCK_READ(&elapsed);                elapsed = (elapsed - start); // counts up!                if (elapsed < 0)                    elapsed += CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;            } while (elapsed < slice);                        // Adjust by elapsed, not slice, since an interrupt may have            // been stalling us for some time.            usec_ticks -= elapsed;        } while (usec_ticks > 0);    }#else // CYGPKG_KERNEL#ifdef HAL_DELAY_US    // Use a HAL feature if defined    HAL_DELAY_US(usecs);#else    // If no accurate delay mechanism, just spin for a while. Having    // an inaccurate delay is much better than no delay at all. The    // count of 10 should mean the loop takes something resembling    // 1us on most CPUs running between 30-100MHz [depends on how many    // instructions this compiles to, how many dispatch units can be    // used for the simple loop, actual CPU frequency, etc]    while (usecs-- > 0) {        int i;        for (i = 0; i < 10; i++);    }#endif // HAL_DELAY_US#endif // CYGPKG_KERNEL    CYGARC_HAL_RESTORE_GP();}#endif // CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US// Reset functions#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESETstatic __call_if_reset_t reset;static voidreset(void){    CYGARC_HAL_SAVE_GP();    // With luck, the platform defines some magic that will cause a hardware    // reset.    HAL_PLATFORM_RESET();#ifdef HAL_PLATFORM_RESET_ENTRY    // If that's not the case (above is an empty statement) there may    // be defined an address we can jump to - and effectively    // reinitialize the system. Not quite as good as a reset, but it    // is often enough.    goto *HAL_PLATFORM_RESET_ENTRY;#else#error " no RESET_ENTRY"#endif    CYGARC_HAL_RESTORE_GP();}// This is the system's default kill signal routine. Unless overridden// by the application, it will cause a board reset when GDB quits the// connection. (The user can avoid the reset by using the GDB 'detach'// command instead of 'kill' or 'quit').static intkill_by_reset(int __irq_nr, void* __regs){    CYGARC_HAL_SAVE_GP();    reset();    CYGARC_HAL_RESTORE_GP();    return 0;}#endif//------------------------------------// NOP service#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE) || \    defined(CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS)static intnop_service(void){    // This is the default service. It always returns false (0), and    // _does not_ trigger any assertions. Clients must either cope    // with the service failure or assert.    return 0;}#endif//----------------------------------// Comm controls#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS#ifdef CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS#define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \  (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS+CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS)#else#define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \  CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS#endifstatic hal_virtual_comm_table_t comm_channels[CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1];static intset_debug_comm(int __comm_id){    static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY;    hal_virtual_comm_table_t* __chan;    int interrupt_state = 0;    int res = 1, update = 0;    CYGARC_HAL_SAVE_GP();    CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER               && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS,               "Invalid channel");    switch (__comm_id) {    case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT:        if (__selected_id > 0)            res = __selected_id-1;        else if (__selected_id == 0)            res = CYGNUM_CALL_IF_SET_COMM_ID_MANGLER;        else             res = __selected_id;        break;    case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY:        CYGACC_CALL_IF_DEBUG_PROCS_SET(0);        __selected_id = __comm_id;        break;    case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER:        __comm_id = 0;        update = 1;        break;    default:        __comm_id++;                    // skip mangler entry        update = 1;        break;    }    if (update) {        // Find the interrupt state of the channel.        __chan = CYGACC_CALL_IF_DEBUG_PROCS();        if (__chan)            interrupt_state = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE);        __selected_id = __comm_id;        CYGACC_CALL_IF_DEBUG_PROCS_SET(comm_channels[__comm_id]);        // Set interrupt state on the new channel.        __chan = CYGACC_CALL_IF_DEBUG_PROCS();        if (interrupt_state)            CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE);        else            CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE);    }    CYGARC_HAL_RESTORE_GP();    return res;}static intset_console_comm(int __comm_id){    static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY;    int res = 1, update = 0;    CYGARC_HAL_SAVE_GP();    CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER               && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS,               "Invalid channel");    switch (__comm_id) {    case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT:        if (__selected_id > 0)            res = __selected_id-1;        else if (__selected_id == 0)            res = CYGNUM_CALL_IF_SET_COMM_ID_MANGLER;        else            res = __selected_id;        break;    case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY:        CYGACC_CALL_IF_CONSOLE_PROCS_SET(0);        __selected_id = __comm_id;        break;    case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER:        __comm_id = 0;        update = 1;        break;    default:        __comm_id++;                    // skip mangler entry        update = 1;        break;    }        if (update) {        __selected_id = __comm_id;            CYGACC_CALL_IF_CONSOLE_PROCS_SET(comm_channels[__comm_id]);    }    CYGARC_HAL_RESTORE_GP();    return res;}#endif//----------------------------------// Cache functions#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_CACHEstatic voidflush_icache(void *__p, int __nbytes){    CYGARC_HAL_SAVE_GP();#ifdef HAL_ICACHE_FLUSH    HAL_ICACHE_FLUSH( __p , __nbytes );#elif defined(HAL_ICACHE_INVALIDATE)    HAL_ICACHE_INVALIDATE();#endif    CYGARC_HAL_RESTORE_GP();}static voidflush_dcache(void *__p, int __nbytes){    CYGARC_HAL_SAVE_GP();#ifdef HAL_DCACHE_FLUSH    HAL_DCACHE_FLUSH( __p , __nbytes );#elif defined(HAL_DCACHE_INVALIDATE)    HAL_DCACHE_INVALIDATE();#endif    CYGARC_HAL_RESTORE_GP();}#endif#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG)//-----------------------------------------------------------------------------// GDB console output mangler (O-packetizer)// COMMS init function at end.// This gets called via the virtual vector console comms entry and// handles O-packetization. The debug comms entries are used for the// actual device IO.static cyg_uint8cyg_hal_diag_mangler_gdb_getc(void* __ch_data){    cyg_uint8 __ch;    hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();    CYGARC_HAL_SAVE_GP();    __ch = CYGACC_COMM_IF_GETC(*__chan);    CYGARC_HAL_RESTORE_GP();    return __ch;}static char __mangler_line[100];static int  __mangler_pos = 0;static voidcyg_hal_diag_mangler_gdb_flush(void* __ch_data){    CYG_INTERRUPT_STATE old;    hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();    // Nothing to do if mangler buffer is empty.    if (__mangler_pos == 0)        return;    // 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.#if defined(CYG_HAL_STARTUP_ROM) \    || !defined(CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION)    HAL_DISABLE_INTERRUPTS(old);#else    CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old);#endif        #if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0    // Only wait 500ms for data to arrive - avoid "stuck" connections    CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, CYGNUM_HAL_DEBUG_GDB_PROTOCOL_TIMEOUT);#endif    while(1)    {	static const char hex[] = "0123456789ABCDEF";	cyg_uint8 csum = 0, c1;	int i;        	CYGACC_COMM_IF_PUTC(*__chan, '$');	CYGACC_COMM_IF_PUTC(*__chan, 'O');	csum += 'O';	for( i = 0; i < __mangler_pos; i++ )        {	    char ch = __mangler_line[i];	    char h = hex[(ch>>4)&0xF];	    char l = hex[ch&0xF];	    CYGACC_COMM_IF_PUTC(*__chan, h);	    CYGACC_COMM_IF_PUTC(*__chan, l);	    csum += h;	    csum += l;	}	CYGACC_COMM_IF_PUTC(*__chan, '#');	CYGACC_COMM_IF_PUTC(*__chan, hex[(csum>>4)&0xF]);	CYGACC_COMM_IF_PUTC(*__chan, hex[csum&0xF]);    nak:#if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0	if (CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, &c1) == 0) {	    c1 = '-';	    if (tries && (--tries == 0)) c1 = '+';	}#else	c1 = CYGACC_COMM_IF_GETC(*__chan);#endif	if( c1 == '+' ) break;	if( cyg_hal_is_break( &c1 , 1 ) ) {	    // Caller's responsibility to react on this.	    CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(1);	    break;	}	if( c1 != '-' ) goto nak;    }    __mangler_pos = 0;    // And re-enable interrupts#if defined(CYG_HAL_STARTUP_ROM) \    || !defined(CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION)    HAL_RESTORE_INTERRUPTS(old);#else    CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old);#endif}

⌨️ 快捷键说明

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