This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

various submissions


Hi,

here's some stuff I made, submitted for itegration into ecos cvs.
There's the modular AT91 HAL, consisting of hal_at91.epk and
hal_eb40.epk. io_flash.diff extends the flash driver interface to
support flash chips with non-uniform sector layout (different
sector sizes), flash_at49xxxx.epk is a flash chip driver for
Atmel AT49LV/BV flash chips using this new interface.
redboot_5.diff patches RedBoot to use the extended flash
driver interface. A copyright assingment covering these
items has been mailed to Red Hat.

at91_flash.diff modifies the at91 flash chip driver so it can
access the entire flash and work with RedBoot even if FIS
support is enabled, which the current version does not. I
hope this patch is sufficiently small so that no copyright
assignment is required for it.

tk

-- 

Thomas Koeller, Software Development

Basler Vision Technologies
An der Strusbek 60-62
22926 Ahrensburg
Germany

Phone	+49 (4102) 463-390
Fax	+49 (4102) 463-46390

mailto:thomas.koeller@baslerweb.com
http://www.baslerweb.com 

Attachment: flash_at49xxxx.epk
Description: GNU Zip compressed data

Attachment: hal_at91.epk
Description: GNU Zip compressed data

Attachment: hal_eb40.epk
Description: GNU Zip compressed data

diff -ru packages-orig/devs/flash/arm/at91/current/ChangeLog packages/devs/flash/arm/at91/current/ChangeLog
--- packages-orig/devs/flash/arm/at91/current/ChangeLog	Sat Oct  5 18:15:48 2002
+++ packages/devs/flash/arm/at91/current/ChangeLog	Sat Oct  5 18:29:01 2002
@@ -1,3 +1,12 @@
+2002-10-05  Thomas Koeller  <thomas@koeller.dyndns.org>
+
+	* src/flash.h:
+      	* src/at91_flash.c:
+	* src/flash_query.c: Allow use of entire flash.
+	* src/flash_erase_block.c: Replaced dummy erase function with real one, as
+	required by redboot fis code.
+	* src/flash_program_buf.c: Re-enable data cache after programming.
+
 2001-07-19  Gary Thomas  <gthomas@redhat.com>
 
 	* src/flash_program_buf.c: Fix - needs to have A16 set.
diff -ru packages-orig/devs/flash/arm/at91/current/src/at91_flash.c packages/devs/flash/arm/at91/current/src/at91_flash.c
--- packages-orig/devs/flash/arm/at91/current/src/at91_flash.c	Sat Oct  5 18:15:48 2002
+++ packages/devs/flash/arm/at91/current/src/at91_flash.c	Sun Oct  6 13:39:45 2002
@@ -41,7 +41,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):    gthomas
-// Contributors: gthomas
+// Contributors: gthomas, tkoeller
 // Date:         2001-07-17
 // Purpose:      
 // Description:  
@@ -89,8 +89,8 @@
     }
 
     if (data[1] == (unsigned short)FLASH_ATMEL_29LV1024) {
-        num_regions = 256;
-        region_size = 0x100;
+        num_regions = N_FLASH_SECTORS;
+        region_size = FLASH_PAGE_SIZE;
     } else {
         (*flash_info.pf)("Unknown device type: %x\n", data[1]);
         return FLASH_ERR_HWR;
@@ -99,8 +99,8 @@
     // Hard wired for now
     flash_info.block_size = region_size;
     flash_info.blocks = num_regions;
-    flash_info.start = (void *)0x01010000;
-    flash_info.end = (void *)(0x01010000+(num_regions*region_size));
+    flash_info.start = (void *) FLASH_BASE;
+    flash_info.end = (void *)(FLASH_BASE +(num_regions*region_size));
     return FLASH_ERR_OK;
 }
 
diff -ru packages-orig/devs/flash/arm/at91/current/src/flash.h packages/devs/flash/arm/at91/current/src/flash.h
--- packages-orig/devs/flash/arm/at91/current/src/flash.h	Sat Oct  5 18:15:48 2002
+++ packages/devs/flash/arm/at91/current/src/flash.h	Sun Oct  6 13:40:25 2002
@@ -41,7 +41,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):    gthomas
-// Contributors: gthomas
+// Contributors: gthomas, tkoeller
 // Date:         2001-07-17
 // Purpose:      
 // Description:  
@@ -74,5 +74,15 @@
 #define FLASH_PAGE_SIZE    0x100
 #define FLASH_PAGE_MASK   ~(FLASH_PAGE_SIZE-1)
 #define FLASH_PAGE_OFFSET  (FLASH_PAGE_SIZE-1)
+
+#define USE_FULL_FLASH 1
+
+#if USE_FULL_FLASH
+# define N_FLASH_SECTORS 512
+# define FLASH_BASE 0x01000000
+#else
+# define N_FLASH_SECTORS 256
+# define FLASH_BASE 0x01010000
+#endif
 
 #endif  // _FLASH_HWR_H_
diff -ru packages-orig/devs/flash/arm/at91/current/src/flash_erase_block.c packages/devs/flash/arm/at91/current/src/flash_erase_block.c
--- packages-orig/devs/flash/arm/at91/current/src/flash_erase_block.c	Sat Oct  5 18:15:48 2002
+++ packages/devs/flash/arm/at91/current/src/flash_erase_block.c	Sat Oct  5 18:19:44 2002
@@ -41,7 +41,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):    gthomas
-// Contributors: gthomas
+// Contributors: gthomas, tkoeller
 // Date:         2001-07-17
 // Purpose:      
 // Description:  
@@ -56,16 +56,43 @@
 #include <cyg/hal/hal_arch.h>
 #include <cyg/hal/hal_cache.h>
 
-//
+/*
 // CAUTION!  This code must be copied to RAM before execution.  Therefore,
 // it must not contain any code which might be position dependent!
-//
+*/
 
-int flash_erase_block(volatile unsigned long *block)
+int flash_erase_block(volatile unsigned short *block)
 {
+  int cache_on, i, timeout = 50000;
+  volatile unsigned short * ROM;
+
+  HAL_DCACHE_IS_ENABLED(cache_on);
+  if (cache_on)
+  {
+    HAL_DCACHE_SYNC();
+    HAL_DCACHE_DISABLE();
+  }
+
+  ROM = (volatile unsigned short *)((unsigned long)block & 0xFFFF0000);
+
+  /* Send lead-in sequence */
+  ROM[FLASH_Key_Addr0] = FLASH_Key0;
+  ROM[FLASH_Key_Addr1] = FLASH_Key1;
+
+  /* Send 'write' command */
+  ROM[FLASH_Key_Addr0] = FLASH_Program;
+
+  /* Clear block to 0xffff */
+  for (i = 0; i < FLASH_PAGE_SIZE/2; i++)
+    block[i] = 0xffff;
+
+  // Wait for data to be programmed
+  while (timeout-- > 0)
+    if (block[(FLASH_PAGE_SIZE/2) - 1] == 0xffff)
+      break;
 
-// This device is implicitly erased as each sector needs to be written
-// as a whole.  Thus, this is a NOP
+  if (cache_on)
+      HAL_DCACHE_ENABLE();
 
-    return 0;
+  return timeout > 0 ? FLASH_PROGRAM_OK : FLASH_PROGRAM_ERROR;
 }
diff -ru packages-orig/devs/flash/arm/at91/current/src/flash_program_buf.c packages/devs/flash/arm/at91/current/src/flash_program_buf.c
--- packages-orig/devs/flash/arm/at91/current/src/flash_program_buf.c	Sat Oct  5 18:15:48 2002
+++ packages/devs/flash/arm/at91/current/src/flash_program_buf.c	Sun Oct  6 13:42:16 2002
@@ -41,7 +41,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):    gthomas
-// Contributors: gthomas
+// Contributors: gthomas, tkoeller
 // Date:         2001-07-17
 // Purpose:      
 // Description:  
@@ -123,5 +123,5 @@
         HAL_DCACHE_ENABLE();
     }
 
-    return FLASH_PROGRAM_OK;
+    return timeout > 0 ? FLASH_PROGRAM_OK : FLASH_PROGRAM_ERROR;
 }
diff -ru packages-orig/devs/flash/arm/at91/current/src/flash_query.c packages/devs/flash/arm/at91/current/src/flash_query.c
--- packages-orig/devs/flash/arm/at91/current/src/flash_query.c	Sat Oct  5 18:15:48 2002
+++ packages/devs/flash/arm/at91/current/src/flash_query.c	Sun Oct  6 13:41:11 2002
@@ -41,7 +41,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):    gthomas
-// Contributors: gthomas
+// Contributors: gthomas, tkoeller
 // Date:         2001-07-17
 // Purpose:      
 // Description:  
@@ -76,7 +76,7 @@
         HAL_DCACHE_DISABLE();
     }
 
-    ROM = (volatile unsigned short *)0x01010000;
+    ROM = (volatile unsigned short *) FLASH_BASE;
 
     // Send lead-in sequence
     ROM[FLASH_Key_Addr0] = FLASH_Key0;
diff -ru packages-orig/io/flash/current/ChangeLog packages/io/flash/current/ChangeLog
--- packages-orig/io/flash/current/ChangeLog	Fri Aug 30 13:11:37 2002
+++ packages/io/flash/current/ChangeLog	Fri Aug 30 13:14:14 2002
@@ -1,3 +1,8 @@
+2002-08-23  Thomas Koeller  <thomas@koeller.dyndns.org>
+    	* include/flash.h:
+	* src/flash.c: Extended public interface to support flash chips
+	with non-uniform sector (block) layout.
+
 2002-01-31  Jonathan Larmour  <jlarmour@redhat.com>
 
 	* src/flashiodev.c: Fix bounds checking and offsetting.
diff -ru packages-orig/io/flash/current/include/flash.h packages/io/flash/current/include/flash.h
--- packages-orig/io/flash/current/include/flash.h	Fri Aug 30 13:11:37 2002
+++ packages/io/flash/current/include/flash.h	Fri Aug 30 13:14:14 2002
@@ -41,7 +41,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):    gthomas
-// Contributors: gthomas
+// Contributors: gthomas, tkoeller
 // Date:         2000-07-14
 // Purpose:      
 // Description:  
@@ -55,8 +55,11 @@
 
 #include <pkgconf/io_flash.h>
 #include <cyg/hal/hal_cache.h>
+#include <cyg/infra/cyg_type.h>
 
 typedef int _printf(const char *fmt, ...);
+typedef struct { void *start; int nbytes; } cyg_io_flash_block_info_t;
+typedef bool cyg_io_flash_block_iterator_callback_t(cyg_io_flash_block_info_t *blkinfo, CYG_ADDRWORD context);
 
 #define FLASH_MIN_WORKSPACE CYGNUM_FLASH_WORKSPACE_SIZE  // Space used by FLASH code
 
@@ -73,6 +76,11 @@
 externC int flash_get_block_info(int *block_size, int *blocks);
 externC bool flash_code_overlaps(void *start, void *end);
 externC char *flash_errmsg(int err);
+externC void flash_iterate_blocks(void * start, int size, cyg_io_flash_block_iterator_callback_t *cb, CYG_ADDRWORD context);
+externC bool flash_get_block(void *flash_addr, cyg_io_flash_block_info_t *blkinfo);
+externC bool flash_get_block_for_index(int index, cyg_io_flash_block_info_t *blkinfo);
+
+
 
 #define FLASH_ERR_OK              0x00  // No error - operation complete
 #define FLASH_ERR_INVALID         0x01  // Invalid FLASH address
@@ -122,9 +130,13 @@
     _printf *pf;
 };
 
+typedef bool flash_get_block_info_func(int block_idx, cyg_io_flash_block_info_t *block_info);
+
 externC struct flash_info flash_info;
 externC int  flash_hwr_init(void);
 externC int  flash_hwr_map_error(int err);
+externC flash_get_block_info_func *flash_block_query;
+
 
 // 
 // Some FLASH devices may require additional support, e.g. to turn on
diff -ru packages-orig/io/flash/current/src/flash.c packages/io/flash/current/src/flash.c
--- packages-orig/io/flash/current/src/flash.c	Fri Aug 30 13:11:37 2002
+++ packages/io/flash/current/src/flash.c	Fri Aug 30 14:37:34 2002
@@ -41,7 +41,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):    gthomas
-// Contributors: gthomas
+// Contributors: gthomas, tkoeller
 // Date:         2000-07-26
 // Purpose:      
 // Description:  
@@ -71,6 +71,28 @@
 #endif
 
 struct flash_info flash_info;
+flash_get_block_info_func *flash_block_query;
+
+static void *
+get_block_base(void *addr)
+{
+    cyg_io_flash_block_info_t bi;
+    return flash_get_block(addr, &bi) ? bi.start : NULL;
+}
+
+static bool
+flash_get_block_info_default(int block_idx, cyg_io_flash_block_info_t *block_info)
+{
+    int absblock =
+    	(block_idx >= 0) ? block_idx : (flash_info.blocks - block_idx);
+    if (absblock >= flash_info.blocks || absblock < 0) {
+    	return false;
+    }
+    block_info->start =
+	(void *) ((CYG_ADDRESS) flash_info.start + absblock * flash_info.block_size);
+    block_info->nbytes = flash_info.block_size;
+    return true;
+}
 
 int
 flash_init(void *work_space, int work_space_size, _printf *pf)
@@ -78,6 +100,7 @@
     int err;
 
     if (flash_info.init) return FLASH_ERR_OK;
+    flash_block_query = flash_get_block_info_default;
     flash_info.pf = pf; // Do this before calling into the driver
     flash_info.work_space = work_space;
     flash_info.work_space_size = work_space_size;
@@ -99,6 +122,62 @@
 }
 #endif
 
+// Returns index of block containing given flash address,
+// or -1 if address invalid.
+static int
+get_block_index(void *flash_addr)
+{
+    int res = -1;
+    if (flash_verify_addr(flash_addr) != FLASH_ERR_OK)
+    	return -1;
+    if (flash_info.block_size != 0) {
+    	res = ((CYG_ADDRESS) flash_addr - (CYG_ADDRESS) flash_info.start) / flash_info.block_size;
+    } else {
+    	cyg_io_flash_block_info_t blkinfo;
+	int i;
+	for (i = 0; flash_block_query(i, &blkinfo); i++) {
+	    if ((CYG_ADDRESS) flash_addr >= (CYG_ADDRESS) blkinfo.start &&
+	    	(CYG_ADDRESS) flash_addr < (CYG_ADDRESS) blkinfo.start + blkinfo.nbytes) {
+	    	res = i;
+		break;
+	    }
+	}
+    }
+    return res;
+}
+
+bool
+flash_get_block(void *flash_addr, cyg_io_flash_block_info_t *blkinfo)
+{
+    int index = get_block_index(flash_addr);
+    bool res = index >= 0;
+    
+    if (res) {
+    	flash_block_query(index, blkinfo);
+    }
+    return res;
+}
+
+bool
+flash_get_block_for_index(int index, cyg_io_flash_block_info_t *blkinfo)
+{
+    return flash_block_query(index, blkinfo);
+}
+
+void
+flash_iterate_blocks(void *start, int size, cyg_io_flash_block_iterator_callback_t cb, CYG_ADDRWORD context)
+{
+    cyg_io_flash_block_info_t blkinfo;
+    int index = get_block_index(start);
+    bool cbres;
+    if (index < 0) return;
+    
+    do {
+    	flash_block_query(index++, &blkinfo);
+    	cbres = cb(&blkinfo, context);
+    } while (cbres && ((CYG_ADDRESS) blkinfo.start + blkinfo.nbytes < (CYG_ADDRESS) start + size));
+}
+
 // FIXME: Want to change all drivers to use this function. But it may
 // make sense to wait till device structure pointer arguments get
 // added as well.
@@ -172,6 +251,7 @@
 {
     unsigned short *block, *end_addr;
     int stat = 0;
+    int bksiz;
     typedef int code_fun(unsigned short *, unsigned int);
     code_fun *_flash_erase_block;
     int d_cache, i_cache;
@@ -202,7 +282,12 @@
     }
 #endif
 
-    block = (unsigned short *)((CYG_ADDRESS)addr & flash_info.block_mask);
+    {
+	cyg_io_flash_block_info_t bi;
+	flash_get_block(addr, &bi);
+	block = (unsigned short *) bi.start;
+	bksiz = bi.nbytes;
+    }
     end_addr = (unsigned short *)((CYG_ADDRESS)addr+len);
 
     /* Check to see if end_addr overflowed */
@@ -222,14 +307,14 @@
         unsigned short *tmp_block;
 
         dp = (unsigned char *)block;
-        for (i = 0;  i < flash_info.block_size;  i++) {
+        for (i = 0;  i < bksiz;  i++) {
             if (*dp++ != (unsigned char)0xFF) {
                 erased = false;
                 break;
             }
         }
         if (!erased) {
-            stat = (*_flash_erase_block)(block, flash_info.block_size);
+            stat = (*_flash_erase_block)(block, bksiz);
             stat = flash_hwr_map_error(stat);
         }
         if (stat) {
@@ -238,7 +323,7 @@
         }
 
         // Check to see if block will overflow
-        tmp_block = block + flash_info.block_size / sizeof(*block);
+        tmp_block = block + bksiz / sizeof(*block);
         if(tmp_block < block){
             // If block address overflows, set block value to end on this loop
             block = end_addr;
@@ -264,6 +349,7 @@
     unsigned char *addr = (unsigned char *)_addr;
     unsigned char *data = (unsigned char *)_data;
     CYG_ADDRESS tmp;
+    cyg_io_flash_block_info_t bi;
     int d_cache, i_cache;
 
     if (!flash_info.init) {
@@ -294,17 +380,17 @@
     (*flash_info.pf)("... Program from %p-%p at %p: ", (void*)data, 
                      (void*)(((CYG_ADDRESS)data)+len), (void*)addr);
 
+    flash_get_block(_addr, &bi);
     HAL_FLASH_CACHES_OFF(d_cache, i_cache);
     FLASH_Enable((unsigned short*)addr, (unsigned short *)(addr+len));
     while (len > 0) {
         size = len;
-        if (size > flash_info.block_size) size = flash_info.block_size;
+        if (size > bi.nbytes) size = bi.nbytes;
 
-        tmp = (CYG_ADDRESS)addr & ~flash_info.block_mask;
+        tmp = (CYG_ADDRESS)bi.start;
         if (tmp) {
-                tmp = flash_info.block_size - tmp;
-                if (size>tmp) size = tmp;
-
+            tmp = bi.nbytes - tmp;
+            if (size>tmp) size = tmp;
         }
 
         stat = (*_flash_program_buf)(addr, data, size, 
@@ -368,7 +454,7 @@
     }
 #endif
 
-    block = (unsigned short *)((CYG_ADDRESS)addr & flash_info.block_mask);
+    block = (unsigned short *) get_block_base(addr);
     end_addr = (unsigned short *)((CYG_ADDRESS)addr+len);
 
     /* Check to see if end_addr overflowed */
@@ -440,7 +526,7 @@
     }
 #endif
 
-    block = (unsigned short *)((CYG_ADDRESS)addr & flash_info.block_mask);
+    block = (unsigned short *) get_block-_base(addr);
     end_addr = (unsigned short *)((CYG_ADDRESS)addr+len);
 
     /* Check to see if end_addr overflowed */
diff -ru packages-orig/redboot/current/ChangeLog packages/redboot/current/ChangeLog
--- packages-orig/redboot/current/ChangeLog	Sun Oct  6 17:07:57 2002
+++ packages/redboot/current/ChangeLog	Sun Oct  6 18:45:12 2002
@@ -1,3 +1,8 @@
+2002-10-06  Thomas Koeller  <thomas@koeller.dyndns.org>
+
+      	* src/flash.c: Added support for new flash driver interface, allowing
+	use of flash chips with non-uniform sector layout.
+
 2002-09-16  Mark Salter  <msalter@redhat.com>
 
 	* src/main.c (set_console_baud_rate): Handle CYGPKG_REDBOOT_ANY_CONSOLE.
diff -ru packages-orig/redboot/current/src/flash.c packages/redboot/current/src/flash.c
--- packages-orig/redboot/current/src/flash.c	Sun Oct  6 17:07:57 2002
+++ packages/redboot/current/src/flash.c	Sun Oct  6 17:19:30 2002
@@ -183,7 +183,8 @@
 #ifdef CYGOPT_REDBOOT_FIS
 static void *fis_work_block;
 static void *fis_addr;
-static int fisdir_size;  // Size of FIS directory.
+static int fisdir_size;     	// Size of FIS directory.
+static int fisdir_block_size;	// Size of flash block containing FIS directory
 #endif
 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
 static void *cfg_base;   // Location in Flash of config data
@@ -206,6 +207,13 @@
     diag_printf("   valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
 }
 
+static bool
+fis_create_callback(cyg_io_flash_block_info_t *blkinfo, unsigned long *size)
+{
+    *size += (unsigned long) blkinfo->nbytes;
+    return true;
+}
+
 #ifdef CYGOPT_REDBOOT_FIS
 struct fis_image_desc *
 fis_lookup(char *name, int *num)
@@ -235,12 +243,12 @@
 #endif
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
     // Ensure [quietly] that the directory is unlocked before trying to update
-    flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr);
+    flash_unlock((void *)fis_addr, fisdir_block_size, (void **)&err_addr);
 #endif
-    if ((stat = flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) {
+    if ((stat = flash_erase(fis_addr, fisdir_block_size, (void **)&err_addr)) != 0) {
         diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat));
     } else {
-        if ((stat = flash_program(fis_addr, fis_work_block, flash_block_size,
+        if ((stat = flash_program(fis_addr, fis_work_block, fisdir_block_size,
                                   (void **)&err_addr)) != 0) {
             diag_printf("Error writing FIS directory at %p: %s\n", 
                         err_addr, flash_errmsg(stat));
@@ -248,7 +256,7 @@
     }
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
     // Ensure [quietly] that the directory is locked after the update
-    flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr);
+    flash_lock((void *)fis_addr, fisdir_block_size, (void **)&err_addr);
 #endif
 }
 
@@ -413,7 +421,7 @@
           diag_printf("   initialization failed %p: %s\n",
                  err_addr, flash_errmsg(stat));
         }
-        erase_start += (erase_size + flash_block_size);
+        erase_start += (erase_size + fisdir_block_size);
         if (fis_addr > cfg_base) {
           erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between config and fis data
         } else {
@@ -501,82 +509,98 @@
     }
 }
 
+typedef struct
+{
+    void *start;
+    int size;
+} flash_region_descriptor_t;
+
+static bool
+fis_free_callback(cyg_io_flash_block_info_t *blkinfo, flash_region_descriptor_t * regdesc)
+{
+    if (* (unsigned long *) blkinfo->start == 0xFFFFFFFF) {
+    	if (regdesc->start == NULL) {
+	    regdesc->start = blkinfo->start;
+	    regdesc->size = blkinfo->nbytes;
+	} else {
+    	    regdesc->size += blkinfo->nbytes;
+	}
+    } else {
+	// Assume that this is something
+	if (regdesc->start != NULL) {
+	    diag_printf(
+	    	"  0x%08lX .. 0x%08lX\n",
+        	(CYG_ADDRESS)regdesc->start,
+		(CYG_ADDRESS)regdesc->start + regdesc->size
+	    );
+    	    regdesc->start = NULL;
+	}
+    }
+    return true;
+}
+
 static void
 fis_free(int argc, char *argv[])
 {
-    unsigned long *fis_ptr, *fis_end;
-    unsigned long *area_start;
-
+    flash_region_descriptor_t regdesc = {NULL, 0};
+    
     // Do not search the area reserved for pre-RedBoot systems:
-    fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
-    fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;
-    area_start = fis_ptr;
-    while (fis_ptr < fis_end) {
-        if (*fis_ptr != (unsigned long)0xFFFFFFFF) {
-            if (area_start != fis_ptr) {
-                // Assume that this is something
-                diag_printf("  0x%08lX .. 0x%08lX\n",
-                            (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr);
-            }
-            // Find next blank block
-            area_start = fis_ptr;
-            while (area_start < fis_end) {
-                if (*area_start == (unsigned long)0xFFFFFFFF) {
-                    break;
-                }
-                area_start += flash_block_size / sizeof(CYG_ADDRESS);
-            }
-            fis_ptr = area_start;
-        } else {
-            fis_ptr += flash_block_size / sizeof(CYG_ADDRESS);
-        }
+    flash_iterate_blocks(
+    	(void *) ((CYG_ADDRESS) flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE),
+	(CYG_ADDRESS) flash_end - (CYG_ADDRESS) flash_start - CYGNUM_REDBOOT_FLASH_RESERVED_BASE,
+	fis_free_callback,
+	(CYG_ADDRWORD) &regdesc
+    );
+    
+    // last region
+    if (regdesc.start != NULL) {
+	diag_printf(
+	    "  0x%08lX .. 0x%08lX\n",
+            (CYG_ADDRESS)regdesc.start,
+	    (CYG_ADDRESS)regdesc.start + regdesc.size
+	);
     }
-    if (area_start != fis_ptr) {
-        diag_printf("  0x%08lX .. 0x%08lX\n", 
-                    (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr);
+}
+
+typedef struct
+{
+    void *start;
+    unsigned long size;
+    unsigned long req_size;
+} find_free_cb_arg_t;
+
+static bool
+fis_find_free_callback(cyg_io_flash_block_info_t *blkinfo, find_free_cb_arg_t *arg)
+{
+    if (* (unsigned long *) blkinfo->start == 0xFFFFFFFF) {
+    	if (arg->start == NULL) {
+	    arg->start = blkinfo->start;
+	    arg->size = blkinfo->nbytes;
+	} else {
+    	    arg->size += (unsigned long) blkinfo->nbytes;
+	}
+    } else {
+    	arg->start = NULL;
     }
+    return arg->size < arg->req_size;
 }
 
 // Find the first unused area of flash which is long enough
 static bool
 fis_find_free(CYG_ADDRESS *addr, unsigned long length)
 {
-    unsigned long *fis_ptr, *fis_end;
-    unsigned long *area_start;
-
+    flash_region_descriptor_t regdesc = {NULL, 0};
+    
     // Do not search the area reserved for pre-RedBoot systems:
-    fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
-    fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;
-    area_start = fis_ptr;
-    while (fis_ptr < fis_end) {
-        if (*fis_ptr != (unsigned long)0xFFFFFFFF) {
-            if (area_start != fis_ptr) {
-                // Assume that this is something
-                if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) {
-                    *addr = (CYG_ADDRESS)area_start;
-                    return true;
-                }
-            }
-            // Find next blank block
-            area_start = fis_ptr;
-            while (area_start < fis_end) {
-                if (*area_start == (unsigned long)0xFFFFFFFF) {
-                    break;
-                }
-                area_start += flash_block_size / sizeof(CYG_ADDRESS);
-            }
-            fis_ptr = area_start;
-        } else {
-            fis_ptr += flash_block_size / sizeof(CYG_ADDRESS);
-        }
-    }
-    if (area_start != fis_ptr) {
-        if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) {
-            *addr = (CYG_ADDRESS)area_start;
-            return true;
-        }
-    }
-    return false;
+    flash_iterate_blocks(
+    	(void *) ((CYG_ADDRESS) flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE),
+	(CYG_ADDRESS) flash_end - (CYG_ADDRESS) flash_start - CYGNUM_REDBOOT_FLASH_RESERVED_BASE,
+	fis_find_free_callback,
+	(CYG_ADDRWORD) &regdesc
+    );
+    
+    *addr = (CYG_ADDRESS) regdesc.start;
+    return regdesc.start != NULL;
 }
 
 static void
@@ -675,23 +699,28 @@
     }
     // 'length' is size of FLASH image, 'img_size' is actual data size
     // Round up length to FLASH block size
-#ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
-    length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size;
-    if (length < img_size) {
-        diag_printf("Invalid FLASH image size/length combination\n");
-        return;
+    {
+    	unsigned long tmp = 0;
+	flash_iterate_blocks((void *) flash_addr, length, fis_create_callback, (CYG_ADDRWORD) &tmp);
+    	length = tmp;
+	if (length < img_size) {
+            diag_printf("Invalid FLASH image size/length combination\n");
+            return;
+	}
     }
-#endif
     if (flash_addr_set &&
         ((stat = flash_verify_addr((void *)flash_addr)) ||
          (stat = flash_verify_addr((void *)(flash_addr+img_size-1))))) {
         _show_invalid_flash_address(flash_addr, stat);
         return;
     }
-    if (flash_addr_set && flash_addr & (flash_block_size-1)) {
-        diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
-        diag_printf("   must be 0x%x aligned\n", flash_block_size);
-        return;
+    if (flash_addr_set) {
+    	cyg_io_flash_block_info_t blkinfo;
+	flash_get_block((void *) flash_addr, &blkinfo);
+	if (flash_addr != (CYG_ADDRESS) blkinfo.start) {
+            diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
+            return;
+	}
     }
     if (strlen(name) >= sizeof(img->name)) {
         diag_printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->name));
@@ -980,19 +1009,24 @@
     }
 
     // Round up length to FLASH block size
-#ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
-    length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size;
-#endif
+    {
+    	unsigned long tmp = 0;
+	flash_iterate_blocks((void *) flash_addr, flash_addr + length, fis_create_callback, (CYG_ADDRWORD) &tmp);
+    	length = tmp;
+    }
     if (flash_addr_set &&
         ((stat = flash_verify_addr((void *)flash_addr)) ||
          (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
         _show_invalid_flash_address(flash_addr, stat);
         return;
     }
-    if (flash_addr_set && flash_addr & (flash_block_size-1)) {
-        diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
-        diag_printf("   must be 0x%x aligned\n", flash_block_size);
-        return;
+    if (flash_addr_set) {
+    	cyg_io_flash_block_info_t blkinfo;
+	flash_get_block(flash_addr, &blkinfo);
+	if (flash_addr != blkinfo.start) {
+            diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
+            return;
+	}
     }
     if ((mem_addr < (CYG_ADDRESS)ram_start) ||
         ((mem_addr+length) >= (CYG_ADDRESS)ram_end)) {
@@ -1057,10 +1091,13 @@
         _show_invalid_flash_address(flash_addr, stat);
         return;
     }
-    if (flash_addr_set && flash_addr & (flash_block_size-1)) {
-        diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
-        diag_printf("   must be 0x%x aligned\n", flash_block_size);
-        return;
+    if (flash_addr_set) {
+    	cyg_io_flash_block_info_t blkinfo;
+	flash_get_block((void *) flash_addr, &blkinfo);
+	if (flash_addr != (CYG_ADDRESS) blkinfo.start) {
+            diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
+            return;
+	}
     }
     // Safety check - make sure the address range is not within the code we're running
     if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1))) {
@@ -1178,8 +1215,13 @@
 _flash_info(void)
 {
     if (!__flash_init) return;
-    diag_printf("FLASH: %p - %p, %d blocks of %p bytes each.\n", 
+    if (flash_block_size != 0) {
+    	diag_printf("FLASH: %p - %p, %d blocks of %p bytes each.\n", 
            flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size);
+   } else {
+    	diag_printf("FLASH: %p - %p, %d blocks of different sizes.\n", 
+           flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks);
+   }
 }
 
 static bool
@@ -1199,25 +1241,32 @@
         flash_get_block_info(&flash_block_size, &flash_num_blocks);
         workspace_end = (unsigned char *)(workspace_end-FLASH_MIN_WORKSPACE);
 #ifdef CYGOPT_REDBOOT_FIS
+    	if (flash_block_size != 0) {
+            fisdir_size = fisdir_block_size = flash_block_size;
+            if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) {
+        	fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
+                                    (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
+            } else {
+        	fis_addr = (void *)((CYG_ADDRESS)flash_start + 
+                                    (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
+            }
+	} else {
+	    cyg_io_flash_block_info_t blkinfo;
+	    flash_get_block_for_index(CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK, &blkinfo);
+	    fis_addr = blkinfo.start;
+	    fisdir_size = fisdir_block_size = blkinfo.nbytes;
+	}
 # ifdef CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER
 	fis_work_block = fis_zlib_common_buffer;
-	if(CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE < flash_block_size) {
+	if(CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE < fisdir_block_size) {
             diag_printf("FLASH: common buffer too small\n");
 	    workspace_end += FLASH_MIN_WORKSPACE;
             return false;
 	}
 # else
-        workspace_end = (unsigned char *)(workspace_end-flash_block_size);
+        workspace_end = (unsigned char *)(workspace_end-fisdir_block_size);
         fis_work_block = workspace_end;
 # endif
-        fisdir_size = flash_block_size;
-        if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) {
-            fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
-                                (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
-        } else {
-            fis_addr = (void *)((CYG_ADDRESS)flash_start + 
-                                (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
-        }
 #endif
         __flash_init = 1;
     }
@@ -2069,25 +2118,39 @@
     config = (struct _config *)(workspace_end-sizeof(struct _config));
     backup_config = (struct _config *)((CYG_ADDRESS)config-sizeof(struct _config));
     workspace_end = (unsigned char *)backup_config;
-    cfg_size = (flash_block_size > sizeof(struct _config)) ? 
-        sizeof(struct _config) : 
-        _rup(sizeof(struct _config), flash_block_size);
 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
-    cfg_size = _rup(cfg_size, sizeof(struct fis_image_desc));
-    if ((flash_block_size-cfg_size) < 8*sizeof(struct fis_image_desc)) {
+    cfg_size = _rup(sizeof(struct _config), sizeof(struct fis_image_desc));
+    if ((fisdir_block_size-cfg_size) < 8*sizeof(struct fis_image_desc)) {
         // Too bad this can't be checked at compile/build time
         diag_printf("Sorry, FLASH config exceeds available space in FIS directory\n");
         return;
     }
-    fisdir_size = flash_block_size - cfg_size;
+    fisdir_size = fisdir_block_size - cfg_size;
     cfg_base = (void *)(((CYG_ADDRESS)fis_addr + flash_block_size) - cfg_size);
 #else
-    if (CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK < 0) {
-        cfg_base = (void *)((CYG_ADDRESS)flash_end + 1 -
-           _rup(_rup((-CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size));
+    if (flash_block_size != 0) {
+	cfg_size = (flash_block_size > sizeof(struct _config)) ? 
+            sizeof(struct _config) : 
+            _rup(sizeof(struct _config), flash_block_size);
+        if (CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK < 0) {
+            cfg_base = (void *)((CYG_ADDRESS)flash_end + 1 -
+               _rup(_rup((-CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size));
+	} else {
+            cfg_base = (void *)((CYG_ADDRESS)flash_start + 
+               _rup(_rup((CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size));
+	}
     } else {
-        cfg_base = (void *)((CYG_ADDRESS)flash_start + 
-           _rup(_rup((CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size));
+	cyg_io_flash_block_info_t blkinfo;
+	flash_get_block_for_index(CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK, &blkinfo);
+	cfg_base = blkinfo.start;
+	cfg_size = blkinfo.nbytes;
+	
+	// If too small, increase size by adding more blocks
+	while (cfg_size < sizeof(struct _config)) {
+	    cyg_io_flash_block_info_t blkinfo;
+	    flash_get_block(cfg_base + cfg_size, &blkinfo);
+	    cfg_size += blkinfo.nbytes;
+	}
     }
 #endif
 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]