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] |
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) ®desc + ); + + // 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) ®desc + ); + + *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] |