Files
test_rtt_413/libraries/HAL_Drivers/drv_inputcapture.c

640 lines
16 KiB
C
Raw Normal View History

/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include <board.h>
#ifdef BSP_USING_CAPTURE
#include "drv_config.h"
#define CAPTURE1_CONFIG \
{ \
.timer.Instance = TIM1, \
.iqrn = TIM1_CC_IRQn, \
.timerx = 1, \
.advanced = RT_TRUE, \
}
#define CAPTURE2_CONFIG \
{ \
.timer.Instance = TIM2, \
.iqrn = TIM2_IRQn, \
.timerx = 2, \
}
#define CAPTURE12_CONFIG \
{ \
.timer.Instance = TIM12, \
.iqrn = TIM8_BRK_TIM12_IRQn, \
.timerx = 12, \
}
#define LOG_TAG "drv.tcap"
#include <drv_log.h>
#define MAX_PERIOD 65535
#define MAX_PULSE 1000
typedef enum {
POLARITY_BOTHEDGE,
POLARITY_RISING,
POLARITY_FALLING,
}trigger_polarity;
struct pulse_data
{
rt_uint32_t last_overflow;
rt_uint32_t last_cnt;
trigger_polarity polarity;
};
struct stm32_capture_device;
struct stm32_capture
{
TIM_HandleTypeDef timer;
IRQn_Type iqrn;
rt_uint8_t timerx;
rt_uint8_t advanced;
rt_uint8_t inited;
rt_uint32_t tim_overflow;
struct stm32_capture_device *channels[4];
};
enum
{
#ifdef BSP_USING_CAPTURE1
CAPTURE1_INDEX,
#endif
#ifdef BSP_USING_CAPTURE2
CAPTURE2_INDEX,
#endif
#ifdef BSP_USING_CAPTURE3
CAPTURE3_INDEX,
#endif
#ifdef BSP_USING_CAPTURE4
CAPTURE4_INDEX,
#endif
#ifdef BSP_USING_CAPTURE5
CAPTURE5_INDEX,
#endif
#ifdef BSP_USING_CAPTURE6
CAPTURE6_INDEX,
#endif
#ifdef BSP_USING_CAPTURE7
CAPTURE7_INDEX,
#endif
#ifdef BSP_USING_CAPTURE8
CAPTURE8_INDEX,
#endif
#ifdef BSP_USING_CAPTURE9
CAPTURE9_INDEX,
#endif
#ifdef BSP_USING_CAPTURE10
CAPTURE10_INDEX,
#endif
#ifdef BSP_USING_CAPTURE11
CAPTURE11_INDEX,
#endif
#ifdef BSP_USING_CAPTURE12
CAPTURE12_INDEX,
#endif
};
static struct stm32_capture stm32_capture_obj[] =
{
#ifdef BSP_USING_CAPTURE1
CAPTURE1_CONFIG,
#endif
#ifdef BSP_USING_CAPTURE2
CAPTURE2_CONFIG,
#endif
#ifdef BSP_USING_CAPTURE3
CAPTURE3_CONFIG,
#endif
#ifdef BSP_USING_CAPTURE4
CAPTURE4_CONFIG,
#endif
#ifdef BSP_USING_CAPTURE5
CAPTURE5_CONFIG,
#endif
#ifdef BSP_USING_CAPTURE6
CAPTURE6_CONFIG,
#endif
#ifdef BSP_USING_CAPTURE7
CAPTURE7_CONFIG,
#endif
#ifdef BSP_USING_CAPTURE8
CAPTURE8_CONFIG,
#endif
#ifdef BSP_USING_CAPTURE9
CAPTURE9_CONFIG,
#endif
#ifdef BSP_USING_CAPTURE10
CAPTURE10_CONFIG,
#endif
#ifdef BSP_USING_CAPTURE11
CAPTURE11_CONFIG,
#endif
#ifdef BSP_USING_CAPTURE12
CAPTURE12_CONFIG,
#endif
};
struct stm32_capture_device
{
struct rt_inputcapture_device parent;
struct stm32_capture *timer;
rt_uint8_t ch;
rt_uint8_t opend;
struct pulse_data data;
rt_uint32_t pulsewidth_us;
};
static struct stm32_capture_device stm32_capture_devices[] =
{
#ifdef BSP_USING_CAPTURE1_CH1
{{0}, &stm32_capture_obj[CAPTURE1_INDEX], 1, {0}},
#endif
#ifdef BSP_USING_CAPTURE1_CH2
{{0}, &stm32_capture_obj[CAPTURE1_INDEX], 2, {0}},
#endif
#ifdef BSP_USING_CAPTURE1_CH3
{{0}, &stm32_capture_obj[CAPTURE1_INDEX], 3, {0}},
#endif
#ifdef BSP_USING_CAPTURE1_CH4
{{0}, &stm32_capture_obj[CAPTURE1_INDEX], 4, {0}},
#endif
#ifdef BSP_USING_CAPTURE2_CH1
{{0}, &stm32_capture_obj[CAPTURE2_INDEX], 1, {0}},
#endif
#ifdef BSP_USING_CAPTURE2_CH2
{{0}, &stm32_capture_obj[CAPTURE2_INDEX], 2, {0}},
#endif
#ifdef BSP_USING_CAPTURE2_CH3
{{0}, &stm32_capture_obj[CAPTURE2_INDEX], 3, {0}},
#endif
#ifdef BSP_USING_CAPTURE2_CH4
{{0}, &stm32_capture_obj[CAPTURE2_INDEX], 4, {0}},
#endif
#ifdef BSP_USING_CAPTURE3_CH1
{{0}, &stm32_capture_obj[CAPTURE3_INDEX], 1, {0}},
#endif
#ifdef BSP_USING_CAPTURE3_CH2
{{0}, &stm32_capture_obj[CAPTURE3_INDEX], 2, {0}},
#endif
#ifdef BSP_USING_CAPTURE3_CH3
{{0}, &stm32_capture_obj[CAPTURE3_INDEX], 3, {0}},
#endif
#ifdef BSP_USING_CAPTURE3_CH4
{{0}, &stm32_capture_obj[CAPTURE3_INDEX], 4, {0}},
#endif
#ifdef BSP_USING_CAPTURE4_CH1
{{0}, &stm32_capture_obj[CAPTURE4_INDEX], 1, {0}},
#endif
#ifdef BSP_USING_CAPTURE4_CH2
{{0}, &stm32_capture_obj[CAPTURE4_INDEX], 2, {0}},
#endif
#ifdef BSP_USING_CAPTURE4_CH3
{{0}, &stm32_capture_obj[CAPTURE4_INDEX], 3, {0}},
#endif
#ifdef BSP_USING_CAPTURE4_CH4
{{0}, &stm32_capture_obj[CAPTURE4_INDEX], 4, {0}},
#endif
#ifdef BSP_USING_CAPTURE5_CH1
{{0}, &stm32_capture_obj[CAPTURE5_INDEX], 1, {0}},
#endif
#ifdef BSP_USING_CAPTURE5_CH2
{{0}, &stm32_capture_obj[CAPTURE5_INDEX], 2, {0}},
#endif
#ifdef BSP_USING_CAPTURE5_CH3
{{0}, &stm32_capture_obj[CAPTURE5_INDEX], 3, {0}},
#endif
#ifdef BSP_USING_CAPTURE5_CH4
{{0}, &stm32_capture_obj[CAPTURE5_INDEX], 4, {0}},
#endif
#ifdef BSP_USING_CAPTURE6_CH1
{{0}, &stm32_capture_obj[CAPTURE6_INDEX], 1, {0}},
#endif
#ifdef BSP_USING_CAPTURE6_CH2
{{0}, &stm32_capture_obj[CAPTURE6_INDEX], 2, {0}},
#endif
#ifdef BSP_USING_CAPTURE6_CH3
{{0}, &stm32_capture_obj[CAPTURE6_INDEX], 3, {0}},
#endif
#ifdef BSP_USING_CAPTURE6_CH4
{{0}, &stm32_capture_obj[CAPTURE6_INDEX], 4, {0}},
#endif
#ifdef BSP_USING_CAPTURE7_CH1
{{0}, &stm32_capture_obj[CAPTURE7_INDEX], 1, {0}},
#endif
#ifdef BSP_USING_CAPTURE7_CH2
{{0}, &stm32_capture_obj[CAPTURE7_INDEX], 2, {0}},
#endif
#ifdef BSP_USING_CAPTURE7_CH3
{{0}, &stm32_capture_obj[CAPTURE7_INDEX], 3, {0}},
#endif
#ifdef BSP_USING_CAPTURE7_CH4
{{0}, &stm32_capture_obj[CAPTURE7_INDEX], 4, {0}},
#endif
#ifdef BSP_USING_CAPTURE8_CH1
{{0}, &stm32_capture_obj[CAPTURE8_INDEX], 1, {0}},
#endif
#ifdef BSP_USING_CAPTURE8_CH2
{{0}, &stm32_capture_obj[CAPTURE8_INDEX], 2, {0}},
#endif
#ifdef BSP_USING_CAPTURE8_CH3
{{0}, &stm32_capture_obj[CAPTURE8_INDEX], 3, {0}},
#endif
#ifdef BSP_USING_CAPTURE8_CH4
{{0}, &stm32_capture_obj[CAPTURE8_INDEX], 4, {0}},
#endif
#ifdef BSP_USING_CAPTURE9_CH1
{{0}, &stm32_capture_obj[CAPTURE9_INDEX], 1, {0}},
#endif
#ifdef BSP_USING_CAPTURE9_CH2
{{0}, &stm32_capture_obj[CAPTURE9_INDEX], 2, {0}},
#endif
#ifdef BSP_USING_CAPTURE9_CH3
{{0}, &stm32_capture_obj[CAPTURE9_INDEX], 3, {0}},
#endif
#ifdef BSP_USING_CAPTURE9_CH4
{{0}, &stm32_capture_obj[CAPTURE9_INDEX], 4, {0}},
#endif
#ifdef BSP_USING_CAPTURE10_CH1
{{0}, &stm32_capture_obj[CAPTURE10_INDEX], 1, {0}},
#endif
#ifdef BSP_USING_CAPTURE10_CH2
{{0}, &stm32_capture_obj[CAPTURE10_INDEX], 2, {0}},
#endif
#ifdef BSP_USING_CAPTURE10_CH3
{{0}, &stm32_capture_obj[CAPTURE10_INDEX], 3, {0}},
#endif
#ifdef BSP_USING_CAPTURE10_CH4
{{0}, &stm32_capture_obj[CAPTURE10_INDEX], 4, {0}},
#endif
#ifdef BSP_USING_CAPTURE12_CH1
{{0}, &stm32_capture_obj[CAPTURE12_INDEX], 1, {0}},
#endif
#ifdef BSP_USING_CAPTURE12_CH2
{{0}, &stm32_capture_obj[CAPTURE12_INDEX], 2, {0}},
#endif
};
static rt_uint64_t get_timer_clock(TIM_HandleTypeDef *htim)
{
rt_uint64_t tim_clock = 0;
#if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7)
if (htim->Instance == TIM9 || htim->Instance == TIM10 || htim->Instance == TIM11 || htim->Instance == TIM1 || htim->Instance == TIM8)
#elif defined(SOC_SERIES_STM32L4)
if (htim->Instance == TIM15 || htim->Instance == TIM16 || htim->Instance == TIM17)
#elif defined(SOC_SERIES_STM32MP1)
if (htim->Instance == TIM4)
#elif defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0)
if (0)
#endif
{
#if !defined(SOC_SERIES_STM32F0) && !defined(SOC_SERIES_STM32G0)
#ifdef STM32F413xx
tim_clock = HAL_RCC_GetPCLK2Freq();
#else
tim_clock = HAL_RCC_GetPCLK2Freq() * 2;
#endif
#endif
}
else
{
#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0)
tim_clock = HAL_RCC_GetPCLK1Freq();
#else
tim_clock = HAL_RCC_GetPCLK1Freq() * 2;
#endif
}
return tim_clock;
}
static void rt_hw_capture_timer_init(struct stm32_capture *device)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_IC_InitTypeDef sConfigIC = {0};
rt_uint64_t tim_clock;
if (device->inited)
{
return;
}
tim_clock = get_timer_clock(&device->timer) / 1000000;
/* configure the timer to ic mode */
device->timer.Init.Prescaler = tim_clock-1;
device->timer.Init.CounterMode = TIM_COUNTERMODE_UP;
device->timer.Init.Period = MAX_PERIOD-1;
device->timer.Init.AutoReloadPreload = MAX_PERIOD-1;
device->timer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32L4)
device->timer.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
#else
device->timer.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
#endif
if (device->advanced && HAL_TIM_Base_Init(&device->timer) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_IC_Init(&device->timer) != HAL_OK)
{
Error_Handler();
}
HAL_NVIC_SetPriority(device->iqrn, 0, 0);
HAL_NVIC_EnableIRQ(device->iqrn);
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&device->timer, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&device->timer, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
if (device->channels[0] != RT_NULL && HAL_TIM_IC_ConfigChannel(&device->timer, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
if (device->channels[1] != RT_NULL && HAL_TIM_IC_ConfigChannel(&device->timer, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
if (device->channels[2] != RT_NULL && HAL_TIM_IC_ConfigChannel(&device->timer, &sConfigIC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
if (device->channels[3] != RT_NULL && HAL_TIM_IC_ConfigChannel(&device->timer, &sConfigIC, TIM_CHANNEL_4) != HAL_OK)
{
Error_Handler();
}
__HAL_TIM_DISABLE(&device->timer);
__HAL_TIM_SET_COUNTER(&device->timer,0);
__HAL_TIM_ENABLE_IT(&device->timer,TIM_IT_UPDATE);
__HAL_TIM_ENABLE(&device->timer);
device->inited = RT_TRUE;
}
static rt_err_t rt_hw_capture_open(struct rt_inputcapture_device *inputcapture)
{
struct stm32_capture_device *device_ch;
rt_uint32_t ch;
rt_enter_critical();
device_ch = rt_container_of(inputcapture, struct stm32_capture_device, parent);
if (device_ch->opend)
{
rt_exit_critical();
return RT_EOK;
}
device_ch->opend = RT_TRUE;
rt_hw_capture_timer_init(device_ch->timer);
rt_exit_critical();
switch (device_ch->ch)
{
case 1:
ch = TIM_CHANNEL_1;
break;
case 2:
ch = TIM_CHANNEL_2;
break;
case 3:
ch = TIM_CHANNEL_3;
break;
default:
ch = TIM_CHANNEL_4;
break;
}
HAL_TIM_IC_Start_IT(&device_ch->timer->timer, ch);
return RT_EOK;
}
void TIM2_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
HAL_TIM_IRQHandler(&stm32_capture_obj[CAPTURE2_INDEX].timer);
/* leave interrupt */
rt_interrupt_leave();
}
void TIM1_CC_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
HAL_TIM_IRQHandler(&stm32_capture_obj[CAPTURE1_INDEX].timer);
/* leave interrupt */
rt_interrupt_leave();
}
void TIM8_BRK_TIM12_IRQHandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
HAL_TIM_IRQHandler(&stm32_capture_obj[CAPTURE12_INDEX].timer);
/* leave interrupt */
rt_interrupt_leave();
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
int i = 0;
for (i = 0; i < sizeof(stm32_capture_obj) / sizeof(stm32_capture_obj[0]); i++)
{
if (stm32_capture_obj[i].timer.Instance == htim->Instance)
{
stm32_capture_obj[i].tim_overflow ++;
}
}
}
static void _capture_computer(struct stm32_capture_device *dev, rt_uint32_t channel)
{
rt_uint32_t trigger_overflow = 0;
rt_uint32_t trigger_cnt = 0;
if (dev->data.polarity == POLARITY_RISING)
{
TIM_RESET_CAPTUREPOLARITY(&dev->timer->timer, channel);
TIM_SET_CAPTUREPOLARITY(&dev->timer->timer,channel, TIM_ICPOLARITY_FALLING);
dev->data.polarity = POLARITY_FALLING;
}
else
{
TIM_RESET_CAPTUREPOLARITY(&dev->timer->timer, channel);
TIM_SET_CAPTUREPOLARITY(&dev->timer->timer,channel, TIM_ICPOLARITY_RISING);
dev->data.polarity = POLARITY_RISING;
}
trigger_cnt = HAL_TIM_ReadCapturedValue(&dev->timer->timer, channel);
trigger_overflow = dev->timer->tim_overflow;
if((trigger_overflow < dev->data.last_overflow) ||
((trigger_overflow - dev->data.last_overflow) > MAX_PULSE))
{
dev->data.last_overflow = trigger_overflow;
dev->data.last_cnt = trigger_cnt;
return;
}
dev->pulsewidth_us = (trigger_overflow - dev->data.last_overflow)*MAX_PERIOD
+ trigger_cnt - dev->data.last_cnt;
rt_hw_inputcapture_isr(&dev->parent, dev->data.polarity != POLARITY_FALLING);
dev->data.last_overflow = trigger_overflow;
dev->data.last_cnt = trigger_cnt;
return;
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
int i = 0;
rt_uint32_t ch, to;
for (i = 0; i < sizeof(stm32_capture_devices) / sizeof(stm32_capture_devices[0]); i++)
{
switch (stm32_capture_devices[i].ch)
{
case 1:
ch = HAL_TIM_ACTIVE_CHANNEL_1;
to = TIM_CHANNEL_1;
break;
case 2:
ch = HAL_TIM_ACTIVE_CHANNEL_2;
to = TIM_CHANNEL_2;
break;
case 3:
ch = HAL_TIM_ACTIVE_CHANNEL_3;
to = TIM_CHANNEL_3;
break;
default:
ch = HAL_TIM_ACTIVE_CHANNEL_4;
to = TIM_CHANNEL_4;
break;
}
if (htim->Channel == ch && htim->Instance == stm32_capture_devices[i].timer->timer.Instance)
{
_capture_computer(&stm32_capture_devices[i], to);
}
}
}
static rt_err_t rt_hw_capture_get_pulsewidth (struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us)
{
struct stm32_capture_device *device;
device = rt_container_of(inputcapture, struct stm32_capture_device, parent);
*pulsewidth_us = device->pulsewidth_us;
return RT_EOK;
}
static rt_err_t rt_hw_capture_init (struct rt_inputcapture_device *inputcapture)
{
return RT_EOK;
}
static rt_err_t rt_hw_capture_close (struct rt_inputcapture_device *inputcapture)
{
struct stm32_capture_device *device_ch;
rt_uint32_t ch;
rt_enter_critical();
device_ch = rt_container_of(inputcapture, struct stm32_capture_device, parent);
if (!device_ch->opend)
{
rt_exit_critical();
return RT_EOK;
}
switch (device_ch->ch)
{
case 1:
ch = TIM_CHANNEL_1;
break;
case 2:
ch = TIM_CHANNEL_2;
break;
case 3:
ch = TIM_CHANNEL_3;
break;
default:
ch = TIM_CHANNEL_4;
break;
}
HAL_TIM_IC_Stop_IT(&device_ch->timer->timer, ch);
device_ch->opend = RT_FALSE;
rt_exit_critical();
return RT_EOK;
}
static const struct rt_inputcapture_ops _drv_ops = {
.init = rt_hw_capture_init,
.open = rt_hw_capture_open,
.close = rt_hw_capture_close,
.get_pulsewidth = rt_hw_capture_get_pulsewidth,
};
int stm32_capture_init(void)
{
int i = 0;
char name[] = "tc00ch0";
for (i = 0; i < sizeof(stm32_capture_devices) / sizeof(stm32_capture_devices[0]); i++)
{
stm32_capture_devices[i].timer->channels[stm32_capture_devices[i].ch - 1] = &stm32_capture_devices[i];
stm32_capture_devices[i].parent.ops = &_drv_ops;
rt_snprintf(name, sizeof(name),"tc%dch%d", stm32_capture_devices[i].timer->timerx, stm32_capture_devices[i].ch);
rt_device_inputcapture_register(&stm32_capture_devices[i].parent, name, RT_NULL);
}
return RT_EOK;
}
#endif