drivers: STM32 async flash erase and write#93173
drivers: STM32 async flash erase and write#93173jpowen898 wants to merge 1 commit intozephyrproject-rtos:mainfrom
Conversation
|
Hello @jpowen898, and thank you very much for your first pull request to the Zephyr project! |
c34e153 to
ae67109
Compare
|
@nordicjm Thanks for the feedback. I made all the requested changes, let me know if there is anything else. |
030ad53 to
df9a4f8
Compare
9129568 to
b5d3812
Compare
etienne-lms
left a comment
There was a problem hiding this comment.
Minor issues, otherwise LGTM.
8bac90d to
625eb03
Compare
| select USE_STM32_HAL_FLASH | ||
| select USE_STM32_HAL_FLASH_EX |
There was a problem hiding this comment.
Is the feature really that difficult to implement w/o the HAL?
There was a problem hiding this comment.
I'm not exactly sure what you mean. But to explain this a little better, when you attempt to do a write/erase to internal flash on the stm32's the current implementation is full blocking meaning it has some while(1) loops which block all threads (not just the current thread) until the flash operation is complete. To erase a single flash sector (128KB) on the stm32h7 platform typically takes ~1.1 seconds, so all threads end up getting starved for that period of time which is too long for my application.
My fix for this is to use the stm hal to start the flash write/erase, then block with a semaphore (so not all threads get starved) and then the semaphore get's free-ed when a the STM flash hw interrupt gets called. So maybe calling this an ASYNC flash opperation is misleading. The flash_write() and flash_erase() functions still block for the same amount of time and complete the same tasks before returning as they did previously, only now they allow the schedule to run other tasks.
| Use asynchronous flash operations to unblock other threads while | ||
| flash is busy. |
There was a problem hiding this comment.
My understanding is that once this option is enabled, only asynchronous operations are enabled. This is a big change from the old behavior (e.g., not isr-ok) so it should be documented.
There was a problem hiding this comment.
So yes when you enable this all operations are done in "asynchronous" mode, I am happy to document that if you would like, just point me to the correct spot to do that. But to be clear the flash_erase() and flash_write() functions complete the same high level tasks as they did before and return in the same amount of time so it should be pretty transperent to the user of the function if it is in async mode or not. Also those functions were never ISR safe because flash_erase() takes ~1.1s to return (longer if you erase multiple sectors at a time) and flash_write() takes ~3.5ms to return (depending on how much you are writting at a time).
There was a problem hiding this comment.
I am happy to document that if you would like, just point me to the correct spot to do that.
In the Kconfig help text itself
Also those functions were never ISR safe because flash_erase() takes ~1.1s to return (longer if you erase multiple sectors at a time) and flash_write() takes ~3.5ms to return (depending on how much you are writting at a time).
isr-ok-ness is unrelated to how long a function may take to execute (otherwise the ENTROPY_BUSYWAIT flag would not exist)
Added optional use of the stm32 hal async flash write and erase capabilities on the l4, f4, and h7 soc families. It is implemented using semaphores to allow for other threads to take action during the erase/write actions. This feature is disabled by default and can be optionally enabled using the FLASH_STM32_ASYNC config option. Signed-off-by: Parker Owen <jpowen898@gmail.com>
|
There was a problem hiding this comment.
Commit message says
This feature is disabled by default and
can be optionally enabled using the FLASH_STM32_ASYNC config option
Actually the feature is default enabled for drivers that support async operations.
(edited) my mistake, see my comment below.
Worth to mention also that when enabled, read operations are synced on flash erase/write semaphore.
When so, read operations are se
|
|
||
| * :dtcompatible:`jedec,mspi-nor` now allows MSPI configuration of read, write and | ||
| control commands separately via devicetree. | ||
| * :kconfig:option:`CONFIG_FLASH_STM32_ASYNC` |
There was a problem hiding this comment.
Maybe a place to address #93173 (comment). E.g.:
* :kconfig:option:`CONFIG_FLASH_STM32_ASYNC`. It is default enabled (when multithreading is enable)
for STM32 flash drivers that support asynchronous operations.
| for (size_t i = 0; i < n; i += FLASH_NB_32BITWORD_IN_FLASHWORD) { | ||
| FLASH_STM32_PRIV(dev)->async_complete = false; | ||
| FLASH_STM32_PRIV(dev)->async_error = false; | ||
| uint32_t wordAddr = (uint32_t)&data[i]; |
There was a problem hiding this comment.
Add an empty line above local variable definition + use a snake_case label.
uint32_t word_addr = (uint32_t)&data[i];
My mistake, it is default disabled. Discard this comment. Sorry. |
| flash_dev = FLASH_STM32_PRIV(dev); | ||
| flash_stm32_async_sem_init(dev); | ||
| IRQ_CONNECT(FLASH_IRQn, 0, flash_stm32_irq_handler, NULL, 0); | ||
| irq_enable(FLASH_IRQn); |
There was a problem hiding this comment.
Please get flash IRQ from device tree.
| return = 0; | ||
| } else if (FLASH_STM32_PRIV(dev)->async_error) { | ||
| LOG_ERR("Flash erase failed at 0x%x", FLASH_STM32_PRIV(dev)->async_ret); | ||
| return = -EIO; |
There was a problem hiding this comment.
| return = -EIO; | |
| return -EIO; |
Ditto above.
| FLASH_STM32_PRIV(dev)->async_error = false; | ||
|
|
||
| HAL_FLASH_Program_IT(FLASH_TYPEPROGRAM_SIZE, offset + FLASH_STM32_BASE_ADDRESS, val); | ||
| k_sem_take(&FLASH_STM32_PRIV(dev)->async_sem, K_FOREVER); |
There was a problem hiding this comment.
You provided a function for flash_stm32_async_sem_init, which is matching flash_stm32_sem_init implementation.
It would be nice to make it complete and consistent and provide matching flash_stm32_async_sem_take and flash_stm32_async_sem_give.
| LOG_DBG("Read offset: %ld, len: %zu", (long int) offset, len); | ||
|
|
||
| if (IS_ENABLED(CONFIG_FLASH_STM32_ASYNC)) { | ||
| flash_stm32_sem_take(dev); |
There was a problem hiding this comment.
Could you tell in the commit message why read operations need to take the semaphore when using the flash programming interrupt.
|
Since this also changes flash API, have added @de-nordic as co-assignee |
|
|
This pull request 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 pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time. |



HAL_FLASHEx_Erase_IT()andHAL_FLASH_Program_IT()functions with their associated interrupt handler.FLASH_STM32_ASYNCconfig option.