-
Notifications
You must be signed in to change notification settings - Fork 984
fix(rp2350): add software spinlocks #5034
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
base: release
Are you sure you want to change the base?
Conversation
Writing to the UART takes time and that may not be a good idea inside an interrupt, but it is essential for debugging sometimes (especially since USB-CDC typically doesn't work inside an interrupt). This fixes UART support in interrupts for the RP2040 at least. You can test it with `-serial=uart` and connecting a USB-UART adapter to the right pins.
…he first error is returned In some cases, e.g nothing connected on the bus, repeated resume-stop sequences can lead to the bus never reaching the stop state, hanging Tx. This change ensures the resume-stop sequence is submitted once on error. It also moves the error code read to before the sequence to ensure it's valid. Fixes: tinygo-org#4998
Oh, whoops. My go fmt extension has been flaking out on me. Will have the missing rp2040 imports updated in a moment. Here's the lock/unlock disassembled output with inlining disabled:
|
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 support the switch to atomic instructions, but if you need something that works right away, RP2350-E2 mentions that some spinlocks are not affected:
The following SIO spinlocks can be used normally because they don’t alias with writable registers: 5, 6, 7,
10, 11, and 18 through 31. Some of the other lock addresses may be used safely depending on which of
the high-addressed SIO registers are in use.
Locks 18 through 24 alias with some read-only TMDS encoder registers, which is safe as only writes are
mis-decoded.
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.
See my comment below.
Also,
Another thing I noticed in that section, they also always disable interrupts when the spinlocks are being held, we may want to do the same: [...]
The runtime does this in various places if needed. The spinlock implementation doesn't need to disable interrupts too.
Thank you for tracking those down. I figured there would probably be some, but I couldn't find them |
…tests that use Chromium headless browser to avoid use of older incompatible version. Signed-off-by: deadprogram <ron@hybridgroup.com>
…wser used for running the wasm tests. Also add favicon link to avoid extra fetches during test runs. Signed-off-by: deadprogram <ron@hybridgroup.com>
With these flags, the TinyGo binary gets 18.8MB (11.6%) smaller. That seems like a quite useful win for such a small change! This is only for Linux for now. MacOS and Windows can be tested later, the flags for those probably need to be modified. Originally inspired by: https://discourse.llvm.org/t/state-of-the-art-for-reducing-executable-size-with-heavily-optimized-program/87952/18 There are some other flags like -Wl,--pack-dyn-relocs=relr that did not shrink binary size in my testing, so I've left them out. This also switches the linker to prefer mold or lld over the default linker, since the system linker is usually ld.bfd which is very slow. (Also, for some reason mold produces smaller binaries than lld).
The revive command seems to have had a syntax error in the file input glob. It appears to have been broken in a way that did not result in a return code being set. This change uses 'find' to build the input to the linter. Note that it is expected to fail the CI script, because it is uncovering some existing lint issues that were not being caught.
Signed-off-by: deadprogram <ron@hybridgroup.com>
This switches the Espressif fork from LLVM 19 to LLVM 20, so we can use the improvements made between those LLVM versions. It also better aligns with the system-LLVM build method, which currently also defaults to LLVM 20. Note that this disables the machine outliner for RISC-V. It appears there's a bug in there somewhere, with the machine outliner enabled the crypto/elliptic package tests fail with -target=riscv-qemu. This should ideally be investigated and reported upstream.
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.
Other than a nit, this looks good to me. @aykevl WDYT?
src/runtime/runtime_rp2.go
Outdated
printLock = spinLock{id: 0} | ||
schedulerLock = spinLock{id: 1} | ||
atomicsLock = spinLock{id: 2} | ||
futexLock = spinLock{id: 3} |
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.
id
is an implementation detail of rp2040 spinlocks, whereas on rp2350 id
s have some meaning but are unusued. I suggest moving the spinlock variables to the rpXXXX.go files and avoid the id
field on rp2350.
src/runtime/runtime_rp2350.go
Outdated
|
||
type spinLock struct { | ||
atomic.Uint32 | ||
id uint8 |
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.
Delete field.
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.
That one's still needed for compatibility with how the rp2040 hardware spinlocks are initialized here:
tinygo/src/runtime/runtime_rp2.go
Lines 295 to 298 in 109e076
printLock = spinLock{id: 20} | |
schedulerLock = spinLock{id: 21} | |
atomicsLock = spinLock{id: 22} | |
futexLock = spinLock{id: 23} |
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.
Indeed. Above, I suggested moving that var ()
block to the runtime_rp2xxx.go
files to get rid of that dependency.
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.
Ah yep, I missed that
After doing some testing, I think this might not actually be locking properly. Going to do some more thorough testing |
- do not install cmake, instead use the version already installed - add macOS 15 to the CI builds - update a could of GH actions to latest release - update Go version being use to Go 1.25.1 Signed-off-by: deadprogram <ron@hybridgroup.com>
GitHub org. The git server for git.musl-libc.org is having troubles, and it also seems like a safer bet to have our own mirror just in case. Signed-off-by: deadprogram <ron@hybridgroup.com>
…d by the test-macos-homebrew job, and it conflicts with the actual build that we want, which is macOS 14 for backwards-compatibility. Signed-off-by: deadprogram <ron@hybridgroup.com>
Signed-off-by: Piotr Bocheński <piotr@bochen.ski>
Yes, this looks good. @mikesmitty can you apply the changes proposed by @eliasnaur? Also, you may want to rebase on the dev branch to hopefully fix the assert-test-linux CI failure. |
1f2642c
to
cee4537
Compare
Sure, here's the rebase. I haven't had time to test or diagnose it yet, been stuck working on a project that's consumed all my free time, but I'm pretty sure it's not functioning properly as confirmed by that CI failure |
Hmm, no I guess it is actually locking. I'm not sure what's happening with that CI test though |
As it turns out, the RP2350 has hardware spinlocks that can be unlocked by writes to nearby addresses, the lower spinlocks currently in use in TinyGo happen to be unlocked by writes to the doorbell interrupt registers used to signal between cores, very possibly leading to some unexpected unlocks. This was not corrected in the A3 or A4 steppings and instead software spinlocks are used by default on RP2350 in pico-sdk:
https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#group_hardware_sync
Another thing I noticed in that section, they also always disable interrupts when the spinlocks are being held, we may want to do the same:
These are the software spinlock macros ported over:
https://github.com/raspberrypi/pico-sdk/blob/2.2.0/src/rp2_common/hardware_sync_spin_lock/include/hardware/sync/spin_lock.h#L112
https://github.com/raspberrypi/pico-sdk/blob/2.2.0/src/rp2_common/hardware_sync_spin_lock/include/hardware/sync/spin_lock.h#L197