/* * File: net_timer.c * Purpose: Provide a timer use by the BaS network as a timeout * indicator * * Notes: */ #include "net_timer.h" #include "bas_printf.h" #include "MCF5475.h" #include "interrupts.h" //#define DBG_TMR #ifdef DBG_TMR #define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0) #else #define dbg(format, arg...) do { ; } while (0) #endif /* DBG_TMR */ #if defined(MACHINE_FIREBEE) #include "firebee.h" #elif defined(MACHINE_M5484LITE) #include "m5484l.h" #elif defined(MACHINE_M54455) #include "m54455.h" #else #error unknown machine! #endif static NET_TIMER net_timer[4] = { {0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0} }; bool timer_default_isr(void *not_used, NET_TIMER *t) { (void) not_used; /* * Clear the pending event */ MCF_GPT_GMS(t->ch) = 0; dbg("timer isr called for timer channel %d\r\n"); /* * Clear the reference - the desired seconds have expired */ t->reference = 0; return 1; } void timer_irq_enable(uint8_t ch) { /* * Setup the appropriate ICR */ MCF_INTC_ICR(TIMER_VECTOR(ch) - 64) = MCF_INTC_ICR_IP(net_timer[ch].pri) | MCF_INTC_ICR_IL(net_timer[ch].lvl); /* * Unmask the FEC interrupt in the interrupt controller */ if (ch == 3) { MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK59; } else if (ch == 2) { MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK60; } else if (ch == 1) { MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK61; } else { MCF_INTC_IMRH &= ~MCF_INTC_IMRH_INT_MASK62; } } bool timer_set_secs(uint8_t ch, uint32_t secs) { uint16_t timeout; /* * Reset the timer */ MCF_GPT_GMS(ch) = 0; /* * Get the timeout in seconds */ timeout = (uint16_t)(secs * net_timer[ch].cnt); /* * Set the reference indicating that we have not yet reached the * desired timeout */ net_timer[ch].reference = 1; /* * Enable timer interrupt to the processor */ timer_irq_enable(ch); /* * Enable the timer using the pre-calculated values */ MCF_GPT_GCIR(ch) = (0 | MCF_GPT_GCIR_CNT(timeout) | MCF_GPT_GCIR_PRE(net_timer[ch].pre) ); MCF_GPT_GMS(ch) = net_timer[ch].gms; return true; } uint32_t timer_get_reference(uint8_t ch) { return (uint32_t) net_timer[ch].reference; } bool timer_init(uint8_t ch, uint8_t lvl, uint8_t pri) { /* * Initialize the timer to expire after one second * * This routine should only be called by the project (board) specific * initialization code. */ if (!((ch <= 3) && (lvl <= 7) && (lvl >= 1) && (pri <= 7))) { dbg("illegal parameters (ch=%d, lvl=%d, pri=%d)\r\n", ch, lvl, pri); return false; } /* * Reset the timer */ MCF_GPT_GMS(ch) = 0; /* * Save off the channel, and interrupt lvl/pri information */ net_timer[ch].ch = ch; net_timer[ch].lvl = lvl; net_timer[ch].pri = pri; /* * Register the timer interrupt handler */ if (!isr_register_handler(TIMER_VECTOR(ch), 3, 0, (bool (*)(void *,void *)) timer_default_isr, NULL, (void *) &net_timer[ch]) ) { dbg("could not register timer interrupt handler\r\n"); return false; } dbg("timer handler registered\r\n", __FUNCTION__); /* * Calculate the require CNT value to get a 1 second timeout * * 1 sec = CNT * Clk Period * PRE * CNT = 1 sec / (Clk Period * PRE) * CNT = Clk Freq / PRE * * The system clock frequency is defined as SYSTEM_CLOCK and * is given in MHz. We need to multiple it by 1000000 to get the * true value. If we assume PRE to be the maximum of 0xFFFF, * then the CNT value needed to achieve a 1 second timeout is * given by: * * CNT = SYSTEM_CLOCK * (1000000/0xFFFF) */ net_timer[ch].pre = 0xFFFF; net_timer[ch].cnt = (uint16_t) ((SYSCLK / 1000) * (1000000 / 0xFFFF)); /* * Save off the appropriate mode select register value */ net_timer[ch].gms = (0 | MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_IEN | MCF_GPT_GMS_SC | MCF_GPT_GMS_CE ); return true; }