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

sam0/rtc_rtt: optimizations to get around the painful long syncwaits #18920

Merged
merged 2 commits into from
Nov 22, 2022

Conversation

jue89
Copy link
Contributor

@jue89 jue89 commented Nov 16, 2022

Contribution description

Instead of blocking until a alarm is set, we just trust that the alarm gets propagated down to the peripheral asynchronously.

Testing procedure

TBD

Issues/PRs references

#18883

@jue89 jue89 added Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Area: cpu Area: CPU/MCU ports labels Nov 16, 2022
@github-actions github-actions bot added the Platform: ARM Platform: This PR/issue effects ARM-based platforms label Nov 16, 2022
_rtt_clear_alarm();

/* make sure that preceding changes have been applied */
_wait_syncbusy();
Copy link
Contributor

@kaspar030 kaspar030 Nov 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's how it works. You need to sync before reading or writing, otherwise the call (and peripheral bus) blocks. I got confused

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I sync before I'm writing.

The current master syncs after writing to the ALARM/COMP register.

Or am I misunderstanding something here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, so the reference manual says:

When executing an operation that requires synchronization, the Synchronization Busy bit in the Status register
(STATUS.SYNCBUSY) will be set immediately, and cleared when synchronization is complete. The Synchronization
Ready interrupt can be used to signal when synchronization is complete. This can be accessed via the Synchronization
Ready Interrupt Flag in the Interrupt Flag Status and Clear register (INTFLAG.SYNCRDY).
If an operation that requires synchronization is executed while STATUS.SYNCBUSY is one, the bus will be stalled. All
operations will complete successfully, but the CPU will be stalled and interrupts will be pending as long as the bus is
stalled.

So the reason to sync after writing the register is to not have a consecutive call stall the bus.
But, if waiting before writing the register, the waiting can be skipped if no operation is in progress.

The following bits need synchronization when written:

- Software Reset bit in the Control register (CTRL.SWRST)
- Enable bit in the Control register (CTRL.ENABLE)

The following registers need synchronization when written:

- The Counter Value register (COUNT)
- The Clock Value register (CLOCK)
- The Counter Period register (PER)
- The Compare n Value registers (COMPn)
- The Alarm n Value registers (ALARMn)
- The Frequency Correction register (FREQCORR)
- The Alarm n Mask register (MASKn)

Write-synchronization is denoted by the Write-Synchronization property in the register description.

The following registers need synchronization when read:
- The Counter Value register (COUNT)
- The Clock Value register (CLOCK)

Read-synchronization is denoted by the Read-Synchronization property in the register description.

Seems like the MODE2.INTENCLR register is not part of this

(I had it the wrong way in my head, I thought you'd need to sync the clock, then there'd be a time window where an op (read/write) can complete.)

Copy link
Contributor Author

@jue89 jue89 Nov 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, we cloud skip the _wait_syncbusy() because the write will sync us anyway?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, when we don't do the active _wait_syncbusy(), we risk blocking all ISRs and the whole AHB.

rtc_set_alarm() / rtt_set_alarm() are heavily used by ztimer during ISR. This will reduce time spent during ISR drastically. We trust that the peripheral is able to propagate the alarm asynchronously.
@riot-ci
Copy link

riot-ci commented Nov 17, 2022

Murdock results

✔️ PASSED

268bdfe sam0/rtc_rtt: don't block until set_alarm has been propagated to periph

Success Failures Total Runtime
117848 0 117848 01h:58m:29s

Artifacts

This only reflects a subset of all builds from https://ci-prod.riot-os.org. Please refer to https://ci.riot-os.org for a complete build for now.

@jue89
Copy link
Contributor Author

jue89 commented Nov 22, 2022

I took the branch from #18795 and made some measurements:

Without this PR

USEMODULE=debug_irq_disable make -C tests/ztimer_msg BOARD=samr30-xpro flash term
(...)
2022-11-22 17:35:46,686 # irq disabled for 344 ticks in sys/ztimer/core.c:189
2022-11-22 17:35:46,693 # irq disabled for 156 ticks in core/mutex.c:198
2022-11-22 17:35:46,700 # irq disabled for 348 ticks in sys/ztimer/core.c:189
2022-11-22 17:35:46,708 # irq disabled for 4499 ticks in sys/ztimer/core.c:120
2022-11-22 17:35:46,717 # irq disabled for 3430 ticks in sys/ztimer/periph_rtt.c:62
2022-11-22 17:35:46,724 # irq disabled for 212 ticks in core/msg.c:176
2022-11-22 17:35:46,731 # irq disabled for 343 ticks in sys/ztimer/core.c:189
(...)

With this PR merged on top

USEMODULE=debug_irq_disable make -C tests/ztimer_msg BOARD=samr30-xpro flash term
(...)
2022-11-22 17:39:56,957 # irq disabled for 340 ticks in sys/ztimer/core.c:189
2022-11-22 17:39:56,964 # irq disabled for 156 ticks in core/mutex.c:198
2022-11-22 17:39:56,972 # irq disabled for 342 ticks in sys/ztimer/core.c:189
2022-11-22 17:39:56,980 # irq disabled for 614 ticks in sys/ztimer/core.c:120
2022-11-22 17:39:56,988 # irq disabled for 219 ticks in sys/ztimer/periph_rtt.c:62
2022-11-22 17:39:56,995 # irq disabled for 215 ticks in core/msg.c:176
2022-11-22 17:39:57,002 # irq disabled for 342 ticks in sys/ztimer/core.c:189
(...)

Yay, I guess :-)

Copy link
Contributor

@benpicco benpicco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
That makes periph_rtt a vialble ZTIMER backend on sam0 - I might be able to drop the ztimer_no_periph_rtt after all 😃

(still have to solve the Deep Sleep issue).

I also tested this on samr21-xpro (since the old sam0 generation often was a bit special wrt RTT) but works fine in both tests/periph_rtt and tests/periph_rtc.

@jue89
Copy link
Contributor Author

jue89 commented Nov 22, 2022

Thank you both for reviewing and testing this PR. I reduces pain on our side, as well :-)

@jue89 jue89 merged commit 97bc825 into RIOT-OS:master Nov 22, 2022
@jue89 jue89 deleted the fix/sam0_rtt_rtc branch November 22, 2022 17:12
@kaspar030 kaspar030 added this to the Release 2023.01 milestone Jan 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: cpu Area: CPU/MCU ports CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ARM Platform: This PR/issue effects ARM-based platforms Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants