pico_flash

Functions

bool flash_safe_execute_core_init (void)
 
bool flash_safe_execute_core_deinit (void)
 
int flash_safe_execute (void(*func)(void *), void *param, uint32_t enter_exit_timeout_ms)
 
flash_safety_helper_tget_flash_safety_helper (void)
 

Detailed Description

High level flash API

Flash cannot be erased or written to when in XIP mode. However the system cannot directly access memory in the flash address space when not in XIP mode.

It is therefore critical that no code or data is being read from flash while flash is been written or erased.

If only one core is being used, then the problem is simple - just disable interrupts; however if code is running on the other core, then it has to be asked, nicely, to avoid flash for a bit. This is hard to do if you don't have complete control of the code running on that core at all times.

This library provides a flash_safe_execute method which calls a function back having sucessfully gotten into a state where interrupts are disabled, and the other core is not executing or reading from flash.

How it does this is dependent on the supported environment (Free RTOS SMP or pico_multicore). Additionally the user can provide their own mechanism by providing a strong definition of get_flash_safety_helper().

Using the default settings, flash_safe_execute will only call the callback function if the state is safe otherwise returning an error (or an assert depending on PICO_FLASH_ASSERT_ON_UNSAFE).

There are conditions where safety would not be guaranteed:

  1. FreeRTOS smp with configNUM_CORES=1 - FreeRTOS still uses pico_multicore in this case, so flash_safe_execute cannot know what the other core is doing, and there is no way to force code execution between a FreeRTOS core and a non FreeRTOS core.
  2. FreeRTOS non SMP with pico_multicore - Again, there is no way to force code execution between a FreeRTOS core and a non FreeRTOS core.
  3. pico_multicore without flash_safe_execute_core_init() having been called on the other core - The flash_safe_execute method does not know if code is executing on the other core, so it has to assume it is. Either way, it is not able to intervene if flash_safe_execute_core_init() has not been called on the other core.

Fortunately, all is not lost in this situation, you may:

Function Documentation

◆ flash_safe_execute()

int flash_safe_execute ( void(*)(void *)  func,
void *  param,
uint32_t  enter_exit_timeout_ms 
)

Execute a function with IRQs disabled and with the other core also not executing/reading flash

Parameters
functhe function to call
paramthe parameter to pass to the function
enter_exit_timeout_msthe timeout for each of the enter/exit phases when coordinating with the other core
Returns
PICO_OK on success (the function will have been called). PICO_TIMEOUT on timeout (the function may have been called). PICO_ERROR_NOT_PERMITTED if safe execution is not possible (the function will not have been called). PICO_ERROR_INSUFFICIENT_RESOURCES if the method fails due to dynamic resource exhaustion (the function will not have been called)
Note
if PICO_FLASH_ASSERT_ON_UNSAFE is 1, this function will assert in debug mode vs returning PICO_ERROR_NOT_PERMITTED

◆ flash_safe_execute_core_deinit()

bool flash_safe_execute_core_deinit ( void  )

De-initialize work done by flash_safe_execute_core_init

Returns
true on success

◆ flash_safe_execute_core_init()

bool flash_safe_execute_core_init ( void  )

Initialize a core such that the other core can lock it out during flash_safe_execute.

Note
This is not necessary for FreeRTOS SMP, but should be used when launching via multicore_launch_core1
Returns
true on success; there is no need to call flash_safe_execute_core_deinit() on failure.

◆ get_flash_safety_helper()

flash_safety_helper_t* get_flash_safety_helper ( void  )

Internal method to return the flash safety helper implementation.

Advanced users can provide their own implementation of this function to perform different inter-core coordination before disabling XIP mode.

Returns
the flash_safety_helper_t