/**************************************************************************** * arch/arm/src/phy62xx/timer.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include "rom_sym_def.h" #include "timer.h" #include "error.h" #include "clock.h" #include "pwrmgr.h" #include "nvic.h" #include "arm_internal.h" #include "jump_function.h" #include /**************************************************************************** * Public Functions ****************************************************************************/ AP_TIM_TypeDef *const TimerIndex[FREE_TIMER_NUMBER] = { AP_TIM5, AP_TIM6 }; static ap_tm_hdl_t s_ap_callback = NULL; static int hal_timer_clear_int(AP_TIM_TypeDef *TIMx) { return TIMx->EOI; } static void hal_timer_stop_counter(AP_TIM_TypeDef *TIMx) { TIMx->ControlReg = 0; TIMx->LoadCount = 0; /* 0x0 */ TIMx->CurrentCount = 0; /* 0x4 */ } static void hal_timer_set_loadtimer(AP_TIM_TypeDef *TIMx, int time) { if (time > 0) { TIMx->ControlReg = 0x0; TIMx->ControlReg = 0x2; TIMx->LoadCount = 4 * time; /* 4MHz system timer, * 4 to convert to 1MHz timer */ TIMx->ControlReg = 0x3; } else { TIMx->ControlReg = 0x0; } } void __attribute__((used)) hal_TIMER5_IRQHandler(void) { if (AP_TIM5->status & 0x1) { hal_timer_clear_int(AP_TIM5); if (s_ap_callback) s_ap_callback(HAL_EVT_TIMER_5); } } void __attribute__((used)) hal_TIMER6_IRQHandler(void) { if (AP_TIM6->status & 0x1) { hal_timer_clear_int(AP_TIM6); if (s_ap_callback) s_ap_callback(HAL_EVT_TIMER_6); } } static void hal_timer_wakeup_handler(void) { if (s_ap_callback) s_ap_callback(HAL_EVT_WAKEUP); } void hal_timer_sleep_handler(void) { if (s_ap_callback) s_ap_callback(HAL_EVT_SLEEP); } int hal_timer_mask_int(User_Timer_e timeId, bool en) { volatile AP_TIM_TypeDef *TIMx; TIMx = TimerIndex[timeId - AP_TIMER_ID_5]; if (en) TIMx->ControlReg |= (1 << 2); else TIMx->ControlReg &= ~(1 << 2); return PPlus_SUCCESS; } int hal_timer_set(User_Timer_e timeId, uint32_t us) { uint32_t time = us; switch (timeId) { case AP_TIMER_ID_5: JUMP_FUNCTION(TIM5_IRQ_HANDLER) = (uint32_t)&hal_TIMER5_IRQHandler; NVIC_EnableIRQ((IRQn_Type)TIM5_IRQn); NVIC_SetPriority((IRQn_Type)TIM5_IRQn, IRQ_PRIO_HAL); hal_timer_set_loadtimer(AP_TIM5, time); hal_clk_gate_enable(MOD_TIMER5); break; case AP_TIMER_ID_6: JUMP_FUNCTION(TIM6_IRQ_HANDLER) = (uint32_t)&hal_TIMER6_IRQHandler; NVIC_EnableIRQ((IRQn_Type)TIM6_IRQn); NVIC_SetPriority((IRQn_Type)TIM6_IRQn, IRQ_PRIO_HAL); hal_timer_set_loadtimer(AP_TIM6, time); hal_clk_gate_enable(MOD_TIMER6); break; default: return PPlus_ERR_INVALID_PARAM; } return PPlus_SUCCESS; } int hal_timer_stop(User_Timer_e timeId) { switch (timeId) { case AP_TIMER_ID_5: JUMP_FUNCTION(TIM5_IRQ_HANDLER) = 0; hal_timer_stop_counter(AP_TIM5); NVIC_DisableIRQ((IRQn_Type)TIM5_IRQn); hal_clk_gate_disable(MOD_TIMER5); break; case AP_TIMER_ID_6: JUMP_FUNCTION(TIM6_IRQ_HANDLER) = 0; hal_timer_stop_counter(AP_TIM6); NVIC_DisableIRQ((IRQn_Type)TIM6_IRQn); hal_clk_gate_disable(MOD_TIMER6); break; default: return PPlus_ERR_INVALID_PARAM; } return PPlus_SUCCESS; } int hal_timer_init(ap_tm_hdl_t callback) { s_ap_callback = callback; hal_timer_stop(AP_TIMER_ID_5); hal_timer_stop(AP_TIMER_ID_6); return hal_pwrmgr_register(MOD_TIMER, hal_timer_sleep_handler, hal_timer_wakeup_handler); } int hal_timer_deinit(void) { s_ap_callback = NULL; return hal_pwrmgr_unregister(MOD_TIMER); } static int systic_timerisr(int irq, uint32_t *regs, void *arg) { /* Process timer interrupt */ nxsched_process_timer(); return 0; } extern uint32_t timer_sysclk_get_clk(void); void up_timer_initialize(void) { irq_attach(PHY62XX_IRQ_SYSTICK, (xcpt_t)systic_timerisr, NULL); putreg32((timer_sysclk_get_clk() / 100 - 1), ARMV6M_SYSTICK_RVR); /* 10ms tick */ putreg32((SYSTICK_CSR_TICKINT | SYSTICK_CSR_ENABLE | SYSTICK_CSR_CLKSOURCE), ARMV6M_SYSTICK_CSR); /* And enable the timer interrupt */ up_enable_irq(PHY62XX_IRQ_SYSTICK); /* set_timer(AP_TIM3, 2000); */ NVIC_EnableIRQ((IRQn_Type)TIM3_IRQn); }