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

Problem Interfacing SPI external Flash and writing to the Flash Registers

Hi,

I am trying to interface  External Flash (IS25LP064A ) using SPI example in SDK v16. I am able to read the Manufacturer_ID and the device ID from the external flash. Now I want to Read, write and Erase the flash. But I am unable to do so. Please tell me if any example is there or the way how to do that .

Please give any example code to interface SPI flash.

Parents
  • HI Amanda,

    Here is my complete code. and here is the data sheet. http://www.issi.com/WW/pdf/25LP032-64A-B.pdf. I am trying to read and write data to flash. But I am unable to write or read. Also I am unable to set the WEL using WREN command. The only output I am getting after reading a status register or any adress is 0. Please let me know what's the missing things in my code. Please help me with any example code if u have or please let me know what is wrong or missing in my code.

    /**
     * Copyright (c) 2015 - 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 "nrf_drv_spi.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"
    
    
    
    /* Flash memory parameters */
    #define FLASH_PAGESIZE          256                     /* 256 Bytes */         /**< External Flash - Page Size */
    #define FLASH_SECTORSIZE        (16 * FLASH_PAGESIZE)	/* 16 Pages = 4KB */    /**< External Flash - Sector Size */
    #define FLASH_BLOCKSIZE		(16 * FLASH_SECTORSIZE)	/* 16 Sectors = 64KB */ /**< External Flash - Block Size */
    #define FLASH_SIZE              (128 * FLASH_BLOCKSIZE)	/* 128 Blocks = 8MB */  /**< External Flash - Total Memory Size */
    #define FLASH_BLOCK32K		(32 * 1024)		/* 32KB Block */   
    #define FLASH_PAGESIZE_OFFSET    0x000100
    
    
    #define REG_SR_BIT_WIP    0
    #define READ_WRITE_LENGTH 200
    #define SPI_INSTANCE  0 /**< SPI instance index. */
    static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
    static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */
    
    
    #define WAIT_FOR_PERIPH() do { \
            while (!m_finished) {} \
            m_finished = false;    \
        } while (0)
    
    #define TEST_STRING "Nordic"
    static uint8_t       m_tx_buf[] = TEST_STRING;           /**< TX buffer. */
    static uint8_t       m_rx_buf[sizeof(TEST_STRING) + 1];    /**< RX buffer. */
    static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */
    
    
    
    static uint8_t m_buffer_rx[256];
    static uint8_t m_buffer_tx[256];
    
    
    void cs_low(void)
    {
    
      nrf_gpio_pin_clear(SPI_SS_PIN);
    }
    
    void cs_high(void)
    {
    
       nrf_gpio_pin_set(SPI_SS_PIN);
    }
    
    
    uint8_t flash_ID_test( uint8_t id )
    {
      ret_code_t err_code;
      static uint8_t instruction[8] = {0};
      
      uint8_t id_read = id;
      switch (id_read)  
      {
                case 1:
                    
                    instruction[0] = 0xAB ;//RDID Command: Read Manufacturer and Product ID
                    instruction[1] = 0x00;
                    instruction[2] = 0x00;
                    instruction[3] = 0x00;
    
                   spi_xfer_done = false;
                   cs_low();
                   err_code = nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction,sizeof(instruction),m_buffer_rx,7);
                   if(err_code == NRF_SUCCESS)
                   {
                        printf("RDID Transfer Successful\n");
                   }
                   printf("Flash_ID_1: %d\n",err_code);
                   while(spi_xfer_done == false)
                   {}
                   printf("\rDevice ID is :");
                   printf("%02x \n",m_buffer_rx[4]);
                   cs_high();
                   break;
                case 2:
                    
                    instruction[0] = 0x90 ;//Read Manufacturer and Device ID
                    instruction[1]= 0x00;
                    instruction[2] = 0x00;
                    instruction[3]= 0x00;
    
                    spi_xfer_done = false;
                    memset(m_buffer_rx,0x00,sizeof(m_buffer_rx));
                    cs_low();
                    nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction,sizeof(instruction),m_buffer_rx,8); 
                   if(err_code == NRF_SUCCESS)
                   {
                        printf("RDID_2 Transfer Successful\n");
                   }
                   while(spi_xfer_done == false)
                   {}
    
                    printf("Flash_ID_2: %d\n",err_code);
                    cs_high();
    //                printf("%02x,%02x,%02x,%02x,%02x,%02x\n",m_buffer_rx[0],m_buffer_rx[1],m_buffer_rx[2],m_buffer_rx[3],m_buffer_rx[4],m_buffer_rx[5]);
                     printf(" Manufacturer_ID: %02x,Device_ID:%02x\n",m_buffer_rx[4],m_buffer_rx[5]);
    //                printf("%d,%d,%d,%d,%d,%d\n",m_buffer_rx[0],m_buffer_rx[1],m_buffer_rx[2],m_buffer_rx[3],m_buffer_rx[4],m_buffer_rx[5]);
                    break;
                case 3:               
                    m_buffer_tx[0] = 0x9f;//FLASH_CMD_RDID
                     spi_xfer_done = false;
    
                    
                    cs_low();
    //                nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,1,m_buffer_rx,4); 
    
                    err_code = nrf_drv_spi_transfer(&spi,m_buffer_tx,1,m_buffer_rx,5);
                    nrf_delay_ms(2);
                    if(err_code == NRF_SUCCESS)
                    {
                        printf("RDID_3 Transfer Successful\n");
                    }
                    while(spi_xfer_done == false){}
                     printf("Flash_ID_3: %d\n",err_code);
                 
                    printf("Manufacturer_ID: %02x Memory_Type : %02x, Capacity:%02x\n",m_buffer_rx[1],m_buffer_rx[2],m_buffer_rx[3]);
                    cs_high();
                    break;
                    
                    default:
                        printf("Out of range");
                    break;
    
      }
    
       return err_code;
    }
    
    
    
    
    
    void enable_software_request(void)
    {
    	cs_low();
    	uint8_t rsten = 0x66;
    	m_buffer_tx[0] = rsten;
    	
    	nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,1,m_buffer_rx,1);
    	
    	cs_high();
    	printf("Flash Enable Software request(RTSEN) Successful\n");
    }
    
    
    
    void reset_software()
    {
    	cs_low();
    	uint8_t rst = 0x99;
    	m_buffer_tx[0] = rst;
    	
    	nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,1,m_buffer_rx,1);
    	cs_high();
    	printf("Flash Software reset successful\n");
    }
    
    void disable_write()
    {
            ret_code_t err_code;
            spi_xfer_done = false;
    	
            cs_low();
    	uint8_t wrdi = 0x04;
    	m_buffer_tx[0] = wrdi;
    	
    	err_code = nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,1,m_buffer_rx,1);
    
    	
            cs_high();
    	
    	printf("Flash disable write opearation successful\n");
    }
    
    uint8_t read_status_register()
    {
         ret_code_t err_code;
         spi_xfer_done = false;
         uint8_t data;
         static uint8_t spi_tx_cmd[2];
         static uint8_t spi_rx_cmd[2];
         uint8_t RDSR =0x05;
        
         cs_low();
    
         spi_tx_cmd[0] = RDSR;
         spi_tx_cmd[1] = 0x00;
    
         err_code = nrf_drv_spi_transfer(&spi,(uint8_t const *)spi_tx_cmd,2,spi_rx_cmd,2);
          printf("Status_Reg_Err_code : %d\n",err_code);
    
          printf("Rdsr-stat: %02X\n",spi_rx_cmd[0]);
          printf("Rdsd stat %02X\n",spi_rx_cmd[1]);
         if(err_code == NRF_SUCCESS)
         {
            printf("RDSR Transfer Successful\n");
         }
         while(spi_xfer_done == false)   {}
    
        cs_high();
    
    
        return  data;
    }
    
    
    void write_enable()
    {
        ret_code_t err_code;
         spi_xfer_done = false;
        
        uint8_t status_register;
        uint8_t spi_tx_cmd[1];
    
        cs_low();
        uint8_t WREN = 0x06;
        spi_tx_cmd[0] = WREN;
    
        err_code = nrf_drv_spi_transfer(&spi,spi_tx_cmd,sizeof(spi_tx_cmd),NULL,0);
        printf("Write_enable_err_code : %d\n",err_code);
    
        if(err_code == NRF_SUCCESS)
        {
           printf("WREN Transfer Successful\n");
        }
        while(spi_xfer_done == false)   {}
    
    
    
    //    cs_high();
    
    //    printf("Flash Write Enable Latch operation successful\n");
    }
    
    
    
    void write_status_register(uint8_t newStatus)
    {
      ret_code_t err_code;
      spi_xfer_done = false;
      uint8_t WRSR = 0x01;
      static uint8_t spi_tx_cmd[2];
      static uint8_t spi_rx_cmd[2];
      cs_low();
      spi_tx_cmd[0] = WRSR;
      spi_tx_cmd[1] = newStatus;
    
      nrf_drv_spi_transfer(&spi,(uint8_t const *)spi_tx_cmd,2,spi_rx_cmd,1);
    
      if(err_code = NRF_SUCCESS)
       {
          printf("RDID Transfer Successful\n");
       }
       while(spi_xfer_done == false)   {}
    
      cs_high();
    
    }
    
    uint8_t read_function_register()
    {
         ret_code_t err_code;
         spi_xfer_done = false;
    
         uint8_t data ;
         uint8_t RDFR = 0x48;
         static uint8_t spi_tx_cmd[2];
         static uint8_t spi_rx_cmd[2];
    
       
    
         cs_low();
         spi_tx_cmd[0] = RDFR;
         spi_tx_cmd[1] = 0x00;
    
         err_code = nrf_drv_spi_transfer(&spi,(uint8_t const *)spi_tx_cmd,sizeof(spi_tx_cmd),spi_rx_cmd,sizeof(spi_rx_cmd));
    
         if(err_code = NRF_SUCCESS)
         {
            printf("RDFR Transfer Successful\n");
         }
         while(spi_xfer_done == false)   {}
    
         cs_high();
    //     printf("%02x\n",spi_rx_cmd[1]);
    //     printf("%02x\n",data);
    //     printf("%02d\n",data);
    
           return  data;
    }
    
    void write_function_register( uint8_t newValue)
    {
        ret_code_t err_code;
        spi_xfer_done = false;
    
        uint8_t WRFR = 0x42;
        static uint8_t spi_tx_cmd[2];
        static uint8_t spi_rx_cmd[2];
        cs_low();
        spi_tx_cmd[0] = WRFR;
        spi_tx_cmd[1] = newValue;
    
       err_code = nrf_drv_spi_transfer(&spi,(uint8_t const *)spi_tx_cmd,2,spi_rx_cmd,1);
       printf("WRFR Err_code: %d\n",err_code);
    
        if(err_code == NRF_SUCCESS)
        {
           printf("WRFR Transfer Successful\n");
        }
        while(spi_xfer_done == false)   {}
        
        cs_high();
    
    }
    
    
    void program_page(uint32_t address, uint8_t *data_ptr, uint32_t data_length)
    {
         int i=0;
         ret_code_t err_code;
    
          uint8_t CMD_PROGRAM = 0x02;
          uint8_t spi_tx_cmd[] = {CMD_PROGRAM, (address >> 16) & 0xFF, (address >> 8) & 0xFF, (address >> 0) & 0xFF};
    
          uint8_t spi_rx_cmd[8];
          write_enable();
    
    
    //      read_status_register();
    
          cs_low();
          spi_xfer_done = false;
          err_code =  nrf_drv_spi_transfer(&spi, (uint8_t const *)spi_tx_cmd, sizeof(spi_tx_cmd),spi_rx_cmd,1);
    
           if(err_code == NRF_SUCCESS)
           {
             printf("RDID Transfer Successful\n");
           }
         while(spi_xfer_done == false)   {}
            printf("Program_page_Err_2: %d\n",err_code);
    
          while(data_length > 255)
          {  
              spi_xfer_done = false;
              err_code = nrf_drv_spi_transfer(&spi,data_ptr,255,0,0);
    
              if(err_code == NRF_SUCCESS)
              {
                 printf("RDID Transfer Successful\n");
              }
              while(spi_xfer_done == false)   {}
                 printf("Program_page_Err_3: %d\n",err_code);
              data_ptr = data_ptr + 255;
              data_length = data_length - 255;
          }
          spi_xfer_done = false;
         err_code = nrf_drv_spi_transfer(&spi, data_ptr, data_length,m_buffer_rx,0);
          if(err_code == NRF_SUCCESS)
          {
             printf("RDID Transfer Successful\n");
          }
          while(spi_xfer_done == false)   {}
             printf("Program_page_Err_4: %d\n",err_code);
    
          cs_high();
    }
    
    
    void normal_read(uint32_t address, uint8_t * data_ptr, uint32_t data_length)
    {
         ret_code_t err_code;
        
         
         uint8_t CMD_READ = 0x03;
    
         uint8_t spi_tx_cmd[] = {CMD_READ, (address >> 16) & 0xFF, (address >> 8) & 0xFF, (address >> 0) & 0xFF};
         static uint8_t spi_rx_cmd[256];
    
         spi_xfer_done = false;
    
         cs_low();
     
    //   data = nrf_drv_spi_transfer(&spi, spi_tx_cmd, sizeof(spi_tx_cmd), spi_rx_cmd,sizeof(spi_rx_cmd));
         err_code = nrf_drv_spi_transfer(&spi, spi_tx_cmd, sizeof(spi_tx_cmd), spi_rx_cmd,4);
          if(err_code == NRF_SUCCESS)
          {
             printf("RDID Transfer Successful\n");
          }
          while(spi_xfer_done == false)   {}
         
          while(data_length > 255)
          {
             spi_xfer_done = false;
            err_code = nrf_drv_spi_transfer(&spi, 0, 0, data_ptr, 255);
            if(err_code == NRF_SUCCESS)
            {
               printf("RDID Transfer Successful\n");
            }
            while(spi_xfer_done == false)   {}
            data_ptr += 255;
            data_length -= 255;
          }
           spi_xfer_done = false;
           err_code = nrf_drv_spi_transfer(&spi, 0, 0, data_ptr, data_length);
           if(err_code == NRF_SUCCESS)
            {
               printf("RDID Transfer Successful\n");
            }
            while(spi_xfer_done == false)   {}
    
    
          cs_high();
    
    
    }
    
    
    
    void sector_erase(uint32_t address)
    {
        uint8_t CMD_SECTOR_ERASE = 0x20;
        uint8_t spi_tx_cmd[] = {CMD_SECTOR_ERASE, (address >> 16) & 0xFF, (address >> 8) & 0xFF, (address >> 0) & 0xFF};
    
       
    
        cs_low();
        write_enable();
           uint8_t WREN = 0x06;
           uint8_t spi_tx_cmd_1[1];
           spi_tx_cmd_1[0] = WREN;
            
           nrf_drv_spi_transfer(&spi,spi_tx_cmd_1,sizeof(spi_tx_cmd_1),0,0); // Enabling Write
       
        nrf_drv_spi_transfer(&spi, spi_tx_cmd, sizeof(spi_tx_cmd), 0, 0);
       cs_high();
    }
    
    void block_erase(uint32_t address)
    {
        uint8_t CMD_BLOCK_ERASE = 0xd8;
        uint8_t spi_tx_cmd[] = {CMD_BLOCK_ERASE, (address >> 16) & 0xFF, (address >> 8) & 0xFF, (address >> 0) & 0xFF};
        write_enable();
        cs_low();
    
        nrf_drv_spi_transfer(&spi, spi_tx_cmd, sizeof(spi_tx_cmd), 0, 0);
       cs_high();
    }
    
    
    void chip_erase(void)
    {
        uint8_t CMD_CHIP_ERASE = 0x60;
       uint8_t spi_tx_cmd[] = {CMD_CHIP_ERASE};
    
        write_enable();
        cs_low();
          nrf_drv_spi_transfer(&spi, spi_tx_cmd, sizeof(spi_tx_cmd), 0, 0);
        cs_high();
    }
    
    
    
    /**
     * @brief SPI user event handler.
     * @param event
     */
    void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                           void *                    p_context)
    {
        spi_xfer_done = true;
        NRF_LOG_INFO("Transfer completed.");
        if (m_rx_buf[0] != 0)
        {
            NRF_LOG_INFO(" Received:");
            NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
        }
    }
    
    void flash_spi_init()
    {   ret_code_t err_code;
        nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
        
        spi_config.ss_pin   = SPI_SS_PIN;
        spi_config.miso_pin = SPI_MISO_PIN;
        spi_config.mosi_pin = SPI_MOSI_PIN;
        spi_config.sck_pin  = SPI_SCK_PIN;
        spi_config.frequency = NRF_DRV_SPI_FREQ_125K;
        
        APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
        nrf_delay_ms(100);
    }
    
    void flash_access_switch()
    {
      
        uint8_t man_id, dev_id, status_register, function_register;
        uint8_t data_buf[READ_WRITE_LENGTH] ;
    
        char str_buff[50] ="Hello";
        char str_read_buff[50] ={0};
    
        uint8_t data_read_buffer[READ_WRITE_LENGTH];
        uint32_t address;
        uint8_t choice;
        address = 0x1000;
    
         uint8_t var =10;
    
         while(1)
         {
         
             printf("Enter your choice\n");
             printf("1.Flash_ID_test\n2.Read status Register\n3.Read Function register\n4.Normal read\n5. Enable write\n6.Sector erase\n");
             printf("7.Program Page\n8.Block Erase\r\n ");
    
             scanf("%d",&choice);
    	
    	
              switch(choice)
              {
                  case 1:
                      flash_ID_test(3);
    
                  case 2:
                       status_register = read_status_register();
    
                       printf("Status: %i\r\n", (int)status_register);
                      break;
    
                  case 3:
                      function_register = read_function_register();
                      printf("Function: %i\r\n", (int)function_register);
                      break;
    
                  case 4:
               
                      normal_read(address, data_read_buffer, 50);
                      printf("Reading address %.8x: ", address);
                      for(int i = 0; i < 50; i++)
                      {
                              printf("%d\r\n" ,(int)data_read_buffer[i]);
                      }
                      printf("\r\n");
                      break;
    
                  case 5:
                      printf("Running write enable\r\n");
                      write_enable();
                      break;
            
                  case 6:
                      printf("Running sector erase at address %8x\r\n",address);
                      sector_erase(address);
                      break;
    
                  case 7:
                      for(int i =0; i < 50; i++) 
                      {
             
                          data_buf[i] = var;
                          var++;
                      }
       
                      program_page(address, data_buf,sizeof(data_buf));
     
           
                      printf("Programming data at address %.8X\r\n", address);
                      break;
    	
                  case 8:
                      printf("Erasing block at addres %.8X\r\n",address);
                      block_erase(address);
                      break;
    
              } //switch
    
         }//while
    
     } // function 
    
    
    
    
    int main(void)
    {
          //spi_xfer_done = false;
    
        bsp_board_init(BSP_INIT_LEDS);
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
    
        error_info_t err_code;
        flash_spi_init(); 
        flash_ID_test(3);
     
    
        flash_access_switch();
       
          
        while (1)
        {
            // Reset rx buffer and transfer done flag
            memset(m_rx_buf, 0, m_length);
            spi_xfer_done = false;
    
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, m_length, m_rx_buf, m_length));
    
            while (!spi_xfer_done)
            {
                __WFE();
            }
    
            NRF_LOG_FLUSH();
    
            bsp_board_led_invert(BSP_BOARD_LED_0);
            nrf_delay_ms(200);
        }
    }
    

  • Hi, 

    Mushtakh Shaikh said:
    I am unable to set the WEL using WREN command.

    Did you get any error, out log, or logic trance of the SPI bus for the write_enable()?

     

    Mushtakh Shaikh said:
    The only output I am getting after reading a status register or any adress is 0.

     Could you try to increase the rx_buffer_length to 4 as this suggestion?

    -Amanda H.  

  • After write_enable, I am getting the following output.

    RDID_3 Transfer Successful
    Flash_ID_3: 0
    Manufacturer_ID: 9d Memory_Type : 60, Capacity:17
    Write_enable_err_code : 0
    WREN Transfer Successful

  • This is the output when after read_status_register();

    I have changed the rx_buffer_length to 4 as per your suggestion.Still I am unable to write the data to flash and read the data from flash. Please help me with any code example if u have.  

    Status_Reg_Err_code : 0
    Rdsr-stat: 00
    Rdsd stat 00
    RDSR Transfer Successful

  • Hi, 

    Can u please tell me what went  wrong in my code ?? 

Reply Children
Related