-
Notifications
You must be signed in to change notification settings - Fork 935
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
initial support for avr #2273
initial support for avr #2273
Conversation
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.
Nice, thanks for the PR! 🚀
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.
Just one thing, could you add this to ci.sh so that it gets built for PRs?
The executor is polling in a hot loop. Is there an AVR equivalent of the "wait for interrupt" instruction? If so, it'd be good to use it. It helps both power consumption, and latency/jitter. |
seems like there are some sleep modes(MCUCR) how does it exit from wfi mode? |
7e9d7e2
to
189057b
Compare
got some problem here on ci/build |
As long as as you haven't changed the sleep mode select register, it should wake up on any interrupt: https://microchipdeveloper.com/xwiki/bin/view/products/mcu-mpu/8-bit-avr/structure/sleep/ So an implementation similar to riscv should work: But interrupts must be enabled before calling sleep so I don't think critical_section can be used: I did a quick test based on the riscv implementation and this documentation in avrsim and it seem to work: pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
init(self.inner.spawner());
loop {
unsafe {
self.inner.poll();
avr_device::interrupt::disable();
if SIGNAL_WORK_THREAD_MODE.load(Ordering::SeqCst) {
SIGNAL_WORK_THREAD_MODE.store(false, Ordering::SeqCst);
avr_device::interrupt::enable();
} else {
// sleep must be preceded by sei because the instruction after sei is guaranteed to run before any interrupts
// can happen. So keep them together.
avr_device::interrupt::enable();
avr_device::asm::sleep();
}
}
}
} A caveat is that the SEN bit must have been set previously: let mut dp = arduino_hal::Peripherals::take().unwrap();
dp.CPU.smcr.write(|w| w.se().set_bit()); This is defined separately in atmega and attiny so it's not generic for all AVR, which makes it a bit of a bummer. Also various AVR documentation recommend to set and unset the SEN bit before and after the sleep instruction. But from what I've been able to read it's just to avoid "accidentally" entering sleep by the programmer. So it seems like a waste of cycles to me. I'm not an experienced AVR developer so perhaps someone with a deeper knowledge could chime in. Potentially bigger power savings could be made by setting a deeper sleep mode depending on what interrupts are used in the application. |
@janderholm |
It should be fine. Waking from idle should take 4 clock cycles before servicing the interrupt. https://microchipdeveloper.com/xwiki/bin/view/products/mcu-mpu/8-bit-avr/structure/sleep/ |
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.
LGTM!
- Can you fix CI?
- Can you rebase, so no merge commits show up in the git history?
Thanks!
i decided to not touch interrupt or se bit, this makes user decide weather to use sleep or not |
just going with @janderholm 's solution i think it might get too complex if i try to keep interrupt state |
Yeah unfortunately sei has to be used just before sleep. For future reference there is another trick where you let __pender just clear the se bit. That way the sleep instruction is a no-op. Then you can set the se bit just before poll and it will go to sleep after handling all waiting tasks if __pender is not executed again. But it's not clear that is any better since you need to set both se and sm at the same time and the implementation is chip dependent I think. |
@djdisodo please make CI check the AVR build, don't remove it. If it needs nightly you can put it in |
@djdisodo I would really much like to try this out. However being a rust / embassy newbie I'm having hard time setting up the project. Could you please make the example (main.rs + Cargo.toml) available in some other form than as a screenshot? |
@karioja sorry for being late, maybe i put the wrong hyperlink here's what i intended for example i'll be updating the example soon, but here's what i've been working on now it's not finished tho.. timer and serial driver might have some performance issue (it ended up being overly complicated) |
Hey, if anyone's interested I've also been playing around with embassy on avr devices, I have a project here which is some firmware for flashlights: https://github.com/simmsb/tyrfing |
would be great if we had spi and i2c driver |
initial support for avr
tested
embassy_time driver for avr
example