pico-sdk
pico-sdk copied to clipboard
Memset and Memcpy are not safe on uint8 if unaligned bytes.
I’ve encountered an issue with the current implementation of memset and memcpy in the standard library on the pico. When the SCB_CCR_UNALIGN_TRP flag is enabled to trap unaligned accesses, both functions may internally perform word-sized operations on unaligned addresses—even when operating on uint8_t arrays. This results in a UsageFault exception on CPUs that do not support unaligned accesses. While this is allowed by the C standard, it is problematic for platforms enforcing strict alignment. To ensure compatibility with systems that enable UNALIGN_TRP, these functions need to handle unaligned pointers correctly, for example, by using byte-wise operations when the pointer is not word-aligned.
example code.
SCB->CCR |= ( SCB_CCR_DIV_0_TRP_Msk | SCB_CCR_UNALIGN_TRP_Msk | SCB_CCR_BFHFNMIGN_Msk);
uint8_t buffer[10];
memset(&buffer[1], 0, 4);
memset(&buffer[2], 0, 4);
DEBUG_PRINT("%d , buffer1 %d, buffer2 %d\n", buffer, &buffer[1], &buffer[2]);
add_compile_options(-mno-unaligned-access)
Added to cmake did not fix the issue.
I guess this must be on RP2350? Looking at the RP2350 datasheet says that CCR.UNALIGN_TRP is RW, but the RP2040 datasheet says that CCR.UNALIGN_TRP is RO and hardwired to 1. (With the latter being one of the unfortunate examples of where the Reset column in the auto-generated register tables doesn't know what the real reset value is. See also https://github.com/raspberrypi/pico-feedback/issues/241 )
IT is but if it is hardwired to 1 on the 2040 wouldnt this have caused alot of problems? I found this in btstack first and then ran the above test.
At the end of the day memset and memcpy should be safe to do on uint8 arrays even with the trap enabled.
I'm leaving this around in 2.2.0 as we might replace the memset implementations, but we are picking them up from the compiler on RP2350 so this must be a common problem outside of pico-sdk
I've actually run into this on RP2040. Misaligned memset cause hardfaults there. However I have only seen that happen in my own code, never in the CYW-Driver
on RP2040 the SDK memset implementation (which actually calls the bootrom memset) should generally be used unless you are doing something ohter than a regular SDK CMake build perhaps. (the bootrom memset never does mis-aligned reads/writes)
What do you mean by
the bootrom memset never does mis-aligned reads/writes
If my software calls memset with a unaligned address should it just result in a build error?
I've seen hardfaults when calling memset on packed structs with misaligned fields.
I'm using the SDKs CMake.
I can try to provide a minimal example to produce a hardfault.
Please do (the RP2040 bootrom version of memcpy/memset will do bytewise operation if the memory is not aligned)
Pls give an example on how to force it to link the memcpy and memset from the bootrom , does this also work on the rp2350.
On RP2040 memcpy/memset should use the bootrom versions if you use a regular CMake SDK build On RP2350 they use the C library versions, because these are much more efficient than the ones for Arm Cortex M0+, however see #2340