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

📄 timer.c

📁 Coldfire MCF5282 DBug bootloader
💻 C
字号:
/*
 * File:		timer.c
 * Purpose:		routines for accessing integrated timer modules
 *
 * Notes:
 *
 * Modifications:
 *
 */

#include "src/include/dbug.h"
#include "src/dev/mcf5206/timer.h"

/********************************************************************/

/* The MCF5206 has two general purpose timer modules */
static mcf5206_timer timer[2] = \
	{
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
		{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
	};

const uint8 TIMER_BENCHMARK = 0;
const uint8 TIMER_NETWORK = 1;

/********************************************************************/
uint32
timer_default_isr(MCF5206_IMM *immp, mcf5206_timer *t)
{
	/* Clear the pending event */
	MCF5206_WR_TIMER_TER(immp,t->channel,0
		| MCF5206_TIMER_TER_REF
		| MCF5206_TIMER_TER_CAP);

	t->timeouts++;
	if (t->reference)
		if (--t->reference == 0)
			timer_stop(t->channel);

	return TRUE;
}

/********************************************************************/
uint32
timer_read(uint8 channel)
{
	uint16 now;

	now = MCF5206_RD_TIMER_TCN(timer[channel].immp, channel);
	timer[channel].then = timer[channel].now;
	timer[channel].now = now;
	return now;
}

/********************************************************************/
void
timer_start(uint8 channel)
{
	/* Reset Timer module */
	MCF5206_WR_TIMER_TMR(timer[channel].immp,channel,0);

	/* Clear any pending Timer events */
	MCF5206_WR_TIMER_TER(timer[channel].immp,channel,0
		| MCF5206_TIMER_TER_REF
		| MCF5206_TIMER_TER_CAP);
	
	/* Clear the appriopriate Interrupt Mask bit */
	MCF5206_WR_SIM_IMR(timer[channel].immp,
						(uint16)(MCF5206_RD_SIM_IMR(timer[channel].immp)
						& ~(MCF5206_SIM_IMR_TIMER0 << channel)));
	
	/* Set Timer Interrupt Control Register */
	if (channel == 0)
		MCF5206_WR_SIM_ICR9(timer[channel].immp, (uint8)(0
			| MCF5206_SIM_ICR_AVEC
			| MCF5206_SIM_ICR_IL(timer[channel].vector - 24)));
	else
		MCF5206_WR_SIM_ICR10(timer[channel].immp, (uint8)(0
			| MCF5206_SIM_ICR_AVEC
			| MCF5206_SIM_ICR_IL(timer[channel].vector - 24)));

	/* Reset the counter */
	MCF5206_WR_TIMER_TCN(timer[channel].immp,channel,0);

	/* Write the TRR register */
	MCF5206_WR_TIMER_TRR(timer[channel].immp,channel,timer[channel].trr);

	/* Write the TMR register and start the free-running timer */
	MCF5206_WR_TIMER_TMR(timer[channel].immp,channel,timer[channel].tmr);
}

/********************************************************************/
void
timer_stop(uint8 channel)
{
	/* Get the latest time */
	timer_read(channel);

	/* Disable timer (reset) */
	MCF5206_WR_TIMER_TMR(timer[channel].immp,channel,0);
}

/********************************************************************/
uint32
timer_set_secs(uint8 channel, uint32 secs)
{
	uint32 timeout;

	/* Get the timeout in seconds */
	timeout = (uint32)(((timer[channel].period * 0xFFFF)/1000000000) + 0.5);

	if (timeout == 0)
	{
		timer[channel].reference = 1;
		return FALSE;
	}

	/* Save the reference reached counter value */
	timer[channel].reference = secs/timeout;

	/* Reset the timeout counter */
	timer[channel].timeouts = 0;

	/* Start the timer */
	timer_start(channel);

	return TRUE;
}

/********************************************************************/
uint32
timer_get_reference(uint8 channel)
{	
	return timer[channel].reference;
}

/********************************************************************/
uint32
timer_get_time(uint8 channel)
{
	/* NOT COMPLETE!  FIX */
	return (timer[channel].now - timer[channel].then);
}

/********************************************************************/
uint32
timer_init(MCF5206_IMM *immp, uint8 channel, float period, 
				   float sysclock, uint32 vector, void (*isr)(void*, void*))
{
	/* 
	 * This routine should only be called by the project (board) specific
	 * initialization code.
	 */
	
	uint16 prescale;

	if ((channel > 1) || (vector < 25) || (vector > 31))
		return FALSE;

	timer[channel].immp = immp;
	
	/* If no period, disable timer */
	if (!period)
	{
		if (timer[channel].isr != NULL)
		{
			isr_remove_handler(channel+1,(void *)timer[channel].isr);
			timer[channel].isr = NULL;
		}
		timer[channel].tmr = 0;
		timer[channel].trr = 0;
		return TRUE;
	}

	/* Register the Timer Interrupt Service Routine */
	if (timer[channel].isr != NULL)
	{
		isr_remove_handler(channel+1, (void *)timer[channel].isr);
		timer[channel].isr = NULL;
	}
	if (isr == NULL)
	{
		isr = (void *)timer_default_isr;
	}
	if (!isr_register_handler(ISR_DBUG_ISR,vector,(void *)isr,
								(void *)timer[channel].immp,(void *)&timer[channel]))
	{
		timer[channel].isr = NULL;
		return FALSE;
	}

	/* Set the Reference Reached value to the maximum value */
	timer[channel].trr = 0xFFFF;

	/* Calculate TMR value */
	timer[channel].tmr = (MCF5206_TIMER_TMR_ORI
						| MCF5206_TIMER_TMR_CE_NONE
						| MCF5206_TIMER_TMR_OM
						| MCF5206_TIMER_TMR_FRR
						| MCF5206_TIMER_TMR_RST);

	if (period < (1000/sysclock)) 
	{
		period = 1000/sysclock;
		timer[channel].tmr |= (MCF5206_TIMER_TMR_CLK_MSCLK 
							 | MCF5206_TIMER_TMR_PS(0));
	}
	else if (period > (1000 * 256 * 16)/sysclock)
	{
		period = (1000 * 256 * 16)/sysclock;
		timer[channel].tmr |= (MCF5206_TIMER_TMR_CLK_DIV16 
							 | MCF5206_TIMER_TMR_PS(256));
	}
	else if (period <= (1000 * 256)/sysclock)
	{
		prescale = (uint16)((period * sysclock)/1000);
		timer[channel].tmr |= (MCF5206_TIMER_TMR_CLK_MSCLK 
							 | MCF5206_TIMER_TMR_PS(prescale));
	}
	else /* period <= (1000 * 256 * 16)/sysclock */
	{
		prescale = (uint16)((period * sysclock)/(1000 * 16));
		timer[channel].tmr |= (MCF5206_TIMER_TMR_CLK_DIV16 
							 | MCF5206_TIMER_TMR_PS(prescale));
	}

	/* Save the Timer settings */
	timer[channel].period = period;
	timer[channel].isr = isr;
	timer[channel].channel = channel;
	timer[channel].vector = vector;

	return TRUE;
}

/********************************************************************/

⌨️ 快捷键说明

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