pico-sdk icon indicating copy to clipboard operation
pico-sdk copied to clipboard

Memset and Memcpy are not safe on uint8 if unaligned bytes.

Open tbandtg opened this issue 6 months ago • 5 comments

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]);

tbandtg avatar May 27 '25 13:05 tbandtg

add_compile_options(-mno-unaligned-access)

Added to cmake did not fix the issue.

tbandtg avatar May 27 '25 13:05 tbandtg

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 )

lurch avatar May 27 '25 13:05 lurch

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.

tbandtg avatar May 27 '25 13:05 tbandtg

At the end of the day memset and memcpy should be safe to do on uint8 arrays even with the trap enabled.

tbandtg avatar May 27 '25 18:05 tbandtg

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

kilograham avatar Jun 12 '25 22:06 kilograham

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

danielecht avatar Jul 07 '25 15:07 danielecht

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)

kilograham avatar Jul 07 '25 15:07 kilograham

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.

danielecht avatar Jul 08 '25 07:07 danielecht

Please do (the RP2040 bootrom version of memcpy/memset will do bytewise operation if the memory is not aligned)

kilograham avatar Jul 08 '25 14:07 kilograham

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.

tbandtg avatar Jul 08 '25 17:07 tbandtg

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

kilograham avatar Jul 08 '25 23:07 kilograham