spi_flash: Make spi_flash op_lock/op_unlock recursive

Allows chaining of multiple flash operations as an atomic operation.
This commit is contained in:
Angus Gratton
2017-11-17 15:00:16 +11:00
committed by Angus Gratton
parent 7e8c2a9c00
commit e72e5a9706
2 changed files with 12 additions and 8 deletions

View File

@@ -47,18 +47,18 @@ static volatile int s_flash_op_cpu = -1;
void spi_flash_init_lock() void spi_flash_init_lock()
{ {
s_flash_op_mutex = xSemaphoreCreateMutex(); s_flash_op_mutex = xSemaphoreCreateRecursiveMutex();
assert(s_flash_op_mutex != NULL); assert(s_flash_op_mutex != NULL);
} }
void spi_flash_op_lock() void spi_flash_op_lock()
{ {
xSemaphoreTake(s_flash_op_mutex, portMAX_DELAY); xSemaphoreTakeRecursive(s_flash_op_mutex, portMAX_DELAY);
} }
void spi_flash_op_unlock() void spi_flash_op_unlock()
{ {
xSemaphoreGive(s_flash_op_mutex); xSemaphoreGiveRecursive(s_flash_op_mutex);
} }
/* /*
If you're going to modify this, keep in mind that while the flash caches of the pro and app If you're going to modify this, keep in mind that while the flash caches of the pro and app
@@ -214,7 +214,7 @@ void spi_flash_op_unlock()
void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu() void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu()
{ {
spi_flash_op_lock(); spi_flash_op_lockspi_flash_op_lock();
esp_intr_noniram_disable(); esp_intr_noniram_disable();
spi_flash_disable_cache(0, &s_flash_op_cache_state[0]); spi_flash_disable_cache(0, &s_flash_op_cache_state[0]);
} }

View File

@@ -289,11 +289,15 @@ typedef void (*spi_flash_op_unlock_func_t)(void);
* is invoked before the call to one of ROM function above. * is invoked before the call to one of ROM function above.
* - 'end' function should restore state of flash cache and non-IRAM interrupts and * - 'end' function should restore state of flash cache and non-IRAM interrupts and
* is invoked after the call to one of ROM function above. * is invoked after the call to one of ROM function above.
* These two functions are not recursive.
* 2) Functions which synchronizes access to internal data used by flash API. * 2) Functions which synchronizes access to internal data used by flash API.
* This functions are mostly intended to synchronize access to flash API internal data * This functions are mostly intended to synchronize access to flash API internal data
* in multithreaded environment and use OS primitives: * in multithreaded environment and use OS primitives:
* - 'op_lock' locks access to flash API internal data. * - 'op_lock' locks access to flash API internal data.
* - 'op_unlock' unlocks access to flash API internal data. * - 'op_unlock' unlocks access to flash API internal data.
* These two functions are recursive and can be used around the outside of multiple calls to
* 'start' & 'end', in order to create atomic multi-part flash operations.
*
* Different versions of the guarding functions should be used depending on the context of * Different versions of the guarding functions should be used depending on the context of
* execution (with or without functional OS). In normal conditions when flash API is called * execution (with or without functional OS). In normal conditions when flash API is called
* from task the functions use OS primitives. When there is no OS at all or when * from task the functions use OS primitives. When there is no OS at all or when
@@ -304,10 +308,10 @@ typedef void (*spi_flash_op_unlock_func_t)(void);
* For example structure can be placed in DRAM and functions in IRAM sections. * For example structure can be placed in DRAM and functions in IRAM sections.
*/ */
typedef struct { typedef struct {
spi_flash_guard_start_func_t start; /**< critical section start func */ spi_flash_guard_start_func_t start; /**< critical section start function. */
spi_flash_guard_end_func_t end; /**< critical section end func */ spi_flash_guard_end_func_t end; /**< critical section end function. */
spi_flash_op_lock_func_t op_lock; /**< flash access API lock func */ spi_flash_op_lock_func_t op_lock; /**< flash access API lock function.*/
spi_flash_op_unlock_func_t op_unlock; /**< flash access API unlock func */ spi_flash_op_unlock_func_t op_unlock; /**< flash access API unlock function.*/
} spi_flash_guard_funcs_t; } spi_flash_guard_funcs_t;
/** /**