X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fat91samd.c;h=ee9e9cbb9edcff95b9a95bb24220eea85efc9a46;hp=5af61ab4ddcc337e5a64a1ac37bf340b2884aaab;hb=c92a605e2622e5598c737a699d3164b9934bbd8c;hpb=565f8481c7b71614a05d79ab79af8610d2535a81 diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index 5af61ab4dd..ee9e9cbb9e 100644 --- a/src/flash/nor/at91samd.c +++ b/src/flash/nor/at91samd.c @@ -352,13 +352,6 @@ static int samd_erase(struct flash_bank *bank, int first, int last) return ERROR_FLASH_BANK_NOT_PROBED; } - /* Make sure the sectors make sense. */ - if (first >= bank->num_sectors || last >= bank->num_sectors) { - LOG_ERROR("Erase range %d - %d not valid (%d sectors total)", - first, last, bank->num_sectors); - return ERROR_FAIL; - } - /* The SAMD NVM has row erase granularity. There are four pages in a row * and the number of rows in a sector depends on the sector size, which in * turn depends on the Flash capacity as there is a fixed number of @@ -367,21 +360,40 @@ static int samd_erase(struct flash_bank *bank, int first, int last) /* For each sector to be erased */ for (int s = first; s <= last; s++) { - /* For each row in that sector */ - for (int r = s * rows_in_sector; r < (s + 1) * rows_in_sector; r++) { - res = samd_erase_row(bank, r * chip->page_size * 4); - if (res != ERROR_OK) { - LOG_ERROR("SAMD: failed to erase sector %d", s); - return res; - } + if (bank->sectors[s].is_protected) { + LOG_ERROR("SAMD: failed to erase sector %d. That sector is write-protected", s); + return ERROR_FLASH_OPERATION_FAILED; } - bank->sectors[s].is_erased = 1; + if (!bank->sectors[s].is_erased) { + /* For each row in that sector */ + for (int r = s * rows_in_sector; r < (s + 1) * rows_in_sector; r++) { + res = samd_erase_row(bank, r * chip->page_size * 4); + if (res != ERROR_OK) { + LOG_ERROR("SAMD: failed to erase sector %d", s); + return res; + } + } + + bank->sectors[s].is_erased = 1; + } } return ERROR_OK; } +static struct flash_sector *samd_find_sector_by_address(struct flash_bank *bank, uint32_t address) +{ + struct samd_info *chip = (struct samd_info *)bank->driver_priv; + + for (int i = 0; i < bank->num_sectors; i++) { + if (bank->sectors[i].offset <= address && + address < bank->sectors[i].offset + chip->sector_size) + return &bank->sectors[i]; + } + return NULL; +} + /* Write an entire row (four pages) from host buffer 'buf' to row-aligned * 'address' in the Flash. */ static int samd_write_row(struct flash_bank *bank, uint32_t address, @@ -390,6 +402,18 @@ static int samd_write_row(struct flash_bank *bank, uint32_t address, int res; struct samd_info *chip = (struct samd_info *)bank->driver_priv; + struct flash_sector *sector = samd_find_sector_by_address(bank, address); + + if (!sector) { + LOG_ERROR("Can't find sector corresponding to address 0x%08" PRIx32, address); + return ERROR_FLASH_OPERATION_FAILED; + } + + if (sector->is_protected) { + LOG_ERROR("Trying to write to a protected sector at 0x%08" PRIx32, address); + return ERROR_FLASH_OPERATION_FAILED; + } + /* Erase the row that we'll be writing to */ res = samd_erase_row(bank, address); if (res != ERROR_OK) @@ -418,6 +442,8 @@ static int samd_write_row(struct flash_bank *bank, uint32_t address, buf += chip->page_size; } + sector->is_erased = 0; + return res; }