📄 drv_api.c
字号:
//==========================================================================//// drv_api.c//// Driver API for non-kernel configurations////==========================================================================//####COPYRIGHTBEGIN####//// -------------------------------------------// The contents of this file are subject to the Cygnus eCos Public License// Version 1.0 (the "License"); you may not use this file except in// compliance with the License. You may obtain a copy of the License at// http://sourceware.cygnus.com/ecos// // 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 Cygnus Operating System, released// September 30, 1998.// // The Initial Developer of the Original Code is Cygnus. Portions created// by Cygnus are Copyright (C) 1998, 1999 Cygnus Solutions. // 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>//--------------------------------------------------------------------------// Staticsstatic volatile cyg_int32 isr_disable_counter; // ISR disable countervolatile cyg_int32 dsr_disable_counter asm("cyg_scheduler_sched_lock"); // DSR disable counterstatic volatile cyg_interrupt *dsr_list; // List of pending DSRs#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAINcyg_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 ) { volatile 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(); }//--------------------------------------------------------------------------// Interrupt end function called from HAL VSR to tidy up. This is where// DSRs will be called if necessary.externC voidinterrupt_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_CHAINcyg_uint32 chain_isr(cyg_vector_t vector, CYG_ADDRWORD data){ CYG_REPORT_FUNCTION(); cyg_interrupt *p = *(cyg_interrupt **)data; while( p != NULL ) { if( p->vector == vector ) { register cyg_uint32 isr_ret = p->isr(vector, p->data); if( isr_ret & CYG_ISR_CALL_DSR ) post_dsr(p); if( isr_ret & CYG_ISR_HANDLED ) break; } p = p->next; } CYG_REPORT_RETURN(); return 0;}#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(); } //--------------------------------------------------------------------------// Release all threads waiting for the mutex.// This is really for threads, so we do nothing here.externC void cyg_drv_mutex_release( cyg_drv_mutex_t *mutex ){ CYG_REPORT_FUNCTION();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -