This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to use external Flash memory on PCA10056 board.

Hello :)

I am using pca10056.
Use SPIM to control the external flush memory of this board.
I read the IC's surface, I recognized its name is MX25R6435F. (Is it correct ?)

I tried to check the behavior by creating the following simple program using nrf5 SDK ver15.3 and SEGGER, but the MISO signal did not change.

What is wrong?

When changing the settings of lines 51 to 54 of this program and using another pin, the reaction was obtained from an EEPROM with the same instruction code.

Thank you as always.
Best regards.

/**
 * Copyright (c) 2017 - 2019, 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 "AS IS" 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 "nrfx_spim.h"
#include "app_util_platform.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "boards.h"
#include "app_error.h"
#include <string.h>
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#define NRFX_SPIM_SCK_PIN   19 // 47
#define NRFX_SPIM_MOSI_PIN  20 // 45
#define NRFX_SPIM_MISO_PIN  21 // 46
#define NRFX_SPIM_SS_PIN    17 // 44

#define SPI_INSTANCE  3                                           /**< SPI instance index. */
static const nrfx_spim_t spi = NRFX_SPIM_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */

static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */

static uint8_t       m_tx_buf[5];           /**< TX buffer. */
static uint8_t       m_rx_buf[5];           /**< RX buffer. */
static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */

void spim_event_handler(nrfx_spim_evt_t const * p_event,
                       void *                  p_context)
{
    spi_xfer_done = true;
    printf("  Transmitted:\t");
    for(int i=0;i<(sizeof(m_tx_buf)/sizeof(m_tx_buf[0]));i++)
    {
        printf("%d\t",m_tx_buf[i]);
    }
    printf("\n");

    printf("  Received:\t");
    for(int i=0;i<(sizeof(m_rx_buf)/sizeof(m_rx_buf[0]));i++)
    {
        printf("%d\t",m_rx_buf[i]);
    }
    printf("\n");
}

void InitSPIM(void)
{
    nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
    spi_config.frequency      = NRF_SPIM_FREQ_1M;
    spi_config.ss_pin         = NRFX_SPIM_SS_PIN;
    spi_config.miso_pin       = NRFX_SPIM_MISO_PIN;
    spi_config.mosi_pin       = NRFX_SPIM_MOSI_PIN;
    spi_config.sck_pin        = NRFX_SPIM_SCK_PIN;
    spi_config.use_hw_ss      = true;
    spi_config.ss_active_high = false;

    APP_ERROR_CHECK(nrfx_spim_init(&spi, &spi_config, spim_event_handler, NULL));

}

void OpRDSR(void)
{
    nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(m_tx_buf, m_length, m_rx_buf, m_length);

    /* RDSR (Read status register:0000 0101) */
    printf("**RDSR(ReaD Status Register)**\n");
    memset(m_tx_buf, 0x00, m_length);
    m_tx_buf[0] = 5;//0b00000101;

    memset(m_rx_buf, 0, m_length);
    spi_xfer_done = false;

    APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, false));
//    APP_ERROR_CHECK(nrfx_spim_xfer_dcx(&spi, &xfer_desc, 0, 15));

    while (!spi_xfer_done)
    {
        __WFE();
    }
}

void OpWREN(void)
{
    nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(m_tx_buf, m_length, m_rx_buf, m_length);

    /* WREN (Write enable:0000 0110) */
    printf("**WREN(WRite ENable)**\n");
    memset(m_tx_buf, 0, m_length);
    m_tx_buf[0] = 0b00000110;

    memset(m_rx_buf, 0, m_length);
    spi_xfer_done = false;   
    APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, false));
    while (!spi_xfer_done)
    {
        __WFE();
    }
}

void OpWRDI(void)
{
    nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(m_tx_buf, m_length, m_rx_buf, m_length);

    /* WRDI (Write disable:0000 0100) */
    printf("**WRDI(WRite DIsable)**\n");
    memset(m_tx_buf, 0, m_length);
    m_tx_buf[0] = 0b00000100;

    memset(m_rx_buf, 0, m_length);
    spi_xfer_done = false;   
    APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, false));
    while (!spi_xfer_done)
    {
        __WFE();
    }
}

/* Test1:RDSR->WREN->RDSR->WRDI->RDSR */
/* Confirm Status Registers change */
void Test1(void)
{
    OpRDSR();

    OpWREN();

    OpRDSR();
    
    OpWRDI();

    OpRDSR();

}

int main(void)
{
    bsp_board_init(BSP_INIT_LEDS);

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    InitSPIM();

    /* Set WP and HOLD*/
    nrf_gpio_cfg_output(22);
    nrf_gpio_pin_set(22);
    nrf_gpio_cfg_output(23);
    nrf_gpio_pin_set(23);

    Test1();

    while (1)
    {
        __WFE();
    }
}

Parents
  • Hi,

    There is an example for this in <SDK_InstallFolder>\examples\peripheral\qspi. See this link.

  • Hi, Sigurd

    I saw the qspi example, but I didn't get any ideas for sqi (or spim) control.
    Is it not able to use that for control flash memory?

  • Daichi said:
    MISO signal did not change

     Do you get any data back at all?

    What did e.g. the Read Satus Register command return ?

  • What did e.g. the Read Satus Register command return ?

    The commands were sent in the following order:
    RSTEN-> RST-> RDSR-> WREN-> RDSR-> WRDI.
    Nothing came back in any RDSR.

  • The code below works for me. Tested using SDK 16.

    I used nrf_log with RTT for logging( in sdk_config.h)

    NRF_LOG_BACKEND_RTT_ENABLED 1
    NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED 0

    Code:

    /**
     * Copyright (c) 2017 - 2019, 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 "AS IS" 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 "nrfx_spim.h"
    #include "app_util_platform.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    #include "boards.h"
    #include "app_error.h"
    #include <string.h>
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #define NRFX_SPIM_SCK_PIN   19 // 47
    #define NRFX_SPIM_MOSI_PIN  20 // 45
    #define NRFX_SPIM_MISO_PIN  21 // 46
    #define NRFX_SPIM_SS_PIN    17 // 44
    #define NRFX_SPIM_DCX_PIN  NRFX_SPIM_PIN_NOT_USED
    
    #define CMD_READ      0x03  // x1 Normal Read Data Byte 
    #define CMD_FREAD     0x0B  // x1 Fast Read Data Byte
    #define CMD_2READ     0xBB  // x2 2READ 
    #define CMD_DREAD     0x3B  // x2 DREAD 
    #define CMD_4READ     0xEB  // x4 4READ 
    #define CMD_QREAD     0x6B  // x4 QREAD 
    #define CMD_PP        0x02  // Page Program 
    #define CMD_4PP       0x38  // x4 PP
    #define CMD_SE        0x20  // 4KB Sector Erase 
    #define CMD_32KBE     0x52  // 32KB Block Erase 
    #define CMD_BE        0xD8  // 64KB Block Erase 
    #define CMD_CE        0xC7  // Chip Erase 
    #define CMD_RDSFDP    0x5A  // Read SFDP 
    #define CMD_WREN      0x06  // Write Enable 
    #define CMD_WRDI      0x04  // Write Disable
    #define CMD_RDSR      0x05  // Read Status Register 
    #define CMD_RDCR      0x15  // Read Configuration Register 
    #define CMD_WRSR      0x01  // Write Status Register
    #define CMD_PESUS     0xB0  // Program/Erase Suspend 
    #define CMD_PERES     0x30  // Program/Erase Resume
    #define CMD_DP        0xB9  // Enter Deep Power Down 
    #define CMD_SBL       0xC0  // Set Burst Length 
    #define CMD_RDID      0x9F  // Read Manufacturer and JDEC Device ID 
    #define CMD_REMS      0x90  // Read Electronic Manufacturer and Device ID
    #define CMD_RES       0xAB  // Read Electronic ID
    #define CMD_ENSO      0xB1  // Enter Secure OTP
    #define CMD_EXSO      0xC1  // Exit Secure OTP
    #define CMD_RDSCUR    0x2B  // Read Security Register
    #define CMD_WRSCUR    0x2F  // Write Security Register
    #define CMD_NOP       0x00  // No Operation
    #define CMD_RSTEN     0x66  // Reset Enable 
    #define CMD_RST       0x99  // Reset 
    #define CMD_RRE       0xFF  // Release Read Enhanced Mode
    
    #define DUMMY          0x00 // Dummy byte
    
    #define SPI_INSTANCE  3                                           /**< SPI instance index. */
    static const nrfx_spim_t spi = NRFX_SPIM_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
    
    static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */
    
    #define BUFF_LENGTH  255
    static uint8_t       m_tx_buf[BUFF_LENGTH];
    static uint8_t       m_rx_buf[BUFF_LENGTH+1];             /**< RX buffer. */
    static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */
    
    void spim_event_handler(nrfx_spim_evt_t const * p_event,
                           void *                  p_context)
    {
        spi_xfer_done = true;
        NRF_LOG_INFO("Transfer completed.");
        if (p_event->xfer_desc.rx_length != 0)
        {
            NRF_LOG_INFO(" Data Received:");
            for (int i = 0; i < p_event->xfer_desc.rx_length; i++)
            {
                NRF_LOG_INFO("m_rx_buf[%d]: 0x%x",i,m_rx_buf[i] );
            }
        }
        NRF_LOG_FLUSH();
    }
    
    void MX25R6435F_data_transfer(uint8_t tx_length, uint8_t rx_length)
    {
        spi_xfer_done = false;
    
        nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(m_tx_buf, tx_length, m_rx_buf, rx_length);
    
        APP_ERROR_CHECK(nrfx_spim_xfer(&spi, &xfer_desc, false));
        while (!spi_xfer_done)
        {
            __WFE();
        }
    }
    
    void clear_buffer(void)
    {
        memset(m_tx_buf, 0x00, BUFF_LENGTH);
        memset(m_rx_buf, 0x00, BUFF_LENGTH);
    }
    
    void OpRDID(void)
    {
        NRF_LOG_INFO("RDID(Read ID)");
        clear_buffer();
    
        m_tx_buf[0] = CMD_RDID;
    
        uint8_t tx_length = 1;
        uint8_t rx_length = 4;
    
        MX25R6435F_data_transfer(tx_length,rx_length);
    
    }
    
    
    void OpRDSR(void)
    {
        NRF_LOG_INFO("RDSR(ReaD Status Register)");
        clear_buffer();
    
        m_tx_buf[0] = CMD_RDSR;
    
        uint8_t tx_length = 1;
        uint8_t rx_length = 2;
    
        MX25R6435F_data_transfer(tx_length,rx_length);
    
    }
    
    void OpWREN(void)
    {
        NRF_LOG_INFO("WREN(WRite ENable)");
        clear_buffer();
    
        m_tx_buf[0] = CMD_WREN;
    
        uint8_t tx_length = 1;
        uint8_t rx_length = 0;
    
        MX25R6435F_data_transfer(tx_length,rx_length);
    
    }
    
    void OpWRDI(void)
    {
        NRF_LOG_INFO("WREN(WRite Disable)");
        clear_buffer();
        m_tx_buf[0] = CMD_WRDI;
    
        uint8_t tx_length = 1;
        uint8_t rx_length = 0;
    
        MX25R6435F_data_transfer(tx_length,rx_length);
    
    }
    
    void init_spim(void)
    {
        nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
        spi_config.frequency      = NRF_SPIM_FREQ_4M;
        spi_config.ss_pin         = NRFX_SPIM_SS_PIN;
        spi_config.miso_pin       = NRFX_SPIM_MISO_PIN;
        spi_config.mosi_pin       = NRFX_SPIM_MOSI_PIN;
        spi_config.sck_pin        = NRFX_SPIM_SCK_PIN;
        spi_config.use_hw_ss      = true;
        spi_config.ss_active_high = false;
    
        APP_ERROR_CHECK(nrfx_spim_init(&spi, &spi_config, spim_event_handler, NULL));
    
    }
    
    /* test_1: */
    void test_1(void)
    {
        OpRDID();
        OpRDSR();
        OpWREN();
        nrf_delay_ms(250);
        OpRDSR();
    
    }
    
    
    
    static void idle_state_handle(void)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            __WFE();
        }
    }
    
    int main(void)
    {
        bsp_board_init(BSP_INIT_LEDS);
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(m_tx_buf, m_length, m_rx_buf, m_length);
    
        init_spim();
    
        NRF_LOG_INFO("NRFX SPIM example started.");
    
        test_1();
    
        while (1)
        {
            idle_state_handle();
        }
    }

  • Hi, Sigurd. Sorry for my late reply.

    Your code works for me, too!
    I will try a lot to understand flash memory.
    Thank you!

  • Hi Sigurd,

    I am working on similar issue but i am using nRF5340 dk i have tested spi_flash example in NCS which is based on qspi i want to use it with spi but when i try to read id it returns 0xff which means no response at MOSI. I tried to use qspi but the drivers for qspi are not exposed can you help me with this

    Regards

    Ahtasham

Reply Children
No Data
Related