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

📄 drv_api.c

📁 基于ecos的redboot
💻 C
📖 第 1 页 / 共 2 页
字号:
//==========================================================================
//
//      drv_api.c
//
//      Driver API for non-kernel configurations
//
//==========================================================================
//####COPYRIGHTBEGIN####
//                                                                          
// -------------------------------------------                              
// The contents of this file are subject to the Red Hat eCos Public License 
// Version 1.1 (the "License"); you may not use this file except in         
// compliance with the License.  You may obtain a copy of the License at    
// http://www.redhat.com/                                                   
//                                                                          
// Software distributed under the License is distributed on an "AS IS"      
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
// License for the specific language governing rights and limitations under 
// the License.                                                             
//                                                                          
// The Original Code is eCos - Embedded Configurable Operating System,      
// released September 30, 1998.                                             
//                                                                          
// The Initial Developer of the Original Code is Red Hat.                   
// Portions created by Red Hat are                                          
// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.                             
// All Rights Reserved.                                                     
// -------------------------------------------                              
//                                                                          
//####COPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):   Nick Garnett
// Date:        1999-02-24
// Purpose:     Driver API for non-kernel configurations
// Description: These functions are used to support drivers when the kernel
//              is not present.
//              
//              
//
//####DESCRIPTIONEND####
//
//==========================================================================

#include <pkgconf/system.h>

#ifndef CYGPKG_KERNEL

#include <cyg/infra/cyg_type.h>
#include <cyg/infra/cyg_trac.h>
#include <cyg/infra/cyg_ass.h>

#include <pkgconf/hal.h>
#include <cyg/hal/drv_api.h>

#include <cyg/hal/hal_arch.h>
#include <cyg/hal/hal_intr.h>

//--------------------------------------------------------------------------
// Statics

static volatile cyg_int32 isr_disable_counter = 1;  // ISR disable counter

volatile cyg_int32 dsr_disable_counter  // DSR disable counter
                      CYGBLD_ATTRIB_ASM_ALIAS( cyg_scheduler_sched_lock );

static cyg_interrupt* volatile dsr_list;        // List of pending DSRs

#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN

cyg_interrupt *chain_list[CYGNUM_HAL_ISR_COUNT];

#endif

//--------------------------------------------------------------------------
// DSR handling functions.
// post_dsr() places a DSR on the list of DSRs to be called.
// call_dsrs() calls the DSRs.

static void post_dsr( cyg_interrupt *intr )
{
    CYG_INTERRUPT_STATE old_intr;

    CYG_REPORT_FUNCTION();

    HAL_DISABLE_INTERRUPTS(old_intr);

    if( intr->dsr_count++ == 0 )
    {
        intr->next_dsr = dsr_list;
        dsr_list = intr;
    }

    HAL_RESTORE_INTERRUPTS(old_intr);

    CYG_REPORT_RETURN();    
}

static void call_dsrs(void)
{
    CYG_REPORT_FUNCTION();
    
    while( dsr_list != NULL )
    {
        cyg_interrupt *intr;
        cyg_int32 count;
        CYG_INTERRUPT_STATE old_intr;

        HAL_DISABLE_INTERRUPTS(old_intr);
        
        intr = dsr_list;
        dsr_list = intr->next_dsr;
        count = intr->dsr_count;
        intr->dsr_count = 0;
        
        HAL_RESTORE_INTERRUPTS(old_intr);

        intr->dsr( intr->vector, count, (CYG_ADDRWORD)intr->data );
    }

    CYG_REPORT_RETURN();
    
}

//--------------------------------------------------------------------------
// This is referenced from the HAL, although it does not actually get called.

externC void
cyg_interrupt_call_pending_DSRs(void)
{
    call_dsrs();
}


//--------------------------------------------------------------------------
// Interrupt end function called from HAL VSR to tidy up. This is where
// DSRs will be called if necessary.

externC void
interrupt_end(
    cyg_uint32          isr_ret,
    cyg_interrupt       *intr,
    HAL_SavedRegisters  *regs
    )
{
    CYG_REPORT_FUNCTION();
    
#ifndef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN

    // Only do this if we are in a non-chained configuration.
    // If we are chained, then chain_isr will do the DSR
    // posting.
    
    if( isr_ret & CYG_ISR_CALL_DSR && intr != NULL ) post_dsr(intr);

#endif

    if( dsr_disable_counter == 0 ) call_dsrs();

    CYG_REPORT_RETURN();    
}

//--------------------------------------------------------------------------
// ISR for handling chained interrupts.

#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN

cyg_uint32 chain_isr(cyg_vector_t vector, CYG_ADDRWORD data)
{
    cyg_interrupt *p = *(cyg_interrupt **)data;
    register cyg_uint32 isr_ret = 0;
    register cyg_uint32 isr_chain_ret = 0;

    CYG_REPORT_FUNCTION();

    while( p != NULL )
    {
        if( p->vector == vector )
        {
            isr_ret = p->isr(vector, p->data);

            isr_chain_ret |= isr_ret;

            if( isr_ret & CYG_ISR_CALL_DSR ) post_dsr(p);

            if( isr_ret & CYG_ISR_HANDLED ) break;
        }

        p = p->next;
    }

#ifdef HAL_DEFAULT_ISR
    if( (isr_chain_ret & (CYG_ISR_CALL_DSR|CYG_ISR_HANDLED)) == 0 )
    {
        // If we finished the loop for some reason other than that an
        // ISR has handled the interrupt, call any default ISR to either
        // report the spurious interrupt, or do some other HAL level processing
        // such as GDB interrupt detection etc.

        HAL_DEFAULT_ISR( vector, 0 );
    }
#endif    

    CYG_REPORT_RETURN();
    
    return isr_ret & CYG_ISR_CALL_DSR;
}

#endif

//--------------------------------------------------------------------------
// ISR lock. This disables interrupts and keeps a count of the number
// times it has been called.

externC void cyg_drv_isr_lock()
{
    CYG_INTERRUPT_STATE dummy;

    CYG_REPORT_FUNCTION();

    HAL_DISABLE_INTERRUPTS(dummy);

    CYG_ASSERT( isr_disable_counter >= 0 , "Disable counter negative");
    
    isr_disable_counter++;
    
    CYG_REPORT_RETURN();    
}

//--------------------------------------------------------------------------
// Unlock ISRs. This decrements the count and re-enables interrupts if it
// goes zero.

externC void cyg_drv_isr_unlock()
{
    CYG_REPORT_FUNCTION();
        
    CYG_ASSERT( isr_disable_counter > 0 , "Disable counter not greater than zero");
    
    isr_disable_counter--;

    if ( isr_disable_counter == 0 )
    {
        HAL_ENABLE_INTERRUPTS();
    }

    CYG_REPORT_RETURN();
}

//--------------------------------------------------------------------------
// Lock DSR lock. Simply increment the counter.

externC void cyg_drv_dsr_lock()
{
    CYG_REPORT_FUNCTION();

    dsr_disable_counter++;

    CYG_REPORT_RETURN();
}

//--------------------------------------------------------------------------
// Unlock DSR lock. If the counter is about to go zero, call any pending
// DSRs and then zero the counter.

externC void cyg_drv_dsr_unlock()
{
    CYG_REPORT_FUNCTION();

    do
    {
        if( dsr_disable_counter == 1 )
        {
            call_dsrs();
        }

        HAL_REORDER_BARRIER();
        
        dsr_disable_counter = 0;

        HAL_REORDER_BARRIER();

        // Check that no DSRs have been posted between calling
        // call_dsrs() and zeroing dsr_disable_counter. If so,
        // loop back and call them.
        
        if( dsr_list != NULL )
        {
            dsr_disable_counter = 1;
            continue;
        }

        CYG_REPORT_RETURN();
        
        return;
        
    } while(1);

    CYG_FAIL( "Should not be executed" );
}

//--------------------------------------------------------------------------
// Initialize a mutex.

externC void cyg_drv_mutex_init( cyg_drv_mutex_t *mutex )
{
    CYG_REPORT_FUNCTION();
    
    mutex->lock = 0;

    CYG_REPORT_RETURN();    
}

//--------------------------------------------------------------------------
// Destroy a mutex.

externC void cyg_drv_mutex_destroy( cyg_drv_mutex_t *mutex )
{
    CYG_REPORT_FUNCTION();
    
    mutex->lock = -1;

    CYG_REPORT_RETURN();    
}

//--------------------------------------------------------------------------
// Lock a mutex. We check that we are not trying to lock a locked or
// destroyed mutex and if not, set it locked.

externC cyg_bool_t cyg_drv_mutex_lock( cyg_drv_mutex_t *mutex )
{
    CYG_REPORT_FUNCTION();
    
    CYG_ASSERT( mutex->lock == 0 , "Trying to lock locked mutex");

    mutex->lock = 1;

    CYG_REPORT_RETURN();

    return true;
}

//--------------------------------------------------------------------------
// Attempt to claim a mutex, and return if it cannot be.

externC cyg_bool_t cyg_drv_mutex_trylock( cyg_drv_mutex_t *mutex )
{
    cyg_bool_t result = true;
    
    CYG_REPORT_FUNCTION();

    if( mutex->lock == 1 ) result = false;
    
    CYG_REPORT_RETURN();

    return result;
}

//--------------------------------------------------------------------------
// Unlock a mutex. We check that the mutex is actually locked before doing
// this.

externC void cyg_drv_mutex_unlock( cyg_drv_mutex_t *mutex )
{
    CYG_REPORT_FUNCTION();

    CYG_ASSERT( mutex->lock == 1 , "Trying to unlock unlocked mutex");

    mutex->lock = 0;
    
    CYG_REPORT_RETURN();    

⌨️ 快捷键说明

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