Skip to content

Conversation

@hierophect
Copy link
Collaborator

@hierophect hierophect commented Jul 23, 2021

This draft PR outlines the requirements for a SAMD51 implementation of the Alarm module, with instructions for light sleep, deep sleep, fake sleep, PinAlarms and TimeAlarms. I've outlined recommendations for what modules should be used where, along with relevant sections from the datasheet, in this git gist. I haven't added much in the way of actual port-specific implementation, to make it more clear what code is generic/universal, and to avoid design errors that I don't have the bandwidth to fix. Hopefully we can collectively fill this out into a real module!

Short version of notes:

  • Light sleep should use Idle Mode, Deep sleep should use Backup Mode
  • PinAlarms should use a PORT/EVSYS implementation (might already be covered by peripherals/external_interrupts) for light sleep, and the RTC->TAMPER system for deep sleep
  • TimeAlarms can use the COMPARE system for both forms of sleep
  • The alarm wake flag can be stored in the Backup Register bank
  • When we get around to sleep memory, it should be implemented with PDBKUPRAM

Ping for @maholli, @dxstp, @PranavMKrishnan, who were interested in helping contribute. This PR can be pushed to by setting a new remote or with the Github CLI tool, gh pr checkout 5048 -R adafruit/circuitpython.

When completed, this will resolve #4837. See issue for further diagrams/discussion

@hierophect
Copy link
Collaborator Author

Discord question from @maholli (paraphrased)

What is the issue described with callbacks / why is the _port_interrupt_after_ticks not sufficient for TimeAlarm?

When the timer alarm goes off when the device is not in deep sleep (so either in light sleep, or fake deep sleep), it needs to call a function that will set the TimeAlarm static variable woke_up to True. In the STM32 HAL, it's possible to either register a specific function that is called when the ISR occurs, or to use a generic function name provided by the HAL which does so automatically. But I'm not sure how to do this for SAMD - I think the timer code used in port.c for _port_interrupt_after_ticks is very close, but it merely sets the interrupt without any callback function.

To explain why we need this: there is a version of STATIC volatile bool woke_up; for both TimeAlarm and PinAlarm. This variable is set when the respective alarm goes off, and is checked by the functions alarm_X_Xalarm_woke_this_cycle. This is required because when the chip is not in deep sleep, there are other things that can wake it up - USB interrupts, communication interrupts, all kinds of stuff, but we don't want any of those to fully restart the chip, just the alarm interrupt. If it's not an alarm, it should just wake, service it, and go back to sleep - these callbacks and woke_up functions are required to implement that. Having a variable for each alarm type also makes it easy to detect what alarm actually woke from sleep, so the relevant alarm object can be returned more easily.

@tannewt
Copy link
Member

tannewt commented Aug 31, 2021

Closing this since no one is actively working on it. The branch and code will remain available to anyone who wants to pick this up.

@tannewt tannewt closed this Aug 31, 2021
@maholli
Copy link

maholli commented Aug 31, 2021

@tannewt happy to leave this closed if it helps organization-wise, but we are still chipping away at it.

In fact, @dxstp just provided some tremendous SAMD/E low power insight over in the gist -- Thank you!

@tannewt
Copy link
Member

tannewt commented Aug 31, 2021

Awesome! I look forward to a new PR from you. Glad this one helped get you started.

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.

Extend deep sleep capability to SAMD port

3 participants