📄 timerdrv.c
字号:
/*******************************************************************************
*
* Motorola Inc.
* (c) Copyright 2002 Motorola, Inc.
* ALL RIGHTS RESERVED.
*
* $Element: /project/dsp568_sdk/sdk/src/dsp56838evm/nos/bsp/timerdrv.c $
* $Author: saa $
* $Revision: /main/2 $
* $VOB: /project/dsp568_sdk $
* $OS: solaris $
*
* Description: source file for the 56838 posix timer driver
*
* Notes:
*
******************************************************************************/
#include "port.h"
#include "bsp.h"
#include "arch.h"
#include "timerdrv.h"
#include "timer.h"
static unsigned long TimerISRCount; /* system timer counter */
/* Local prototypes */
static void timerRealTimeClockISR(union sigval Params);
/* QT ISR prototypes */
extern posix_tContext posix_ctx_A_0;
extern posix_tContext posix_ctx_A_1;
extern posix_tContext posix_ctx_A_2;
extern posix_tContext posix_ctx_A_3;
extern posix_tContext posix_ctx_B_0;
extern posix_tContext posix_ctx_B_1;
extern posix_tContext posix_ctx_B_2;
extern posix_tContext posix_ctx_B_3;
extern posix_tContext posix_ctx_C_0;
extern posix_tContext posix_ctx_C_1;
extern posix_tContext posix_ctx_C_2;
extern posix_tContext posix_ctx_C_3;
extern posix_tContext posix_ctx_D_0;
extern posix_tContext posix_ctx_D_1;
extern posix_tContext posix_ctx_D_2;
extern posix_tContext posix_ctx_D_3;
/*** Quadrature timer Normal ISR template ***/
#if 0
#define INSTQTISR( isr, base, device ) \
void isr(void) \
{ \
extern const union sigval sig; \
if( --(device.SoftCounter) == 0 ) \
{ \
device.SoftCounter = device.reloadSoftCounter; \
if(device.pUserFunc != 0 ) \
device.pUserFunc( sig ); \
} \
if( (device.reloadSoftCounter == 0) && (device.SoftCounter < 2)) \
periphBitSet(QTB_ONCE,(volatile unsigned short*)(base)); \
}
#else
#define POUND #
#define INSTQTISR( isr, base, device ) \
void isr(void) \
{ \
asm( adda #0x0000002 , SP ); \
asm( move.l A10 , X:(SP)+ ); \
asm( move.l R2 , X:(SP) ); \
asm( move.w device + SoftCounter_offset , A ); \
asm( dec.w A ); \
asm( bne nextsoftstep ); \
asm( tst.w device + pUserFunc_offset ); \
asm( beq nextsoftstep ); \
asm( move.l device + pUserFunc_offset , R2 ); \
asm( adda #2 , SP ); \
asm( move.w #0 , X:(SP) ); \
asm( jsr (R2) ); \
asm( suba #2 , SP ); \
asm( move.w device + reloadSoftCounter_offset , A1 ); \
asm( nextsoftstep: ); \
asm( move.w A1 , device + SoftCounter_offset ); \
asm( tst.w device + reloadSoftCounter_offset ); \
asm( bne endstep ); \
asm( move.w device + SoftCounter_offset , A1 ); \
asm( cmp.w #1 , A ); \
asm( bne endstep ); \
asm( move.l POUND base , R2 ); \
asm( move.w X:(R2-0x1000) , A1 ); \
asm( bfset 0x0040 , A ); \
asm( move.w A1 , X:( R2 - 0x1000 ) ); \
asm( endstep: ); \
asm( move.l X:(SP)- , R2 ); \
asm( move.l X:(SP)- , A ); \
}
#endif
/* Quadrature timer isr service routines */
INSTQTISR( POSIXtimerISRA0, archoff_TimerA0_ControlReg, posix_ctx_A_0 )
INSTQTISR( POSIXtimerISRA1, archoff_TimerA1_ControlReg, posix_ctx_A_1 )
INSTQTISR( POSIXtimerISRA2, archoff_TimerA2_ControlReg, posix_ctx_A_2 )
INSTQTISR( POSIXtimerISRA3, archoff_TimerA3_ControlReg, posix_ctx_A_3 )
#if !defined(DSP56838EVM)
INSTQTISR( POSIXtimerISRB0, archoff_TimerB0_ControlReg, posix_ctx_B_0 )
INSTQTISR( POSIXtimerISRB1, archoff_TimerB1_ControlReg, posix_ctx_B_1 )
INSTQTISR( POSIXtimerISRB2, archoff_TimerB2_ControlReg, posix_ctx_B_2 )
INSTQTISR( POSIXtimerISRB3, archoff_TimerB3_ControlReg, posix_ctx_B_3 )
#endif /* !defined(DSP56838EVM) */
INSTQTISR( POSIXtimerISRC0, archoff_TimerC0_ControlReg, posix_ctx_C_0 )
INSTQTISR( POSIXtimerISRC1, archoff_TimerC1_ControlReg, posix_ctx_C_1 )
INSTQTISR( POSIXtimerISRC2, archoff_TimerC2_ControlReg, posix_ctx_C_2 )
INSTQTISR( POSIXtimerISRC3, archoff_TimerC3_ControlReg, posix_ctx_C_3 )
INSTQTISR( POSIXtimerISRD0, archoff_TimerD0_ControlReg, posix_ctx_D_0 )
INSTQTISR( POSIXtimerISRD1, archoff_TimerD1_ControlReg, posix_ctx_D_1 )
INSTQTISR( POSIXtimerISRD2, archoff_TimerD2_ControlReg, posix_ctx_D_2 )
INSTQTISR( POSIXtimerISRD3, archoff_TimerD3_ControlReg, posix_ctx_D_3 )
#define POSIX_TIMER_READ_PRESCALER_VALUE( bspDevice, Dummy ) \
( 1<< (timerStdFastStart.bits.InputSource & 0xFFF8 ) )
#define POSIX_TIMER_GET_CONTEXT(TimerID) \
((posix_tContext*)timer_qt_readCompareReg1( (arch_sTimerChannel*) TimerID ) )
extern const qt_sQuadState timerStdFastStart;
/*****************************************************************************
*
* Module: U64addU32
*
* Description: addition unsigned 64 and unsigned 32 bits numbers
*
* Returns: none
*
* Arguments: pFirst - pointer to unsigned U64 value
* second - 32 bits unsigned number
* pRezult - not null pointer to U64 value
*
* Range Issues:
*
* Special Issues:
* Register discription:
* R2 - pointer to U64 value
* A - 32 bits number
* R3 - not null pointer to U64 value
*
* Module doesn't save register: B
*
* if overflow occurs then carry bit will be set
*
* Test Method:
*
*****************************************************************************/
static void U64addU32(const U64 * pFirst, const unsigned long second, U64 * pResult)
{
asm(adda #1, SP );
asm(move.w A0, X:(SP)+ );
asm(move.w A1, X:(SP)+ );
asm(move.w B0, X:(SP)+ );
asm(move.w B1, X:(SP) );
asm(move.l X:(R2), B ); /* Prepare data for addition least 32-bits */
asm(add A, B ); /* Add least 32-bits */
asm(move.l B10, X:(R3) ); /* Save least 32-bits */
asm(move.l X:(R2+2), B ); /* copy high 32-bits to result */
asm(move.l #0, Y );
asm(adc Y, B );
asm(move.l B10, X:(R3+2)); /* Save least 32-bits */
asm(move.w X:(SP)-, B1 );
asm(move.w X:(SP)-, B0 );
asm(move.w X:(SP)-, A1 );
asm(move.w X:(SP)-, A0 );
asm(rts );
}
/*****************************************************************************
*
* Module: U64mulU32
*
* Description: multiplication unsigned 64 and unsigned 32 bits multiplier
*
* Returns: none
*
* Arguments: pFirst - pointer to U64 value
* second - 32 bits multiplier
* pRezult - not null pointer to U64 value
*
* Range Issues:
*
* Special Issues:
* Register discription:
* R2 - pointer to U64 value
* A - 32 bits number
* R3 - not null pointer to U64 value
*
* Module doesn't save registers: B, Y
*
* Return: return higest bits of results (64..96 bits) in register A
*
* Test Method:
*
*****************************************************************************/
static unsigned long U64mulU32(const U64 * pFirst, const unsigned long second, U64* pRezult)
{
asm(adda #1, SP );
asm(move.w B0, X:(SP)+ );
asm(move.w B1, X:(SP)+ );
asm(move.w Y0, X:(SP)+ );
asm(move.w Y1, X:(SP) );
asm(move.l #0, Y ); /* prepare register to use as carry number */
asm(do #4, ENDDO ); /* multiply step by step evry 16-bits of U64 */
asm(move.w X:(R2), B0 ); /* take current 16-bits of U64 (start from least) */
asm(impyuu A0, B0, B ); /* multiply least part of multiplier */
asm(add Y, B ); /* add carry number */
asm(move.w B0, Y0 ); /* save 16 bits of resuls */
asm(move.w X:(R2)+, B0 ); /* take next 16-bits of U64 */
asm(move.w Y0, X:(R3)+ ); /* save our current result to memory ( it's use to realise such possibility U64mul32(&a, b, &a)) */
asm(impyuu A1, B0, Y ); /* multiply high part of multiplier */
asm(move.w B1, B0 ); /* sum up carry number */
asm(clr.w B1 );
asm(add B, Y );
asm(ENDDO: );
asm(move.w Y0, A0 ); /* if overflow occures, the higest bits will be in register A (return value) */
asm(move.w Y1, A1 );
asm(adda #-4, R2 );
asm(adda #-4, R3 );
asm(move.w X:(SP)-, Y1 );
asm(move.w X:(SP)-, Y0 );
asm(move.w X:(SP)-, B1 );
asm(move.w X:(SP)-, B0 );
asm(rts );
};
/*****************************************************************************
*
* Module: incU64
*
* Description: increase U64
*
* Returns: carry bit set if pU64 == 0xFFFF FFFF FFFF FFFF
*
* Arguments: pU64 - not null pointer to 64 bits dividend
*
*
* Range Issues:
*
* Special Issues: For executive loop only. Module doesn't save register: A
*
* Test Method:
*
*****************************************************************************/
static void incU64(U64 * pU64)
{
asm(adda #1, SP );
asm(move.w A0, X:(SP)+ );
asm(move.w A1, X:(SP) );
asm(move.l X:(R2), A ); /* movel low bits to A */
asm(inc.l A ); /* increase A */
asm(move.l A10, X:(R2) ); /* save result */
asm(move.l X:(R2+2), A ); /* movel high bits to A */
asm(brclr #1, SR, CarryBitClear ); /* test carry bit ; carry bit set if overflow occurs*/
asm(inc.l A ); /* inc hifh bits if overflow occurs */
asm(CarryBitClear: );
asm(move.l A10, X:(R2+2) ); /* save high bits */
asm(move.w X:(SP)-, A1 );
asm(move.w X:(SP)-, A0 );
asm(rts );
}
/*****************************************************************************
*
* Module: U32divU16s
*
* Description: division unsigned 32 bits value by unsigned 16 bits value divider
*
* Returns: quotient
*
* Arguments: Dividend - not null pointer to 32 bits dividend
* Divisor - 16 bits unsigned divider
*
* Range Issues:
*
* Special Issues: For executive loop only. Module doesn't save registers: A, B, Y, X0
*
* Test Method:
*
*****************************************************************************/
static unsigned short U32divU16s(const unsigned long Dividend, const unsigned short Divisor, unsigned long * Result)
{
asm( move.w Y0, Y1 ); /* save real divider */
asm( brclr #$8000, Y0, Core ); /* if (sign bit is not set) then go core */
asm( lsr.w Y1 ); /* new divider:=divider>>1 */
/* division */
asm(Core: ); /* main part of division */
asm( clr B ); /* preparing for division */
asm( move.w A1, B0 ); /* move high number position in register B */
asm( bfclr #$0001, SR ); /* clear carry flag ( for first shifting )) */
asm( rep #17 ); /* 16-bit for division + 1-bit for sign */
asm( div Y1, B ); /* Positive quotient in B0 */
asm( move.w B0, A1 ); /* Save quotient in A1 */
asm( add Y1, B ); /* Restore remainder in B1 */
asm( asr B ); /* Required for correct integer remainder */
asm( move.w A0, B0 ); /* move low number position in register B */
asm( bfclr #$0001, SR ); /* clear carry flag ( for first shifting )) */
asm( rep #17 ); /* 16-bit for division + 1-bit for sign */
asm( div Y1, B ); /* Positive quotient in B0 */
asm( move.w B0, A0 ); /* Save quotient in A0 */
asm( add Y1, B ); /* Restore remainder in B1 */
asm( asr B ); /* Required for correct integer remainder */
/* correct the result if divisor is odd number */
asm( bfclr #$FF, A2 );
asm( bfclr #$FF, B2 );
asm( brclr #$8000, Y0, Endofdiv); /* if sign bit not set go Endofdiv */
asm( brclr #$0001, A0, EvenA ); /* if quotient(A/[Y>>1]) is even go OddA */
asm( add Y1, B ); /* odd quotient. remainder( A / Y ) = remainder( A / [Y>>1] ) + Y >> 1 */
asm(EvenA: );
asm( asr A ); /* quotient(A\[Y>>1])>>=1 */
asm( brclr #$0001, Y0, Endofdiv); /* if divider is even go Endofdiv */
asm( move.w B1, B0 ); /* for addition operation */
asm( clr.w B1 );
asm( clr.w X0 );
asm( clr.w Y1 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -