This is the mail archive of the
ecos-discuss@sources.redhat.com
mailing list for the eCos project.
Re: Supporting Paged Flash in eCos/RedBoot
Ian Campbell wrote:
Hi,
Attached is a rough first draft of a patch to implement an improved
flash interface -- It's a first pass and I certainly wouldn't expect you
to apply it as is...
The main bulk of the patch modifies the API of cyg/io/flash.h such that
each function takes a struct flash_info * as it's first parameter and
all addresses are described as unsigned long offsets
NB The flash drivers were written when Gary thought he could get away with
using things like ints and longs instead of the normal eCos-y types like
cyg_uint32 etc. Since we'd want to support flash drivers in eCos, it would
be good for proper portability to use e.g. CYG_ADDRESS for addresses. In
saying that, unsigned longs are okay for just offsets, although a
typedef'd type might be cunning.
It would also be brilliant if the functions had a "cyg_" prefix on the
front and not just "flash_". Otherwise the namespace gets polluted and it
only takes a user to have a global in their app called "int
flash_program;" for weird stuff to happen , or the link to fail :-). We
can add #define's for the existing API functions in flash.h for e.g.
flash_init to cyg_flash_init, for backwards compatibility, on the
assumption that these will go away "soon".
If this is too much right for you to do, we can revisit this before making
this API "official". Incidentally, while it's still work in progress, we
should probably even keep the existing drivers (and redboot flash.c)
working the same way. That can be by just renaming the files to
flash_erase_block2.c etc. all depending on that CDL interface setting, or
in the case of the strata flash driver, a configuration option so the user
can set it so we don't break systems relying on the old driver. But don't
worry about that for now - we can copy the files when it's closer to
completion... otherwise the diffs won't be helpful :-).
So, comments?
Many, as I'm sure you were expecting :-)... It's good stuff so far though...
Index: devs/flash/intel/strata/current/src/flash_erase_block.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/flash/intel/strata/current/src/flash_erase_block.c,v
retrieving revision 1.4
diff -u -b -B -w -p -u -r1.4 flash_erase_block.c
--- devs/flash/intel/strata/current/src/flash_erase_block.c 23 May 2002 23:01:02 -0000 1.4
+++ devs/flash/intel/strata/current/src/flash_erase_block.c 21 Feb 2003 13:33:53 -0000
@@ -56,19 +56,19 @@
#include <cyg/hal/hal_arch.h>
#include <cyg/hal/hal_cache.h>
+#include <cyg/io/flash.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 flash_t *block, unsigned int block_size)
+int flash_erase_block(struct flash_info *flash_info, unsigned long block, unsigned int block_size)
IMHO The hardware driver should already be perfectly aware what size the
block is :-), so that needn't be passed in.
int
-flash_program_buf(volatile flash_t *addr, flash_t *data, int len,
+flash_program_buf(struct flash_info *flash_info,
+ unsigned long offset, flash_t *data, int len,
unsigned long block_mask, int buffer_size)
I've never liked that block_mask thing. Again the driver should already
know what's needed. This is particularly relevant if the data written
straddles a boundary where the block size changes.
int
-flash_unlock_block(volatile flash_t *block, int block_size, int blocks)
+flash_unlock_block(struct flash_info *flash_info, unsigned long block, unsigned long block_size, int blocks)
Again block_size needn't be psased in. In other drivers then it's more
likely the right thing happens if a block size boundary is straddled.
Index: devs/flash/intel/strata/current/src/strata.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/flash/intel/strata/current/src/strata.c,v
retrieving revision 1.7
diff -u -b -B -w -p -u -r1.7 strata.c
--- devs/flash/intel/strata/current/src/strata.c 23 May 2002 23:01:02 -0000 1.7
+++ devs/flash/intel/strata/current/src/strata.c 21 Feb 2003 13:33:53 -0000
@@ -67,31 +67,53 @@ extern void diag_dump_buf(void *buf, CYG
extern int strncmp(const char *s1, const char *s2, size_t len);
extern void *memcpy( void *, const void *, size_t );
+#ifndef CYGHWR_IO_FLASH_DEVICE_NOT_IN_RAM
+// Use this function to make function pointers anonymous - forcing the
+// compiler to use jumps instead of branches when calling driver
+// services.
+static void* __anonymizer(void* p)
+{
+ return p;
+}
+#endif
About time this stuff got added to the strataflash driver. Great!
int
-flash_hwr_init(void)
+flash_hwr_init(struct flash_info *flash_info)
{
@@ -138,30 +160,34 @@ flash_hwr_init(void)
}
#endif // Not CYGOPT_FLASH_IS_BOOTBLOCK
- flash_info.block_size = region_size*CYGNUM_FLASH_DEVICES;
- flash_info.buffer_size = buffer_size;
- flash_info.blocks = num_regions;
- flash_info.start = (void *)CYGNUM_FLASH_BASE;
- flash_info.end = (void *)(CYGNUM_FLASH_BASE +
- (num_regions*region_size*CYGNUM_FLASH_DEVICES));
-#ifdef CYGNUM_FLASH_BASE_MASK
+ flash_info->block_size = region_size*CYGNUM_FLASH_DEVICES;
+ flash_info->buffer_size = buffer_size;
+ flash_info->blocks = num_regions*CYGNUM_FLASH_BANKS;
+#if 0 // IJC
+ flash_info->start = (void *)CYGNUM_FLASH_BASE;
+ flash_info->end = (void *)(CYGNUM_FLASH_BASE +
+ (num_regions*region_size*CYGNUM_FLASH_DEVICES*CYGNUM_FLASH_BANKS));
+#endif
+ flash_info->size = (num_regions*region_size*CYGNUM_FLASH_DEVICES*CYGNUM_FLASH_BANKS);
+
+#ifdef CYGNUM_FLASH_BASE_MASK_DISABLE // IJC -- what does this do?
Hmm... now what if a flash driver is for a flash with bootblocks? Or any
other device with different block sizes. We'd need to specify multiple
block sizes. Also specifying a count of blocks wouldn't be helpful in that
context.
This came up before with the AT91 flash, and I tried to do something to
get that working. Just in case it's a useful starting point, I've attached
a patch for io/flash that was meant to support variable block sizes
better. It's against the repository version not yours I'm afraid. In
particular struct flash_info would now contain a block table, with entries
describing the size. I never completed the work (doesn't help when you
have no hardware!), so the patch is yours to do with as you will :-). I
would (obviously) recommend this approach though.
Index: devs/flash/intel/strata/current/src/strata.h
+// ------------------------------------------------------------------------
+
+#ifndef HAL_FLASH_READ
+#define HAL_FLASH_READ(__OFFSET__, __VALUE__) \
+CYG_MACRO_START \
+__VALUE__ = *(volatile flash_t *)(cyg_uint8*)FLASH_P2V(CYGNUM_FLASH_BASE)+(__OFFSET__));\
+CYG_MACRO_END
+#endif
+
+#ifndef HAL_FLASH_WRITE
+#define HAL_FLASH_WRITE(__OFFSET__, __VALUE__) \
+CYG_MACRO_START \
+*(volatile flash_t *)((cyg_uint8*)FLASH_P2V(CYGNUM_FLASH_BASE)+(__OFFSET__)) = (__VALUE__); \
+CYG_MACRO_END
+#endif
+
If these are defined in the flash driver, they aren't really HAL macros
wanting the HAL prefix. That would confuse people as to where they are
defined. May I suggest CYGHWR_FLASH_READ and CYGHWR_FLASH_WRITE perhaps?
[snip io/flash/current/src/flash.c]
There's plenty of stuff in flash.c to munge to get rid of the reliance on
fixed block sizes and block masks.
[snip redboot/current/src/flash.c]
At this point I wouldn't try to get redboot working with the multiple
block sizes aspect of the API - save that challenge to another day as it
requires quite a rethink of this file. What's important is that the
underlying API in io/flash is capable of it.
This is all good stuff, and is definitely going the right way. You've
obviously also been very productive!
Great work,
Jifl
--
eCosCentric http://www.eCosCentric.com/ The eCos and RedBoot experts
--[ "You can complain because roses have thorns, or you ]--
--[ can rejoice because thorns have roses." -Lincoln ]-- Opinions==mine
? flash.at91.dead.patch
Index: cdl/io_flash.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/flash/current/cdl/io_flash.cdl,v
retrieving revision 1.11
diff -u -5 -p -r1.11 io_flash.cdl
--- cdl/io_flash.cdl 23 May 2002 23:06:14 -0000 1.11
+++ cdl/io_flash.cdl 14 Feb 2003 01:17:11 -0000
@@ -104,10 +104,19 @@ cdl_package CYGPKG_IO_FLASH {
description "
This option will be enabled by devices which can support
locking (write-protection) of individual blocks."
}
+ cdl_interface CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE {
+ display "Hardware has variable block sizes"
+ flavor booldata
+ description "
+ This option is enabled when a flash device and its driver
+ have variable block sizes, i.e. different block sizes for
+ different regions of the flash device."
+ }
+
cdl_option CYGSEM_IO_FLASH_VERIFY_PROGRAM {
display "Verify data programmed to flash"
flavor bool
default_value 1
description "
Index: include/flash.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/flash/current/include/flash.h,v
retrieving revision 1.15
diff -u -5 -p -r1.15 flash.h
--- include/flash.h 23 May 2002 23:06:14 -0000 1.15
+++ include/flash.h 14 Feb 2003 01:17:11 -0000
@@ -56,10 +56,18 @@
#include <pkgconf/io_flash.h>
#include <cyg/hal/hal_cache.h>
typedef int _printf(const char *fmt, ...);
+struct flash_block_table_entry {
+ void *offset_addr; // offset of this address from the start of
+ // the flash device's base address
+ unsigned long size; // size of this region
+ unsigned long block_size; // size of blocks in this region
+ // potential for expansion in future...
+};
+
#define FLASH_MIN_WORKSPACE CYGNUM_FLASH_WORKSPACE_SIZE // Space used by FLASH code
externC int flash_init(void *work_space, int work_space_length, _printf *pf);
externC int flash_erase(void *base, int len, void **err_address);
externC int flash_program(void *flash_base, void *ram_base, int len, void **err_address);
@@ -68,10 +76,22 @@ externC void flash_dev_query(void *data)
externC int flash_lock(void *base, int len, void **err_address);
externC int flash_unlock(void *base, int len, void **err_address);
#endif
externC int flash_verify_addr(void *base);
externC int flash_get_limits(void *base, void **start, void **end);
+
+// flash_block_size() returns -ve error code on error, or block size for
+// address on success
+externC int flash_block_size( void *address );
+
+// flash_get_block_table() returns a block table used by the driver giving
+// definitions of block sizes. The address argument is used to indicate
+// which device when in the future multiple devices are supported.
+externC int flash_get_block_table( void *flash_at_address,
+ const struct flash_block_table_entry **table);
+
+// flash_get_block_info() is deprecated.
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);
#define FLASH_ERR_OK 0x00 // No error - operation complete
@@ -111,14 +131,18 @@ typedef struct {
#ifdef _FLASH_PRIVATE_
struct flash_info {
void *work_space;
int work_space_size;
+#ifdef CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE
+ const struct flash_block_table_entry *block_table;
+#else
int block_size; // Assuming fixed size "blocks"
int blocks; // Number of blocks
+ unsigned long block_mask; // ~(block_size-1)
+#endif
int buffer_size; // Size of write buffer (only defined for some devices)
- unsigned long block_mask;
void *start, *end; // Address range
int init;
_printf *pf;
};
Index: src/flash.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/flash/current/src/flash.c,v
retrieving revision 1.20
diff -u -5 -p -r1.20 flash.c
--- src/flash.c 23 May 2002 23:06:16 -0000 1.20
+++ src/flash.c 14 Feb 2003 01:17:11 -0000
@@ -82,11 +82,13 @@ flash_init(void *work_space, int work_sp
flash_info.work_space = work_space;
flash_info.work_space_size = work_space_size;
if ((err = flash_hwr_init()) != FLASH_ERR_OK) {
return err;
}
+#ifndef CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE
flash_info.block_mask = ~(flash_info.block_size-1);
+#endif
flash_info.init = 1;
return FLASH_ERR_OK;
}
#ifndef CYGHWR_IO_FLASH_DEVICE_NOT_IN_RAM
@@ -155,17 +157,76 @@ flash_get_limits(void *target, void **st
*end = flash_info.end;
return FLASH_ERR_OK;
}
int
+flash_block_size( void *address )
+{
+ if (!flash_info.init) {
+ return -FLASH_ERR_NOT_INIT;
+ }
+#ifdef CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE
+ if ( address < flash_info.start || address >= flash_info.end )
+ return -FLASH_ERR_INVALID;
+ {
+ struct flash_block_table_entry *t = flash_info.block_table;
+ CYG_ADDRESS offset = (CYG_ADDRESS)address - (CYG_ADDRESS)flash_info.start;
+ while (t->offset_addr < offset) {
+ if (t->size == 0) // reached end of table. Hmm. This shouldn't
+ // happen though given the address check above.
+ return -FLASH_ERR_INVALID;
+ }
+ return t->block_size;
+ }
+#else
+ return flash_info.block_size;
+#endif
+}
+
+int flash_get_block_table( void *flash_at_address,
+ const struct flash_block_table_entry **table )
+{
+ if (!flash_info.init) {
+ return FLASH_ERR_NOT_INIT;
+ }
+#ifdef CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE
+ // flash_at_address ignored for now
+ *table = flash_info.block_table;
+#else
+ {
+ // make a block table up
+ static struct flash_block_table_entry flash_fixed_block_table[2];
+ if (flash_fixed_block_table[0].size == 0) {
+ flash_fixed_block_table[0].offset_addr = NULL;
+ flash_fixed_block_table[0].size = flash_info.block_size * flash_info.blocks;
+ flash_fixed_block_table[0].block_size = flash_info.block_size;
+ }
+ *table = flash_fixed_block_table;
+ }
+#endif
+ return FLASH_ERR_OK;
+} // flash_get_block_table()
+
+
+int
flash_get_block_info(int *block_size, int *blocks)
{
if (!flash_info.init) {
return FLASH_ERR_NOT_INIT;
}
+ diag_printf("Warning, flash_get_block_info() is deprecated.\n");
+#ifdef CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE
+ // may as well pick something
+ *block_size = flash_block_size( flash_info.start );
+ if (*block_size < 0)
+ return -FLASH_ERR_INVALID;
+ *blocks = -1; // it's just tough. This makes no sense for variable
+ // block sizes.
+#else
*block_size = flash_info.block_size;
*blocks = flash_info.blocks;
+#endif
return FLASH_ERR_OK;
}
int
flash_erase(void *addr, int len, void **err_addr)
@@ -173,10 +234,12 @@ flash_erase(void *addr, int len, void **
unsigned short *block, *end_addr;
int stat = 0;
typedef int code_fun(unsigned short *, unsigned int);
code_fun *_flash_erase_block;
int d_cache, i_cache;
+ int block_size;
+ unsigned long block_mask;
if (!flash_info.init) {
return FLASH_ERR_NOT_INIT;
}
@@ -200,11 +263,21 @@ flash_erase(void *addr, int len, void **
externC code_fun flash_erase_block;
_flash_erase_block = (code_fun*) __anonymizer(&flash_erase_block);
}
#endif
- block = (unsigned short *)((CYG_ADDRESS)addr & flash_info.block_mask);
+#ifdef CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE
+ block_size = flash_block_size( addr );
+ if ( block_size < 0 ) {
+ *err_addr = addr;
+ return -block_size; // error code is -ve value
+ }
+ block_mask = ~(block_size-1);
+#else
+ block_mask = flash_info.block_mask;
+#endif
+ block = (unsigned short *)((CYG_ADDRESS)addr & block_mask);
end_addr = (unsigned short *)((CYG_ADDRESS)addr+len);
/* Check to see if end_addr overflowed */
if( (end_addr < block) && (len > 0) ){
end_addr = (unsigned short *) ((CYG_ADDRESS) flash_info.end - 1);
@@ -220,27 +293,35 @@ flash_erase(void *addr, int len, void **
unsigned char *dp;
bool erased = true;
unsigned short *tmp_block;
dp = (unsigned char *)block;
- for (i = 0; i < flash_info.block_size; i++) {
+#ifdef CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE
+ block_size = flash_block_size( block );
+ if ( block_size < 0 ) {
+ err_addr = (void *)block;
+ stat = -block_size; // error code is -ve value
+ break;
+ }
+#endif
+ for (i = 0; i < block_size; 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, block_size);
stat = flash_hwr_map_error(stat);
}
if (stat) {
*err_addr = (void *)block;
break;
}
// Check to see if block will overflow
- tmp_block = block + flash_info.block_size / sizeof(*block);
+ tmp_block = block + block_size / sizeof(*block);
if(tmp_block < block){
// If block address overflows, set block value to end on this loop
block = end_addr;
}
else{
@@ -263,10 +344,12 @@ flash_program(void *_addr, void *_data,
code_fun *_flash_program_buf;
unsigned char *addr = (unsigned char *)_addr;
unsigned char *data = (unsigned char *)_data;
CYG_ADDRESS tmp;
int d_cache, i_cache;
+ int block_size;
+ unsigned long block_mask;
if (!flash_info.init) {
return FLASH_ERR_NOT_INIT;
}
@@ -292,25 +375,38 @@ flash_program(void *_addr, void *_data,
#endif
(*flash_info.pf)("... Program from %p-%p at %p: ", (void*)data,
(void*)(((CYG_ADDRESS)data)+len), (void*)addr);
+#ifndef CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE
+ block_size = flash_info.block_size;
+ block_mask = flash_info.block_mask;
+#endif
HAL_FLASH_CACHES_OFF(d_cache, i_cache);
FLASH_Enable((unsigned short*)addr, (unsigned short *)(addr+len));
while (len > 0) {
+#ifdef CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE
+ block_size = flash_block_size( addr );
+ if (block_size < 0) {
+ stat = -block_size; // error code is -ve value
+ *err_addr = (void *)addr;
+ break;
+ }
+ block_mask = ~(block_size-1);
+#endif
size = len;
- if (size > flash_info.block_size) size = flash_info.block_size;
+ if (size > block_size) size = block_size;
- tmp = (CYG_ADDRESS)addr & ~flash_info.block_mask;
+ tmp = (CYG_ADDRESS)addr & block_mask;
if (tmp) {
- tmp = flash_info.block_size - tmp;
+ tmp = block_size - tmp;
if (size>tmp) size = tmp;
}
stat = (*_flash_program_buf)(addr, data, size,
- flash_info.block_mask, flash_info.buffer_size);
+ block_mask, flash_info.buffer_size);
stat = flash_hwr_map_error(stat);
#ifdef CYGSEM_IO_FLASH_VERIFY_PROGRAM
if (0 == stat) // Claims to be OK
if (memcmp(addr, data, size) != 0) {
stat = 0x0BAD;
@@ -340,10 +436,12 @@ flash_lock(void *addr, int len, void **e
unsigned short *block, *end_addr;
int stat = 0;
typedef int code_fun(unsigned short *);
code_fun *_flash_lock_block;
int d_cache, i_cache;
+ int block_size;
+ unsigned long block_mask;
if (!flash_info.init) {
return FLASH_ERR_NOT_INIT;
}
@@ -366,11 +464,21 @@ flash_lock(void *addr, int len, void **e
externC code_fun flash_lock_block;
_flash_lock_block = (code_fun*) __anonymizer(&flash_lock_block);
}
#endif
- block = (unsigned short *)((CYG_ADDRESS)addr & flash_info.block_mask);
+#ifdef CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE
+ block_size = flash_block_size( addr );
+ if ( block_size < 0 ) {
+ *err_addr = addr;
+ return -block_size; // error code is -ve value
+ }
+ block_mask = ~(block_size-1);
+#else
+ block_mask = flash_info.block_mask;
+#endif
+ block = (unsigned short *)((CYG_ADDRESS)addr & block_mask);
end_addr = (unsigned short *)((CYG_ADDRESS)addr+len);
/* Check to see if end_addr overflowed */
if( (end_addr < block) && (len > 0) ){
end_addr = (unsigned short *) ((CYG_ADDRESS) flash_info.end - 1);
@@ -387,12 +495,20 @@ flash_lock(void *addr, int len, void **e
if (stat) {
*err_addr = (void *)block;
break;
}
+#ifdef CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE
+ block_size = flash_block_size( block );
+ if (block_size < 0) {
+ stat = -block_size; // error code is -ve value
+ *err_addr = (void *)block;
+ break;
+ }
+#endif
// Check to see if block will overflow
- tmp_block = block + flash_info.block_size / sizeof(*block);
+ tmp_block = block + block_size / sizeof(*block);
if(tmp_block < block){
// If block address overflows, set block value to end on this loop
block = end_addr;
}
else{
@@ -412,10 +528,12 @@ flash_unlock(void *addr, int len, void *
unsigned short *block, *end_addr;
int stat = 0;
typedef int code_fun(unsigned short *, int, int);
code_fun *_flash_unlock_block;
int d_cache, i_cache;
+ int block_size;
+ unsigned long block_mask;
if (!flash_info.init) {
return FLASH_ERR_NOT_INIT;
}
@@ -438,11 +556,21 @@ flash_unlock(void *addr, int len, void *
externC code_fun flash_unlock_block;
_flash_unlock_block = (code_fun*) __anonymizer(&flash_unlock_block);
}
#endif
- block = (unsigned short *)((CYG_ADDRESS)addr & flash_info.block_mask);
+#ifdef CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE
+ block_size = flash_block_size( addr );
+ if ( block_size < 0 ) {
+ *err_addr = addr;
+ return -block_size; // error code is -ve value
+ }
+ block_mask = ~(block_size-1);
+#else
+ block_mask = flash_info.block_mask;
+#endif
+ block = (unsigned short *)((CYG_ADDRESS)addr & block_mask);
end_addr = (unsigned short *)((CYG_ADDRESS)addr+len);
/* Check to see if end_addr overflowed */
if( (end_addr < block) && (len > 0) ){
end_addr = (unsigned short *) ((CYG_ADDRESS) flash_info.end - 1);
@@ -452,18 +580,32 @@ flash_unlock(void *addr, int len, void *
HAL_FLASH_CACHES_OFF(d_cache, i_cache);
FLASH_Enable(block, end_addr);
while (block < end_addr) {
unsigned short *tmp_block;
- stat = (*_flash_unlock_block)(block, flash_info.block_size, flash_info.blocks);
+
+#ifdef CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE
+ block_size = flash_block_size( block );
+ if (block_size < 0) {
+ stat = -block_size; // error code is -ve value
+ *err_addr = (void *)block;
+ break;
+ }
+ // flash device drivers should know their own size, but we can't change
+ // the interface to existing drivers easily. We have to wait for some
+ // big flash driver overhaul to have an excuse to fix this.
+ stat = (*_flash_unlock_block)(block, block_size, 0);
+#else
+ stat = (*_flash_unlock_block)(block, block_size, flash_info.blocks);
+#endif
stat = flash_hwr_map_error(stat);
if (stat) {
*err_addr = (void *)block;
break;
}
- tmp_block = block + flash_info.block_size / sizeof(*block);
+ tmp_block = block + block_size / sizeof(*block);
if(tmp_block < block){
// If block address overflows, set block value to end on this loop
block = end_addr;
}
else{
Index: src/flashiodev.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/flash/current/src/flashiodev.c,v
retrieving revision 1.2
diff -u -5 -p -r1.2 flashiodev.c
--- src/flashiodev.c 23 May 2002 23:06:16 -0000 1.2
+++ src/flashiodev.c 14 Feb 2003 01:17:11 -0000
@@ -195,13 +195,29 @@ flashiodev_get_config( cyg_io_handle_t h
if ( startpos > flashend )
return -EINVAL;
#endif
if ( *len != sizeof( cyg_io_flash_getconfig_blocksize_t ) )
return -EINVAL;
-
- // offset unused for now
+
+#ifdef CYGINT_IO_FLASH_VARIABLE_BLOCK_SIZE
+ {
+ struct flash_block_table_entry *t = flash_info.block_table;
+ CYG_ADDRESS realoffset = CYGNUM_IO_FLASH_BLOCK_OFFSET_1 + b->offset;
+
+ // we've already checked above whether it's in flash at all.
+
+ while (t->offset_addr < realoffset)
+ {
+ if (t->size == 0) // reached end of table. Hmm. This shouldn't
+ // happen though.
+ return -EINVAL;
+ }
+ b->block_size = t->block_size;
+ }
+#else
b->block_size = flash_info.block_size;
+#endif
return ENOERR;
}
default:
return -EINVAL;
--
Before posting, please read the FAQ: http://sources.redhat.com/fom/ecos
and search the list archive: http://sources.redhat.com/ml/ecos-discuss