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

Interface External flash to nrf52832

I want to interface a 16MB external flash (SPI) with nrf52832 on the development board.Suggest me how should I start with and if there is an example for external flash then let me know. 

  • I am able to see only a high pulse on MISO line on logic analyser. I did try RDID command I am getting correct values but data which I get is always 0XFF.

  • Hi Torbjorn,

    I am able to read the data now.It was due to some hardware issues that I was not able to read on MISO line.But now I am facing issue in erasing the chip.what else do I need to send to erase chip/ sector/block with it's instruction command?

  • Hi 

    This should be described in the datasheet of your flash device. 

    If you can't find it there please share the datasheet with me, and I will have a look. 

    Best regards
    Torbjørn

  • Ok sharing with you the datasheet and the code which I am using. I added delay after CS_LOW so I am able to get the chip erase done. but still the issue is that after sending chip erase function I am not abl to write it. Also sector earse is not working ,I think I am struggling with the timing issues. I will be grateful if you can help me with these issues and make my flash running propelry.MX25R1635F, Wide Range, 16Mb, v1.6.pdf

  • and the code as below

    ///**
    // ******************************************************************************
    // * @file      ext_flash.c
    // *            This source file provides external flash memory related functionalities.
    // *
    // * @author    Glide Embedded Technology <www.glidemtech.com>
    // * @date       7, August, 2019
    // ******************************************************************************
    // */
    //
    ///* Includes ------------------------------------------------------------------*/
    ///* Includes ------------------------------------------------------------------*/
    #include <stdio.h>
    #include <string.h>
    #include <stdint.h>
    //
    #include "external_flash.h"
    #include <hal/nrf_gpio.h>
    #include <hal/nrf_spi.h>
    #include "nrf_drv_spi.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "nrf_delay.h"
    
    
    
    
    
    uint8_t print = 1;
    
    
    #define SPI_INSTANCE  0 /**< SPI instance index. */
    static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);
    
    #define WAIT_FOR_PERIPH() do { \
            while (!m_finished) {} \
            m_finished = false;    \
        } while (0)
    
    static volatile bool m_finished = false;
    
    
    static uint8_t m_buffer_tx[256];
    static uint8_t m_buffer_rx[256];
    
    //static uint8_t m_data_send[256];
    static uint8_t m_data_receive[256];
    
    #define TEST_STRING  "Z" //"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); 
    
    static uint8_t m_buffer_tx[256];
    static uint8_t m_buffer_rx[256];
    
    //static uint8_t m_data_send[256];
    static uint8_t m_data_receive[256];
    
    static uint8_t m_data_send[256] = {[0 ... 255] = 0xbb};
    uint8_t StatusReg;
    uint8_t ConfigReg;
    uint8_t SecurityReg;
    
    /**
     * @brief SPI user event handler.
     * @param event
     */
    void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                           void *                    p_context)
    {
        m_finished = true;
        uint16_t i ;
        //printf("\n\rTransfer completed.");
        if (m_buffer_rx[0] != 0)
        {
    //        printf(" Received:");
            for(i=0;i<8;i++)
            {
    //          printf("m_buffer_rx[%d] = %x ",i,m_buffer_rx[i]);
            }
            NRF_LOG_HEXDUMP_INFO(m_buffer_rx, strlen((const char *)m_buffer_rx));
        }
       // nrf_gpio_pin_set(SPI_SS_PIN);
    }
    void cs_low(void)
    {
      nrf_gpio_pin_set(SPI_SS_PIN);
    }
    
    
    void cs_high(void)
    {
      nrf_gpio_pin_clear(SPI_SS_PIN);
    }
    
    
    
    /*
     * Reset setting Command
     */
    
    /*
     * Function:       CMD_RSTEN
     * Arguments:      None.
     * Description:    Enable RST command
     * Return Message: FlashOperationSuccess
     */
    ReturnMsg cmd_rsten( void )
    {
        // Chip select go low to start a flash command
        cs_low();
    
        // Write RSTEN command
       
        uint8_t instruction = FLASH_CMD_RSTEN;
        m_buffer_tx[0] = instruction;
        
       nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,1,m_buffer_rx,1);
    
        // Chip select go high to end a flash command
        cs_high();
    
        return FlashOperationSuccess;
    }
    
    /*
     * Function:       CMD_RST
     * Arguments:      fsptr, pointer of flash status structure
     * Description:    The RST instruction is used as a system (software) reset that
     *                 puts the device in normal operating Ready mode.
     * Return Message: FlashOperationSuccess
     */
    ReturnMsg cmd_rst( void )
    {
        // Chip select go low to start a flash command
        cs_low();
    
        // Write RST command = 0x99
        
        uint8_t instruction = FLASH_CMD_RST;
        m_buffer_tx[0] = instruction;
        
       nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,1,m_buffer_rx,1);
    
        // Chip select go high to end a flash command
        cs_high();
    
     
        return FlashOperationSuccess;
    }
    
    
    
    /*
     * Function:       CMD_WRSR
     * Arguments:      UpdateValue, 8/16 bit status register value to updata
     * Description:    The WRSR instruction is for changing the values of
     *                 Status Register Bits (and configuration register)
     * Return Message: FlashIsBusy, FlashTimeOut, FlashOperationSuccess
     */
    
    //ReturnMsg cmd_wrsr( uint8_t UpdateValue )
    //
    //{
    //    // Check flash is busy or not
    //    if( IsFlashBusy() )    return FlashIsBusy;
    //
    //    // Setting Write Enable Latch bit
    //    uint8_t err_code;
    //   err_code = cmd_wren();
    //
    //    // Chip select go low to start a flash command
    ////    cs_low();
    //
    //    // Send command and update value
    //
    //    uint8_t instruction[9] = {0};
    //    instruction[0] = FLASH_CMD_WRSR;
    //    nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction,1,m_buffer_rx,3); 
    //    nrf_delay_ms(2);
    //    printf("UPDATE VALUE  = %d",UpdateValue);
    //    instruction[1]=UpdateValue;
    ////    memcpy(instruction[1],UpdateValue,8);
    //    nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction[1],2,m_buffer_rx,4); 
    //
    ////#ifdef SUPPORT_WRSR_CR
    ////    SendByte( UpdateValue >> 8, SIO );    // write configuration register
    ////#endif
    //
    //    // Chip select go high to end a flash command
    //    cs_high();
    //
    //
    //    if( WaitFlashReady( WriteStatusRegCycleTime ) )
    //        return FlashOperationSuccess;
    //    else
    //        return FlashTimeOut;
    //
    //}
    
    
    
    ReturnMsg cmd_wrsr( uint8_t UpdateValue )
    
    {
        // Check flash is busy or not
        if( IsFlashBusy() )    return FlashIsBusy;
    
        // Setting Write Enable Latch bit
        uint8_t err_code;
        uint8_t read_value;
            nrf_gpio_pin_clear(SPI_WP_PIN);
       err_code = cmd_wren();
    
        // Chip select go low to start a flash command
    //    cs_low();
    
        // Send command and update value
       err_code =  cmd_rdsr(read_value);
       printf("rdsr valu = %d \n",read_value);
       if((read_value & 2)== 1)
      {
         uint8_t instruction[9] = {0};
        instruction[0] = FLASH_CMD_WRSR;
        nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction,1,m_buffer_rx,3); 
        nrf_delay_ms(2);
        printf("UPDATE VALUE  = %d",UpdateValue);
        instruction[1]=UpdateValue;
    //    memcpy(instruction[1],UpdateValue,8);
        nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction[1],2,m_buffer_rx,4); 
    
        err_code =  cmd_rdsr(read_value);
       printf("rdsr valu = %d \n",read_value);
       if((read_value ^ 1)==1)
       {
          printf("wep is zero \n");
        
       }
    
      }
    
    
    //    uint8_t instruction[9] = {0};
    //    instruction[0] = FLASH_CMD_WRSR;
    //    nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction,1,m_buffer_rx,3); 
    //    nrf_delay_ms(2);
    //    printf("UPDATE VALUE  = %d",UpdateValue);
    //    instruction[1]=UpdateValue;
    ////    memcpy(instruction[1],UpdateValue,8);
    //    nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction[1],2,m_buffer_rx,4); 
    
    //#ifdef SUPPORT_WRSR_CR
    //    SendByte( UpdateValue >> 8, SIO );    // write configuration register
    //#endif
    
        // Chip select go high to end a flash command
        cs_high();
    
    
        if( WaitFlashReady( WriteStatusRegCycleTime ) )
            return FlashOperationSuccess;
        else
            return FlashTimeOut;
    
    }
    
    
    /*
     * Function:       CMD_RDSCUR
     * Arguments:      SecurityReg, 8 bit buffer to store security register value
     * Description:    The RDSCUR instruction is for reading the value of
     *                 Security Register bits.
     * Return Message: FlashOperationSuccess
     */
    ReturnMsg cmd_rdscur( uint8_t *SecurityReg )
    {
        uint8_t  gDataBuffer;
    
        // Chip select go low to start a flash command
        cs_low();
    
        //Send command
        
        uint8_t instruction = FLASH_CMD_RDSCUR;
        nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction,1,gDataBuffer,3); 
    
        // Chip select go high to end a flash command
        cs_high();
    
        *SecurityReg = gDataBuffer;
    
        return FlashOperationSuccess;
    
    }
    
    /*
     * Function:       CMD_WRSCUR
     * Arguments:      None.
     * Description:    The WRSCUR instruction is for changing the values of
     *                 Security Register Bits.
     * Return Message: FlashIsBusy, FlashOperationSuccess, FlashWriteRegFailed,
     *                 FlashTimeOut
     */
    ReturnMsg cmd_wrscur( void )
    {
        uint8_t  gDataBuffer;
    
        // Check flash is busy or not
        if( IsFlashBusy() )    return FlashIsBusy;
    
        // Setting Write Enable Latch bit
        cmd_wren();
    
        // Chip select go low to start a flash command
        cs_low();
    
        // Write WRSCUR command
        uint8_t instruction = FLASH_CMD_WRSCUR;
        nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction,1,gDataBuffer,3); 
    
        // Chip select go high to end a flash command
        cs_high();
    
        if( WaitFlashReady( WriteSecuRegCycleTime ) ){
    
            cmd_rdscur( &gDataBuffer );
    
            // Check security register LDSO bit
            if( (gDataBuffer & FLASH_LDSO_MASK) == FLASH_LDSO_MASK )
                    return FlashOperationSuccess;
            else
                    return FlashWriteRegFailed;
        }
        else
            return FlashTimeOut;
    
    }
    
    
    /*
     * Function:       CMD_RDID
     * Arguments:      Identification, 32 bit buffer to store id
     * Description:    The RDID instruction is to read the manufacturer ID
     *                 of 1-byte and followed by Device ID of 2-byte.
     * Return Message: FlashOperationSuccess
     */
    ReturnMsg cmd_rdid( uint32_t *Identification )
    {
        uint32_t temp;
        uint8_t  gDataBuffer[3];
    
        // Chip select go low to start a flash command
        cs_low();
    
        // Send command
    //    SendByte( FLASH_CMD_RDID, SIO );
        uint8_t instruction = FLASH_CMD_RDID;
        nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction,1,gDataBuffer,3); 
    
       
       
    
        // Chip select go high to end a command
        cs_high();
    
        // Store identification
        temp =  gDataBuffer[0];
        temp =  (temp << 8) | gDataBuffer[1];
        *Identification =  (temp << 8) | gDataBuffer[2];
        printf("rdid = %x  %x",gDataBuffer [0],gDataBuffer [1]);
    
        return FlashOperationSuccess;
    }
    
    /*
     * Function:       CMD_RES
     * Arguments:      ElectricIdentification, 8 bit buffer to store electric id
     * Description:    The RES instruction is to read the Device
     *                 electric identification of 1-byte.
     * Return Message: FlashOperationSuccess
     */
    ReturnMsg cmd_res( uint8_t *ElectricIdentification )
    {
    
        printf("cmd_res \n");
        // Chip select go low to start a flash command
        cs_low();
    
        // Send flash command and insert dummy cycle
         uint8_t instruction[4];
        instruction[0]= FLASH_CMD_RES;
        instruction[1]= 0;
        instruction[2]=0;
        instruction[3]=0;
        nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction,4,m_buffer_rx,5); 
        // Get electric identification
        *ElectricIdentification = m_buffer_rx[4];
        printf(" eid = %x\n",m_buffer_rx[4]);
        // Chip select go high to end a flash command
      cs_high();
    
        return FlashOperationSuccess;
    }
    
    /*
     * Function:       CMD_REMS
     * Arguments:      REMS_Identification, 16 bit buffer to store id
     *                 fsptr, pointer of flash status structure
     * Description:    The REMS instruction is to read the Device
     *                 manufacturer ID and electric ID of 1-byte.
     * Return Message: FlashOperationSuccess
     */
    ReturnMsg cmd_rems( uint16_t *REMS_Identification, FlashStatus *fsptr )
    {
        uint8_t  gDataBuffer[2];
    
        // Chip select go low to start a flash command
        cs_low();
    
        // Send flash command and insert dummy cycle ( if need )
        // ArrangeOpt = 0x00 will output the manufacturer's ID first
        //            = 0x01 will output electric ID first
    //    SendByte( FLASH_CMD_REMS, SIO );
    //    InsertDummyCycle( 16 );
    //    SendByte( fsptr->ArrangeOpt, SIO );
        uint8_t instruction[4];
        instruction[0]= FLASH_CMD_REMS;
        instruction[1]= 0;
        instruction[2]=0;
         instruction[3]=0x00;
        nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction,4,m_buffer_rx,6); 
        // Get ID
        gDataBuffer[0] = m_buffer_rx[2];//GetByte( SIO );
        gDataBuffer[1] = m_buffer_rx[3];//GetByte( SIO );
    
        // Store identification informaion
        *REMS_Identification = (gDataBuffer[0] << 8) | gDataBuffer[1];
    
        // Chip select go high to end a flash command
        cs_high();
    
        return FlashOperationSuccess;
    }
    
    void cmd_read( uint32_t flash_address, uint8_t *target_address, uint32_t byte_length )
    {
        uint32_t index;
        uint8_t  addr_4byte_mode;
    
        // Check flash address
        if( flash_address > FlashSize ) 
          return FlashAddressInvalid;
        nrf_delay_ms(5);
    
        // Chip select go low to start a flash command
        cs_low();
    
        // Write READ command and address
    
        uint8_t instruction;
        instruction = FLASH_CMD_READ;
        m_buffer_tx[0]= instruction;
        m_buffer_tx[1] = flash_address >> 16;
        m_buffer_tx[2] = flash_address >> 8;
        m_buffer_tx[3] = flash_address;
        nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,FLASH_CMD_READ_LENGHT,m_data_receive,FLASH_CMD_READ_LENGHT+16); 
    //    for( index=0; index < 4; index++ )
    //    {
    //      printf("m_buffer_tx[%d] = %.02x \n",index,m_buffer_tx[index]);
    //      nrf_delay_ms(10);
    //    }
       
    //    for( index=0; index < 20; index++ )
    //    {
    //      printf("m_data_receive[%d] = %.02x \n",index,m_data_receive[index]);
    //      nrf_delay_ms(10);
    //    }
    
        // Chip select go high to end a flash command
       nrf_delay_ms(500);
       cs_high();
    
        return true;
    }
    
    /*
     * Function:       Wait_Flash_WarmUp
     * Arguments:      None.
     * Description:    Wait some time until flash read / write enable.
     * Return Message: None.
     */
    void wait_flash_warm_up()
    {
        uint32_t time_cnt = FlashFullAccessTime;
        while( time_cnt > 0 )
        {
            time_cnt--;
        }
    }
    uint8_t flash_ID_test( uint8_t id )
    {
    
      uint8_t instruction[8] = {0};
    
      uint8_t id_read = id;
      switch (id_read)  
      {
                case 1:
                    
                    instruction[0] = FLASH_CMD_RES ;
                    instruction[1]= 0x00;
                    instruction[2] = 0x00;
                    instruction[3]= 0x00;
                    cs_low();
                    nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction,4,m_buffer_rx,5); 
                    nrf_delay_ms(1);
                    printf("\rValue is 1:");
                     printf("%02x,%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],m_buffer_rx[6]);
                    cs_high();
                    break;
                case 2:
                    
                    instruction[0] = FLASH_CMD_REMS ;
                    instruction[1]= 0x01;
                    instruction[2] = 0x02;
                    instruction[3]= 0x00;
                    printf("\rValue is 2:");
                    nrf_drv_spi_transfer(&spi,(uint8_t const *)instruction,4,m_buffer_rx,6); 
                    nrf_delay_ms(2);
                    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]);
                    break;
                case 3:               
                    m_buffer_tx[0] = FLASH_CMD_RDID;
                    cs_low();
    //                nrf_gpio_pin_clear(SPI_SS_PIN);
                    nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,1,m_buffer_rx,4); 
                    //nrf_delay_ms(2);
                    //nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,1,m_buffer_rx,3); 
                     nrf_delay_ms(2);
                     printf("\rValue is 3:");
                     printf("%02x,%02x,%02x\n",m_buffer_rx[1],m_buffer_rx[2],m_buffer_rx[3]);
    //                nrf_gpio_pin_set(SPI_SS_PIN);
                    cs_high();
                    break;
                default:
                    printf("Out of range");
                    break;
    
      }
    
       return true;
    }
    
    
    ReturnMsg cmd_rdsr( uint8_t *StatusReg )
    {
        uint8_t  gDataBuffer;
    
        // Chip select go low to start a flash command
        cs_low();
    
        // Send command
    
        nrf_drv_spi_transfer(&spi,FLASH_CMD_RDSR,1,gDataBuffer,1); 
        // Chip select go high to end a flash command
        cs_high();
    
        *StatusReg = gDataBuffer;
    //     printf("cmd_rdsr =  %d \n",gDataBuffer);
    
        return FlashOperationSuccess;
    }
    
    ReturnMsg cmd_rdcr( uint8_t *StatusReg )
    {
        uint8_t  gDataBuffer;
    
        // Chip select go low to start a flash command
         cs_low();
    
        // Send command
    //    SendByte( FLASH_CMD_RDSR, SIO );
    //    gDataBuffer = GetByte( SIO );
        nrf_drv_spi_transfer(&spi,FLASH_CMD_RDCR,1,gDataBuffer,1); 
        // Chip select go high to end a flash command
        cs_high();
    
        *StatusReg = gDataBuffer;
    //    printf("status register = %x \n",StatusReg);
    
        return FlashOperationSuccess;
    }
    
    
    bool IsFlashBusy( void )
    {
        uint8_t  gDataBuffer;
    
        cmd_rdsr( &gDataBuffer );
        
        if( (gDataBuffer & FLASH_WIP_MASK)  == FLASH_WIP_MASK )
            return true;
        else
            return false;
    }
    
    bool WaitFlashReady( uint32_t ExpectTime )
    {
    
        uint32_t temp = 0;
        while( IsFlashBusy() )
        {
            if( temp > ExpectTime )
            {
                return false;
            }
            temp = temp + 1;
        }
           return true;
    }
    
    ReturnMsg cmd_wren( void )
    {
        // Chip select go low to start a flash command
        cs_low();
    
        // Write Enable command = 0x06, Setting Write Enable Latch Bit
        uint8_t instruction = FLASH_CMD_WREN;
        m_buffer_tx[0] = instruction;
        
       nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,1,m_buffer_rx,1);
        // Chip select go high to end a flash command
        cs_high();
    
        return FlashOperationSuccess;
    }
    
    
    
    ReturnMsg cmd_wrdis( void )
    {
        // Chip select go low to start a flash command
        cs_low();
    
        // Write Enable command = 0x06, Setting Write Enable Latch Bit
        uint8_t instruction = FLASH_CMD_WRDI;
        m_buffer_tx[0] = instruction;
        
       nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,1,m_buffer_rx,1);
        // Chip select go high to end a flash command
        cs_high();
    
        return FlashOperationSuccess;
    }
    
    ReturnMsg cmd_pp( uint32_t flash_address, uint8_t *source_address, uint32_t byte_length )
    {
        uint32_t index;
        // Check flash address
        if( flash_address > FLASH_SIZE ) return FlashAddressInvalid;
        //
        //    // Check flash is busy or not
        if( IsFlashBusy() )    return FlashIsBusy;
    
        // Setting Write Enable Latch bit
        cmd_wren();
        
        nrf_delay_ms(5);
    
        // Chip select go low to start a flash command
        cs_low();
        nrf_delay_ms(100);
    
        // Write Page Program command
        uint8_t len = 4;
        m_buffer_tx[0]=FLASH_CMD_PP;
    //    memcpy(m_buffer_tx,instruction,4);
        //    nrf_drv_spi_transfer(&spi,instruction,len,m_buffer_rx,len+1); 
        memcpy(m_buffer_tx[4],flash_address >> 16,1);
    
        m_buffer_tx[1] = flash_address >> 16;
        m_buffer_tx[2] = flash_address >> 8;
        m_buffer_tx[3] = flash_address;
    
        for( index=4; index < 20; index++ )
        {
           m_buffer_tx[index] = source_address[index];//0xaa;
        }
         printf("\r data transmitted:  ");
               for( index=0; index < 20; index++ )
              {
                printf(" %.02x ",m_buffer_tx[index]);
                nrf_delay_ms(10);
              }
              printf("\n");
    
    //    nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,20,m_data_receive,40);
            nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,20,m_data_receive,0);
        // Chip select go high to end a flash command
        cs_high();
    
        if( WaitFlashReady( PageProgramCycleTime ) )
            return FlashOperationSuccess;
        else
          return FlashTimeOut;
    }
    
    uint8_t cmd_se( uint32_t flash_address )
    {
        // Check flash address
        if( flash_address > FLASH_SIZE ) return FlashAddressInvalid;
    
        // Check flash is busy or not
        if( IsFlashBusy() )    return FlashIsBusy;
    
        // Setting Write Enable Latch bit
        cmd_wren();
    
        // Chip select go low to start a flash command
        cs_low();
    
        //Write Sector Erase command = 0x20;
    
        m_buffer_tx[0] = FLASH_CMD_SE;
        m_buffer_tx[1] = flash_address >> 16;
        m_buffer_tx[2] = flash_address >> 8;
        m_buffer_tx[3] = flash_address;
    
        printf(" \r sectore esrase command : %0.2x,%0.2x,%0.2x,%0.2x\n ",m_buffer_tx[0],m_buffer_tx[1],m_buffer_tx[2],m_buffer_tx[3]);
    
        nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,4,m_buffer_rx,4); 
        // Chip select go high to end a flash command
        cs_high();
    
    //    if( WaitFlashReady( SectorEraseCycleTime ) )
        if( WaitFlashReady( 240000000 ))
        {
            cmd_rdscur(SecurityReg);
            printf("SecurityReg   %d \n ",SecurityReg);
            return FlashOperationSuccess;
        }
        else
            return FlashTimeOut;
    }
    
    uint8_t cmd_block_erase( uint32_t flash_address )
    {
        // Check flash address
        if( flash_address > FLASH_SIZE ) return FlashAddressInvalid;
    
        // Check flash is busy or not
        if( IsFlashBusy() )    return FlashIsBusy;
    
        // Setting Write Enable Latch bit
    //    cmd_wren();
    
        // Chip select go low to start a flash command
        cs_low();
    
        //Write Sector Erase command = 0x20;
        uint8_t instruction;
        instruction= FLASH_CMD_SE;
    //    instruction[1]= 0;
    //    instruction[2] =0;
    //    instruction[3]=0;
        m_buffer_tx[0] = instruction;
    //    memcpy(m_buffer_tx,instruction,4);
        m_buffer_tx[1] = flash_address >> 16;
        m_buffer_tx[2] = flash_address >> 8;
        m_buffer_tx[3] = flash_address;
    
    //    SendByte( FLASH_CMD_SE, SIO );
    //    SendFlashAddr( flash_address, SIO, addr_4byte_mode );
        nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,4,m_buffer_rx,4); 
        // Chip select go high to end a flash command
        cs_high();
    
        if( WaitFlashReady( SectorEraseCycleTime ) )
            return FlashOperationSuccess;
        else
            return FlashTimeOut;
    }
    
    /*
     * Function:       CMD_CE
     * Arguments:      None.
     * Description:    The CE instruction is for erasing the data
     *                 of the whole chip to be "1".
     * Return Message: FlashIsBusy, FlashOperationSuccess, FlashTimeOut
     */
    ReturnMsg cmd_ce( void )
    {
        // Check flash is busy or not
        if( IsFlashBusy() )    return FlashIsBusy;
    
        // Setting Write Enable Latch bit
        cmd_wren();
    
        // Chip select go low to start a flash command
        cs_low();
        nrf_delay_ms(100);
        //Write Chip Erase command = 0x60;
         m_buffer_tx[0] = 0xC7;//FLASH_CMD_CE;
         nrf_drv_spi_transfer(&spi,(uint8_t const *)m_buffer_tx,1,m_buffer_rx,0);
    
        // Chip select go high to end a flash command
        cs_high();
    //    cmd_rdsr(StatusReg);
    //    printf("StatusReg= %d \n",StatusReg);
    
        //if( WaitFlashReady( 60000 ) )
          nrf_delay_ms(60000);
            return FlashOperationSuccess;
    //    else
    //        return FlashTimeOut;
    //return FlashOperationSuccess;
    }
    
    
    /*
     * Simple flash read/write test
     */
    uint8_t flash_read_write_test( void )
    {
        uint8_t  message= 0;
        FlashStatus  flash_state = {0};
    
        uint32_t  flash_addr;
        uint32_t  trans_len = 0;
        uint16_t  i=0, error_cnt = 0;
        uint16_t  seed = 0;
        uint8_t   st_reg = 0;
    
        /* Assign initial condition */
        flash_addr = FLASH_TARGET_ADDR;
        trans_len = TRANS_LENGTH;
        seed = RANDOM_SEED;
    
        /* Erase 4K sector of flash memory
           Note: It needs to erase dirty sector before program */
        uint8_t err_code;
    //    err_code = cmd_ce();//cmd_block_erase(flash_addr);//cmd_se( flash_addr );
    //    printf("error code = %d \n",err_code);
    //     nrf_delay_ms(300);
    
    
    //    cmd_read( flash_addr, m_data_receive, TRANS_LENGTH );
    //     nrf_delay_ms(300);
    //
    //                printf("\r data after chip erase:  ");
    //           for( i=4; i < 20; i++ )
    //          {
    //            printf(" %.02x ",m_data_receive[i]);
    //            nrf_delay_ms(10);
    //          }
    //          printf("\n");
        
    
        /* Program data to flash memory */
        cmd_pp( flash_addr, m_data_send, TRANS_LENGTH );
        nrf_delay_ms(100);
    
        /* Read flash memory data to memory buffer */
        cmd_read( flash_addr, m_data_receive, TRANS_LENGTH );
         nrf_delay_ms(300);
    
        /* Compare original data and flash data */
        
    //    for( i=4; i < (trans_len); i=i+1 )
    //    {
    //        if( m_data_send[i] != m_data_receive[i] )
    //        {
    //            printf("wrong data \n");
    //            Error_inc( error_cnt );
    //        }
    //        else
    //         {
               printf("\r data received:  ");
               for( i=4; i < 20; i++ )
              {
                printf(" %.02x ",m_data_receive[i]);
                nrf_delay_ms(10);
              }
              printf("\n");
    
    //         }
    //    }
        
        /* Erase 4K sector of flash memory */
        cmd_ce();//cmd_block_erase(flash_addr); //cmd_se( flash_addr );
        nrf_delay_ms(240); //240    60000
    
    
        if( error_cnt != 0 )
            return false;
        else
            return true;
    
    }
    uint8_t ext_flash_init(void)
    {
    
        uint8_t retval = false;
    
        /* Configure SPI pins */
        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.mode     = NRF_DRV_SPI_MODE_0;
        spi_config.frequency= NRF_DRV_SPI_FREQ_125K;
        APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
    
        nrf_gpio_pin_set(SPI_WP_PIN);
    
        uint8_t err_code;
        cmd_rsten();
        cmd_rst();
        err_code = cmd_wrdis();
    
        /* Set CS pin to High*/
    
    //    cs_high();
    
        wait_flash_warm_up();
        nrf_delay_ms(100);
        flash_ID_test(2);
    
        /* read and verify manufacturer and device id from external flash to ensure external flash is working */
        if(flash_ID_test(2) == true)
        {
           return true;
        }
    
    
    
        return retval;
    }
    
    
    

Related