This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
[flashv2 merge] Dataflash driver
- From: Jonathan Larmour <jifl at eCosCentric dot com>
- To: eCos Patches List <ecos-patches at ecos dot sourceware dot org>
- Date: Tue, 18 Nov 2008 01:06:09 +0000
- Subject: [flashv2 merge] Dataflash driver
- Openpgp: id=A5FB74E6
Attached...
--
eCosCentric Limited http://www.eCosCentric.com/ The eCos experts
Barnwell House, Barnwell Drive, Cambridge, UK. Tel: +44 1223 245571
Registered in England and Wales: Reg No 4422071.
------["Si fractum non sit, noli id reficere"]------ Opinions==mine
Index: packages/devs/flash/atmel/dataflash/current/ChangeLog
===================================================================
RCS file: packages/devs/flash/atmel/dataflash/current/ChangeLog
diff -N packages/devs/flash/atmel/dataflash/current/ChangeLog
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ packages/devs/flash/atmel/dataflash/current/ChangeLog 18 Nov 2008 01:05:46 -0000
@@ -0,0 +1,96 @@
+2005-06-29 Jani Monoses <ani@iv.ro>
+
+ * include/dataflash.h: Allow the package to be compiled without
+ io/flash. Return correct value from cyg_dataflash_get_page_count()
+
+2004-12-02 Bart Veer <bartv@ecoscentric.com>
+
+ * include/dataflash.h,
+ src/devs_flash_atmel_dataflash_flash_dev_funs.c: include
+ <cyg/io/flash_dev.h> explicitly rather than using _FLASH_PRIVATE_
+
+2004-11-29 Bart Veer <bartv@ecoscentric.com>
+
+ (df_flash_hwr_map_error): this is now internal to the driver, no
+ longer needed by the generic flash code.
+ * src/devs_flash_atmel_dataflash_flash_dev_funs.c: use the dummy
+ query/lock/unlock functions provided by the generic flash code
+
+2004-11-22 Bart Veer <bartv@ecoscentric.com>
+
+ * include/dataflash.h, src/devs_flash_atmel_dataflash.c,
+ src/devs_flash_atmel_dataflash_flash_dev_funs.c: merge the config
+ and priv structures, removing the duplicate spi_dev data in the
+ process. Adjust device driver API as per changes to the generic
+ flash code.
+ * src/devs_flash_atmel_dataflash_flash_dev_funs.c (df_flash_init):
+ Rename cyg_block_info to cyg_flash_block_info
+
+2004-11-21 Bart Veer <bartv@ecoscentric.com>
+
+ * cdl/devs_flash_atmel_dataflash.cdl: CYGHWR_IO_FLASH_DEVICE_V2 is
+ now implicit
+
+2004-11-20 Bart Veer <bartv@ecoscentric.com>
+
+ * cdl/devs_flash_atmel_dataflash.cdl: data flash requires indirect
+ read support in the main flash code.
+
+2004-10-07 Savin Zlobec <savin@elatec.si>
+
+ * include/dataflash.h:
+ * src/devs_flash_atmel_dataflash.c:
+ Changed the API to be more consistent, included error
+ reporting and added blocking/non blocking mode of operation.
+ * src/devs_flash_atmel_dataflash_flash_dev_funs.c:
+ Synced with new API and set the block size to DataFlash's
+ native page size.
+
+2004-10-07 Andrew Lunn <andrew.lunn@ascom.ch>
+
+ * cdl/devs_flash_atmel_dataflash.cdl: Remove
+ CYGSEM_IO_FLASH_READ_INDIRECT which only legacy drivers should use
+ when they provide a flash_read_buf function. For V2 drivers
+ providing a read function in the device structure is sufficient.
+
+2004-09-07 Savin Zlobec <savin@elatec.si>
+
+ * cdl/devs_flash_atmel_dataflash.cdl:
+ * include/dataflash.h:
+ * src/devs_flash_atmel_dataflash.c:
+ * src/devs_flash_atmel_dataflash_flash_dev_funs.c:
+ Atmel DataFlash driver implementation.
+
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
Index: packages/devs/flash/atmel/dataflash/current/cdl/devs_flash_atmel_dataflash.cdl
===================================================================
RCS file: packages/devs/flash/atmel/dataflash/current/cdl/devs_flash_atmel_dataflash.cdl
diff -N packages/devs/flash/atmel/dataflash/current/cdl/devs_flash_atmel_dataflash.cdl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ packages/devs/flash/atmel/dataflash/current/cdl/devs_flash_atmel_dataflash.cdl 18 Nov 2008 01:05:46 -0000
@@ -0,0 +1,71 @@
+# ====================================================================
+#
+# devs_flash_atmel_dataflash.cdl
+#
+# Atmel DataFlash parts support
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+## WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s): Savin Zlobec <savin@elatec.si>
+# Date: 2004-08-27
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_FLASH_ATMEL_DATAFLASH {
+ display "Atmel DataFlash parts support"
+ description "Support for Atmel DataFlash"
+ active_if CYGPKG_IO_SPI
+ requires CYGPKG_ERROR
+ hardware
+ compile devs_flash_atmel_dataflash.c
+ include_dir cyg/io
+
+ cdl_interface CYGPKG_DEVS_FLASH_ATMEL_DATAFLASH_FLASH_DEV {
+ display "Support for DataFlash IO Flash interface"
+ flavor bool
+ active_if CYGPKG_IO_FLASH
+ implements CYGHWR_IO_FLASH_DEVICE
+ implements CYGHWR_IO_FLASH_INDIRECT_READS
+ compile devs_flash_atmel_dataflash_flash_dev_funs.c
+ description "This option will be enabled by platforms which
+ need to support access to DataFlash through IO Flash API."
+ }
+}
+
+# EOF devs_flash_atmel_dataflash.cdl
Index: packages/devs/flash/atmel/dataflash/current/include/dataflash.h
===================================================================
RCS file: packages/devs/flash/atmel/dataflash/current/include/dataflash.h
diff -N packages/devs/flash/atmel/dataflash/current/include/dataflash.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ packages/devs/flash/atmel/dataflash/current/include/dataflash.h 18 Nov 2008 01:05:46 -0000
@@ -0,0 +1,249 @@
+#ifndef CYGONCE_DATAFLASH_H
+#define CYGONCE_DATAFLASH_H
+//==========================================================================
+//
+// dataflash.h
+//
+// DataFlash series flash driver defines
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Savin Zlobec <savin@elatec.si>
+// Date: 2004-08-27
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/hal.h>
+#include <pkgconf/devs_flash_atmel_dataflash.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/hal/drv_api.h>
+#include <cyg/io/spi.h>
+
+//----------------------------------------------------------------------------
+
+enum {
+ CYG_DATAFLASH_ERR_OK = 0, // No error
+ CYG_DATAFLASH_ERR_INVALID = 1, // Invalid address error
+ CYG_DATAFLASH_ERR_WRONG_PART = 2, // Unsupported device error
+ CYG_DATAFLASH_ERR_TIMEOUT = 3, // Operation timeout error
+ CYG_DATAFLASH_ERR_COMPARE = 4 // Buffer - main memory compare error
+};
+
+enum {
+ CYG_DATAFLASH_STATE_IDLE = 0,
+ CYG_DATAFLASH_STATE_BUSY = 1
+};
+
+//----------------------------------------------------------------------------
+
+typedef struct cyg_dataflash_dev_info_s
+{
+ cyg_uint8 device_id; // Device ID
+ cyg_uint16 page_size; // Page size in bytes
+ cyg_uint16 page_count; // Total number of pages
+ cyg_uint8 baddr_bits; // Bits used for byte address in addressing seq
+ cyg_uint16 block_size; // Block size in pages
+ cyg_uint16 sector_sizes[64]; // Sector sizes in blocks
+ cyg_uint16 sector_count; // Total number of sectors
+} cyg_dataflash_dev_info_t;
+
+typedef struct cyg_dataflash_device_s
+{
+ const cyg_dataflash_dev_info_t *info; // DataFlash device info
+ cyg_spi_device *spi_dev; // SPI device
+ cyg_drv_mutex_t lock; // Access lock
+ cyg_bool polled; // Polled mode flag
+ cyg_bool blocking; // Blocking mode flag
+ int state; // Current state (IDLE, BUSY, ...)
+ cyg_uint8 busy_buf; // Current busy buffer number
+} cyg_dataflash_device_t;
+
+//----------------------------------------------------------------------------
+#ifdef CYGPKG_IO_FLASH
+#include <cyg/io/flash.h>
+#include <cyg/io/flash_dev.h>
+
+typedef struct cyg_dataflash_flash_dev_priv_s
+{
+ cyg_int16 start_sector; // Start sector of flash driver space
+ cyg_int16 end_sector; // End sector of flash driver space
+ cyg_dataflash_device_t dev; // DataFlash device
+ cyg_uint32 start_page; // Start page of flash driver space
+ cyg_uint32 end_page; // End page of flash driver space
+ cyg_flash_block_info_t block_info[1];
+} cyg_dataflash_flash_dev_priv_t;
+
+externC struct cyg_flash_dev_funs cyg_dataflash_flash_dev_funs;
+
+#define CYG_DATAFLASH_FLASH_DRIVER(name, _sdev, _addr, _start, _end) \
+ static cyg_dataflash_flash_dev_priv_t cyg_dataflash_priv_ ## name = { \
+ .start_sector = _start, \
+ .end_sector = _end, \
+ .dev.spi_dev = _sdev, \
+ }; \
+ CYG_FLASH_DRIVER(name, \
+ &cyg_dataflash_flash_dev_funs, \
+ 0, \
+ _addr, \
+ 0, \
+ 1, \
+ cyg_dataflash_priv_ ## name.block_info, \
+ & cyg_dataflash_priv_ ## name \
+ )
+
+#endif
+//----------------------------------------------------------------------------
+
+static inline cyg_uint8
+cyg_dataflash_get_device_id(cyg_dataflash_device_t *dev)
+{
+ return dev->info->device_id;
+}
+
+static inline cyg_uint16
+cyg_dataflash_get_page_size(cyg_dataflash_device_t *dev)
+{
+ return dev->info->page_size;
+}
+
+static inline cyg_uint16
+cyg_dataflash_get_page_count(cyg_dataflash_device_t *dev)
+{
+ return dev->info->page_count;
+}
+
+static inline cyg_uint16
+cyg_dataflash_get_block_size(cyg_dataflash_device_t *dev)
+{
+ return dev->info->block_size;
+}
+
+static inline cyg_uint16
+cyg_dataflash_get_sector_size(cyg_dataflash_device_t *dev, cyg_uint8 sector_num)
+{
+ return dev->info->sector_sizes[sector_num];
+}
+
+static inline cyg_uint16
+cyg_dataflash_get_sector_count(cyg_dataflash_device_t *dev)
+{
+ return dev->info->sector_count;
+}
+
+static inline void
+cyg_dataflash_set_polled_operation(cyg_dataflash_device_t *dev, cyg_bool polled)
+{
+ dev->polled = polled;
+}
+
+static inline void
+cyg_dataflash_set_blocking_operation(cyg_dataflash_device_t *dev, cyg_bool block)
+{
+ dev->blocking = block;
+}
+
+//----------------------------------------------------------------------------
+
+externC int cyg_dataflash_init(cyg_bool polled,
+ cyg_dataflash_device_t *dev);
+
+externC int cyg_dataflash_aquire(cyg_dataflash_device_t *dev);
+
+externC int cyg_dataflash_release(cyg_dataflash_device_t *dev);
+
+externC cyg_uint16 cyg_dataflash_get_sector_start(cyg_dataflash_device_t *dev,
+ cyg_uint16 sector_num);
+
+externC int cyg_dataflash_wait_ready(cyg_dataflash_device_t *dev);
+
+externC int cyg_dataflash_read_buf(cyg_dataflash_device_t *dev,
+ cyg_uint8 buf_num,
+ cyg_uint8 *buf,
+ cyg_uint32 len,
+ cyg_uint32 pos);
+
+externC int cyg_dataflash_write_buf(cyg_dataflash_device_t *dev,
+ cyg_uint8 buf_num,
+ const cyg_uint8 *buf,
+ cyg_uint32 len,
+ cyg_uint32 pos);
+
+externC int cyg_dataflash_mem_to_buf(cyg_dataflash_device_t *dev,
+ cyg_uint8 buf_num,
+ cyg_uint32 page_num);
+
+externC int cyg_dataflash_program_buf(cyg_dataflash_device_t *dev,
+ cyg_uint8 buf_num,
+ cyg_uint32 page_num,
+ cyg_bool erase);
+
+externC int cyg_dataflash_compare_buf(cyg_dataflash_device_t *dev,
+ cyg_uint8 buf_num,
+ cyg_uint32 page_num);
+
+externC int cyg_dataflash_erase(cyg_dataflash_device_t *dev,
+ cyg_uint32 page_num);
+
+externC int cyg_dataflash_erase_block(cyg_dataflash_device_t *dev,
+ cyg_uint32 block_num);
+
+externC int cyg_dataflash_auto_rewrite(cyg_dataflash_device_t *dev,
+ cyg_uint8 buf_num,
+ cyg_uint32 page_num);
+
+externC int cyg_dataflash_read(cyg_dataflash_device_t *dev,
+ cyg_uint8 *buf,
+ cyg_uint32 len,
+ cyg_uint32 pos);
+
+externC int cyg_dataflash_program(cyg_dataflash_device_t *dev,
+ const cyg_uint8 *buf,
+ cyg_uint32 *len,
+ cyg_uint32 pos,
+ cyg_bool erase,
+ cyg_bool verify);
+
+//----------------------------------------------------------------------------
+
+#endif // CYGONCE_DATAFLASH_H
+
+//----------------------------------------------------------------------------
+// End of dataflash.h
Index: packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash.c
===================================================================
RCS file: packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash.c
diff -N packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash.c 18 Nov 2008 01:05:46 -0000
@@ -0,0 +1,923 @@
+//==========================================================================
+//
+// devs_flash_atmel_dataflash.c
+//
+// Atmel DataFlash series flash driver
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Savin Zlobec <savin@elatec.si>
+// Date: 2004-08-27
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/hal.h>
+#include <pkgconf/devs_flash_atmel_dataflash.h>
+
+#include <cyg/infra/diag.h>
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/hal/drv_api.h>
+#include <cyg/io/spi.h>
+#include <cyg/io/dataflash.h>
+
+// --------------------------------------------------------------------------
+// DataFlash command opcodes
+
+// Read commands opcodes
+#define DF_CONT_ARRAY_READ_CMD 0x68
+#define DF_MMEM_PAGE_READ_CMD 0x52
+#define DF_BUF1_READ_CMD 0x54
+#define DF_BUF2_READ_CMD 0x56
+#define DF_STATUS_READ_CMD 0x57
+
+// Program and erase commands opcodes
+#define DF_BUF1_WRITE_CMD 0x84
+#define DF_BUF2_WRITE_CMD 0x87
+#define DF_BUF1_PROG_W_ERASE_CMD 0x83
+#define DF_BUF2_PROG_W_ERASE_CMD 0x86
+#define DF_BUF1_PROG_WO_ERASE_CMD 0x88
+#define DF_BUF2_PROG_WO_ERASE_CMD 0x89
+#define DF_PAGE_ERASE_CMD 0x81
+#define DF_BLOCK_ERASE_CMD 0x50
+#define DF_PROG_THROUGH_BUF1_CMD 0x82
+#define DF_PROG_THROUGH_BUF2_CMD 0x85
+
+// Additional commands opcodes
+#define DF_TRANSFER_TO_BUF1_CMD 0x53
+#define DF_TRANSFER_TO_BUF2_CMD 0x55
+#define DF_BUF1_COMPARE_CMD 0x60
+#define DF_BUF2_COMPARE_CMD 0x61
+#define DF_AUTO_REWRITE_THROUGH_BUF1_CMD 0x58
+#define DF_AUTO_REWRITE_THROUGH_BUF2_CMD 0x59
+
+//----------------------------------------------------------------------------
+
+#define DATA_BUF_NONE 0x00 // Data buffer number for no buffer
+#define DATA_BUF_ALL 0xFF // Data buffer number for all buffers
+
+//----------------------------------------------------------------------------
+
+typedef struct df_status_s
+{
+ cyg_uint8 reserved:2;
+ cyg_uint8 device_id:4;
+ cyg_uint8 compare_err:1;
+ cyg_uint8 ready:1;
+} df_status_t;
+
+//----------------------------------------------------------------------------
+
+static const cyg_dataflash_dev_info_t df_dev_info[] =
+{
+ { // AT45DB011B
+ device_id: 0x03,
+ page_size: 264,
+ page_count: 512,
+ baddr_bits: 9,
+ block_size: 8,
+ sector_sizes: { 1, 31, 32 },
+ sector_count: 3
+ },
+ { // AT45DB021B
+ device_id: 0x05,
+ page_size: 264,
+ page_count: 1024,
+ baddr_bits: 9,
+ block_size: 8,
+ sector_sizes: { 1, 31, 32, 64 },
+ sector_count: 4
+ },
+ { // AT45DB041B
+ device_id: 0x07,
+ page_size: 264,
+ page_count: 2048,
+ baddr_bits: 9,
+ block_size: 8,
+ sector_sizes: { 1, 31, 32, 64, 64, 64 },
+ sector_count: 6
+ },
+ { // AT45DB081B
+ device_id: 0x09,
+ page_size: 264,
+ page_count: 4096,
+ baddr_bits: 9,
+ block_size: 8,
+ sector_sizes: { 1, 31, 32, 64, 64, 64, 64, 64, 64, 64 },
+ sector_count: 10
+ },
+ { // AT45DB161B
+ device_id: 0x0B,
+ page_size: 528,
+ page_count: 4096,
+ baddr_bits: 10,
+ block_size: 8,
+ sector_sizes: { 1, 31, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32 },
+ sector_count: 17
+ },
+ { // AT45DB321B
+ device_id: 0x0D,
+ page_size: 528,
+ page_count: 8192,
+ baddr_bits: 10,
+ block_size: 8,
+ sector_sizes: { 1, 63, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64 },
+ sector_count: 17
+ },
+ { // AT45DB642
+ device_id: 0x0F,
+ page_size: 1056,
+ page_count: 8192,
+ baddr_bits: 11,
+ block_size: 8,
+ sector_sizes: { 1, 31, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32 },
+ sector_count: 35
+ },
+ { 0 }
+};
+
+//----------------------------------------------------------------------------
+
+static void
+df_compose_addr(cyg_dataflash_device_t *dev,
+ cyg_uint8 *cmd_buf,
+ cyg_uint16 page_addr,
+ cyg_uint16 byte_addr)
+{
+ cyg_uint32 baddr_bits = dev->info->baddr_bits;
+ cyg_uint32 addr;
+
+ addr = (page_addr << baddr_bits) | (byte_addr & ((1<<baddr_bits) - 1));
+
+ cmd_buf[1] = (addr >> 16) & 0xFF;
+ cmd_buf[2] = (addr >> 8) & 0xFF;
+ cmd_buf[3] = addr & 0xFF;
+}
+
+static df_status_t
+df_read_status(cyg_dataflash_device_t *dev)
+{
+ cyg_spi_device *spi_dev = dev->spi_dev;
+ const cyg_uint8 cmd_buf[2] = { DF_STATUS_READ_CMD, 0 };
+ cyg_uint8 rx_buf[2];
+ df_status_t *status;
+
+ cyg_spi_transaction_transfer(spi_dev, true, 2, cmd_buf, rx_buf, true);
+
+ status = (df_status_t *) &rx_buf[1];
+
+ return *status;
+}
+
+static void
+df_set_busy_buf(cyg_dataflash_device_t *dev, cyg_uint8 buf_num)
+{
+ dev->state = CYG_DATAFLASH_STATE_BUSY;
+ dev->busy_buf = buf_num;
+}
+
+static void
+df_set_busy(cyg_dataflash_device_t *dev)
+{
+ df_set_busy_buf(dev, DATA_BUF_ALL);
+}
+
+static int
+df_wait_ready_buf(cyg_dataflash_device_t *dev, cyg_uint8 buf_num)
+{
+ df_status_t status;
+
+ if (CYG_DATAFLASH_STATE_IDLE == dev->state)
+ return CYG_DATAFLASH_ERR_OK;
+
+ if (DATA_BUF_ALL == buf_num ||
+ DATA_BUF_ALL == dev->busy_buf ||
+ dev->busy_buf == buf_num)
+ {
+ // REMIND: this loop should have an timeout
+ // in case of device malfunction
+
+ do
+ {
+ status = df_read_status(dev);
+ } while (0 == status.ready);
+
+ dev->state = CYG_DATAFLASH_STATE_IDLE;
+ dev->busy_buf = DATA_BUF_NONE;
+ }
+
+ return CYG_DATAFLASH_ERR_OK;
+
+}
+
+static int
+df_wait_ready(cyg_dataflash_device_t *dev)
+{
+ return df_wait_ready_buf(dev, DATA_BUF_ALL);
+}
+
+static void
+df_detect_device(cyg_dataflash_device_t *dev)
+{
+ const cyg_dataflash_dev_info_t *dev_info;
+ cyg_spi_device *spi_dev = dev->spi_dev;
+ df_status_t status;
+
+ cyg_spi_transaction_begin(spi_dev);
+ status = df_read_status(dev);
+ cyg_spi_transaction_end(spi_dev);
+
+ dev_info = df_dev_info;
+
+ while (dev_info->device_id != 0)
+ {
+ if (status.device_id == dev_info->device_id)
+ {
+ dev->info = dev_info;
+ return;
+ }
+ dev_info++;
+ }
+ dev->info = NULL;
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_init()
+
+int
+cyg_dataflash_init(cyg_bool polled,
+ cyg_dataflash_device_t *dev)
+{
+ dev->polled = polled;
+ dev->blocking = false;
+ dev->state = CYG_DATAFLASH_STATE_IDLE;
+ dev->busy_buf = DATA_BUF_NONE;
+
+ cyg_drv_mutex_init(&dev->lock);
+
+ df_detect_device(dev);
+
+ if (NULL == dev->info)
+ return CYG_DATAFLASH_ERR_WRONG_PART;
+ else
+ return CYG_DATAFLASH_ERR_OK;
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_aquire()
+
+int
+cyg_dataflash_aquire(cyg_dataflash_device_t *dev)
+{
+ while (!cyg_drv_mutex_lock(&dev->lock));
+ return CYG_DATAFLASH_ERR_OK;
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_release()
+
+int
+cyg_dataflash_release(cyg_dataflash_device_t *dev)
+{
+ int err;
+
+ err = df_wait_ready(dev);
+
+ cyg_drv_mutex_unlock(&dev->lock);
+
+ return err;
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_get_sector_start()
+
+cyg_uint16
+cyg_dataflash_get_sector_start(cyg_dataflash_device_t *dev,
+ cyg_uint16 sector_num)
+{
+ cyg_uint16 res, i;
+
+ if (sector_num >= dev->info->sector_count)
+ return 0;
+
+ res = 0;
+ for (i = 0; i < sector_num; i++)
+ res += dev->info->sector_sizes[i];
+
+ return res;
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_wait_ready()
+
+int
+cyg_dataflash_wait_ready(cyg_dataflash_device_t *dev)
+{
+ return df_wait_ready(dev);
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_read_buf()
+
+int
+cyg_dataflash_read_buf(cyg_dataflash_device_t *dev,
+ cyg_uint8 buf_num,
+ cyg_uint8 *buf,
+ cyg_uint32 len,
+ cyg_uint32 pos)
+
+{
+ cyg_spi_device *spi_dev = dev->spi_dev;
+ int err = CYG_DATAFLASH_ERR_OK;
+ cyg_uint8 cmd_buf[5];
+
+ // Check if the position is inside the page
+ if (pos >= dev->info->page_size)
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ // Compose DataFlash command
+
+ if (1 == buf_num) cmd_buf[0] = DF_BUF1_READ_CMD;
+ else if (2 == buf_num) cmd_buf[0] = DF_BUF2_READ_CMD;
+ else
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ df_compose_addr(dev, cmd_buf, 0, pos);
+
+ cyg_spi_transaction_begin(spi_dev);
+
+ // Wait for the target buffer to become ready
+ err = df_wait_ready_buf(dev, buf_num);
+
+ if (CYG_DATAFLASH_ERR_OK == err)
+ {
+ // Send command and read data
+
+ cyg_spi_transaction_transfer(spi_dev, true, 5, cmd_buf, NULL, false);
+ cyg_spi_transaction_transfer(spi_dev, dev->polled, len, buf, buf, true);
+ }
+
+ cyg_spi_transaction_end(spi_dev);
+
+ return err;
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_write_buf()
+
+int
+cyg_dataflash_write_buf(cyg_dataflash_device_t *dev,
+ cyg_uint8 buf_num,
+ const cyg_uint8 *buf,
+ cyg_uint32 len,
+ cyg_uint32 pos)
+{
+ cyg_spi_device *spi_dev = dev->spi_dev;
+ int err = CYG_DATAFLASH_ERR_OK;
+ cyg_uint8 cmd_buf[4];
+
+ // Check if the position is inside the page
+ if (pos >= dev->info->page_size)
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ // Compose DataFlash command
+
+ if (1 == buf_num) cmd_buf[0] = DF_BUF1_WRITE_CMD;
+ else if (2 == buf_num) cmd_buf[0] = DF_BUF2_WRITE_CMD;
+ else
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ df_compose_addr(dev, cmd_buf, 0, pos);
+
+ cyg_spi_transaction_begin(spi_dev);
+
+ // Wait for the target buffer to become ready
+ err = df_wait_ready_buf(dev, buf_num);
+
+ if (CYG_DATAFLASH_ERR_OK == err)
+ {
+ // Send command and data
+
+ cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, false);
+ cyg_spi_transaction_transfer(spi_dev, dev->polled,
+ len, buf, NULL, true);
+ }
+
+ cyg_spi_transaction_end(spi_dev);
+
+ return err;
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_mem_to_buf()
+
+int
+cyg_dataflash_mem_to_buf(cyg_dataflash_device_t *dev,
+ cyg_uint8 buf_num,
+ cyg_uint32 page_num)
+{
+ cyg_spi_device *spi_dev = dev->spi_dev;
+ int err = CYG_DATAFLASH_ERR_OK;
+ cyg_uint8 cmd_buf[4];
+
+ // Check if the page number is inside the flash
+ if (page_num >= dev->info->page_count)
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ // Compose DataFlash command
+
+ if (1 == buf_num) cmd_buf[0] = DF_TRANSFER_TO_BUF1_CMD;
+ else if (2 == buf_num) cmd_buf[0] = DF_TRANSFER_TO_BUF2_CMD;
+ else
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ df_compose_addr(dev, cmd_buf, page_num, 0);
+
+ cyg_spi_transaction_begin(spi_dev);
+
+ // Wait for the device to become ready
+ err = df_wait_ready(dev);
+
+ if (CYG_DATAFLASH_ERR_OK == err)
+ {
+ // Send the command
+ cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true);
+
+ // Mark the target buffer as busy
+ df_set_busy_buf(dev, buf_num);
+
+ // Wait if in blocking mode
+ if (dev->blocking)
+ err = df_wait_ready(dev);
+ }
+
+ cyg_spi_transaction_end(spi_dev);
+
+ return err;
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_program_buf()
+
+int
+cyg_dataflash_program_buf(cyg_dataflash_device_t *dev,
+ cyg_uint8 buf_num,
+ cyg_uint32 page_num,
+ cyg_bool erase)
+{
+ cyg_spi_device *spi_dev = dev->spi_dev;
+ int err = CYG_DATAFLASH_ERR_OK;
+ cyg_uint8 cmd_buf[4];
+
+ // Check if the page number is inside the flash
+ if (page_num >= dev->info->page_count)
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ // Compose DataFlash command
+
+ if (erase)
+ {
+ if (1 == buf_num) cmd_buf[0] = DF_BUF1_PROG_W_ERASE_CMD;
+ else if (2 == buf_num) cmd_buf[0] = DF_BUF2_PROG_W_ERASE_CMD;
+ else
+ return CYG_DATAFLASH_ERR_INVALID;
+ }
+ else
+ {
+ if (1 == buf_num) cmd_buf[0] = DF_BUF1_PROG_WO_ERASE_CMD;
+ else if (2 == buf_num) cmd_buf[0] = DF_BUF2_PROG_WO_ERASE_CMD;
+ else
+ return CYG_DATAFLASH_ERR_INVALID;
+ }
+
+ df_compose_addr(dev, cmd_buf, page_num, 0);
+
+ cyg_spi_transaction_begin(spi_dev);
+
+ // Wait for the device to become ready
+ err = df_wait_ready(dev);
+
+ if (CYG_DATAFLASH_ERR_OK == err)
+ {
+ // Send the command
+ cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true);
+
+ // Mark the target buffer as busy
+ df_set_busy_buf(dev, buf_num);
+
+ // Wait if in blocking mode
+ if (dev->blocking)
+ err = df_wait_ready(dev);
+ }
+
+ cyg_spi_transaction_end(spi_dev);
+
+ return err;
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_compare_buf()
+
+int
+cyg_dataflash_compare_buf(cyg_dataflash_device_t *dev,
+ cyg_uint8 buf_num,
+ cyg_uint32 page_num)
+{
+ cyg_spi_device *spi_dev = dev->spi_dev;
+ int err = CYG_DATAFLASH_ERR_OK;
+ cyg_uint8 cmd_buf[4];
+ df_status_t status;
+
+ // Check if the page number is inside the flash
+ if (page_num >= dev->info->page_count)
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ // Compose DataFlash command
+
+ if (1 == buf_num) cmd_buf[0] = DF_BUF1_COMPARE_CMD;
+ else if (2 == buf_num) cmd_buf[0] = DF_BUF2_COMPARE_CMD;
+ else
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ df_compose_addr(dev, cmd_buf, page_num, 0);
+
+ cyg_spi_transaction_begin(spi_dev);
+
+ // Wait for the device to become ready
+ err = df_wait_ready(dev);
+
+ if (CYG_DATAFLASH_ERR_OK == err)
+ {
+ // Send the command
+ cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true);
+
+ // Wait for the device to become ready
+ df_set_busy(dev);
+ err = df_wait_ready(dev);
+
+ // Read the result of memory compare
+
+ if (CYG_DATAFLASH_ERR_OK == err)
+ {
+ status = df_read_status(dev);
+ if (status.compare_err)
+ err = CYG_DATAFLASH_ERR_COMPARE;
+ }
+ }
+
+ cyg_spi_transaction_end(spi_dev);
+
+ return err;
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_erase()
+
+int
+cyg_dataflash_erase(cyg_dataflash_device_t *dev,
+ cyg_uint32 page_num)
+{
+ cyg_spi_device *spi_dev = dev->spi_dev;
+ int err = CYG_DATAFLASH_ERR_OK;
+ cyg_uint8 cmd_buf[4];
+
+ // Check if the page number is inside the flash
+ if (page_num >= dev->info->page_count)
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ // Compose DataFlash command
+
+ cmd_buf[0] = DF_PAGE_ERASE_CMD;
+ df_compose_addr(dev, cmd_buf, page_num, 0);
+
+ cyg_spi_transaction_begin(spi_dev);
+
+ // Wait for the device to become ready
+ err = df_wait_ready(dev);
+
+ if (CYG_DATAFLASH_ERR_OK == err)
+ {
+ // Send the command
+ cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true);
+
+ // Set device state to busy
+ df_set_busy_buf(dev, DATA_BUF_NONE);
+
+ // Wait if in blocking mode
+ if (dev->blocking)
+ err = df_wait_ready(dev);
+ }
+
+ cyg_spi_transaction_end(spi_dev);
+
+ return err;
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_erase_block()
+
+int
+cyg_dataflash_erase_block(cyg_dataflash_device_t *dev,
+ cyg_uint32 block_num)
+{
+ cyg_spi_device *spi_dev = dev->spi_dev;
+ int err = CYG_DATAFLASH_ERR_OK;
+ cyg_uint8 cmd_buf[4];
+
+ // Check if the block number is inside the flash
+ if (block_num >= (dev->info->page_count >> 3))
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ // Compose DataFlash command
+
+ cmd_buf[0] = DF_BLOCK_ERASE_CMD;
+ df_compose_addr(dev, cmd_buf, block_num << 3, 0);
+
+ cyg_spi_transaction_begin(spi_dev);
+
+ // Wait for the device to become ready
+ err = df_wait_ready(dev);
+
+ if (CYG_DATAFLASH_ERR_OK == err)
+ {
+ // Send the command
+ cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true);
+
+ // Set device state to busy
+ df_set_busy_buf(dev, DATA_BUF_NONE);
+
+ // Wait if in blocking mode
+ if (dev->blocking)
+ err = df_wait_ready(dev);
+ }
+
+ cyg_spi_transaction_end(spi_dev);
+
+ return err;
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_auto_rewrite()
+
+int
+cyg_dataflash_auto_rewrite(cyg_dataflash_device_t *dev,
+ cyg_uint8 buf_num,
+ cyg_uint32 page_num)
+{
+ cyg_spi_device *spi_dev = dev->spi_dev;
+ int err = CYG_DATAFLASH_ERR_OK;
+ cyg_uint8 cmd_buf[4];
+
+ // Check if the page number is inside the flash
+ if (page_num >= dev->info->page_count)
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ // Compose DataFlash command
+
+ if (1 == buf_num) cmd_buf[0] = DF_AUTO_REWRITE_THROUGH_BUF1_CMD;
+ else if (2 == buf_num) cmd_buf[0] = DF_AUTO_REWRITE_THROUGH_BUF2_CMD;
+ else
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ df_compose_addr(dev, cmd_buf, page_num, 0);
+
+ cyg_spi_transaction_begin(spi_dev);
+
+ // Wait for the device to become ready
+ err = df_wait_ready(dev);
+
+ if (CYG_DATAFLASH_ERR_OK == err)
+ {
+ // Send the command
+ cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true);
+
+ // Mark the target buffer as busy
+ df_set_busy_buf(dev, buf_num);
+
+ // Wait if in blocking mode
+ if (dev->blocking)
+ err = df_wait_ready(dev);
+ }
+
+ cyg_spi_transaction_end(spi_dev);
+
+ return err;
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_read()
+
+int
+cyg_dataflash_read(cyg_dataflash_device_t *dev,
+ cyg_uint8 *buf,
+ cyg_uint32 len,
+ cyg_uint32 pos)
+{
+ cyg_spi_device *spi_dev = dev->spi_dev;
+ int err = CYG_DATAFLASH_ERR_OK;
+ cyg_uint8 cmd_buf[8];
+ cyg_uint32 page_num, page_pos;
+
+ // Calculate page number and position from given absolute position
+
+ page_num = pos / dev->info->page_size;
+ page_pos = pos % dev->info->page_size;
+
+ // Check if the page number is inside the flash
+ if (page_num >= dev->info->page_count)
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ // Compose DataFlash command
+
+ cmd_buf[0] = DF_CONT_ARRAY_READ_CMD;
+ df_compose_addr(dev, cmd_buf, page_num, page_pos);
+
+ cyg_spi_transaction_begin(spi_dev);
+
+ // Wait for the device to become ready
+ err = df_wait_ready(dev);
+
+ if (CYG_DATAFLASH_ERR_OK == err)
+ {
+ // Send the command and read data from DataFlash main memory
+
+ cyg_spi_transaction_transfer(spi_dev, true, 8, cmd_buf, NULL, false);
+ cyg_spi_transaction_transfer(spi_dev, dev->polled, len, buf, buf, true);
+ }
+
+ cyg_spi_transaction_end(spi_dev);
+
+ return err;
+}
+
+//----------------------------------------------------------------------------
+// cyg_dataflash_program()
+
+int
+cyg_dataflash_program(cyg_dataflash_device_t *dev,
+ const cyg_uint8 *buf,
+ cyg_uint32 *len,
+ cyg_uint32 pos,
+ cyg_bool erase,
+ cyg_bool verify)
+{
+ cyg_spi_device *spi_dev = dev->spi_dev;
+ int err = CYG_DATAFLASH_ERR_OK;
+ cyg_uint8 cmd_buf[4];
+ cyg_uint32 count, page_num, page_pos;
+
+ // Calculate page number and position from given absolute position
+
+ page_num = pos / dev->info->page_size;
+ page_pos = pos % dev->info->page_size;
+ count = *len;
+
+ cyg_spi_transaction_begin(spi_dev);
+
+ // Wait for device to become ready
+ err = df_wait_ready(dev);
+ if (CYG_DATAFLASH_ERR_OK != err)
+ goto out;
+
+ // Loop until count bytes written
+
+ while (count > 0)
+ {
+ df_status_t status;
+ cyg_uint32 size;
+
+ // Check if the current page number is inside the flash
+ if (page_num >= dev->info->page_count)
+ {
+ err = CYG_DATAFLASH_ERR_INVALID;
+ goto out;
+ }
+
+ // Calculate the number of bytes to write to the current page
+ if ((page_pos + count) > dev->info->page_size)
+ size = dev->info->page_size - page_pos;
+ else
+ size = count;
+
+ // Compose DataFlash command address
+ df_compose_addr(dev, cmd_buf, page_num, page_pos);
+
+ // If we are not rewritting the whole page, then first
+ // read the old data from main memory to the target buffer
+
+ if (page_pos > 0 || size < dev->info->page_size)
+ {
+ cmd_buf[0] = DF_TRANSFER_TO_BUF1_CMD;
+ cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true);
+ df_set_busy(dev);
+ err = df_wait_ready(dev);
+ if (CYG_DATAFLASH_ERR_OK != err)
+ goto out;
+ }
+
+ // Write data to the target buffer
+
+ cmd_buf[0] = DF_BUF1_WRITE_CMD;
+ cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, false);
+ cyg_spi_transaction_transfer(spi_dev, dev->polled,
+ size, buf, NULL, true);
+ df_set_busy(dev);
+ err = df_wait_ready(dev);
+ if (CYG_DATAFLASH_ERR_OK != err)
+ goto out;
+
+ // Program data from the target buffer to main memory
+ // and perform an erase before if requested
+
+ if (erase)
+ cmd_buf[0] = DF_BUF1_PROG_W_ERASE_CMD;
+ else
+ cmd_buf[0] = DF_BUF1_PROG_WO_ERASE_CMD;
+
+ cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true);
+ df_set_busy(dev);
+ err = df_wait_ready(dev);
+ if (CYG_DATAFLASH_ERR_OK != err)
+ goto out;
+
+ // Compare the target buffer contents with the freshly
+ // written main memory page (if requested)
+
+ if (verify)
+ {
+ cmd_buf[0] = DF_BUF1_COMPARE_CMD;
+ cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true);
+ df_set_busy(dev);
+ err = df_wait_ready(dev);
+ if (CYG_DATAFLASH_ERR_OK != err)
+ goto out;
+
+ status = df_read_status(dev);
+
+ if (status.compare_err)
+ {
+ err = CYG_DATAFLASH_ERR_COMPARE;
+ goto out;
+ }
+ }
+
+ // Adjust running values
+
+ page_pos = 0;
+ page_num += 1;
+ count -= size;
+ buf += size;
+ }
+
+out:
+ cyg_spi_transaction_end(spi_dev);
+
+ *len -= count;
+
+ return err;
+}
+
+//----------------------------------------------------------------------------
+// End of devs_flash_atmel_dataflash.c
Index: packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash_flash_dev_funs.c
===================================================================
RCS file: packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash_flash_dev_funs.c
diff -N packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash_flash_dev_funs.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash_flash_dev_funs.c 18 Nov 2008 01:05:46 -0000
@@ -0,0 +1,224 @@
+//==========================================================================
+//
+// devs_flash_atmel_dataflash_flash_dev_funs.c
+//
+// DataFlash flash device funs
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Savin Zlobec <savin@elatec.si>
+// Date: 2004-09-06
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/system.h>
+#include <pkgconf/hal.h>
+#include <pkgconf/devs_flash_atmel_dataflash.h>
+#include <pkgconf/io_flash.h>
+
+#include <cyg/infra/diag.h>
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <cyg/io/spi.h>
+#include <cyg/io/dataflash.h>
+
+// --------------------------------------------------------------------------
+
+#define RETURN_ON_ERROR(_op_) \
+ if (CYG_DATAFLASH_ERR_OK != (err = _op_)) return df_flash_hwr_map_error(dev, err)
+
+#define GOTO_ON_ERROR(_op_) \
+ if (CYG_DATAFLASH_ERR_OK != (err = _op_)) goto on_error
+
+static int
+df_flash_hwr_map_error(struct cyg_flash_dev *dev, int err)
+{
+ switch (err)
+ {
+ case CYG_DATAFLASH_ERR_OK: return CYG_FLASH_ERR_OK;
+ case CYG_DATAFLASH_ERR_INVALID: return CYG_FLASH_ERR_INVALID;
+ case CYG_DATAFLASH_ERR_WRONG_PART: return CYG_FLASH_ERR_DRV_WRONG_PART;
+ case CYG_DATAFLASH_ERR_TIMEOUT: return CYG_FLASH_ERR_DRV_TIMEOUT;
+ case CYG_DATAFLASH_ERR_COMPARE: return CYG_FLASH_ERR_DRV_VERIFY;
+ default: return CYG_FLASH_ERR_INVALID;
+ }
+}
+
+// --------------------------------------------------------------------------
+
+static int
+df_flash_init(struct cyg_flash_dev *dev)
+{
+ cyg_dataflash_flash_dev_priv_t *priv;
+ cyg_dataflash_device_t *df_dev;
+ int sector_cnt;
+
+ priv = (cyg_dataflash_flash_dev_priv_t *) dev->priv;
+ df_dev = &priv->dev;
+
+#ifdef CYGPKG_REDBOOT
+ if (cyg_dataflash_init(true, df_dev))
+#else
+ if (cyg_dataflash_init(false, df_dev))
+#endif
+ return CYG_DATAFLASH_ERR_WRONG_PART;
+
+ cyg_dataflash_set_blocking_operation(df_dev, true);
+
+ sector_cnt = cyg_dataflash_get_sector_count(df_dev);
+
+ if (priv->end_sector < 0)
+ priv->end_sector = sector_cnt - 1;
+
+ if (priv->start_sector >= sector_cnt ||
+ priv->end_sector >= sector_cnt ||
+ priv->end_sector < priv->start_sector)
+ return CYG_DATAFLASH_ERR_INVALID;
+
+ priv->start_page = cyg_dataflash_get_block_size(df_dev) *
+ cyg_dataflash_get_sector_start(df_dev, priv->start_sector);
+
+ priv->end_page = cyg_dataflash_get_block_size(df_dev) *
+ (cyg_dataflash_get_sector_start(df_dev, priv->end_sector) +
+ cyg_dataflash_get_sector_size(df_dev, priv->end_sector));
+
+ dev->end = (cyg_flashaddr_t)(dev->start +
+ ((priv->end_page - priv->start_page) *
+ cyg_dataflash_get_page_size(df_dev)) - 1);
+ priv->block_info[0].block_size = cyg_dataflash_get_page_size(df_dev);
+ priv->block_info[0].blocks = priv->end_page - priv->start_page;
+
+ return CYG_DATAFLASH_ERR_OK;
+}
+
+static int
+df_flash_erase_block(struct cyg_flash_dev *dev,
+ cyg_flashaddr_t base)
+{
+ cyg_dataflash_flash_dev_priv_t *priv;
+ cyg_uint32 page;
+ int err;
+
+ priv = (cyg_dataflash_flash_dev_priv_t *) dev->priv;
+
+ page = priv->start_page + ((base - dev->start) /
+ cyg_dataflash_get_page_size(&priv->dev));
+
+ RETURN_ON_ERROR( cyg_dataflash_aquire(&priv->dev) );
+ GOTO_ON_ERROR( cyg_dataflash_erase(&priv->dev, page) );
+ RETURN_ON_ERROR( cyg_dataflash_release(&priv->dev) );
+
+ return CYG_DATAFLASH_ERR_OK;
+
+on_error:
+ cyg_dataflash_release(&priv->dev);
+ return df_flash_hwr_map_error(dev, err);
+}
+
+static int
+df_flash_program(struct cyg_flash_dev *dev,
+ cyg_flashaddr_t base,
+ const void *data,
+ size_t len)
+{
+ cyg_dataflash_flash_dev_priv_t *priv;
+ cyg_uint32 page, pos;
+ int err;
+
+ priv = (cyg_dataflash_flash_dev_priv_t *) dev->priv;
+
+ page = priv->start_page + ((base - dev->start) /
+ cyg_dataflash_get_page_size(&priv->dev));
+ pos = (base - dev->start) % cyg_dataflash_get_page_size(&priv->dev);
+
+ RETURN_ON_ERROR( cyg_dataflash_aquire(&priv->dev) );
+ GOTO_ON_ERROR( cyg_dataflash_mem_to_buf(&priv->dev, 1, page) );
+ GOTO_ON_ERROR( cyg_dataflash_write_buf(&priv->dev, 1, data, len, pos) );
+ GOTO_ON_ERROR( cyg_dataflash_program_buf(&priv->dev, 1, page, true) );
+ RETURN_ON_ERROR( cyg_dataflash_release(&priv->dev) );
+
+ return CYG_DATAFLASH_ERR_OK;
+
+on_error:
+ cyg_dataflash_release(&priv->dev);
+ return df_flash_hwr_map_error(dev, err);
+}
+
+static int
+df_flash_read(struct cyg_flash_dev *dev,
+ const cyg_flashaddr_t base,
+ void *data,
+ size_t len)
+{
+ cyg_dataflash_flash_dev_priv_t *priv;
+ cyg_uint32 page, pos;
+ int err;
+
+ priv = (cyg_dataflash_flash_dev_priv_t *) dev->priv;
+
+ page = priv->start_page + ((base - dev->start) /
+ cyg_dataflash_get_page_size(&priv->dev));
+ pos = (base - dev->start) % cyg_dataflash_get_page_size(&priv->dev);
+
+ RETURN_ON_ERROR( cyg_dataflash_aquire(&priv->dev) );
+ GOTO_ON_ERROR( cyg_dataflash_mem_to_buf(&priv->dev, 1, page) );
+ GOTO_ON_ERROR( cyg_dataflash_read_buf(&priv->dev, 1, data, len, pos) );
+ RETURN_ON_ERROR( cyg_dataflash_release(&priv->dev) );
+
+ return CYG_DATAFLASH_ERR_OK;
+
+on_error:
+ cyg_dataflash_release(&priv->dev);
+ return df_flash_hwr_map_error(dev, err);
+}
+
+// --------------------------------------------------------------------------
+
+CYG_FLASH_FUNS(cyg_dataflash_flash_dev_funs,
+ df_flash_init,
+ cyg_flash_devfn_query_nop,
+ df_flash_erase_block,
+ df_flash_program,
+ df_flash_read,
+ cyg_flash_devfn_lock_nop,
+ cyg_flash_devfn_unlock_nop
+);
+
+//----------------------------------------------------------------------------
+// End of devs_flash_atmel_dataflash_flash_dev_funs.c