This is an automated email from Gerrit. Rick Foos ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/3230
-- gerrit commit 0b79a8f84692cac93e2c8c5cc189e7b24c5e7006 Author: Rick Foos <[email protected]> Date: Mon Feb 8 15:19:30 2016 -0600 Add support for Ambiq Micro EVK. Change-Id: Iae92d869369c6827244f0071f9cb522d8d91fed8 Signed-off-by: Rick Foos <[email protected]> diff --git a/contrib/99-openocd.rules b/contrib/99-openocd.rules index 344b933..bc9aae7 100644 --- a/contrib/99-openocd.rules +++ b/contrib/99-openocd.rules @@ -119,6 +119,10 @@ ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="664", GROUP="plugdev" # TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="664", GROUP="plugdev" +# Ambiq Micro EVK's. +SUBSYSTEMS=="usb", ACTION=="add", ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="6010", MODE="664", GROUP="plugdev", RUN+="/sbin/modprobe ftdi_sio" RUN+="/bin/sh -c 'echo 2aec 6010 > /sys/bus/usb-serial/drivers/ftdi_sio/new_id'" +SUBSYSTEMS=="usb", ACTION=="add", ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="6011", MODE="664", GROUP="plugdev", RUN+="/sbin/modprobe ftdi_sio" RUN+="/bin/sh -c 'echo 2aec 6011 > /sys/bus/usb-serial/drivers/ftdi_sio/new_id'" + # Marvell Sheevaplug ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="664", GROUP="plugdev" diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index 834e4d4..8a8122f 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -10,6 +10,7 @@ libocdflashnor_la_SOURCES = \ NOR_DRIVERS = \ aduc702x.c \ aducm360.c \ + ambiqmicro.c \ at91sam4.c \ at91sam4l.c \ at91samd.c \ diff --git a/src/flash/nor/ambiqmicro.c b/src/flash/nor/ambiqmicro.c new file mode 100644 index 0000000..37ab29b --- /dev/null +++ b/src/flash/nor/ambiqmicro.c @@ -0,0 +1,1018 @@ +/****************************************************************************** + * + * @file ambiqmicro.c + * + * @brief Ambiq Micro flash driver. + * + *****************************************************************************/ + +/****************************************************************************** + * Copyright (c) 2015, David Racine <dracine at ambiqmicro.com> + * + * Copyright (c) 2016, Rick Foos <rfoos at solengtech.com> + * + * Copyright (c) 2016, Ambiq Micro, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "jtag/interface.h" +#include "imp.h" +#include "target/algorithm.h" +#include "target/armv7m.h" +#include "target/cortex_m.h" + +/* + * Address and Key defines + */ +#define PROGRAM_KEY (0x12344321) +#define OTP_PROGRAM_KEY (0x87655678) + +#define FLASH_PROGRAM_MAIN_FROM_SRAM 0x0800005d +#define FLASH_PROGRAM_OTP_FROM_SRAM 0x08000061 +#define FLASH_ERASE_LIST_MAIN_PAGES_FROM_SRAM 0x08000065 +#define FLASH_MASS_ERASE_MAIN_PAGES_FROM_SRAM 0x08000069 + + +/**************************************************************************** + * + * MCUCTRL device structure + * + *****************************************************************************/ +typedef struct { + /* + * Device part number. (BCD format) + */ + uint32_t ui32ChipPN; + + /* + * Flash Size. + */ + uint32_t ui32FlashSize; + + /* + * SRAM Size. + */ + uint32_t ui32SRAMSize; +} +am_hal_mcuctrl_device_t; + +const uint32_t apollo_flash_size[] = { + 1 << 15, + 1 << 16, + 1 << 17, + 1 << 18, + 1 << 19, + 1 << 20, + 1 << 21 +}; + +const uint32_t apollo_sram_size[] = { + 1 << 15, + 1 << 16, + 1 << 17, + 1 << 18, + 1 << 19, + 1 << 20, + 1 << 21 +}; + +struct ambiqmicro_flash_bank { + /* chip id register */ + + uint32_t probed; + + const char *target_name; + uint8_t target_class; + + uint32_t sramsiz; + uint32_t flshsiz; + + /* flash geometry */ + uint32_t num_pages; + uint32_t pagesize; + uint32_t pages_in_lockregion; + + /* nv memory bits */ + uint16_t num_lockbits; + + /* main clock status */ + uint32_t rcc; + uint32_t rcc2; + uint8_t mck_valid; + uint8_t xtal_mask; + uint32_t iosc_freq; + uint32_t mck_freq; + const char *iosc_desc; + const char *mck_desc; +}; + +static struct { + uint8_t class; + uint8_t partno; + const char *partname; +} ambiqmicroParts[] = { + {0xFF, 0x00, "Unknown Part"}, + {0x01, 0x00, "Apollo"}, + {0xFF, 0x00, "Unknown Part"} +}; + +static char *ambiqmicroClassname[1] = { + "Apollo" +}; + +uint32_t source[256]; +uint32_t result[256]; +uint32_t *presult; + +uint32_t *pSrc = source; +volatile uint32_t *pDst = (volatile uint32_t *) 0; + +/* + * Return Code. + */ +int rc; + +/*************************************************************************** +* openocd command interface * +***************************************************************************/ + +/* flash_bank ambiqmicro <base> <size> 0 0 <target#> + */ +FLASH_BANK_COMMAND_HANDLER(ambiqmicro_flash_bank_command) +{ + struct ambiqmicro_flash_bank *ambiqmicro_info; + + if (CMD_ARGC < 6) + return ERROR_COMMAND_SYNTAX_ERROR; + + ambiqmicro_info = calloc(sizeof(struct ambiqmicro_flash_bank), 1); + + bank->driver_priv = ambiqmicro_info; + + ambiqmicro_info->target_name = "Unknown target"; + + /* part wasn't probed yet */ + ambiqmicro_info->probed = 0; + + return ERROR_OK; +} + +static int get_ambiqmicro_info(struct flash_bank *bank, char *buf, int buf_size) +{ + struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv; + + if (ambiqmicro_info->probed == 0) { + LOG_ERROR("Target not probed"); + return ERROR_FLASH_BANK_NOT_PROBED; + } + + snprintf(buf, + buf_size, + "\nAmbiq Micro information: Chip is " + "class %i (%s) %s\n", + ambiqmicro_info->target_class, + ambiqmicroClassname[ambiqmicro_info->target_class], + ambiqmicro_info->target_name); + + return ERROR_OK; +} + +/*************************************************************************** +* chip identification and status * +***************************************************************************/ + +/* Fill in driver info structure */ +static int ambiqmicro_read_part_info(struct flash_bank *bank) +{ + struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv; + struct target *target = bank->target; + uint32_t ui32PartNum = 0; + + /* + * Read Part Number. + */ + target_read_u32(target, 0x40020000, &ui32PartNum); + LOG_DEBUG("Part number: %d", ui32PartNum); + + /* + * Determine device class. + */ + ambiqmicro_info->target_class = (ui32PartNum & 0xFF000000) >> 24; + + switch (ambiqmicro_info->target_class) { + case 1: /* 1 - Apollo */ + case 5: /* 5 - Apollo Secure */ + bank->base = bank->bank_number * 0x40000; + ambiqmicro_info->pagesize = 2048; + ambiqmicro_info->flshsiz = + apollo_flash_size[(ui32PartNum & 0x00F00000) >> 20]; + ambiqmicro_info->sramsiz = + apollo_sram_size[(ui32PartNum & 0x000F0000) >> 16]; + ambiqmicro_info->num_pages = ambiqmicro_info->flshsiz / + ambiqmicro_info->pagesize; + if (ambiqmicro_info->num_pages > 128) { + ambiqmicro_info->num_pages = 128; + ambiqmicro_info->flshsiz = 1024 * 256; + } + break; + + default: + LOG_INFO("Unknown Class. Using Apollo-64 as default."); + + bank->base = bank->bank_number * 0x40000; + ambiqmicro_info->pagesize = 2048; + ambiqmicro_info->flshsiz = apollo_flash_size[1]; + ambiqmicro_info->sramsiz = apollo_sram_size[0]; + ambiqmicro_info->num_pages = ambiqmicro_info->flshsiz / + ambiqmicro_info->pagesize; + if (ambiqmicro_info->num_pages > 128) { + ambiqmicro_info->num_pages = 128; + ambiqmicro_info->flshsiz = 1024 * 256; + } + break; + + } + + ambiqmicro_info->target_name = + ambiqmicroParts[ambiqmicro_info->target_class].partname; + + LOG_DEBUG("num_pages: %d, pagesize: %d, flash: %d, sram: %d", + ambiqmicro_info->num_pages, + ambiqmicro_info->pagesize, + ambiqmicro_info->flshsiz, + ambiqmicro_info->sramsiz); + + return ERROR_OK; +} + +/*************************************************************************** +* flash operations * +***************************************************************************/ + +static int ambiqmicro_protect_check(struct flash_bank *bank) +{ + struct ambiqmicro_flash_bank *ambiqmicro = bank->driver_priv; + int status = ERROR_OK; + uint32_t i; + + + if (ambiqmicro->probed == 0) { + LOG_ERROR("Target not probed"); + return ERROR_FLASH_BANK_NOT_PROBED; + } + + for (i = 0; i < (unsigned) bank->num_sectors; i++) + bank->sectors[i].is_protected = -1; + + return status; +} + +static int ambiqmicro_mass_erase(struct flash_bank *bank) +{ + struct target *target = NULL; + struct ambiqmicro_flash_bank *ambiqmicro_info = NULL; + uint32_t retval = ERROR_OK; + + ambiqmicro_info = bank->driver_priv; + target = bank->target; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (ambiqmicro_info->probed == 0) { + LOG_ERROR("Target not probed"); + return ERROR_FLASH_BANK_NOT_PROBED; + } + + /* + * Clear Bootloader bit. + */ + retval = target_write_u32(target, 0x400201a0, 0x0); + + /* + * Set up the SRAM. + */ + + /* + * Bank. + */ + retval = target_write_u32(target, 0x10000000, bank->bank_number); + + /* + * Write Key. + */ + retval = target_write_u32(target, 0x10000004, PROGRAM_KEY); + + /* + * Breakpoint. + */ + retval = target_write_u32(target, 0x10000008, 0xfffffffe); + + /* + * Erase the main array. + */ + LOG_INFO("Mass erase on bank %d", bank->bank_number); + + /* + * passed pc, addr = ROM function, handle breakpoints, not debugging. + */ + retval = target_resume( + target, + false, + FLASH_MASS_ERASE_MAIN_PAGES_FROM_SRAM, + true, + true); + + if (retval != ERROR_OK) + LOG_ERROR("error executing ambiqmicro flash mass erase algorithm"); + + /* + * Wait for halt. + */ + for (;; ) { + target_poll(target); + if (target->state == TARGET_HALTED) + break; + else if (target->state == TARGET_RUNNING || + target->state == TARGET_DEBUG_RUNNING) { + /* + * Keep polling until target halts. + */ + target_poll(target); + alive_sleep(100); + LOG_DEBUG("state = %d", target->state); + } else { + LOG_ERROR("Target not halted or running %d", target->state); + retval = ERROR_OK; + break; + } + } + + /* + * Read return value. + */ + target_read_u32(target, 0x10000008, &retval); + + if (retval != 0) { + LOG_ERROR("Flash not happy %d", retval); + return -1; + } + + /* + * Set Bootloader bit. + */ + retval = target_write_u32(target, 0x400201a0, 0x1); + + if (retval != ERROR_OK) + LOG_ERROR("error setting bootloader bit"); + + return ERROR_OK; +} + + +static int ambiqmicro_erase(struct flash_bank *bank, int first, int last) +{ + struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv; + struct target *target = bank->target; + uint32_t retval = ERROR_OK; + + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (ambiqmicro_info->probed == 0) { + LOG_ERROR("Target not probed"); + return ERROR_FLASH_BANK_NOT_PROBED; + } + + /* + * Check pages. + * Fix num_pages for the device. + */ + if ((first < 0) || (last < first) || (last >= (int)ambiqmicro_info->num_pages)) + return ERROR_FLASH_SECTOR_INVALID; + + /* + * Just Mass Erase if all pages are given. + * TODO: Fix num_pages for the device + */ + if ((first == 0) && (last == ((int)ambiqmicro_info->num_pages-1))) + return ambiqmicro_mass_erase(bank); + + /* + * Clear Bootloader bit. + */ + retval = target_write_u32(target, 0x400201a0, 0x0); + + /* + * Set up the SRAM. + */ + + /* + * Bank. + */ + retval = target_write_u32(target, 0x10000000, bank->bank_number); + + /* + * Number of pages to erase. + */ + retval = target_write_u32(target, 0x10000004, 1 + (last-first)); + + /* + * Write Key. + */ + retval = target_write_u32(target, 0x10000008, PROGRAM_KEY); + + /* + * Breakpoint. + */ + retval = target_write_u32(target, 0x1000000c, 0xfffffffe); + + /* + * Pointer to flash address. + */ + retval = target_write_u32(target, 0x10000010, first); + + /* + * Erase the pages. + */ + LOG_INFO("Erasing pages %d to %d on bank %d", first, last, bank->bank_number); + + /* + * passed pc, addr = ROM function, handle breakpoints, not debugging. + */ + retval = target_resume( + target, + false, + FLASH_ERASE_LIST_MAIN_PAGES_FROM_SRAM, + true, + true); + + if (retval != ERROR_OK) + LOG_ERROR("error executing ambiqmicro flash mass erase algorithm"); + + /* + * Wait for halt. + */ + for (;; ) { + target_poll(target); + if (target->state == TARGET_HALTED) + break; + else if (target->state == TARGET_RUNNING || + target->state == TARGET_DEBUG_RUNNING) { + /* + * Keep polling until target halts. + */ + target_poll(target); + alive_sleep(100); + LOG_DEBUG("state = %d", target->state); + } else { + LOG_ERROR("Target not halted or running %d", target->state); + retval = ERROR_OK; + break; + } + } + + LOG_INFO("%d pages erased!", 1+(last-first)); + + if (first == 0) { + /* + * Set Bootloader bit. + */ + retval = target_write_u32(target, 0x400201a0, 0x1); + } + + /* + * Read return value. + */ + target_read_u32(target, 0x1000000c, &retval); + + if (retval != 0) { + LOG_ERROR("Flash not happy %d", retval); + return -1; + } + + return ERROR_OK; +} + +static int ambiqmicro_protect(struct flash_bank *bank, int set, int first, int last) +{ + /* struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv; + * struct target *target = bank->target; */ + + /* + * TODO + */ + LOG_INFO("Not yet implemented"); + + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + return ERROR_OK; +} + +static int ambiqmicro_write_block(struct flash_bank *bank, + const uint8_t *buffer, uint32_t offset, uint32_t count) +{ + /* struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv; */ + struct target *target = bank->target; + uint32_t address = bank->base + offset; + uint32_t ui32buffer_pointer = 0x10000010; + uint32_t ui32maxbuffer; + uint32_t thisrun_count; + uint32_t retval = ERROR_OK; + + if (((count%4) != 0) || ((offset%4) != 0)) { + LOG_ERROR("write block must be multiple of 4 bytes in offset & length"); + return ERROR_FAIL; + } + + /* + * Max buffer size for this device. + * Hard code 6kB for the buffer. + */ + ui32maxbuffer = 0x1800; + + LOG_INFO("Flashing main array"); + + while (count > 0) { + if (count > ui32maxbuffer) + thisrun_count = ui32maxbuffer; + else + thisrun_count = count; + + /* + * Set up the SRAM. + */ + + /* + * Pointer to flash. + */ + retval = target_write_u32(target, 0x10000000, address); + + /* + * Number of 32-bit words to program. + */ + retval = target_write_u32(target, 0x10000004, thisrun_count/4); + + /* + * Write Key. + */ + retval = target_write_u32(target, 0x10000008, PROGRAM_KEY); + + /* + * Breakpoint. + */ + retval = target_write_u32(target, 0x1000000c, 0xfffffffe); + + /* + * Write Buffer. + */ + retval = target_write_buffer(target, ui32buffer_pointer, thisrun_count, buffer); + + if (retval != ERROR_OK) + break; + + LOG_DEBUG("address = 0x%08x", address); + + retval = target_resume( + target, + false, + FLASH_PROGRAM_MAIN_FROM_SRAM, + true, + true); + + if (retval != ERROR_OK) { + LOG_ERROR("error executing ambiqmicro flash write algorithm"); + break; + } + + /* + * Wait for halt. + */ + for (;; ) { + target_poll(target); + if (target->state == TARGET_HALTED) + break; + else if (target->state == TARGET_RUNNING || + target->state == TARGET_DEBUG_RUNNING) { + /* + * Keep polling until target halts. + */ + target_poll(target); + alive_sleep(100); + LOG_DEBUG("state = %d", target->state); + } else { + LOG_ERROR("Target not halted or running %d", target->state); + retval = ERROR_OK; + break; + } + } + + /* + * Read return value. + */ + target_read_u32(target, 0x1000000c, &retval); + + if (retval != 0) { + LOG_ERROR("Flash not happy %d", retval); + return -1; + } + + buffer += thisrun_count; + address += thisrun_count; + count -= thisrun_count; + } + + + LOG_INFO("Main array flashed"); + + /* + * Clear Bootloader bit. + */ + retval = target_write_u32(target, 0x400201a0, 0x0); + + if (retval != ERROR_OK) + LOG_ERROR("error clearing bootloader bit"); + + return retval; +} + +static int ambiqmicro_write(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + uint32_t retval; + + /* try using a block write */ + retval = ambiqmicro_write_block(bank, buffer, offset, count); + if (retval != ERROR_OK) + LOG_ERROR("write failed"); + + return retval; +} + +static int ambiqmicro_probe(struct flash_bank *bank) +{ + struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv; + uint32_t retval; + + /* If this is a ambiqmicro chip, it has flash; probe() is just + * to figure out how much is present. Only do it once. + */ + if (ambiqmicro_info->probed == 1) { + LOG_INFO("Target already probed"); + return ERROR_OK; + } + + /* ambiqmicro_read_part_info() already handled error checking and + * reporting. Note that it doesn't write, so we don't care about + * whether the target is halted or not. + */ + retval = ambiqmicro_read_part_info(bank); + if (retval != ERROR_OK) + return retval; + + if (bank->sectors) { + free(bank->sectors); + bank->sectors = NULL; + } + + /* provide this for the benefit of the NOR flash framework */ + bank->size = ambiqmicro_info->pagesize * ambiqmicro_info->num_pages; + bank->num_sectors = ambiqmicro_info->num_pages; + bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); + for (int i = 0; i < bank->num_sectors; i++) { + bank->sectors[i].offset = i * ambiqmicro_info->pagesize; + bank->sectors[i].size = ambiqmicro_info->pagesize; + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = -1; + } + + /* + * Part has been probed. + */ + ambiqmicro_info->probed = 1; + + return retval; +} + +static int ambiqmicro_otp_program(struct flash_bank *bank, + uint32_t offset, uint32_t count) +{ + struct target *target = NULL; + struct ambiqmicro_flash_bank *ambiqmicro_info = NULL; + uint32_t retval = ERROR_OK; + + ambiqmicro_info = bank->driver_priv; + target = bank->target; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (ambiqmicro_info->probed == 0) { + LOG_ERROR("Target not probed"); + return ERROR_FLASH_BANK_NOT_PROBED; + } + + if (count > 256) { + LOG_ERROR("Count must be < 256"); + return -1; + } + + /* + * Clear Bootloader bit. + */ + retval = target_write_u32(target, 0x400201a0, 0x0); + + /* + * Set up the SRAM. + */ + + /* + * Bank. + */ + retval = target_write_u32(target, 0x10000000, offset); + + /* + * Num of words to program. + */ + retval = target_write_u32(target, 0x10000004, count); + + /* + * Write Key. + */ + retval = target_write_u32(target, 0x10000008, OTP_PROGRAM_KEY); + + /* + * Breakpoint. + */ + retval = target_write_u32(target, 0x1000000c, 0xfffffffe); + + /* + * Program OTP. + */ + LOG_INFO("Programming OTP offset 0x%08x", offset); + + /* + * passed pc, addr = ROM function, handle breakpoints, not debugging. + */ + retval = target_resume( + target, + false, + FLASH_PROGRAM_OTP_FROM_SRAM, + true, + true); + + if (retval != ERROR_OK) + LOG_ERROR("error executing ambiqmicro otp program algorithm"); + + /* + * Wait for halt. + */ + for (;; ) { + target_poll(target); + if (target->state == TARGET_HALTED) + break; + else if (target->state == TARGET_RUNNING || + target->state == TARGET_DEBUG_RUNNING) { + /* + * Keep polling until target halts. + */ + target_poll(target); + alive_sleep(100); + LOG_DEBUG("state = %d", target->state); + } else { + LOG_ERROR("Target not halted or running %d", target->state); + retval = ERROR_OK; + break; + } + } + + /* + * Read return value. + */ + target_read_u32(target, 0x1000000c, &retval); + + if (retval != 0) { + LOG_ERROR("Flash not happy %d", retval); + return -1; + } + + LOG_INFO("Programming OTP finished"); + + return ERROR_OK; +} + +#if 0 +static int ambiqmicro_auto_probe(struct flash_bank *bank) +{ + struct ambiqmicro_flash_bank *ambiqmicro_info = bank->driver_priv; + if (ambiqmicro_info->probed) + return ERROR_OK; + return ambiqmicro_probe(bank); +} +#endif + + +COMMAND_HANDLER(ambiqmicro_handle_mass_erase_command) +{ + int i; + + if (CMD_ARGC < 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct flash_bank *bank; + uint32_t retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + if (ambiqmicro_mass_erase(bank) == ERROR_OK) { + /* set all sectors as erased */ + for (i = 0; i < bank->num_sectors; i++) + bank->sectors[i].is_erased = 1; + + command_print(CMD_CTX, "ambiqmicro mass erase complete"); + } else + command_print(CMD_CTX, "ambiqmicro mass erase failed"); + + return ERROR_OK; +} + +COMMAND_HANDLER(ambiqmicro_handle_page_erase_command) +{ + struct flash_bank *bank; + uint32_t first, last; + uint32_t retval; + + if (CMD_ARGC < 3) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last); + + retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + if (ambiqmicro_erase(bank, first, last) == ERROR_OK) + command_print(CMD_CTX, "ambiqmicro page erase complete"); + else + command_print(CMD_CTX, "ambiqmicro page erase failed"); + + return ERROR_OK; +} + + +/** + * Enable/Disable fault regs. + */ +COMMAND_HANDLER(ambiqmicro_handle_fault_capture_command) +{ + struct flash_bank *bank; + uint32_t enable; + uint32_t retval; + + if (CMD_ARGC < 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], enable); + enable = enable >= 1; + + command_print(CMD_CTX, "enable=%d", enable); + + retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + /* + * TODO + */ + LOG_INFO("Not yet implemented"); + + return ERROR_OK; +} + +/** + * Program the otp block. + */ +COMMAND_HANDLER(ambiqmicro_handle_program_otp_command) +{ + struct flash_bank *bank; + uint32_t offset, count; + uint32_t retval; + + if (CMD_ARGC < 3) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], offset); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count); + + command_print(CMD_CTX, "offset=0x%08x count=%d", offset, count); + + CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + + retval = ambiqmicro_otp_program(bank, offset, count); + + if (retval != ERROR_OK) + LOG_ERROR("error check log"); + + return ERROR_OK; +} + + + +static const struct command_registration ambiqmicro_exec_command_handlers[] = { + { + .name = "mass_erase", + .usage = "<bank>", + .handler = ambiqmicro_handle_mass_erase_command, + .mode = COMMAND_EXEC, + .help = "Erase entire device", + }, + { + .name = "page_erase", + .usage = "<bank> <first> <last>", + .handler = ambiqmicro_handle_page_erase_command, + .mode = COMMAND_EXEC, + .help = "Erase device pages", + }, + { + .name = "fault_capture", + .usage = "<bank> <enable>", + .handler = ambiqmicro_handle_fault_capture_command, + .mode = COMMAND_EXEC, + .help = "Enable/disable the fault capture registers", + }, + { + .name = "program_otp", + .handler = ambiqmicro_handle_program_otp_command, + .mode = COMMAND_EXEC, + .usage = "<bank> <offset> <count>", + .help = + "Program OTP (assumes you have already written array starting at 0x10000010)", + }, + COMMAND_REGISTRATION_DONE +}; +static const struct command_registration ambiqmicro_command_handlers[] = { + { + .name = "ambiqmicro", + .mode = COMMAND_EXEC, + .help = "ambiqmicro flash command group", + .usage = "", + .chain = ambiqmicro_exec_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + +struct flash_driver ambiqmicro_flash = { + .name = "ambiqmicro", + .commands = ambiqmicro_command_handlers, + .flash_bank_command = ambiqmicro_flash_bank_command, + .erase = ambiqmicro_erase, + .protect = ambiqmicro_protect, + .write = ambiqmicro_write, + .read = default_flash_read, + .probe = ambiqmicro_probe, + .auto_probe = ambiqmicro_probe, + .erase_check = default_flash_blank_check, + .protect_check = ambiqmicro_protect_check, + .info = get_ambiqmicro_info, +}; diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 48d584e..7a69c74 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -27,6 +27,7 @@ extern struct flash_driver lpc288x_flash; extern struct flash_driver lpc2900_flash; extern struct flash_driver lpcspifi_flash; extern struct flash_driver cfi_flash; +extern struct flash_driver ambiqmicro_flash; extern struct flash_driver at91sam3_flash; extern struct flash_driver at91sam4_flash; extern struct flash_driver at91sam4l_flash; @@ -75,6 +76,7 @@ static struct flash_driver *flash_drivers[] = { &lpc2900_flash, &lpcspifi_flash, &cfi_flash, + &ambiqmicro_flash, &at91sam7_flash, &at91sam3_flash, &at91sam4_flash, diff --git a/tcl/board/am-apollo_evk.cfg b/tcl/board/am-apollo_evk.cfg new file mode 100644 index 0000000..10dd9d8 --- /dev/null +++ b/tcl/board/am-apollo_evk.cfg @@ -0,0 +1,6 @@ +# +# Ambiq Micro - Apollo EVK Board. +# + +source [find interface/am-ft4232.cfg] +source [find target/am-apollo.cfg] diff --git a/tcl/interface/am-ft4232.cfg b/tcl/interface/am-ft4232.cfg new file mode 100644 index 0000000..24e9cb3 --- /dev/null +++ b/tcl/interface/am-ft4232.cfg @@ -0,0 +1,26 @@ +# +# Ambiq Micro - FT4232 Target +# + +# TCP server configuration +gdb_port 3333 +telnet_port 4444 +gdb_memory_map enable +gdb_flash_program enable + +interface ftdi +#ftdi_device_desc "Quad RS232-HS" +ftdi_vid_pid 0x2AEC 0x6011 + +# Channel for using JTAG +ftdi_channel 0 + +ftdi_layout_init 0x8c58 0xffab + +# Signals +ftdi_layout_signal SWD_EN -data 0 +ftdi_layout_signal SWDIO_OE -ndata 0x80 +# Use GPIOL0 as nTRST +ftdi_layout_signal nTRST -data 0x10 +# Use GPIOL2 as nRST +ftdi_layout_signal nRST -oe 0x40 diff --git a/tcl/target/am-apollo.cfg b/tcl/target/am-apollo.cfg new file mode 100644 index 0000000..08cb7c1 --- /dev/null +++ b/tcl/target/am-apollo.cfg @@ -0,0 +1,58 @@ +# +# Ambiq Micro - Apollo Target +# + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME apollo +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + set _ENDIAN little +} + +# Work-area is a space in RAM used for flash programming +# By default use 0kB +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x200 +} + +if { [info exists CPUTAPID ] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x2BA01477 +} + +set _TRANSPORT swd +transport select $_TRANSPORT + +swd newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME + +$_TARGETNAME configure -work-area-phys 0x10000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +# flash size will be probed +set _FLASHNAME $_CHIPNAME.flash0 +flash bank $_FLASHNAME ambiqmicro 0 0x00040000 0 0 $_TARGETNAME +# This is a 512K chip - it has the 2nd bank +set _FLASHNAME $_CHIPNAME.flash1 +flash bank $_FLASHNAME ambiqmicro 0x00040000 0x00040000 0 0 $_TARGETNAME + +# Reset target when gdb connects. +$_TARGETNAME configure -event gdb-attach { + reset init + halt +} +# if srst is not fitted use SYSRESETREQ to +# perform a soft reset +cortex_m reset_config sysresetreq + +# SWD clock +adapter_khz 100 -- ------------------------------------------------------------------------------ Site24x7 APM Insight: Get Deep Visibility into Application Performance APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month Monitor end-to-end web transactions and take corrective actions now Troubleshoot faster and improve end-user experience. Signup Now! http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140 _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
