Skip to content

Commit 03fd406

Browse files
authored
✨ STM32F1 Timer (#129)
* 🚧 Rough-Draft of timer implementation * ✨ Implemented timer interface for callback functions - Added timer interface for stm32f1 series - Added a working demo for the stm32f1 timer - Added generic timer helper/interface for STM32 MCUs - Updated general_purpose_timer to use a manager Note: This is an unpolished, but working commit. Will improve it. * 🚧 Callback timer progress checkpoint - Updated demo to rename it and clean it up - Added new function to check if a specific interrupt vector is enabled - Improved and cleaned up commenting - Fixed schedule timing calculation to accomodate edge cases - Removed remnants of basic_timer to be added in separate PR - Moved some manager functions from protected to public * ✨ STM32F1 + STM32_Generic timer driver - Updated timer managers to track resource allocation. Prevents reusing of same timer for incompatible features such as callbacks & pwm. - Tested and working copy for both the callback functionality as well as pwm generation. * ✨ STM32 & STM32F1 Callback Timer - Updated and fixed documentation - Removed now redundant static pwm availability variable - Updated resource_count to just raw count instead of bit mask - Added reset_peripheral function to power.cpp
1 parent e19b4ca commit 03fd406

File tree

12 files changed

+1260
-502
lines changed

12 files changed

+1260
-502
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ libhal_test_and_make_library(
4848
src/stm32_generic/i2c.cpp
4949
src/stm32_generic/pwm.cpp
5050
src/stm32_generic/spi.cpp
51+
src/stm32_generic/timer.cpp
5152
src/stm32_generic/uart.cpp
5253

5354
# stm32f1

include/libhal-arm-mcu/interrupt.hpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,33 @@ inline void disable_interrupt(irq_enum auto p_irq)
294294
disable_interrupt(static_cast<irq_t>(p_irq));
295295
}
296296

297+
/**
298+
* @brief determine if a particular interrupt has been enabled.
299+
*
300+
* This is only to determine if that particular entry is enabled, it does not
301+
* care about what handler is inside.
302+
*
303+
* @param p_irq - irq to check.
304+
* @return true - the interrupt has been enabled.
305+
* @return false - the interrupt is disabled or is invalid.
306+
*/
307+
[[nodiscard]] bool is_interrupt_enabled(irq_t p_irq);
308+
309+
/**
310+
* @brief determine if a particular interrupt has been enabled.
311+
*
312+
* This is only to determine if that particular entry is enabled, it does not
313+
* care about what handler is inside.
314+
*
315+
* @param p_irq - irq to check.
316+
* @return true - the interrupt has been enabled.
317+
* @return false - the interrupt is disabled or is invalid.
318+
*/
319+
[[nodiscard]] inline bool is_interrupt_enabled(irq_enum auto p_irq)
320+
{
321+
return is_interrupt_enabled(static_cast<irq_t>(p_irq));
322+
}
323+
297324
/**
298325
* @brief determine if a particular handler has been put into the interrupt
299326
* vector table.
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright 2024 - 2025 Khalil Estell and the libhal contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#pragma once
16+
17+
#include <libhal-arm-mcu/interrupt.hpp>
18+
#include <libhal/functional.hpp>
19+
#include <libhal/initializers.hpp>
20+
#include <libhal/units.hpp>
21+
22+
namespace hal::stm32_generic {
23+
24+
/**
25+
* @brief Implements shared timer setup and control logic common to all STM32
26+
* series.
27+
*
28+
* This class provides the common functionality for timer configuration and
29+
* control, abstracting the parts of the timer interface that remain consistent
30+
* across different STM32 series. It is intended to be used by series-specific
31+
* implementations, which handle MCU-specific configuration details and pass
32+
* any required parameters to these generic functions.
33+
*/
34+
class timer final
35+
{
36+
public:
37+
/**
38+
* @brief Construct timer uninitialized
39+
*
40+
* The purpose of this is to send the settings through the initialize function
41+
* instead, because all the settings are series-specific. Therefore in the
42+
* series-specific implementations of the timer, the address is deduced from
43+
* the timer, as well as all the interrupt configuration is done, then they
44+
* are passed to initialize.
45+
*
46+
* If this constructor is used, it is unsafe to call any API of this class
47+
* before calling the `initialize()` API with the correct inputs. Once that
48+
* API has been called without failure, then the other APIs will become
49+
* available.
50+
*/
51+
timer(hal::unsafe);
52+
53+
/**
54+
* @brief Determine if the timer is currently running
55+
*
56+
* @return true - if a callback has been scheduled and has not been invoked
57+
* yet, false otherwise.
58+
*/
59+
[[nodiscard]] bool is_running();
60+
61+
/**
62+
* @brief Stops a scheduled event from happening.
63+
*
64+
* Does nothing if the timer is not currently running.
65+
*
66+
* Note that there must be sufficient time between the this call finishing and
67+
* the scheduled event's termination. If this call is too close to when the
68+
* schedule event expires, this function may not complete before the timer
69+
* interrupt is triggered.
70+
*/
71+
void cancel();
72+
73+
/**
74+
* @brief Schedule an interrupt to occur for this timer
75+
*
76+
* If this is called and the timer has already scheduled an event (in other
77+
* words, `is_running()` returns true), then the previous scheduled event will
78+
* be canceled and the new scheduled event will be started.
79+
*
80+
* If the delay time result in a tick period of 0, then the timer will execute
81+
* after 1 tick period. For example, if the tick period is 1ms and the
82+
* requested time delay is 500us, then the event will be scheduled for 1ms.
83+
*
84+
* If the tick period is 1ms and the requested time is 2.5ms then the event
85+
* will be scheduled after 2 tick periods or in 2ms.
86+
*
87+
* @param p_delay - the amount of time until the timer expires
88+
* @param p_timer_clock_frequency - the clock driving the timer
89+
* @throws hal::argument_out_of_domain - if p_delay cannot be achieved.
90+
*/
91+
void schedule(hal::time_duration p_delay, u32 p_timer_clock_frequency);
92+
93+
/**
94+
* @brief Initialize the timer with the series-specific settings
95+
*
96+
* This is where the constructed uninitialized timer gets initialized. It gets
97+
* all the series-specific settings passed to it that it needs, and it
98+
* handles them appropriately.
99+
*
100+
* @param p_peripheral_address - the address of the chosen timer peripheral
101+
* @param initialize_interrupts_function - the function needed to initialize
102+
* interrupts for the specific series stm32. For example, for the stm32f1
103+
* series, the function passed would be
104+
* `hal::stm32f1::initialize_interrupts()`.
105+
* @param p_irq - the irq number for the chosen timer
106+
* @param p_handler - the platform specific interrupt handler to be installed
107+
* @throws hal::device_or_resource_busy - if the timer interrupt vector is
108+
* already in use.
109+
*/
110+
void initialize(hal::unsafe,
111+
void* p_peripheral_address,
112+
void (*initialize_interrupts_function)(),
113+
cortex_m::irq_t p_irq,
114+
cortex_m::interrupt_pointer p_handler);
115+
116+
private:
117+
/// Stores the base address of the timer
118+
void* m_reg = nullptr;
119+
};
120+
} // namespace hal::stm32_generic

0 commit comments

Comments
 (0)