libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
stm32_timebase.cpp
1#include "stm32_timebase.hpp"
2
3using namespace LibXR;
4
5namespace
6{
7enum class STM32TimebaseBackend : uint8_t
8{
9 SYSTICK = 0,
10 TIMER = 1,
11};
12
13STM32TimebaseBackend g_backend = STM32TimebaseBackend::SYSTICK;
14
15MicrosecondTimestamp GetSysTickMicroseconds()
16{
17 do
18 {
19 const uint32_t tick_before = HAL_GetTick();
20 const uint32_t counter_before = SysTick->VAL;
21 // 读取挂起位,不通过 CTRL 读取并清除 COUNTFLAG。
22 // Read the pending bit without reading and clearing COUNTFLAG through CTRL.
23 const bool pending = (SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) != 0U;
24 const uint32_t counter_after = SysTick->VAL;
25 const uint32_t tick_after = HAL_GetTick();
26 if (tick_before != tick_after)
27 {
28 continue;
29 }
30
31 const bool crossed_zero =
32 counter_before != 0U && (counter_after == 0U || counter_after > counter_before);
33 uint32_t logical_tick = tick_after + static_cast<uint32_t>(pending || crossed_zero);
34 const uint64_t period_counts = static_cast<uint64_t>(SysTick->LOAD) + 1U;
35 uint64_t fraction = 0U;
36 if (counter_after != 0U)
37 {
38 fraction = 1000U - static_cast<uint64_t>(counter_after) * 1000U / period_counts;
39 if (fraction == 1000U)
40 {
41 ++logical_tick;
42 fraction = 0U;
43 }
44 }
45 return MicrosecondTimestamp(static_cast<uint64_t>(logical_tick) * 1000U + fraction);
46 } while (true);
47}
48
49#ifdef HAL_TIM_MODULE_ENABLED
50MicrosecondTimestamp GetTimerMicroseconds(TIM_HandleTypeDef* htim)
51{
52 DEV_ASSERT(htim != nullptr);
53
54 do
55 {
56 const uint32_t tick_before = HAL_GetTick();
57 const uint32_t counter_before = __HAL_TIM_GET_COUNTER(htim);
58 const bool pending = __HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != 0U;
59 const uint32_t counter_after = __HAL_TIM_GET_COUNTER(htim);
60 const uint32_t tick_after = HAL_GetTick();
61 if (tick_before != tick_after)
62 {
63 continue;
64 }
65
66 const bool period_elapsed = pending || counter_after < counter_before;
67 const uint32_t logical_tick = tick_after + static_cast<uint32_t>(period_elapsed);
68 const uint64_t period_counts =
69 static_cast<uint64_t>(__HAL_TIM_GET_AUTORELOAD(htim)) + 1U;
70 const uint64_t fraction =
71 static_cast<uint64_t>(counter_after) * 1000U / period_counts;
72 return MicrosecondTimestamp(static_cast<uint64_t>(logical_tick) * 1000U + fraction);
73 } while (true);
74}
75
76#endif
77} // namespace
78
80{
81 ConfigureWrapRange(static_cast<uint64_t>(UINT32_MAX) * 1000ULL + 999ULL, UINT32_MAX);
82 g_backend = STM32TimebaseBackend::SYSTICK;
83 SetReady();
84}
85
87{
88 switch (g_backend)
89 {
90 case STM32TimebaseBackend::SYSTICK:
91 return GetSysTickMicroseconds();
92#ifdef HAL_TIM_MODULE_ENABLED
93 case STM32TimebaseBackend::TIMER:
94 return GetTimerMicroseconds(STM32TimerTimebase::htim);
95#endif
96 }
97
98 DEV_ASSERT(false);
99 return MicrosecondTimestamp(0ULL);
100}
101
102MillisecondTimestamp Timebase::GetMilliseconds() { return HAL_GetTick(); }
103
104#ifdef HAL_TIM_MODULE_ENABLED
105
106TIM_HandleTypeDef* STM32TimerTimebase::htim = nullptr;
107
109{
110 ASSERT(timer != nullptr);
111
112 htim = timer;
113 ConfigureWrapRange(static_cast<uint64_t>(UINT32_MAX) * 1000ULL + 999ULL, UINT32_MAX);
114 g_backend = STM32TimebaseBackend::TIMER;
115 SetReady();
116}
117
118#endif
微秒时间戳 / Microsecond timestamp
毫秒时间戳 / Millisecond timestamp
STM32Timebase()
默认构造函数 / Default constructor
STM32TimerTimebase(TIM_HandleTypeDef *timer)
构造函数 / Constructor
static TIM_HandleTypeDef * htim
硬件定时器句柄静态指针 / Static pointer to timer handle
static void ConfigureWrapRange(uint64_t max_valid_us, uint32_t max_valid_ms) noexcept
配置时间戳回绕上界。 Configure the timestamp wraparound limits.
Definition timebase.hpp:95
static void SetReady(bool ready=true) noexcept
设置时间基就绪状态。 Set the timebase ready flag.
Definition timebase.hpp:85
static MicrosecondTimestamp GetMicroseconds()
获取当前时间的微秒级时间戳。 Gets the current timestamp in microseconds.
static MillisecondTimestamp GetMilliseconds()
获取当前时间的毫秒级时间戳。 Gets the current timestamp in milliseconds.
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14