zephyr/drivers/flash/soc_flash_nrf.h
Kyle Cooke 9892af1464 drivers: flash: soc_flash_nrf: Account for ticker in timeout
We have been encountering timeout issues when erasing large flash
 sections (before receiving an image via mcuboot) from this semaphore
 take:
5af0fbc2e3/drivers/flash/soc_flash_nrf_ticker.c (L225-L233)

I think this is because this constant is based on the time taken to erase
 the chip but doesn't take account of the fact it is being done by a
 ticker. If I understand correctly the ticker is a timeshare mechanism
 so the actual max erase time is some factor based on how much time is
 given to the task by the ticker.

This multiplies the max timeout by 1.5

Signed-off-by: Kyle Cooke <cookekyle97@gmail.com>
2022-10-13 16:06:08 +09:00

194 lines
6.5 KiB
C

/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __SOC_FLASH_NRF_H__
#define __SOC_FLASH_NRF_H__
#include <zephyr/kernel.h>
#include <soc.h>
#define FLASH_OP_DONE (0) /* 0 for compliance with the driver API. */
#define FLASH_OP_ONGOING 1
struct flash_context {
uint32_t data_addr; /* Address of data to write. */
uint32_t flash_addr; /* Address of flash to write or erase. */
uint32_t len; /* Size of data to write or erase [B]. */
#ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
uint8_t enable_time_limit; /* set execution limited to the execution
* window.
*/
#endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
#if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE)
uint32_t flash_addr_next;
#endif /* CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE */
}; /*< Context type for f. @ref write_op @ref erase_op */
#ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE
/* The timeout is multiplied by CONFIG_SOC_FLASH_NRF_TIMEOUT_MULTIPLIER/10
* because switching tasks may take a significant portion of time.
*/
#define FLASH_TIMEOUT_MS ((FLASH_PAGE_ERASE_MAX_TIME_US) * \
(FLASH_PAGE_MAX_CNT) / 1000 * \
CONFIG_SOC_FLASH_NRF_TIMEOUT_MULTIPLIER / 10)
/**
* @defgroup nrf_flash_sync sync backend API
*
* API declared below contains prototypes of function which shall be
* implemented by the synchronization backend.
* @{
*/
/**
* Callback which executes the flash operation.
*
* @param context pointer to flash_context structure.
* @retval @ref FLASH_OP_DONE once operation was done, @ref FLASH_OP_ONGOING if
* operation needs more time for execution and a negative error code if
* operation was aborted.
*/
typedef int (*flash_op_handler_t) (void *context);
struct flash_op_desc {
flash_op_handler_t handler;
struct flash_context *context; /* [in,out] */
};
/**
* Synchronization backend driver initialization procedure.
*
* This will be run within flash driver initialization
*/
int nrf_flash_sync_init(void);
/**
* Set synchronization context for synchronous operations.
*
* This function set backend's internal context for expected timing parameter.
*
* @param duration Duration of the execution window [us]
*/
void nrf_flash_sync_set_context(uint32_t duration);
/**
* Check if the operation need to be run synchronous with radio.
*
* @retval True if operation need to be run synchronously, otherwise False
*/
bool nrf_flash_sync_is_required(void);
/**
* Execute the flash operation synchronously along the radio operations.
*
* Function executes callbacks op_desc->handler() in execution windows according
* to timing settings requested by nrf_flash_sync_set_context().
* This routine need to be called the handler as many time as it returns
* FLASH_OP_ONGOING, however an operation timeout should be implemented.
* When the handler() returns FLASH_OP_DONE or an error code, no further
* execution windows are needed so function should return as the handler()
* finished its operation.
*
* @retval 0 if op_desc->handler() was executed and finished its operation
* successfully. Otherwise (handler returned error, timeout, couldn't schedule
* execution...) a negative error code.
*
* execution window
* Driver task task
* | |
* | |
* nrf_flash_sync_ # |
* set_context() # |
* | |
* | |
* call nrf_flash_ # |
* sync_exe() # |
* #---------------->|
* | |
* | # execution window 0
* | # call flash_op_handler_t handler()
* | #
* | #
* | # flash_op_handler_t handler() return
* | # FLASH_OP_ONGOING
* | # {backend request/allow
* | | the next execution window}
* . .
* . .
* . .
* | |
* | # execution window N
* | # call flash_op_handler_t handler()
* | #
* | #
* | #
* | # flash_op_handler_t handler() returns
* | # FLASH_OP_DONE
* |<----------------# {backend transfer execution
* # | to the driver back}
* nrf_flash_ # |
* sync_exe() | |
* return | |
*/
int nrf_flash_sync_exe(struct flash_op_desc *op_desc);
/**
* @}
*/
/**
* @defgroup nrf_flash_sync_timing sync timing backend API
* @ingroup nrf_flash_sync
* @{
*
* API which is used by nrf flash driver for check where execution fill in
* the execution window.
*
* API is used as follows:
* begin of execution window
* call flash_op_handler_t handler()
* nrf_flash_sync_get_timestamp_begin()
* [does some chunk of work]
* nrf_flash_sync_check_time_limit() == false
* [does some chunk of work]
* nrf_flash_sync_check_time_limit() == false
* [does some chunk of work]
* ...
* nrf_flash_sync_check_time_limit() == true
* [preserve work context for next execution window]
* return form flash_op_handler_t handler()
* [return from execution window]
* end of execution window
*/
/**
* Get timestamp and store it in synchronization backend
* context data as operation beginning time reference.
* This timestamp will be used by @ref nrf_flash_sync_check_time_limit()
* as the execution window begin reference.
*/
void nrf_flash_sync_get_timestamp_begin(void);
/**
* Estimate whether next iteration will fit in time constraints.
* This function fetch current timestamp and compare it with the operation
* beginning timestamp reference stored by
* @ref nrf_flash_sync_get_timestamp_begin() in the synchronization backend
* context data.
*
* @param iteration iteration number.
* @retval true if estimated time excess, false otherwise.
*/
bool nrf_flash_sync_check_time_limit(uint32_t iteration);
/**
* @}
*/
#endif /* !CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE */
#endif /* !__SOC_FLASH_NRF_H__ */