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

📄 am186tmr.c

📁 Real-Time Kernel
💻 C
字号:
/*
//	Paradigm C++ Real Time Kernel - AMD Am186 Timer Interrupt Support
//	Copyright 1999, 2002 Paradigm Systems.  All rights reserved.
//
//	Description
//	===========
//	This file implements a timer device driver for the Am186 family of
// microcontrollers.
*/

#include <stddef.h>
#include <embedded.h>

#include <rtkernel.h>
#include <finetime.h>
#include <rttimer.h>
#include <udtimer.h>

#define IOB186EM	0xff00
#include <am186em.h>


#define ASM __asm

/*
// 40MHz processor clock, 10MHz timer input clock (1/4 clock frequency)
// FineTime period is 100ns, 2^32 FineTimes is 429.496 seconds
// FineTime = ( Seconds * 430 ) / 2^32
//
// FineTime to Time conversions
// ============================
// Seconds.Factor         = Seconds / FineTime          = 430      << 32
// Milliseconds.Factor    = 1000 * Seconds.Factor       = 26875    << 28
// Microseconds.Factor    = 1000 * Milliseconds.Factor  = 3355443  << 25
//
// Time to FineTime conversions
// ============================
// Seconds.RevFactor      = 1.0 / Seconds.Factor        = 10000000 << 0
// Milliseconds.RevFactor = 1.0 / Milliseconds.Factor   = 10000    << 0
// Microseconds.RevFactor = 1.0 / Microseconds.Factor   = 10       << 0
*/

struct TimeConverter _UDTimerFineTimeConverter = {
   /*   Factor,   RevFactor, Shift, RevShift */
	{      430L,   10000000L,   -32,        0 },  /* Seconds      */
	{    26875L,      10000L,   -28,        0 },  /* Milliseconds */
	{  3355443L,         10L,   -25,        0 }   /* Microseconds */
} ;


static void (*UDTimerUserHandler)(void) ;
static uint16 UDTimerTimerReload ;
static uint32 UDTimerCurrentTime ;


/*-----------------------------------*/
uint32 _UDTimerSetTimerInterval( uint32 Units )
{
	UDTimerTimerReload = (uint16) ( ( Units >= 0x10000L ) ? 0 : Units ) ;
	outport( TMR1_COUNT, UDTimerTimerReload ) ;
	return ( UDTimerTimerReload == 0 ) ? 0x10000L : UDTimerTimerReload ;
}


/*-----------------------------------*/
void _UDTimerReadFineTime( FineTime* T )
{
	_pushf() ;
	_disable() ;

	ASM mov   di, word ptr UDTimerCurrentTime
	ASM mov   si, word ptr UDTimerCurrentTime + 2
	_BX = inport( TMR1_COUNT ) ;

	_AX = inport( TMR1_CON ) ;
	ASM and   ax, 02000h
	ASM mov   ax, bx
	ASM jz    NoIR
	ASM add   di, 1
	ASM adc   si, 0
	_AX = inport( TMR1_COUNT ) ;

NoIR:
	_popf() ;
	ASM mov   cx, UDTimerTimerReload
	ASM or    cx, cx
	ASM jz    Mult10000
/*MultTimerReload:*/
	ASM sub   cx, ax
	ASM mov   ax, UDTimerTimerReload
	ASM mul   si
	ASM mov   bx, dx
	ASM push  ax
	ASM mov   ax, UDTimerTimerReload
	ASM mul   di
	ASM add   ax, cx
	ASM pop   cx
	ASM adc   dx, cx
	ASM adc   bx, 0

	T->W[0] = _AX ;
	T->W[1] = _DX ;
	T->W[2] = _BX ;
	return ;

Mult10000:
	T->W[0] = _AX ;
	T->W[1] = _DI ;
	T->W[2] = _SI ;
}


/*-----------------------------------*/
void _UDTimerFTimeSinceTInt( FineTime* T )
{
	T->W[0] = inport( TMR1_COUNT ) ;
	T->W[1] = 0 ;
	T->W[2] = 0 ;
}



/*-----------------------------------*/
static void UDTimerInterrupt(void)
{
#ifdef __PDREMOTE__
	// Stop the timer for debugging
	outport( TMR1_CON, ( ( inport( TMR1_CON ) | TCU_INH ) & ~TCU_EN ) ) ;
#endif

	// Bump the interrupt tick count
	UDTimerCurrentTime++ ;

	// Send the timer EOI command
	outport( INT_EOI, 8 ) ;

	// Call any user-defined code hooked in
	if ( UDTimerUserHandler )   {
		(*UDTimerUserHandler)() ;
	}

#ifdef __PDREMOTE__
	// Start the timer for debugging
	outport( TMR1_CON,( inport( TMR1_CON ) | TCU_INH | TCU_EN ) ) ;
#endif
}


/*-----------------------------------*/
void _UDTimerSetTimerHandler( void (*userHandler)() )
{
	UDTimerUserHandler = userHandler ;
}


/*-----------------------------------*/
void _UDTimerInit(void)
{
	// Only do this once
	static int timerInitialized ;
	if ( !timerInitialized )   {
		// Disable interrupts during hardware initialization
		disable() ;

		// Install the user-defined timer interrupt handler
		RTKSetIRQHandler( TMR1_VEC, UDTimerInterrupt, 256 ) ;

		// Initialize the timer hardware
		outport( TMR1_CON, TCU_EN | TCU_INH | TCU_INT | TCU_CONT ) ;
		outport( TMR1_COUNT, 0x0000 ) ;
		outport( TMR1_CMPA, 0xffff ) ;

		// Unmask the timer interrupt
		outport( TMRINT_CON, 0x0000 ) ;

		// All done, reenable interrupts
		timerInitialized = 1 ;
		enable() ;
	}
}

⌨️ 快捷键说明

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