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__