11/*
2- * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
2+ * Copyright (c) 2021-2025 Espressif Systems (Shanghai) Co., Ltd.
33 *
44 * SPDX-License-Identifier: Apache-2.0
55 */
@@ -45,11 +45,37 @@ LOG_MODULE_REGISTER(flash_esp32, CONFIG_FLASH_LOG_LEVEL);
4545#define ALIGN_OFFSET (num , align ) ((num) & ((align) - 1))
4646#endif
4747
48+ #ifdef CONFIG_ESP_FLASH_ASYNC_WORK
49+ #define ESP_FLASH_WORKQUEUE_STACK_SIZE CONFIG_ESP_FLASH_ASYNC_WORK_STACK_SIZE
50+ #define ESP_FLASH_WORKQUEUE_PRIORITY CONFIG_ESP_FLASH_ASYNC_WORK_PRIORITY
51+ K_THREAD_STACK_DEFINE (esp_flash_workqueue_stack , ESP_FLASH_WORKQUEUE_STACK_SIZE );
52+ static struct k_work_q esp_flash_workqueue ;
53+ #endif /* CONFIG_ESP_FLASH_ASYNC_WORK */
54+
55+ #ifdef CONFIG_ESP_FLASH_ASYNC
56+ enum {
57+ FLASH_OP_NONE ,
58+ FLASH_OP_READ ,
59+ FLASH_OP_WRITE ,
60+ FLASH_OP_ERASE
61+ };
62+ #endif
63+
4864struct flash_esp32_dev_config {
4965 spi_dev_t * controller ;
5066};
5167
5268struct flash_esp32_dev_data {
69+ #ifdef CONFIG_ESP_FLASH_ASYNC
70+ struct k_work work ;
71+ struct k_mutex lock ;
72+ const struct device * dev ;
73+ int type ;
74+ off_t addr ;
75+ size_t len ;
76+ void * buf ;
77+ int ret ;
78+ #endif
5379#ifdef CONFIG_MULTITHREADING
5480 struct k_sem sem ;
5581#endif
@@ -60,7 +86,7 @@ static const struct flash_parameters flash_esp32_parameters = {
6086 .erase_value = 0xff ,
6187};
6288
63- #ifdef CONFIG_MULTITHREADING
89+ #if defined( CONFIG_MULTITHREADING ) && !defined( CONFIG_ESP_FLASH_ASYNC )
6490static inline void flash_esp32_sem_take (const struct device * dev )
6591{
6692 struct flash_esp32_dev_data * data = dev -> data ;
@@ -79,7 +105,7 @@ static inline void flash_esp32_sem_give(const struct device *dev)
79105#define flash_esp32_sem_take (dev ) do {} while (0)
80106#define flash_esp32_sem_give (dev ) do {} while (0)
81107
82- #endif /* CONFIG_MULTITHREADING */
108+ #endif /* CONFIG_MULTITHREADING && !CONFIG_ESP_FLASH_ASYNC */
83109
84110#include <zephyr/kernel.h>
85111#include <zephyr/logging/log.h>
@@ -374,12 +400,9 @@ static int flash_esp32_read(const struct device *dev, off_t address, void *buffe
374400 }
375401#else
376402 flash_esp32_sem_take (dev );
377-
378403 ret = flash_esp32_read_check_enc (address , buffer , length );
379-
380404 flash_esp32_sem_give (dev );
381- #endif
382-
405+ #endif /* CONFIG_MCUBOOT */
383406 if (ret != 0 ) {
384407 LOG_ERR ("Flash read error: %d" , ret );
385408 return - EIO ;
@@ -388,9 +411,7 @@ static int flash_esp32_read(const struct device *dev, off_t address, void *buffe
388411 return 0 ;
389412}
390413
391- static int flash_esp32_write (const struct device * dev ,
392- off_t address ,
393- const void * buffer ,
414+ static int flash_esp32_write (const struct device * dev , off_t address , const void * buffer ,
394415 size_t length )
395416{
396417 int ret = 0 ;
@@ -423,11 +444,10 @@ static int flash_esp32_write(const struct device *dev,
423444 }
424445#else
425446 ret = flash_esp32_write_check_enc (address , buffer , length );
426- #endif
447+ #endif /* CONFIG_ESP_FLASH_ENCRYPTION */
427448
428449 flash_esp32_sem_give (dev );
429- #endif
430-
450+ #endif /* CONFIG_MCUBOOT */
431451 if (ret != 0 ) {
432452 LOG_ERR ("Flash write error: %d" , ret );
433453 return - EIO ;
@@ -480,17 +500,94 @@ static int flash_esp32_erase(const struct device *dev, off_t start, size_t len)
480500 }
481501#else
482502 ret = esp_flash_erase_region (NULL , start , len );
483- #endif
503+ #endif /* CONFIG_ESP_FLASH_ENCRYPTION */
484504
485505 flash_esp32_sem_give (dev );
486- #endif
506+ #endif /* CONFIG_MCUBOOT */
487507 if (ret != 0 ) {
488508 LOG_ERR ("Flash erase error: %d" , ret );
489509 return - EIO ;
490510 }
491511 return 0 ;
492512}
493513
514+ #ifdef CONFIG_ESP_FLASH_ASYNC
515+ static void flash_work_handler (struct k_work * work )
516+ {
517+ struct flash_esp32_dev_data * data = CONTAINER_OF (work , struct flash_esp32_dev_data , work );
518+
519+ if (data -> type == FLASH_OP_READ ) {
520+ data -> ret = flash_esp32_read (data -> dev , data -> addr , data -> buf , data -> len );
521+ } else if (data -> type == FLASH_OP_WRITE ) {
522+ data -> ret = flash_esp32_write (data -> dev , data -> addr , data -> buf , data -> len );
523+ } else if (data -> type == FLASH_OP_ERASE ) {
524+ data -> ret = flash_esp32_erase (data -> dev , data -> addr , data -> len );
525+ } else {
526+ data -> ret = - EINVAL ;
527+ }
528+
529+ k_sem_give (& data -> sem );
530+ }
531+
532+ static int flash_esp32_read_async (const struct device * dev , off_t address ,
533+ void * buffer , size_t length )
534+ {
535+ struct flash_esp32_dev_data * data = dev -> data ;
536+
537+ k_mutex_lock (& data -> lock , K_TIMEOUT_ABS_SEC (3 ));
538+
539+ data -> dev = dev ;
540+ data -> addr = address ;
541+ data -> buf = buffer ;
542+ data -> len = length ;
543+ data -> type = FLASH_OP_READ ;
544+
545+ k_work_submit (& data -> work );
546+ k_sem_take (& data -> sem , FLASH_SEM_TIMEOUT );
547+ k_mutex_unlock (& data -> lock );
548+
549+ return data -> ret ;
550+ }
551+
552+ static int flash_esp32_write_async (const struct device * dev , off_t address ,
553+ const void * buffer , size_t length )
554+ {
555+ struct flash_esp32_dev_data * data = dev -> data ;
556+
557+ k_mutex_lock (& data -> lock , K_TIMEOUT_ABS_SEC (3 ));
558+
559+ data -> dev = dev ;
560+ data -> addr = address ;
561+ data -> buf = (void * ) buffer ;
562+ data -> len = length ;
563+ data -> type = FLASH_OP_WRITE ;
564+
565+ k_work_submit (& data -> work );
566+ k_sem_take (& data -> sem , FLASH_SEM_TIMEOUT );
567+ k_mutex_unlock (& data -> lock );
568+
569+ return 0 ;
570+ }
571+ static int flash_esp32_erase_async (const struct device * dev , off_t start , size_t len )
572+ {
573+ struct flash_esp32_dev_data * data = dev -> data ;
574+
575+ k_mutex_lock (& data -> lock , K_TIMEOUT_ABS_SEC (3 ));
576+
577+ data -> addr = start ;
578+ data -> len = len ;
579+ data -> buf = NULL ;
580+ data -> type = FLASH_OP_ERASE ;
581+
582+ k_work_submit (& data -> work );
583+ k_sem_take (& data -> sem , FLASH_SEM_TIMEOUT );
584+ k_mutex_unlock (& data -> lock );
585+
586+ return 0 ;
587+ }
588+ #endif
589+
590+
494591#if CONFIG_FLASH_PAGE_LAYOUT
495592static const struct flash_pages_layout flash_esp32_pages_layout = {
496593 .pages_count = DT_REG_SIZE (SOC_NV_FLASH_NODE ) / FLASH_ERASE_BLK_SZ ,
@@ -504,7 +601,7 @@ void flash_esp32_page_layout(const struct device *dev,
504601 * layout = & flash_esp32_pages_layout ;
505602 * layout_size = 1 ;
506603}
507- #endif /* CONFIG_FLASH_PAGE_LAYOUT */
604+ #endif
508605
509606static const struct flash_parameters *
510607flash_esp32_get_parameters (const struct device * dev )
@@ -517,18 +614,37 @@ flash_esp32_get_parameters(const struct device *dev)
517614static int flash_esp32_init (const struct device * dev )
518615{
519616#ifdef CONFIG_MULTITHREADING
520- struct flash_esp32_dev_data * const dev_data = dev -> data ;
521-
522- k_sem_init (& dev_data -> sem , 1 , 1 );
617+ struct flash_esp32_dev_data * const data = dev -> data ;
618+
619+ #ifdef CONFIG_ESP_FLASH_ASYNC
620+ k_sem_init (& data -> sem , 0 , 1 );
621+ k_mutex_init (& data -> lock );
622+ k_work_init (& data -> work , flash_work_handler );
623+
624+ #ifdef CONFIG_ESP_FLASH_ASYNC_WORK
625+ k_work_queue_init (& esp_flash_workqueue );
626+ k_work_queue_start (& esp_flash_workqueue , esp_flash_workqueue_stack ,
627+ K_THREAD_STACK_SIZEOF (esp_flash_workqueue_stack ),
628+ ESP_FLASH_WORKQUEUE_PRIORITY , NULL );
629+ k_work_submit_to_queue (& esp_flash_workqueue , & data -> work );
630+ #endif
631+ #else
632+ k_sem_init (& data -> sem , 1 , 1 );
633+ #endif /* CONFIG_ESP_FLASH_ASYNC */
523634#endif /* CONFIG_MULTITHREADING */
524-
525635 return 0 ;
526636}
527637
528638static DEVICE_API (flash , flash_esp32_driver_api ) = {
639+ #ifdef CONFIG_ESP_FLASH_ASYNC
640+ .read = flash_esp32_read_async ,
641+ .write = flash_esp32_write_async ,
642+ .erase = flash_esp32_erase_async ,
643+ #else
529644 .read = flash_esp32_read ,
530645 .write = flash_esp32_write ,
531646 .erase = flash_esp32_erase ,
647+ #endif
532648 .get_parameters = flash_esp32_get_parameters ,
533649#ifdef CONFIG_FLASH_PAGE_LAYOUT
534650 .page_layout = flash_esp32_page_layout ,
0 commit comments