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

📄 timerdrv.c

📁 56f8300E系列dsp的BOOTloader
💻 C
📖 第 1 页 / 共 4 页
字号:
    /*			while(remainder<0) do { remainder += divider; quotient += 1 } 			*/
    asm(Circle:             			);

    asm(	cmp     A, B            	);  /* no more than 4 times 					*/
    asm(	bge     GetK        		);
    asm(	add     Y, B            	);  /* Y = divider 								*/
    asm(	inc.w   X0          		);
    asm(	bra     Circle      		);

    asm(GetK:               			);

    asm(	sub     A, B            	);  /* the same: remainder += divider * k, k = {0, 1, 2, 3, 4} */
    asm(	move.w  B0, B1      		);  /* calling convention 						*/
    asm(	move.w  Y0, B0      		);
    asm(	move.w  X0, Y0      		);
    asm(	bfclr   #$0001, SR  		);
    asm(	sbc     Y, A            	);
    asm(	move.w  B0, Y0      		);

    asm(Endofdiv:           			); /* end of division 							*/

    asm(	move.l  A10, X:(R2)  		); /* save results of division 					*/
    asm(	move.w  B1, Y0      		);
    asm(	rts                 		);
}

/*****************************************************************************
*
* Module: U64divU16
*
* Description: division unsigned 64 bits value by unsigned 16 bits value divider
*
* Returns: remainder
*
* Arguments: puDividend - not null pointer to 64 bits dividend
*            uDivider   - 16 bits unsigned divider
*            puQuotient - not null pointer to 64 bits quotient
*
* Range Issues: 
*
* Special Issues:  For executive loop only. Module doesn't save registers: A, B, Y, X0, C1, D1
*                                           Use SP
* Test Method: 
*
*****************************************************************************/
static unsigned short U64divU16(const U64 * puDividend, const unsigned short uDivider, U64 * puQuotient)
{       
    asm(adda    #1, SP      		);
    asm(move.w  Y1, X:(SP)+ 		);
    asm(move.w  B0, X:(SP)+ 		);
    asm(move.w  B1, X:(SP)+ 		);
    asm(move.w  A0, X:(SP)+ 		);
    asm(move.w  A1, X:(SP)+ 		);
    asm(move.w  D1, X:(SP)+ 		);
    asm(move.w  C1, X:(SP)+ 		);
                                                                        
    asm(move.l  X:(R2), B   		);  /* save X:(R2), X:(R2+1) to X:(SP) 				*/
    asm(move.w  B0, X:(SP)+ 		);
    asm(move.w  B1, X:(SP)  		);          
    asm(move.w  Y0, C1      		);  /* save divider (Y0) to C1 						*/

    asm(move.l  X:(R2+2), A 		);	/* move 2 high number positions in register A 	*/    
    asm(jsr     U32divU16s  		);  /* divide high positions 						*/
    asm(move.l  A10, x:(R3+2)		);  /* save high number positions of results 		*/

    asm(move.w  Y0, A1      		);  /* move reminder of first division  			*/
    asm(move.w  X:(SP), A0  		);  /* prepare next 16 bit for division 			*/
    asm(move.w  C1, Y0      		);  /* restore divider 								*/
    asm(jsr     U32divU16s  		);  /* divide middle number position 				*/
    asm(move.w  A0, D1      		);  /* save middle number position of result 		*/
		                                /* not at once to R3 because if user write U64divU16(&a, b, &a) */      
        		                        /* next division destroy this result 			*/
    asm(move.w  Y0, A1      		);  /* move reminder of second division  			*/
    asm(move.w  X:(SP-1), A0		);  /* prepare next 16 bit for division 			*/
    asm(move.w  C1, Y0      		);  /* restore divider 								*/
    asm(jsr     U32divU16s  		);  /* divide low number position 					*/

    asm(move.w  X:(SP)-, B1 		);  /* restore X:(R2), X:(R2+1) 					*/
    asm(move.w  X:(SP)-, B0 		);
    asm(move.l  B10, X:(R2) 		);
    asm(move.w  D1, A1      		);  /* save results of low bits D1A0 -> X:(R3) 		*/
    asm(move.l  A10, x:(R3) 		);


    asm(move.w  X:(SP)-, C1 		);
    asm(move.w  X:(SP)-, D1 		);
    asm(move.w  X:(SP)-, A1 		);
    asm(move.w  X:(SP)-, A0 		);
    asm(move.w  X:(SP)-, B1 		);
    asm(move.w  X:(SP)-, B0 		);
    asm(move.w  X:(SP)-, Y1 		);

    asm(rts                 		);
}

#if 0
/*****************************************************************************
*
* Module: TimerCallback
*
* Description: program counter routine for POSIX timer
*
* Returns: none
*
* Arguments: QT callback type, Timer device
*
* Range Issues: 
*
* Special Issues: to be optimized in asm
*
* Test Method: 
*
*****************************************************************************/
void  TimerCallback( posix_tContext* ptr )
{
    extern const union sigval sig; /* non OS version */

 //   periphBitClear( QTB_TCF, &((arch_sTimerChannel*)ptr->bspDevice)->StatusControlReg );             

    if(  --ptr->SoftCounter == 0 )
    {
        ptr->SoftCounter = ptr->reloadSoftCounter;
        if(ptr->pUserFunc != 0 ) 
            ptr->pUserFunc( sig );
    }
}
#endif
/*****************************************************************************
*
* Module:         timerRealTimeClockISR
*
* Description:   Update CLOCK_REALTIME system timer counter
*    
* Returns: None  
*
* Range Issues:   None
* Special Issues: None
* Test Method:    timers.mcp
*
*****************************************************************************/
#pragma interrupt called
static void timerRealTimeClockISR(union sigval Params) 
{   /* update system counter */
    timerTick();  /* increments TimerISRCount */    
}

/* No operating system (nos) version */

/* Include OS hooks for Timer ticks */

void timerSleep(long Ticks)
{
    unsigned long TargetISRCount = TimerISRCount + Ticks;
    
    while(TimerISRCount < TargetISRCount)
    {
          continue;
    }
}

void timerTick(void)
{
    TimerISRCount++;
}

/*****************************************************************************
*
* Module: timer_create
*
* Description (POSIX) :    
*   The timer_create() function creates a per-process timer using the specified
*   clock, ClockID, as the timing base. The EventParams argument, if non-NULL, 
*   points to a sigevent structure. This structure, allocated by the application, 
*   defines the asynchronous notification that will occur when the timer expires. 
*    
* Returns: 
*   If the call succeeds, timer_create() returns zero and in the 
*   location referenced by TimerID, stores a timer ID of type timer_t used to
*   identify the timer in subsequent timer requests. This timer ID will be 
*   unique within the calling process until the timer is deleted.      
*
* Range Issues:   None
* Special Issues: None
* Test Method:    timers.mcp
*
*****************************************************************************/
int timer_create (  const clockid_t          ClockID, 
                    const struct sigevent *  EventParams, 
                    timer_t *          TimerID)
{
    extern const posix_tConfig posixDeviceMap[];
    posix_tContext* ptr = NULL;
    const posix_tConfig * cfg = &posixDeviceMap[0];

    while(1)
    {
        if(cfg->ctx == 0 )
            return -1; /* last timer */
        if( (unsigned short)cfg->base == ClockID )
            break;
        cfg++;
    }
    
    *TimerID = ClockID;
    ptr = cfg->ctx;
    ptr->pUserFunc = EventParams->sigev_notify_function; /* save user function here */
    timer_qt_writeCompareReg1( (arch_sTimerChannel*)ClockID, (unsigned short)ptr);
    
    return 0;
}

/*****************************************************************************
*
* Module:         timer_delete
*
* Description (POSIX) :    
*   The timer_delete() function deletes the specified timer, timerid, previously
*   created by the timer_create() function. If the timer is armed when 
*   timer_delete() is called, the behaviour will be as if the timer is
*   automatically disarmed before removal. The disposition of pending 
*   signals for the deleted timer is unspecified. 
*    
* Returns: If successful, the function returns a value of zero. Otherwise, 
*       the function returns a value of -1.       
*
* Range Issues:   None
* Special Issues: None
* Test Method:    timers.mcp
*
*****************************************************************************/
int timer_delete(timer_t TimerID)
{
        timer_qt_disable( (arch_sTimerChannel*)TimerID );
}

/*****************************************************************************
*
* Module:         time2Ticks
*
* Description  :    
*   Translate time (ns) to ticks
*    
* Range Issues:   None
* Special Issues: None
* Test Method:    timers.mcp
*
*****************************************************************************/
static void time2Ticks(const struct timespec * pTimeValue, U64 * pTicks)
{
    U64 nsTime;
    
    /*translate into nanoseconds*/
    
    nsTime.w[0] = pTimeValue->tv_sec;
    nsTime.w[1] = 0;
    
    U64mulU32(&nsTime, 1000000000UL, &nsTime);      /* nSec=Sec*10^9    */
    U64addU32(&nsTime, pTimeValue->tv_nsec, &nsTime);
    
    /* translate software counter into ticks        */
    /* tick = nanoSec * qtINPUT_FREQUENCY / 10^9    */

    U64mulU32(&nsTime, IP_BUS_FREQUENCY, &nsTime);  
    
    U64divU16(&nsTime, 1000, &nsTime);
    
    U64divU16(&nsTime, 1000, &nsTime);
    
    U64divU16(&nsTime, 1000, &nsTime);   
    pTicks->w[0] = nsTime.w[0];
    pTicks->w[1] = nsTime.w[1];
}

/*****************************************************************************
*
* Module:         ticks2ns
*
* Description  :    
*   Translate ticks to ns
*    
* Range Issues:   None
* Special Issues: None
* Test Method:    timers.mcp
*
*****************************************************************************/
static void ticks2ns(U64* tickPeriod, U64* timePeriod)
{
    /* translate ticks to ns: ns=10^9 * ticks / FREQ  */
    U64mulU32(tickPeriod, 1000000000, timePeriod);
    U64divU16(timePeriod, IP_BUS_FREQUENCY_1, timePeriod);
    U64divU16(timePeriod, IP_BUS_FREQUENCY_2, timePeriod);
}

/*****************************************************************************
*
* Module:         ns2Time
*
* Description  :    
*   It represents time, which is specified in ns, as <sec, ns>
*    
* Range Issues:   None
* Special Issues: None
* Test Method:    timers.mcp
*
*****************************************************************************/
static void ns2Time(U64* timePeriod, struct timespec * tp)
{
    U64     secCount;
    unsigned long nsCount;
	U64	   	tmp;

    /* timePeriod   = 10^9 * secCount  + nsCount 							*/
    /* 1:timePeriod = 10^3 * secCount1 + nsCount1 							*/
    /* 2:secCount1  = 10^3 * secCount2 + nsCount2 							*/
    /* 3:secCount   = 10^3 * secCount2 + nsCount3 							*/
    /* 4:nsCount    = 10^6 * nsCount3  + nsCount2 * 10^3 + nsCount1 		*/

    nsCount = U64divU16(timePeriod, 1000, &secCount);
	
	tmp.w[0] = U64divU16(&secCount, 1000, &secCount);	
	tmp.w[1] = 0;
	
	U64mulU32(&tmp,1000,&tmp);
		
    nsCount +=tmp.w[0];
    
    tmp.w[0]= U64divU16(&secCount, 1000, &secCount);
   	U64mulU32(&tmp,1000000,&tmp);
   	nsCount +=tmp.w[0];
     
    tp->tv_nsec = nsCount;
    tp->tv_sec  = secCount.w[0];
}

static unsigned short factorization(U64* tickPeriod, unsigned long* SWCounter)
{
	struct  /* representation nuber A as: A = divider * quot + rem, 0 < rem < divider    */
    {
        unsigned long quot;
        unsigned short rem;
    }					 	div1, div2;
    
	U64                  	SW;
    
    const unsigned short           SearchCount = 32;   /* max number of divider to try     */

                            
    unsigned short 		        rem0, rem1, minRem,
                            HWCounter,
                            foundDivider;
                            
    for( HWCounter = 0xFFFF-SearchCount, minRem = 0xFFFF;
	         HWCounter < 0xFFFF && minRem > 500;
    		     ++HWCounter)

    {
        div1.rem = rem0 = U64divU16(tickPeriod, HWCounter, &SW);
        div2.rem = rem1 = HWCounter - rem0;
            
        /* Predcondition: SWCounter.w[1] == 0 */

⌨️ 快捷键说明

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