<?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>Missing data when reading from the NAND Flash (SPIM3 32MHz) to USB MSC</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/111373/missing-data-when-reading-from-the-nand-flash-spim3-32mhz-to-usb-msc</link><description>Hello we are using custom board nrf52840 with nRF SDK 15.2.0 on SEGGER Embedded Studio 
 I hope someone can help me with this issue. I am using SPIM3 to communicate with the NAND Flash AS5F18G04SND-10LIN (1GB). The read/write functions for communicating</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Fri, 24 May 2024 13:09:31 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/111373/missing-data-when-reading-from-the-nand-flash-spim3-32mhz-to-usb-msc" /><item><title>RE: Missing data when reading from the NAND Flash (SPIM3 32MHz) to USB MSC</title><link>https://devzone.nordicsemi.com/thread/485829?ContentTypeID=1</link><pubDate>Fri, 24 May 2024 13:09:31 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:5b603c0a-6b20-4a77-8ed6-4f5c2ad98723</guid><dc:creator>Jared</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;The code looked ok. I can&amp;#39;t see anything that would result in the loss of data.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;What frequency are you using and how far down in frequency do you need to decrease it to not return&amp;nbsp;&lt;span&gt;NRFX_ERROR_BUSY&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;regards&lt;/p&gt;
&lt;p&gt;Jared&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Missing data when reading from the NAND Flash (SPIM3 32MHz) to USB MSC</title><link>https://devzone.nordicsemi.com/thread/485440?ContentTypeID=1</link><pubDate>Wed, 22 May 2024 13:42:48 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:0fbe0eb0-7644-4bd9-9167-38a47843d9d9</guid><dc:creator>Nhat Tran</dc:creator><description>&lt;p&gt;Thanks for your support!&lt;/p&gt;
&lt;p&gt;You can see my implementation for &lt;code&gt;spi_block_dev&lt;/code&gt; and &lt;code&gt;usb_msc&lt;/code&gt; in this &lt;a href="https://drive.google.com/drive/folders/1PQNy7C-Mj0EoH8MwAnHtGhdrpxpsSEn_?usp=sharing"&gt;folder link&lt;/a&gt;. My flash block write size is 4096 bytes&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;block_dev_spi_read_req()&lt;/code&gt; and &lt;code&gt;block_dev_spi_write_req()&lt;/code&gt;, I use my custom flash interface &lt;code&gt;disk_read&lt;/code&gt;() and &lt;code&gt;disk_write&lt;/code&gt;()&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;disk_read&lt;/code&gt;() and &lt;code&gt;disk_write&lt;/code&gt;() functions will be ported to the Dhara library as shown below:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;int dhara_map_read(struct dhara_map * m, dhara_sector_t s, uint8_t * data, dhara_error_t * err)
{
    const struct dhara_nand * n = m-&amp;gt;journal.nand;
    dhara_error_t my_err;
    dhara_page_t p;

    if (dhara_map_find(m, s, &amp;amp;p, &amp;amp;my_err) &amp;lt; 0)
    {
        if (my_err == DHARA_E_NOT_FOUND)
        {
            memset(data, 0xff, 1 &amp;lt;&amp;lt; n-&amp;gt;log2_page_size);
            return 0;
        }

        dhara_set_error(err, my_err);
        return -1;
    }

    return dhara_nand_read(n, p, 0, 1 &amp;lt;&amp;lt; n-&amp;gt;log2_page_size, data, err);
}

int dhara_map_write(
    struct dhara_map * m, dhara_sector_t dst, const uint8_t * data, dhara_error_t * err)
{
    for (;;)
    {
        uint8_t meta[DHARA_META_SIZE];
        dhara_error_t my_err;
        const dhara_sector_t old_count = m-&amp;gt;count;

        if (prepare_write(m, dst, meta, err) &amp;lt; 0)
            return -1;

        if (!dhara_journal_enqueue(&amp;amp;m-&amp;gt;journal, data, meta, &amp;amp;my_err))
            break;

        m-&amp;gt;count = old_count;

        if (try_recover(m, my_err, err) &amp;lt; 0)
            return -1;
    }

    return 0;
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Below is the part of the program where I communicate with the flash via SPIM3:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;const nrfx_spim_t spi_flash = NRFX_SPIM_INSTANCE(3);
void spi_flash_init()
{
    nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
    spi_config.ss_pin = NRFX_SPIM_PIN_NOT_USED;
    spi_config.miso_pin = FLASH_SPI_MISO_PIN;
    spi_config.mosi_pin = FLASH_SPI_MOSI_PIN;
    spi_config.sck_pin = FLASH_SPI_SCK_PIN;
    spi_config.frequency = NRF_SPIM_FREQ_32M;
    APP_ERROR_CHECK(nrfx_spim_init(&amp;amp;spi_flash, &amp;amp;spi_config, spi_event_handler, NULL));
    nrf_gpio_cfg_output(FLASH_SPI_SS_PIN);
    nrf_gpio_pin_set(FLASH_SPI_SS_PIN);
}
void restart_spim3(void)
{
    *(volatile uint32_t *)0x4002FFFC = 0; 
    *(volatile uint32_t *)0x4002FFFC; 
    *(volatile uint32_t *)0x4002FFFC = 1; 
}
/*
 * Function:      spi_flash_write
 * Arguments:	  _spi,       spi instance
 *                addr,      address to be written to.
 * 		  byte_count, number of byte to write.
 *                wr_buff,     Pointer to a data buffer where the write data
 * will be stored. wr_cmd,     write command code to be written to the flash.
 * Return Value:  SUCCESS.
 *                FAILURE.
 * Description:   This function prepares the data to be written and put them
 * into data buffer, then call nrf_drv_spi_transfer function to start a write
 * data transfer.
 */

ret_code_t spi_flash_write(nrfx_spim_t const * const _spi, uint32_t addr, uint32_t byte_count,
    const uint8_t * wr_buff, uint8_t wr_cmd)
{
    restart_spim3();
    uint8_t * ptr = write_buffer;
    uint8_t iter, rem, i;
    uint32_t len_inst;
    uint32_t transfer_bytes;
    uint32_t count = 3500;
    ret_code_t status;
    len_inst = len_cmd + len_addr;
    write_buffer[0] = wr_cmd;
    addr_to_cmd(addr, write_buffer);
    memcpy(write_buffer + len_inst, wr_buff, byte_count);
    transfer_bytes = byte_count + len_inst;
    iter = transfer_bytes / SPI_MAX_DATA_SIZE;
    rem = transfer_bytes % SPI_MAX_DATA_SIZE;
    //NRF_LOG_INFO(&amp;quot;To Transfer %u Iter %u Rem %u&amp;quot;,transfer_bytes,iter,rem);
    nrf_gpio_pin_clear(FLASH_SPI_SS_PIN);
    for (i = 0; i &amp;lt;= iter; i++)
    {
        spi_xfer_done = false;
        xfer_desc.p_rx_buffer = read_buffer;
        xfer_desc.p_tx_buffer = ptr;
        if (i == iter)
        {
            xfer_desc.rx_length = rem;
            xfer_desc.tx_length = rem;
            status = nrfx_spim_xfer(_spi, &amp;amp;xfer_desc,NULL);
        }
        else
        {
            xfer_desc.rx_length = SPI_MAX_DATA_SIZE;
            xfer_desc.tx_length = SPI_MAX_DATA_SIZE;
            status =
                nrfx_spim_xfer(_spi, &amp;amp;xfer_desc,NULL);
            ptr = ptr + SPI_MAX_DATA_SIZE;
        }
        msg(&amp;quot;status: %d&amp;quot;, status);
#if 0
        while(!spi_xfer_done)
        {
            __WFE();
        }
#else
        while (!spi_xfer_done &amp;amp;&amp;amp; count &amp;gt; 0)
        {
            //__WFE();
            count--;
        }
        if(count == 0)
        {
            restart_spim3();
            nrf_gpio_pin_set(FLASH_SPI_SS_PIN);
        }
#endif
        if (status != NRF_SUCCESS)
            return FAILURE;
    }
    nrf_gpio_pin_set(FLASH_SPI_SS_PIN);
    return SUCCESS;
}

/*
 * Function:      spi_flash_read
 * Arguments:	  _spi,       spi instance
 *                addr,      address to be written to.
 * 		  byte_count, number of byte to write.
 *                rd_buff,     Pointer to a data buffer where the write data
 * will be stored. rd_cmd,     write command code to be written to the flash.
 * Return Value:  SUCCESS.
 *                FAILURE.
 * Description:   This function calls nrf_drv_spi_transfer to start a read data
 * transfer and puts the data into data buffer
 */

ret_code_t spi_flash_read(nrfx_spim_t const * const _spi, uint32_t addr, uint32_t byte_count,
    uint8_t * rd_buff, uint8_t rd_cmd)
{
    restart_spim3();
    uint32_t len_inst;
    uint32_t transfer_bytes;
    uint16_t iter, rem;
    uint32_t count = 3500;
    ret_code_t status;
    uint8_t * ptr = read_buffer;
    len_inst = len_cmd + len_addr + len_dummy;
    write_buffer[0] = rd_cmd;
    addr_to_cmd(addr, write_buffer);
    if (len_dummy)
        write_buffer[1 + len_addr] = 0xFF;
    transfer_bytes = byte_count + len_inst;
    iter = transfer_bytes / SPI_MAX_DATA_SIZE;
    rem = transfer_bytes % SPI_MAX_DATA_SIZE;
    //NRF_LOG_INFO(&amp;quot;To Transfer %u Iter %u Rem %u&amp;quot;,transfer_bytes,iter,rem);
    nrf_gpio_pin_clear(FLASH_SPI_SS_PIN);
    for (uint8_t i = 0; i &amp;lt;= iter; i++)
    {
        spi_xfer_done = false;
        //NRF_LOG_INFO(&amp;quot;Iter %d&amp;quot;,i);
        xfer_desc.p_rx_buffer = ptr;
        xfer_desc.p_tx_buffer = write_buffer;
        if (i == iter)
        {
            xfer_desc.rx_length = rem;
            xfer_desc.tx_length = rem;
            status = nrfx_spim_xfer(_spi, &amp;amp;xfer_desc,NULL);
            
        }
        else
        {
            xfer_desc.rx_length = SPI_MAX_DATA_SIZE;
            xfer_desc.tx_length = SPI_MAX_DATA_SIZE;
            status = nrfx_spim_xfer(_spi, &amp;amp;xfer_desc,NULL);
            ptr = ptr + SPI_MAX_DATA_SIZE;
            
        }
        msg(&amp;quot;status: %d&amp;quot;, status);
#if 0
        while(!spi_xfer_done)
        {
            __WFE();
        }
#else
        while (!spi_xfer_done &amp;amp;&amp;amp; count &amp;gt; 0)
        {
            //__WFE();
            count --;
        }
        if(count == 0)
        {
            restart_spim3();
            nrf_gpio_pin_set(FLASH_SPI_SS_PIN);
            //return FAILURE;
        }
#endif
        if (status != NRF_SUCCESS)
            return FAILURE;
    }
    nrf_gpio_pin_set(FLASH_SPI_SS_PIN);
    memcpy(rd_buff, read_buffer + len_inst, byte_count);
   // msg(&amp;quot;spi_flash_read: 0x%x 0x%x\n&amp;quot;, rd_buff[0], rd_buff[1]);
    return SUCCESS;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;When running USB MSC, there are times when error code 17 (NRFX_ERROR_BUSY) is returned from &lt;code&gt;nrfx_spim_xfer()&lt;/code&gt; in spi_flash_read / spi_flash_write&amp;nbsp; This error code prevents me from reading data from the flash. This issue occurs periodically. Every time I test, the error occurs at the same fixed blocks (so all the times I miss data, it is always at the same spots). The data misses only change when I adjust the clock frequency of SPIM3 or when I increase the &lt;code&gt;MSC_WORKBUFFER_SIZE&lt;/code&gt;. Please note that SPIM3 only encounters error 17 when called by USB MSC, and it works very well outside of USB MSC. I also retried reading up to 10 times when there was an error, but all of my retries returned error code 17(NRFX_ERROR_BUSY).&lt;/p&gt;
&lt;p&gt;This is my sdk_config.h for SPI:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// &amp;lt;e&amp;gt; SPI0_ENABLED - Enable SPI0 instance
//==========================================================
#ifndef SPI0_ENABLED
#define SPI0_ENABLED 1
#endif
// &amp;lt;q&amp;gt; SPI0_USE_EASY_DMA  - Use EasyDMA
 

#ifndef SPI0_USE_EASY_DMA
#define SPI0_USE_EASY_DMA 1
#endif

// &amp;lt;/e&amp;gt;

// &amp;lt;e&amp;gt; SPI1_ENABLED - Enable SPI1 instance
//==========================================================
#ifndef SPI1_ENABLED
#define SPI1_ENABLED 0
#endif
// &amp;lt;q&amp;gt; SPI1_USE_EASY_DMA  - Use EasyDMA
 

#ifndef SPI1_USE_EASY_DMA
#define SPI1_USE_EASY_DMA 1
#endif



// &amp;lt;/e&amp;gt;

// &amp;lt;e&amp;gt; SPI2_ENABLED - Enable SPI2 instance
//==========================================================
#ifndef SPI2_ENABLED
#define SPI2_ENABLED 1
#endif
// &amp;lt;q&amp;gt; SPI2_USE_EASY_DMA  - Use EasyDMA
 

#ifndef SPI2_USE_EASY_DMA
#define SPI2_USE_EASY_DMA 1
#endif


// &amp;lt;e&amp;gt; NRFX_SPIM_ENABLED - nrfx_spim - SPIM peripheral driver
//==========================================================
#ifndef NRFX_SPIM_ENABLED
#define NRFX_SPIM_ENABLED 1
#endif
// &amp;lt;q&amp;gt; NRFX_SPIM0_ENABLED  - Enable SPIM0 instance
 

#ifndef NRFX_SPIM0_ENABLED
#define NRFX_SPIM0_ENABLED 0
#endif

// &amp;lt;q&amp;gt; NRFX_SPIM1_ENABLED  - Enable SPIM1 instance
 

#ifndef NRFX_SPIM1_ENABLED
#define NRFX_SPIM1_ENABLED 0
#endif

// &amp;lt;q&amp;gt; NRFX_SPIM2_ENABLED  - Enable SPIM2 instance
 

#ifndef NRFX_SPIM2_ENABLED
#define NRFX_SPIM2_ENABLED 2
#endif

// &amp;lt;q&amp;gt; NRFX_SPIM3_ENABLED  - Enable SPIM3 instance
 

#ifndef NRFX_SPIM3_ENABLED
#define NRFX_SPIM3_ENABLED 3
#endif

// &amp;lt;q&amp;gt; NRFX_SPIM_EXTENDED_ENABLED  - Enable extended SPIM features
 

#ifndef NRFX_SPIM_EXTENDED_ENABLED
#define NRFX_SPIM_EXTENDED_ENABLED 0
#endif&lt;/pre&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Missing data when reading from the NAND Flash (SPIM3 32MHz) to USB MSC</title><link>https://devzone.nordicsemi.com/thread/485410?ContentTypeID=1</link><pubDate>Wed, 22 May 2024 12:29:21 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:fd754596-76ac-40bb-8c95-9ff0e296e173</guid><dc:creator>Jared</dc:creator><description>&lt;p&gt;Hi there,&lt;/p&gt;
&lt;p&gt;Can you describe in more detail how you have implemented the USB MSC write and read functions with the external flash through SPIM?&lt;/p&gt;
&lt;p&gt;Code examples would be great,&lt;/p&gt;
&lt;p&gt;Also, have you tried changing the SPIM instance and see if the issue is still reproducible?&lt;/p&gt;
&lt;p&gt;regards&lt;/p&gt;
&lt;p&gt;Jared&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>