-
Notifications
You must be signed in to change notification settings - Fork 237
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
Interrupts on RISC-V #847
base: main
Are you sure you want to change the base?
Interrupts on RISC-V #847
Conversation
4c95771
to
03e56ec
Compare
We might want to block this until we've written a new interrupt macro that works like the cortex-m-rt macro and does the static mut transform and type-checks the function signature. |
rp235x-hal/src/arch.rs
Outdated
#[no_mangle] | ||
#[allow(non_snake_case)] | ||
unsafe fn DefaultIrqHandler() { | ||
panic!(); |
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.
cortex_m does not panic but loop {}
in the default handler.
It did panic for a short while in the past, but that was reverted here: https://github.com/rust-embedded/cortex-m-rt/pull/289/files#diff-b1a35a68f14e696205874893c07fd24fdb88882b47c23cc0e0c80a30c7d53759L993
I'm not sure if the reasons for that decision also apply for RISC-V, but at least for the rp2040/rp235x case it would be nicer if both implementations did the same.
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'll fix this
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.
Changed it to spin
As the rp235x is a multi-core processor, and given that rust-embedded/cortex-m#411 indicates that the transformation made by cortex-m-rt is unsound on multi-core systems, I don't think we should just copy it. Is there a good way to make the transform safe on rp235x? Taking a full critical section on each interrupt entry is probably too expensive? |
So I guess the risk is that both CPUs enter the same interrupt handler at the same time. If one peripheral interrupt signal is unmasked on both CPUs, that could happen. So perhaps the fix is to design the interrupt API to make that impossible (like a bitmask in a static atomic or the watchdog scratch that records which cpu has which interrupt enabled). Or we could ensure that if you enter an interrupt on Core A, it is masked for the duration on Core B - which is nicer than turning all interrupts off or holding a spin lock. But given 2040 has the same problem the question is whether we want to fix it here or make a plan and fix it later. |
The user already unmasks the interrupt, and that operation is unsafe. It is almost certainly a bug if they do so on both cores, and we have had no reports of people doing this accidentally. Until someone comes has a use-case where having both cores handle an interrupt is beneficial, I think trying to solve this is not a good use of our time. My opinion is we should document "don't do this" and move on with our lives |
That's an option, I just wouldn't want to spend time on porting the macro only to remove it again later.
Are there situations where it's not avoidable? Any non maskable interrupts or exceptions? |
But to be honest, there's a second thing I dislike about the interrupt macro, so I'm biased. For me, it's totally non-obvious that the macro annotation changes the code inside the function.
I always feel like the usage of the variable doesn't match the declaration. This was very confusing when I was new to embedded rust, and it still sometimes surprises me. Therefore I'd prefer something more obvious. Perhaps a macro directly on the static mut?
Probably needs an Back to topic: Personally I'd merge the PR as it is, and not wait for an (That said, if someone ported |
BTW, do I understand |
For the rp2040, we could use separate vector tables for core0 and core1, and let the macro create two distinct functions with their own statics, so even if an interrupt was actually running on both cores at the same time, it would not access the same data.
The second core to run this interrupt would always get a |
I think the UART interrupt is cleared by reading the FIFO which can happen before the ISR ends. So it could re-fire before the ISR ends. Not sure either Interrupt Controller can avoid that. |
What do we want to do with this? There's been some changes over in riscv-rt since. |
I'd like to see interrupts working on risc-v and willing to work on this if you'd like. That |
1) Use the Machine Timer, not the cycle counter 2) Use the hal::arch module to control interrupts 3) Write a MachineExternal interrupt handler which asks Xh3irq which interrupt to run next, and then runs it. Note: we lose the macros that do that static-mut hack for us. Maybe we can add that back in later.
We don't mention NVIC in the examples, because in RISC-V mode the interrupt controller is the Xh3irq. Unless its the vector-table example, which only works on Arm currently.
I switched to the ADC FIFO IRQ so that the index and the bit number would be different.
4fd6e7d
to
e2b3113
Compare
I rebased and took out any use of the unsound static-mut conversion. Now the interrupts just run in a critical section. Not yet tested on hardware. |
Also it doesn't need to be unsafe.
) Adds an Xh3irq controller driver
) Adds a default
MachineExternal
handler which uses the Xh3irq to run whichever interrupts are pending) Adds a bunch of interrupt control stuff to
hal::arch
) Fixes the
powman_test
example to use the new interrupt APIs - it now works on RISC-V and Arm.Tested
powman_test
on a Pico 2 in bothriscv32imac-unknown-none-elf
andthumbv8m.main-none-eabihf
.