mx25l1606e SPI FLASH驱动代码

13 篇文章 4 订阅
3 篇文章 0 订阅

mx25l1606e SPI FLASH驱动代码

1. yc_drv_mx25l1606e.c

#include <stdint.h>
#include <string.h>

#include "nrf_drv_spi.h"
#include "yc_drv_mx25l1606e.h"

#include "nrf_delay.h"
#include "yc_ssd1306.h"

extern void nrf_delay_us(uint32_t volatile number_of_us);
extern nrf_drv_spi_t SPI_0;

#define flash_delay_us(n)    nrf_delay_us(n);
#define flash_delay_ms(n)    nrf_delay_ms(n);

#define FLASH_CS_LOW()           {nrf_drv_gpiote_out_clear(FLASH_SPI_CS);\
														      nrf_drv_gpiote_out_set(OLED_SPI_CS);}
#define FLASH_CS_HIGH()           nrf_drv_gpiote_out_set(FLASH_SPI_CS)

static uint32_t flash_spi_write(uint8_t byte);
static uint32_t flash_spi_transfer(uint8_t  * p_tx_buf,
                                   uint8_t         tx_buf_len,
                                   uint8_t       * p_rx_buf,
                                   uint8_t         rx_buf_len);
//static uint32_t flash_write_status(uint8_t flash_status);
static uint32_t flash_read_status(void);
static uint32_t wait_for_ready(void);
static uint32_t flash_write_enable(bool enable);

static uint32_t get_manufacture_info(uint8_t *manuf_id, uint8_t *device_id);
static uint32_t flash_power(bool up_or_own);


static uint32_t flash_spi_write(uint8_t byte)
{
    uint32_t err_code=0;
    err_code = nrf_drv_spi_transfer(&SPI_0, &byte, 1, NULL, 0);
    if(err_code)
    {
        DRV_printf("!!!flash_spi_write ERROR(0x%02X)\n",err_code);
    }
    return err_code;
}
static uint32_t flash_spi_read(uint8_t *rx_buf, uint8_t rx_len)
{
    uint32_t err_code=0;
    err_code = nrf_drv_spi_transfer(&SPI_0, NULL, NULL, rx_buf, rx_len);
    if(err_code)
    {
        DRV_printf("!!!flash_spi_read ERROR(0x%02X)\n",err_code);
    }
    return err_code;
}

static uint32_t flash_spi_transfer(uint8_t  * p_tx_buf,\
                                   uint8_t         tx_buf_len,\
                                   uint8_t       * p_rx_buf,\
                                   uint8_t         rx_buf_len)
{
    uint32_t err_code=0;
    err_code  = nrf_drv_spi_transfer(&SPI_0, p_tx_buf, tx_buf_len, NULL, 0);
    err_code += nrf_drv_spi_transfer(&SPI_0, NULL, 0, p_rx_buf, rx_buf_len);
    if(err_code)
    {
        DRV_printf("!!!flash_spi_transfer ERROR(0x%02X)\n",err_code);
    }
    return err_code;
}
static uint32_t flash_power(bool up_or_down)
{
    uint32_t err_code = FLASH_SUCCESS;
    flash_delay_us(100);
    FLASH_CS_LOW();
    if(!up_or_down)
    {
        err_code = flash_spi_write(MX25L1606E_PWR_DOWN_CMD);  //0xB9
    }
    else
    {
        err_code = flash_spi_write(MX25L1606E_PWR_UP_CMD);  //0xAB
    }

    FLASH_CS_HIGH();
    nrf_delay_us(9);
    return err_code;
}

#if 0
/************************************************************************************/
static uint32_t flash_write_status(uint8_t flash_status)
{
    uint32_t err_code = FLASH_SUCCESS;
    uint8_t buf[2];
    buf[0] = MX25L1606E_WRSR_CMD;
    buf[1] = flash_status;
    FLASH_CS_LOW();
    err_code = flash_spi_transfer(buf,2,NULL,0);
    if(err_code)
    {
        DRV_printf("!!!flash_write_status ERROR(0x%02X)\n",err_code);
    }
    FLASH_CS_HIGH();
    return err_code;
}
#endif
/**************************************************************************/
/*!
    @brief Gets the value of the Read Status Register (0x05)

    @return     The 8-bit value returned by the Read Status Register
*/
/**************************************************************************/
static uint32_t flash_read_status(void)
{
    uint32_t err_code = FLASH_SUCCESS;
    uint8_t buf[2],status;
    FLASH_CS_LOW();
    err_code = flash_spi_write(MX25L1606E_READ_STATUS_CMD);// Send read status cmd
    err_code += flash_spi_read(buf, 2);           	// Dummy write
    if(err_code)
    {
        DRV_printf("!!!flash_read_status ERROR(0x%02X)\n",err_code);
    }
    FLASH_CS_HIGH();
    status =	buf[0];
    return status & (FLASH_STAT_BUSY | FLASH_STAT_WRTEN);
}

/**************************************************************************/
/*!
    @brief  Waits for the SPI flash to indicate that it is ready (not
            busy) or until a timeout occurs.

    @return An error message indicating that a timeoout occured
            (SPIFLASH_ERROR_TIMEOUT_READY) or an OK signal to indicate that
            the SPI flash is ready (SPIFLASH_ERROR_OK)
*/
/**************************************************************************/
static uint32_t wait_for_ready(void)
{
    uint32_t timeout = 0,err_code = FLASH_SUCCESS;
    uint8_t  status;

    while ( timeout < 1000 )
    {
        status = flash_read_status() & FLASH_STAT_BUSY;
        if (status == 0)
        {
            break;
        }
        timeout++;
    }
    if ( timeout == 1000 )
    {
        // In this case, 1 equals an error so we can say "if(results) ..."
        err_code = FLASH_ERROR_TIMEOUT_READY;
        DRV_printf("!!!wait_for_ready FLASH_ERROR_TIMEOUT_READY(0x%02X)\n",err_code);
        return err_code;
    }
    return err_code;
}

/**************************************************************************/
/*!
    @brief  Gets the unique 24-bit ID assigned to this IC (useful for
            security purposes to detect if the flash was changed, etc.)

    @param[out] *device_unique_id
                Pointer to the uint32_t device_unique_id that will store
                the 24 byte long unique ID

    @note   The unique ID is return in bit order 23..0
*/
/**************************************************************************/
uint32_t get_unique_id(uint32_t *device_unique_id)
{
    uint32_t err_code = FLASH_SUCCESS;
    uint8_t  buf[3];
    flash_power(up);
    memset(buf,0,3);
    if (wait_for_ready())
    {
        DRV_printf("!!!get_unique_id FLASH_ERROR_TIMEOUT_READY\n");
        return FLASH_ERROR_TIMEOUT_READY;
    }
    FLASH_CS_LOW();
    err_code  = flash_spi_write(MX25L1606E_RDID_CMD);
    err_code += flash_spi_read(buf, 3);
    FLASH_CS_HIGH();
    flash_power(down);
//		DRV_HEX_printf("",buf,10);
    *device_unique_id=0;
    *device_unique_id = (((uint32_t)buf[0]<<16) + ((uint32_t)buf[1]<<8) + buf[2]);
    return err_code;
}

/**************************************************************************/
/*!
    @brief Gets the 8-bit manufacturer ID and device ID for the flash

    @param[out] *manuf_id
                Pointer to the uint8_t that will store the manufacturer ID
    @param[out] *device_id
                Pointer to the uint8_t that will store the device ID
*/
/**************************************************************************/
static uint32_t get_manufacture_info(uint8_t *manuf_id, uint8_t *device_id)
{
    uint32_t err_code = FLASH_SUCCESS;
    uint8_t  buf[4];
    flash_power(up);
    memset(buf,0,4);
    if (wait_for_ready())
    {
        DRV_printf("!!!get_manufacture_info FLASH_ERROR_TIMEOUT_READY\n");
        return FLASH_ERROR_TIMEOUT_READY;
    }
    FLASH_CS_LOW();
    buf[0] = MX25L1606E_REMS_CMD;
    buf[1] = 0x00;	// Dummy write
    buf[2] = 0x00;	// Dummy write
    buf[3] = 0x00;	// 0x00 = manufacturer first,0x01 = device ID  first
    err_code = flash_spi_transfer(buf,4,NULL,0);
    memset(buf,0,4);
    err_code += flash_spi_read(buf, 4);
//		DRV_HEX_printf("",buf,10);
    FLASH_CS_HIGH();
    flash_power(down);
    *manuf_id  = buf[0];
    *device_id = buf[1];
    return err_code;
}



/**************************************************************************/
/*!
    @brief Sets the write flag on the MX25L1606E, and if required puts the
           WP pin in an appropriate state

    @param[in]  enable
                True (1) to enable writing, false (0) to disable it
*/
/**************************************************************************/
static uint32_t flash_write_enable(bool enable)
{
    uint32_t err_code = FLASH_SUCCESS;
    FLASH_CS_LOW();
    err_code = flash_spi_write(enable?MX25L1606E_WREN_CMD:MX25L1606E_WRDI_CMD);
    if(err_code)
    {
        DRV_printf("!!!flash_write_enable ERROR(0x%02X)\n",err_code);
    }
    FLASH_CS_HIGH();
    return err_code;
}

/***********************************************************************************************/


/**************************************************************************/
/*!
    @brief Reads the specified number of bytes from the supplied address.

    This function will read one or more bytes starting at the supplied
    address. Please note that bufferLength is zero-based, meaning you
    should  supply '0' to read a single byte, '3' to read 4 bytes of data,
    etc.

    @param[in]  address
                The 24-bit address where the read will start.
    @param[out] *buffer
                Pointer to the buffer that will store the read results
    @param[in]  len
                Length of the buffer.
*/
/**************************************************************************/
uint32_t flash_read_buffer(uint32_t address, uint8_t *buffer, uint32_t len)
{
    uint8_t buf[4],size=0;
    uint32_t err_code = FLASH_SUCCESS,n = 0,spi_transfer_times=0;
		flash_power(up);
    // Make sure the address is valid
    if (address >= MX25L1606E_TOTAL_SIZE)
    {
			  flash_power(down);
        DRV_printf("!!!flash_read_buffer FLASH_ERROR_LENGTH\n");
        return FLASH_ERROR_LENGTH;
    }
    // Wait until the device is ready or a timeout occurs
    if (wait_for_ready())
    {
				flash_power(down);
        DRV_printf("!!!flash_read_buffer FLASH_ERROR_TIMEOUT_READY\n");
        return FLASH_ERROR_TIMEOUT_READY;
    }
 
    len = ((address + len) > MX25L1606E_TOTAL_SIZE)?(MX25L1606E_TOTAL_SIZE - address):len;

    FLASH_CS_LOW();

    buf[0] = MX25L1606E_READ_CMD;// 0x03 read data command
    spi_transfer_times = len/FLASH_SPI_SINGLE_TRANSFER_MAX_SIZE + 1;

    buf[1] = (uint8_t)((address >> 16) & 0x000000FF);     // address upper 8;
    buf[2] = (uint8_t)((address >> 8) & 0x000000FF);      // address mid 8;
    buf[3] = (uint8_t)(address & 0x000000FF);             // address lower 8;
    err_code = flash_spi_transfer(buf, 4, NULL, 0);
    for (uint8_t i=0; i<spi_transfer_times; i++	) // Fill response buffer
    {
        // 24 bit addr
        size = (len < 256 ? len : 255);
        err_code +=flash_spi_transfer(NULL, 0 , &buffer[n], size);
        n += size;
        len -=size;
    }
//		DRV_HEX_printf("xxxxRead Buf:",buffer,30);
    FLASH_CS_HIGH();
    flash_power(down);
    // Return bytes written
    if(!err_code)
    {
        return n;
    }
    else
    {
        DRV_printf("!!!flash_read_buffer FLASH_ERROR_SPI_TRANSFER\n");
        return 0;
    }
}
/**************************************************************************/
/*!
    @brief Erases the contents of a single sector

    @param[in]  sectorNumber
                The sector number to erase (zero-based).
*/
/**************************************************************************/
uint32_t flash_erase_sector (uint32_t sector_number)
{
    uint8_t buf[4];
    flash_power(up); 
	// Make sure the address is valid
    if (sector_number >= MX25L1606E_SECTORS)
    {
        DRV_printf("!!!flash_read_buffer FLASH_PARAM\n");
        return FLASH_PARAM;
    }

    // Wait until the device is ready or a timeout occurs
    if (wait_for_ready())
    {
				flash_power(down);
        DRV_printf("!!!flash_erase_sector FLASH_ERROR_TIMEOUT_READY\n");
        return FLASH_ERROR_TIMEOUT_READY;
    }

    // Make sure the chip is write enabled
    flash_write_enable (true);

    // Make sure the write enable latch is actually set
    uint8_t status;
    status = flash_read_status();
    if (!(status & FLASH_STAT_WRTEN))
    {
        DRV_printf("!!!flash_read_buffer FLASH_ERROR_STATUS\n");
        // Throw a write protection error (write enable latch not set)

        flash_power(down);
        return FLASH_ERROR_STATUS;
    }

    // Send the erase sector command
    uint32_t address = sector_number * MX25L1606E_SECTOR_SIZE;
    FLASH_CS_LOW();

    buf[0] = MX25L1606E_SECTOR_ERASE_CMD;
    buf[1] = (uint8_t)((address >> 16) & 0x000000FF);     // address upper 8;
    buf[2] = (uint8_t)((address >> 8) & 0x000000FF);      // address mid 8;
    buf[3] = (uint8_t)(address & 0x000000FF);             // address lower 8;

    flash_spi_transfer(buf, 4,NULL, 0);
    FLASH_CS_HIGH();

    // Wait until the busy bit is cleared before exiting
    // This can take up to 400ms according to the datasheet
    while(flash_read_status() & FLASH_STAT_BUSY);
    flash_power(down);
    return FLASH_SUCCESS;
}

/**************************************************************************/
/*!
    @brief Erases the entire flash chip
*/
/**************************************************************************/
uint32_t flash_erase_chip (void)
{
    uint8_t status;
    DRV_printf("A");
    flash_power(up);
    // Wait until the device is ready or a timeout occurs
    if (wait_for_ready())
    {
        flash_power(down);
        return FLASH_ERROR_TIMEOUT_READY;
    }

    DRV_printf("B");
    status = flash_read_status();
    DRV_printf("Stat: 0x%02X\n",status);
    // Make sure the chip is write enabled
    flash_write_enable(true);

    DRV_printf("C");
    // Make sure the write enable latch is actually set
    status = flash_read_status();
    DRV_printf("Stat: 0x%02X\n",flash_read_status());
    if (!(status & FLASH_STAT_WRTEN))
    {
        flash_power(down);
        // Throw a write protection error (write enable latch not set)
        return FLASH_ERROR_STATUS;
    }

    DRV_printf("D");

    // Send the erase chip command
    FLASH_CS_LOW();
    flash_spi_write(MX25L1606E_CHIP_ERASE_CMD);
    FLASH_CS_HIGH();

    DRV_printf("Stat: 0x%02X\n",flash_read_status());


    DRV_printf("E");

    // Wait until the busy bit is cleared before exiting
    // This can take up to 10 seconds according to the datasheet!
    while (flash_read_status() & FLASH_STAT_BUSY)
    {
        DRV_printf("Stat: 0x%02X\n",flash_read_status());
    }
    flash_power(down);
    return FLASH_SUCCESS;
}

/**************************************************************************/
/*!
    @brief      Writes up to 256 bytes of data to the specified page.

    @note       Before writing data to a page, make sure that the 4K sector
                containing the specific page has been erased, otherwise the
                data will be meaningless.

    @param[in]  address
                The 24-bit address where the write will start.
    @param[out] *buffer
                Pointer to the buffer that will store the read results
    @param[in]  len
                Length of the buffer.  Valid values are from 1 to 256,
                within the limits of the starting address and page length.
*/
/**************************************************************************/
uint32_t flash_write_page(uint32_t address,const uint8_t *buffer, uint32_t len)
{
    uint32_t err_code = FLASH_SUCCESS;
    uint8_t status,buf[5];

    // Make sure the address is valid
    if (address >= MX25L1606E_MAX_ADDRESS)
    {
        DRV_printf("!!!flash_read_buffer FLASH_PARAM\n");
        return FLASH_PARAM;
    }

    // Make sure that the supplied data is no larger than the page size
    if (len > MX25L1606E_PAGE_SIZE)
    {
        DRV_printf("!!!flash_read_buffer FLASH_ERROR_LENGTH\n");
        return FLASH_ERROR_LENGTH;
    }

    // Make sure that the data won't wrap around to the beginning of the sector
    if ((address % MX25L1606E_PAGE_SIZE) + len > MX25L1606E_PAGE_SIZE)
    {
        // If you try to write to a page beyond the last byte, it will
        // wrap around to the start of the page, almost certainly
        // messing up your data
        DRV_printf("!!!flash_read_buffer FLASH_ERROR_LENGTH\n");
        return FLASH_ERROR_LENGTH;
    }
    flash_power(up);
    // Wait until the device is ready or a timeout occurs
    if (wait_for_ready())
    {
        flash_power(down);
			  DRV_printf("!!!flash_erase_sector FLASH_ERROR_TIMEOUT_READY\n");
        return FLASH_ERROR_STATUS;
    }

    // Make sure the chip is write enabled
    flash_write_enable(true);

    // Make sure the write enable latch is actually set
    status = flash_read_status();
//			DRV_printf("Stat: 0x%02X\n",flash_read_status());
    if (!(status & FLASH_STAT_WRTEN))
    {
        flash_power(down);
        DRV_printf("!!!flash_write_page FLASH_ERROR_STATUS(0x%02X)\n",status);
        // Throw a write protection error (write enable latch not set)
        return FLASH_ERROR_STATUS;
    }

    FLASH_CS_LOW();

    buf[0] = MX25L1606E_PAGE_WRITE_CMD;
    buf[1] = (uint8_t)((address >> 16) & 0x000000FF);     // address upper 8;
    buf[2] = (uint8_t)((address >> 8) & 0x000000FF);      // address mid 8;
    buf[3] = (uint8_t)(address & 0x000000FF);             // address lower 8;

    // Transfer data
    if(len)
    {
        buf[4] = buffer[0];
        err_code = flash_spi_transfer(buf, 5, NULL, 0);
    }
    err_code += flash_spi_transfer((uint8_t *)&buffer[1], len-1, NULL, 0);

    // Write only occurs after the CS line is de-asserted
    FLASH_CS_HIGH();

    // Wait at least 3ms (max page program time according to datasheet)
//  flash_delay_ms(1);

    // Wait until the device is ready or a timeout occurs
    if (wait_for_ready())
    {
        flash_power(down);
			  DRV_printf("!!!flash_write_page FLASH_ERROR_STATUS\n");
        return FLASH_ERROR_STATUS;
    }
    flash_power(down);
    if(!err_code)
    {
        return len;
    }
    else
    {
        DRV_printf("!!!flash_read_buffer FLASH_ERROR_SPI_TRANSFER\n");
        return 0;
    }

}

/**************************************************************************/
/*!
    @brief      Writes a continuous stream of data that will automatically
                cross page boundaries.

    @note       Before writing data, make sure that the appropriate sectors
                have been erased, otherwise the data will be meaningless.

    @param[in]  address
                The 24-bit address where the write will start.
    @param[out] *buffer
                Pointer to the buffer that will store the read results
    @param[in]  len
                Length of the buffer, within the limits of the starting
                address and size of the flash device.
*/
/**************************************************************************/
uint32_t flash_write_buffer(uint32_t address,const uint8_t *buffer, uint32_t len)
{
    uint32_t bytes_to_write;
    uint32_t buffer_offset;
    uint32_t results;
    uint32_t bytes_written;

    // There's no point duplicating most error checks here since they will all be
    // done in the underlying call to spiflashWritePage
//	DRV_HEX_printf("write_buffer:",(uint8_t *)&buffer,len);
    // If the data is only on one page we can take a shortcut
    if ((address % MX25L1606E_PAGE_SIZE) + len <= MX25L1606E_PAGE_SIZE)
    {
        // Only one page ... write and be done with it
        return flash_write_page(address, buffer, len);
    }

    // Block spans multiple pages
    bytes_written = 0;
    buffer_offset = 0;
    while(len)
    {
        // Figure out how many bytes need to be written to this page
        bytes_to_write = MX25L1606E_PAGE_SIZE - (address % MX25L1606E_PAGE_SIZE);
        // Write the current page
        results = flash_write_page(address, buffer+buffer_offset, bytes_to_write);
        bytes_written += results;
        // Abort if we returned an error
        if (!results)
        {
            DRV_printf("!!!flash_read_buffer READ PAGE ERROR\n");
            return bytes_written;  // Something bad happened ... but return what we've written so far
        }
        // Adjust address and len, and buffer offset
        address += bytes_to_write;
        len -= bytes_to_write;
        buffer_offset += bytes_to_write;
        // If the next page is the last one, write it and exit
        // otherwise stay in the the loop and keep writing
        if (len <= MX25L1606E_PAGE_SIZE)
        {
            // Write the last frame and then quit
            results = flash_write_page(address, buffer+buffer_offset, len);
            bytes_written += results;
            // Abort if we returned an error
            if (!results)
            {
                DRV_printf("!!!flash_read_buffer READ PAGE ERROR\n");
                return bytes_written;  // Something bad happened ... but return what we've written so far
            }
            // set len to zero to gracefully exit loop
            len = 0;
        }
    }

    // Return the number of bytes written
    return bytes_written;
}




/**************************************************************************/
/*!
    @brief Finds append address

*/
/**************************************************************************/
uint32_t find_first_empty_addr(void)
{
    uint32_t address, latestUsedAddr;
    uint8_t b,buf[4];
    flash_power(up);
    memset(buf,0,4);

    // Wait until the device is ready or a timeout occurs
    if (wait_for_ready())
    {
        flash_power(down);
        return FLASH_ERROR_TIMEOUT_READY;
    }


    for (int16_t page=0; page < MX25L1606E_PAGES; page++)
    {

        address = page * MX25L1606E_PAGE_SIZE;

        // read every byte of the page, compare to 0xFF
        // Send the read data command
        FLASH_CS_LOW();
        buf[0] = MX25L1606E_READ_CMD;
        buf[1] = (uint8_t)((address >> 16) & 0x000000FF);     // address upper 8;
        buf[2] = (uint8_t)((address >> 8) & 0x000000FF);      // address mid 8;
        buf[3] = (uint8_t)(address & 0x000000FF);             // address lower 8;

        //DRV_printf("0x%02X",address);

        flash_spi_transfer(buf, 4, NULL, 0);
        for (int16_t i=0; i<MX25L1606E_PAGE_SIZE; i++)
        {
            flash_spi_read(&b,1);
            //DRV_printf("0x%02X",b);
            if (b == 0xFF)
            {
                flash_power(down);
                DRV_printf("Found an empty byte at 0x%02X",latestUsedAddr);
                return address + i;
            }
        }
        FLASH_CS_HIGH();
    }

    return FLASH_SUCCESS;  // Return bytes written
}

/***********************************************************************************************/
uint32_t flash_init(void)
{
//    uint8_t buf[5000];
//    memset(buf,0xAA,4000);
    uint32_t err_code = FLASH_SUCCESS;
    uint32_t device_unique_id = 0;
    uint8_t manufacture_id = 0,device_id = 0;
//    flash_power(up);
    err_code  = get_unique_id(&device_unique_id);
    err_code += get_manufacture_info(&manufacture_id, &device_id);

    DRV_printf("%s(0x%02X)------>flash_init()\n", (device_unique_id==MX25L1606E_UNIQUE_ID)?"Success":"Failure",err_code);
    if(!err_code)
    {
        DRV_printf("		FLASH device_unique_id:0x%02X\n",device_unique_id);
        DRV_printf("		FLASH manufacture id  :0x%02X\n",manufacture_id);
        DRV_printf("		FLASH device_id       :0x%02X\n",device_id);
    }
//    err_code +=flash_erase_sector(0);
//		flash_write_page(0x00,buf,256);
//    flash_write_buffer(0,buf, 4000);
//    flash_delay_ms(10);
//    memset(buf,0,5000);
//    DRV_printf("flash_read_buffer():%d\n",flash_read_buffer(0,buf,4096));
//    DRV_HEX_printf("--->buf:",buf,4096);

//		memset(buf,0,100);
//		flash_read_buffer(250,buf,10);
//		DRV_HEX_printf("--->buf:",buf,10);
//    flash_power(down);
    return err_code;
}

/***********************************************************************************************/
uint32_t FLASH_disk_status(void)
{
    uint32_t err_code = FLASH_SUCCESS, flash_id;

    if(!get_unique_id(&flash_id))
    {
        if(flash_id != MX25L1606E_UNIQUE_ID)
        {
            DRV_printf("!!!FLASH_disk_status FLASH_ERROR\n");
            err_code = FLASH_ERROR;
        }
    }
    else
    {
        DRV_printf("!!!FLASH_disk_status FLASH_ERROR\n");
        err_code = FLASH_ERROR;
    }

    return err_code;
}
uint32_t FLASH_disk_initialize(void)
{
    uint32_t err_code = FLASH_SUCCESS;
    if(flash_init())
    {
        DRV_printf("!!!FLASH_disk_initialize FLASH_ERROR\n");
        return FLASH_ERROR;
    }
		DRV_printf("FLASH_disk_initialize FLASH_SUCCESS\n");
    return err_code;
}
uint32_t FLASH_disk_read(uint8_t *buff,uint32_t sector, uint32_t count)
{
    uint32_t err_code = FLASH_SUCCESS, n=0;
    DRV_printf("!!!FLASH_disk_read sector=%02d, count=%02d\n",sector ,count);
    if ((sector >= MX25L1606E_SECTORS)||(count>(MX25L1606E_TOTAL_SIZE-(sector<<12))))
    {
        DRV_printf("!!!FLASH_disk_read FLASH_ERROR_LENGTH\n");
        return FLASH_PARAM;
    }
    n = flash_read_buffer(sector<<12,buff,count<<12);
//		DRV_HEX_printf("Read Data:",buff,15);
    if(n!=(count<<12))
    {
        DRV_printf("!!!!!FLASH_disk_read FLASH_ERROR\n");
        return FLASH_PARAM;
    }
    return err_code;
}

uint32_t FLASH_disk_write(const uint8_t *buff, uint32_t sector, uint32_t count)
{
    uint32_t err_code = FLASH_SUCCESS, n = 0,erase_sector=0;

    if ((sector >= MX25L1606E_SECTORS)||(count>(MX25L1606E_TOTAL_SIZE-(sector<<12))))
    {
        DRV_printf("!!!FLASH_disk_read FLASH_ERROR_LENGTH\n");
        return FLASH_PARAM;
    }
		erase_sector = sector;
		for(uint8_t i=0;i<count;i++)
		{
				flash_erase_sector(erase_sector++);
		}
		DRV_printf("!!!FLASH_disk_write sector=%02d, count=%02d\n",sector ,count);		
//		DRV_HEX_printf("Write Data:",(uint8_t *)buff,10);
    n = flash_write_buffer(sector<<12,buff,count<<12);
    if(n!=(count<<12))
    {
        DRV_printf("!!!!!FLASH_disk_read FLASH_ERROR\n");
        return FLASH_PARAM;
    }
    return err_code;
}










2. yc_drv_mx25l1606e.h

#ifndef __YC_DRV_MX25L1606E_H__
#define __YC_DRV_MX25L1606E_H__

#include "SEGGER_RTT.h"
#include "SEGGER_RTT_Conf.h"
#include "yc_common.h"
#include "yc_board_i5.h"

/********************************************************************************************************************/
/*****************************************      Debug macro       ***************************************************/
#ifndef DRV_DEBUG
#define  DRV_DEBUG  0
#endif

#if (DRV_DEBUG ==1)
#define DRV_printf(Format , ...)			            SEGGER_RTT_printf(0 , "[DRV]: "Format , ##__VA_ARGS__)
#define DRV_HEX_printf(str,p_buf , buf_len)       YC_HEX_printf("[DRV]: "str,p_buf, buf_len)

#else
#define DRV_printf(Format , ...)
#define DRV_HEX_printf(str,p_buf , buf_len)
#endif



/********************************************************************************************************************/





#define	FLASH_SPI_CS			I5_SPI_FLASH_CS_PIN
#define	FLASH_SPI_MOSI		I5_SPI_MOSI_PIN
#define	FLASH_SPI_MISO		I5_SPI_MISO_PIN
#define	FLASH_SPI_CLK		  I5_SPI_SCK_PIN

#define FLASH_SPI_SINGLE_TRANSFER_MAX_SIZE   255

#define  FLASH_SPI_STATREAD      0x02
#define  FLASH_SPI_DATAWRITE     0x01
#define  FLASH_SPI_DATAREAD      0x03
#define  FLASH_SPI_READY         0x01

// Flash status bits
#define FLASH_STAT_BUSY         0x01   // Erase/Write in Progress
#define FLASH_STAT_WRTEN        0x02   // Write Enable Latch

/***********************************************************************************************************/

// SPI Flash Characteristics (MX25L1606E Specific) size=2M

#define MX25L1606E_MAX_ADDRESS          0x1FFFFF
#define MX25L1606E_PAGE_SIZE            256    // 256 bytes per programmable page
#define MX25L1606E_PAGES                8192   // 2,097,152 Bytes / 256 bytes per page
#define MX25L1606E_SECTOR_SIZE          4096   // 1 erase sector = 4096 bytes
#define MX25L1606E_SECTORS              512    // 2,097,152 Bytes / 4096 bytes per sector
//#define MX25L1606E_BLOCK_SIZE           65536 
#define MX25L1606E_BLOCKS               32
#define MX25L1606E_TOTAL_SIZE           MX25L1606E_PAGES*MX25L1606E_PAGE_SIZE
#define MX25L1606E_UNIQUE_ID            0xC22015
#define MX25L1606E_MANUFACTURER_ID      0xC2   // Used to validate read data
#define MX25L1606E_DEVICE_ID            0x14 // Used to validate read data


#define MX25L1606E_RDID_CMD            0x9F
#define MX25L1606E_READ_STATUS_CMD     0x05
#define MX25L1606E_WRSR_CMD            0x01
#define MX25L1606E_REMS_CMD            0x90
#define MX25L1606E_PWR_DOWN_CMD        0xB9
#define MX25L1606E_PWR_UP_CMD          0xAB
#define MX25L1606E_RES_CMD             0xAB
#define MX25L1606E_PAGE_WRITE_CMD      0x02
#define MX25L1606E_WREN_CMD            0x06
#define MX25L1606E_WRDI_CMD            0x04
#define MX25L1606E_CHIP_ERASE_CMD      0x60
#define MX25L1606E_BE_CMD              0x52
#define MX25L1606E_SECTOR_ERASE_CMD    0x20
#define MX25L1606E_READ_CMD            0x03
#define MX25L1606E_FREAD_CMD           0x0B
#define MX25L1606E_DREAD_CMD           0x3B

typedef enum
{
	FLASH_SUCCESS = 0,
	FLASH_ERROR,
	FLASH_PARAM,
	FLASH_ERROR_TIMEOUT_READY,
	FLASH_ERROR_LENGTH,
	FLASH_ERROR_STATUS,	
	FLASH_ERROR_SPI_TRANSFER,
}flash_error_t;

typedef enum
{	
	up   = true,	
	down = false,
}flash_power_t;



typedef struct
{
    uint8_t  manufacturer_id;
    uint16_t device_id;
}flashInfoTypedef;






uint32_t get_unique_id(uint32_t *device_unique_id);

uint32_t flash_read_buffer(uint32_t address, uint8_t *buffer, uint32_t len);
uint32_t flash_erase_sector (uint32_t sector_number);
uint32_t flash_erase_chip (void);
uint32_t flash_write_page(uint32_t address, const uint8_t *buffer, uint32_t len);
uint32_t flash_write_buffer(uint32_t address, const uint8_t *buffer, uint32_t len);
uint32_t find_first_empty_addr(void);
uint32_t flash_init(void);


/****************************************************************************/
uint32_t FLASH_disk_status(void);
uint32_t FLASH_disk_initialize(void);
uint32_t FLASH_disk_read(uint8_t *buff,uint32_t sector, uint32_t count);
uint32_t FLASH_disk_write(const uint8_t *buff, uint32_t sector, uint32_t count);



#endif  //__YC_DRV_MX25L1606E_H__


 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值