Loading...
Searching...
No Matches
bench_time.h
Go to the documentation of this file.
/**
******************************************************************************
* @file bench_time.h
* @brief Заголовочный файл для измерения времени между событиями
******************************************************************************
* @addtogroup BENCH_TIME Time measurement
* @brief Библиотека для измерения времени/тиков между событиями
* @details
Поддерживает:
- Многоканальные измерения (несколько независимых таймеров)
- Платформонезависимый интерфейс
- Измерение в тиках или временных единицах
- Статистику измерений (мин/макс/среднее)
- Настраиваемый размер тиков для каждого канала
Параметры для конфигурации:
- @ref BENCH_TIME_ENABLE - Включить бенч времени
- @ref BENCH_TIME_MAX_CHANNELS - Максимальное количество каналов измерения (по умолчанию 8)
@par Пример использования:
@code
#include "bench_time.h"
// Инициализация
BenchTime_Init();
// Измерение с SysTick
BenchTime_Start(0, HAL_GetTick, 0xFFFFFFFF);
some_function();
uint32_t time = BenchTime_End(0, HAL_GetTick);
// Измерение с TIM2 (16-бит)
BenchTime_Start(1, TIM2->CNT, 0xFFFF);
fast_function();
uint32_t time2 = BenchTime_End(1, TIM2->CNT);
// Измерение с DWT цикловым счетчиком
BenchTime_Start(2, DWT->CYCCNT, 0xFFFFFFFF);
critical_function();
uint32_t cycles = BenchTime_End(2, DWT->CYCCNT);
// Многоканальное измерение
BenchTime_Start(0, HAL_GetTick, 1000); // общее время
BenchTime_Start(1, TIM3->CNT, 500); // часть 1
// ... код 1
uint32_t part1 = BenchTime_End(1, TIM3->CNT);
BenchTime_Start(2, TIM4->CNT, 200); // часть 2
// ... код 2
uint32_t part2 = BenchTime_End(2, TIM4->CNT);
uint32_t total = BenchTime_End(0, HAL_GetTick); // общее время
// Статистика
uint32_t min_time = BenchTime_GetMin(0);
uint32_t max_time = BenchTime_GetMax(0);
uint32_t avg_time = BenchTime_GetAverage(0);
uint32_t count = BenchTime_GetCount(0);
@endcode
* @{
*****************************************************************************/
#ifndef __BENCH_TIME_H_
#define __BENCH_TIME_H_
#include "mylibs_defs.h"
#include <stdint.h>
#ifdef BENCH_TIME_ENABLE
// Конфигурация библиотеки
#ifndef BENCH_TIME_MAX_CHANNELS
#define BENCH_TIME_MAX_CHANNELS 8 ///< Максимальное количество каналов измерения
#endif
/**
* @brief Структура статистики измерений
*/
typedef struct {
uint32_t min_ticks; ///< Минимальное время в тиках
uint32_t max_ticks; ///< Максимальное время в тиках
uint32_t total_ticks; ///< Суммарное время в тиках
uint32_t count; ///< Количество измерений
uint32_t last_ticks; ///< Последнее измеренное время
} BenchTimeStats_t;
/**
* @brief Структура канала измерения
*/
typedef struct {
uint32_t start_tick; ///< Время старта в тиках
uint32_t tick_period; ///< Период тиков для переполнения
uint32_t is_running; ///< Флаг активного измерения
BenchTimeStats_t stats; ///< Статистика измерений
} BenchTimeChannel_t;
/**
* @brief Основная структура менеджера измерений
*/
typedef struct {
BenchTimeChannel_t channels[BENCH_TIME_MAX_CHANNELS]; ///< Каналы измерения
} BenchTime_t;
static BenchTime_t hbt = {0}; ///< Внутренний экземпляр
/**
* @brief Инициализация системы измерения времени
*/
static inline void BenchTime_Init(void) {
for (int i = 0; i < BENCH_TIME_MAX_CHANNELS; i++) {
hbt.channels[i].start_tick = 0;
hbt.channels[i].tick_period = 0xFFFFFFFF;
hbt.channels[i].is_running = 0;
hbt.channels[i].stats.min_ticks = 0xFFFFFFFF;
hbt.channels[i].stats.max_ticks = 0;
hbt.channels[i].stats.total_ticks = 0;
hbt.channels[i].stats.count = 0;
hbt.channels[i].stats.last_ticks = 0;
}
}
/**
* @brief Начало измерения на указанном канале
* @param channel Номер канала (0..BENCH_TIME_MAX_CHANNELS-1)
* @param ticks Источник тиков (например: HAL_GetTick(), TIM2->CNT, DWT->CYCCNT)
* @param tick_period Период тиков для переполнения
* @return 1 - успех, 0 - ошибка
*/
static inline uint32_t BenchTime_Start(uint8_t channel, uint32_t ticks, uint32_t tick_period) {
if (channel >= BENCH_TIME_MAX_CHANNELS) return 0;
if (hbt.channels[channel].is_running) return 0;
hbt.channels[channel].start_tick = ticks;
hbt.channels[channel].tick_period = tick_period;
hbt.channels[channel].is_running = 1;
return 1;
}
/**
* @brief Окончание измерения на указанном канале
* @param channel Номер канала (0..BENCH_TIME_MAX_CHANNELS-1)
* @param ticks Источник тиков (должен быть тот же что в Start)
* @return Измеренное время в тиках, 0 - в случае ошибки
*/
static inline uint32_t BenchTime_End(uint8_t channel, uint32_t ticks) {
if (channel >= BENCH_TIME_MAX_CHANNELS) return 0;
if (!hbt.channels[channel].is_running) return 0;
uint32_t end_tick = ticks;
uint32_t start_tick = hbt.channels[channel].start_tick;
uint32_t tick_period = hbt.channels[channel].tick_period;
uint32_t elapsed_ticks;
if (end_tick >= start_tick) {
elapsed_ticks = end_tick - start_tick;
} else {
elapsed_ticks = (tick_period - start_tick) + end_tick + 1;
}
if (elapsed_ticks > tick_period) {
elapsed_ticks = tick_period;
}
hbt.channels[channel].is_running = 0;
// Обновление статистики
BenchTimeStats_t* stats = &hbt.channels[channel].stats;
stats->last_ticks = elapsed_ticks;
if (elapsed_ticks < stats->min_ticks) {
stats->min_ticks = elapsed_ticks;
}
if (elapsed_ticks > stats->max_ticks) {
stats->max_ticks = elapsed_ticks;
}
stats->total_ticks += elapsed_ticks;
stats->count++;
return elapsed_ticks;
}
/**
* @brief Получение минимального времени измерения
*/
static inline uint32_t BenchTime_GetMin(uint8_t channel) {
if (channel >= BENCH_TIME_MAX_CHANNELS) return 0;
return hbt.channels[channel].stats.min_ticks;
}
/**
* @brief Получение максимального времени измерения
*/
static inline uint32_t BenchTime_GetMax(uint8_t channel) {
if (channel >= BENCH_TIME_MAX_CHANNELS) return 0;
return hbt.channels[channel].stats.max_ticks;
}
/**
* @brief Получение среднего времени измерения
*/
static inline uint32_t BenchTime_GetAverage(uint8_t channel) {
if (channel >= BENCH_TIME_MAX_CHANNELS) return 0;
BenchTimeStats_t* stats = &hbt.channels[channel].stats;
if (stats->count == 0) return 0;
return stats->total_ticks / stats->count;
}
/**
* @brief Получение количества измерений
*/
static inline uint32_t BenchTime_GetCount(uint8_t channel) {
if (channel >= BENCH_TIME_MAX_CHANNELS) return 0;
return hbt.channels[channel].stats.count;
}
/**
* @brief Получение последнего измеренного времени
*/
static inline uint32_t BenchTime_GetLast(uint8_t channel) {
if (channel >= BENCH_TIME_MAX_CHANNELS) return 0;
return hbt.channels[channel].stats.last_ticks;
}
/**
* @brief Сброс статистики для канала
*/
static inline void BenchTime_ResetStats(uint8_t channel) {
if (channel >= BENCH_TIME_MAX_CHANNELS) return;
BenchTimeStats_t* stats = &hbt.channels[channel].stats;
stats->min_ticks = 0xFFFFFFFF;
stats->max_ticks = 0;
stats->total_ticks = 0;
stats->count = 0;
stats->last_ticks = 0;
}
#else //BENCH_TIME_ENABLE
#define BenchTime_Init()
#define BenchTime_Start(channel, ticks, tick_period) 0
#define BenchTime_End(channel, ticks) 0
#define BenchTime_GetMin(channel) 0
#define BenchTime_GetMax(channel) 0
#define BenchTime_GetAverage(channel) 0
#define BenchTime_GetCount(channel) 0
#define BenchTime_GetLast(channel) 0
#define BenchTime_ResetStats(channel)
#endif //BENCH_TIME_ENABLE
#endif // __BENCH_TIME_H_
/** BENCH_TIME
* @}
*/
BENCH_TIME_MAX_CHANNELS
#define BENCH_TIME_MAX_CHANNELS
Максимальное количество каналов измерения
Definition __mylibs_config.h:82
mylibs_defs.h
Заголочный файл для дефайнов библиотеки MyLibsGeneral.