X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fat91sam4l.c;h=f8c6f6490644c384cc2375ff9427116a952230d3;hb=4f371e8eed5c4e479d326cf09f7827884c23b947;hp=a5eb67271494c57c08047206689b44e36e3e2c50;hpb=b1a1a48b30243d3582a8443f4baf3dd500683eda;p=openocd.git diff --git a/src/flash/nor/at91sam4l.c b/src/flash/nor/at91sam4l.c index a5eb672714..f8c6f64906 100644 --- a/src/flash/nor/at91sam4l.c +++ b/src/flash/nor/at91sam4l.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -24,13 +22,15 @@ #include "imp.h" +#include + /* At this time, the SAM4L Flash is available in these capacities: * ATSAM4Lx4xx: 256KB (512 pages) * ATSAM4Lx2xx: 128KB (256 pages) * ATSAM4Lx8xx: 512KB (1024 pages) */ -/* There are 16 lockable regions regardless of overall capacity. The number +/* There are 16 lockable regions regardless of overall capacity. The number * of pages per sector is therefore dependant on capacity. */ #define SAM4L_NUM_SECTORS 16 @@ -75,6 +75,14 @@ #define SAM4L_FMCD_CMDKEY 0xA5UL /* 'key' to issue commands, see 14.10.2 */ + +/* SMAP registers and bits */ +#define SMAP_BASE 0x400A3000 + +#define SMAP_SCR (SMAP_BASE + 8) +#define SMAP_SCR_HCR (1 << 1) + + struct sam4l_chip_info { uint32_t id; uint32_t exid; @@ -117,14 +125,12 @@ struct sam4l_info { uint32_t page_size; int num_pages; int sector_size; - int pages_per_sector; + unsigned int pages_per_sector; bool probed; struct target *target; - struct sam4l_info *next; }; -static struct sam4l_info *sam4l_chips; static int sam4l_flash_wait_until_ready(struct target *target) { @@ -196,37 +202,26 @@ static int sam4l_flash_command(struct target *target, uint8_t cmd, int page) FLASH_BANK_COMMAND_HANDLER(sam4l_flash_bank_command) { - struct sam4l_info *chip = sam4l_chips; - - while (chip) { - if (chip->target == bank->target) - break; - chip = chip->next; - } - - if (!chip) { - /* Create a new chip */ - chip = calloc(1, sizeof(*chip)); - if (!chip) - return ERROR_FAIL; - - chip->target = bank->target; - chip->probed = false; - - bank->driver_priv = chip; - - /* Insert it into the chips list (at head) */ - chip->next = sam4l_chips; - sam4l_chips = chip; - } - if (bank->base != SAM4L_FLASH) { - LOG_ERROR("Address 0x%08" PRIx32 " invalid bank address (try 0x%08" PRIx32 + LOG_ERROR("Address " TARGET_ADDR_FMT + " invalid bank address (try 0x%08" PRIx32 "[at91sam4l series] )", bank->base, SAM4L_FLASH); return ERROR_FAIL; } + struct sam4l_info *chip; + chip = calloc(1, sizeof(*chip)); + if (!chip) { + LOG_ERROR("No memory for flash bank chip info"); + return ERROR_FAIL; + } + + chip->target = bank->target; + chip->probed = false; + + bank->driver_priv = chip; + return ERROR_OK; } @@ -340,7 +335,7 @@ static int sam4l_probe(struct flash_bank *bank) /* Fill out the sector information: all SAM4L sectors are the same size and * there is always a fixed number of them. */ - for (int i = 0; i < bank->num_sectors; i++) { + for (unsigned int i = 0; i < bank->num_sectors; i++) { bank->sectors[i].size = chip->sector_size; bank->sectors[i].offset = i * chip->sector_size; /* mark as unknown */ @@ -351,7 +346,7 @@ static int sam4l_probe(struct flash_bank *bank) /* Done */ chip->probed = true; - LOG_INFO("SAM4L MCU: %s (Rev %c) (%" PRIu32 "KB Flash with %d %" PRId32 "B pages, %" PRIu32 "KB RAM)", + LOG_INFO("SAM4L MCU: %s (Rev %c) (%" PRIu32 "KB Flash with %d %" PRIu32 "B pages, %" PRIu32 "KB RAM)", chip->details ? chip->details->name : "unknown", (char)('A' + (id & 0xF)), chip->flash_kb, chip->num_pages, chip->page_size, chip->ram_kb); @@ -380,15 +375,16 @@ static int sam4l_protect_check(struct flash_bank *bank) return res; st >>= 16; /* There are 16 lock region bits in the upper half word */ - for (int i = 0; i < bank->num_sectors; i++) - bank->sectors[i].is_protected = !!(st & (1<num_sectors; i++) + bank->sectors[i].is_protected = !!(st & (1<driver_priv; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); @@ -403,7 +399,7 @@ static int sam4l_protect(struct flash_bank *bank, int set, int first, int last) /* Make sure the pages make sense. */ if (first >= bank->num_sectors || last >= bank->num_sectors) { - LOG_ERROR("Protect range %d - %d not valid (%d sectors total)", first, last, + LOG_ERROR("Protect range %u - %u not valid (%u sectors total)", first, last, bank->num_sectors); return ERROR_FAIL; } @@ -411,7 +407,7 @@ static int sam4l_protect(struct flash_bank *bank, int set, int first, int last) /* Try to lock or unlock each sector in the range. This is done by locking * a region containing one page in that sector, we arbitrarily choose the 0th * page in the sector. */ - for (int i = first; i <= last; i++) { + for (unsigned int i = first; i <= last; i++) { int res; res = sam4l_flash_command(bank->target, @@ -425,7 +421,8 @@ static int sam4l_protect(struct flash_bank *bank, int set, int first, int last) return ERROR_OK; } -static int sam4l_erase(struct flash_bank *bank, int first, int last) +static int sam4l_erase(struct flash_bank *bank, unsigned int first, + unsigned int last) { int ret; struct sam4l_info *chip = (struct sam4l_info *)bank->driver_priv; @@ -443,7 +440,7 @@ static int sam4l_erase(struct flash_bank *bank, int first, int last) /* Make sure the pages make sense. */ if (first >= bank->num_sectors || last >= bank->num_sectors) { - LOG_ERROR("Erase range %d - %d not valid (%d sectors total)", first, last, + LOG_ERROR("Erase range %u - %u not valid (%u sectors total)", first, last, bank->num_sectors); return ERROR_FAIL; } @@ -458,19 +455,19 @@ static int sam4l_erase(struct flash_bank *bank, int first, int last) return ret; } } else { - LOG_DEBUG("Erasing sectors %d through %d...\n", first, last); + LOG_DEBUG("Erasing sectors %u through %u...\n", first, last); /* For each sector... */ - for (int i = first; i <= last; i++) { + for (unsigned int i = first; i <= last; i++) { /* For each page in that sector... */ - for (int j = 0; j < chip->pages_per_sector; j++) { - int pn = i * chip->pages_per_sector + j; + for (unsigned int j = 0; j < chip->pages_per_sector; j++) { + unsigned int pn = i * chip->pages_per_sector + j; bool is_erased = false; /* Issue the page erase */ ret = sam4l_flash_command(bank->target, SAM4L_FCMD_EP, pn); if (ret != ERROR_OK) { - LOG_ERROR("Erasing page %d failed", pn); + LOG_ERROR("Erasing page %u failed", pn); return ret; } @@ -479,13 +476,10 @@ static int sam4l_erase(struct flash_bank *bank, int first, int last) return ret; if (!is_erased) { - LOG_DEBUG("Page %d was not erased.", pn); + LOG_DEBUG("Page %u was not erased.", pn); return ERROR_FAIL; } } - - /* This sector is definitely erased. */ - bank->sectors[i].is_erased = 1; } } @@ -606,6 +600,7 @@ static int sam4l_write(struct flash_bank *bank, const uint8_t *buffer, /* There's at least one aligned page to write out. */ if (count >= chip->page_size) { + assert(chip->page_size > 0); int np = count / chip->page_size + ((count % chip->page_size) ? 1 : 0); for (int i = 0; i < np; i++) { @@ -633,21 +628,52 @@ static int sam4l_write(struct flash_bank *bank, const uint8_t *buffer, return ERROR_OK; } -COMMAND_HANDLER(sam4l_handle_info_command) + +COMMAND_HANDLER(sam4l_handle_reset_deassert) { - return ERROR_OK; + struct target *target = get_current_target(CMD_CTX); + int retval = ERROR_OK; + enum reset_types jtag_reset_config = jtag_get_reset_config(); + + /* If the target has been unresponsive before, try to re-establish + * communication now - CPU is held in reset by DSU, DAP is working */ + if (!target_was_examined(target)) + target_examine_one(target); + target_poll(target); + + /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset() + * so we just release reset held by SMAP + * + * n_RESET (srst) clears the DP, so reenable debug and set vector catch here + * + * After vectreset SMAP release is not needed however makes no harm + */ + if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) { + retval = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); + if (retval == ERROR_OK) + retval = target_write_u32(target, DCB_DEMCR, + TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); + /* do not return on error here, releasing SMAP reset is more important */ + } + + int retval2 = target_write_u32(target, SMAP_SCR, SMAP_SCR_HCR); + if (retval2 != ERROR_OK) + return retval2; + + return retval; } static const struct command_registration at91sam4l_exec_command_handlers[] = { { - .name = "info", - .handler = sam4l_handle_info_command, + .name = "smap_reset_deassert", + .handler = sam4l_handle_reset_deassert, .mode = COMMAND_EXEC, - .help = "Print information about the current at91sam4l chip" - "and its flash configuration.", + .help = "deassert internal reset held by SMAP", + .usage = "", }, COMMAND_REGISTRATION_DONE }; + static const struct command_registration at91sam4l_command_handlers[] = { { .name = "at91sam4l", @@ -659,7 +685,7 @@ static const struct command_registration at91sam4l_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver at91sam4l_flash = { +const struct flash_driver at91sam4l_flash = { .name = "at91sam4l", .commands = at91sam4l_command_handlers, .flash_bank_command = sam4l_flash_bank_command, @@ -671,4 +697,5 @@ struct flash_driver at91sam4l_flash = { .auto_probe = sam4l_probe, .erase_check = default_flash_blank_check, .protect_check = sam4l_protect_check, + .free_driver_priv = default_flash_free_driver_priv, };