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

📄 hal_if.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
//=============================================================================
//
//      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, 2003 Gary Thomas
// Copyright (C) 2003 Nick Garnett <nickg@calivar.com>
// Copyright (C) 2003 Jonathan Larmour <jlarmour@eCosCentric.com>
//
// 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 the copyright
// holders.
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//=============================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):   jskov
// Contributors:jskov, woehler
// 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
#ifdef CYGOPT_REDBOOT_FIS
#include <fis.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_CONFIG

static __call_if_flash_cfg_op_fn_t flash_config_op;

static cyg_bool
flash_config_op(int op, struct cyg_fconfig *fc)
{
    cyg_bool res = false;

    CYGARC_HAL_SAVE_GP();

    switch (op) {
    case CYGNUM_CALL_IF_FLASH_CFG_GET:
        res = flash_get_config(fc->key, fc->val, fc->type);
        break;
    case CYGNUM_CALL_IF_FLASH_CFG_NEXT:
        res = flash_next_key(fc->key, fc->keylen, &fc->type, &fc->offset);
        break;
    case CYGNUM_CALL_IF_FLASH_CFG_SET:
        res = flash_set_config(fc->key, fc->val, fc->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

#ifdef CYGOPT_REDBOOT_FIS

static __call_if_flash_fis_op_fn_t flash_fis_op;

static cyg_bool
flash_fis_op( int op, char *name, void *val)
{
    cyg_bool res = false;
    struct fis_image_desc *fis;
    int num;

    CYGARC_HAL_SAVE_GP();
    fis = fis_lookup(name, &num);
    if(fis != NULL)
    {
        switch ( op ) {
        case CYGNUM_CALL_IF_FLASH_FIS_GET_FLASH_BASE:
            *(CYG_ADDRESS *)val = fis->flash_base; 
            res = true;
            break;
        case CYGNUM_CALL_IF_FLASH_FIS_GET_SIZE:
            *(unsigned long *)val = fis->size;
            res = true;
            break;
        case CYGNUM_CALL_IF_FLASH_FIS_GET_MEM_BASE:
            *(CYG_ADDRESS *)val = fis->mem_base;
            res = true;
            break;
        case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_POINT:
            *(CYG_ADDRESS *)val = fis->entry_point;
            res = true;
            break;
        case CYGNUM_CALL_IF_FLASH_FIS_GET_DATA_LENGTH:
            *(unsigned long *)val = fis->data_length;
            res = true;
            break;
        case CYGNUM_CALL_IF_FLASH_FIS_GET_DESC_CKSUM:
            *(unsigned long *)val = fis->desc_cksum;
            res = true;
            break;
        case CYGNUM_CALL_IF_FLASH_FIS_GET_FILE_CKSUM:
            *(unsigned long *)val = fis->file_cksum;
            res = true;
            break;
        default:
            break;
        }
    }
    CYGARC_HAL_RESTORE_GP();
    return res;
}
#endif

//----------------------------
// Delay uS
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US

static __call_if_delay_us_t delay_us;

static void
delay_us(cyg_int32 usecs)
{
    CYGARC_HAL_SAVE_GP();
#ifdef CYGPKG_KERNEL
    {
        cyg_int32 start, elapsed, elapsed_usec;
        cyg_int32 slice;
        cyg_int32 usec_per_period = CYGNUM_HAL_RTC_NUMERATOR/CYGNUM_HAL_RTC_DENOMINATOR/1000;
        cyg_int32 ticks_per_usec = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/usec_per_period;
        
        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 would also
            // be problems figuring out when the timer wrapped.  We
            // may lose a tick or two for each cycle but it shouldn't
            // matter much.

            // The tests against CYGNUM_KERNEL_COUNTERS_RTC_PERIOD
            // check for a value that would cause a 32 bit signed
            // multiply to overflow. But this also implies that just
            // multiplying by ticks_per_usec will yield a good
            // approximation.  Otherwise we need to do the full
            // multiply+divide to get sufficient accuracy. Note that
            // this test is actually constant, so the compiler will
            // eliminate it and only compile the branch that is
            // selected.
            
            if( usecs > usec_per_period/2 )
                slice = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2;
            else if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2 >= 0x7FFFFFFF/usec_per_period )
                slice = usecs * ticks_per_usec;
            else
            {
                slice = usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
                slice /= usec_per_period;
            }
    
            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.

            if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD >= 0x7FFFFFFF/usec_per_period )
                elapsed_usec = elapsed / ticks_per_usec;
            else
            {
                elapsed_usec = elapsed * usec_per_period;
                elapsed_usec = elapsed_usec / CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
            }

            // It is possible for elapsed_usec to end up zero in some
            // circumstances and we could end up looping indefinitely.
            // Avoid that by ensuring that we always decrement usec by
            // at least 1 each time.
            
            usecs -= elapsed_usec ? elapsed_usec : 1;
            
        } while (usecs > 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_RESET

static __call_if_reset_t reset;

static void
reset(void)
{
    CYGARC_HAL_SAVE_GP();
    // With luck, the platform defines some magic that will cause a hardware
    // reset.
#ifdef HAL_PLATFORM_RESET
    HAL_PLATFORM_RESET();
#endif

#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
    CYG_FAIL("Reset failed");
    CYGARC_HAL_RESTORE_GP();
}

#endif

//------------------------------------
// NOP service
#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE) || \    defined(CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS)
static int
nop_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
#endif

static hal_virtual_comm_table_t comm_channels[CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1];

static int
set_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:

⌨️ 快捷键说明

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