Closed tmilkovic51 closed 11 months ago
@tmilkovic51, probably something else is wrong, nvs should never do unaligned writes (when the write-block-size has been set correctly).
@tmilkovic51, probably something else is wrong, nvs should never do unaligned writes (when the write-block-size has been set correctly).
Destination addresses for flash writes generated by NVS are fine. The issue here is, it seems, with misaligned reads of source data buffer (data which is to be written to flash). In this case, source data buffer is a misaligned Settings key value (string) located somewhere in .rodata
section, which is mapped to MCU flash memory.
So, the setting key (unaligned string, in my case it was "lorawan/nvm/MacGroup1"
) is being read from flash (.rodata
section) by dereferencing an uint64_t*
pointer, which generates an unaligned memory read from flash (I'm not an STM32/ARM expert, but maybe unaligned reads from RAM are fine, but it's unaligned reads from flash that generate the exception).
EDIT: Maybe the title of the issue was a bit misleading. I added to the title that read may be an issue
@tmilkovic51, the problem is IMO in the flash driver: https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/flash/flash_stm32h7x.c#L374, this supposes that void *data is 8 byte aligned, which is not guaranteed.
@erwango fyi.
@tmilkovic51 I've followed @Laczen opinion and tried to deal with this case, please have a test: https://github.com/zephyrproject-rtos/zephyr/pull/59098
@tmilkovic51 I've followed @Laczen opinion and tried to deal with this case, please have a test: https://github.com/zephyrproject-rtos/zephyr/pull/59098
Not fully ready yet. See my comments in PR
I think this is a broader problem than just the stm32h7 driver. I am encountering the same on stm32u585xx and it's probably not just limited to those. Do we need to change each driver or is there a place we can make a broader change?
@martincalsyn I've took a quick look at STM32 series flash drivers and this is their status (I didn't test it on actual hardware, just inspected the code):
memcpy
to copy the source data into temporary (aligned) buffer (either uint64_t
, uint32_t
or uint16_t
, depending on write_block_size
property in flash controller device tree node)UNALIGNED_GET
macro to access the source data as uint64_t
uint64_t*
uint64_t*
UNALIGNED_GET
macro to acces the source data as uint64_t
UNALIGNED_GET
macro to access the source data as uint64_t
Series in bold could potentially have this issue. Affected files are: flash_stm32h7x.c
, flash_stm32l5x.c
and flash_stm32g4x.c
. After unaligned read access is resolved in all of these, no series will be left affected.
Wow. All over the map. The UNALIGNED_GET seems like the least memory-expensive way to do it (though most cpu expensive). I have devkits here for all but the G4 series to test on. Do you plan to offer a revised PR or should I jump in in some fashion?
There are some solutions proposed in #59098, so take a look there. It's still TBD on what is the best way to resolve this, but good thing is that the same approach could be applied to all affected series if required.
This issue has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this issue will automatically be closed in 14 days. Note, that you can always re-open a closed issue at any time.
Describe the bug On STM32H7 MCUs, an unaligned memory access exception happens on successful LoRaWAN network join.
When joining a LoRaWAN network by calling
lorawan_join()
function, the LoRaWAN subsystem writes some settings to NVS. Each NVS setting has a string representing its name (a key). NVS setting name strings are treated asconst char
arrays, which go in.rodata
section. Since there is no alignment requirement forconst char
arrays, linker puts the setting name strings fromlorawan_nvm_settings.c
file one after another (sequentially) in.rodata
section (there are 7 different LoRaWAN settings in lorawan_nvm_settings.c file).In
lorawan_nvm_save_settings
function, LoRaWAN setting name string is passed tosettings_save_one()
, which eventually gets passed to STM32 flash driver'sflash_stm32_write(const struct device *dev, off_t offset, const void *data, size_t len)
function asconst void *data
parameter. This function then calls STM32H7 flash driver'sflash_stm32_write_range(const struct device *dev, unsigned int offset, const void *data, unsigned int len)
function which casts pointer to data fromconst void*
toconst uint64_t*
and passes the data towrite_nwords(const struct device *dev, off_t offset, const uint64_t *data, uint8_t n)
function.Finally, after all these calls, pointer which points to arbitrary aligned data (
const char
array located in flash) ends up being casted toconst uint64_t* data
and gets accessed by pointer dereference inwrite_ndwords
function:(here is a link to the line where this code is located)
This dereference causes unaligned memory access exception on STM32H7, which could be fixed either in
lorawan_nvm_settings.c
file by copying the setting name string to a temporary 8-byte aligned buffer which will then get passed tosettings_save_one()
function or it can be fixed inflash_stm32h7x.c
file (better solution) by handling a special case if source data (data to be written to flash) is coming from flash region (e.g..rodata
section) and it is unaligned.Please also mention any information which could help others to understand the problem you're facing:
flash_stm32h7x.c
). (NVS subsystem cannot be used on STM32H7 MCUs other than STM32H7A3/B3/B0 since their flash blocks are too big for NVS subsystem - 128 KB)lorawan_nvm_save_settings
function and pass pointer to that buffer when callingsettings_save_one
function instead of passing pointer to strings located in.rodata
(i.e. located in flash). A proper solution would be to handle unaligned source data located in flash in STM32H7 flash driver.write_ndwords()
function in STM32H7 flash driver has always been like thisTo Reproduce I encountered this on a custom board, but the issue could be reproduced by building and running
samples/subsys/lorawan/class_a
sample onstm32h7b3i_dk
board withstorage
flash partition and LoRa transceeiver chip added to board device tree, settings subsystem with NVS backend enabled (CONFIG_NVS=y CONFIG_SETTINGS=y CONFIG_SETTINGS_NVS=y
) and LoRaWAN NVM enabled (CONFIG_LORAWAN_NVM_SETTINGS=y
). This should cause unaligned memory access exception to happen upon successful LoRaWAN network join.Expected behavior STM32H7 flash driver should support unaligned source data to be written to flash, regardless if source data is located in RAM or flash (to be honest, I didn't check if STM32H7 flash driver supports writing unaligned source data from RAM to flash, only from flash (
.rodata
) to flash).Impact Showstopper for using LoRaWAN subsystem with NVM support (
CONFIG_LORAWAN_NVM_SETTINGS=y
) on STM32H7A3/B3/B0 MCUs. Some LoRaWAN servers don't support joining if you don't send a monotonically increasing counter value on every new join request, so havingCONFIG_LORAWAN_NVM_SETTINGS=y
is a must-have.Logs and console output
Log output - exception happens when stepping over this line (sorry for bunch of dropped messages, it is because debug log level for flash driver is enabled):
Environment (please complete the following information):
Additional context
prj.conf
file used with a custom board and project:Relevant parts of custom board DTS: