X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fcore.c;h=1bd09b444d9c392d08f6f097937039c9660e8d43;hb=ee4106ee995a1fc81778f4ebd496d6782e592b63;hp=e6c0eeb2ea2eaf8260668529c3325f4cd69eac7d;hpb=7e33f87b3d25331f3ac366c88e0b0ebb196422ec;p=openocd.git diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index e6c0eeb2ea..1bd09b444d 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -3,6 +3,7 @@ * Copyright (C) 2007-2010 Øyvind Harboe * * Copyright (C) 2008 by Spencer Oliver * * Copyright (C) 2009 Zachary T Welch * + * Copyright (C) 2010 by Antonio Borneo * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -54,74 +55,27 @@ int flash_driver_erase(struct flash_bank *bank, int first, int last) int flash_driver_protect(struct flash_bank *bank, int set, int first, int last) { int retval; - bool updated = false; - - /* NOTE: "first == last" means (un?)protect just that sector. - code including Lower level ddrivers may rely on this "first <= last" - * invariant. - */ /* callers may not supply illegal parameters ... */ if (first < 0 || first > last || last >= bank->num_sectors) + { + LOG_ERROR("illegal sector range"); return ERROR_FAIL; + } /* force "set" to 0/1 */ set = !!set; - /* - * Filter out what trivial nonsense we can, so drivers don't have to. + /* DANGER! * - * Don't tell drivers to change to the current state... it's needless, - * and reducing the amount of work to be done (potentially to nothing) - * speeds at least some things up. - */ -scan: - for (int i = first; i <= last; i++) { - struct flash_sector *sector = bank->sectors + i; - - /* Only filter requests to protect the already-protected, or - * to unprotect the already-unprotected. Changing from the - * unknown state (-1) to a known one is unwise but allowed; - * protection status is best checked first. - */ - if (sector->is_protected != set) - continue; - - /* Shrink this range of sectors from the start; don't overrun - * the end. Also shrink from the end; don't overun the start. - * - * REVISIT we could handle discontiguous regions by issuing - * more than one driver request. How much would that matter? - */ - if (i == first && i != last) { - updated = true; - first++; - } else if (i == last && i != first) { - updated = true; - last--; - } - } - - /* updating the range affects the tests in the scan loop above; so - * re-scan, to make sure we didn't miss anything. - */ - if (updated) { - updated = false; - goto scan; - } - - /* Single sector, already protected? Nothing to do! - * We may have trimmed our parameters into this degenerate case. + * We must not use any cached information about protection state!!!! * - * FIXME repeating the "is_protected==set" test is a giveaway that - * this fast-exit belongs earlier, in the trim-it-down loop; mve. - * */ - if (first == last && bank->sectors[first].is_protected == set) - return ERROR_OK; - - - /* Note that we don't pass illegal parameters to drivers; any - * trimming just turns one valid range into another one. + * There are a million things that could change the protect state: + * + * the target could have reset, power cycled, been hot plugged, + * the application could have run, etc. + * + * Drivers only receive valid sector range. */ retval = bank->driver->protect(bank, set, first, last); if (retval != ERROR_OK) @@ -147,6 +101,29 @@ int flash_driver_write(struct flash_bank *bank, return retval; } +int flash_driver_read(struct flash_bank *bank, + uint8_t *buffer, uint32_t offset, uint32_t count) +{ + int retval; + + LOG_DEBUG("call flash_driver_read()"); + + retval = bank->driver->read(bank, buffer, offset, count); + if (retval != ERROR_OK) + { + LOG_ERROR("error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32 " (%d)", + bank->base, offset, retval); + } + + return retval; +} + +int default_flash_read(struct flash_bank *bank, + uint8_t *buffer, uint32_t offset, uint32_t count) +{ + return target_read_buffer(bank->target, offset + bank->base, count, buffer); +} + void flash_bank_add(struct flash_bank *bank) { /* put flash bank in linked list */ @@ -201,7 +178,7 @@ int flash_get_bank_count(void) return i; } -struct flash_bank *get_flash_bank_by_name(const char *name) +struct flash_bank *get_flash_bank_by_name_noprobe(const char *name) { unsigned requested = get_flash_name_index(name); unsigned found = 0; @@ -220,22 +197,45 @@ struct flash_bank *get_flash_bank_by_name(const char *name) return NULL; } -struct flash_bank *get_flash_bank_by_num(int num) +struct flash_bank *get_flash_bank_by_name(const char *name) +{ + struct flash_bank *bank; + int retval; + + bank = get_flash_bank_by_name_noprobe(name); + if (bank != NULL) + { + retval = bank->driver->auto_probe(bank); + + if (retval != ERROR_OK) + { + LOG_ERROR("auto_probe failed %d\n", retval); + return NULL; + } + } + + return bank; +} + +int get_flash_bank_by_num(int num, struct flash_bank **bank) { struct flash_bank *p = get_flash_bank_by_num_noprobe(num); int retval; if (p == NULL) - return NULL; + { + return ERROR_FAIL; + } retval = p->driver->auto_probe(p); if (retval != ERROR_OK) { LOG_ERROR("auto_probe failed %d\n", retval); - return NULL; + return retval; } - return p; + *bank = p; + return ERROR_OK; } /* lookup flash bank by address */ @@ -499,7 +499,7 @@ static int flash_driver_unprotect(struct flash_bank *bank, int first, int last) return flash_driver_protect(bank, 0, first, last); } -static int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length) +int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length) { /* By default, pad to sector boundaries ... the real issue here * is that our (only) caller *permanently* removes protection, @@ -680,7 +680,7 @@ int flash_write_unlock(struct target *target, struct image *image, intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections; int t_section_num = diff / sizeof(struct imageection); - LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, section_offset = %d, buffer_size = %d, size_read = %d", + LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, section_offset = %d, buffer_size = %d, size_read = %d", (int)section, (int)t_section_num, (int)section_offset, (int)buffer_size, (int)size_read); if ((retval = image_read_section(image, t_section_num, section_offset, @@ -751,34 +751,3 @@ int flash_write(struct target *target, struct image *image, { return flash_write_unlock(target, image, written, erase, false); } - -/** - * Invalidates cached flash state which a target can change as it runs. - * - * @param target The target being resumed - * - * OpenOCD caches some flash state for brief periods. For example, a sector - * that is protected must be unprotected before OpenOCD tries to write it, - * Also, a sector that's not erased must be erased before it's written. - * - * As a rule, OpenOCD and target firmware can both modify the flash, so when - * a target starts running, OpenOCD needs to invalidate its cached state. - */ -void nor_resume(struct target *target) -{ - struct flash_bank *bank; - - for (bank = flash_banks; bank; bank = bank->next) { - int i; - - if (bank->target != target) - continue; - - for (i = 0; i < bank->num_sectors; i++) { - struct flash_sector *sector = bank->sectors + i; - - sector->is_erased = -1; - sector->is_protected = -1; - } - } -}