4 releases (2 breaking)
|0.3.1||Jan 24, 2023|
|0.3.0||Dec 2, 2022|
|0.2.0||Aug 10, 2022|
|0.1.0||Jun 21, 2022|
#49 in Emulators
1,472 downloads per month
Used in esp32s2-hal
Xtensa atomic emulation trap handler
Add the following rustflags to
.cargo/config.toml in your project. Take care not to overwrite any existing ones.
rustflags = [ # enable the atomic codegen option for Xtensa "-C", "target-feature=+s32c1i", # tell the core library have atomics even though it's not specified in the target definition "--cfg", 'target_has_atomic="8"', "--cfg", 'target_has_atomic="16"', "--cfg", 'target_has_atomic="32"', "--cfg", 'target_has_atomic="ptr"', ]
Include this line of code somewhere in
use xtensa_atomic_emulation_trap as _;
and build the project. The
core::sync::atomic API will now be available.
How it works
We build code for silicon that has the
s32c1i feature, then when our target attempts to execute these instructions it throws an illegal instruction exception, at which point we can decode the instruction and emulate it in software.
There is only one atomic instruction to emulate in the Xtensa ISA,
However, compare values are written to the
SCOMPARE1 (Special Reg No. 12) register, so in silicon without this feature it won't exist. We need to emulate the instruction and the register for sucessful atomic emulation.
See 184.108.40.206 of the ISA RM for an example atomic compare swap loop.
To emulate the WSR instruction, we must first decode it and verify that the target register is 12, the
SCOMPARE1 register. Once that is confirmed, we can use this crates virtual
SCOMPARE1 to store the value.
Emulation of the
S32C1I instruction is a little more complicated. First we decode the entire instruction to get the following values:
target register- this contains the new value we wish to swap to
source register- this conaints the address in memory of the current value
offset- optional offset to add to the address in the source register
We deference the
source address +
offset to find the current value and compare it to the stored value inside our
SCOMPARE1 virtual register. If they are equal, the new target value is written to memory at the
source address +
offset. Regardless of whether the new value is written the old value is always written back into the target register.
I get linker errors when I build for debug
Follow the instructions here, and also add the following.
[profile.dev.package.xtensa-atomic-emulation-trap] opt-level = 'z'