<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>How can i write external qspi flash over BLE DFU?</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/74931/how-can-i-write-external-qspi-flash-over-ble-dfu</link><description>Hello 
 
 i&amp;#39;m use nrf52840 and I want write external qspi flash over BLE DFU but cannot be use 
 how can i solve this problem? 
 
 DFU log 
 
 
 
 modified nrf_fstorage_sd.c</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 13 May 2021 02:33:53 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/74931/how-can-i-write-external-qspi-flash-over-ble-dfu" /><item><title>RE: How can i write external qspi flash over BLE DFU?</title><link>https://devzone.nordicsemi.com/thread/309634?ContentTypeID=1</link><pubDate>Thu, 13 May 2021 02:33:53 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:897c6922-19f1-48cb-b5cc-aebcc4d8095c</guid><dc:creator>Joshua Yoo</dc:creator><description>&lt;p&gt;Thanks, very helpful&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: How can i write external qspi flash over BLE DFU?</title><link>https://devzone.nordicsemi.com/thread/309248?ContentTypeID=1</link><pubDate>Tue, 11 May 2021 12:37:35 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:82f40586-351b-4756-b289-30f13f17f6a7</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;nrf_fstorage_sys_evt_handler() is registered as an observer for SoC event from the SoftDevice, so whenever there is a new SoC event,&amp;nbsp;nrf_fstorage_sys_evt_handler() will be called. When writing to the internal flash using the SoftDevice API you will get a SoC event whenever a operation has completed. When writing to external flash this does not happen as that does not generate a SoftDevice SoC event. In stead, you would probably want to use QSPI driver events to know that a write has completed (NRFX_QSPI_EVENT_DONE).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: How can i write external qspi flash over BLE DFU?</title><link>https://devzone.nordicsemi.com/thread/309106?ContentTypeID=1</link><pubDate>Tue, 11 May 2021 04:15:58 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:dbb926bf-74b5-42f4-a707-82951e5ae250</guid><dc:creator>Joshua Yoo</dc:creator><description>&lt;p&gt;hello Einar, I&amp;#39;m want to write external flash instead of internal flash using BLE DFU.&lt;br /&gt;when the download is complete and I will copy it to internal flash memory. but it stop while receiving data over BLE.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;I think that &amp;#39;nrf_fstorage_sys_evt_handler()&amp;#39; was not called because a problem occurred after using &amp;#39;erase_execute&amp;#39;, &amp;#39;write_execute&amp;#39;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;Is there a way to call the &amp;#39;nrf_fstorage_sys_evt_handler()&amp;#39;?&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;attach modified&amp;nbsp;&lt;span&gt;&lt;strong&gt;nrf_fstorage_sd.c&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/**
 * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA &amp;quot;AS IS&amp;quot; AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include &amp;quot;sdk_common.h&amp;quot;

#if NRF_MODULE_ENABLED(NRF_FSTORAGE)

#include &amp;quot;nrf_fstorage_sd.h&amp;quot;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;stdbool.h&amp;gt;
#include &amp;quot;nordic_common.h&amp;quot;
#include &amp;quot;nrf_soc.h&amp;quot;
#include &amp;quot;nrf_sdh.h&amp;quot;
#include &amp;quot;nrf_sdh_soc.h&amp;quot;
#include &amp;quot;nrf_atomic.h&amp;quot;
#include &amp;quot;nrf_atfifo.h&amp;quot;
#include &amp;quot;app_util_platform.h&amp;quot;

#include &amp;quot;nrf_log.h&amp;quot;

#include &amp;quot;nrfx_qspi.h&amp;quot;
#if (NRF_FSTORAGE_SD_MAX_WRITE_SIZE % 4)
#error NRF_FSTORAGE_SD_MAX_WRITE_SIZE must be a multiple of the word size.
#endif


/**@brief   fstorage operation codes. */
typedef enum
{
    NRF_FSTORAGE_OP_WRITE,  //!&amp;lt; Write bytes to flash.
    NRF_FSTORAGE_OP_ERASE   //!&amp;lt; Erase flash pages.
} nrf_fstorage_sd_opcode_t;

ANON_UNIONS_ENABLE;
/**@brief   fstorage operation queue element. */
typedef struct
{
    nrf_fstorage_t           const * p_fs;     //!&amp;lt; The fstorage instance that requested the operation.
    nrf_fstorage_sd_opcode_t         op_code;  //!&amp;lt; Requested operation.
    void                           * p_param;  //!&amp;lt; User-defined parameter passed to the event handler.
    union
    {
        struct
        {
            void     const * p_src;     //!&amp;lt; Data to be written to flash.
            uint32_t         dest;      //!&amp;lt; Destination of the data in flash.
            uint32_t         len;       //!&amp;lt; Length of the data to be written (in bytes).
            uint32_t         offset;    //!&amp;lt; Write offset.
        } write;
        struct
        {
            uint32_t page;              //!&amp;lt; Physical page number.
            uint32_t progress;          //!&amp;lt; Number of pages erased.
            uint32_t pages_to_erase;    //!&amp;lt; Total number of pages to erase.
        } erase;
    };
} nrf_fstorage_sd_op_t;
ANON_UNIONS_DISABLE;

typedef enum
{
    NRF_FSTORAGE_STATE_IDLE,            //!&amp;lt; No operations requested to the SoftDevice.
    NRF_FSTORAGE_STATE_OP_PENDING,      //!&amp;lt; A non-fstorage operation is pending.
    NRF_FSTORAGE_STATE_OP_EXECUTING,    //!&amp;lt; An fstorage operation is executing.
} nrf_fstorage_sd_state_t;

/**@brief   Internal state. */
typedef struct
{
    nrf_atomic_flag_t       initialized;    //!&amp;lt; fstorage is initalized.
    nrf_atomic_flag_t       queue_running;  //!&amp;lt; The queue is running.
                                            /** Prevent API calls from entering queue_process(). */
    nrf_fstorage_sd_state_t state;          //!&amp;lt; Internal fstorage state.
    uint32_t                retries;        //!&amp;lt; Number of times an operation has been retried on timeout.
    bool                    sd_enabled;     //!&amp;lt; The SoftDevice is enabled.
    bool                    paused;         //!&amp;lt; A SoftDevice state change is impending.
                                            /** Do not load a new operation when the last one completes. */
} nrf_fstorage_sd_work_t;


void nrf_fstorage_sys_evt_handler(uint32_t, void *);
bool nrf_fstorage_sdh_req_handler(nrf_sdh_req_evt_t, void *);
void nrf_fstorage_sdh_state_handler(nrf_sdh_state_evt_t, void *);


/* Flash device information. */
static nrf_fstorage_info_t m_flash_info =
{
#if   defined(NRF51)
    .erase_unit   = 1024,
#elif defined(NRF52_SERIES)
    .erase_unit   = 4096,
#endif
    .program_unit = 4,
    .rmap         = true,
    .wmap         = false,
};

/* Queue of fstorage operations. */
NRF_ATFIFO_DEF(m_fifo, nrf_fstorage_sd_op_t, NRF_FSTORAGE_SD_QUEUE_SIZE);

/* Define a nrf_sdh_soc event observer to receive SoftDevice system events. */
NRF_SDH_SOC_OBSERVER(m_sys_obs, 0, nrf_fstorage_sys_evt_handler, NULL);

/* nrf_sdh request observer. */
NRF_SDH_REQUEST_OBSERVER(m_req_obs, 0) =
{
    .handler = nrf_fstorage_sdh_req_handler,
};

/* nrf_sdh state observer. */
NRF_SDH_STATE_OBSERVER(m_state_obs, 0) =
{
    .handler = nrf_fstorage_sdh_state_handler,
};

static nrf_fstorage_sd_work_t   m_flags;        /* Internal status. */
static nrf_fstorage_sd_op_t   * m_p_cur_op;     /* The current operation being executed. */
static nrf_atfifo_item_get_t    m_iget_ctx;     /* Context for nrf_atfifo_item_get() and nrf_atfifo_item_free(). */


/* Send events to the application. */
static void event_send(nrf_fstorage_sd_op_t const * p_op, ret_code_t result)
{
    if (p_op-&amp;gt;p_fs-&amp;gt;evt_handler == NULL)
    {
        /* Nothing to do. */
        return;
    }

    nrf_fstorage_evt_t evt =
    {
        .result  = result,
        .p_param = p_op-&amp;gt;p_param,
    };

    switch (p_op-&amp;gt;op_code)
    {
        case NRF_FSTORAGE_OP_WRITE:
            evt.id    = NRF_FSTORAGE_EVT_WRITE_RESULT;
            evt.addr  = p_op-&amp;gt;write.dest;
            evt.p_src = p_op-&amp;gt;write.p_src;
            evt.len   = p_op-&amp;gt;write.len;
            break;

        case NRF_FSTORAGE_OP_ERASE:
            evt.id   = NRF_FSTORAGE_EVT_ERASE_RESULT;
            evt.addr = (p_op-&amp;gt;erase.page * m_flash_info.erase_unit);
            evt.len  = p_op-&amp;gt;erase.pages_to_erase;
            break;

        default:
            /* Should not happen. */
            break;
    }

    p_op-&amp;gt;p_fs-&amp;gt;evt_handler(&amp;amp;evt);
}


/* Write to flash. */
static uint32_t write_execute(nrf_fstorage_sd_op_t const * p_op)
{
    //uint32_t chunk_len;

    //chunk_len = MIN(p_op-&amp;gt;write.len - p_op-&amp;gt;write.offset, NRF_FSTORAGE_SD_MAX_WRITE_SIZE);
    //chunk_len = MAX(1, chunk_len / m_flash_info.program_unit);

    ///* Cast to p_src to uint32_t to perform arithmetic. */
    //uint32_t       * p_dest = (uint32_t*)(p_op-&amp;gt;write.dest + p_op-&amp;gt;write.offset);
    //uint32_t const * p_src  = (uint32_t*)((uint32_t)p_op-&amp;gt;write.p_src + p_op-&amp;gt;write.offset);
    
    //return sd_flash_write(p_dest, p_src, chunk_len);

    uint32_t err_code;
    uint32_t chunk_len;

    chunk_len = MIN(p_op-&amp;gt;write.len - p_op-&amp;gt;write.offset, NRF_FSTORAGE_SD_MAX_WRITE_SIZE);
    chunk_len = MAX(1, chunk_len / m_flash_info.program_unit);

    /* Cast to p_src to uint32_t to perform arithmetic. */
    uint32_t         p_dest = (p_op-&amp;gt;write.dest + p_op-&amp;gt;write.offset);
    uint32_t const * p_src  = (uint32_t*)((uint32_t)p_op-&amp;gt;write.p_src + p_op-&amp;gt;write.offset);
    
    err_code = nrfx_qspi_write(p_src, chunk_len, p_dest);

    sd_flash_write(NULL, NULL, chunk_len);

    return err_code;
}


/* Erase flash page(s). */
static uint32_t erase_execute(nrf_fstorage_sd_op_t const * p_op)
{
    //NRF_LOG_DEBUG(&amp;quot;Erase page number %d, progress %d&amp;quot;, p_op-&amp;gt;erase.page, p_op-&amp;gt;erase.progress);

    //return sd_flash_page_erase(p_op-&amp;gt;erase.page + p_op-&amp;gt;erase.progress);        
    
    uint32_t err_code;
    uint32_t erase_start_addr = (p_op-&amp;gt;erase.page + p_op-&amp;gt;erase.progress) * 4096;  
       
    nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, erase_start_addr);    
    
    NRF_LOG_DEBUG(&amp;quot;SD Erase page address : 0x%x&amp;quot;, erase_start_addr);

    return err_code;
}


/* Free the current queue element. */
static void queue_free(void)
{
    (void) nrf_atfifo_item_free(m_fifo, &amp;amp;m_iget_ctx);
}


/* Load a new operation from the queue. */
static bool queue_load_next(void)
{
    m_p_cur_op = nrf_atfifo_item_get(m_fifo, &amp;amp;m_iget_ctx);

    return (m_p_cur_op != NULL);
}


/* Execute an operation in the queue. */
static void queue_process(void)
{
    uint32_t rc;

    if (m_flags.state == NRF_FSTORAGE_STATE_IDLE)
    {
        if (!queue_load_next())
        {
            /* No more operations, nothing to do. */
            m_flags.queue_running = false;
            return;
        }
    }

    m_flags.state = NRF_FSTORAGE_STATE_OP_EXECUTING;
    
    switch (m_p_cur_op-&amp;gt;op_code)
    {
        case NRF_FSTORAGE_OP_WRITE:            
            rc = write_execute(m_p_cur_op);
            break;

        case NRF_FSTORAGE_OP_ERASE:
            rc = erase_execute(m_p_cur_op);
            break;

         default:
            rc = NRF_ERROR_INTERNAL;
            break;
    }
    
    NRF_LOG_DEBUG(&amp;quot;Que Excute code : %d, rc : %d&amp;quot;, m_p_cur_op-&amp;gt;op_code,rc);    
    NRF_LOG_DEBUG(&amp;quot;Queue Excute sd_enabled : %d&amp;quot;, m_flags.sd_enabled);

    if(rc != 0)
      NRF_LOG_DEBUG(&amp;quot;queue process error  0x%x&amp;quot;, rc);
    

    switch (rc)
    {
        case NRF_SUCCESS:
        {
            /* The operation was accepted by the SoftDevice.
             * If the SoftDevice is enabled, wait for a system event. Otherwise,
             * the SoftDevice call is synchronous and will not send an event so we simulate it. */
            if (!m_flags.sd_enabled)
            {
                nrf_fstorage_sys_evt_handler(NRF_EVT_FLASH_OPERATION_SUCCESS, NULL);
            }
        } break;

        case NRF_ERROR_BUSY:
        {
            /* The SoftDevice is executing a flash operation that was not requested by fstorage.
             * Stop processing the queue until a system event is received. */
            m_flags.state = NRF_FSTORAGE_STATE_OP_PENDING;
        } break;

        default:
        {
            /* An error has occurred. We cannot proceed further with this operation. */
            event_send(m_p_cur_op, NRF_ERROR_INTERNAL);
            /* Reset the internal state so we can accept other operations. */
            m_flags.state         = NRF_FSTORAGE_STATE_IDLE;
            m_flags.queue_running = false;
            /* Free the current queue element. */
            queue_free();
        } break;
    }
}


/* Start processing the queue if it is not running and fstorage is not paused. */
static void queue_start(void)
{
    NRF_LOG_DEBUG(&amp;quot;queue_start() queue_running : %d, paused : %d&amp;quot;, m_flags.queue_running, m_flags.paused);
    if (   (!nrf_atomic_flag_set_fetch(&amp;amp;m_flags.queue_running))
        &amp;amp;&amp;amp; (!m_flags.paused))
    {
        queue_process();
    }
}


/* Flash operation success callback. Keeps track of the progress of an operation. */
static bool on_operation_success(nrf_fstorage_sd_op_t * const p_op)
{
    /* Reset the retry counter on success. */
    m_flags.retries = 0;

    switch (p_op-&amp;gt;op_code)
    {
        case NRF_FSTORAGE_OP_WRITE:
        {
            /* Update the offset only if the operation is successful
             * so that it can be retried in case it times out. */
            uint32_t const chunk_len = MIN(p_op-&amp;gt;write.len - p_op-&amp;gt;write.offset,
                                           NRF_FSTORAGE_SD_MAX_WRITE_SIZE);

            p_op-&amp;gt;write.offset += chunk_len;

            if (p_op-&amp;gt;write.offset == p_op-&amp;gt;write.len)
            {
                return true;
            }
        } break;

        case NRF_FSTORAGE_OP_ERASE:
        {
            p_op-&amp;gt;erase.progress++;

            if (p_op-&amp;gt;erase.progress == p_op-&amp;gt;erase.pages_to_erase)
            {
                return true;
            }
        } break;

        default:
            /* Should not happen. */
            break;
    }

    return false;
}


/* Flash operation failure callback. */
static bool on_operation_failure(nrf_fstorage_sd_op_t const * p_op)
{
    UNUSED_PARAMETER(p_op);

    m_flags.retries++;

    if (m_flags.retries &amp;gt; NRF_FSTORAGE_SD_MAX_RETRIES)
    {
        /* Maximum amount of retries reached. Give up. */
        m_flags.retries = 0;
        return true;
    }

    return false;
}


static ret_code_t init(nrf_fstorage_t * p_fs, void * p_param)
{
    UNUSED_PARAMETER(p_param);

    p_fs-&amp;gt;p_flash_info = &amp;amp;m_flash_info;

    if (!nrf_atomic_flag_set_fetch(&amp;amp;m_flags.initialized))
    {
#if NRF_SDH_ENABLED
        m_flags.sd_enabled = nrf_sdh_is_enabled();
#endif
        (void) NRF_ATFIFO_INIT(m_fifo);
    }

    return NRF_SUCCESS;
}


static ret_code_t uninit(nrf_fstorage_t * p_fs, void * p_param)
{
    UNUSED_PARAMETER(p_fs);
    UNUSED_PARAMETER(p_param);

    /* The state is re-initialized upon init().
     * The common uninitialization code is run by the caller. */

    memset(&amp;amp;m_flags, 0x00, sizeof(m_flags));

    (void) nrf_atfifo_clear(m_fifo);

    return NRF_SUCCESS;
}


static ret_code_t write(nrf_fstorage_t const * p_fs,
                        uint32_t               dest,
                        void           const * p_src,
                        uint32_t               len,
                        void                 * p_param)
{
    nrf_fstorage_sd_op_t  * p_op;
    nrf_atfifo_item_put_t   iput_ctx;
    
    NRF_LOG_DEBUG(&amp;quot;sd Write&amp;quot;);
    /* Get a free queue element. */
    p_op = nrf_atfifo_item_alloc(m_fifo, &amp;amp;iput_ctx);

    if (p_op == NULL)
    {
        return NRF_ERROR_NO_MEM;
    }

    /* Initialize the operation. */
    memset(p_op, 0x00, sizeof(nrf_fstorage_sd_op_t));

    p_op-&amp;gt;op_code     = NRF_FSTORAGE_OP_WRITE;
    p_op-&amp;gt;p_fs        = p_fs;
    p_op-&amp;gt;p_param     = p_param;
    p_op-&amp;gt;write.dest  = dest;
    p_op-&amp;gt;write.p_src = p_src;
    p_op-&amp;gt;write.len   = len;

    /* Put the operation on the queue. */
    (void) nrf_atfifo_item_put(m_fifo, &amp;amp;iput_ctx);

    queue_start();

    return NRF_SUCCESS;
}


static ret_code_t read(nrf_fstorage_t const * p_fs, uint32_t src, void * p_dest, uint32_t len)
{
    //memcpy(p_dest, (uint32_t*)src, len);
    
    //NRF_LOG_DEBUG(&amp;quot;sd Read&amp;quot;);

    //return NRF_SUCCESS;

    ret_code_t err_code;
    err_code = nrfx_qspi_read(p_dest, len, src);
    
    return err_code;
}


static ret_code_t erase(nrf_fstorage_t const * p_fs,
                        uint32_t               page_addr,
                        uint32_t               len,
                        void                 * p_param)
{
    nrf_fstorage_sd_op_t  * p_op;
    nrf_atfifo_item_put_t   iput_ctx;

    /* Get a free queue element. */
    p_op = nrf_atfifo_item_alloc(m_fifo, &amp;amp;iput_ctx);
    
    NRF_LOG_DEBUG(&amp;quot;sd erase&amp;quot;);
    if (p_op == NULL)
    {
        return NRF_ERROR_NO_MEM;
    }

    /* Initialize the operation. */
    memset(p_op, 0x00, sizeof(nrf_fstorage_sd_op_t));

    p_op-&amp;gt;op_code              = NRF_FSTORAGE_OP_ERASE;
    p_op-&amp;gt;p_fs                 = p_fs;
    p_op-&amp;gt;p_param              = p_param;
    p_op-&amp;gt;erase.page           = (page_addr / m_flash_info.erase_unit);
    p_op-&amp;gt;erase.pages_to_erase = len;

    /* Put the operation on the queue. */
    (void) nrf_atfifo_item_put(m_fifo, &amp;amp;iput_ctx);

    queue_start();

    return NRF_SUCCESS;
}


static uint8_t const * rmap(nrf_fstorage_t const * p_fs, uint32_t addr)
{
    UNUSED_PARAMETER(p_fs);

    return (uint8_t*)addr;
}


static uint8_t * wmap(nrf_fstorage_t const * p_fs, uint32_t addr)
{
    UNUSED_PARAMETER(p_fs);
    UNUSED_PARAMETER(addr);

    /* Not supported. */
    return NULL;
}


static bool is_busy(nrf_fstorage_t const * p_fs)
{
    UNUSED_PARAMETER(p_fs);

    return (m_flags.state != NRF_FSTORAGE_STATE_IDLE);
}


void nrf_fstorage_sys_evt_handler(uint32_t sys_evt, void * p_context)
{
    UNUSED_PARAMETER(p_context);

    if (   (sys_evt != NRF_EVT_FLASH_OPERATION_SUCCESS)
        &amp;amp;&amp;amp; (sys_evt != NRF_EVT_FLASH_OPERATION_ERROR))
    {
        /* Ignore any non-flash events. */
        return;
    }

    NRF_LOG_DEBUG(&amp;quot;nrf_fstorage_sys_evt_handler() flag state %d, paused %d, sys_evt %d &amp;quot;,m_flags.state, m_flags.paused, sys_evt);

    switch (m_flags.state)
    {
        case NRF_FSTORAGE_STATE_IDLE:
            /* Ignore flash events if no flash operation was requested. */
            return;

        case NRF_FSTORAGE_STATE_OP_PENDING:
            /* The SoftDevice has completed a flash operation that was not requested by fstorage.
             * It should be possible to request an operation now.
             * Process the queue at the end of this function. */
            break;

        case NRF_FSTORAGE_STATE_OP_EXECUTING:
        {
            /* Handle the result of a flash operation initiated by this module. */
            bool operation_finished = false;

            switch (sys_evt)
            {
                case NRF_EVT_FLASH_OPERATION_SUCCESS:
                    operation_finished = on_operation_success(m_p_cur_op);
                    break;

                case NRF_EVT_FLASH_OPERATION_ERROR:
                    operation_finished = on_operation_failure(m_p_cur_op);
                    break;

                default:
                    break;
            }

            if (operation_finished)
            {
                /* The operation has finished. Change state to NRF_FSTORAGE_STATE_IDLE
                 * so that queue_process() will fetch a new operation from the queue. */
                m_flags.state = NRF_FSTORAGE_STATE_IDLE;

                event_send(m_p_cur_op, (sys_evt == NRF_EVT_FLASH_OPERATION_SUCCESS) ?
                                        NRF_SUCCESS : NRF_ERROR_TIMEOUT);
                
                NRF_LOG_DEBUG(&amp;quot;operation_finished  m_flags.state %d&amp;quot;,  m_flags.state);
                /* Free the queue element after sending out the event to prevent API calls made
                 * in the event context to queue elements indefinitely, without this function
                 * ever returning in case the SoftDevice calls are synchronous. */
                queue_free();
            }
        } break;
    }

    if (!m_flags.paused)
    {
        queue_process();
    }
    else
    {
        /* A flash operation has completed. Let the SoftDevice change state. */
        (void) nrf_sdh_request_continue();
    }
}


bool nrf_fstorage_sdh_req_handler(nrf_sdh_req_evt_t req, void * p_context)
{
    UNUSED_PARAMETER(req);
    UNUSED_PARAMETER(p_context);

    m_flags.paused = true;  
    
    NRF_LOG_DEBUG(&amp;quot;nrf_fstorage_sdh_req_handler&amp;quot;);
    /* If there are any operations ongoing, pause the SoftDevice state change. */
    return (m_flags.state == NRF_FSTORAGE_STATE_IDLE);
}


void nrf_fstorage_sdh_state_handler(nrf_sdh_state_evt_t state, void * p_context)
{
    UNUSED_PARAMETER(p_context);
    
    NRF_LOG_DEBUG(&amp;quot;nrf_fstorage_sdh_state_handler state %d&amp;quot;, state);
    if (    (state == NRF_SDH_EVT_STATE_ENABLED)
        ||  (state == NRF_SDH_EVT_STATE_DISABLED))
    {
        m_flags.paused     = false;
        m_flags.sd_enabled = (state == NRF_SDH_EVT_STATE_ENABLED);

        /* Execute any operations still in the queue. */
        queue_process();
    }
}


/* Exported API implementation. */
nrf_fstorage_api_t nrf_fstorage_sd =
{
    .init    = init,
    .uninit  = uninit,
    .read    = read,
    .write   = write,
    .erase   = erase,                           
    .rmap    = rmap,
    .wmap    = wmap,
    .is_busy = is_busy
};


#endif // NRF_FSTORAGE_ENABLED


&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: How can i write external qspi flash over BLE DFU?</title><link>https://devzone.nordicsemi.com/thread/308950?ContentTypeID=1</link><pubDate>Mon, 10 May 2021 11:54:46 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:78c1da68-70a9-4330-9bfe-71ee65561ccf</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I see the log and your modified nrf_fstorage_sd.c but I am not sure how you use this and how you intend it to work, nor how it fails. Can you elaborate by providing more overview and also details about this?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>