📄 am186tmr.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 + -