📄 mcf5xxx_timer.c
字号:
/*
* File: mcf5xxx_timer.c
* Purpose: routines for accessing integrated timer modules
*
* Notes: Provides an interface to the DMA timer module common
* to many ColdFire processors
*
* Modifications:
*
*/
#include "src/include/dbug.h"
#include "src/cpu/coldfire/mcf5xxx/mcf5xxx_timer.h"
/********************************************************************/
static MCF5XXX_TIMER timer[TIMER_NUM_CH];
/********************************************************************/
uint32
timer_default_isr(void *not_used, MCF5XXX_TIMER *t)
{
(void) not_used;
/* Clear the pending event */
MCF_TIMER_DTER(t->channel) = (0
| MCF_TIMER_DTER_REF
| MCF_TIMER_DTER_CAP);
t->timeouts++;
if (t->reference)
if (--t->reference == 0)
timer_stop(t->channel);
return TRUE;
}
/********************************************************************/
uint32
timer_read(uint8 channel)
{
uint32 now;
now = MCF_TIMER_DTCN(channel);
timer[channel].then = timer[channel].now;
timer[channel].now = now;
return now;
}
/********************************************************************/
void
timer_start(uint8 channel)
{
/* Reset Timer module */
MCF_TIMER_DTMR(channel) = 0;
/* Clear any pending Timer events */
MCF_TIMER_DTER(channel) = (0
| MCF_TIMER_DTER_REF
| MCF_TIMER_DTER_CAP);
#if (defined(CPU_MCF5282) || \
defined(CPU_MCF5275) || \
defined(CPU_MCF523X) || \
defined(CPU_MCF5271))
/* Set Timer Interrupt Control Register */
MCF_INTC0_ICRn(19 + channel) = (uint8)(MCF_INTC0_ICRn_IL(timer[channel].level));
/* Clear the appriopriate Interrupt Mask bit */
MCF_INTC0_IMRL &= ~((MCF_INTC0_IMRL_INT_MASK19 << channel) |
MCF_INTC0_IMRL_MASKALL);
#elif (defined(CPU_MCF5208))
/* Set Timer Interrupt Control Register */
MCF_INTC_ICR(32 + channel) = (uint8)(MCF_INTC_ICR_IL(timer[channel].level));
/* Clear the appriopriate Interrupt Mask bit */
MCF_INTC_IMRH &= ~(MCF_INTC_IMRH_INT_MASK32 << channel);
#elif (defined(CPU_MCF532X))
/* Set Timer Interrupt Control Register */
MCF_INTC0_ICR(32 + channel) = (uint8)(MCF_INTC_ICR_IL(timer[channel].level));
/* Clear the appriopriate Interrupt Mask bit */
MCF_INTC0_IMRH &= ~(MCF_INTC_IMRH_INT_MASK32 << channel);
#elif (defined(CPU_MCF5272))
MCF_INTC_ICR1 = (0 |
MCF_INTC_ICR1_TMR_IPL(timer[channel].level, channel) |
MCF_INTC_ICR1_TMR_IP(channel));
#elif (defined(CPU_MCF5307) || \
defined(CPU_MCF5407) || \
defined(CPU_MCF5249))
/* Clear the appriopriate Interrupt Mask bit */
MCF_SIM_IMR &= ~(MCF_SIM_IMR_TIMER0 << channel);
/* Set Timer Interrupt Control Register */
MCF_SIM_ICR(channel - 1) = (0 |
MCF_SIM_ICR_AVEC |
MCF_SIM_ICR_IL(timer[channel].level - 24)));
#else
#error "Unsuppoted ColdFire in timer.c"
#endif
/* Reset the counter */
MCF_TIMER_DTCN(channel) = 0;
/* Write the TRR register */
MCF_TIMER_DTRR(channel) = timer[channel].trr;
/* Write the TMR register and start the free-running timer */
MCF_TIMER_DTMR(channel) = timer[channel].tmr;
#if defined(DEBUG_PRINT)
printf("DTMR = %08x\n", MCF_TIMER_DTMR(channel) );
printf("IMRH = %08x\n", MCF_INTC0_IMRH );
printf("ICR32 = %08x\n", MCF_INTC0_ICR32 );
printf("ICR(32) = %08x\n", MCF_INTC0_ICR(32) );
#endif
}
/********************************************************************/
void
timer_stop(uint8 channel)
{
/* Get the latest time */
timer_read(channel);
/* Disable timer (reset) */
MCF_TIMER_DTMR(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(uint8 channel, float period, float sysclock, uint32 level,
void (*isr)(void*, void*))
{
/*
* This routine should only be called by the project (board) specific
* initialization code.
*/
uint16 prescale;
if ((channel > 3) || (level < 1) || (level > 7))
return FALSE;
/* If no period, disable timer */
if (!period)
{
if (timer[channel].isr != NULL)
{
isr_remove_handler(ISR_DBUG_ISR,(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(ISR_DBUG_ISR, (void *)timer[channel].isr);
timer[channel].isr = NULL;
}
if (isr == NULL)
{
isr = (void *)timer_default_isr;
}
#if (defined(CPU_MCF5307) || defined(CPU_MCF5407) || defined(CPU_MCF5249))
if (!isr_register_handler(ISR_DBUG_ISR, level, (void *)isr,
NULL, (void *)&timer[channel]))
{
timer[channel].isr = NULL;
return FALSE;
}
#else
if (!isr_register_handler(ISR_DBUG_ISR, TIMER_VECTOR(channel), (void *)isr,
NULL, (void *)&timer[channel]))
{
timer[channel].isr = NULL;
return FALSE;
}
#endif
/* Set the Reference Reached value to the maximum value */
timer[channel].trr = 0xFFFF;
/* Calculate TMR value */
timer[channel].tmr = (MCF_TIMER_DTMR_ORRI
| MCF_TIMER_DTMR_CE_NONE
| MCF_TIMER_DTMR_OM
| MCF_TIMER_DTMR_FRR
| MCF_TIMER_DTMR_RST);
if (period < (1000/sysclock))
{
period = 1000/sysclock;
timer[channel].tmr |= (MCF_TIMER_DTMR_CLK_DIV1
| MCF_TIMER_DTMR_PS(0));
}
else if (period > (1000 * 256 * 16)/sysclock)
{
period = (1000 * 256 * 16)/sysclock;
timer[channel].tmr |= (MCF_TIMER_DTMR_CLK_DIV16
| MCF_TIMER_DTMR_PS(256));
}
else if (period <= (1000 * 256)/sysclock)
{
prescale = (uint16)((period * sysclock)/1000);
timer[channel].tmr |= (MCF_TIMER_DTMR_CLK_DIV1
| MCF_TIMER_DTMR_PS(prescale));
}
else /* period <= (1000 * 256 * 16)/sysclock */
{
prescale = (uint16)((period * sysclock)/(1000 * 16));
timer[channel].tmr |= (MCF_TIMER_DTMR_CLK_DIV16
| MCF_TIMER_DTMR_PS(prescale));
}
/* Save the Timer settings */
timer[channel].period = period;
timer[channel].isr = isr;
timer[channel].channel = channel;
timer[channel].level = level;
return TRUE;
}
/********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -