MyLibs 1.0
Расширенные библиотеки для STM32
Loading...
Searching...
No Matches
bench_time.h
Go to the documentation of this file.
1/**
2******************************************************************************
3* @file bench_time.h
4* @brief Заголовочный файл для измерения времени между событиями
5******************************************************************************
6* @addtogroup BENCH_TIME Time measurement
7* @brief Библиотека для измерения времени/тиков между событиями
8* @details
9Поддерживает:
10- Многоканальные измерения (несколько независимых таймеров)
11- Платформонезависимый интерфейс
12- Измерение в тиках или временных единицах
13- Статистику измерений (мин/макс/среднее)
14- Настраиваемый размер тиков для каждого канала
15
16Параметры для конфигурации:
17- @ref BENCH_TIME_ENABLE - Включить бенч времени
18- @ref BENCH_TIME_MAX_CHANNELS - Максимальное количество каналов измерения (по умолчанию 8)
19
20@par Пример использования:
21@code
22#include "bench_time.h"
23
24// Инициализация
25BenchTime_Init();
26
27// Измерение с SysTick
28BenchTime_Start(0, HAL_GetTick, 0xFFFFFFFF);
29some_function();
30uint32_t time = BenchTime_End(0, HAL_GetTick);
31
32// Измерение с TIM2 (16-бит)
33BenchTime_Start(1, TIM2->CNT, 0xFFFF);
34fast_function();
35uint32_t time2 = BenchTime_End(1, TIM2->CNT);
36
37// Измерение с DWT цикловым счетчиком
38BenchTime_Start(2, DWT->CYCCNT, 0xFFFFFFFF);
39critical_function();
40uint32_t cycles = BenchTime_End(2, DWT->CYCCNT);
41
42// Многоканальное измерение
43BenchTime_Start(0, HAL_GetTick, 1000); // общее время
44BenchTime_Start(1, TIM3->CNT, 500); // часть 1
45
46// ... код 1
47
48uint32_t part1 = BenchTime_End(1, TIM3->CNT);
49BenchTime_Start(2, TIM4->CNT, 200); // часть 2
50
51// ... код 2
52
53uint32_t part2 = BenchTime_End(2, TIM4->CNT);
54uint32_t total = BenchTime_End(0, HAL_GetTick); // общее время
55
56// Статистика
57uint32_t min_time = BenchTime_GetMin(0);
58uint32_t max_time = BenchTime_GetMax(0);
59uint32_t avg_time = BenchTime_GetAverage(0);
60uint32_t count = BenchTime_GetCount(0);
61@endcode
62* @{
63*****************************************************************************/
64#ifndef __BENCH_TIME_H_
65#define __BENCH_TIME_H_
66
67#include "mylibs_defs.h"
68#include <stdint.h>
69
70#ifdef BENCH_TIME_ENABLE
71
72// Конфигурация библиотеки
73#ifndef BENCH_TIME_MAX_CHANNELS
74#define BENCH_TIME_MAX_CHANNELS 8 ///< Максимальное количество каналов измерения
75#endif
76
77/**
78 * @brief Структура статистики измерений
79 */
80typedef struct {
81 uint32_t min_ticks; ///< Минимальное время в тиках
82 uint32_t max_ticks; ///< Максимальное время в тиках
83 uint32_t total_ticks; ///< Суммарное время в тиках
84 uint32_t count; ///< Количество измерений
85 uint32_t last_ticks; ///< Последнее измеренное время
86} BenchTimeStats_t;
87
88/**
89 * @brief Структура канала измерения
90 */
91typedef struct {
92 uint32_t start_tick; ///< Время старта в тиках
93 uint32_t tick_period; ///< Период тиков для переполнения
94 uint32_t is_running; ///< Флаг активного измерения
95 BenchTimeStats_t stats; ///< Статистика измерений
96} BenchTimeChannel_t;
97
98/**
99 * @brief Основная структура менеджера измерений
100 */
101typedef struct {
102 BenchTimeChannel_t channels[BENCH_TIME_MAX_CHANNELS]; ///< Каналы измерения
103} BenchTime_t;
104
105static BenchTime_t hbt = {0}; ///< Внутренний экземпляр
106
107/**
108 * @brief Инициализация системы измерения времени
109 */
110static inline void BenchTime_Init(void) {
111 for (int i = 0; i < BENCH_TIME_MAX_CHANNELS; i++) {
112 hbt.channels[i].start_tick = 0;
113 hbt.channels[i].tick_period = 0xFFFFFFFF;
114 hbt.channels[i].is_running = 0;
115 hbt.channels[i].stats.min_ticks = 0xFFFFFFFF;
116 hbt.channels[i].stats.max_ticks = 0;
117 hbt.channels[i].stats.total_ticks = 0;
118 hbt.channels[i].stats.count = 0;
119 hbt.channels[i].stats.last_ticks = 0;
120 }
121}
122
123/**
124 * @brief Начало измерения на указанном канале
125 * @param channel Номер канала (0..BENCH_TIME_MAX_CHANNELS-1)
126 * @param ticks Источник тиков (например: HAL_GetTick(), TIM2->CNT, DWT->CYCCNT)
127 * @param tick_period Период тиков для переполнения
128 * @return 1 - успех, 0 - ошибка
129 */
130static inline uint32_t BenchTime_Start(uint8_t channel, uint32_t ticks, uint32_t tick_period) {
131 if (channel >= BENCH_TIME_MAX_CHANNELS) return 0;
132 if (hbt.channels[channel].is_running) return 0;
133
134 hbt.channels[channel].start_tick = ticks;
135 hbt.channels[channel].tick_period = tick_period;
136 hbt.channels[channel].is_running = 1;
137 return 1;
138}
139
140/**
141 * @brief Окончание измерения на указанном канале
142 * @param channel Номер канала (0..BENCH_TIME_MAX_CHANNELS-1)
143 * @param ticks Источник тиков (должен быть тот же что в Start)
144 * @return Измеренное время в тиках, 0 - в случае ошибки
145 */
146static inline uint32_t BenchTime_End(uint8_t channel, uint32_t ticks) {
147 if (channel >= BENCH_TIME_MAX_CHANNELS) return 0;
148 if (!hbt.channels[channel].is_running) return 0;
149
150 uint32_t end_tick = ticks;
151 uint32_t start_tick = hbt.channels[channel].start_tick;
152 uint32_t tick_period = hbt.channels[channel].tick_period;
153 uint32_t elapsed_ticks;
154
155 if (end_tick >= start_tick) {
156 elapsed_ticks = end_tick - start_tick;
157 } else {
158 elapsed_ticks = (tick_period - start_tick) + end_tick + 1;
159 }
160
161 if (elapsed_ticks > tick_period) {
162 elapsed_ticks = tick_period;
163 }
164
165 hbt.channels[channel].is_running = 0;
166
167 // Обновление статистики
168 BenchTimeStats_t* stats = &hbt.channels[channel].stats;
169 stats->last_ticks = elapsed_ticks;
170
171 if (elapsed_ticks < stats->min_ticks) {
172 stats->min_ticks = elapsed_ticks;
173 }
174
175 if (elapsed_ticks > stats->max_ticks) {
176 stats->max_ticks = elapsed_ticks;
177 }
178
179 stats->total_ticks += elapsed_ticks;
180 stats->count++;
181
182 return elapsed_ticks;
183}
184
185/**
186 * @brief Получение минимального времени измерения
187 */
188static inline uint32_t BenchTime_GetMin(uint8_t channel) {
189 if (channel >= BENCH_TIME_MAX_CHANNELS) return 0;
190 return hbt.channels[channel].stats.min_ticks;
191}
192
193/**
194 * @brief Получение максимального времени измерения
195 */
196static inline uint32_t BenchTime_GetMax(uint8_t channel) {
197 if (channel >= BENCH_TIME_MAX_CHANNELS) return 0;
198 return hbt.channels[channel].stats.max_ticks;
199}
200
201/**
202 * @brief Получение среднего времени измерения
203 */
204static inline uint32_t BenchTime_GetAverage(uint8_t channel) {
205 if (channel >= BENCH_TIME_MAX_CHANNELS) return 0;
206 BenchTimeStats_t* stats = &hbt.channels[channel].stats;
207 if (stats->count == 0) return 0;
208 return stats->total_ticks / stats->count;
209}
210
211/**
212 * @brief Получение количества измерений
213 */
214static inline uint32_t BenchTime_GetCount(uint8_t channel) {
215 if (channel >= BENCH_TIME_MAX_CHANNELS) return 0;
216 return hbt.channels[channel].stats.count;
217}
218
219/**
220 * @brief Получение последнего измеренного времени
221 */
222static inline uint32_t BenchTime_GetLast(uint8_t channel) {
223 if (channel >= BENCH_TIME_MAX_CHANNELS) return 0;
224 return hbt.channels[channel].stats.last_ticks;
225}
226
227/**
228 * @brief Сброс статистики для канала
229 */
230static inline void BenchTime_ResetStats(uint8_t channel) {
231 if (channel >= BENCH_TIME_MAX_CHANNELS) return;
232 BenchTimeStats_t* stats = &hbt.channels[channel].stats;
233 stats->min_ticks = 0xFFFFFFFF;
234 stats->max_ticks = 0;
235 stats->total_ticks = 0;
236 stats->count = 0;
237 stats->last_ticks = 0;
238}
239#else //BENCH_TIME_ENABLE
240
241#define BenchTime_Init()
242#define BenchTime_Start(channel, ticks, tick_period) 0
243#define BenchTime_End(channel, ticks) 0
244#define BenchTime_GetMin(channel) 0
245#define BenchTime_GetMax(channel) 0
246#define BenchTime_GetAverage(channel) 0
247#define BenchTime_GetCount(channel) 0
248#define BenchTime_GetLast(channel) 0
249#define BenchTime_ResetStats(channel)
250
251#endif //BENCH_TIME_ENABLE
252
253#endif // __BENCH_TIME_H_
254
255/** BENCH_TIME
256 * @}
257 */
#define BENCH_TIME_MAX_CHANNELS
Максимальное количество каналов измерения
Заголочный файл для дефайнов библиотеки MyLibsGeneral.