Page 1 of 1

IDF 6.0.1 ESP32-C6 LP core GCC 15.2 zaamo_zalrsc extensions

Posted: Tue Jun 02, 2026 3:51 pm
by molejnik_bct
Hi,
The new IDF 6.0.1 introduced new GCC compiler version 15.2. The compiler now uses extra RISC-V extensions. Specifically zaamo_zalrsc. The compiler uses those extensions for ESP32C6 HP core code compilation and LP core compilation. We see an issue on ESP32C6 with LP core SPI peripheral when the LP core code is compiled by the new GCC 15.2. Can you confirm the ESP32C6 LP core supports those new zaamo_zalrsc extensions? The exact same LP core code compiled with GCC 14.2 (as used by IDF 5.5.4) works fine with no issue.
If the new RISC-V extensions are not supported on the LP core is there a way for the GCC compiler ver. 15.2 to not to generate code that uses the new opcodes of these extensions? If so, could you please list the GCC options/arguments? Thank you.

Re: IDF 6.0.1 ESP32-C6 LP core GCC 15.2 zaamo_zalrsc extensions

Posted: Wed Jun 03, 2026 2:09 pm
by molejnik_bct
I found the answer myself.
1) C6 LP core should support zaamo_zalrsc extensions since the RISC-V has 'A' (atomic instructions) support (stated in the datasheet)
2) The LP compiler can be forced not to use the extensions by modifying IDF components/ulp/cmake/toolchain-lp-core-riscv.cmake
and changing -march=... to -march=rv32imc_zicsr_zifencei
That does not however fix the SPI issue. So, the SPI issue is not caused by the extensions.
3) The issue seems to be caused by memcpy implementation in the new compiler. In my case the memcpy target was SPI_W0_REG - a register HW address for SPI transfer buffer. memcpy in the older compiler dealt with the data transfer to the HW register fine, the new compiler's memcpy did not. The fix was simple: memcpy was replaced by a simple loop using REG_WRITE() macro, where the SPI data are passed as uint32_t integers into the register.

Re: IDF 6.0.1 ESP32-C6 LP core GCC 15.2 zaamo_zalrsc extensions

Posted: Thu Jun 04, 2026 7:30 am
by Sprite
3) The issue seems to be caused by memcpy implementation in the new compiler. In my case the memcpy target was SPI_W0_REG - a register HW address for SPI transfer buffer. memcpy in the older compiler dealt with the data transfer to the HW register fine, the new compiler's memcpy did not. The fix was simple: memcpy was replaced by a simple loop using REG_WRITE() macro, where the SPI data are passed as uint32_t integers into the register.
Reason is likely that hardware registers need to be written in 32-bit increments; memcpy assumes memory without those restrictions and may use larger or smaller data sizes. In general - don't use memcpy to write to hardware registers.