Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor timer taxonomy #495

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

honzasp
Copy link
Contributor

@honzasp honzasp commented Jun 26, 2024

This PR accompanies embassy-rs/embassy#3123. It simplifies the register definitions for timers, unifies the naming of timers and supports the type-safe timer taxonomy from that PR.

However, as a necessary trade-off, it exposes registers and register fields for all channels even for timers that don't have the full number of channels: for example, all four CCR registers are exposed for Tim1ch. The idea here is that Tim1ch represents a timer that is at least as capable as a 1-channel timer, but might have up to 4 channels. For example, this allows us to implement a PWM driver that works for all timers with channels (it requires only the functionality of Tim1ch), but still supports up to 4 channels for timers that have them (so it can be used with Tim4ch or TimAdv2ch).

The idea is that the higher-level code ensures that only the available channels are used. For example, the SimplePwm driver ensures this by accessing only those channels that correspond to pins that belong to the timer peripheral: if there is a pin for channel 3, then the timer surely supports channel 3!

@honzasp
Copy link
Contributor Author

honzasp commented Jun 26, 2024

Marked as draft because I want to double-check that I didn't introduce any unintentional breakage (in particular in the v2 and l0 versions).

@honzasp honzasp marked this pull request as ready for review June 29, 2024 12:36
@embassy-ci
Copy link

embassy-ci bot commented Jun 29, 2024

@embassy-ci
Copy link

embassy-ci bot commented Jun 29, 2024

honzasp added a commit to honzasp/stm32-data-generated that referenced this pull request Jun 29, 2024
@honzasp
Copy link
Contributor Author

honzasp commented Jun 29, 2024

This PR should now be ready for review ✔️

@Dirbaio
Copy link
Member

Dirbaio commented Jul 24, 2024

However, as a necessary trade-off, it exposes registers and register fields for all channels even for timers that don't have the full number of channels: for example, all four CCR registers are exposed for Tim1ch. The idea here is that Tim1ch represents a timer that is at least as capable as a 1-channel timer, but might have up to 4 channels. For example, this allows us to implement a PWM driver that works for all timers with channels (it requires only the functionality of Tim1ch), but still supports up to 4 channels for timers that have them (so it can be used with Tim4ch or TimAdv2ch).

can't you already do this by unsafely casting a Tim1ch to a Tim4ch? For example, when you construct a SimplePwm, store it in self as a Tim4ch but record either in a field or in the type that it actually had only 1 ch, then avoid using the higher channels.

IMO this is better than changing the registers to allow 4ch in the 1ch timers, because:

There's 2 kinds of users of the PAC:

  • HAL authors, writing generic code over all timers
  • end users, using raw register access with one particular timer instance.

increasing the number of channels impacts end users (they can accidentally try using channels that don't exist), while requiring unsafe casting impacts only HAL authors, which are likely more "sophisticated" users.

@honzasp
Copy link
Contributor Author

honzasp commented Jul 30, 2024

can't you already do this by unsafely casting a Tim1ch to a Tim4ch? For example, when you construct a SimplePwm, store it in self as a Tim4ch but record either in a field or in the type that it actually had only 1 ch, then avoid using the higher channels.

Sure, it's possible to treat any general-purpose timer as a Tim4ch, but the disadvantage is that Tim4ch gives you access to many registers and fields that are not available in Tim1ch and Tim2ch.

increasing the number of channels impacts end users (they can accidentally try using channels that don't exist), while requiring unsafe casting impacts only HAL authors, which are likely more "sophisticated" users.

I agree that this change makes life slightly harder for people who use this crate directly, but it should make life significantly easier for people who use Embassy.

In the current situation, we protect end users of the PAC crate from using non-existent channels in a timer (i.e., if they try to use channel 3 in a 2-channel timer, they get a compile-time or a runtime error), but we don't protect end users of Embassy from using the wrong timer type (e.g., if they try to use CountingMode::EdgeAlignedDown with a 2-channel timer, they get no error).

With the proposed changes, we won't be able to protect the users of the PAC from using more channels, but we will be able to ensure that users of Embassy use timer peripherals that actually support all operations that they need.

In my opinion, it's a good trade-off: it's quite simple to understand that a 2-channel timer has only two channels, but understanding all types of STM32 timers and their features takes a few days of detailed studying of reference manuals.

@embassy-ci
Copy link

embassy-ci bot commented Oct 10, 2024

honzasp added a commit to honzasp/stm32-data-generated that referenced this pull request Oct 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants