/*----------------------------------------------------------------------------*/ static enum result tmrInit(void *object, const void *configBase) { const struct GpTimerConfig * const config = configBase; const struct GpTimerBaseConfig baseConfig = { .channel = config->channel }; struct GpTimer * const timer = object; enum result res; assert(config->event < GPTIMER_EVENT_END); timer->event = config->event ? config->event : GPTIMER_MATCH0; --timer->event; /* Call base class constructor */ if ((res = GpTimerBase->init(object, &baseConfig)) != E_OK) return res; timer->base.handler = interruptHandler; timer->callback = 0; /* Initialize peripheral block */ LPC_TIMER_Type * const reg = timer->base.reg; reg->TCR = TCR_CRES; reg->IR = reg->IR; /* Clear pending interrupts */ reg->CCR = 0; reg->CTCR = 0; reg->MCR = 0; updateFrequency(timer, config->frequency); /* Configure prescaler and default match value */ reg->MR[timer->event] = getMaxValue(timer); /* Enable external match to generate signals to other peripherals */ reg->EMR = EMR_CONTROL(timer->event, CONTROL_TOGGLE); #ifdef CONFIG_GPTIMER_PM if ((res = pmRegister(interface, powerStateHandler)) != E_OK) return res; #endif /* Timer is disabled by default */ reg->TCR = 0; irqSetPriority(timer->base.irq, config->priority); irqEnable(timer->base.irq); return E_OK; } /*----------------------------------------------------------------------------*/ static void tmrDeinit(void *object) { struct GpTimer * const timer = object; LPC_TIMER_Type * const reg = timer->base.reg; irqDisable(timer->base.irq); reg->TCR = 0; #ifdef CONFIG_GPTIMER_PM pmUnregister(interface); #endif GpTimerBase->deinit(timer); } /*----------------------------------------------------------------------------*/ static void tmrCallback(void *object, void (*callback)(void *), void *argument) { struct GpTimer * const timer = object; LPC_TIMER_Type * const reg = timer->base.reg; timer->callbackArgument = argument; timer->callback = callback; if (callback) { reg->IR = reg->IR; reg->MCR |= MCR_INTERRUPT(timer->event); } else reg->MCR &= ~MCR_INTERRUPT(timer->event); } /*----------------------------------------------------------------------------*/ static void tmrSetEnabled(void *object, bool state) { struct GpTimer * const timer = object; LPC_TIMER_Type * const reg = timer->base.reg; /* Stop the timer */ reg->TCR = 0; /* Clear pending interrupt flags and direct memory access requests */ reg->IR = IR_MATCH_INTERRUPT(timer->event); if (state) { /* Clear match value to avoid undefined output level */ reg->EMR &= ~EMR_EXTERNAL_MATCH(timer->event); reg->TCR = TCR_CEN; } } /*----------------------------------------------------------------------------*/ static uint32_t tmrGetFrequency(const void *object) { const struct GpTimer * const timer = object; const LPC_TIMER_Type * const reg = timer->base.reg; const uint32_t baseClock = gpTimerGetClock((const struct GpTimerBase *)timer); return baseClock / (reg->PR + 1); } /*----------------------------------------------------------------------------*/ static void tmrSetFrequency(void *object, uint32_t frequency) { updateFrequency(object, frequency); }
/*----------------------------------------------------------------------------*/ static enum Result tmrInit(void *object, const void *configBase) { const struct GpTimerConfig * const config = configBase; assert(config); const struct GpTimerBaseConfig baseConfig = { .channel = config->channel }; struct GpTimer * const timer = object; enum Result res; assert(config->event < GPTIMER_EVENT_END); /* Call base class constructor */ if ((res = GpTimerBase->init(timer, &baseConfig)) != E_OK) return res; timer->base.handler = interruptHandler; timer->callback = 0; timer->event = (config->event ? config->event : GPTIMER_MATCH0) - 1; /* Initialize peripheral block */ LPC_TIMER_Type * const reg = timer->base.reg; reg->TCR = TCR_CRES; reg->IR = reg->IR; /* Clear pending interrupts */ reg->CCR = 0; reg->CTCR = 0; timer->frequency = config->frequency; gpTimerSetFrequency(&timer->base, timer->frequency); /* Configure prescaler and default match value */ reg->MR[timer->event] = getMaxValue(timer); /* Reset the timer after reaching the match register value */ reg->MCR = MCR_RESET(timer->event); /* Enable external match to generate signals to other peripherals */ reg->EMR = EMR_CONTROL(timer->event, CONTROL_TOGGLE); #ifdef CONFIG_PLATFORM_NXP_GPTIMER_PM if ((res = pmRegister(powerStateHandler, timer)) != E_OK) return res; #endif /* Clear timer reset flag, but do not enable */ reg->TCR = 0; irqSetPriority(timer->base.irq, config->priority); irqEnable(timer->base.irq); return E_OK; } /*----------------------------------------------------------------------------*/ #ifndef CONFIG_PLATFORM_NXP_GPTIMER_NO_DEINIT static void tmrDeinit(void *object) { struct GpTimer * const timer = object; LPC_TIMER_Type * const reg = timer->base.reg; irqDisable(timer->base.irq); reg->TCR = 0; #ifdef CONFIG_PLATFORM_NXP_GPTIMER_PM pmUnregister(timer); #endif GpTimerBase->deinit(timer); } #endif /*----------------------------------------------------------------------------*/ static void tmrEnable(void *object) { struct GpTimer * const timer = object; LPC_TIMER_Type * const reg = timer->base.reg; /* Clear pending interrupt flags and direct memory access requests */ reg->IR = IR_MATCH_INTERRUPT(timer->event); /* Clear match value to avoid undefined output level */ reg->EMR &= ~EMR_EXTERNAL_MATCH(timer->event); /* Start the timer */ reg->TCR = TCR_CEN; } /*----------------------------------------------------------------------------*/ static void tmrDisable(void *object) { struct GpTimer * const timer = object; LPC_TIMER_Type * const reg = timer->base.reg; reg->TCR = 0; } /*----------------------------------------------------------------------------*/ static void tmrSetCallback(void *object, void (*callback)(void *), void *argument) { struct GpTimer * const timer = object; LPC_TIMER_Type * const reg = timer->base.reg; timer->callbackArgument = argument; timer->callback = callback; if (callback) { reg->IR = reg->IR; reg->MCR |= MCR_INTERRUPT(timer->event); } else reg->MCR &= ~MCR_INTERRUPT(timer->event); } /*----------------------------------------------------------------------------*/ static uint32_t tmrGetFrequency(const void *object) { const struct GpTimer * const timer = object; const LPC_TIMER_Type * const reg = timer->base.reg; const uint32_t baseClock = gpTimerGetClock(&timer->base); return baseClock / (reg->PR + 1); } /*----------------------------------------------------------------------------*/ static void tmrSetFrequency(void *object, uint32_t frequency) { struct GpTimer * const timer = object; timer->frequency = frequency; gpTimerSetFrequency(&timer->base, timer->frequency); } /*----------------------------------------------------------------------------*/ static uint32_t tmrGetOverflow(const void *object) { const struct GpTimer * const timer = object; const LPC_TIMER_Type * const reg = timer->base.reg; return (reg->MR[timer->event] + 1) & getMaxValue(timer); } /*----------------------------------------------------------------------------*/ static void tmrSetOverflow(void *object, uint32_t overflow) { struct GpTimer * const timer = object; LPC_TIMER_Type * const reg = timer->base.reg; assert(overflow <= getMaxValue(timer)); reg->MR[timer->event] = overflow - 1; } /*----------------------------------------------------------------------------*/ static uint32_t tmrGetValue(const void *object) { const struct GpTimer * const timer = object; const LPC_TIMER_Type * const reg = timer->base.reg; return reg->TC; } /*----------------------------------------------------------------------------*/ static void tmrSetValue(void *object, uint32_t value) { struct GpTimer * const timer = object; LPC_TIMER_Type * const reg = timer->base.reg; assert(value <= reg->MR[timer->event]); reg->PC = 0; reg->TC = value; }