Files
mr-library/bsp/wch/driver/drv_timer.c
2024-01-02 00:02:48 +08:00

404 lines
10 KiB
C

/*
* @copyright (c) 2023-2024, MR Development Team
*
* @license SPDX-License-Identifier: Apache-2.0
*
* @date 2023-11-30 MacRsh First version
*/
#include "drv_timer.h"
#ifdef MR_USING_TIMER
enum drv_timer_index
{
#ifdef MR_USING_TIMER1
DRV_INDEX_TIMER1,
#endif /* MR_USING_TIMER1 */
#ifdef MR_USING_TIMER2
DRV_INDEX_TIMER2,
#endif /* MR_USING_TIMER2 */
#ifdef MR_USING_TIMER3
DRV_INDEX_TIMER3,
#endif /* MR_USING_TIMER3 */
#ifdef MR_USING_TIMER4
DRV_INDEX_TIMER4,
#endif /* MR_USING_TIMER4 */
#ifdef MR_USING_TIMER5
DRV_INDEX_TIMER5,
#endif /* MR_USING_TIMER5 */
#ifdef MR_USING_TIMER6
DRV_INDEX_TIMER6,
#endif /* MR_USING_TIMER6 */
#ifdef MR_USING_TIMER7
DRV_INDEX_TIMER7,
#endif /* MR_USING_TIMER7 */
#ifdef MR_USING_TIMER8
DRV_INDEX_TIMER8,
#endif /* MR_USING_TIMER8 */
#ifdef MR_USING_TIMER9
DRV_INDEX_TIMER9,
#endif /* MR_USING_TIMER9 */
#ifdef MR_USING_TIMER10
DRV_INDEX_TIMER10,
#endif /* MR_USING_TIMER10 */
};
static const char *timer_name[] =
{
#ifdef MR_USING_TIMER1
"timer1",
#endif /* MR_USING_TIMER1 */
#ifdef MR_USING_TIMER2
"timer2",
#endif /* MR_USING_TIMER2 */
#ifdef MR_USING_TIMER3
"timer3",
#endif /* MR_USING_TIMER3 */
#ifdef MR_USING_TIMER4
"timer4",
#endif /* MR_USING_TIMER4 */
#ifdef MR_USING_TIMER5
"timer5",
#endif /* MR_USING_TIMER5 */
#ifdef MR_USING_TIMER6
"timer6",
#endif /* MR_USING_TIMER6 */
#ifdef MR_USING_TIMER7
"timer7",
#endif /* MR_USING_TIMER7 */
#ifdef MR_USING_TIMER8
"timer8",
#endif /* MR_USING_TIMER8 */
#ifdef MR_USING_TIMER9
"timer9",
#endif /* MR_USING_TIMER9 */
#ifdef MR_USING_TIMER10
"timer10",
#endif /* MR_USING_TIMER10 */
};
static struct drv_timer_data timer_drv_data[] =
{
#ifdef MR_USING_TIMER1
DRV_TIMER1_CONFIG,
#endif /* MR_USING_TIMER1 */
#ifdef MR_USING_TIMER2
DRV_TIMER2_CONFIG,
#endif /* MR_USING_TIMER2 */
#ifdef MR_USING_TIMER3
DRV_TIMER3_CONFIG,
#endif /* MR_USING_TIMER3 */
#ifdef MR_USING_TIMER4
DRV_TIMER4_CONFIG,
#endif /* MR_USING_TIMER4 */
#ifdef MR_USING_TIMER5
DRV_TIMER5_CONFIG,
#endif /* MR_USING_TIMER5 */
#ifdef MR_USING_TIMER6
DRV_TIMER6_CONFIG,
#endif /* MR_USING_TIMER6 */
#ifdef MR_USING_TIMER7
DRV_TIMER7_CONFIG,
#endif /* MR_USING_TIMER7 */
#ifdef MR_USING_TIMER8
DRV_TIMER8_CONFIG,
#endif /* MR_USING_TIMER8 */
#ifdef MR_USING_TIMER9
DRV_TIMER9_CONFIG,
#endif /* MR_USING_TIMER9 */
#ifdef MR_USING_TIMER10
DRV_TIMER10_CONFIG,
#endif /* MR_USING_TIMER10 */
};
static struct mr_timer timer_dev[MR_ARRAY_NUM(timer_drv_data)];
static struct mr_timer_info timer_info[] =
{
#ifdef MR_USING_TIMER1
DRV_TIMER1_INFO_CONFIG,
#endif /* MR_USING_TIMER1 */
#ifdef MR_USING_TIMER2
DRV_TIMER2_INFO_CONFIG,
#endif /* MR_USING_TIMER2 */
#ifdef MR_USING_TIMER3
DRV_TIMER3_INFO_CONFIG,
#endif /* MR_USING_TIMER3 */
#ifdef MR_USING_TIMER4
DRV_TIMER4_INFO_CONFIG,
#endif /* MR_USING_TIMER4 */
#ifdef MR_USING_TIMER5
DRV_TIMER5_INFO_CONFIG,
#endif /* MR_USING_TIMER5 */
#ifdef MR_USING_TIMER6
DRV_TIMER6_INFO_CONFIG,
#endif /* MR_USING_TIMER6 */
#ifdef MR_USING_TIMER7
DRV_TIMER7_INFO_CONFIG,
#endif /* MR_USING_TIMER7 */
#ifdef MR_USING_TIMER8
DRV_TIMER8_INFO_CONFIG,
#endif /* MR_USING_TIMER8 */
#ifdef MR_USING_TIMER9
DRV_TIMER9_INFO_CONFIG,
#endif /* MR_USING_TIMER9 */
#ifdef MR_USING_TIMER10
DRV_TIMER10_INFO_CONFIG,
#endif /* MR_USING_TIMER10 */
};
static int drv_timer_configure(struct mr_timer *timer, int state)
{
struct drv_timer_data *timer_data = (struct drv_timer_data *)timer->dev.drv->data;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = {0};
NVIC_InitTypeDef NVIC_InitStructure = {0};
RCC_ClocksTypeDef RCC_ClockStructure = {0};
uint32_t pclk = 0;
/* Configure clock */
RCC_GetClocksFreq(&RCC_ClockStructure);
if ((uint32_t)timer_data->instance > APB2PERIPH_BASE)
{
RCC_APB2PeriphClockCmd(timer_data->clock, state);
pclk = RCC_ClockStructure.PCLK2_Frequency;
} else
{
RCC_APB1PeriphClockCmd(timer_data->clock, state);
pclk = RCC_ClockStructure.PCLK1_Frequency;
}
/* Update timer clock(MHz) */
timer->info->clk = pclk / 1000000;
/* Configure timer */
TIM_TimeBaseInitStructure.TIM_Period = 0;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(timer_data->instance, &TIM_TimeBaseInitStructure);
/* Configure NVIC */
NVIC_InitStructure.NVIC_IRQChannel = timer_data->irq;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = state;
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(timer_data->instance, TIM_IT_Update, state);
TIM_ClearITPendingBit(timer_data->instance, TIM_IT_Update);
return MR_EOK;
}
static void drv_timer_start(struct mr_timer *timer, uint32_t prescaler, uint32_t period)
{
struct drv_timer_data *timer_data = (struct drv_timer_data *)timer->dev.drv->data;
/* Set the PSC and ARR, and enable the timer */
timer_data->instance->CNT = 0;
timer_data->instance->PSC = prescaler - 1;
timer_data->instance->ATRLR = period - 1;
TIM_Cmd(timer_data->instance, ENABLE);
}
static void drv_timer_stop(struct mr_timer *timer)
{
struct drv_timer_data *timer_data = (struct drv_timer_data *)timer->dev.drv->data;
/* Disable the timer */
TIM_Cmd(timer_data->instance, DISABLE);
}
static uint32_t drv_timer_get_count(struct mr_timer *timer)
{
struct drv_timer_data *timer_data = (struct drv_timer_data *)timer->dev.drv->data;
return timer_data->instance->CNT;
}
static void drv_timer_isr(struct mr_timer *timer)
{
struct drv_timer_data *timer_data = (struct drv_timer_data *)timer->dev.drv->data;
if (TIM_GetITStatus(timer_data->instance, TIM_IT_Update) != RESET)
{
mr_dev_isr(&timer->dev, MR_ISR_TIMER_TIMEOUT_INT, MR_NULL);
TIM_ClearITPendingBit(timer_data->instance, TIM_IT_Update);
}
}
#ifdef MR_USING_TIMER1
void TIM1_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM1_UP_IRQHandler(void)
{
drv_timer_isr(&timer_dev[DRV_INDEX_TIMER1]);
}
#endif /* MR_USING_TIMER1 */
#ifdef MR_USING_TIMER2
void TIM2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM2_IRQHandler(void)
{
drv_timer_isr(&timer_dev[DRV_INDEX_TIMER2]);
}
#endif /* MR_USING_TIMER2 */
#ifdef MR_USING_TIMER3
void TIM3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM3_IRQHandler(void)
{
drv_timer_isr(&timer_dev[DRV_INDEX_TIMER3]);
}
#endif /* MR_USING_TIMER3 */
#ifdef MR_USING_TIMER4
void TIM4_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM4_IRQHandler(void)
{
drv_timer_isr(&timer_dev[DRV_INDEX_TIMER4]);
}
#endif /* MR_USING_TIMER4 */
#ifdef MR_USING_TIMER5
void TIM5_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM5_IRQHandler(void)
{
drv_timer_isr(&timer_dev[DRV_INDEX_TIMER5]);
}
#endif /* MR_USING_TIMER5 */
#ifdef MR_USING_TIMER6
void TIM6_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM6_IRQHandler(void)
{
drv_timer_isr(&timer_dev[DRV_INDEX_TIMER6]);
}
#endif /* MR_USING_TIMER6 */
#ifdef MR_USING_TIMER7
void TIM7_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM7_IRQHandler(void)
{
drv_timer_isr(&timer_dev[DRV_INDEX_TIMER7]);
}
#endif /* MR_USING_TIMER7 */
#ifdef MR_USING_TIMER8
void TIM8_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM8_UP_IRQHandler(void)
{
drv_timer_isr(&timer_dev[DRV_INDEX_TIMER8]);
}
#endif /* MR_USING_TIMER8 */
#ifdef MR_USING_TIMER9
void TIM9_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM9_UP_IRQHandler(void)
{
drv_timer_isr(&timer_dev[DRV_INDEX_TIMER9]);
}
#endif /* MR_USING_TIMER9 */
#ifdef MR_USING_TIMER10
void TIM10_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM10_UP_IRQHandler(void)
{
drv_timer_isr(&timer_dev[DRV_INDEX_TIMER10]);
}
#endif /* MR_USING_TIMER10 */
static struct mr_timer_ops timer_drv_ops =
{
drv_timer_configure,
drv_timer_start,
drv_timer_stop,
drv_timer_get_count
};
static struct mr_drv timer_drv[] =
{
#ifdef MR_USING_TIMER1
{
Mr_Drv_Type_Timer,
&timer_drv_ops,
&timer_drv_data[DRV_INDEX_TIMER1]
},
#endif /* MR_USING_TIMER1 */
#ifdef MR_USING_TIMER2
{
Mr_Drv_Type_Timer,
&timer_drv_ops,
&timer_drv_data[DRV_INDEX_TIMER2]
},
#endif /* MR_USING_TIMER2 */
#ifdef MR_USING_TIMER3
{
Mr_Drv_Type_Timer,
&timer_drv_ops,
&timer_drv_data[DRV_INDEX_TIMER3]
},
#endif /* MR_USING_TIMER3 */
#ifdef MR_USING_TIMER4
{
Mr_Drv_Type_Timer,
&timer_drv_ops,
&timer_drv_data[DRV_INDEX_TIMER4]
},
#endif /* MR_USING_TIMER4 */
#ifdef MR_USING_TIMER5
{
Mr_Drv_Type_Timer,
&timer_drv_ops,
&timer_drv_data[DRV_INDEX_TIMER5]
},
#endif /* MR_USING_TIMER5 */
#ifdef MR_USING_TIMER6
{
Mr_Drv_Type_Timer,
&timer_drv_ops,
&timer_drv_data[DRV_INDEX_TIMER6]
},
#endif /* MR_USING_TIMER6 */
#ifdef MR_USING_TIMER7
{
Mr_Drv_Type_Timer,
&timer_drv_ops,
&timer_drv_data[DRV_INDEX_TIMER7]
},
#endif /* MR_USING_TIMER7 */
#ifdef MR_USING_TIMER8
{
Mr_Drv_Type_Timer,
&timer_drv_ops,
&timer_drv_data[DRV_INDEX_TIMER8]
},
#endif /* MR_USING_TIMER8 */
#ifdef MR_USING_TIMER9
{
Mr_Drv_Type_Timer,
&timer_drv_ops,
&timer_drv_data[DRV_INDEX_TIMER9]
},
#endif /* MR_USING_TIMER9 */
#ifdef MR_USING_TIMER10
{
Mr_Drv_Type_Timer,
&timer_drv_ops,
&timer_drv_data[DRV_INDEX_TIMER10]
},
#endif /* MR_USING_TIMER10 */
};
int drv_timer_init(void)
{
int index = 0;
for (index = 0; index < MR_ARRAY_NUM(timer_dev); index++)
{
mr_timer_register(&timer_dev[index], timer_name[index], &timer_drv[index], &timer_info[index]);
}
return MR_EOK;
}
MR_INIT_DRV_EXPORT(drv_timer_init);
#endif /* MR_USING_TIMER */