📄 drv_api.c
字号:
//==========================================================================
//
// 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 + -