-
Notifications
You must be signed in to change notification settings - Fork 943
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
rp2040: rtc support #3398
base: dev
Are you sure you want to change the base?
rp2040: rtc support #3398
Conversation
src/machine/machine_rp2040-rtc.go
Outdated
|
||
// Enable the IRQ at the proc | ||
interrupt.New(rp.IRQ_RTC_IRQ, rtcHandleInterrupt).Enable() | ||
irqSet(rp.IRQ_RTC_IRQ, true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really needed?
I see this pattern of interrupt.New().Enable()
followed by irqSet()
across rp2040 related code.
Yet, it works w/o irqSet()
call too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aykevl what would be your understanding?
If this irqSet
is indeed not needed in such cases, I could make a PR that cleans this in RP2040 machine.
src/machine/machine_rp2040-rtc.go
Outdated
rtc.clkDivM1.Set(rtcFreq) | ||
} | ||
|
||
func (rtc *rtcType) SetTime(t RtcTime) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this accept time.Time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd love to. Unfortunately, that makes a cycle:
package github.com/tinygo-org/tinygo/src/examples/rtc
imports machine
imports time
imports runtime
imports machine: import cycle not allowed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd go for a SetDate
function that follows the stdlib format of creating a new date (excluding the loc).
This would probably make it more natural to use than with a machine specific type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check this out, it might be a way of solving this cyclical dependency problem given that we all agree it's time the machine package had it's own Time type.
machine/time.go
type Time struct {
// Same fields as time.Time
}
func (rtc *RTC) SetTime[T ~Time](t T) error {
// do the setting.
}
time/time.go
// replace contents of time.Time type.
type Time machine.Time
I have no idea of the far reaching consequences of this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've actually made an alternative PR #3403 that sets RTC interrupt with a delay instead of actual time. Probably, that's better than such tricks.
src/machine/machine_rp2040-rtc.go
Outdated
|
||
// --- | ||
|
||
type RtcTime struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this only be used for setting alarms? For get/set time, use time.Time instead?
Also, how generic is this - should it be in a top-level rtc.go
, or is it rp2040 specific?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't use time.Time
, unfortunately. See above.
This implementation is RP2040 specific.
We don't have any API for RTC as of yet (nRF family uses it, but does not expose, probably others too).
So the idea was we can try and make it for RP2040 first and generalise once we have at least two families exposing RTC?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I... really don't like that chip vendors think they can implement the Gregorian calendar in hardware. Because they can't:
- It does not deal with timezones or daylight saving time at all.
- As admitted in the datasheet, it doesn't correctly deal with the leap century. Admittedly that's rather rare (we're not due for another 77 years) but it shows that this kind of thing is difficult.
- It does not verify the day of the week.
- This is really something that only the UI should do. Most time protocols (like NTP) only deal with Unix time, which is a plain and simple number. It only adds complexity and bugs between systems that deal with Unix time and systems that attempt to use the Gregorian calendar.
Anyway, that's my view on this and kind of besides the point of this PR.
But regarding this specific PR: it implements a new API for the machine package which I don't want to add without getting it right. So I suggest making a PR to tinygo-site, see tinygo-org/tinygo-site#317 for example (content/docs/reference/machine.md is the important part, the rest is optional). That way, it's easier to see what it is doing. And we'd need to document the API anyway so better do it right from the start.
Example output
This is all due to the fact RTC returns seconds precision and the loop iteration takes slightly more than a second (1 second and ~800µs to be precise). Both clocks have exactly same value internally, they run from the same source (XOSC). The accumulated error is immediately visible in the value of the system clock (µs precision) and is not visible until it adds up to more than a second in RTC case. The moment error accumulates to a whole second, the output jumps two seconds for both SYS and RTC. Confirmed by letting the (slightly modified) example run for 20 minutes:
I shall probably modify the example and remove the confusing DIFF output. |
If possible I would not expose a If we do not create a Same for Last Point: If you we do choose to keep |
Real Time Clock on RP2040.
Probably, not very useful by itself, but the ability to fire a scheduled interrupt enables us to support RTC-governed Deep Sleep and Dormant states later.