Merge branch 'master' into from_upstream

Conflicts:
	README
	contrib/loaders/flash/fespi/Makefile
	src/flash/nor/fespi.c
	src/flash/nor/spi.c

Change-Id: I78a4e73685cc95daace95e9d16066a6fb51034fb
This commit is contained in:
Tim Newsome
2019-02-08 14:39:47 -08:00
147 changed files with 6456 additions and 1240 deletions
+1
View File
@@ -179,6 +179,7 @@ COMMAND_HANDLER(handle_mxc_biswap_command)
static const struct command_registration mxc_sub_command_handlers[] = {
{
.name = "biswap",
.mode = COMMAND_EXEC,
.handler = handle_mxc_biswap_command,
.help = "Turns on/off bad block information swaping from main area, "
"without parameter query status.",
+2
View File
@@ -17,6 +17,7 @@ NOR_DRIVERS = \
%D%/at91sam7.c \
%D%/ath79.c \
%D%/atsamv.c \
%D%/atsame5.c \
%D%/avrf.c \
%D%/bluenrg-x.c \
%D%/cc3220sf.c \
@@ -64,6 +65,7 @@ NOR_DRIVERS = \
%D%/str9xpec.c \
%D%/tms470.c \
%D%/virtual.c \
%D%/w600.c \
%D%/xcf.c \
%D%/xmc1xxx.c \
%D%/xmc4xxx.c
-14
View File
@@ -74,12 +74,6 @@ static int aduc702x_build_sector_list(struct flash_bank *bank)
return ERROR_OK;
}
static int aduc702x_protect_check(struct flash_bank *bank)
{
printf("aduc702x_protect_check not implemented yet.\n");
return ERROR_OK;
}
static int aduc702x_erase(struct flash_bank *bank, int first, int last)
{
/* int res; */
@@ -130,12 +124,6 @@ static int aduc702x_erase(struct flash_bank *bank, int first, int last)
return ERROR_OK;
}
static int aduc702x_protect(struct flash_bank *bank, int set, int first, int last)
{
printf("aduc702x_protect not implemented yet.\n");
return ERROR_FLASH_OPERATION_FAILED;
}
/* If this fn returns ERROR_TARGET_RESOURCE_NOT_AVAILABLE, then the caller can fall
* back to another mechanism that does not require onboard RAM
*
@@ -394,11 +382,9 @@ struct flash_driver aduc702x_flash = {
.name = "aduc702x",
.flash_bank_command = aduc702x_flash_bank_command,
.erase = aduc702x_erase,
.protect = aduc702x_protect,
.write = aduc702x_write,
.read = default_flash_read,
.probe = aduc702x_probe,
.auto_probe = aduc702x_probe,
.erase_check = default_flash_blank_check,
.protect_check = aduc702x_protect_check,
};
-16
View File
@@ -102,13 +102,6 @@ static int aducm360_build_sector_list(struct flash_bank *bank)
return ERROR_OK;
}
/* ----------------------------------------------------------------------- */
static int aducm360_protect_check(struct flash_bank *bank)
{
LOG_WARNING("aducm360_protect_check not implemented.");
return ERROR_OK;
}
/* ----------------------------------------------------------------------- */
static int aducm360_mass_erase(struct target *target)
{
@@ -194,13 +187,6 @@ static int aducm360_erase(struct flash_bank *bank, int first, int last)
return res;
}
/* ----------------------------------------------------------------------- */
static int aducm360_protect(struct flash_bank *bank, int set, int first, int last)
{
LOG_ERROR("aducm360_protect not implemented.");
return ERROR_FLASH_OPERATION_FAILED;
}
/* ----------------------------------------------------------------------- */
static int aducm360_write_block_sync(
struct flash_bank *bank,
@@ -572,11 +558,9 @@ struct flash_driver aducm360_flash = {
.name = "aducm360",
.flash_bank_command = aducm360_flash_bank_command,
.erase = aducm360_erase,
.protect = aducm360_protect,
.write = aducm360_write,
.read = default_flash_read,
.probe = aducm360_probe,
.auto_probe = aducm360_probe,
.erase_check = default_flash_blank_check,
.protect_check = aducm360_protect_check,
};
+1 -23
View File
@@ -2991,28 +2991,6 @@ static int sam3_GetInfo(struct sam3_chip *pChip)
return ERROR_OK;
}
static int sam3_erase_check(struct flash_bank *bank)
{
int x;
LOG_DEBUG("Here");
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (0 == bank->num_sectors) {
LOG_ERROR("Target: not supported/not probed");
return ERROR_FAIL;
}
LOG_INFO("sam3 - supports auto-erase, erase_check ignored");
for (x = 0; x < bank->num_sectors; x++)
bank->sectors[x].is_erased = 1;
LOG_DEBUG("Done");
return ERROR_OK;
}
static int sam3_protect_check(struct flash_bank *bank)
{
int r;
@@ -3785,7 +3763,7 @@ struct flash_driver at91sam3_flash = {
.read = default_flash_read,
.probe = sam3_probe,
.auto_probe = sam3_auto_probe,
.erase_check = sam3_erase_check,
.erase_check = default_flash_blank_check,
.protect_check = sam3_protect_check,
.free_driver_priv = sam3_free_driver_priv,
};
+29
View File
@@ -180,6 +180,28 @@ static const struct samd_part samd21_parts[] = {
{ 0x24, "SAMD21G15B", 32, 4 },
{ 0x26, "SAMD21E16B", 64, 8 },
{ 0x27, "SAMD21E15B", 32, 4 },
/* Known SAMDA1 parts.
SAMD-A1 series uses the same series identifier like the SAMD21
taken from http://ww1.microchip.com/downloads/en/DeviceDoc/40001895A.pdf (pages 14-17) */
{ 0x29, "SAMDA1J16A", 64, 8 },
{ 0x2A, "SAMDA1J15A", 32, 4 },
{ 0x2B, "SAMDA1J14A", 16, 4 },
{ 0x2C, "SAMDA1G16A", 64, 8 },
{ 0x2D, "SAMDA1G15A", 32, 4 },
{ 0x2E, "SAMDA1G14A", 16, 4 },
{ 0x2F, "SAMDA1E16A", 64, 8 },
{ 0x30, "SAMDA1E15A", 32, 4 },
{ 0x31, "SAMDA1E14A", 16, 4 },
{ 0x64, "SAMDA1J16B", 64, 8 },
{ 0x65, "SAMDA1J15B", 32, 4 },
{ 0x66, "SAMDA1J14B", 16, 4 },
{ 0x67, "SAMDA1G16B", 64, 8 },
{ 0x68, "SAMDA1G15B", 32, 4 },
{ 0x69, "SAMDA1G14B", 16, 4 },
{ 0x6A, "SAMDA1E16B", 64, 8 },
{ 0x6B, "SAMDA1E15B", 32, 4 },
{ 0x6C, "SAMDA1E14B", 16, 4 },
};
/* Known SAML21 parts. */
@@ -208,6 +230,9 @@ static const struct samd_part saml21_parts[] = {
/* SAMR30 parts have integrated SAML21 with a radio */
{ 0x1E, "SAMR30G18A", 256, 32 },
{ 0x1F, "SAMR30E18A", 256, 32 },
/* SAMR34/R35 parts have integrated SAML21 with a lora radio */
{ 0x28, "SAMR34J18", 256, 32 },
};
/* Known SAML22 parts. */
@@ -237,6 +262,8 @@ static const struct samd_part samc20_parts[] = {
{ 0x0B, "SAMC20E17A", 128, 16 },
{ 0x0C, "SAMC20E16A", 64, 8 },
{ 0x0D, "SAMC20E15A", 32, 4 },
{ 0x20, "SAMC20N18A", 256, 32 },
{ 0x21, "SAMC20N17A", 128, 16 },
};
/* Known SAMC21 parts. */
@@ -253,6 +280,8 @@ static const struct samd_part samc21_parts[] = {
{ 0x0B, "SAMC21E17A", 128, 16 },
{ 0x0C, "SAMC21E16A", 64, 8 },
{ 0x0D, "SAMC21E15A", 32, 4 },
{ 0x20, "SAMC21N18A", 256, 32 },
{ 0x21, "SAMC21N17A", 128, 16 },
};
/* Each family of parts contains a parts table in the DEVSEL field of DID. The
+31 -22
View File
@@ -522,6 +522,9 @@ static int ath79_erase(struct flash_bank *bank, int first, int last)
return ERROR_FLASH_BANK_NOT_PROBED;
}
if (ath79_info->dev->erase_cmd == 0x00)
return ERROR_FLASH_OPER_UNSUPPORTED;
for (sector = first; sector <= last; sector++) {
if (bank->sectors[sector].is_protected) {
LOG_ERROR("Flash sector %d protected", sector);
@@ -560,7 +563,11 @@ static int ath79_write_page(struct flash_bank *bank, const uint8_t *buffer,
address,
};
int retval;
uint32_t i;
uint32_t i, pagesize;
/* if no write pagesize, use reasonable default */
pagesize = ath79_info->dev->pagesize ?
ath79_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
if (address & 0xff) {
LOG_ERROR("ath79_write_page: unaligned write address: %08x",
@@ -573,7 +580,7 @@ static int ath79_write_page(struct flash_bank *bank, const uint8_t *buffer,
}
if (len > ath79_info->dev->pagesize) {
LOG_ERROR("ath79_write_page: len bigger than page size %d: %d",
ath79_info->dev->pagesize, len);
pagesize, len);
return ERROR_FAIL;
}
@@ -611,12 +618,16 @@ static int ath79_write_buffer(struct flash_bank *bank, const uint8_t *buffer,
uint32_t address, uint32_t len)
{
struct ath79_flash_bank *ath79_info = bank->driver_priv;
const uint32_t page_size = ath79_info->dev->pagesize;
uint32_t page_size;
int retval;
LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32,
__func__, address, len);
/* if no valid page_size, use reasonable default */
page_size = ath79_info->dev->pagesize ?
ath79_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
while (len > 0) {
int page_len = len > page_size ? page_size : len;
@@ -642,13 +653,6 @@ static int ath79_write(struct flash_bank *bank, const uint8_t *buffer,
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
__func__, offset, count);
if (offset < bank->base || offset >= bank->base + bank->size) {
LOG_ERROR("Start address out of range");
return ERROR_FAIL;
}
offset -= bank->base;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
@@ -718,13 +722,6 @@ static int ath79_read(struct flash_bank *bank, uint8_t *buffer,
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
__func__, offset, count);
if (offset < bank->base || offset >= bank->base + bank->size) {
LOG_ERROR("Start address out of range");
return ERROR_FAIL;
}
offset -= bank->base;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
@@ -775,6 +772,7 @@ static int ath79_probe(struct flash_bank *bank)
struct ath79_flash_bank *ath79_info = bank->driver_priv;
struct flash_sector *sectors;
uint32_t id = 0; /* silence uninitialized warning */
uint32_t pagesize, sectorsize;
const struct ath79_target *target_device;
int retval;
@@ -820,16 +818,27 @@ static int ath79_probe(struct flash_bank *bank)
/* Set correct size value */
bank->size = ath79_info->dev->size_in_bytes;
if (bank->size <= (1UL << 16))
LOG_WARNING("device needs 2-byte addresses - not implemented");
if (bank->size > (1UL << 24))
LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
/* if no sectors, treat whole bank as single sector */
sectorsize = ath79_info->dev->sectorsize ?
ath79_info->dev->sectorsize : ath79_info->dev->size_in_bytes;
/* create and fill sectors array */
bank->num_sectors =
ath79_info->dev->size_in_bytes / ath79_info->dev->sectorsize;
bank->num_sectors = ath79_info->dev->size_in_bytes / sectorsize;
sectors = calloc(1, sizeof(struct flash_sector) * bank->num_sectors);
if (!sectors) {
LOG_ERROR("not enough memory");
return ERROR_FAIL;
}
ath79_info->spi.page_buf = malloc(ath79_info->dev->pagesize);
/* if no write pagesize, use reasonable default */
pagesize = ath79_info->dev->pagesize ? ath79_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
ath79_info->spi.page_buf = malloc(pagesize);
if (!ath79_info->spi.page_buf) {
LOG_ERROR("not enough memory");
free(sectors);
@@ -837,8 +846,8 @@ static int ath79_probe(struct flash_bank *bank)
}
for (int sector = 0; sector < bank->num_sectors; sector++) {
sectors[sector].offset = sector * ath79_info->dev->sectorsize;
sectors[sector].size = ath79_info->dev->sectorsize;
sectors[sector].offset = sector * sectorsize;
sectors[sector].size = sectorsize;
sectors[sector].is_erased = 0;
sectors[sector].is_protected = 1;
}
+955
View File
@@ -0,0 +1,955 @@
/***************************************************************************
* Copyright (C) 2017 by Tomas Vanek *
* vanekt@fbl.cz *
* *
* Based on at91samd.c *
* Copyright (C) 2013 by Andrey Yurovsky *
* Andrey Yurovsky <yurovsky@gmail.com> *
* *
* 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 *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* 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, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "imp.h"
#include "helper/binarybuffer.h"
#include <target/cortex_m.h>
/* A note to prefixing.
* Definitions and functions ingerited from at91samd.c without
* any change retained the original prefix samd_ so they eventualy
* may go to samd_common.h and .c
* As currently there are olny 3 short functions identical with
* the original source, no common file was created. */
#define SAME5_PAGES_PER_BLOCK 16
#define SAME5_NUM_PROT_BLOCKS 32
#define SAMD_PAGE_SIZE_MAX 1024
#define SAMD_FLASH 0x00000000 /* physical Flash memory */
#define SAMD_USER_ROW 0x00804000 /* User Row of Flash */
#define SAME5_PAC 0x40000000 /* Peripheral Access Control */
#define SAMD_DSU 0x41002000 /* Device Service Unit */
#define SAMD_NVMCTRL 0x41004000 /* Non-volatile memory controller */
#define SAMD_DSU_STATUSA 1 /* DSU status register */
#define SAMD_DSU_DID 0x18 /* Device ID register */
#define SAMD_DSU_CTRL_EXT 0x100 /* CTRL register, external access */
#define SAME5_NVMCTRL_CTRLA 0x00 /* NVM control A register */
#define SAME5_NVMCTRL_CTRLB 0x04 /* NVM control B register */
#define SAMD_NVMCTRL_PARAM 0x08 /* NVM parameters register */
#define SAME5_NVMCTRL_INTFLAG 0x10 /* NVM interrupt flag register */
#define SAME5_NVMCTRL_STATUS 0x12 /* NVM status register */
#define SAME5_NVMCTRL_ADDR 0x14 /* NVM address register */
#define SAME5_NVMCTRL_LOCK 0x18 /* NVM Lock section register */
#define SAMD_CMDEX_KEY 0xA5UL
#define SAMD_NVM_CMD(n) ((SAMD_CMDEX_KEY << 8) | (n & 0x7F))
/* NVMCTRL commands. */
#define SAME5_NVM_CMD_EP 0x00 /* Erase Page (User Page only) */
#define SAME5_NVM_CMD_EB 0x01 /* Erase Block */
#define SAME5_NVM_CMD_WP 0x03 /* Write Page */
#define SAME5_NVM_CMD_WQW 0x04 /* Write Quad Word */
#define SAME5_NVM_CMD_LR 0x11 /* Lock Region */
#define SAME5_NVM_CMD_UR 0x12 /* Unlock Region */
#define SAME5_NVM_CMD_PBC 0x15 /* Page Buffer Clear */
#define SAME5_NVM_CMD_SSB 0x16 /* Set Security Bit */
/* NVMCTRL bits */
#define SAME5_NVMCTRL_CTRLA_WMODE_MASK 0x30
#define SAME5_NVMCTRL_INTFLAG_DONE (1 << 0)
#define SAME5_NVMCTRL_INTFLAG_ADDRE (1 << 1)
#define SAME5_NVMCTRL_INTFLAG_PROGE (1 << 2)
#define SAME5_NVMCTRL_INTFLAG_LOCKE (1 << 3)
#define SAME5_NVMCTRL_INTFLAG_ECCSE (1 << 4)
#define SAME5_NVMCTRL_INTFLAG_ECCDE (1 << 5)
#define SAME5_NVMCTRL_INTFLAG_NVME (1 << 6)
/* Known identifiers */
#define SAMD_PROCESSOR_M0 0x01
#define SAMD_PROCESSOR_M4 0x06
#define SAMD_FAMILY_D 0x00
#define SAMD_FAMILY_E 0x03
#define SAMD_SERIES_51 0x06
#define SAME_SERIES_51 0x01
#define SAME_SERIES_53 0x03
#define SAME_SERIES_54 0x04
/* Device ID macros */
#define SAMD_GET_PROCESSOR(id) (id >> 28)
#define SAMD_GET_FAMILY(id) (((id >> 23) & 0x1F))
#define SAMD_GET_SERIES(id) (((id >> 16) & 0x3F))
#define SAMD_GET_DEVSEL(id) (id & 0xFF)
/* Bits to mask user row */
#define NVMUSERROW_SAM_E5_D5_MASK ((uint64_t)0x7FFF00FF3C007FFF)
struct samd_part {
uint8_t id;
const char *name;
uint32_t flash_kb;
uint32_t ram_kb;
};
/* See SAM D5x/E5x Family Silicon Errata and Data Sheet Clarification
* DS80000748B */
/* Known SAMD51 parts. */
static const struct samd_part samd51_parts[] = {
{ 0x00, "SAMD51P20A", 1024, 256 },
{ 0x01, "SAMD51P19A", 512, 192 },
{ 0x02, "SAMD51N20A", 1024, 256 },
{ 0x03, "SAMD51N19A", 512, 192 },
{ 0x04, "SAMD51J20A", 1024, 256 },
{ 0x05, "SAMD51J19A", 512, 192 },
{ 0x06, "SAMD51J18A", 256, 128 },
{ 0x07, "SAMD51G19A", 512, 192 },
{ 0x08, "SAMD51G18A", 256, 128 },
};
/* Known SAME51 parts. */
static const struct samd_part same51_parts[] = {
{ 0x00, "SAME51N20A", 1024, 256 },
{ 0x01, "SAME51N19A", 512, 192 },
{ 0x02, "SAME51J19A", 512, 192 },
{ 0x03, "SAME51J18A", 256, 128 },
{ 0x04, "SAME51J20A", 1024, 256 },
};
/* Known SAME53 parts. */
static const struct samd_part same53_parts[] = {
{ 0x02, "SAME53N20A", 1024, 256 },
{ 0x03, "SAME53N19A", 512, 192 },
{ 0x04, "SAME53J20A", 1024, 256 },
{ 0x05, "SAME53J19A", 512, 192 },
{ 0x06, "SAME53J18A", 256, 128 },
};
/* Known SAME54 parts. */
static const struct samd_part same54_parts[] = {
{ 0x00, "SAME54P20A", 1024, 256 },
{ 0x01, "SAME54P19A", 512, 192 },
{ 0x02, "SAME54N20A", 1024, 256 },
{ 0x03, "SAME54N19A", 512, 192 },
};
/* Each family of parts contains a parts table in the DEVSEL field of DID. The
* processor ID, family ID, and series ID are used to determine which exact
* family this is and then we can use the corresponding table. */
struct samd_family {
uint8_t processor;
uint8_t family;
uint8_t series;
const struct samd_part *parts;
size_t num_parts;
};
/* Known SAMD families */
static const struct samd_family samd_families[] = {
{ SAMD_PROCESSOR_M4, SAMD_FAMILY_D, SAMD_SERIES_51,
samd51_parts, ARRAY_SIZE(samd51_parts) },
{ SAMD_PROCESSOR_M4, SAMD_FAMILY_E, SAME_SERIES_51,
same51_parts, ARRAY_SIZE(same51_parts) },
{ SAMD_PROCESSOR_M4, SAMD_FAMILY_E, SAME_SERIES_53,
same53_parts, ARRAY_SIZE(same53_parts) },
{ SAMD_PROCESSOR_M4, SAMD_FAMILY_E, SAME_SERIES_54,
same54_parts, ARRAY_SIZE(same54_parts) },
};
struct samd_info {
const struct samd_params *par;
uint32_t page_size;
int num_pages;
int sector_size;
int prot_block_size;
bool probed;
struct target *target;
};
/**
* Gives the family structure to specific device id.
* @param id The id of the device.
* @return On failure NULL, otherwise a pointer to the structure.
*/
static const struct samd_family *samd_find_family(uint32_t id)
{
uint8_t processor = SAMD_GET_PROCESSOR(id);
uint8_t family = SAMD_GET_FAMILY(id);
uint8_t series = SAMD_GET_SERIES(id);
for (unsigned i = 0; i < ARRAY_SIZE(samd_families); i++) {
if (samd_families[i].processor == processor &&
samd_families[i].series == series &&
samd_families[i].family == family)
return &samd_families[i];
}
return NULL;
}
/**
* Gives the part structure to specific device id.
* @param id The id of the device.
* @return On failure NULL, otherwise a pointer to the structure.
*/
static const struct samd_part *samd_find_part(uint32_t id)
{
uint8_t devsel = SAMD_GET_DEVSEL(id);
const struct samd_family *family = samd_find_family(id);
if (family == NULL)
return NULL;
for (unsigned i = 0; i < family->num_parts; i++) {
if (family->parts[i].id == devsel)
return &family->parts[i];
}
return NULL;
}
static int same5_protect_check(struct flash_bank *bank)
{
int res, prot_block;
uint32_t lock;
res = target_read_u32(bank->target,
SAMD_NVMCTRL + SAME5_NVMCTRL_LOCK, &lock);
if (res != ERROR_OK)
return res;
/* Lock bits are active-low */
for (prot_block = 0; prot_block < bank->num_prot_blocks; prot_block++)
bank->prot_blocks[prot_block].is_protected = !(lock & (1u<<prot_block));
return ERROR_OK;
}
static int samd_get_flash_page_info(struct target *target,
uint32_t *sizep, int *nump)
{
int res;
uint32_t param;
res = target_read_u32(target, SAMD_NVMCTRL + SAMD_NVMCTRL_PARAM, &param);
if (res == ERROR_OK) {
/* The PSZ field (bits 18:16) indicate the page size bytes as 2^(3+n)
* so 0 is 8KB and 7 is 1024KB. */
if (sizep)
*sizep = (8 << ((param >> 16) & 0x7));
/* The NVMP field (bits 15:0) indicates the total number of pages */
if (nump)
*nump = param & 0xFFFF;
} else {
LOG_ERROR("Couldn't read NVM Parameters register");
}
return res;
}
static int same5_probe(struct flash_bank *bank)
{
uint32_t id;
int res;
struct samd_info *chip = (struct samd_info *)bank->driver_priv;
const struct samd_part *part;
if (chip->probed)
return ERROR_OK;
res = target_read_u32(bank->target, SAMD_DSU + SAMD_DSU_DID, &id);
if (res != ERROR_OK) {
LOG_ERROR("Couldn't read Device ID register");
return res;
}
part = samd_find_part(id);
if (part == NULL) {
LOG_ERROR("Couldn't find part corresponding to DID %08" PRIx32, id);
return ERROR_FAIL;
}
bank->size = part->flash_kb * 1024;
res = samd_get_flash_page_info(bank->target, &chip->page_size,
&chip->num_pages);
if (res != ERROR_OK) {
LOG_ERROR("Couldn't determine Flash page size");
return res;
}
/* Sanity check: the total flash size in the DSU should match the page size
* multiplied by the number of pages. */
if (bank->size != chip->num_pages * chip->page_size) {
LOG_WARNING("SAM: bank size doesn't match NVM parameters. "
"Identified %" PRIu32 "KB Flash but NVMCTRL reports %u %" PRIu32 "B pages",
part->flash_kb, chip->num_pages, chip->page_size);
}
/* Erase granularity = 1 block = 16 pages */
chip->sector_size = chip->page_size * SAME5_PAGES_PER_BLOCK;
/* Allocate the sector table */
bank->num_sectors = chip->num_pages / SAME5_PAGES_PER_BLOCK;
bank->sectors = alloc_block_array(0, chip->sector_size, bank->num_sectors);
if (!bank->sectors)
return ERROR_FAIL;
/* 16 protection blocks per device */
chip->prot_block_size = bank->size / SAME5_NUM_PROT_BLOCKS;
/* Allocate the table of protection blocks */
bank->num_prot_blocks = SAME5_NUM_PROT_BLOCKS;
bank->prot_blocks = alloc_block_array(0, chip->prot_block_size, bank->num_prot_blocks);
if (!bank->prot_blocks)
return ERROR_FAIL;
same5_protect_check(bank);
/* Done */
chip->probed = true;
LOG_INFO("SAM MCU: %s (%" PRIu32 "KB Flash, %" PRIu32 "KB RAM)", part->name,
part->flash_kb, part->ram_kb);
return ERROR_OK;
}
static int same5_wait_and_check_error(struct target *target)
{
int ret, ret2;
int rep_cnt = 100;
uint16_t intflag;
do {
ret = target_read_u16(target,
SAMD_NVMCTRL + SAME5_NVMCTRL_INTFLAG, &intflag);
if (ret == ERROR_OK && intflag & SAME5_NVMCTRL_INTFLAG_DONE)
break;
} while (--rep_cnt);
if (ret != ERROR_OK) {
LOG_ERROR("Can't read NVM INTFLAG");
return ret;
}
#if 0
if (intflag & SAME5_NVMCTRL_INTFLAG_ECCSE)
LOG_ERROR("SAM: ECC Single Error");
if (intflag & SAME5_NVMCTRL_INTFLAG_ECCDE) {
LOG_ERROR("SAM: ECC Double Error");
ret = ERROR_FLASH_OPERATION_FAILED;
}
#endif
if (intflag & SAME5_NVMCTRL_INTFLAG_ADDRE) {
LOG_ERROR("SAM: Addr Error");
ret = ERROR_FLASH_OPERATION_FAILED;
}
if (intflag & SAME5_NVMCTRL_INTFLAG_NVME) {
LOG_ERROR("SAM: NVM Error");
ret = ERROR_FLASH_OPERATION_FAILED;
}
if (intflag & SAME5_NVMCTRL_INTFLAG_LOCKE) {
LOG_ERROR("SAM: NVM lock error");
ret = ERROR_FLASH_PROTECTED;
}
if (intflag & SAME5_NVMCTRL_INTFLAG_PROGE) {
LOG_ERROR("SAM: NVM programming error");
ret = ERROR_FLASH_OPER_UNSUPPORTED;
}
/* Clear the error conditions by writing a one to them */
ret2 = target_write_u16(target,
SAMD_NVMCTRL + SAME5_NVMCTRL_INTFLAG, intflag);
if (ret2 != ERROR_OK)
LOG_ERROR("Can't clear NVM error conditions");
return ret;
}
static int same5_issue_nvmctrl_command(struct target *target, uint16_t cmd)
{
int res;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
/* Issue the NVM command */
/* 32-bit write is used to ensure atomic operation on ST-Link */
res = target_write_u32(target,
SAMD_NVMCTRL + SAME5_NVMCTRL_CTRLB, SAMD_NVM_CMD(cmd));
if (res != ERROR_OK)
return res;
/* Check to see if the NVM command resulted in an error condition. */
return same5_wait_and_check_error(target);
}
/**
* Erases a flash block or page at the given address.
* @param target Pointer to the target structure.
* @param address The address of the row.
* @return On success ERROR_OK, on failure an errorcode.
*/
static int same5_erase_block(struct target *target, uint32_t address)
{
int res;
/* Set an address contained in the block to be erased */
res = target_write_u32(target,
SAMD_NVMCTRL + SAME5_NVMCTRL_ADDR, address);
/* Issue the Erase Block command. */
if (res == ERROR_OK)
res = same5_issue_nvmctrl_command(target,
address == SAMD_USER_ROW ? SAME5_NVM_CMD_EP : SAME5_NVM_CMD_EB);
if (res != ERROR_OK) {
LOG_ERROR("Failed to erase block containing %08" PRIx32, address);
return ERROR_FAIL;
}
return ERROR_OK;
}
static int same5_pre_write_check(struct target *target)
{
int res;
uint32_t nvm_ctrla;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
/* Check if manual write mode is set */
res = target_read_u32(target, SAMD_NVMCTRL + SAME5_NVMCTRL_CTRLA, &nvm_ctrla);
if (res != ERROR_OK)
return res;
if (nvm_ctrla & SAME5_NVMCTRL_CTRLA_WMODE_MASK) {
LOG_ERROR("The flash controller must be in manual write mode. Issue 'reset init' and retry.");
return ERROR_FAIL;
}
return res;
}
/**
* Modify the contents of the User Row in Flash. The User Row itself
* has a size of one page and contains a combination of "fuses" and
* calibration data. Bits which have a value of zero in the mask will
* not be changed.
* @param target Pointer to the target structure.
* @param data Pointer to the value to write.
* @param mask Pointer to bitmask, 0 -> value stays untouched.
* @param offset Offset in user row where new data will be applied.
* @param count Size of buffer and mask in bytes.
* @return On success ERROR_OK, on failure an errorcode.
*/
static int same5_modify_user_row_masked(struct target *target,
const uint8_t *data, const uint8_t *mask,
uint32_t offset, uint32_t count)
{
int res;
/* Retrieve the MCU's flash page size, in bytes. */
uint32_t page_size;
res = samd_get_flash_page_info(target, &page_size, NULL);
if (res != ERROR_OK) {
LOG_ERROR("Couldn't determine Flash page size");
return res;
}
/* Make sure the size is sane. */
assert(page_size <= SAMD_PAGE_SIZE_MAX &&
page_size >= offset + count);
uint8_t buf[SAMD_PAGE_SIZE_MAX];
/* Read the user row (comprising one page) by words. */
res = target_read_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf);
if (res != ERROR_OK)
return res;
/* Modify buffer and check if really changed */
bool changed = false;
uint32_t i;
for (i = 0; i < count; i++) {
uint8_t old_b = buf[offset+i];
uint8_t new_b = (old_b & ~mask[i]) | (data[i] & mask[i]);
buf[offset+i] = new_b;
if (old_b != new_b)
changed = true;
}
if (!changed)
return ERROR_OK;
res = same5_pre_write_check(target);
if (res != ERROR_OK)
return res;
res = same5_erase_block(target, SAMD_USER_ROW);
if (res != ERROR_OK) {
LOG_ERROR("Couldn't erase user row");
return res;
}
/* Write the page buffer back out to the target using Write Quad Word */
for (i = 0; i < page_size; i += 4 * 4) {
res = target_write_memory(target, SAMD_USER_ROW + i, 4, 4, buf + i);
if (res != ERROR_OK)
return res;
/* Trigger flash write */
res = same5_issue_nvmctrl_command(target, SAME5_NVM_CMD_WQW);
if (res != ERROR_OK)
return res;
}
return res;
}
/**
* Modifies the user row register to the given value.
* @param target Pointer to the target structure.
* @param value The value to write.
* @param startb The bit-offset by which the given value is shifted.
* @param endb The bit-offset of the last bit in value to write.
* @return On success ERROR_OK, on failure an errorcode.
*/
static int same5_modify_user_row(struct target *target, uint32_t value,
uint8_t startb, uint8_t endb)
{
uint8_t buf_val[8] = { 0 };
uint8_t buf_mask[8] = { 0 };
assert(startb <= endb && endb < 64);
buf_set_u32(buf_val, startb, endb + 1 - startb, value);
buf_set_u32(buf_mask, startb, endb + 1 - startb, 0xffffffff);
return same5_modify_user_row_masked(target,
buf_val, buf_mask, 0, 8);
}
static int same5_protect(struct flash_bank *bank, int set, int first_prot_bl, int last_prot_bl)
{
int res = ERROR_OK;
int prot_block;
/* We can issue lock/unlock region commands with the target running but
* the settings won't persist unless we're able to modify the LOCK regions
* and that requires the target to be halted. */
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
for (prot_block = first_prot_bl; prot_block <= last_prot_bl; prot_block++) {
if (set != bank->prot_blocks[prot_block].is_protected) {
/* Load an address that is within this protection block (we use offset 0) */
res = target_write_u32(bank->target,
SAMD_NVMCTRL + SAME5_NVMCTRL_ADDR,
bank->prot_blocks[prot_block].offset);
if (res != ERROR_OK)
goto exit;
/* Tell the controller to lock that block */
res = same5_issue_nvmctrl_command(bank->target,
set ? SAME5_NVM_CMD_LR : SAME5_NVM_CMD_UR);
if (res != ERROR_OK)
goto exit;
}
}
/* We've now applied our changes, however they will be undone by the next
* reset unless we also apply them to the LOCK bits in the User Page.
* A '1' means unlocked and a '0' means locked. */
const uint8_t lock[4] = { 0, 0, 0, 0 };
const uint8_t unlock[4] = { 0xff, 0xff, 0xff, 0xff };
uint8_t mask[4] = { 0, 0, 0, 0 };
buf_set_u32(mask, first_prot_bl, last_prot_bl + 1 - first_prot_bl, 0xffffffff);
res = same5_modify_user_row_masked(bank->target,
set ? lock : unlock, mask, 8, 4);
if (res != ERROR_OK)
LOG_WARNING("SAM: protect settings were not made persistent!");
res = ERROR_OK;
exit:
same5_protect_check(bank);
return res;
}
static int same5_erase(struct flash_bank *bank, int first_sect, int last_sect)
{
int res, s;
struct samd_info *chip = (struct samd_info *)bank->driver_priv;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (!chip->probed)
return ERROR_FLASH_BANK_NOT_PROBED;
/* For each sector to be erased */
for (s = first_sect; s <= last_sect; s++) {
res = same5_erase_block(bank->target, bank->sectors[s].offset);
if (res != ERROR_OK) {
LOG_ERROR("SAM: failed to erase sector %d at 0x%08" PRIx32, s, bank->sectors[s].offset);
return res;
}
}
return ERROR_OK;
}
static int same5_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
int res;
uint32_t address;
uint32_t pg_offset;
uint32_t nb;
uint32_t nw;
struct samd_info *chip = (struct samd_info *)bank->driver_priv;
uint8_t *pb = NULL;
res = same5_pre_write_check(bank->target);
if (res != ERROR_OK)
return res;
if (!chip->probed)
return ERROR_FLASH_BANK_NOT_PROBED;
res = same5_issue_nvmctrl_command(bank->target, SAME5_NVM_CMD_PBC);
if (res != ERROR_OK) {
LOG_ERROR("%s: %d", __func__, __LINE__);
return res;
}
while (count) {
nb = chip->page_size - offset % chip->page_size;
if (count < nb)
nb = count;
address = bank->base + offset;
pg_offset = offset % chip->page_size;
if (offset % 4 || (offset + nb) % 4) {
/* Either start or end of write is not word aligned */
if (!pb) {
pb = malloc(chip->page_size);
if (!pb)
return ERROR_FAIL;
}
/* Set temporary page buffer to 0xff and overwrite the relevant part */
memset(pb, 0xff, chip->page_size);
memcpy(pb + pg_offset, buffer, nb);
/* Align start address to a word boundary */
address -= offset % 4;
pg_offset -= offset % 4;
assert(pg_offset % 4 == 0);
/* Extend length to whole words */
nw = (nb + offset % 4 + 3) / 4;
assert(pg_offset + 4 * nw <= chip->page_size);
/* Now we have original data extended by 0xff bytes
* to the nearest word boundary on both start and end */
res = target_write_memory(bank->target, address, 4, nw, pb + pg_offset);
} else {
assert(nb % 4 == 0);
nw = nb / 4;
assert(pg_offset + 4 * nw <= chip->page_size);
/* Word aligned data, use direct write from buffer */
res = target_write_memory(bank->target, address, 4, nw, buffer);
}
if (res != ERROR_OK) {
LOG_ERROR("%s: %d", __func__, __LINE__);
goto free_pb;
}
res = same5_issue_nvmctrl_command(bank->target, SAME5_NVM_CMD_WP);
if (res != ERROR_OK) {
LOG_ERROR("%s: write failed at address 0x%08" PRIx32, __func__, address);
goto free_pb;
}
/* We're done with the page contents */
count -= nb;
offset += nb;
buffer += nb;
}
free_pb:
if (pb)
free(pb);
return res;
}
FLASH_BANK_COMMAND_HANDLER(same5_flash_bank_command)
{
if (bank->base != SAMD_FLASH) {
LOG_ERROR("Address 0x%08" PRIx32 " invalid bank address (try 0x%08" PRIx32
"[same5] )",
bank->base, SAMD_FLASH);
return ERROR_FAIL;
}
struct samd_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;
}
COMMAND_HANDLER(same5_handle_chip_erase_command)
{
struct target *target = get_current_target(CMD_CTX);
if (!target)
return ERROR_FAIL;
/* Enable access to the DSU by disabling the write protect bit */
target_write_u32(target, SAME5_PAC, (1<<16) | (1<<5) | (1<<1));
/* intentionally without error checking - not accessible on secured chip */
/* Tell the DSU to perform a full chip erase. It takes about 240ms to
* perform the erase. */
int res = target_write_u8(target, SAMD_DSU + SAMD_DSU_CTRL_EXT, (1<<4));
if (res == ERROR_OK)
command_print(CMD_CTX, "chip erase started");
else
command_print(CMD_CTX, "write to DSU CTRL failed");
return res;
}
COMMAND_HANDLER(same5_handle_userpage_command)
{
int res = ERROR_OK;
struct target *target = get_current_target(CMD_CTX);
if (!target)
return ERROR_FAIL;
if (CMD_ARGC > 2) {
command_print(CMD_CTX, "Too much Arguments given.");
return ERROR_COMMAND_SYNTAX_ERROR;
}
if (CMD_ARGC >= 1) {
uint64_t mask = NVMUSERROW_SAM_E5_D5_MASK;
uint64_t value = strtoull(CMD_ARGV[0], NULL, 0);
if (CMD_ARGC == 2) {
uint64_t mask_temp = strtoull(CMD_ARGV[1], NULL, 0);
mask &= mask_temp;
}
uint8_t val_buf[8], mask_buf[8];
target_buffer_set_u64(target, val_buf, value);
target_buffer_set_u64(target, mask_buf, mask);
res = same5_modify_user_row_masked(target,
val_buf, mask_buf, 0, sizeof(val_buf));
}
uint8_t buffer[8];
int res2 = target_read_memory(target, SAMD_USER_ROW, 4, 2, buffer);
if (res2 == ERROR_OK) {
uint64_t value = target_buffer_get_u64(target, buffer);
command_print(CMD_CTX, "USER PAGE: 0x%016"PRIX64, value);
} else {
LOG_ERROR("USER PAGE could not be read.");
}
if (CMD_ARGC >= 1)
return res;
else
return res2;
}
COMMAND_HANDLER(same5_handle_bootloader_command)
{
int res = ERROR_OK;
struct target *target = get_current_target(CMD_CTX);
if (!target)
return ERROR_FAIL;
if (CMD_ARGC >= 1) {
unsigned long size = strtoul(CMD_ARGV[0], NULL, 0);
uint32_t code = (size + 8191) / 8192;
if (code > 15) {
command_print(CMD_CTX, "Invalid bootloader size. Please "
"see datasheet for a list valid sizes.");
return ERROR_COMMAND_SYNTAX_ERROR;
}
res = same5_modify_user_row(target, 15 - code, 26, 29);
}
uint32_t val;
int res2 = target_read_u32(target, SAMD_USER_ROW, &val);
if (res2 == ERROR_OK) {
uint32_t code = (val >> 26) & 0xf; /* grab size code */
uint32_t size = (15 - code) * 8192;
command_print(CMD_CTX, "Bootloader protected in the first %"
PRIu32 " bytes", size);
}
if (CMD_ARGC >= 1)
return res;
else
return res2;
}
COMMAND_HANDLER(samd_handle_reset_deassert)
{
struct target *target = get_current_target(CMD_CTX);
int res = ERROR_OK;
enum reset_types jtag_reset_config = jtag_get_reset_config();
if (!target)
return ERROR_FAIL;
/* 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 DSU
*
* n_RESET (srst) clears the DP, so reenable debug and set vector catch here
*
* After vectreset DSU release is not needed however makes no harm
*/
if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) {
res = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
if (res == ERROR_OK)
res = target_write_u32(target, DCB_DEMCR,
TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
/* do not return on error here, releasing DSU reset is more important */
}
/* clear CPU Reset Phase Extension bit */
int res2 = target_write_u8(target, SAMD_DSU + SAMD_DSU_STATUSA, (1<<1));
if (res2 != ERROR_OK)
return res2;
return res;
}
static const struct command_registration same5_exec_command_handlers[] = {
{
.name = "dsu_reset_deassert",
.handler = samd_handle_reset_deassert,
.mode = COMMAND_EXEC,
.help = "Deasert internal reset held by DSU."
},
{
.name = "chip-erase",
.handler = same5_handle_chip_erase_command,
.mode = COMMAND_EXEC,
.help = "Erase the entire Flash by using the Chip-"
"Erase feature in the Device Service Unit (DSU).",
},
{
.name = "bootloader",
.usage = "[size_in_bytes]",
.handler = same5_handle_bootloader_command,
.mode = COMMAND_EXEC,
.help = "Show or set the bootloader protection size, stored in the User Row. "
"Changes are stored immediately but take affect after the MCU is "
"reset.",
},
{
.name = "userpage",
.usage = "[value] [mask]",
.handler = same5_handle_userpage_command,
.mode = COMMAND_EXEC,
.help = "Show or set the first 64-bit part of user page "
"located at address 0x804000. Use the optional mask argument "
"to prevent changes at positions where the bitvalue is zero. "
"For security reasons the reserved-bits are masked out "
"in background and therefore cannot be changed.",
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration same5_command_handlers[] = {
{
.name = "atsame5",
.mode = COMMAND_ANY,
.help = "atsame5 flash command group",
.usage = "",
.chain = same5_exec_command_handlers,
},
COMMAND_REGISTRATION_DONE
};
struct flash_driver atsame5_flash = {
.name = "atsame5",
.commands = same5_command_handlers,
.flash_bank_command = same5_flash_bank_command,
.erase = same5_erase,
.protect = same5_protect,
.write = same5_write,
.read = default_flash_read,
.probe = same5_probe,
.auto_probe = same5_probe,
.erase_check = default_flash_blank_check,
.protect_check = same5_protect_check,
.free_driver_priv = default_flash_free_driver_priv,
};
+1 -15
View File
@@ -233,12 +233,6 @@ static int avrf_erase(struct flash_bank *bank, int first, int last)
return avr_jtagprg_leaveprogmode(avr);
}
static int avrf_protect(struct flash_bank *bank, int set, int first, int last)
{
LOG_INFO("%s", __func__);
return ERROR_OK;
}
static int avrf_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
{
struct target *target = bank->target;
@@ -338,7 +332,7 @@ static int avrf_probe(struct flash_bank *bank)
bank->sectors[i].offset = i * avr_info->flash_page_size;
bank->sectors[i].size = avr_info->flash_page_size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1;
bank->sectors[i].is_protected = -1;
}
avrf_info->probed = 1;
@@ -360,12 +354,6 @@ static int avrf_auto_probe(struct flash_bank *bank)
return avrf_probe(bank);
}
static int avrf_protect_check(struct flash_bank *bank)
{
LOG_INFO("%s", __func__);
return ERROR_OK;
}
static int avrf_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct target *target = bank->target;
@@ -479,13 +467,11 @@ struct flash_driver avr_flash = {
.commands = avrf_command_handlers,
.flash_bank_command = avrf_flash_bank_command,
.erase = avrf_erase,
.protect = avrf_protect,
.write = avrf_write,
.read = default_flash_read,
.probe = avrf_probe,
.auto_probe = avrf_auto_probe,
.erase_check = default_flash_blank_check,
.protect_check = avrf_protect_check,
.info = avrf_info,
.free_driver_priv = default_flash_free_driver_priv,
};
-18
View File
@@ -312,12 +312,6 @@ static int cc26xx_erase(struct flash_bank *bank, int first, int last)
return retval;
}
static int cc26xx_protect(struct flash_bank *bank, int set, int first,
int last)
{
return ERROR_OK;
}
static int cc26xx_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
@@ -497,22 +491,12 @@ static int cc26xx_auto_probe(struct flash_bank *bank)
int retval = ERROR_OK;
if (bank->bank_number != 0) {
/* Invalid bank number somehow */
return ERROR_FAIL;
}
if (!cc26xx_bank->probed)
retval = cc26xx_probe(bank);
return retval;
}
static int cc26xx_protect_check(struct flash_bank *bank)
{
return ERROR_OK;
}
static int cc26xx_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
@@ -555,13 +539,11 @@ struct flash_driver cc26xx_flash = {
.name = "cc26xx",
.flash_bank_command = cc26xx_flash_bank_command,
.erase = cc26xx_erase,
.protect = cc26xx_protect,
.write = cc26xx_write,
.read = default_flash_read,
.probe = cc26xx_probe,
.auto_probe = cc26xx_auto_probe,
.erase_check = default_flash_blank_check,
.protect_check = cc26xx_protect_check,
.info = cc26xx_info,
.free_driver_priv = default_flash_free_driver_priv,
};
+3 -29
View File
@@ -173,12 +173,6 @@ static int cc3220sf_erase(struct flash_bank *bank, int first, int last)
return retval;
}
static int cc3220sf_protect(struct flash_bank *bank, int set, int first,
int last)
{
return ERROR_OK;
}
static int cc3220sf_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
@@ -436,18 +430,10 @@ static int cc3220sf_probe(struct flash_bank *bank)
uint32_t base;
uint32_t size;
int num_sectors;
int bank_id;
bank_id = bank->bank_number;
if (0 == bank_id) {
base = FLASH_BASE_ADDR;
size = FLASH_NUM_SECTORS * FLASH_SECTOR_SIZE;
num_sectors = FLASH_NUM_SECTORS;
} else {
/* Invalid bank number somehow */
return ERROR_FAIL;
}
base = FLASH_BASE_ADDR;
size = FLASH_NUM_SECTORS * FLASH_SECTOR_SIZE;
num_sectors = FLASH_NUM_SECTORS;
if (NULL != bank->sectors) {
free(bank->sectors);
@@ -485,22 +471,12 @@ static int cc3220sf_auto_probe(struct flash_bank *bank)
int retval = ERROR_OK;
if (0 != bank->bank_number) {
/* Invalid bank number somehow */
return ERROR_FAIL;
}
if (!cc3220sf_bank->probed)
retval = cc3220sf_probe(bank);
return retval;
}
static int cc3220sf_protect_check(struct flash_bank *bank)
{
return ERROR_OK;
}
static int cc3220sf_info(struct flash_bank *bank, char *buf, int buf_size)
{
int printed;
@@ -517,13 +493,11 @@ struct flash_driver cc3220sf_flash = {
.name = "cc3220sf",
.flash_bank_command = cc3220sf_flash_bank_command,
.erase = cc3220sf_erase,
.protect = cc3220sf_protect,
.write = cc3220sf_write,
.read = default_flash_read,
.probe = cc3220sf_probe,
.auto_probe = cc3220sf_auto_probe,
.erase_check = default_flash_blank_check,
.protect_check = cc3220sf_protect_check,
.info = cc3220sf_info,
.free_driver_priv = default_flash_free_driver_priv,
};
-5
View File
@@ -1098,11 +1098,6 @@ static int cfi_protect(struct flash_bank *bank, int set, int first, int last)
return ERROR_TARGET_NOT_HALTED;
}
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
LOG_ERROR("Invalid sector range");
return ERROR_FLASH_SECTOR_INVALID;
}
if (cfi_info->qry[0] != 'Q')
return ERROR_FLASH_BANK_NOT_PROBED;
+7 -2
View File
@@ -68,6 +68,11 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last)
/* force "set" to 0/1 */
set = !!set;
if (bank->driver->protect == NULL) {
LOG_ERROR("Flash protection is not supported.");
return ERROR_FLASH_OPER_UNSUPPORTED;
}
/* DANGER!
*
* We must not use any cached information about protection state!!!!
@@ -319,8 +324,8 @@ static int default_flash_mem_blank_check(struct flash_bank *bank)
for (j = 0; j < bank->sectors[i].size; j += buffer_size) {
uint32_t chunk;
chunk = buffer_size;
if (chunk > (j - bank->sectors[i].size))
chunk = (j - bank->sectors[i].size);
if (chunk > (bank->sectors[i].size - j))
chunk = (bank->sectors[i].size - j);
retval = target_read_memory(target,
bank->base + bank->sectors[i].offset + j,
+4
View File
@@ -109,6 +109,8 @@ struct flash_driver {
/**
* Bank/sector protection routine (target-specific).
*
* If protection is not implemented, set method to NULL
*
* When called, the driver should enable/disable protection
* for MINIMUM the range covered by first..last sectors
* inclusive. Some chips have alignment requirements will
@@ -178,6 +180,8 @@ struct flash_driver {
* flash_sector_s::is_protected field for each of the flash
* bank's sectors.
*
* If protection is not implemented, set method to NULL
*
* @param bank - the bank to check
* @returns ERROR_OK if successful; otherwise, an error code.
*/
+4
View File
@@ -29,6 +29,7 @@ extern struct flash_driver at91sam4l_flash;
extern struct flash_driver at91sam7_flash;
extern struct flash_driver at91samd_flash;
extern struct flash_driver ath79_flash;
extern struct flash_driver atsame5_flash;
extern struct flash_driver atsamv_flash;
extern struct flash_driver avr_flash;
extern struct flash_driver bluenrgx_flash;
@@ -78,6 +79,7 @@ extern struct flash_driver str9x_flash;
extern struct flash_driver str9xpec_flash;
extern struct flash_driver tms470_flash;
extern struct flash_driver virtual_flash;
extern struct flash_driver w600_flash;
extern struct flash_driver xcf_flash;
extern struct flash_driver xmc1xxx_flash;
extern struct flash_driver xmc4xxx_flash;
@@ -96,6 +98,7 @@ static struct flash_driver *flash_drivers[] = {
&at91sam7_flash,
&at91samd_flash,
&ath79_flash,
&atsame5_flash,
&atsamv_flash,
&avr_flash,
&bluenrgx_flash,
@@ -148,6 +151,7 @@ static struct flash_driver *flash_drivers[] = {
&xcf_flash,
&xmc1xxx_flash,
&xmc4xxx_flash,
&w600_flash,
NULL,
};
+1 -1
View File
@@ -429,7 +429,7 @@ static int efm32x_erase_page(struct flash_bank *bank, uint32_t addr)
*/
int ret = 0;
uint32_t status = 0;
addr += bank->base;
LOG_DEBUG("erasing flash page at 0x%08" PRIx32, addr);
ret = efm32x_write_reg_u32(bank, EFM32_MSC_REG_ADDRB, addr);
+30 -64
View File
@@ -104,9 +104,12 @@ struct esirisc_flash_bank {
uint32_t wait_states;
};
static const struct command_registration esirisc_flash_command_handlers[];
FLASH_BANK_COMMAND_HANDLER(esirisc_flash_bank_command)
{
struct esirisc_flash_bank *esirisc_info;
struct command *esirisc_cmd;
if (CMD_ARGC < 9)
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -119,6 +122,10 @@ FLASH_BANK_COMMAND_HANDLER(esirisc_flash_bank_command)
bank->driver_priv = esirisc_info;
/* register commands using existing esirisc context */
esirisc_cmd = command_find_in_context(CMD_CTX, "esirisc");
register_commands(CMD_CTX, esirisc_cmd, esirisc_flash_command_handlers);
return ERROR_OK;
}
@@ -149,7 +156,7 @@ static int esirisc_flash_disable_protect(struct flash_bank *bank)
if (!(control & CONTROL_WP))
return ERROR_OK;
esirisc_flash_unlock(bank);
(void)esirisc_flash_unlock(bank);
control &= ~CONTROL_WP;
@@ -168,7 +175,7 @@ static int esirisc_flash_enable_protect(struct flash_bank *bank)
if (control & CONTROL_WP)
return ERROR_OK;
esirisc_flash_unlock(bank);
(void)esirisc_flash_unlock(bank);
control |= CONTROL_WP;
@@ -254,7 +261,7 @@ static int esirisc_flash_erase(struct flash_bank *bank, int first, int last)
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
esirisc_flash_disable_protect(bank);
(void)esirisc_flash_disable_protect(bank);
for (int page = first; page < last; ++page) {
uint32_t address = page * PAGE_SIZE;
@@ -268,7 +275,7 @@ static int esirisc_flash_erase(struct flash_bank *bank, int first, int last)
}
}
esirisc_flash_enable_protect(bank);
(void)esirisc_flash_enable_protect(bank);
return retval;
}
@@ -282,7 +289,7 @@ static int esirisc_flash_mass_erase(struct flash_bank *bank)
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
esirisc_flash_disable_protect(bank);
(void)esirisc_flash_disable_protect(bank);
target_write_u32(target, esirisc_info->cfg + ADDRESS, 0);
@@ -290,7 +297,7 @@ static int esirisc_flash_mass_erase(struct flash_bank *bank)
if (retval != ERROR_OK)
LOG_ERROR("%s: failed to mass erase", bank->name);
esirisc_flash_enable_protect(bank);
(void)esirisc_flash_enable_protect(bank);
return retval;
}
@@ -308,32 +315,17 @@ static int esirisc_flash_ref_erase(struct flash_bank *bank)
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
esirisc_flash_disable_protect(bank);
(void)esirisc_flash_disable_protect(bank);
retval = esirisc_flash_control(bank, CONTROL_ERC);
if (retval != ERROR_OK)
LOG_ERROR("%s: failed to erase reference cell", bank->name);
esirisc_flash_enable_protect(bank);
(void)esirisc_flash_enable_protect(bank);
return retval;
}
static int esirisc_flash_protect(struct flash_bank *bank, int set, int first, int last)
{
struct target *target = bank->target;
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
if (set)
esirisc_flash_enable_protect(bank);
else
esirisc_flash_disable_protect(bank);
return ERROR_OK;
}
static int esirisc_flash_fill_pb(struct flash_bank *bank,
const uint8_t *buffer, uint32_t count)
{
@@ -375,7 +367,7 @@ static int esirisc_flash_write(struct flash_bank *bank,
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
esirisc_flash_disable_protect(bank);
(void)esirisc_flash_disable_protect(bank);
/*
* The address register is auto-incremented based on the contents of
@@ -406,7 +398,7 @@ static int esirisc_flash_write(struct flash_bank *bank,
count -= num_bytes;
}
esirisc_flash_enable_protect(bank);
(void)esirisc_flash_enable_protect(bank);
return retval;
}
@@ -432,11 +424,11 @@ static int esirisc_flash_init(struct flash_bank *bank)
uint32_t value;
int retval;
esirisc_flash_disable_protect(bank);
(void)esirisc_flash_disable_protect(bank);
/* initialize timing registers */
value = TIMING0_F(esirisc_flash_num_cycles(bank, TNVH)) |
TIMING0_R(esirisc_info->wait_states);
value = TIMING0_F(esirisc_flash_num_cycles(bank, TNVH))
| TIMING0_R(esirisc_info->wait_states);
LOG_DEBUG("TIMING0: 0x%" PRIx32, value);
target_write_u32(target, esirisc_info->cfg + TIMING0, value);
@@ -446,9 +438,9 @@ static int esirisc_flash_init(struct flash_bank *bank)
LOG_DEBUG("TIMING1: 0x%" PRIx32, value);
target_write_u32(target, esirisc_info->cfg + TIMING1, value);
value = TIMING2_T(esirisc_flash_num_cycles(bank, 10)) |
TIMING2_H(esirisc_flash_num_cycles(bank, 100)) |
TIMING2_P(esirisc_flash_num_cycles(bank, TPROG));
value = TIMING2_T(esirisc_flash_num_cycles(bank, 10))
| TIMING2_H(esirisc_flash_num_cycles(bank, 100))
| TIMING2_P(esirisc_flash_num_cycles(bank, TPROG));
LOG_DEBUG("TIMING2: 0x%" PRIx32, value);
target_write_u32(target, esirisc_info->cfg + TIMING2, value);
@@ -458,7 +450,7 @@ static int esirisc_flash_init(struct flash_bank *bank)
if (retval != ERROR_OK)
LOG_ERROR("%s: failed to recall trim code", bank->name);
esirisc_flash_enable_protect(bank);
(void)esirisc_flash_enable_protect(bank);
return retval;
}
@@ -475,13 +467,6 @@ static int esirisc_flash_probe(struct flash_bank *bank)
bank->num_sectors = bank->size / PAGE_SIZE;
bank->sectors = alloc_block_array(0, PAGE_SIZE, bank->num_sectors);
/*
* Register write protection is enforced using a single protection
* block for the entire bank. This is as good as it gets.
*/
bank->num_prot_blocks = 1;
bank->prot_blocks = alloc_block_array(0, bank->size, bank->num_prot_blocks);
retval = esirisc_flash_init(bank);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to initialize bank", bank->name);
@@ -503,23 +488,6 @@ static int esirisc_flash_auto_probe(struct flash_bank *bank)
return esirisc_flash_probe(bank);
}
static int esirisc_flash_protect_check(struct flash_bank *bank)
{
struct esirisc_flash_bank *esirisc_info = bank->driver_priv;
struct target *target = bank->target;
uint32_t control;
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
target_read_u32(target, esirisc_info->cfg + CONTROL, &control);
/* single protection block (also see: esirisc_flash_probe()) */
bank->prot_blocks[0].is_protected = !!(control & CONTROL_WP);
return ERROR_OK;
}
static int esirisc_flash_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct esirisc_flash_bank *esirisc_info = bank->driver_priv;
@@ -579,14 +547,14 @@ static const struct command_registration esirisc_flash_exec_command_handlers[] =
.name = "mass_erase",
.handler = handle_esirisc_flash_mass_erase_command,
.mode = COMMAND_EXEC,
.help = "erases all pages in data memory",
.help = "erase all pages in data memory",
.usage = "bank_id",
},
{
.name = "ref_erase",
.handler = handle_esirisc_flash_ref_erase_command,
.mode = COMMAND_EXEC,
.help = "erases reference cell (uncommon)",
.help = "erase reference cell (uncommon)",
.usage = "bank_id",
},
COMMAND_REGISTRATION_DONE
@@ -594,9 +562,9 @@ static const struct command_registration esirisc_flash_exec_command_handlers[] =
static const struct command_registration esirisc_flash_command_handlers[] = {
{
.name = "esirisc_flash",
.mode = COMMAND_ANY,
.help = "eSi-RISC flash command group",
.name = "flash",
.mode = COMMAND_EXEC,
.help = "eSi-TSMC Flash command group",
.usage = "",
.chain = esirisc_flash_exec_command_handlers,
},
@@ -605,17 +573,15 @@ static const struct command_registration esirisc_flash_command_handlers[] = {
struct flash_driver esirisc_flash = {
.name = "esirisc",
.commands = esirisc_flash_command_handlers,
.usage = "flash bank bank_id 'esirisc' base_address size_bytes 0 0 target "
"cfg_address clock_hz wait_states",
.flash_bank_command = esirisc_flash_bank_command,
.erase = esirisc_flash_erase,
.protect = esirisc_flash_protect,
.write = esirisc_flash_write,
.read = default_flash_read,
.probe = esirisc_flash_probe,
.auto_probe = esirisc_flash_auto_probe,
.erase_check = default_flash_blank_check,
.protect_check = esirisc_flash_protect_check,
.info = esirisc_flash_info,
.free_driver_priv = default_flash_free_driver_priv,
};
-13
View File
@@ -85,12 +85,6 @@ static int faux_erase(struct flash_bank *bank, int first, int last)
return ERROR_OK;
}
static int faux_protect(struct flash_bank *bank, int set, int first, int last)
{
LOG_USER("set protection sector %d to %d to %s", first, last, set ? "on" : "off");
return ERROR_OK;
}
static int faux_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
{
struct faux_flash_bank *info = bank->driver_priv;
@@ -98,11 +92,6 @@ static int faux_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t o
return ERROR_OK;
}
static int faux_protect_check(struct flash_bank *bank)
{
return ERROR_OK;
}
static int faux_info(struct flash_bank *bank, char *buf, int buf_size)
{
snprintf(buf, buf_size, "faux flash driver");
@@ -129,13 +118,11 @@ struct flash_driver faux_flash = {
.commands = faux_command_handlers,
.flash_bank_command = faux_flash_bank_command,
.erase = faux_erase,
.protect = faux_protect,
.write = faux_write,
.read = default_flash_read,
.probe = faux_probe,
.auto_probe = faux_probe,
.erase_check = default_flash_blank_check,
.protect_check = faux_protect_check,
.info = faux_info,
.free_driver_priv = default_flash_free_driver_priv,
};
+19 -5
View File
@@ -391,6 +391,9 @@ static int fespi_erase(struct flash_bank *bank, int first, int last)
}
}
if (fespi_info->dev->erase_cmd == 0x00)
return ERROR_FLASH_OPER_UNSUPPORTED;
if (fespi_write_reg(bank, FESPI_REG_TXCTRL, FESPI_TXWM(1)) != ERROR_OK)
return ERROR_FAIL;
retval = fespi_txwm_wait(bank);
@@ -795,7 +798,9 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
data_wa_size /= 2;
}
page_size = fespi_info->dev->pagesize;
/* If no valid page_size, use reasonable default. */
page_size = fespi_info->dev->pagesize ?
fespi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
fespi_txwm_wait(bank);
@@ -911,6 +916,7 @@ static int fespi_probe(struct flash_bank *bank)
uint32_t id = 0; /* silence uninitialized warning */
const struct fespi_target *target_device;
int retval;
uint32_t sectorsize;
if (fespi_info->probed)
free(bank->sectors);
@@ -972,9 +978,17 @@ static int fespi_probe(struct flash_bank *bank)
/* Set correct size value */
bank->size = fespi_info->dev->size_in_bytes;
if (bank->size <= (1UL << 16))
LOG_WARNING("device needs 2-byte addresses - not implemented");
if (bank->size > (1UL << 24))
LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
/* if no sectors, treat whole bank as single sector */
sectorsize = fespi_info->dev->sectorsize ?
fespi_info->dev->sectorsize : fespi_info->dev->size_in_bytes;
/* create and fill sectors array */
bank->num_sectors =
fespi_info->dev->size_in_bytes / fespi_info->dev->sectorsize;
bank->num_sectors = fespi_info->dev->size_in_bytes / sectorsize;
sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
if (sectors == NULL) {
LOG_ERROR("not enough memory");
@@ -982,8 +996,8 @@ static int fespi_probe(struct flash_bank *bank)
}
for (int sector = 0; sector < bank->num_sectors; sector++) {
sectors[sector].offset = sector * fespi_info->dev->sectorsize;
sectors[sector].size = fespi_info->dev->sectorsize;
sectors[sector].offset = sector * sectorsize;
sectors[sector].size = sectorsize;
sectors[sector].is_erased = -1;
sectors[sector].is_protected = 0;
}
-6
View File
@@ -537,11 +537,6 @@ static int fm4_auto_probe(struct flash_bank *bank)
return fm4_probe(bank);
}
static int fm4_protect_check(struct flash_bank *bank)
{
return ERROR_OK;
}
static int fm4_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
{
struct fm4_flash_bank *fm4_bank = bank->driver_priv;
@@ -714,7 +709,6 @@ struct flash_driver fm4_flash = {
.info = fm4_get_info_command,
.probe = fm4_probe,
.auto_probe = fm4_auto_probe,
.protect_check = fm4_protect_check,
.read = default_flash_read,
.erase = fm4_flash_erase,
.erase_check = default_flash_blank_check,
+24 -19
View File
@@ -166,7 +166,7 @@ static int jtagspi_probe(struct flash_bank *bank)
struct jtagspi_flash_bank *info = bank->driver_priv;
struct flash_sector *sectors;
uint8_t in_buf[3];
uint32_t id;
uint32_t id, sectorsize;
if (info->probed)
free(bank->sectors);
@@ -199,10 +199,17 @@ static int jtagspi_probe(struct flash_bank *bank)
/* Set correct size value */
bank->size = info->dev->size_in_bytes;
if (bank->size <= (1UL << 16))
LOG_WARNING("device needs 2-byte addresses - not implemented");
if (bank->size > (1UL << 24))
LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
/* if no sectors, treat whole bank as single sector */
sectorsize = info->dev->sectorsize ?
info->dev->sectorsize : info->dev->size_in_bytes;
/* create and fill sectors array */
bank->num_sectors =
info->dev->size_in_bytes / info->dev->sectorsize;
bank->num_sectors = info->dev->size_in_bytes / sectorsize;
sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
if (sectors == NULL) {
LOG_ERROR("not enough memory");
@@ -210,8 +217,8 @@ static int jtagspi_probe(struct flash_bank *bank)
}
for (int sector = 0; sector < bank->num_sectors; sector++) {
sectors[sector].offset = sector * info->dev->sectorsize;
sectors[sector].size = info->dev->sectorsize;
sectors[sector].offset = sector * sectorsize;
sectors[sector].size = sectorsize;
sectors[sector].is_erased = -1;
sectors[sector].is_protected = 0;
}
@@ -269,6 +276,9 @@ static int jtagspi_bulk_erase(struct flash_bank *bank)
int retval;
int64_t t0 = timeval_ms();
if (info->dev->chip_erase_cmd == 0x00)
return ERROR_FLASH_OPER_UNSUPPORTED;
retval = jtagspi_write_enable(bank);
if (retval != ERROR_OK)
return retval;
@@ -328,6 +338,9 @@ static int jtagspi_erase(struct flash_bank *bank, int first, int last)
LOG_WARNING("Bulk flash erase failed. Falling back to sector erase.");
}
if (info->dev->erase_cmd == 0x00)
return ERROR_FLASH_OPER_UNSUPPORTED;
for (sector = first; sector <= last; sector++) {
retval = jtagspi_sector_erase(bank, sector);
if (retval != ERROR_OK) {
@@ -343,21 +356,11 @@ static int jtagspi_protect(struct flash_bank *bank, int set, int first, int last
{
int sector;
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
LOG_ERROR("Flash sector invalid");
return ERROR_FLASH_SECTOR_INVALID;
}
for (sector = first; sector <= last; sector++)
bank->sectors[sector].is_protected = set;
return ERROR_OK;
}
static int jtagspi_protect_check(struct flash_bank *bank)
{
return ERROR_OK;
}
static int jtagspi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
{
struct jtagspi_flash_bank *info = bank->driver_priv;
@@ -386,16 +389,19 @@ static int jtagspi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_
{
struct jtagspi_flash_bank *info = bank->driver_priv;
int retval;
uint32_t n;
uint32_t n, pagesize;
if (!(info->probed)) {
LOG_ERROR("Flash bank not yet probed.");
return ERROR_FLASH_BANK_NOT_PROBED;
}
for (n = 0; n < count; n += info->dev->pagesize) {
/* if no write pagesize, use reasonable default */
pagesize = info->dev->pagesize ? info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
for (n = 0; n < count; n += pagesize) {
retval = jtagspi_page_write(bank, buffer + n, offset + n,
MIN(count - n, info->dev->pagesize));
MIN(count - n, pagesize));
if (retval != ERROR_OK) {
LOG_ERROR("page write error");
return retval;
@@ -431,7 +437,6 @@ struct flash_driver jtagspi_flash = {
.probe = jtagspi_probe,
.auto_probe = jtagspi_probe,
.erase_check = default_flash_blank_check,
.protect_check = jtagspi_protect_check,
.info = jtagspi_info,
.free_driver_priv = default_flash_free_driver_priv,
};
+1 -1
View File
@@ -1035,7 +1035,7 @@ static int kinetis_disable_wdog_algo(struct target *target, size_t code_size, co
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARM_MODE_THREAD;
init_reg_param(&reg_params[0], "r0", 32, PARAM_IN);
init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
buf_set_u32(reg_params[0].value, 0, 32, wdog_base);
retval = target_run_algorithm(target, 0, NULL, 1, reg_params,
+56 -15
View File
@@ -12,6 +12,9 @@
* by Nemui Trinomius *
* nemuisan_kawausogasuki@live.jp *
* *
* LPC8N04/HNS31xx support Copyright (C) 2018 *
* by Jean-Christian de Rivaz jcdr [at] innodelec [dot] ch *
* *
* 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 *
* the Free Software Foundation; either version 2 of the License, or *
@@ -38,7 +41,7 @@
/**
* @file
* flash programming support for NXP LPC8xx,LPC1xxx,LPC4xxx,LP5410x and LPC2xxx devices.
* flash programming support for NXP LPC8xx,LPC1xxx,LPC4xxx,LP5410x,LPC2xxx and NHS31xx devices.
*
* @todo Provide a way to update CCLK after declaring the flash bank. The value which is correct after chip reset will
* rarely still work right after the clocks switch to use the PLL (e.g. 4MHz --> 100 MHz).
@@ -77,6 +80,9 @@
* lpc800:
* - 810 | 1 | 2 (tested with LPC810/LPC811/LPC812)
* - 822 | 4 (tested with LPC824)
* - 8N04
* - NHS31xx (tested with NHS3100)
* - 844 | 5 (tested with LPC845)
*
* lpc1100:
* - 11xx
@@ -111,6 +117,8 @@
* - 408x
* - 81x
* - 82x
* - 8N04
* - NHS31xx
*/
/* Part IDs for autodetection */
@@ -257,6 +265,20 @@
#define LPC824_201 0x00008241
#define LPC824_201_1 0x00008242
#define LPC8N04 0x00008A04
#define NHS3100 0x4e310020
#define NHS3152 0x4e315220
#define NHS3153 0x4e315320 /* Only specified in Rev.1 of the datasheet */
#define LPC844_201 0x00008441
#define LPC844_201_1 0x00008442
#define LPC844_201_2 0x00008444
#define LPC845_301 0x00008451
#define LPC845_301_1 0x00008452
#define LPC845_301_2 0x00008453
#define LPC845_301_3 0x00008454
#define IAP_CODE_LEN 0x34
#define LPC11xx_REG_SECTORS 24
@@ -282,6 +304,7 @@ struct lpc2000_flash_bank {
int checksum_vector;
uint32_t iap_max_stack;
uint32_t lpc4300_bank;
uint32_t iap_entry_alternative;
bool probed;
};
@@ -526,10 +549,18 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
case 16 * 1024:
bank->num_sectors = 16;
break;
case 30 * 1024:
lpc2000_info->cmd51_max_buffer = 1024; /* For LPC8N04 and NHS31xx, have 8kB of SRAM */
bank->num_sectors = 30; /* There have only 30kB of writable Flash out of 32kB */
break;
case 32 * 1024:
lpc2000_info->cmd51_max_buffer = 1024; /* For LPC824, has 8kB of SRAM */
bank->num_sectors = 32;
break;
case 64 * 1024:
lpc2000_info->cmd51_max_buffer = 1024; /* For LPC844, has 8kB of SRAM */
bank->num_sectors = 64;
break;
default:
LOG_ERROR("BUG: unknown bank->size encountered");
exit(-1);
@@ -741,6 +772,9 @@ static int lpc2000_iap_call(struct flash_bank *bank, struct working_area *iap_wo
exit(-1);
}
if (lpc2000_info->iap_entry_alternative != 0x0)
iap_entry_point = lpc2000_info->iap_entry_alternative;
struct mem_param mem_params[2];
/* command parameter table */
@@ -938,6 +972,8 @@ FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command)
if (strcmp(CMD_ARGV[8], "calc_checksum") == 0)
lpc2000_info->calc_checksum = 1;
}
if (CMD_ARGC >= 10 && !lpc2000_info->iap_entry_alternative)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[9], lpc2000_info->iap_entry_alternative);
return ERROR_OK;
}
@@ -1018,12 +1054,6 @@ static int lpc2000_erase(struct flash_bank *bank, int first, int last)
return retval;
}
static int lpc2000_protect(struct flash_bank *bank, int set, int first, int last)
{
/* can't protect/unprotect on the lpc2000 */
return ERROR_OK;
}
static int lpc2000_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
{
struct target *target = bank->target;
@@ -1458,6 +1488,25 @@ static int lpc2000_auto_probe_flash(struct flash_bank *bank)
bank->size = 32 * 1024;
break;
case LPC8N04:
case NHS3100:
case NHS3152:
case NHS3153:
lpc2000_info->variant = lpc800;
bank->size = 30 * 1024;
break;
case LPC844_201:
case LPC844_201_1:
case LPC844_201_2:
case LPC845_301:
case LPC845_301_1:
case LPC845_301_2:
case LPC845_301_3:
lpc2000_info->variant = lpc800;
bank->size = 64 * 1024;
break;
default:
LOG_ERROR("BUG: unknown Part ID encountered: 0x%" PRIx32, part_id);
exit(-1);
@@ -1501,12 +1550,6 @@ static int lpc2000_erase_check(struct flash_bank *bank)
return lpc2000_iap_blank_check(bank, 0, bank->num_sectors - 1);
}
static int lpc2000_protect_check(struct flash_bank *bank)
{
/* sectors are always protected */
return ERROR_OK;
}
static int get_lpc2000_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
@@ -1571,13 +1614,11 @@ struct flash_driver lpc2000_flash = {
.commands = lpc2000_command_handlers,
.flash_bank_command = lpc2000_flash_bank_command,
.erase = lpc2000_erase,
.protect = lpc2000_protect,
.write = lpc2000_write,
.read = default_flash_read,
.probe = lpc2000_probe,
.auto_probe = lpc2000_probe,
.erase_check = lpc2000_erase_check,
.protect_check = lpc2000_protect_check,
.info = get_lpc2000_info,
.free_driver_priv = default_flash_free_driver_priv,
};
+2 -12
View File
@@ -167,6 +167,7 @@ static int lpc288x_read_part_info(struct flash_bank *bank)
return ERROR_OK;
}
/* TODO: Revisit! Is it impossible to read protection status? */
static int lpc288x_protect_check(struct flash_bank *bank)
{
return ERROR_OK;
@@ -231,17 +232,6 @@ static uint32_t lpc288x_system_ready(struct flash_bank *bank)
return ERROR_OK;
}
static int lpc288x_erase_check(struct flash_bank *bank)
{
uint32_t status = lpc288x_system_ready(bank); /* probed? halted? */
if (status != ERROR_OK) {
LOG_INFO("Processor not halted/not probed");
return status;
}
return ERROR_OK;
}
static int lpc288x_erase(struct flash_bank *bank, int first, int last)
{
uint32_t status;
@@ -431,7 +421,7 @@ struct flash_driver lpc288x_flash = {
.read = default_flash_read,
.probe = lpc288x_probe,
.auto_probe = lpc288x_probe,
.erase_check = lpc288x_erase_check,
.erase_check = default_flash_blank_check,
.protect_check = lpc288x_protect_check,
.free_driver_priv = default_flash_free_driver_priv,
};
+7 -13
View File
@@ -1035,18 +1035,13 @@ static int lpc2900_erase(struct flash_bank *bank, int first, int last)
return ERROR_OK;
}
static int lpc2900_protect(struct flash_bank *bank, int set, int first, int last)
{
/* This command is not supported.
* "Protection" in LPC2900 terms is handled transparently. Sectors will
* automatically be unprotected as needed.
* Instead we use the concept of sector security. A secured sector is shown
* as "protected" in OpenOCD. Sector security is a permanent feature, and
* cannot be disabled once activated.
*/
return ERROR_OK;
}
/* lpc2900_protect command is not supported.
* "Protection" in LPC2900 terms is handled transparently. Sectors will
* automatically be unprotected as needed.
* Instead we use the concept of sector security. A secured sector is shown
* as "protected" in OpenOCD. Sector security is a permanent feature, and
* cannot be disabled once activated.
*/
/**
* Write data to flash.
@@ -1591,7 +1586,6 @@ struct flash_driver lpc2900_flash = {
.commands = lpc2900_command_handlers,
.flash_bank_command = lpc2900_flash_bank_command,
.erase = lpc2900_erase,
.protect = lpc2900_protect,
.write = lpc2900_write,
.read = default_flash_read,
.probe = lpc2900_probe,
+21 -5
View File
@@ -387,6 +387,9 @@ static int lpcspifi_bulk_erase(struct flash_bank *bank)
uint32_t value;
int retval = ERROR_OK;
if (lpcspifi_info->dev->chip_erase_cmd == 0x00)
return ERROR_FLASH_OPER_UNSUPPORTED;
retval = lpcspifi_set_sw_mode(bank);
if (retval == ERROR_OK)
@@ -460,6 +463,9 @@ static int lpcspifi_erase(struct flash_bank *bank, int first, int last)
LOG_WARNING("Bulk flash erase failed. Falling back to sector-by-sector erase.");
}
if (lpcspifi_info->dev->erase_cmd == 0x00)
return ERROR_FLASH_OPER_UNSUPPORTED;
retval = lpcspifi_set_hw_mode(bank);
if (retval != ERROR_OK)
return retval;
@@ -613,7 +619,9 @@ static int lpcspifi_write(struct flash_bank *bank, const uint8_t *buffer,
}
}
page_size = lpcspifi_info->dev->pagesize;
/* if no valid page_size, use reasonable default */
page_size = lpcspifi_info->dev->pagesize ?
lpcspifi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
retval = lpcspifi_set_hw_mode(bank);
if (retval != ERROR_OK)
@@ -839,6 +847,7 @@ static int lpcspifi_probe(struct flash_bank *bank)
struct flash_sector *sectors;
uint32_t id = 0; /* silence uninitialized warning */
int retval;
uint32_t sectorsize;
/* If we've already probed, we should be fine to skip this time. */
if (lpcspifi_info->probed)
@@ -876,10 +885,17 @@ static int lpcspifi_probe(struct flash_bank *bank)
/* Set correct size value */
bank->size = lpcspifi_info->dev->size_in_bytes;
if (bank->size <= (1UL << 16))
LOG_WARNING("device needs 2-byte addresses - not implemented");
if (bank->size > (1UL << 24))
LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
/* if no sectors, treat whole bank as single sector */
sectorsize = lpcspifi_info->dev->sectorsize ?
lpcspifi_info->dev->sectorsize : lpcspifi_info->dev->size_in_bytes;
/* create and fill sectors array */
bank->num_sectors =
lpcspifi_info->dev->size_in_bytes / lpcspifi_info->dev->sectorsize;
bank->num_sectors = lpcspifi_info->dev->size_in_bytes / sectorsize;
sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
if (sectors == NULL) {
LOG_ERROR("not enough memory");
@@ -887,8 +903,8 @@ static int lpcspifi_probe(struct flash_bank *bank)
}
for (int sector = 0; sector < bank->num_sectors; sector++) {
sectors[sector].offset = sector * lpcspifi_info->dev->sectorsize;
sectors[sector].size = lpcspifi_info->dev->sectorsize;
sectors[sector].offset = sector * sectorsize;
sectors[sector].size = sectorsize;
sectors[sector].is_erased = -1;
sectors[sector].is_protected = 0;
}
-12
View File
@@ -86,11 +86,6 @@ FLASH_BANK_COMMAND_HANDLER(mdr_flash_bank_command)
return ERROR_OK;
}
static int mdr_protect_check(struct flash_bank *bank)
{
return ERROR_OK;
}
static int mdr_mass_erase(struct flash_bank *bank)
{
struct target *target = bank->target;
@@ -217,11 +212,6 @@ reset_pg_and_lock:
return retval;
}
static int mdr_protect(struct flash_bank *bank, int set, int first, int last)
{
return ERROR_OK;
}
static int mdr_write_block(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
@@ -625,13 +615,11 @@ struct flash_driver mdr_flash = {
"<type>: 0 for main memory, 1 for info memory",
.flash_bank_command = mdr_flash_bank_command,
.erase = mdr_erase,
.protect = mdr_protect,
.write = mdr_write,
.read = mdr_read,
.probe = mdr_probe,
.auto_probe = mdr_auto_probe,
.erase_check = default_flash_blank_check,
.protect_check = mdr_protect_check,
.info = get_mdr_info,
.free_driver_priv = default_flash_free_driver_priv,
};
+22 -14
View File
@@ -503,6 +503,9 @@ static int mrvlqspi_bulk_erase(struct flash_bank *bank)
int retval;
struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv;
if (mrvlqspi_info->dev->chip_erase_cmd == 0x00)
return ERROR_FLASH_OPER_UNSUPPORTED;
/* Set flash write enable */
retval = mrvlqspi_set_write_status(bank, WRITE_ENABLE);
if (retval != ERROR_OK)
@@ -570,6 +573,9 @@ static int mrvlqspi_flash_erase(struct flash_bank *bank, int first, int last)
" Falling back to sector-by-sector erase.");
}
if (mrvlqspi_info->dev->erase_cmd == 0x00)
return ERROR_FLASH_OPER_UNSUPPORTED;
for (sector = first; sector <= last; sector++) {
retval = mrvlqspi_block_erase(bank,
sector * mrvlqspi_info->dev->sectorsize);
@@ -619,7 +625,9 @@ static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer,
}
}
page_size = mrvlqspi_info->dev->pagesize;
/* if no valid page_size, use reasonable default */
page_size = mrvlqspi_info->dev->pagesize ?
mrvlqspi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
/* See contrib/loaders/flash/mrvlqspi.S for src */
static const uint8_t mrvlqspi_flash_write_code[] = {
@@ -826,6 +834,7 @@ static int mrvlqspi_probe(struct flash_bank *bank)
uint32_t id = 0;
int retval;
struct flash_sector *sectors;
uint32_t sectorsize;
/* If we've already probed, we should be fine to skip this time. */
if (mrvlqspi_info->probed)
@@ -859,12 +868,20 @@ static int mrvlqspi_probe(struct flash_bank *bank)
LOG_INFO("Found flash device \'%s\' ID 0x%08" PRIx32,
mrvlqspi_info->dev->name, mrvlqspi_info->dev->device_id);
/* Set correct size value */
bank->size = mrvlqspi_info->dev->size_in_bytes;
if (bank->size <= (1UL << 16))
LOG_WARNING("device needs 2-byte addresses - not implemented");
if (bank->size > (1UL << 24))
LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
/* if no sectors, treat whole bank as single sector */
sectorsize = mrvlqspi_info->dev->sectorsize ?
mrvlqspi_info->dev->sectorsize : mrvlqspi_info->dev->size_in_bytes;
/* create and fill sectors array */
bank->num_sectors = mrvlqspi_info->dev->size_in_bytes /
mrvlqspi_info->dev->sectorsize;
bank->num_sectors = mrvlqspi_info->dev->size_in_bytes / sectorsize;
sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
if (sectors == NULL) {
LOG_ERROR("not enough memory");
@@ -872,9 +889,8 @@ static int mrvlqspi_probe(struct flash_bank *bank)
}
for (int sector = 0; sector < bank->num_sectors; sector++) {
sectors[sector].offset =
sector * mrvlqspi_info->dev->sectorsize;
sectors[sector].size = mrvlqspi_info->dev->sectorsize;
sectors[sector].offset = sector * sectorsize;
sectors[sector].size = sectorsize;
sectors[sector].is_erased = -1;
sectors[sector].is_protected = 0;
}
@@ -899,12 +915,6 @@ static int mrvlqspi_flash_erase_check(struct flash_bank *bank)
return ERROR_OK;
}
static int mrvlqspi_protect_check(struct flash_bank *bank)
{
/* Not implemented yet */
return ERROR_OK;
}
int mrvlqspi_get_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv;
@@ -947,13 +957,11 @@ struct flash_driver mrvlqspi_flash = {
.name = "mrvlqspi",
.flash_bank_command = mrvlqspi_flash_bank_command,
.erase = mrvlqspi_flash_erase,
.protect = NULL,
.write = mrvlqspi_flash_write,
.read = mrvlqspi_flash_read,
.probe = mrvlqspi_probe,
.auto_probe = mrvlqspi_auto_probe,
.erase_check = mrvlqspi_flash_erase_check,
.protect_check = mrvlqspi_protect_check,
.info = mrvlqspi_get_info,
.free_driver_priv = default_flash_free_driver_priv,
};
-13
View File
@@ -655,12 +655,6 @@ static int msp432_erase(struct flash_bank *bank, int first, int last)
return retval;
}
static int msp432_protect(struct flash_bank *bank, int set, int first,
int last)
{
return ERROR_OK;
}
static int msp432_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
@@ -985,11 +979,6 @@ static int msp432_auto_probe(struct flash_bank *bank)
return retval;
}
static int msp432_protect_check(struct flash_bank *bank)
{
return ERROR_OK;
}
static int msp432_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct msp432_bank *msp432_bank = bank->driver_priv;
@@ -1091,13 +1080,11 @@ struct flash_driver msp432_flash = {
.commands = msp432_command_handlers,
.flash_bank_command = msp432_flash_bank_command,
.erase = msp432_erase,
.protect = msp432_protect,
.write = msp432_write,
.read = default_flash_read,
.probe = msp432_probe,
.auto_probe = msp432_auto_probe,
.erase_check = default_flash_blank_check,
.protect_check = msp432_protect_check,
.info = msp432_info,
.free_driver_priv = msp432_flash_free_driver_priv,
};
+2 -1
View File
@@ -211,6 +211,7 @@ static const struct nrf5_device_spec nrf5_known_devices_table[] = {
/* nRF52832 Devices */
NRF5_DEVICE_DEF(0x00C7, "52832", "QFAA", "B0", 512),
NRF5_DEVICE_DEF(0x0139, "52832", "QFAA", "E0", 512),
NRF5_DEVICE_DEF(0x00E3, "52832", "CIAA", "B0", 512),
/* nRF52840 Devices */
NRF5_DEVICE_DEF(0x0150, "52840", "QIAA", "C0", 1024),
@@ -248,7 +249,7 @@ static int nrf5_wait_for_nvmc(struct nrf5_info *chip)
{
uint32_t ready;
int res;
int timeout_ms = 200;
int timeout_ms = 340;
int64_t ts_start = timeval_ms();
do {
+1 -18
View File
@@ -30,16 +30,6 @@ struct ocl_priv {
unsigned int bufalign;
};
static int ocl_erase_check(struct flash_bank *bank)
{
return ERROR_OK;
}
static int ocl_protect_check(struct flash_bank *bank)
{
return ERROR_OK;
}
/* flash_bank ocl 0 0 0 0 <target#> */
FLASH_BANK_COMMAND_HANDLER(ocl_flash_bank_command)
{
@@ -111,11 +101,6 @@ static int ocl_erase(struct flash_bank *bank, int first, int last)
return ERROR_OK;
}
static int ocl_protect(struct flash_bank *bank, int set, int first, int last)
{
return ERROR_OK;
}
static int ocl_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
{
struct ocl_priv *ocl = bank->driver_priv;
@@ -333,12 +318,10 @@ struct flash_driver ocl_flash = {
.name = "ocl",
.flash_bank_command = ocl_flash_bank_command,
.erase = ocl_erase,
.protect = ocl_protect,
.write = ocl_write,
.read = default_flash_read,
.probe = ocl_probe,
.erase_check = ocl_erase_check,
.protect_check = ocl_protect_check,
.erase_check = default_flash_blank_check,
.auto_probe = ocl_auto_probe,
.free_driver_priv = default_flash_free_driver_priv,
};
-22
View File
@@ -753,16 +753,6 @@ static int psoc5lp_nvl_write(struct flash_bank *bank,
return ERROR_OK;
}
static int psoc5lp_nvl_protect_check(struct flash_bank *bank)
{
int i;
for (i = 0; i < bank->num_sectors; i++)
bank->sectors[i].is_protected = -1;
return ERROR_OK;
}
static int psoc5lp_nvl_get_info_command(struct flash_bank *bank,
char *buf, int buf_size)
{
@@ -855,7 +845,6 @@ struct flash_driver psoc5lp_nvl_flash = {
.info = psoc5lp_nvl_get_info_command,
.probe = psoc5lp_nvl_probe,
.auto_probe = psoc5lp_nvl_auto_probe,
.protect_check = psoc5lp_nvl_protect_check,
.read = psoc5lp_nvl_read,
.erase = psoc5lp_nvl_erase,
.erase_check = psoc5lp_nvl_erase_check,
@@ -945,16 +934,6 @@ static int psoc5lp_eeprom_write(struct flash_bank *bank,
return ERROR_OK;
}
static int psoc5lp_eeprom_protect_check(struct flash_bank *bank)
{
int i;
for (i = 0; i < bank->num_sectors; i++)
bank->sectors[i].is_protected = -1;
return ERROR_OK;
}
static int psoc5lp_eeprom_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
{
struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
@@ -1064,7 +1043,6 @@ struct flash_driver psoc5lp_eeprom_flash = {
.info = psoc5lp_eeprom_get_info_command,
.probe = psoc5lp_eeprom_probe,
.auto_probe = psoc5lp_eeprom_auto_probe,
.protect_check = psoc5lp_eeprom_protect_check,
.read = default_flash_read,
.erase = psoc5lp_eeprom_erase,
.erase_check = default_flash_blank_check,
+117 -54
View File
@@ -1,4 +1,7 @@
/***************************************************************************
* Copyright (C) 2018 by Andreas Bolsch *
* andreas.bolsch@mni.thm.de *
* *
* Copyright (C) 2012 by George Harris *
* george@luminairecoffee.com *
* *
@@ -30,58 +33,118 @@
/* Shared table of known SPI flash devices for SPI-based flash drivers. Taken
* from device datasheets and Linux SPI flash drivers. */
const struct flash_device flash_devices[] = {
/* name, erase_cmd, chip_erase_cmd, device_id, pagesize, sectorsize, size_in_bytes */
FLASH_ID("st m25p05", 0xd8, 0xc7, 0x00102020, 0x80, 0x8000, 0x10000),
FLASH_ID("st m25p10", 0xd8, 0xc7, 0x00112020, 0x80, 0x8000, 0x20000),
FLASH_ID("st m25p20", 0xd8, 0xc7, 0x00122020, 0x100, 0x10000, 0x40000),
FLASH_ID("st m25p40", 0xd8, 0xc7, 0x00132020, 0x100, 0x10000, 0x80000),
FLASH_ID("st m25p80", 0xd8, 0xc7, 0x00142020, 0x100, 0x10000, 0x100000),
FLASH_ID("st m25p16", 0xd8, 0xc7, 0x00152020, 0x100, 0x10000, 0x200000),
FLASH_ID("st m25p32", 0xd8, 0xc7, 0x00162020, 0x100, 0x10000, 0x400000),
FLASH_ID("st m25p64", 0xd8, 0xc7, 0x00172020, 0x100, 0x10000, 0x800000),
FLASH_ID("st m25p128", 0xd8, 0xc7, 0x00182020, 0x100, 0x40000, 0x1000000),
FLASH_ID("st m45pe10", 0xd8, 0xd8, 0x00114020, 0x100, 0x10000, 0x20000),
FLASH_ID("st m45pe20", 0xd8, 0xd8, 0x00124020, 0x100, 0x10000, 0x40000),
FLASH_ID("st m45pe40", 0xd8, 0xd8, 0x00134020, 0x100, 0x10000, 0x80000),
FLASH_ID("st m45pe80", 0xd8, 0xd8, 0x00144020, 0x100, 0x10000, 0x100000),
FLASH_ID("sp s25fl004", 0xd8, 0xc7, 0x00120201, 0x100, 0x10000, 0x80000),
FLASH_ID("sp s25fl008", 0xd8, 0xc7, 0x00130201, 0x100, 0x10000, 0x100000),
FLASH_ID("sp s25fl016", 0xd8, 0xc7, 0x00140201, 0x100, 0x10000, 0x200000),
FLASH_ID("sp s25fl116k", 0xd8, 0xc7, 0x00154001, 0x100, 0x10000, 0x200000),
FLASH_ID("sp s25fl032", 0xd8, 0xc7, 0x00150201, 0x100, 0x10000, 0x400000),
FLASH_ID("sp s25fl132k", 0xd8, 0xc7, 0x00164001, 0x100, 0x10000, 0x400000),
FLASH_ID("sp s25fl064", 0xd8, 0xc7, 0x00160201, 0x100, 0x10000, 0x800000),
FLASH_ID("sp s25fl164k", 0xd8, 0xc7, 0x00174001, 0x100, 0x10000, 0x800000),
FLASH_ID("sp s25fl128", 0xd8, 0xc7, 0x00182001, 0x100, 0x10000, 0x1000000),
FLASH_ID("sp s25fl256", 0xd8, 0xc7, 0x00190201, 0x100, 0x10000, 0x2000000),
FLASH_ID("cy s25fl256", 0xd8, 0xc7, 0x00196001, 0x100, 0x10000, 0x2000000),
FLASH_ID("atmel 25f512", 0x52, 0xc7, 0x0065001f, 0x80, 0x8000, 0x10000),
FLASH_ID("atmel 25f1024", 0x52, 0x62, 0x0060001f, 0x100, 0x8000, 0x20000),
FLASH_ID("atmel 25f2048", 0x52, 0x62, 0x0063001f, 0x100, 0x10000, 0x40000),
FLASH_ID("atmel 25f4096", 0x52, 0x62, 0x0064001f, 0x100, 0x10000, 0x80000),
FLASH_ID("atmel 25fs040", 0xd7, 0xc7, 0x0004661f, 0x100, 0x10000, 0x80000),
FLASH_ID("mac 25l512", 0xd8, 0xc7, 0x001020c2, 0x010, 0x10000, 0x10000),
FLASH_ID("mac 25l1005", 0xd8, 0xc7, 0x001120c2, 0x010, 0x10000, 0x20000),
FLASH_ID("mac 25l2005", 0xd8, 0xc7, 0x001220c2, 0x010, 0x10000, 0x40000),
FLASH_ID("mac 25l4005", 0xd8, 0xc7, 0x001320c2, 0x010, 0x10000, 0x80000),
FLASH_ID("mac 25l8005", 0xd8, 0xc7, 0x001420c2, 0x010, 0x10000, 0x100000),
FLASH_ID("mac 25l1605", 0xd8, 0xc7, 0x001520c2, 0x100, 0x10000, 0x200000),
FLASH_ID("mac 25l3205", 0xd8, 0xc7, 0x001620c2, 0x100, 0x10000, 0x400000),
FLASH_ID("mac 25l6405", 0xd8, 0xc7, 0x001720c2, 0x100, 0x10000, 0x800000),
FLASH_ID("micron n25q064", 0xd8, 0xc7, 0x0017ba20, 0x100, 0x10000, 0x800000),
FLASH_ID("micron n25q128", 0xd8, 0xc7, 0x0018ba20, 0x100, 0x10000, 0x1000000),
FLASH_ID("micron n25q256 3v", 0xd8, 0xc7, 0x0019ba20, 0x100, 0x10000, 0x2000000),
FLASH_ID("micron n25q256 1.8v", 0xd8, 0xc7, 0x0019bb20, 0x100, 0x10000, 0x2000000),
FLASH_ID("issi is25lp128", 0xd8, 0xc7, 0x0018609d, 0x100, 0x10000, 0x1000000),
FLASH_ID("issi is25wp256d", 0xd8, 0xc7, 0x0019709d, 0x100, 0x10000, 0x2000000),
FLASH_ID("win w25q80bv", 0xd8, 0xc7, 0x001440ef, 0x100, 0x10000, 0x100000),
FLASH_ID("win w25q32fv", 0xd8, 0xc7, 0x001640ef, 0x100, 0x10000, 0x400000),
FLASH_ID("win w25q32dw", 0xd8, 0xc7, 0x001660ef, 0x100, 0x10000, 0x400000),
FLASH_ID("win w25q64cv", 0xd8, 0xc7, 0x001740ef, 0x100, 0x10000, 0x800000),
FLASH_ID("win w25q128fv", 0xd8, 0xc7, 0x001840ef, 0x100, 0x10000, 0x1000000),
FLASH_ID("gd gd25q20", 0x20, 0xc7, 0x00c84012, 0x100, 0x1000, 0x80000),
FLASH_ID("gd gd25q16c", 0xd8, 0xc7, 0x001540c8, 0x100, 0x10000, 0x200000),
FLASH_ID("gd gd25q32c", 0xd8, 0xc7, 0x001640c8, 0x100, 0x10000, 0x400000),
FLASH_ID("gd gd25q128c", 0xd8, 0xc7, 0x001840c8, 0x100, 0x10000, 0x1000000),
FLASH_ID(NULL, 0, 0, 0, 0, 0, 0)
/* name, read_cmd, qread_cmd, pprog_cmd, erase_cmd, chip_erase_cmd, device_id,
* pagesize, sectorsize, size_in_bytes */
FLASH_ID("st m25p05", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00102020, 0x80, 0x8000, 0x10000),
FLASH_ID("st m25p10", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00112020, 0x80, 0x8000, 0x20000),
FLASH_ID("st m25p20", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00122020, 0x100, 0x10000, 0x40000),
FLASH_ID("st m25p40", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00132020, 0x100, 0x10000, 0x80000),
FLASH_ID("st m25p80", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00142020, 0x100, 0x10000, 0x100000),
FLASH_ID("st m25p16", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00152020, 0x100, 0x10000, 0x200000),
FLASH_ID("st m25p32", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00162020, 0x100, 0x10000, 0x400000),
FLASH_ID("st m25p64", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00172020, 0x100, 0x10000, 0x800000),
FLASH_ID("st m25p128", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00182020, 0x100, 0x40000, 0x1000000),
FLASH_ID("st m45pe10", 0x03, 0x00, 0x02, 0xd8, 0xd8, 0x00114020, 0x100, 0x10000, 0x20000),
FLASH_ID("st m45pe20", 0x03, 0x00, 0x02, 0xd8, 0xd8, 0x00124020, 0x100, 0x10000, 0x40000),
FLASH_ID("st m45pe40", 0x03, 0x00, 0x02, 0xd8, 0xd8, 0x00134020, 0x100, 0x10000, 0x80000),
FLASH_ID("st m45pe80", 0x03, 0x00, 0x02, 0xd8, 0xd8, 0x00144020, 0x100, 0x10000, 0x100000),
FLASH_ID("sp s25fl004", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00120201, 0x100, 0x10000, 0x80000),
FLASH_ID("sp s25fl008", 0x03, 0x08, 0x02, 0xd8, 0xc7, 0x00130201, 0x100, 0x10000, 0x100000),
FLASH_ID("sp s25fl016", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00140201, 0x100, 0x10000, 0x200000),
FLASH_ID("sp s25fl116k", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00154001, 0x100, 0x10000, 0x200000),
FLASH_ID("sp s25fl032", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00150201, 0x100, 0x10000, 0x400000),
FLASH_ID("sp s25fl132k", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00164001, 0x100, 0x10000, 0x400000),
FLASH_ID("sp s25fl064", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00160201, 0x100, 0x10000, 0x800000),
FLASH_ID("sp s25fl164k", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00174001, 0x100, 0x10000, 0x800000),
FLASH_ID("sp s25fl128s", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00182001, 0x100, 0x10000, 0x1000000),
FLASH_ID("sp s25fl256s", 0x13, 0x00, 0x12, 0xdc, 0xc7, 0x00190201, 0x100, 0x10000, 0x2000000),
FLASH_ID("sp s25fl512s", 0x13, 0x00, 0x12, 0xdc, 0xc7, 0x00200201, 0x200, 0x40000, 0x4000000),
FLASH_ID("cyp s25fl064l", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00176001, 0x100, 0x10000, 0x800000),
FLASH_ID("cyp s25fl128l", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00186001, 0x100, 0x10000, 0x1000000),
FLASH_ID("cyp s25fl256l", 0x13, 0x00, 0x12, 0xdc, 0xc7, 0x00196001, 0x100, 0x10000, 0x2000000),
FLASH_ID("atmel 25f512", 0x03, 0x00, 0x02, 0x52, 0xc7, 0x0065001f, 0x80, 0x8000, 0x10000),
FLASH_ID("atmel 25f1024", 0x03, 0x00, 0x02, 0x52, 0x62, 0x0060001f, 0x100, 0x8000, 0x20000),
FLASH_ID("atmel 25f2048", 0x03, 0x00, 0x02, 0x52, 0x62, 0x0063001f, 0x100, 0x10000, 0x40000),
FLASH_ID("atmel 25f4096", 0x03, 0x00, 0x02, 0x52, 0x62, 0x0064001f, 0x100, 0x10000, 0x80000),
FLASH_ID("atmel 25fs040", 0x03, 0x00, 0x02, 0xd7, 0xc7, 0x0004661f, 0x100, 0x10000, 0x80000),
FLASH_ID("adesto 25df081a", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0001451f, 0x100, 0x10000, 0x100000),
FLASH_ID("mac 25l512", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001020c2, 0x010, 0x10000, 0x10000),
FLASH_ID("mac 25l1005", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001120c2, 0x010, 0x10000, 0x20000),
FLASH_ID("mac 25l2005", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001220c2, 0x010, 0x10000, 0x40000),
FLASH_ID("mac 25l4005", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001320c2, 0x010, 0x10000, 0x80000),
FLASH_ID("mac 25l8005", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001420c2, 0x010, 0x10000, 0x100000),
FLASH_ID("mac 25l1605", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001520c2, 0x100, 0x10000, 0x200000),
FLASH_ID("mac 25l3205", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001620c2, 0x100, 0x10000, 0x400000),
FLASH_ID("mac 25l6405", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001720c2, 0x100, 0x10000, 0x800000),
FLASH_ID("mac 25l12845", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001820c2, 0x100, 0x10000, 0x1000000),
FLASH_ID("mac 25l25645", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001920c2, 0x100, 0x10000, 0x2000000),
FLASH_ID("mac 25l51245", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001a20c2, 0x100, 0x10000, 0x4000000),
FLASH_ID("mac 25lm51245", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x003a85c2, 0x100, 0x10000, 0x4000000),
FLASH_ID("mac 25r512f", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001028c2, 0x100, 0x10000, 0x10000),
FLASH_ID("mac 25r1035f", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001128c2, 0x100, 0x10000, 0x20000),
FLASH_ID("mac 25r2035f", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001228c2, 0x100, 0x10000, 0x40000),
FLASH_ID("mac 25r4035f", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001328c2, 0x100, 0x10000, 0x80000),
FLASH_ID("mac 25r8035f", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001428c2, 0x100, 0x10000, 0x100000),
FLASH_ID("mac 25r1635f", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001528c2, 0x100, 0x10000, 0x200000),
FLASH_ID("mac 25r3235f", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001628c2, 0x100, 0x10000, 0x400000),
FLASH_ID("mac 25r6435f", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001728c2, 0x100, 0x10000, 0x800000),
FLASH_ID("micron n25q064", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x0017ba20, 0x100, 0x10000, 0x800000),
FLASH_ID("micron n25q128", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x0018ba20, 0x100, 0x10000, 0x1000000),
FLASH_ID("micron n25q256 3v", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0019ba20, 0x100, 0x10000, 0x2000000),
FLASH_ID("micron n25q256 1.8v", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0019bb20, 0x100, 0x10000, 0x2000000),
FLASH_ID("micron mt25ql512", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0020ba20, 0x100, 0x10000, 0x4000000),
FLASH_ID("micron mt25ql01", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0021ba20, 0x100, 0x10000, 0x8000000),
FLASH_ID("micron mt25ql02", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0022ba20, 0x100, 0x10000, 0x10000000),
FLASH_ID("win w25q80bv", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001440ef, 0x100, 0x10000, 0x100000),
FLASH_ID("win w25q16jv", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001540ef, 0x100, 0x10000, 0x200000),
FLASH_ID("win w25q16jv", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001570ef, 0x100, 0x10000, 0x200000), /* QPI / DTR */
FLASH_ID("win w25q32fv/jv", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001640ef, 0x100, 0x10000, 0x400000),
FLASH_ID("win w25q32fv", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001660ef, 0x100, 0x10000, 0x400000), /* QPI mode */
FLASH_ID("win w25q32jv", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001670ef, 0x100, 0x10000, 0x400000),
FLASH_ID("win w25q64fv/jv", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001740ef, 0x100, 0x10000, 0x800000),
FLASH_ID("win w25q64fv", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001760ef, 0x100, 0x10000, 0x800000), /* QPI mode */
FLASH_ID("win w25q64jv", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001770ef, 0x100, 0x10000, 0x800000),
FLASH_ID("win w25q128fv/jv", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001840ef, 0x100, 0x10000, 0x1000000),
FLASH_ID("win w25q128fv", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001860ef, 0x100, 0x10000, 0x1000000), /* QPI mode */
FLASH_ID("win w25q128jv", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001870ef, 0x100, 0x10000, 0x1000000),
FLASH_ID("win w25q256fv/jv", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001940ef, 0x100, 0x10000, 0x2000000),
FLASH_ID("win w25q256fv", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001960ef, 0x100, 0x10000, 0x2000000), /* QPI mode */
FLASH_ID("win w25q256jv", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001970ef, 0x100, 0x10000, 0x2000000),
FLASH_ID("gd gd25q512", 0x03, 0x00, 0x02, 0x20, 0xc7, 0x001040c8, 0x100, 0x1000, 0x10000),
FLASH_ID("gd gd25q10", 0x03, 0x00, 0x02, 0x20, 0xc7, 0x001140c8, 0x100, 0x1000, 0x20000),
FLASH_ID("gd gd25q20", 0x03, 0x00, 0x02, 0x20, 0xc7, 0x001240c8, 0x100, 0x1000, 0x40000),
FLASH_ID("gd gd25q40", 0x03, 0x00, 0x02, 0x20, 0xc7, 0x001340c8, 0x100, 0x1000, 0x80000),
FLASH_ID("gd gd25q16c", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001540c8, 0x100, 0x10000, 0x200000),
FLASH_ID("gd gd25q32c", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001640c8, 0x100, 0x10000, 0x400000),
FLASH_ID("gd gd25q64c", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001740c8, 0x100, 0x10000, 0x800000),
FLASH_ID("gd gd25q128c", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001840c8, 0x100, 0x10000, 0x1000000),
FLASH_ID("gd gd25q256c", 0x13, 0x00, 0x12, 0xdc, 0xc7, 0x001940c8, 0x100, 0x10000, 0x2000000),
FLASH_ID("gd gd25q512mc", 0x13, 0x00, 0x12, 0xdc, 0xc7, 0x002040c8, 0x100, 0x10000, 0x4000000),
FLASH_ID("issi is25lp032", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0016609d, 0x100, 0x10000, 0x400000),
FLASH_ID("issi is25lp064", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0017609d, 0x100, 0x10000, 0x800000),
FLASH_ID("issi is25lp128d", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x0018609d, 0x100, 0x10000, 0x1000000),
FLASH_ID("issi is25wp128d", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x0018709d, 0x100, 0x10000, 0x1000000),
FLASH_ID("issi is25lp256d", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0019609d, 0x100, 0x10000, 0x2000000),
FLASH_ID("issi is25wp256d", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0019709d, 0x100, 0x10000, 0x2000000),
FLASH_ID("issi is25lp512m", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001a609d, 0x100, 0x10000, 0x4000000),
FLASH_ID("issi is25wp512m", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001a709d, 0x100, 0x10000, 0x4000000),
/* FRAM, no erase commands, no write page or sectors */
FRAM_ID("fu mb85rs16n", 0x03, 0, 0x02, 0x00010104, 0x800),
FRAM_ID("fu mb85rs32v", 0x03, 0, 0x02, 0x00010204, 0x1000), /* exists ? */
FRAM_ID("fu mb85rs64v", 0x03, 0, 0x02, 0x00020304, 0x2000),
FRAM_ID("fu mb85rs128b", 0x03, 0, 0x02, 0x00090404, 0x4000),
FRAM_ID("fu mb85rs256b", 0x03, 0, 0x02, 0x00090504, 0x8000),
FRAM_ID("fu mb85rs512t", 0x03, 0, 0x02, 0x00032604, 0x10000),
FRAM_ID("fu mb85rs1mt", 0x03, 0, 0x02, 0x00032704, 0x20000),
FRAM_ID("fu mb85rs2mta", 0x03, 0, 0x02, 0x00034804, 0x40000),
FRAM_ID("cyp fm25v01a", 0x03, 0, 0x02, 0x000821c2, 0x4000),
FRAM_ID("cyp fm25v02", 0x03, 0, 0x02, 0x000022c2, 0x8000),
FRAM_ID("cyp fm25v02a", 0x03, 0, 0x02, 0x000822c2, 0x8000),
FRAM_ID("cyp fm25v05", 0x03, 0, 0x02, 0x000023c2, 0x10000),
FRAM_ID("cyp fm25v10", 0x03, 0, 0x02, 0x000024c2, 0x20000),
FRAM_ID("cyp fm25v20a", 0x03, 0, 0x02, 0x000825c2, 0x40000),
FRAM_ID("cyp fm25v40", 0x03, 0, 0x02, 0x004026c2, 0x80000),
FLASH_ID(NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0)
};
+45 -13
View File
@@ -1,4 +1,7 @@
/***************************************************************************
* Copyright (C) 2018 by Andreas Bolsch *
* andreas.bolsch@mni.thm.de *
* *
* Copyright (C) 2012 by George Harris *
* george@luminairecoffee.com *
* *
@@ -22,40 +25,69 @@
#ifndef OPENOCD_FLASH_NOR_SPI_H
#define OPENOCD_FLASH_NOR_SPI_H
#ifndef __ASSEMBLER__
/* data structure to maintain flash ids from different vendors */
struct flash_device {
char *name;
uint8_t read_cmd;
uint8_t qread_cmd;
uint8_t pprog_cmd;
uint8_t erase_cmd;
uint8_t chip_erase_cmd;
uint32_t device_id;
uint32_t pagesize;
unsigned long sectorsize;
unsigned long size_in_bytes;
uint32_t sectorsize;
uint32_t size_in_bytes;
};
#define FLASH_ID(n, es, ces, id, psize, ssize, size) \
{ \
.name = n, \
.erase_cmd = es, \
.chip_erase_cmd = ces, \
.device_id = id, \
.pagesize = psize, \
.sectorsize = ssize, \
.size_in_bytes = size \
#define FLASH_ID(n, re, qr, pp, es, ces, id, psize, ssize, size) \
{ \
.name = n, \
.read_cmd = re, \
.qread_cmd = qr, \
.pprog_cmd = pp, \
.erase_cmd = es, \
.chip_erase_cmd = ces, \
.device_id = id, \
.pagesize = psize, \
.sectorsize = ssize, \
.size_in_bytes = size, \
}
#define FRAM_ID(n, re, qr, pp, id, size) \
{ \
.name = n, \
.read_cmd = re, \
.qread_cmd = qr, \
.pprog_cmd = pp, \
.erase_cmd = 0x00, \
.chip_erase_cmd = 0x00, \
.device_id = id, \
.pagesize = 0, \
.sectorsize = 0, \
.size_in_bytes = size, \
}
extern const struct flash_device flash_devices[];
#endif
/* fields in SPI flash status register */
#define SPIFLASH_BSY_BIT 0x00000001 /* WIP Bit of SPI SR on SMI SR */
#define SPIFLASH_WE_BIT 0x00000002 /* WEL Bit of SPI SR on SMI SR */
#define SPIFLASH_BSY 0
#define SPIFLASH_BSY_BIT (1 << SPIFLASH_BSY) /* WIP Bit of SPI SR */
#define SPIFLASH_WE 1
#define SPIFLASH_WE_BIT (1 << SPIFLASH_WE) /* WEL Bit of SPI SR */
/* SPI Flash Commands */
#define SPIFLASH_READ_ID 0x9F /* Read Flash Identification */
#define SPIFLASH_READ_MID 0xAF /* Read Flash Identification, multi-io */
#define SPIFLASH_READ_STATUS 0x05 /* Read Status Register */
#define SPIFLASH_WRITE_ENABLE 0x06 /* Write Enable */
#define SPIFLASH_PAGE_PROGRAM 0x02 /* Page Program */
#define SPIFLASH_FAST_READ 0x0B /* Fast Read */
#define SPIFLASH_READ 0x03 /* Normal Read */
#define SPIFLASH_DEF_PAGESIZE 256 /* default for non-page-oriented devices (FRAMs) */
#endif /* OPENOCD_FLASH_NOR_SPI_H */
+4 -2
View File
@@ -1355,6 +1355,7 @@ COMMAND_HANDLER(stellaris_handle_mass_erase_command)
COMMAND_HANDLER(stellaris_handle_recover_command)
{
struct flash_bank *bank;
struct arm *arm;
int retval;
if (CMD_ARGC != 0)
@@ -1383,12 +1384,13 @@ COMMAND_HANDLER(stellaris_handle_recover_command)
}
adapter_assert_reset();
arm = target_to_arm(bank->target);
for (int i = 0; i < 5; i++) {
retval = dap_to_swd(bank->target);
retval = dap_to_swd(arm->dap);
if (retval != ERROR_OK)
goto done;
retval = dap_to_jtag(bank->target);
retval = dap_to_jtag(arm->dap);
if (retval != ERROR_OK)
goto done;
}
+21 -11
View File
@@ -131,7 +131,7 @@ struct stm32x_flash_bank {
static int stm32x_mass_erase(struct flash_bank *bank);
static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id);
static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count);
uint32_t address, uint32_t count);
/* flash bank stm32x <base> <size> 0 0 <target#>
*/
@@ -343,8 +343,7 @@ static int stm32x_write_options(struct flash_bank *bank)
target_buffer_set_u16(target, opt_bytes + 12, (stm32x_info->option_bytes.protection >> 16) & 0xff);
target_buffer_set_u16(target, opt_bytes + 14, (stm32x_info->option_bytes.protection >> 24) & 0xff);
uint32_t offset = STM32_OB_RDP - bank->base;
retval = stm32x_write_block(bank, opt_bytes, offset, sizeof(opt_bytes) / 2);
retval = stm32x_write_block(bank, opt_bytes, STM32_OB_RDP, sizeof(opt_bytes) / 2);
if (retval != ERROR_OK) {
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
LOG_ERROR("working area required to erase options bytes");
@@ -443,8 +442,10 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
return retval;
retval = stm32x_erase_options(bank);
if (retval != ERROR_OK)
if (retval != ERROR_OK) {
LOG_ERROR("stm32x failed to erase options");
return retval;
}
for (int i = first; i <= last; i++) {
if (set)
@@ -457,14 +458,13 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
}
static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
uint32_t address, uint32_t count)
{
struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
struct target *target = bank->target;
uint32_t buffer_size = 16384;
struct working_area *write_algorithm;
struct working_area *source;
uint32_t address = bank->base + offset;
struct reg_param reg_params[5];
struct armv7m_algorithm armv7m_info;
int retval = ERROR_OK;
@@ -599,7 +599,7 @@ static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer,
goto cleanup;
/* try using a block write */
retval = stm32x_write_block(bank, buffer, offset, words_remaining);
retval = stm32x_write_block(bank, buffer, bank->base + offset, words_remaining);
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
/* if block write failed (no sufficient working area),
@@ -1227,12 +1227,12 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
return retval;
if (stm32x_erase_options(bank) != ERROR_OK) {
command_print(CMD_CTX, "stm32x failed to unlock device");
command_print(CMD_CTX, "stm32x failed to erase options");
return ERROR_OK;
}
if (stm32x_write_options(bank) != ERROR_OK) {
command_print(CMD_CTX, "stm32x failed to lock device");
command_print(CMD_CTX, "stm32x failed to unlock device");
return ERROR_OK;
}
@@ -1313,7 +1313,8 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
{
struct target *target = NULL;
struct stm32x_flash_bank *stm32x_info = NULL;
uint16_t optionbyte;
uint8_t optionbyte;
uint16_t useropt;
if (CMD_ARGC < 2)
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -1342,6 +1343,7 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
/* start with current options */
optionbyte = stm32x_info->option_bytes.user;
useropt = stm32x_info->option_bytes.data;
/* skip over flash bank */
CMD_ARGC--;
@@ -1360,6 +1362,13 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
optionbyte |= (1 << 2);
else if (strcmp("RSTSTNDBY", CMD_ARGV[0]) == 0)
optionbyte &= ~(1 << 2);
else if (strcmp("USEROPT", CMD_ARGV[0]) == 0) {
if (CMD_ARGC < 2)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], useropt);
CMD_ARGC--;
CMD_ARGV++;
}
else if (stm32x_info->has_dual_banks) {
if (strcmp("BOOT0", CMD_ARGV[0]) == 0)
optionbyte |= (1 << 3);
@@ -1379,6 +1388,7 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
}
stm32x_info->option_bytes.user = optionbyte;
stm32x_info->option_bytes.data = useropt;
if (stm32x_write_options(bank) != ERROR_OK) {
command_print(CMD_CTX, "stm32x failed to write options");
@@ -1536,7 +1546,7 @@ static const struct command_registration stm32x_exec_command_handlers[] = {
.mode = COMMAND_EXEC,
.usage = "bank_id ('SWWDG'|'HWWDG') "
"('RSTSTNDBY'|'NORSTSTNDBY') "
"('RSTSTOP'|'NORSTSTOP')",
"('RSTSTOP'|'NORSTSTOP') ('USEROPT' user_data)",
.help = "Replace bits in device option bytes.",
},
{
+78 -27
View File
@@ -33,6 +33,9 @@
* RM0394 (STM32L43x/44x/45x/46x)
* http://www.st.com/resource/en/reference_manual/dm00151940.pdf
*
* RM0432 (STM32L4R/4Sxx)
* http://www.st.com/resource/en/reference_manual/dm00310109.pdf
*
* STM32L476RG Datasheet (for erase timing)
* http://www.st.com/resource/en/datasheet/stm32l476rg.pdf
*
@@ -43,6 +46,14 @@
*
* RM0394 devices have a single bank only.
*
* RM0432 devices have single and dual bank operating modes.
* The FLASH size is 1Mbyte or 2Mbyte.
* Bank page (sector) size is 4Kbyte (dual mode) or 8Kbyte (single mode).
*
* Bank mode is controlled by two different bits in option bytes register.
* In 2M FLASH devices bit 22 (DBANK) controls Dual Bank mode.
* In 1M FLASH devices bit 21 (DB1M) controls Dual Bank mode.
*
*/
/* Erase time can be as high as 25ms, 10x this and assume it's toast... */
@@ -82,7 +93,7 @@
#define FLASH_BSY (1 << 16)
/* Fast programming not used => related errors not used*/
#define FLASH_PGSERR (1 << 7) /* Programming sequence error */
#define FLASH_SIZERR (1 << 6) /* Size error */
#define FLASH_SIZERR (1 << 6) /* Size error */
#define FLASH_PGAERR (1 << 5) /* Programming alignment error */
#define FLASH_WRPERR (1 << 4) /* Write protection error */
#define FLASH_PROGERR (1 << 3) /* Programming error */
@@ -93,7 +104,8 @@
/* STM32_FLASH_OBR bit definitions (reading) */
#define OPT_DUALBANK 21 /* dual flash bank only */
#define OPT_DBANK_LE_1M (1 << 21) /* dual bank for devices up to 1M flash */
#define OPT_DBANK_GE_2M (1 << 22) /* dual bank for devices with 2M flash */
/* register unlock keys */
@@ -325,7 +337,7 @@ static int stm32l4_protect_check(struct flash_bank *bank)
bank->sectors[i].is_protected = 0;
} else {
uint8_t snb;
snb = i - stm32l4_info->bank2_start + 256;
snb = i - stm32l4_info->bank2_start;
if (((snb >= wrp2a_start) &&
(snb <= wrp2a_end)) ||
((snb >= wrp2b_start) &&
@@ -362,7 +374,7 @@ static int stm32l4_erase(struct flash_bank *bank, int first, int last)
1. Check that no Flash memory operation is ongoing by
checking the BSY bit in the FLASH_SR register
2. Set the PER bit and select the page and bank
you wish to erase in the FLASH_CR register
you wish to erase in the FLASH_CR register
3. Set the STRT bit in the FLASH_CR register
4. Wait for the BSY bit to be cleared
*/
@@ -372,9 +384,9 @@ static int stm32l4_erase(struct flash_bank *bank, int first, int last)
uint32_t erase_flags;
erase_flags = FLASH_PER | FLASH_STRT;
if (i >= stm32l4_info->bank2_start) {
if (i >= stm32l4_info->bank2_start) {
uint8_t snb;
snb = (i - stm32l4_info->bank2_start) + 256;
snb = i - stm32l4_info->bank2_start;
erase_flags |= snb << FLASH_PAGE_SHIFT | FLASH_CR_BKER;
} else
erase_flags |= i << FLASH_PAGE_SHIFT;
@@ -473,7 +485,7 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer,
* buffer, free the algorithm */
target_free_working_area(target, write_algorithm);
LOG_WARNING("no large enough working area available, can't do block memory writes");
LOG_WARNING("large enough working area not available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
}
@@ -594,6 +606,9 @@ static int stm32l4_probe(struct flash_bank *bank)
/* set max flash size depending on family */
switch (device_id & 0xfff) {
case 0x470:
max_flash_size_in_kb = 2048;
break;
case 0x461:
case 0x415:
max_flash_size_in_kb = 1024;
@@ -605,7 +620,7 @@ static int stm32l4_probe(struct flash_bank *bank)
max_flash_size_in_kb = 256;
break;
default:
LOG_WARNING("Cannot identify target as a STM32L4 family.");
LOG_WARNING("Cannot identify target as an STM32L4 family device.");
return ERROR_FAIL;
}
@@ -622,45 +637,77 @@ static int stm32l4_probe(struct flash_bank *bank)
LOG_INFO("flash size = %dkbytes", flash_size_in_kb);
/* did we assign flash size? */
assert(flash_size_in_kb != 0xffff);
/* did we assign a flash size? */
assert((flash_size_in_kb != 0xffff) && flash_size_in_kb);
/* get options to for DUAL BANK. */
/* get options for DUAL BANK. */
retval = target_read_u32(target, STM32_FLASH_OPTR, &options);
if (retval != ERROR_OK)
return retval;
/* only devices with < 1024 kiB may be set to single bank dual banks */
if ((flash_size_in_kb == 1024) || !(options & OPT_DUALBANK))
stm32l4_info->bank2_start = 256;
else
stm32l4_info->bank2_start = flash_size_in_kb << 9;
int num_pages = 0;
int page_size = 0;
/* did we assign flash size? */
assert((flash_size_in_kb != 0xffff) && flash_size_in_kb);
/* calculate numbers of pages */
int num_pages = flash_size_in_kb / 2;
/* check that calculation result makes sense */
assert(num_pages > 0);
switch (device_id & 0xfff) {
case 0x470:
/* L4R/S have 1M or 2M FLASH and dual/single bank mode.
* Page size is 4K or 8K.*/
if (flash_size_in_kb == 2048) {
stm32l4_info->bank2_start = 256;
if (options & OPT_DBANK_GE_2M) {
page_size = 4096;
num_pages = 512;
} else {
page_size = 8192;
num_pages = 256;
}
break;
}
if (flash_size_in_kb == 1024) {
stm32l4_info->bank2_start = 128;
if (options & OPT_DBANK_LE_1M) {
page_size = 4096;
num_pages = 256;
} else {
page_size = 8192;
num_pages = 128;
}
break;
}
/* Invalid FLASH size for this device. */
LOG_WARNING("Invalid flash size for STM32L4+ family device.");
return ERROR_FAIL;
default:
/* Other L4 family devices have 2K pages. */
page_size = 2048;
num_pages = flash_size_in_kb / 2;
/* check that calculation result makes sense */
assert(num_pages > 0);
if ((flash_size_in_kb == 1024) || !(options & OPT_DBANK_LE_1M))
stm32l4_info->bank2_start = 256;
else
stm32l4_info->bank2_start = num_pages / 2;
break;
}
/* Release sector table if allocated. */
if (bank->sectors) {
free(bank->sectors);
bank->sectors = NULL;
}
/* Set bank configuration and construct sector table. */
bank->base = base_address;
bank->size = num_pages * (1 << 11);
bank->size = num_pages * page_size;
bank->num_sectors = num_pages;
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
if (!bank->sectors)
return ERROR_FAIL; /* Checkme: What better error to use?*/
for (i = 0; i < num_pages; i++) {
bank->sectors[i].offset = i << 11;
bank->sectors[i].size = 1 << 11;
bank->sectors[i].offset = i * page_size;
bank->sectors[i].size = page_size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1;
}
@@ -703,6 +750,10 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size)
const char *device_str;
switch (device_id) {
case 0x470:
device_str = "STM32L4R/4Sxx";
break;
case 0x461:
device_str = "STM32L496/4A6";
break;
+1 -9
View File
@@ -424,13 +424,6 @@ static int stm32lx_erase(struct flash_bank *bank, int first, int last)
return ERROR_OK;
}
static int stm32lx_protect(struct flash_bank *bank, int set, int first,
int last)
{
LOG_WARNING("protection of the STM32L flash is not implemented");
return ERROR_OK;
}
static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
@@ -863,7 +856,7 @@ static int stm32lx_probe(struct flash_bank *bank)
bank->sectors[i].offset = i * FLASH_SECTOR_SIZE;
bank->sectors[i].size = FLASH_SECTOR_SIZE;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1;
bank->sectors[i].is_protected = -1;
}
stm32lx_info->probed = 1;
@@ -956,7 +949,6 @@ struct flash_driver stm32lx_flash = {
.commands = stm32lx_command_handlers,
.flash_bank_command = stm32lx_flash_bank_command,
.erase = stm32lx_erase,
.protect = stm32lx_protect,
.write = stm32lx_write,
.read = default_flash_read,
.probe = stm32lx_probe,
+25 -15
View File
@@ -269,17 +269,14 @@ static int smi_write_enable(struct flash_bank *bank)
static uint32_t erase_command(struct stmsmi_flash_bank *stmsmi_info,
uint32_t offset)
{
union {
uint32_t command;
uint8_t x[4];
} cmd;
uint8_t cmd_bytes[] = {
stmsmi_info->dev->erase_cmd,
offset >> 16,
offset >> 8,
offset
};
cmd.x[0] = stmsmi_info->dev->erase_cmd;
cmd.x[1] = offset >> 16;
cmd.x[2] = offset >> 8;
cmd.x[3] = offset;
return cmd.command;
return le_to_h_u32(cmd_bytes);
}
static int smi_erase_sector(struct flash_bank *bank, int sector)
@@ -348,6 +345,9 @@ static int stmsmi_erase(struct flash_bank *bank, int first, int last)
}
}
if (stmsmi_info->dev->erase_cmd == 0x00)
return ERROR_FLASH_OPER_UNSUPPORTED;
for (sector = first; sector <= last; sector++) {
retval = smi_erase_sector(bank, sector);
if (retval != ERROR_OK)
@@ -431,7 +431,9 @@ static int stmsmi_write(struct flash_bank *bank, const uint8_t *buffer,
}
}
page_size = stmsmi_info->dev->pagesize;
/* if no valid page_size, use reasonable default */
page_size = stmsmi_info->dev->pagesize ?
stmsmi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
/* unaligned buffer head */
if (count > 0 && (offset & 3) != 0) {
@@ -524,7 +526,7 @@ static int stmsmi_probe(struct flash_bank *bank)
{
struct target *target = bank->target;
struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
uint32_t io_base;
uint32_t io_base, sectorsize;
struct flash_sector *sectors;
uint32_t id = 0; /* silence uninitialized warning */
const struct stmsmi_target *target_device;
@@ -589,10 +591,18 @@ static int stmsmi_probe(struct flash_bank *bank)
/* Set correct size value */
bank->size = stmsmi_info->dev->size_in_bytes;
if (bank->size <= (1UL << 16))
LOG_WARNING("device needs 2-byte addresses - not implemented");
if (bank->size > (1UL << 24))
LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
/* if no sectors, treat whole bank as single sector */
sectorsize = stmsmi_info->dev->sectorsize ?
stmsmi_info->dev->sectorsize : stmsmi_info->dev->size_in_bytes;
/* create and fill sectors array */
bank->num_sectors =
stmsmi_info->dev->size_in_bytes / stmsmi_info->dev->sectorsize;
stmsmi_info->dev->size_in_bytes / sectorsize;
sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
if (sectors == NULL) {
LOG_ERROR("not enough memory");
@@ -600,8 +610,8 @@ static int stmsmi_probe(struct flash_bank *bank)
}
for (int sector = 0; sector < bank->num_sectors; sector++) {
sectors[sector].offset = sector * stmsmi_info->dev->sectorsize;
sectors[sector].size = stmsmi_info->dev->sectorsize;
sectors[sector].offset = sector * sectorsize;
sectors[sector].size = sectorsize;
sectors[sector].is_erased = -1;
sectors[sector].is_protected = 1;
}
+12 -4
View File
@@ -98,10 +98,18 @@ COMMAND_HANDLER(handle_flash_info_command)
if (retval != ERROR_OK)
return retval;
/* We must query the hardware to avoid printing stale information! */
retval = p->driver->protect_check(p);
if (retval != ERROR_OK)
return retval;
/* If the driver does not implement protection, we show the default
* state of is_protected array - usually protection state unknown */
if (p->driver->protect_check == NULL) {
retval = ERROR_FLASH_OPER_UNSUPPORTED;
} else {
/* We must query the hardware to avoid printing stale information! */
retval = p->driver->protect_check(p);
if (retval != ERROR_OK && retval != ERROR_FLASH_OPER_UNSUPPORTED)
return retval;
}
if (retval == ERROR_FLASH_OPER_UNSUPPORTED)
LOG_WARNING("Flash protection check is not implemented.");
command_print(CMD_CTX,
"#%d : %s at 0x%8.8" TARGET_PRIxADDR ", size 0x%8.8" PRIx32
+390
View File
@@ -0,0 +1,390 @@
/***************************************************************************
* Copyright (C) 2018 by Simon Qian *
* SimonQian@SimonQian.com *
* *
* 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 *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* 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, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "imp.h"
#include <helper/binarybuffer.h>
#include <target/algorithm.h>
#include <target/armv7m.h>
#define W600_FLASH_SECSIZE 0x1000
#define W600_FLASH_PAGESIZE 0x100
#define W600_FLASH_BASE 0x08000000
#define W600_FLASH_PROTECT_SIZE 0x2000
/* w600 register locations */
#define QFLASH_REGBASE 0X40002000
#define QFLASH_CMD_INFO (QFLASH_REGBASE + 0)
#define QFLASH_CMD_START (QFLASH_REGBASE + 4)
#define QFLASH_BUFFER (QFLASH_REGBASE + 0X200)
#define QFLASH_CMD_READ (1ul << 14)
#define QFLASH_CMD_WRITE 0
#define QFLASH_CMD_ADDR (1ul << 31)
#define QFLASH_CMD_DATA (1ul << 15)
#define QFLASH_CMD_DATALEN(len) (((len) & 0x3FF) << 16)
#define QFLASH_CMD_RDID (QFLASH_CMD_READ | 0x9F)
#define QFLASH_CMD_WREN (QFLASH_CMD_WRITE | 0x06)
#define QFLASH_CMD_WRDI (QFLASH_CMD_WRITE | 0x04)
#define QFLASH_CMD_SE (QFLASH_CMD_WRITE | QFLASH_CMD_ADDR | (1ul << 11) | 0x20)
#define QFLASH_CMD_PP (QFLASH_CMD_WRITE | QFLASH_CMD_ADDR | (1ul << 12) | 0x02)
#define QFLASH_START (1ul << 28)
#define QFLASH_ADDR(addr) (((addr) & 0xFFFFF) << 8)
#define QFLASH_CRM(crm) (((crm) & 0xFF) << 0)
struct w600_flash_param {
uint8_t id;
uint8_t se_delay;
uint8_t pp_delay;
};
static const struct w600_flash_param w600_param[] = {
{
.id = 0x85,
.se_delay = 8,
.pp_delay = 2,
},
{
.id = 0x1C,
.se_delay = 50,
.pp_delay = 1,
},
{
.id = 0xC8,
.se_delay = 45,
.pp_delay = 1,
},
{
.id = 0x0B,
.se_delay = 60,
.pp_delay = 1,
},
{
.id = 0x68,
.se_delay = 50,
.pp_delay = 1,
},
};
struct w600_flash_bank {
int probed;
uint32_t id;
const struct w600_flash_param *param;
uint32_t register_base;
uint32_t user_bank_size;
};
/* flash bank w600 <base> <size> 0 0 <target#>
*/
FLASH_BANK_COMMAND_HANDLER(w600_flash_bank_command)
{
struct w600_flash_bank *w600_info;
if (CMD_ARGC < 6)
return ERROR_COMMAND_SYNTAX_ERROR;
w600_info = malloc(sizeof(struct w600_flash_bank));
bank->driver_priv = w600_info;
w600_info->probed = 0;
w600_info->register_base = QFLASH_REGBASE;
w600_info->user_bank_size = bank->size;
return ERROR_OK;
}
static int w600_get_delay(struct flash_bank *bank, uint32_t cmd)
{
struct w600_flash_bank *w600_info = bank->driver_priv;
if (!w600_info->param)
return 0;
switch (cmd) {
case QFLASH_CMD_SE:
return w600_info->param->se_delay;
case QFLASH_CMD_PP:
return w600_info->param->pp_delay;
default:
return 0;
}
}
static int w600_start_do(struct flash_bank *bank, uint32_t cmd, uint32_t addr,
uint32_t len, int timeout)
{
struct target *target = bank->target;
if (len > 0)
cmd |= QFLASH_CMD_DATALEN(len - 1) | QFLASH_CMD_DATA;
LOG_DEBUG("WRITE CMD: 0x%08" PRIx32 "", cmd);
int retval = target_write_u32(target, QFLASH_CMD_INFO, cmd);
if (retval != ERROR_OK)
return retval;
addr |= QFLASH_START;
LOG_DEBUG("WRITE START: 0x%08" PRIx32 "", addr);
retval = target_write_u32(target, QFLASH_CMD_START, addr);
if (retval != ERROR_OK)
return retval;
LOG_DEBUG("DELAY %dms", timeout);
alive_sleep(timeout);
int retry = 100;
uint32_t status;
for (;;) {
LOG_DEBUG("READ START...");
retval = target_read_u32(target, QFLASH_CMD_START, &status);
if (retval == ERROR_OK)
LOG_DEBUG("READ START: 0x%08" PRIx32 "", status);
else
LOG_DEBUG("READ START FAILED");
if ((retval != ERROR_OK) || (status & QFLASH_START)) {
if (retry-- <= 0) {
LOG_ERROR("timed out waiting for flash");
return ERROR_FAIL;
}
continue;
}
break;
}
return retval;
}
static int w600_write_enable(struct flash_bank *bank)
{
return w600_start_do(bank, QFLASH_CMD_WREN, 0, 0, 0);
}
static int w600_write_disable(struct flash_bank *bank)
{
return w600_start_do(bank, QFLASH_CMD_WRDI, 0, 0, 0);
}
static int w600_start(struct flash_bank *bank, uint32_t cmd, uint32_t addr,
uint32_t len)
{
int retval = w600_write_enable(bank);
if (retval != ERROR_OK)
return retval;
retval = w600_start_do(bank, cmd, addr, len, w600_get_delay(bank, cmd));
if (retval != ERROR_OK)
return retval;
retval = w600_write_disable(bank);
if (retval != ERROR_OK)
return retval;
return retval;
}
static int w600_erase(struct flash_bank *bank, int first, int last)
{
int retval = ERROR_OK;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (first < W600_FLASH_PROTECT_SIZE / W600_FLASH_SECSIZE) {
LOG_ERROR("can not erase protected area");
return ERROR_FAIL;
}
for (int i = first; i <= last; i++) {
retval = w600_start(bank, QFLASH_CMD_SE,
QFLASH_ADDR(bank->sectors[i].offset), 0);
if (retval != ERROR_OK)
break;
}
return retval;
}
static int w600_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
struct target *target = bank->target;
int retval = ERROR_OK;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if ((offset % W600_FLASH_PAGESIZE) != 0) {
LOG_WARNING("offset 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment",
offset, W600_FLASH_PAGESIZE);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
if ((count % W600_FLASH_PAGESIZE) != 0) {
LOG_WARNING("count 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment",
offset, W600_FLASH_PAGESIZE);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
while (count > 0) {
retval = target_write_buffer(target, QFLASH_BUFFER, W600_FLASH_PAGESIZE, buffer);
if (retval != ERROR_OK)
break;
retval = w600_start(bank, QFLASH_CMD_PP, QFLASH_ADDR(offset),
W600_FLASH_PAGESIZE);
if (retval != ERROR_OK)
break;
count -= W600_FLASH_PAGESIZE;
offset += W600_FLASH_PAGESIZE;
buffer += W600_FLASH_PAGESIZE;
}
return retval;
}
static int w600_get_flash_id(struct flash_bank *bank, uint32_t *flash_id)
{
struct target *target = bank->target;
int retval = w600_start(bank, QFLASH_CMD_RDID, 0, 4);
if (retval != ERROR_OK)
return retval;
return target_read_u32(target, QFLASH_BUFFER, flash_id);
}
static int w600_probe(struct flash_bank *bank)
{
struct w600_flash_bank *w600_info = bank->driver_priv;
uint32_t flash_size;
uint32_t flash_id;
size_t i;
w600_info->probed = 0;
/* read stm32 device id register */
int retval = w600_get_flash_id(bank, &flash_id);
if (retval != ERROR_OK)
return retval;
LOG_INFO("flash_id id = 0x%08" PRIx32 "", flash_id);
w600_info->id = flash_id;
w600_info->param = NULL;
for (i = 0; i < ARRAY_SIZE(w600_param); i++) {
if (w600_param[i].id == (flash_id & 0xFF)) {
w600_info->param = &w600_param[i];
break;
}
}
if (!w600_info->param) {
LOG_ERROR("flash_id not supported for w600");
return ERROR_FAIL;
}
/* if the user sets the size manually then ignore the probed value
* this allows us to work around devices that have a invalid flash size register value */
if (w600_info->user_bank_size) {
LOG_INFO("ignoring flash probed value, using configured bank size");
flash_size = w600_info->user_bank_size;
} else {
flash_size = ((flash_id & 0xFFFFFF) >> 16) & 0xFF;
if ((flash_size != 0x14) && (flash_size != 0x13)) {
LOG_ERROR("w600 flash size failed, probe inaccurate");
return ERROR_FAIL;
}
flash_size = 1 << flash_size;
}
LOG_INFO("flash size = %dkbytes", flash_size / 1024);
/* calculate numbers of pages */
size_t num_pages = flash_size / W600_FLASH_SECSIZE;
/* check that calculation result makes sense */
assert(num_pages > 0);
if (bank->sectors) {
free(bank->sectors);
bank->sectors = NULL;
}
bank->base = W600_FLASH_BASE;
bank->size = num_pages * W600_FLASH_SECSIZE;
bank->num_sectors = num_pages;
bank->write_start_alignment = W600_FLASH_PAGESIZE;
bank->write_end_alignment = W600_FLASH_PAGESIZE;
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
for (i = 0; i < num_pages; i++) {
bank->sectors[i].offset = i * W600_FLASH_SECSIZE;
bank->sectors[i].size = W600_FLASH_SECSIZE;
bank->sectors[i].is_erased = -1;
/* offset 0 to W600_FLASH_PROTECT_SIZE shoule be protected */
bank->sectors[i].is_protected = (i < W600_FLASH_PROTECT_SIZE / W600_FLASH_SECSIZE);
}
w600_info->probed = 1;
return ERROR_OK;
}
static int w600_auto_probe(struct flash_bank *bank)
{
struct w600_flash_bank *w600_info = bank->driver_priv;
if (w600_info->probed)
return ERROR_OK;
return w600_probe(bank);
}
static int get_w600_info(struct flash_bank *bank, char *buf, int buf_size)
{
uint32_t flash_id;
/* read w600 device id register */
int retval = w600_get_flash_id(bank, &flash_id);
if (retval != ERROR_OK)
return retval;
snprintf(buf, buf_size, "w600 : 0x%08" PRIx32 "", flash_id);
return ERROR_OK;
}
struct flash_driver w600_flash = {
.name = "w600",
.flash_bank_command = w600_flash_bank_command,
.erase = w600_erase,
.write = w600_write,
.read = default_flash_read,
.probe = w600_probe,
.auto_probe = w600_auto_probe,
.erase_check = default_flash_blank_check,
.info = get_w600_info,
.free_driver_priv = default_flash_free_driver_priv,
};
+36 -23
View File
@@ -557,6 +557,10 @@ static char *__command_name(struct command *c, char delim, unsigned extra)
if (NULL == c->parent) {
/* allocate enough for the name, child names, and '\0' */
name = malloc(len + extra + 1);
if (!name) {
LOG_ERROR("Out of memory");
return NULL;
}
strcpy(name, c->name);
} else {
/* parent's extra must include both the space and name */
@@ -575,31 +579,35 @@ char *command_name(struct command *c, char delim)
static bool command_can_run(struct command_context *cmd_ctx, struct command *c)
{
return c->mode == COMMAND_ANY || c->mode == cmd_ctx->mode;
if (c->mode == COMMAND_ANY || c->mode == cmd_ctx->mode)
return true;
/* Many commands may be run only before/after 'init' */
const char *when;
switch (c->mode) {
case COMMAND_CONFIG:
when = "before";
break;
case COMMAND_EXEC:
when = "after";
break;
/* handle the impossible with humor; it guarantees a bug report! */
default:
when = "if Cthulhu is summoned by";
break;
}
char *full_name = command_name(c, ' ');
LOG_ERROR("The '%s' command must be used %s 'init'.",
full_name ? full_name : c->name, when);
free(full_name);
return false;
}
static int run_command(struct command_context *context,
struct command *c, const char *words[], unsigned num_words)
{
if (!command_can_run(context, c)) {
/* Many commands may be run only before/after 'init' */
const char *when;
switch (c->mode) {
case COMMAND_CONFIG:
when = "before";
break;
case COMMAND_EXEC:
when = "after";
break;
/* handle the impossible with humor; it guarantees a bug report! */
default:
when = "if Cthulhu is summoned by";
break;
}
LOG_ERROR("The '%s' command must be used %s 'init'.",
c->name, when);
if (!command_can_run(context, c))
return ERROR_FAIL;
}
struct command_invocation cmd = {
.ctx = context,
@@ -631,15 +639,17 @@ static int run_command(struct command_context *context,
if (NULL != full_name) {
command_run_linef(context, "usage %s", full_name);
free(full_name);
} else
retval = -ENOMEM;
}
} else if (retval == ERROR_COMMAND_CLOSE_CONNECTION) {
/* just fall through for a shutdown request */
} else if (retval != ERROR_OK) {
/* we do not print out an error message because the command *should*
* have printed out an error
*/
LOG_DEBUG("Command failed with error code %d", retval);
char *full_name = command_name(c, ' ');
LOG_DEBUG("Command '%s' failed with error code %d",
full_name ? full_name : c->name, retval);
free(full_name);
}
return retval;
@@ -870,7 +880,7 @@ static COMMAND_HELPER(command_help_show, struct command *c, unsigned n,
{
char *cmd_name = command_name(c, ' ');
if (NULL == cmd_name)
return -ENOMEM;
return ERROR_FAIL;
/* If the match string occurs anywhere, we print out
* stuff for this command. */
@@ -1026,6 +1036,9 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
/* pass the command through to the intended handler */
if (c->jim_handler) {
if (!command_can_run(cmd_ctx, c))
return ERROR_FAIL;
interp->cmdPrivData = c->jim_handler_data;
return (*c->jim_handler)(interp, count, start);
}
+8 -38
View File
@@ -61,46 +61,16 @@ static const char * const log_strings[6] = {
static int count;
static struct store_log_forward *log_head;
static int log_forward_count;
struct store_log_forward {
struct store_log_forward *next;
const char *file;
int line;
const char *function;
const char *string;
};
/* either forward the log to the listeners or store it for possible forwarding later */
/* forward the log to the listeners */
static void log_forward(const char *file, unsigned line, const char *function, const char *string)
{
if (log_forward_count == 0) {
struct log_callback *cb, *next;
cb = log_callbacks;
/* DANGER!!!! the log callback can remove itself!!!! */
while (cb) {
next = cb->next;
cb->fn(cb->priv, file, line, function, string);
cb = next;
}
} else {
struct store_log_forward *log = malloc(sizeof(struct store_log_forward));
log->file = strdup(file);
log->line = line;
log->function = strdup(function);
log->string = strdup(string);
log->next = NULL;
if (log_head == NULL)
log_head = log;
else {
/* append to tail */
struct store_log_forward *t;
t = log_head;
while (t->next != NULL)
t = t->next;
t->next = log;
}
struct log_callback *cb, *next;
cb = log_callbacks;
/* DANGER!!!! the log callback can remove itself!!!! */
while (cb) {
next = cb->next;
cb->fn(cb->priv, file, line, function, string);
cb = next;
}
}
+6 -3
View File
@@ -12,15 +12,18 @@ proc exit {} {
# All commands are registered with an 'ocd_' prefix, while the "real"
# command is a wrapper that calls this function. Its primary purpose is
# to discard 'handler' command output,
# to discard 'handler' command output.
# Due to the two nested proc calls, this wrapper has to explicitly run
# the wrapped command in the stack frame two levels above.
proc ocd_bouncer {name args} {
set cmd [format "ocd_%s" $name]
set type [eval ocd_command type $cmd $args]
set errcode error
set skiplevel [expr [eval info level] > 1 ? 2 : 1]
if {$type == "native"} {
return [eval $cmd $args]
return [uplevel $skiplevel $cmd $args]
} else {if {$type == "simple"} {
set errcode [catch {eval $cmd $args}]
set errcode [catch {uplevel $skiplevel $cmd $args}]
if {$errcode == 0} {
return ""
} else {
+48
View File
@@ -35,6 +35,7 @@
#include "interface.h"
#include "interfaces.h"
#include <transport/transport.h>
#include <jtag/drivers/jtag_usb_common.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
@@ -456,7 +457,54 @@ COMMAND_HANDLER(handle_adapter_khz_command)
return retval;
}
#ifndef HAVE_JTAG_MINIDRIVER_H
#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
COMMAND_HANDLER(handle_usb_location_command)
{
if (CMD_ARGC == 1)
jtag_usb_set_location(CMD_ARGV[0]);
command_print(CMD_CTX, "adapter usb location: %s", jtag_usb_get_location());
return ERROR_OK;
}
#endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */
static const struct command_registration adapter_usb_command_handlers[] = {
#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
{
.name = "location",
.handler = &handle_usb_location_command,
.mode = COMMAND_CONFIG,
.help = "set the USB bus location of the USB device",
.usage = "<bus>-port[.port]...",
},
#endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */
COMMAND_REGISTRATION_DONE
};
#endif /* MINIDRIVER */
static const struct command_registration adapter_command_handlers[] = {
#ifndef HAVE_JTAG_MINIDRIVER_H
{
.name = "usb",
.mode = COMMAND_ANY,
.help = "usb adapter command group",
.usage = "",
.chain = adapter_usb_command_handlers,
},
#endif /* MINIDRIVER */
COMMAND_REGISTRATION_DONE
};
static const struct command_registration interface_command_handlers[] = {
{
.name = "adapter",
.mode = COMMAND_ANY,
.help = "adapter command group",
.usage = "",
.chain = adapter_command_handlers,
},
{
.name = "adapter_khz",
.handler = handle_adapter_khz_command,
+1 -1
View File
@@ -340,7 +340,7 @@ aice_transport_jtag_subcommand_handlers[] = {
},
{
.name = "configure",
.mode = COMMAND_EXEC,
.mode = COMMAND_ANY,
.jim_handler = jim_jtag_configure,
.help = "Provide a Tcl handler for the specified "
"TAP event.",
+1 -4
View File
@@ -2139,11 +2139,8 @@ static int aice_usb_open(struct aice_port_param_s *param)
unsigned int aice_read_ep;
unsigned int aice_write_ep;
#ifdef HAVE_LIBUSB1
jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1, LIBUSB_TRANSFER_TYPE_BULK);
#else
jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1, USB_ENDPOINT_TYPE_BULK);
#endif
LOG_DEBUG("aice_read_ep=0x%x, aice_write_ep=0x%x", aice_read_ep, aice_write_ep);
aice_handler.usb_read_ep = aice_read_ep;
+2
View File
@@ -19,6 +19,7 @@ DRIVERFILES =
# Standard Driver: common files
DRIVERFILES += %D%/driver.c
DRIVERFILES += %D%/jtag_usb_common.c
if USE_LIBUSB1
DRIVERFILES += %D%/libusb1_common.c
@@ -166,6 +167,7 @@ endif
DRIVERHEADERS = \
%D%/bitbang.h \
%D%/bitq.h \
%D%/jtag_usb_common.h \
%D%/libusb0_common.h \
%D%/libusb1_common.h \
%D%/libusb_common.h \
-3
View File
@@ -30,9 +30,6 @@
#include <jtag/interface.h>
#include <jtag/commands.h>
/* YUK! - but this is currently a global.... */
extern struct jtag_interface *jtag_interface;
/**
* Function bitbang_stableclocks
* issues a number of clock cycles while staying in a stable state.
+32 -1
View File
@@ -1096,7 +1096,7 @@ static int cmsis_dap_init(void)
if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
if (jtag_reset_config & RESET_SRST_NO_GATING) {
retval = cmsis_dap_cmd_DAP_SWJ_Pins(0, (1 << 7), 0, NULL);
retval = cmsis_dap_cmd_DAP_SWJ_Pins(0, SWJ_PIN_SRST, 0, NULL);
if (retval != ERROR_OK)
return ERROR_FAIL;
LOG_INFO("Connecting under reset");
@@ -1670,6 +1670,30 @@ COMMAND_HANDLER(cmsis_dap_handle_info_command)
return ERROR_OK;
}
COMMAND_HANDLER(cmsis_dap_handle_cmd_command)
{
int retval;
unsigned i;
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
buffer[0] = 0; /* report number */
for (i = 0; i < CMD_ARGC; i++)
buffer[i + 1] = strtoul(CMD_ARGV[i], NULL, 16);
retval = cmsis_dap_usb_xfer(cmsis_dap_handle, CMD_ARGC + 1);
if (retval != ERROR_OK) {
LOG_ERROR("CMSIS-DAP command failed.");
return ERROR_JTAG_DEVICE_ERROR;
}
LOG_INFO("Returned data %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8,
buffer[1], buffer[2], buffer[3], buffer[4]);
return ERROR_OK;
}
COMMAND_HANDLER(cmsis_dap_handle_vid_pid_command)
{
if (CMD_ARGC > MAX_USB_IDS * 2) {
@@ -1729,6 +1753,13 @@ static const struct command_registration cmsis_dap_subcommand_handlers[] = {
.usage = "",
.help = "show cmsis-dap info",
},
{
.name = "cmd",
.handler = &cmsis_dap_handle_cmd_command,
.mode = COMMAND_EXEC,
.usage = "",
.help = "issue cmsis-dap command",
},
COMMAND_REGISTRATION_DONE
};
+293 -32
View File
@@ -39,24 +39,9 @@
#include <time.h>
/*
* Bit 7 (0x80, pin 6, RI ): unused.
* Bit 6 (0x40, pin 10,DCD): /SYSRST output.
* Bit 5 (0x20, pin 9, DSR): unused.
* Bit 4 (0x10, pin 2, DTR): /TRST output.
* Bit 3 (0x08, pin 11,CTS): TMS output.
* Bit 2 (0x04, pin 3, RTS): TDO input.
* Bit 1 (0x02, pin 5, RXD): TDI output.
* Bit 0 (0x01, pin 1, TXD): TCK output.
*
* Sync bit bang mode is implemented as described in FTDI Application
* Note AN232R-01: "Bit Bang Modes for the FT232R and FT245R".
*/
#define TCK (1 << 0)
#define TDI (1 << 1)
#define READ_TDO (1 << 2)
#define TMS (1 << 3)
#define NTRST (1 << 4)
#define NSYSRST (1 << 6)
/*
* USB endpoints.
@@ -81,7 +66,7 @@
#define SIO_WRITE_EEPROM 0x91
#define SIO_ERASE_EEPROM 0x92
#define FT232R_BUF_SIZE 4000
#define FT232R_BUF_SIZE_EXTRA 4096
static char *ft232r_serial_desc;
static uint16_t ft232r_vid = 0x0403; /* FTDI */
@@ -91,6 +76,33 @@ static jtag_libusb_device_handle *adapter;
static uint8_t *ft232r_output;
static size_t ft232r_output_len;
/**
* FT232R GPIO bit number to RS232 name
*/
#define FT232R_BIT_COUNT 8
static char *ft232r_bit_name_array[FT232R_BIT_COUNT] = {
"TXD", /* 0: pin 1 TCK output */
"RXD", /* 1: pin 5 TDI output */
"RTS", /* 2: pin 3 TDO input */
"CTS", /* 3: pin 11 TMS output */
"DTR", /* 4: pin 2 /TRST output */
"DSR", /* 5: pin 9 unused */
"DCD", /* 6: pin 10 /SYSRST output */
"RI" /* 7: pin 6 unused */
};
static int tck_gpio; /* initialized to 0 by default */
static int tdi_gpio = 1;
static int tdo_gpio = 2;
static int tms_gpio = 3;
static int ntrst_gpio = 4;
static int nsysrst_gpio = 6;
static size_t ft232r_buf_size = FT232R_BUF_SIZE_EXTRA;
/** 0xFFFF disables restore by default, after exit serial port will not work.
* 0x15 sets TXD RTS DTR as outputs, after exit serial port will continue to work.
*/
static uint16_t ft232r_restore_bitmode = 0xFFFF;
/**
* Perform sync bitbang output/input transaction.
* Before call, an array ft232r_output[] should be filled with data to send.
@@ -160,20 +172,35 @@ static int ft232r_send_recv(void)
return ERROR_OK;
}
void ft232r_increase_buf_size(size_t new_buf_size)
{
uint8_t *new_buf_ptr;
if (new_buf_size >= ft232r_buf_size) {
new_buf_size += FT232R_BUF_SIZE_EXTRA;
new_buf_ptr = realloc(ft232r_output, new_buf_size);
if (new_buf_ptr != NULL) {
ft232r_output = new_buf_ptr;
ft232r_buf_size = new_buf_size;
}
}
}
/**
* Add one TCK/TMS/TDI sample to send buffer.
*/
static void ft232r_write(int tck, int tms, int tdi)
{
unsigned out_value = NTRST | NSYSRST;
unsigned out_value = (1<<ntrst_gpio) | (1<<nsysrst_gpio);
if (tck)
out_value |= TCK;
out_value |= (1<<tck_gpio);
if (tms)
out_value |= TMS;
out_value |= (1<<tms_gpio);
if (tdi)
out_value |= TDI;
out_value |= (1<<tdi_gpio);
if (ft232r_output_len >= FT232R_BUF_SIZE) {
ft232r_increase_buf_size(ft232r_output_len);
if (ft232r_output_len >= ft232r_buf_size) {
/* FIXME: should we just execute queue here? */
LOG_ERROR("ft232r_write: buffer overflow");
return;
@@ -187,20 +214,22 @@ static void ft232r_write(int tck, int tms, int tdi)
*/
static void ft232r_reset(int trst, int srst)
{
unsigned out_value = NTRST | NSYSRST;
unsigned out_value = (1<<ntrst_gpio) | (1<<nsysrst_gpio);
LOG_DEBUG("ft232r_reset(%d,%d)", trst, srst);
if (trst == 1)
out_value &= ~NTRST; /* switch /TRST low */
out_value &= ~(1<<ntrst_gpio); /* switch /TRST low */
else if (trst == 0)
out_value |= NTRST; /* switch /TRST high */
out_value |= (1<<ntrst_gpio); /* switch /TRST high */
if (srst == 1)
out_value &= ~NSYSRST; /* switch /SYSRST low */
out_value &= ~(1<<nsysrst_gpio); /* switch /SYSRST low */
else if (srst == 0)
out_value |= NSYSRST; /* switch /SYSRST high */
out_value |= (1<<nsysrst_gpio); /* switch /SYSRST high */
if (ft232r_output_len >= FT232R_BUF_SIZE) {
ft232r_increase_buf_size(ft232r_output_len);
if (ft232r_output_len >= ft232r_buf_size) {
/* FIXME: should we just execute queue here? */
LOG_ERROR("ft232r_write: buffer overflow");
return;
@@ -236,7 +265,10 @@ static int ft232r_init(void)
return ERROR_JTAG_INIT_FAILED;
}
libusb_detach_kernel_driver(adapter, 0);
if (ft232r_restore_bitmode == 0xFFFF) /* serial port will not be restored after jtag: */
libusb_detach_kernel_driver(adapter, 0);
else /* serial port will be restored after jtag: */
libusb_set_auto_detach_kernel_driver(adapter, 1); /* 1: DONT_DETACH_SIO_MODULE */
if (jtag_libusb_claim_interface(adapter, 0)) {
LOG_ERROR("unable to claim interface");
@@ -254,7 +286,7 @@ static int ft232r_init(void)
/* Sync bit bang mode. */
if (jtag_libusb_control_transfer(adapter,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
SIO_SET_BITMODE, TCK | TDI | TMS | NTRST | NSYSRST | 0x400,
SIO_SET_BITMODE, (1<<tck_gpio) | (1<<tdi_gpio) | (1<<tms_gpio) | (1<<ntrst_gpio) | (1<<nsysrst_gpio) | 0x400,
0, 0, 0, 1000) != 0) {
LOG_ERROR("cannot set sync bitbang mode");
return ERROR_JTAG_INIT_FAILED;
@@ -279,7 +311,7 @@ static int ft232r_init(void)
return ERROR_JTAG_INIT_FAILED;
}
ft232r_output = malloc(FT232R_BUF_SIZE);
ft232r_output = malloc(ft232r_buf_size);
if (ft232r_output == NULL) {
LOG_ERROR("Unable to allocate memory for the buffer");
return ERROR_JTAG_INIT_FAILED;
@@ -290,11 +322,24 @@ static int ft232r_init(void)
static int ft232r_quit(void)
{
/* to restore serial port: set TXD RTS DTR as outputs, others as inputs, disable sync bit bang mode. */
if (ft232r_restore_bitmode != 0xFFFF) {
if (jtag_libusb_control_transfer(adapter,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
SIO_SET_BITMODE, ft232r_restore_bitmode,
0, 0, 0, 1000) != 0) {
LOG_ERROR("cannot set bitmode to restore serial port");
}
}
if (jtag_libusb_release_interface(adapter, 0) != 0)
LOG_ERROR("usb release interface failed");
jtag_libusb_close(adapter);
free(ft232r_output);
free(ft232r_output); /* free used memory */
ft232r_output = NULL; /* reset pointer to memory */
ft232r_buf_size = FT232R_BUF_SIZE_EXTRA; /* reset next initial buffer size */
return ERROR_OK;
}
@@ -331,6 +376,27 @@ static int ft232r_khz(int khz, int *divisor)
return ERROR_OK;
}
static char *ft232r_bit_number_to_name(int bit)
{
if (bit >= 0 && bit < FT232R_BIT_COUNT)
return ft232r_bit_name_array[bit];
return "?";
}
static int ft232r_bit_name_to_number(const char *name)
{
int i;
if (name[0] >= '0' && name[0] <= '9' && name[1] == '\0') {
i = atoi(name);
if (i >= 0 && i < FT232R_BIT_COUNT)
return i;
}
for (i = 0; i < FT232R_BIT_COUNT; i++)
if (strcasecmp(name, ft232r_bit_name_array[i]) == 0)
return i;
return -1;
}
COMMAND_HANDLER(ft232r_handle_serial_desc_command)
{
if (CMD_ARGC == 1)
@@ -357,6 +423,145 @@ COMMAND_HANDLER(ft232r_handle_vid_pid_command)
return ERROR_OK;
}
COMMAND_HANDLER(ft232r_handle_jtag_nums_command)
{
if (CMD_ARGC == 4) {
tck_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
tms_gpio = ft232r_bit_name_to_number(CMD_ARGV[1]);
tdi_gpio = ft232r_bit_name_to_number(CMD_ARGV[2]);
tdo_gpio = ft232r_bit_name_to_number(CMD_ARGV[3]);
} else if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (tck_gpio < 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (tms_gpio < 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (tdi_gpio < 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (tdo_gpio < 0)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD_CTX,
"FT232R nums: TCK = %d %s, TMS = %d %s, TDI = %d %s, TDO = %d %s",
tck_gpio, ft232r_bit_number_to_name(tck_gpio),
tms_gpio, ft232r_bit_number_to_name(tms_gpio),
tdi_gpio, ft232r_bit_number_to_name(tdi_gpio),
tdo_gpio, ft232r_bit_number_to_name(tdo_gpio));
return ERROR_OK;
}
COMMAND_HANDLER(ft232r_handle_tck_num_command)
{
if (CMD_ARGC == 1)
tck_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
else if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (tck_gpio < 0)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD_CTX,
"FT232R num: TCK = %d %s", tck_gpio, ft232r_bit_number_to_name(tck_gpio));
return ERROR_OK;
}
COMMAND_HANDLER(ft232r_handle_tms_num_command)
{
if (CMD_ARGC == 1)
tms_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
else if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (tms_gpio < 0)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD_CTX,
"FT232R num: TMS = %d %s", tms_gpio, ft232r_bit_number_to_name(tms_gpio));
return ERROR_OK;
}
COMMAND_HANDLER(ft232r_handle_tdo_num_command)
{
if (CMD_ARGC == 1)
tdo_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
else if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (tdo_gpio < 0)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD_CTX,
"FT232R num: TDO = %d %s", tdo_gpio, ft232r_bit_number_to_name(tdo_gpio));
return ERROR_OK;
}
COMMAND_HANDLER(ft232r_handle_tdi_num_command)
{
if (CMD_ARGC == 1)
tdi_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
else if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (tdi_gpio < 0)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD_CTX,
"FT232R num: TDI = %d %s", tdi_gpio, ft232r_bit_number_to_name(tdi_gpio));
return ERROR_OK;
}
COMMAND_HANDLER(ft232r_handle_trst_num_command)
{
if (CMD_ARGC == 1)
ntrst_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
else if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (ntrst_gpio < 0)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD_CTX,
"FT232R num: TRST = %d %s", ntrst_gpio, ft232r_bit_number_to_name(ntrst_gpio));
return ERROR_OK;
}
COMMAND_HANDLER(ft232r_handle_srst_num_command)
{
if (CMD_ARGC == 1)
nsysrst_gpio = ft232r_bit_name_to_number(CMD_ARGV[0]);
else if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
if (nsysrst_gpio < 0)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD_CTX,
"FT232R num: SRST = %d %s", nsysrst_gpio, ft232r_bit_number_to_name(nsysrst_gpio));
return ERROR_OK;
}
COMMAND_HANDLER(ft232r_handle_restore_serial_command)
{
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], ft232r_restore_bitmode);
else if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD_CTX,
"FT232R restore serial: 0x%04X (%s)",
ft232r_restore_bitmode, ft232r_restore_bitmode == 0xFFFF ? "disabled" : "enabled");
return ERROR_OK;
}
static const struct command_registration ft232r_command_handlers[] = {
{
.name = "ft232r_serial_desc",
@@ -372,6 +577,62 @@ static const struct command_registration ft232r_command_handlers[] = {
.help = "USB VID and PID of the adapter",
.usage = "vid pid",
},
{
.name = "ft232r_jtag_nums",
.handler = ft232r_handle_jtag_nums_command,
.mode = COMMAND_CONFIG,
.help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
.usage = "<0-7|TXD-RI> <0-7|TXD-RI> <0-7|TXD-RI> <0-7|TXD-RI>",
},
{
.name = "ft232r_tck_num",
.handler = ft232r_handle_tck_num_command,
.mode = COMMAND_CONFIG,
.help = "gpio number for tck.",
.usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
},
{
.name = "ft232r_tms_num",
.handler = ft232r_handle_tms_num_command,
.mode = COMMAND_CONFIG,
.help = "gpio number for tms.",
.usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
},
{
.name = "ft232r_tdo_num",
.handler = ft232r_handle_tdo_num_command,
.mode = COMMAND_CONFIG,
.help = "gpio number for tdo.",
.usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
},
{
.name = "ft232r_tdi_num",
.handler = ft232r_handle_tdi_num_command,
.mode = COMMAND_CONFIG,
.help = "gpio number for tdi.",
.usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
},
{
.name = "ft232r_srst_num",
.handler = ft232r_handle_srst_num_command,
.mode = COMMAND_CONFIG,
.help = "gpio number for srst.",
.usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
},
{
.name = "ft232r_trst_num",
.handler = ft232r_handle_trst_num_command,
.mode = COMMAND_CONFIG,
.help = "gpio number for trst.",
.usage = "<0-7|TXD|RXD|RTS|CTS|DTR|DSR|DCD|RI>",
},
{
.name = "ft232r_restore_serial",
.handler = ft232r_handle_restore_serial_command,
.mode = COMMAND_CONFIG,
.help = "bitmode control word that restores serial port.",
.usage = "bitmode_control_word",
},
COMMAND_REGISTRATION_DONE
};
@@ -553,7 +814,7 @@ static void syncbb_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int
int bcval = 1 << (bit_cnt % 8);
int val = ft232r_output[bit0_index + bit_cnt*2 + 1];
if (val & READ_TDO)
if (val & (1<<tdo_gpio))
buffer[bytec] |= bcval;
else
buffer[bytec] &= ~bcval;
+2 -2
View File
@@ -160,10 +160,10 @@ static int imx_gpio_swd_write(int tck, int tms, int tdi)
static int imx_gpio_reset(int trst, int srst)
{
if (trst_gpio != -1)
trst ? gpio_set(trst_gpio) : gpio_clear(trst_gpio);
trst ? gpio_clear(trst_gpio) : gpio_set(trst_gpio);
if (srst_gpio != -1)
srst ? gpio_set(srst_gpio) : gpio_clear(srst_gpio);
srst ? gpio_clear(srst_gpio) : gpio_set(srst_gpio);
return ERROR_OK;
}
+1 -1
View File
@@ -2130,7 +2130,7 @@ skip:
static void jlink_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint32_t ap_delay_clk)
{
uint8_t data_parity_trn[DIV_ROUND_UP(32 + 1, 8)];
if (tap_length + 46 + 8 + ap_delay_clk >= sizeof(tdi_buffer) * 8 ||
if (tap_length + 46 + 8 + ap_delay_clk >= swd_buffer_size * 8 ||
pending_scan_results_length == MAX_PENDING_SCAN_RESULTS) {
/* Not enough room in the queue. Run the queue. */
queued_retval = jlink_swd_run_queue();
+85
View File
@@ -0,0 +1,85 @@
/*
* SPDX-License-Identifier: GPL-2.0+
* Copyright (c) 2018 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
*/
#include <helper/log.h>
#include "jtag_usb_common.h"
static char *jtag_usb_location;
/*
* 1 char: bus
* 2 * 7 chars: max 7 ports
* 1 char: test for overflow
* ------
* 16 chars
*/
#define JTAG_USB_MAX_LOCATION_LENGHT 16
void jtag_usb_set_location(const char *location)
{
if (strnlen(location, JTAG_USB_MAX_LOCATION_LENGHT) ==
JTAG_USB_MAX_LOCATION_LENGHT)
LOG_WARNING("usb location string is too long!!\n");
if (jtag_usb_location)
free(jtag_usb_location);
jtag_usb_location = strndup(location, JTAG_USB_MAX_LOCATION_LENGHT);
}
const char *jtag_usb_get_location(void)
{
return jtag_usb_location;
}
bool jtag_usb_location_equal(uint8_t dev_bus, uint8_t *port_path,
size_t path_len)
{
size_t path_step, string_lengh;
char *ptr, *loc;
bool equal = false;
/* strtok need non const char */
loc = strndup(jtag_usb_get_location(), JTAG_USB_MAX_LOCATION_LENGHT);
string_lengh = strnlen(loc, JTAG_USB_MAX_LOCATION_LENGHT);
ptr = strtok(loc, "-");
if (ptr == NULL) {
LOG_WARNING("no '-' in usb path\n");
goto done;
}
string_lengh -= 1;
/* check bus mismatch */
if (atoi(ptr) != dev_bus)
goto done;
path_step = 0;
while (path_step < path_len) {
ptr = strtok(NULL, ".");
/* no more tokens in path */
if (ptr == NULL)
break;
/* path mismatch at some step */
if (path_step < path_len && atoi(ptr) != port_path[path_step])
break;
path_step++;
string_lengh -= 2;
};
/* walked the full path, all elements match */
if (path_step == path_len && !string_lengh)
equal = true;
else
LOG_WARNING("excluded by device path option: %s\n",
jtag_usb_get_location());
done:
free(loc);
return equal;
}
+14
View File
@@ -0,0 +1,14 @@
/*
* SPDX-License-Identifier: GPL-2.0+
* Copyright (c) 2018 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
*/
#ifndef OPENOCD_JTAG_USB_COMMON_H
#define OPENOCD_JTAG_USB_COMMON_H
void jtag_usb_set_location(const char *location);
const char *jtag_usb_get_location(void);
bool jtag_usb_location_equal(uint8_t dev_bus, uint8_t *port_path,
size_t path_len);
#endif /* OPENOCD_JTAG_USB_COMMON_H */
+13
View File
@@ -29,6 +29,10 @@
#include <arpa/inet.h>
#endif
#ifndef _WIN32
#include <netinet/tcp.h>
#endif
#define NO_TAP_SHIFT 0
#define TAP_SHIFT 1
@@ -368,6 +372,8 @@ static int jtag_vpi_execute_queue(void)
static int jtag_vpi_init(void)
{
int flag = 1;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
LOG_ERROR("Could not create socket");
@@ -395,6 +401,13 @@ static int jtag_vpi_init(void)
return ERROR_COMMAND_CLOSE_CONNECTION;
}
if (serv_addr.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
/* This increases performance drematically for local
* connections, which is the most likely arrangement
* for a VPI connection. */
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
}
LOG_INFO("Connection to %s : %u succeed", server_address, server_port);
return ERROR_OK;
+10 -3
View File
@@ -67,7 +67,8 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
const char *serial,
struct jtag_libusb_device_handle **out)
{
int retval = -ENODEV;
int retval = ERROR_FAIL;
bool serial_mismatch = false;
struct jtag_libusb_device_handle *libusb_handle;
usb_init();
@@ -83,21 +84,27 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
libusb_handle = usb_open(dev);
if (NULL == libusb_handle) {
retval = -errno;
LOG_ERROR("usb_open() failed with %s", usb_strerror());
continue;
}
/* Device must be open to use libusb_get_string_descriptor_ascii. */
if (serial != NULL &&
!string_descriptor_equal(libusb_handle, dev->descriptor.iSerialNumber, serial)) {
serial_mismatch = true;
usb_close(libusb_handle);
continue;
}
*out = libusb_handle;
retval = 0;
retval = ERROR_OK;
serial_mismatch = false;
break;
}
}
if (serial_mismatch)
LOG_INFO("No device matches the serial string");
return retval;
}
+1
View File
@@ -38,6 +38,7 @@
#define LIBUSB_RECIPIENT_DEVICE USB_RECIP_DEVICE
#define LIBUSB_ENDPOINT_OUT USB_ENDPOINT_OUT
#define LIBUSB_ENDPOINT_IN USB_ENDPOINT_IN
#define LIBUSB_TRANSFER_TYPE_BULK USB_ENDPOINT_TYPE_BULK
static inline int jtag_libusb_claim_interface(jtag_libusb_device_handle *devh,
int iface)
+43 -1
View File
@@ -20,8 +20,15 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "log.h"
#include <jtag/drivers/jtag_usb_common.h>
#include "libusb1_common.h"
#include "log.h"
/*
* comment from libusb:
* As per the USB 3.0 specs, the current maximum limit for the depth is 7.
*/
#define MAX_USB_PORTS 7
static struct libusb_context *jtag_libusb_context; /**< Libusb context **/
static libusb_device **devs; /**< The usb device list **/
@@ -38,6 +45,31 @@ static bool jtag_libusb_match(struct libusb_device_descriptor *dev_desc,
return false;
}
#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
static bool jtag_libusb_location_equal(libusb_device *device)
{
uint8_t port_path[MAX_USB_PORTS];
uint8_t dev_bus;
int path_len;
path_len = libusb_get_port_numbers(device, port_path, MAX_USB_PORTS);
if (path_len == LIBUSB_ERROR_OVERFLOW) {
LOG_WARNING("cannot determine path to usb device! (more than %i ports in path)\n",
MAX_USB_PORTS);
return false;
}
dev_bus = libusb_get_bus_number(device);
return jtag_usb_location_equal(dev_bus, port_path, path_len);
}
#else /* HAVE_LIBUSB_GET_PORT_NUMBERS */
static bool jtag_libusb_location_equal(libusb_device *device)
{
return true;
}
#endif /* HAVE_LIBUSB_GET_PORT_NUMBERS */
/* Returns true if the string descriptor indexed by str_index in device matches string */
static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_index,
const char *string)
@@ -72,6 +104,7 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
{
int cnt, idx, errCode;
int retval = ERROR_FAIL;
bool serial_mismatch = false;
struct jtag_libusb_device_handle *libusb_handle = NULL;
if (libusb_init(&jtag_libusb_context) < 0)
@@ -88,6 +121,9 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
if (!jtag_libusb_match(&dev_desc, vids, pids))
continue;
if (jtag_usb_get_location() && !jtag_libusb_location_equal(devs[idx]))
continue;
errCode = libusb_open(devs[idx], &libusb_handle);
if (errCode) {
@@ -99,6 +135,7 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
/* Device must be open to use libusb_get_string_descriptor_ascii. */
if (serial != NULL &&
!string_descriptor_equal(libusb_handle, dev_desc.iSerialNumber, serial)) {
serial_mismatch = true;
libusb_close(libusb_handle);
continue;
}
@@ -106,10 +143,15 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
/* Success. */
*out = libusb_handle;
retval = ERROR_OK;
serial_mismatch = false;
break;
}
if (cnt >= 0)
libusb_free_device_list(devs, 1);
if (serial_mismatch)
LOG_INFO("No device matches the serial string");
return retval;
}
File diff suppressed because it is too large Load Diff
+12 -2
View File
@@ -457,62 +457,70 @@ static const struct command_registration sysfsgpio_command_handlers[] = {
.handler = &sysfsgpio_handle_jtag_gpionums,
.mode = COMMAND_CONFIG,
.help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
.usage = "(tck tms tdi tdo)* ",
.usage = "[tck tms tdi tdo]",
},
{
.name = "sysfsgpio_tck_num",
.handler = &sysfsgpio_handle_jtag_gpionum_tck,
.mode = COMMAND_CONFIG,
.help = "gpio number for tck.",
.usage = "[tck]",
},
{
.name = "sysfsgpio_tms_num",
.handler = &sysfsgpio_handle_jtag_gpionum_tms,
.mode = COMMAND_CONFIG,
.help = "gpio number for tms.",
.usage = "[tms]",
},
{
.name = "sysfsgpio_tdo_num",
.handler = &sysfsgpio_handle_jtag_gpionum_tdo,
.mode = COMMAND_CONFIG,
.help = "gpio number for tdo.",
.usage = "[tdo]",
},
{
.name = "sysfsgpio_tdi_num",
.handler = &sysfsgpio_handle_jtag_gpionum_tdi,
.mode = COMMAND_CONFIG,
.help = "gpio number for tdi.",
.usage = "[tdi]",
},
{
.name = "sysfsgpio_srst_num",
.handler = &sysfsgpio_handle_jtag_gpionum_srst,
.mode = COMMAND_CONFIG,
.help = "gpio number for srst.",
.usage = "[srst]",
},
{
.name = "sysfsgpio_trst_num",
.handler = &sysfsgpio_handle_jtag_gpionum_trst,
.mode = COMMAND_CONFIG,
.help = "gpio number for trst.",
.usage = "[trst]",
},
{
.name = "sysfsgpio_swd_nums",
.handler = &sysfsgpio_handle_swd_gpionums,
.mode = COMMAND_CONFIG,
.help = "gpio numbers for swclk, swdio. (in that order)",
.usage = "(swclk swdio)* ",
.usage = "[swclk swdio]",
},
{
.name = "sysfsgpio_swclk_num",
.handler = &sysfsgpio_handle_swd_gpionum_swclk,
.mode = COMMAND_CONFIG,
.help = "gpio number for swclk.",
.usage = "[swclk]",
},
{
.name = "sysfsgpio_swdio_num",
.handler = &sysfsgpio_handle_swd_gpionum_swdio,
.mode = COMMAND_CONFIG,
.help = "gpio number for swdio.",
.usage = "[swdio]",
},
COMMAND_REGISTRATION_DONE
};
@@ -561,6 +569,8 @@ static void cleanup_all_fds(void)
cleanup_fd(tdo_fd, tdo_gpio);
cleanup_fd(trst_fd, trst_gpio);
cleanup_fd(srst_fd, srst_gpio);
cleanup_fd(swclk_fd, swclk_gpio);
cleanup_fd(swdio_fd, swdio_gpio);
}
static bool sysfsgpio_jtag_mode_possible(void)
+7 -4
View File
@@ -19,6 +19,7 @@
#include "config.h"
#endif
#include "usb_common.h"
#include "log.h"
static bool jtag_usb_match(struct usb_device *dev,
@@ -45,10 +46,12 @@ int jtag_usb_open(const uint16_t vids[], const uint16_t pids[],
continue;
*out = usb_open(dev);
if (NULL == *out)
return -errno;
return 0;
if (NULL == *out) {
LOG_ERROR("usb_open() failed with %s", usb_strerror());
return ERROR_FAIL;
}
return ERROR_OK;
}
}
return -ENODEV;
return ERROR_FAIL;
}
+84 -1
View File
@@ -29,6 +29,13 @@
/* XDS110 USB serial number length */
#define XDS110_SERIAL_LEN 8
/* XDS110 stand-alone probe voltage supply limits */
#define XDS110_MIN_VOLTAGE 1800
#define XDS110_MAX_VOLTAGE 3600
/* XDS110 stand-alone probe hardware ID */
#define XDS110_STAND_ALONE_ID 0x21
/* Firmware version that introduced OpenOCD support via block accesses */
#define OCD_FIRMWARE_VERSION 0x02030011
#define OCD_FIRMWARE_UPGRADE \
@@ -162,6 +169,7 @@
#define SWD_DISCONNECT 0x18 /* Switch from SWD to JTAG connection */
#define CJTAG_CONNECT 0x2b /* Switch from JTAG to cJTAG connection */
#define CJTAG_DISCONNECT 0x2c /* Switch from cJTAG to JTAG connection */
#define XDS_SET_SUPPLY 0x32 /* Set up stand-alone probe upply voltage */
#define OCD_DAP_REQUEST 0x3a /* Handle block of DAP requests */
#define OCD_SCAN_REQUEST 0x3b /* Handle block of JTAG scan requests */
#define OCD_PATHMOVE 0x3c /* Handle PATHMOVE to navigate JTAG states */
@@ -219,6 +227,8 @@ struct xds110_info {
uint32_t delay_count;
/* XDS110 serial number */
char serial[XDS110_SERIAL_LEN + 1];
/* XDS110 voltage supply setting */
uint32_t voltage;
/* XDS110 firmware and hardware version */
uint32_t firmware;
uint16_t hardware;
@@ -242,6 +252,7 @@ static struct xds110_info xds110 = {
.speed = XDS110_MAX_TCK_SPEED,
.delay_count = 0,
.serial = {0},
.voltage = 0,
.firmware = 0,
.hardware = 0,
.txn_request_size = 0,
@@ -601,10 +612,15 @@ static bool xds_execute(uint32_t out_length, uint32_t in_length,
if (bytes_read != in_length) {
/* Unexpected amount of data returned */
success = false;
LOG_DEBUG("XDS110: command 0x%02x return %d bytes, expected %d",
xds110.write_payload[0], bytes_read, in_length);
} else {
/* Extract error code from return packet */
error = (int)xds110_get_u32(&xds110.read_payload[0]);
done = true;
if (SC_ERR_NONE != error)
LOG_DEBUG("XDS110: command 0x%02x returned error %d",
xds110.write_payload[0], error);
}
}
}
@@ -952,6 +968,24 @@ static bool cjtag_disconnect(void)
return success;
}
static bool xds_set_supply(uint32_t voltage)
{
uint8_t *volts_pntr = &xds110.write_payload[XDS_OUT_LEN + 0]; /* 32-bits */
uint8_t *source_pntr = &xds110.write_payload[XDS_OUT_LEN + 4]; /* 8-bits */
bool success;
xds110.write_payload[0] = XDS_SET_SUPPLY;
xds110_set_u32(volts_pntr, voltage);
*source_pntr = (uint8_t)(0 != voltage ? 1 : 0);
success = xds_execute(XDS_OUT_LEN + 5, XDS_IN_LEN, DEFAULT_ATTEMPTS,
DEFAULT_TIMEOUT);
return success;
}
static bool ocd_dap_request(uint8_t *dap_requests, uint32_t request_size,
uint32_t *dap_results, uint32_t result_count)
{
@@ -1318,7 +1352,7 @@ static void xds110_show_info(void)
(((firmware >> 4) & 0xf) * 10) + ((firmware >> 0) & 0xf));
LOG_INFO("XDS110: hardware version = 0x%04x", xds110.hardware);
if (0 != xds110.serial[0])
LOG_INFO("XDS110: serial number = %s)", xds110.serial);
LOG_INFO("XDS110: serial number = %s", xds110.serial);
if (xds110.is_swd_mode) {
LOG_INFO("XDS110: connected to target via SWD");
LOG_INFO("XDS110: SWCLK set to %d kHz", xds110.speed);
@@ -1390,6 +1424,20 @@ static int xds110_init(void)
}
}
if (success) {
/* Set supply voltage for stand-alone probes */
if (XDS110_STAND_ALONE_ID == xds110.hardware) {
success = xds_set_supply(xds110.voltage);
/* Allow time for target device to power up */
/* (CC32xx takes up to 1300 ms before debug is enabled) */
alive_sleep(1500);
} else if (0 != xds110.voltage) {
/* Voltage supply not a feature of embedded probes */
LOG_WARNING(
"XDS110: ignoring supply voltage, not supported on this probe");
}
}
if (success) {
success = xds_set_trst(0);
if (success)
@@ -1569,6 +1617,9 @@ static void xds110_execute_reset(struct jtag_command *cmd)
srst = 0;
}
(void)xds_set_srst(srst);
/* Toggle TCK to trigger HIB on CC13x/CC26x devices */
(void)xds_cycle_tck(60000);
}
}
@@ -1918,6 +1969,31 @@ COMMAND_HANDLER(xds110_handle_serial_command)
return ERROR_OK;
}
COMMAND_HANDLER(xds110_handle_supply_voltage_command)
{
uint32_t voltage = 0;
if (CMD_ARGC == 1) {
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], voltage);
if (voltage == 0 || (voltage >= XDS110_MIN_VOLTAGE && voltage
<= XDS110_MAX_VOLTAGE)) {
/* Requested voltage is in range */
xds110.voltage = voltage;
} else {
LOG_ERROR("XDS110: voltage must be 0 or between %d and %d "
"millivolts", XDS110_MIN_VOLTAGE, XDS110_MAX_VOLTAGE);
return ERROR_FAIL;
}
xds110.voltage = voltage;
} else {
LOG_ERROR("XDS110: expected one argument to xds110_supply_voltage "
"<millivolts>");
return ERROR_FAIL;
}
return ERROR_OK;
}
static const struct command_registration xds110_subcommand_handlers[] = {
{
.name = "info",
@@ -1944,6 +2020,13 @@ static const struct command_registration xds110_command_handlers[] = {
.help = "set the XDS110 probe serial number",
.usage = "serial_string",
},
{
.name = "xds110_supply_voltage",
.handler = &xds110_handle_supply_voltage_command,
.mode = COMMAND_CONFIG,
.help = "set the XDS110 probe supply voltage",
.usage = "supply_voltage (millivolts)",
},
COMMAND_REGISTRATION_DONE
};
+110 -16
View File
@@ -53,16 +53,25 @@ static inline uint8_t swd_cmd(bool is_read, bool is_ap, uint8_t regnum)
/* SWD_ACK_* bits are defined in <target/arm_adi_v5.h> */
/*
* The following sequences are updated to
* ARM(tm) Debug Interface v5 Architecture Specification ARM IHI 0031E
*/
/**
* Line reset.
* SWD Line reset.
*
* Line reset is at least 50 SWCLK cycles with SWDIO driven high, followed
* by at least one idle (low) cycle.
* SWD Line reset is at least 50 SWCLK cycles with SWDIO driven high,
* followed by at least two idle (low) cycle.
* Bits are stored (and transmitted) LSB-first.
*/
static const uint8_t swd_seq_line_reset[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03
/* At least 50 SWCLK cycles with SWDIO high */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/* At least 2 idle (low) cycles */
0x00,
};
static const unsigned swd_seq_line_reset_len = 51;
static const unsigned swd_seq_line_reset_len = 64;
/**
* JTAG-to-SWD sequence.
@@ -71,36 +80,53 @@ static const unsigned swd_seq_line_reset_len = 51;
* high, putting either interface logic into reset state, followed by a
* specific 16-bit sequence and finally a line reset in case the SWJ-DP was
* already in SWD mode.
* Bits are stored (and transmitted) LSB-first.
*/
static const uint8_t swd_seq_jtag_to_swd[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x9e,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
/* At least 50 TCK/SWCLK cycles with TMS/SWDIO high */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/* Switching sequence from JTAG to SWD */
0x9e, 0xe7,
/* At least 50 TCK/SWCLK cycles with TMS/SWDIO high */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/* At least 2 idle (low) cycles */
0x00,
};
static const unsigned swd_seq_jtag_to_swd_len = 118;
static const unsigned swd_seq_jtag_to_swd_len = 136;
/**
* SWD-to-JTAG sequence.
*
* The SWD-to-JTAG sequence is at least 50 TCK/SWCLK cycles with TMS/SWDIO
* high, putting either interface logic into reset state, followed by a
* specific 16-bit sequence and finally at least 5 TCK cycles to put the
* JTAG TAP in TLR.
* specific 16-bit sequence and finally at least 5 TCK/SWCLK cycles with
* TMS/SWDIO high to put the JTAG TAP in Test-Logic-Reset state.
* Bits are stored (and transmitted) LSB-first.
*/
static const uint8_t swd_seq_swd_to_jtag[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x9c, 0xff
/* At least 50 TCK/SWCLK cycles with TMS/SWDIO high */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/* Switching sequence from SWD to JTAG */
0x3c, 0xe7,
/* At least 5 TCK/SWCLK cycles with TMS/SWDIO high */
0xff,
};
static const unsigned swd_seq_swd_to_jtag_len = 71;
static const unsigned swd_seq_swd_to_jtag_len = 80;
/**
* SWD-to-dormant sequence.
*
* This is at least 50 SWCLK cycles with SWDIO high to put the interface
* in reset state, followed by a specific 16-bit sequence.
* Bits are stored (and transmitted) LSB-first.
*/
static const uint8_t swd_seq_swd_to_dormant[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x8e, 0x03
/* At least 50 SWCLK cycles with SWDIO high */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/* Switching sequence from SWD to dormant */
0xbc, 0xe3,
};
static const unsigned swd_seq_swd_to_dormant_len = 66;
static const unsigned swd_seq_swd_to_dormant_len = 72;
/**
* Dormant-to-SWD sequence.
@@ -110,14 +136,82 @@ static const unsigned swd_seq_swd_to_dormant_len = 66;
* sequence, followed by 4 TCK/SWCLK cycles with TMS/SWDIO low, followed by
* a specific protocol-dependent activation code. For SWD the activation code
* is an 8-bit sequence. The sequence ends with a line reset.
* Bits are stored (and transmitted) LSB-first.
*/
static const uint8_t swd_seq_dormant_to_swd[] = {
/* At least 8 SWCLK cycles with SWDIO high */
0xff,
/* Selection alert sequence */
0x92, 0xf3, 0x09, 0x62, 0x95, 0x2d, 0x85, 0x86,
0xe9, 0xaf, 0xdd, 0xe3, 0xa2, 0x0e, 0xbc, 0x19,
0x10, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f
/*
* 4 SWCLK cycles with SWDIO low ...
* + SWD activation code 0x1a ...
* + at least 8 SWCLK cycles with SWDIO high
*/
0xa0, /* ((0x00) & GENMASK(3, 0)) | ((0x1a << 4) & GENMASK(7, 4)) */
0xf1, /* ((0x1a >> 4) & GENMASK(3, 0)) | ((0xff << 4) & GENMASK(7, 4)) */
0xff,
/* At least 50 SWCLK cycles with SWDIO high */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/* At least 2 idle (low) cycles */
0x00,
};
static const unsigned swd_seq_dormant_to_swd_len = 199;
static const unsigned swd_seq_dormant_to_swd_len = 224;
/**
* JTAG-to-dormant sequence.
*
* This is at least 5 TCK cycles with TMS high to put the interface
* in test-logic-reset state, followed by a specific 31-bit sequence.
* Bits are stored (and transmitted) LSB-first.
*/
static const uint8_t swd_seq_jtag_to_dormant[] = {
/* At least 5 TCK cycles with TMS high */
0xff,
/*
* Still one TCK cycle with TMS high followed by 31 bits JTAG-to-DS
* select sequence 0xba, 0xbb, 0xbb, 0x33,
*/
0x75, /* ((0xff >> 7) & GENMASK(0, 0)) | ((0xba << 1) & GENMASK(7, 1)) */
0x77, /* ((0xba >> 7) & GENMASK(0, 0)) | ((0xbb << 1) & GENMASK(7, 1)) */
0x77, /* ((0xbb >> 7) & GENMASK(0, 0)) | ((0xbb << 1) & GENMASK(7, 1)) */
0x67, /* ((0xbb >> 7) & GENMASK(0, 0)) | ((0x33 << 1) & GENMASK(7, 1)) */
};
static const unsigned swd_seq_jtag_to_dormant_len = 40;
/**
* Dormant-to-JTAG sequence.
*
* This is at least 8 TCK/SWCLK cycles with TMS/SWDIO high to abort any ongoing
* selection alert sequence, followed by a specific 128-bit selection alert
* sequence, followed by 4 TCK/SWCLK cycles with TMS/SWDIO low, followed by
* a specific protocol-dependent activation code. For JTAG there are two
* possible activation codes:
* - "JTAG-Serial": 12 bits 0x00, 0x00
* - "Arm CoreSight JTAG-DP": 8 bits 0x0a
* We use "JTAG-Serial" only, which seams more generic.
* Since the target TAP can be either in Run/Test Idle or in Test-Logic-Reset
* states, Arm recommends to put the TAP in Run/Test Idle using one TCK cycle
* with TMS low. To keep the sequence length multiple of 8, 8 TCK cycle with
* TMS low are sent (allowed by JTAG state machine).
* Bits are stored (and transmitted) LSB-first.
*/
static const uint8_t swd_seq_dormant_to_jtag[] = {
/* At least 8 TCK/SWCLK cycles with TMS/SWDIO high */
0xff,
/* Selection alert sequence */
0x92, 0xf3, 0x09, 0x62, 0x95, 0x2d, 0x85, 0x86,
0xe9, 0xaf, 0xdd, 0xe3, 0xa2, 0x0e, 0xbc, 0x19,
/*
* 4 TCK/SWCLK cycles with TMS/SWDIO low ...
* + 12 bits JTAG-serial activation code 0x00, 0x00
*/
0x00, 0x00,
/* put the TAP in Run/Test Idle */
0x00,
};
static const unsigned swd_seq_dormant_to_jtag_len = 160;
enum swd_special_seq {
LINE_RESET,
+1 -1
View File
@@ -894,7 +894,7 @@ static const struct command_registration jtag_subcommand_handlers[] = {
},
{
.name = "configure",
.mode = COMMAND_EXEC,
.mode = COMMAND_ANY,
.jim_handler = jim_jtag_configure,
.help = "Provide a Tcl handler for the specified "
"TAP event.",
+1
View File
@@ -12,6 +12,7 @@ noinst_LTLIBRARIES += %D%/librtos.la
%D%/eCos.c \
%D%/linux.c \
%D%/ChibiOS.c \
%D%/chromium-ec.c \
%D%/embKernel.c \
%D%/mqx.c \
%D%/riscv_debug.c \
+387
View File
@@ -0,0 +1,387 @@
/*
* SPDX-License-Identifier: GPL-2.0
*
* Copyright (c) 2018 National Instruments Corp
* Author: Moritz Fischer <moritz.fischer@ettus.com>
*
* Chromium-EC RTOS Task Awareness
*/
#include <rtos/rtos.h>
#include <target/target.h>
#include <target/target_type.h>
#include "rtos_standard_stackings.h"
#define CROS_EC_MAX_TASKS 32
#define CROS_EC_MAX_NAME 200
#define CROS_EC_IDLE_STRING "<< idle >>"
#define BIT(x) (1 << (x))
struct chromium_ec_params {
const char *target_name;
size_t ptr_size;
off_t task_offset_next;
off_t task_offset_sp;
off_t task_offset_events;
off_t task_offset_runtime;
const struct rtos_register_stacking *stacking;
};
static const struct chromium_ec_params chromium_ec_params_list[] = {
{
.target_name = "hla_target",
.ptr_size = 4,
.task_offset_next = 24,
.task_offset_sp = 0,
.task_offset_events = 4,
.task_offset_runtime = 8,
.stacking = &rtos_standard_Cortex_M3_stacking,
},
{
.target_name = "cortex_m",
.ptr_size = 4,
.task_offset_next = 24,
.task_offset_sp = 0,
.task_offset_events = 4,
.task_offset_runtime = 8,
.stacking = &rtos_standard_Cortex_M3_stacking,
},
};
static const char * const chromium_ec_symbol_list[] = {
"start_called",
"current_task",
"tasks",
"tasks_enabled",
"tasks_ready",
"task_names",
"build_info",
NULL,
};
enum chromium_ec_symbol_values {
CHROMIUM_EC_VAL_start_called = 0,
CHROMIUM_EC_VAL_current_task,
CHROMIUM_EC_VAL_tasks,
CHROMIUM_EC_VAL_tasks_enabled,
CHROMIUM_EC_VAL_tasks_ready,
CHROMIUM_EC_VAL_task_names,
CHROMIUM_EC_VAL_build_info,
CHROMIUM_EC_VAL_COUNT,
};
#define CROS_EC_MAX_BUILDINFO 512
static bool chromium_ec_detect_rtos(struct target *target)
{
char build_info_buf[CROS_EC_MAX_BUILDINFO];
enum chromium_ec_symbol_values sym;
int ret;
if (!target || !target->rtos || !target->rtos->symbols)
return false;
for (sym = CHROMIUM_EC_VAL_start_called;
sym < CHROMIUM_EC_VAL_COUNT; sym++) {
if (target->rtos->symbols[sym].address) {
LOG_DEBUG("Chromium-EC: Symbol \"%s\" found",
chromium_ec_symbol_list[sym]);
} else {
LOG_ERROR("Chromium-EC: Symbol \"%s\" missing",
chromium_ec_symbol_list[sym]);
return false;
}
}
ret = target_read_buffer(target,
target->rtos->symbols[CHROMIUM_EC_VAL_build_info].address,
sizeof(build_info_buf),
(uint8_t *)build_info_buf);
if (ret != ERROR_OK)
return false;
LOG_INFO("Chromium-EC: Buildinfo: %s", build_info_buf);
return target->rtos->symbols &&
target->rtos->symbols[CHROMIUM_EC_VAL_start_called].address;
}
static int chromium_ec_create(struct target *target)
{
struct chromium_ec_params *params;
size_t t;
for (t = 0; t < ARRAY_SIZE(chromium_ec_params_list); t++)
if (!strcmp(chromium_ec_params_list[t].target_name, target->type->name)) {
params = malloc(sizeof(*params));
if (!params) {
LOG_ERROR("Chromium-EC: out of memory");
return ERROR_FAIL;
}
memcpy(params, &chromium_ec_params_list[t], sizeof(*params));
target->rtos->rtos_specific_params = (void *)params;
target->rtos->current_thread = 0;
target->rtos->thread_details = NULL;
target->rtos->thread_count = 0;
LOG_INFO("Chromium-EC: Using target: %s", target->type->name);
return ERROR_OK;
}
LOG_ERROR("Chromium-EC: target not supported: %s", target->type->name);
return ERROR_FAIL;
}
static int chromium_ec_get_current_task_ptr(struct rtos *rtos, uint32_t *current_task)
{
if (!rtos || !rtos->symbols)
return ERROR_FAIL;
return target_read_u32(rtos->target,
rtos->symbols[CHROMIUM_EC_VAL_current_task].address,
current_task);
}
static int chromium_ec_get_num_tasks(struct rtos *rtos, int *num_tasks)
{
uint32_t tasks_enabled;
int ret, t, found;
ret = target_read_u32(rtos->target,
rtos->symbols[CHROMIUM_EC_VAL_tasks_enabled].address,
&tasks_enabled);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to determine #of tasks");
return ret;
}
found = 0;
for (t = 0; t < CROS_EC_MAX_TASKS; t++)
if (tasks_enabled & BIT(t))
found++;
*num_tasks = found;
return ERROR_OK;
}
static int chromium_ec_update_threads(struct rtos *rtos)
{
uint32_t tasks_enabled, tasks_ready, start_called;
uint32_t current_task, thread_ptr, name_ptr;
char thread_str_buf[CROS_EC_MAX_NAME];
int ret, t, num_tasks, tasks_found;
struct chromium_ec_params *params;
uint8_t runtime_buf[8];
uint64_t runtime;
uint32_t events;
params = rtos->rtos_specific_params;
if (!params)
return ERROR_FAIL;
if (!rtos->symbols)
return ERROR_FAIL;
num_tasks = 0;
ret = chromium_ec_get_num_tasks(rtos, &num_tasks);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to get number of tasks");
return ret;
}
current_task = 0;
ret = chromium_ec_get_current_task_ptr(rtos, &current_task);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to get current task");
return ret;
}
LOG_DEBUG("Current task: %lx tasks_found: %d",
(unsigned long)current_task,
num_tasks);
/* set current task to what we read */
rtos->current_thread = current_task;
/* Nuke the old tasks */
rtos_free_threadlist(rtos);
/* One check if task switching has started ... */
start_called = 0;
ret = target_read_u32(rtos->target, rtos->symbols[CHROMIUM_EC_VAL_start_called].address,
&start_called);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to load start_called");
return ret;
}
if (!rtos->current_thread || !num_tasks || !start_called) {
num_tasks++;
rtos->thread_details = malloc(
sizeof(struct thread_detail) * num_tasks);
rtos->thread_details->threadid = 1;
rtos->thread_details->exists = true;
rtos->thread_details->extra_info_str = NULL;
rtos->thread_details->thread_name_str = strdup("Current Execution");
if (!num_tasks || !start_called) {
rtos->thread_count = 1;
return ERROR_OK;
}
} else {
/* create space for new thread details */
rtos->thread_details = malloc(
sizeof(struct thread_detail) * num_tasks);
}
tasks_enabled = 0;
ret = target_read_u32(rtos->target, rtos->symbols[CHROMIUM_EC_VAL_tasks_enabled].address,
&tasks_enabled);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to load tasks_enabled");
return ret;
}
tasks_ready = 0;
ret = target_read_u32(rtos->target, rtos->symbols[CHROMIUM_EC_VAL_tasks_ready].address,
&tasks_ready);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to load tasks_ready");
return ret;
}
thread_ptr = rtos->symbols[CHROMIUM_EC_VAL_tasks].address;
tasks_found = 0;
for (t = 0; t < CROS_EC_MAX_TASKS; t++) {
if (!(tasks_enabled & BIT(t)))
continue;
if (thread_ptr == current_task)
rtos->current_thread = thread_ptr;
rtos->thread_details[tasks_found].threadid = thread_ptr;
ret = target_read_u32(rtos->target,
rtos->symbols[CHROMIUM_EC_VAL_task_names].address +
params->ptr_size * t, &name_ptr);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to read name_ptr");
return ret;
}
/* read name buffer */
ret = target_read_buffer(rtos->target, name_ptr, CROS_EC_MAX_NAME,
(uint8_t *)thread_str_buf);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to read task name");
return ret;
}
/* sanitize string, gdb chokes on "<< idle >>" */
if (thread_str_buf[CROS_EC_MAX_NAME - 1] != '\0')
thread_str_buf[CROS_EC_MAX_NAME - 1] = '\0';
if (!strncmp(thread_str_buf, CROS_EC_IDLE_STRING, CROS_EC_MAX_NAME))
rtos->thread_details[tasks_found].thread_name_str = strdup("IDLE");
else
rtos->thread_details[tasks_found].thread_name_str = strdup(thread_str_buf);
events = 0;
ret = target_read_u32(rtos->target,
thread_ptr + params->task_offset_events,
&events);
if (ret != ERROR_OK)
LOG_ERROR("Failed to get task %d's events", t);
/* this is a bit kludgy but will do for now */
ret = target_read_buffer(rtos->target,
thread_ptr + params->task_offset_runtime,
sizeof(runtime_buf), runtime_buf);
if (ret != ERROR_OK)
LOG_ERROR("Failed to get task %d's runtime", t);
runtime = target_buffer_get_u64(rtos->target, runtime_buf);
/* Priority is simply the positon in the array */
if (thread_ptr == current_task)
snprintf(thread_str_buf, sizeof(thread_str_buf),
"State: Running, Priority: %u, Events: %" PRIx32 ", Runtime: %" PRIu64 "\n",
t, events, runtime);
else
snprintf(thread_str_buf, sizeof(thread_str_buf),
"State: %s, Priority: %u, Events: %" PRIx32 ", Runtime: %" PRIu64 "\n",
tasks_ready & BIT(t) ? "Ready" : "Waiting", t,
events, runtime);
rtos->thread_details[tasks_found].extra_info_str = strdup(thread_str_buf);
rtos->thread_details[tasks_found].exists = true;
thread_ptr += params->task_offset_next;
tasks_found++;
}
rtos->thread_count = tasks_found;
return ERROR_OK;
}
static int chromium_ec_get_thread_reg_list(struct rtos *rtos,
threadid_t threadid,
struct rtos_reg **reg_list,
int *num_regs)
{
struct chromium_ec_params *params = rtos->rtos_specific_params;
uint32_t stack_ptr = 0;
int ret, t;
for (t = 0; t < rtos->thread_count; t++)
if (threadid == rtos->thread_details[t].threadid)
break;
/* if we didn't find threadid, bail */
if (t == rtos->thread_count)
return ERROR_FAIL;
ret = target_read_u32(rtos->target,
rtos->symbols[CHROMIUM_EC_VAL_tasks].address +
params->task_offset_next * t,
&stack_ptr);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to load TCB");
return ret;
}
return rtos_generic_stack_read(rtos->target, params->stacking,
stack_ptr, reg_list, num_regs);
}
static int chromium_ec_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
{
size_t s;
*symbol_list = calloc(ARRAY_SIZE(chromium_ec_symbol_list),
sizeof(symbol_table_elem_t));
if (!(*symbol_list)) {
LOG_ERROR("Chromium-EC: out of memory");
return ERROR_FAIL;
}
for (s = 0; s < ARRAY_SIZE(chromium_ec_symbol_list); s++)
(*symbol_list)[s].symbol_name = chromium_ec_symbol_list[s];
return ERROR_OK;
}
const struct rtos_type chromium_ec_rtos = {
.name = "Chromium-EC",
.detect_rtos = chromium_ec_detect_rtos,
.create = chromium_ec_create,
.update_threads = chromium_ec_update_threads,
.get_thread_reg_list = chromium_ec_get_thread_reg_list,
.get_symbol_list_to_lookup = chromium_ec_get_symbol_list_to_lookup,
};
+2
View File
@@ -32,6 +32,7 @@ extern struct rtos_type ThreadX_rtos;
extern struct rtos_type eCos_rtos;
extern struct rtos_type Linux_os;
extern struct rtos_type ChibiOS_rtos;
extern struct rtos_type chromium_ec_rtos;
extern struct rtos_type embKernel_rtos;
extern struct rtos_type mqx_rtos;
extern struct rtos_type uCOS_III_rtos;
@@ -45,6 +46,7 @@ static struct rtos_type *rtos_types[] = {
&eCos_rtos,
&Linux_os,
&ChibiOS_rtos,
&chromium_ec_rtos,
&embKernel_rtos,
&mqx_rtos,
&uCOS_III_rtos,
+4 -2
View File
@@ -143,7 +143,8 @@ INTEL_IA32_SRC = \
ESIRISC_SRC = \
%D%/esirisc.c \
%D%/esirisc_jtag.c
%D%/esirisc_jtag.c \
%D%/esirisc_trace.c
%C%_libtarget_la_SOURCES += \
%D%/algorithm.h \
@@ -228,7 +229,8 @@ ESIRISC_SRC = \
%D%/arm_cti.h \
%D%/esirisc.h \
%D%/esirisc_jtag.h \
%D%/esirisc_regs.h
%D%/esirisc_regs.h \
%D%/esirisc_trace.h
include %D%/openrisc/Makefile.am
include %D%/riscv/Makefile.am
+4
View File
@@ -100,6 +100,7 @@ static int aarch64_restore_system_control_reg(struct target *target)
case ARM_MODE_ABT:
case ARM_MODE_FIQ:
case ARM_MODE_IRQ:
case ARM_MODE_SYS:
instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0);
break;
@@ -172,6 +173,7 @@ static int aarch64_mmu_modify(struct target *target, int enable)
case ARM_MODE_ABT:
case ARM_MODE_FIQ:
case ARM_MODE_IRQ:
case ARM_MODE_SYS:
instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0);
break;
@@ -1032,6 +1034,7 @@ static int aarch64_post_debug_entry(struct target *target)
case ARM_MODE_ABT:
case ARM_MODE_FIQ:
case ARM_MODE_IRQ:
case ARM_MODE_SYS:
instr = ARMV4_5_MRC(15, 0, 0, 1, 0, 0);
break;
@@ -2824,6 +2827,7 @@ struct target_type aarch64_target = {
.deassert_reset = aarch64_deassert_reset,
/* REVISIT allow exporting VFP3 registers ... */
.get_gdb_arch = armv8_get_gdb_arch,
.get_gdb_reg_list = armv8_get_gdb_reg_list,
.read_memory = aarch64_read_memory,
+2 -51
View File
@@ -72,8 +72,8 @@ static const char *dap_reg_name(int instr, int reg_addr)
case DP_RDBUFF:
reg_name = "RDBUFF";
break;
case DP_WCR:
reg_name = "WCR";
case DP_DLCR:
reg_name = "DLCR";
break;
default:
reg_name = "UNK";
@@ -726,52 +726,3 @@ const struct dap_ops jtag_dp_ops = {
.run = jtag_dp_run,
.sync = jtag_dp_sync,
};
static const uint8_t swd2jtag_bitseq[] = {
/* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
* putting both JTAG and SWD logic into reset state.
*/
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/* Switching equence disables SWD and enables JTAG
* NOTE: bits in the DP's IDCODE can expose the need for
* the old/deprecated sequence (0xae 0xde).
*/
0x3c, 0xe7,
/* At least 50 TCK/SWCLK cycles with TMS/SWDIO high,
* putting both JTAG and SWD logic into reset state.
* NOTE: some docs say "at least 5".
*/
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
/** Put the debug link into JTAG mode, if the target supports it.
* The link's initial mode may be either SWD or JTAG.
*
* @param target Enters JTAG mode (if possible).
*
* Note that targets implemented with SW-DP do not support JTAG, and
* that some targets which could otherwise support it may have been
* configured to disable JTAG signaling
*
* @return ERROR_OK or else a fault code.
*/
int dap_to_jtag(struct target *target)
{
int retval;
LOG_DEBUG("Enter JTAG mode");
/* REVISIT it's nasty to need to make calls to a "jtag"
* subsystem if the link isn't in JTAG mode...
*/
retval = jtag_add_tms_seq(8 * sizeof(swd2jtag_bitseq),
swd2jtag_bitseq, TAP_RESET);
if (retval == ERROR_OK)
retval = jtag_execute_queue();
/* REVISIT set up the DAP's ops vector for JTAG mode. */
return retval;
}
-65
View File
@@ -297,71 +297,6 @@ const struct dap_ops swd_dap_ops = {
.quit = swd_quit,
};
/*
* This represents the bits which must be sent out on TMS/SWDIO to
* switch a DAP implemented using an SWJ-DP module into SWD mode.
* These bits are stored (and transmitted) LSB-first.
*
* See the DAP-Lite specification, section 2.2.5 for information
* about making the debug link select SWD or JTAG. (Similar info
* is in a few other ARM documents.)
*/
static const uint8_t jtag2swd_bitseq[] = {
/* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
* putting both JTAG and SWD logic into reset state.
*/
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/* Switching sequence enables SWD and disables JTAG
* NOTE: bits in the DP's IDCODE may expose the need for
* an old/obsolete/deprecated sequence (0xb6 0xed).
*/
0x9e, 0xe7,
/* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
* putting both JTAG and SWD logic into reset state.
*/
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
/**
* Put the debug link into SWD mode, if the target supports it.
* The link's initial mode may be either JTAG (for example,
* with SWJ-DP after reset) or SWD.
*
* @param target Enters SWD mode (if possible).
*
* Note that targets using the JTAG-DP do not support SWD, and that
* some targets which could otherwise support it may have have been
* configured to disable SWD signaling
*
* @return ERROR_OK or else a fault code.
*/
int dap_to_swd(struct target *target)
{
struct arm *arm = target_to_arm(target);
int retval;
if (!arm->dap) {
LOG_ERROR("SWD mode is not available");
return ERROR_FAIL;
}
LOG_DEBUG("Enter SWD mode");
/* REVISIT it's ugly to need to make calls to a "jtag"
* subsystem if the link may not be in JTAG mode...
*/
retval = jtag_add_tms_seq(8 * sizeof(jtag2swd_bitseq),
jtag2swd_bitseq, TAP_INVALID);
if (retval == ERROR_OK)
retval = jtag_execute_queue();
/* set up the DAP's ops vector for SWD mode. */
arm->dap->ops = &swd_dap_ops;
return retval;
}
static const struct command_registration swd_commands[] = {
{
/*
+2
View File
@@ -263,9 +263,11 @@ struct reg_cache *armv8_build_reg_cache(struct target *target);
extern const struct command_registration arm_command_handlers[];
int arm_arch_state(struct target *target);
const char *arm_get_gdb_arch(struct target *target);
int arm_get_gdb_reg_list(struct target *target,
struct reg **reg_list[], int *reg_list_size,
enum target_register_class reg_class);
const char *armv8_get_gdb_arch(struct target *target);
int armv8_get_gdb_reg_list(struct target *target,
struct reg **reg_list[], int *reg_list_size,
enum target_register_class reg_class);
+1
View File
@@ -1362,6 +1362,7 @@ struct target_type arm11_target = {
.assert_reset = arm11_assert_reset,
.deassert_reset = arm11_deassert_reset,
.get_gdb_arch = arm_get_gdb_arch,
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm11_read_memory,
+1
View File
@@ -560,6 +560,7 @@ struct target_type arm720t_target = {
.deassert_reset = arm7_9_deassert_reset,
.soft_reset_halt = arm720t_soft_reset_halt,
.get_gdb_arch = arm_get_gdb_arch,
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm720t_read_memory,
+1
View File
@@ -699,6 +699,7 @@ struct target_type arm7tdmi_target = {
.deassert_reset = arm7_9_deassert_reset,
.soft_reset_halt = arm7_9_soft_reset_halt,
.get_gdb_arch = arm_get_gdb_arch,
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm7_9_read_memory,
+1
View File
@@ -1693,6 +1693,7 @@ struct target_type arm920t_target = {
.deassert_reset = arm7_9_deassert_reset,
.soft_reset_halt = arm920t_soft_reset_halt,
.get_gdb_arch = arm_get_gdb_arch,
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm920t_read_memory,
+1
View File
@@ -804,6 +804,7 @@ struct target_type arm926ejs_target = {
.deassert_reset = arm7_9_deassert_reset,
.soft_reset_halt = arm926ejs_soft_reset_halt,
.get_gdb_arch = arm_get_gdb_arch,
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm7_9_read_memory,
+1
View File
@@ -756,6 +756,7 @@ struct target_type arm946e_target = {
.deassert_reset = arm7_9_deassert_reset,
.soft_reset_halt = arm7_9_soft_reset_halt,
.get_gdb_arch = arm_get_gdb_arch,
.get_gdb_reg_list = arm_get_gdb_reg_list,
/* .read_memory = arm7_9_read_memory, */
+1
View File
@@ -259,6 +259,7 @@ struct target_type arm966e_target = {
.deassert_reset = arm7_9_deassert_reset,
.soft_reset_halt = arm7_9_soft_reset_halt,
.get_gdb_arch = arm_get_gdb_arch,
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm7_9_read_memory,
+1
View File
@@ -902,6 +902,7 @@ struct target_type arm9tdmi_target = {
.deassert_reset = arm7_9_deassert_reset,
.soft_reset_halt = arm7_9_soft_reset_halt,
.get_gdb_arch = arm_get_gdb_arch,
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = arm7_9_read_memory,
+74 -1
View File
@@ -59,7 +59,7 @@
/*
* Relevant specifications from ARM include:
*
* ARM(tm) Debug Interface v5 Architecture Specification ARM IHI 0031A
* ARM(tm) Debug Interface v5 Architecture Specification ARM IHI 0031E
* CoreSight(tm) v1.0 Architecture Specification ARM IHI 0029B
*
* CoreSight(tm) DAP-Lite TRM, ARM DDI 0316D
@@ -73,6 +73,8 @@
#include "jtag/interface.h"
#include "arm.h"
#include "arm_adi_v5.h"
#include "jtag/swd.h"
#include "transport/transport.h"
#include <helper/jep106.h>
#include <helper/time_support.h>
#include <helper/list.h>
@@ -788,6 +790,77 @@ int mem_ap_init(struct adiv5_ap *ap)
return ERROR_OK;
}
/**
* Put the debug link into SWD mode, if the target supports it.
* The link's initial mode may be either JTAG (for example,
* with SWJ-DP after reset) or SWD.
*
* Note that targets using the JTAG-DP do not support SWD, and that
* some targets which could otherwise support it may have been
* configured to disable SWD signaling
*
* @param dap The DAP used
* @return ERROR_OK or else a fault code.
*/
int dap_to_swd(struct adiv5_dap *dap)
{
int retval;
LOG_DEBUG("Enter SWD mode");
if (transport_is_jtag()) {
retval = jtag_add_tms_seq(swd_seq_jtag_to_swd_len,
swd_seq_jtag_to_swd, TAP_INVALID);
if (retval == ERROR_OK)
retval = jtag_execute_queue();
return retval;
}
if (transport_is_swd()) {
const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
return swd->switch_seq(JTAG_TO_SWD);
}
LOG_ERROR("Nor JTAG nor SWD transport");
return ERROR_FAIL;
}
/**
* Put the debug link into JTAG mode, if the target supports it.
* The link's initial mode may be either SWD or JTAG.
*
* Note that targets implemented with SW-DP do not support JTAG, and
* that some targets which could otherwise support it may have been
* configured to disable JTAG signaling
*
* @param dap The DAP used
* @return ERROR_OK or else a fault code.
*/
int dap_to_jtag(struct adiv5_dap *dap)
{
int retval;
LOG_DEBUG("Enter JTAG mode");
if (transport_is_jtag()) {
retval = jtag_add_tms_seq(swd_seq_swd_to_jtag_len,
swd_seq_swd_to_jtag, TAP_RESET);
if (retval == ERROR_OK)
retval = jtag_execute_queue();
return retval;
}
if (transport_is_swd()) {
const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
return swd->switch_seq(SWD_TO_JTAG);
}
LOG_ERROR("Nor JTAG nor SWD transport");
return ERROR_FAIL;
}
/* CID interpretation -- see ARM IHI 0029B section 3
* and ARM IHI 0031A table 13-3.
*/
+2 -2
View File
@@ -516,10 +516,10 @@ int dap_lookup_cs_component(struct adiv5_ap *ap,
struct target;
/* Put debug link into SWD mode */
int dap_to_swd(struct target *target);
int dap_to_swd(struct adiv5_dap *dap);
/* Put debug link into JTAG mode */
int dap_to_jtag(struct target *target);
int dap_to_jtag(struct adiv5_dap *dap);
extern const struct command_registration dap_instance_commands[];
+7 -3
View File
@@ -173,7 +173,7 @@ int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel)
return arm_cti_write_reg(self, CTI_APPCLEAR, CTI_CHNL(channel));
}
static uint32_t cti_regs[26];
static uint32_t cti_regs[28];
static const struct {
uint32_t offset;
@@ -206,6 +206,8 @@ static const struct {
{ CTI_CHOU_STATUS, "CHOUT", &cti_regs[23] },
{ CTI_APPSET, "APPSET", &cti_regs[24] },
{ CTI_APPCLEAR, "APPCLR", &cti_regs[25] },
{ CTI_APPPULSE, "APPPULSE", &cti_regs[26] },
{ CTI_INACK, "INACK", &cti_regs[27] },
};
static int cti_find_reg_offset(const char *name)
@@ -216,6 +218,8 @@ static int cti_find_reg_offset(const char *name)
if (!strcmp(name, cti_names[i].label))
return cti_names[i].offset;
}
LOG_ERROR("unknown CTI register %s", name);
return -1;
}
@@ -297,7 +301,7 @@ COMMAND_HANDLER(handle_cti_write)
uint32_t value;
if (CMD_ARGC != 2) {
Jim_SetResultString(interp, "Wrong numer of args", -1);
Jim_SetResultString(interp, "Wrong number of args", -1);
return ERROR_FAIL;
}
@@ -320,7 +324,7 @@ COMMAND_HANDLER(handle_cti_read)
uint32_t value;
if (CMD_ARGC != 1) {
Jim_SetResultString(interp, "Wrong numer of args", -1);
Jim_SetResultString(interp, "Wrong number of args", -1);
return ERROR_FAIL;
}
+5
View File
@@ -313,6 +313,11 @@ COMMAND_HANDLER(handle_dap_info_command)
struct adiv5_dap *dap = arm->dap;
uint32_t apsel;
if (dap == NULL) {
LOG_ERROR("DAP instance not available. Probably a HLA target...");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
switch (CMD_ARGC) {
case 0:
apsel = dap->apsel;
+1 -1
View File
@@ -213,7 +213,7 @@
/* Breakpoint instruction (ARMv5)
* Im: 16-bit immediate
*/
#define ARMV5_BKPT(Im) (0xe1200070 | ((Im & 0xfff0) << 8) | (Im & 0xf))
#define ARMV5_BKPT(Im) (0xe1200070 | ((Im & 0xfff0) << 4) | (Im & 0xf))
/* Thumb mode instructions
+20
View File
@@ -1134,6 +1134,7 @@ static const struct command_registration arm_exec_command_handlers[] = {
},
{
.name = "mrc",
.mode = COMMAND_EXEC,
.jim_handler = &jim_mcrmrc,
.help = "read coprocessor register",
.usage = "cpnum op1 CRn CRm op2",
@@ -1179,6 +1180,20 @@ const struct command_registration arm_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
/*
* gdb for arm targets (e.g. arm-none-eabi-gdb) supports several variants
* of arm architecture. You can list them using the autocompletion of gdb
* command prompt by typing "set architecture " and then press TAB key.
* The default, selected automatically, is "arm".
* Let's use the default value, here, to make gdb-multiarch behave in the
* same way as a gdb for arm. This can be changed later on. User can still
* set the specific architecture variant with the gdb command.
*/
const char *arm_get_gdb_arch(struct target *target)
{
return "arm";
}
int arm_get_gdb_reg_list(struct target *target,
struct reg **reg_list[], int *reg_list_size,
enum target_register_class reg_class)
@@ -1340,6 +1355,8 @@ int armv4_5_run_algorithm_inner(struct target *target,
cpsr = buf_get_u32(arm->cpsr->value, 0, 32);
for (i = 0; i < num_mem_params; i++) {
if (mem_params[i].direction == PARAM_IN)
continue;
retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size,
mem_params[i].value);
if (retval != ERROR_OK)
@@ -1347,6 +1364,9 @@ int armv4_5_run_algorithm_inner(struct target *target,
}
for (i = 0; i < num_reg_params; i++) {
if (reg_params[i].direction == PARAM_IN)
continue;
struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, 0);
if (!reg) {
LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
+4 -2
View File
@@ -72,7 +72,8 @@ int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor);
if ((first_lvl_descriptor & 0x3) == 0) {
LOG_ERROR("Address translation failure");
/* Avoid LOG_ERROR, probably GDB is guessing the stack frame */
LOG_WARNING("Address translation failure [1]: va %8.8" PRIx32 "", va);
return ERROR_TARGET_TRANSLATION_FAULT;
}
@@ -103,7 +104,8 @@ int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
if ((second_lvl_descriptor & 0x3) == 0) {
LOG_ERROR("Address translation failure");
/* Avoid LOG_ERROR, probably GDB is guessing the stack frame */
LOG_WARNING("Address translation failure [2]: va %8.8" PRIx32 "", va);
return ERROR_TARGET_TRANSLATION_FAULT;
}
+22 -1
View File
@@ -379,7 +379,8 @@ int armv7m_start_algorithm(struct target *target,
}
for (int i = 0; i < num_mem_params; i++) {
/* TODO: Write only out params */
if (mem_params[i].direction == PARAM_IN)
continue;
retval = target_write_buffer(target, mem_params[i].address,
mem_params[i].size,
mem_params[i].value);
@@ -388,6 +389,9 @@ int armv7m_start_algorithm(struct target *target,
}
for (int i = 0; i < num_reg_params; i++) {
if (reg_params[i].direction == PARAM_IN)
continue;
struct reg *reg =
register_get_by_name(armv7m->arm.core_cache, reg_params[i].reg_name, 0);
/* uint32_t regvalue; */
@@ -407,6 +411,23 @@ int armv7m_start_algorithm(struct target *target,
armv7m_set_core_reg(reg, reg_params[i].value);
}
{
/*
* Ensure xPSR.T is set to avoid trying to run things in arm
* (non-thumb) mode, which armv7m does not support.
*
* We do this by setting the entirety of xPSR, which should
* remove all the unknowns about xPSR state.
*
* Because xPSR.T is populated on reset from the vector table,
* it might be 0 if the vector table has "bad" data in it.
*/
struct reg *reg = &armv7m->arm.core_cache->reg_list[ARMV7M_xPSR];
buf_set_u32(reg->value, 0, 32, 0x01000000);
reg->valid = 1;
reg->dirty = 1;
}
if (armv7m_algorithm_info->core_mode != ARM_MODE_ANY &&
armv7m_algorithm_info->core_mode != core_mode) {
+15
View File
@@ -73,6 +73,10 @@ static const struct {
.name = "ABT",
.psr = ARM_MODE_ABT,
},
{
.name = "SYS",
.psr = ARM_MODE_SYS,
},
{
.name = "EL0T",
.psr = ARMV8_64_EL0T,
@@ -1477,6 +1481,9 @@ static int armv8_get_core_reg32(struct reg *reg)
struct reg *reg64;
int retval;
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
/* get the corresponding Aarch64 register */
reg64 = cache->reg_list + armv8_reg->num;
if (reg64->valid) {
@@ -1500,6 +1507,9 @@ static int armv8_set_core_reg32(struct reg *reg, uint8_t *buf)
struct reg *reg64 = cache->reg_list + armv8_reg->num;
uint32_t value = buf_get_u32(buf, 0, 32);
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
if (reg64 == arm->cpsr) {
armv8_set_cpsr(arm, value);
} else {
@@ -1668,6 +1678,11 @@ const struct command_registration armv8_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
const char *armv8_get_gdb_arch(struct target *target)
{
return "aarch64";
}
int armv8_get_gdb_reg_list(struct target *target,
struct reg **reg_list[], int *reg_list_size,
enum target_register_class reg_class)
+5
View File
@@ -573,6 +573,7 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
case ARM_MODE_ABT:
case ARM_MODE_IRQ:
case ARM_MODE_FIQ:
case ARM_MODE_SYS:
target_el = 1;
break;
/*
@@ -790,6 +791,10 @@ int armv8_dpm_read_current_registers(struct arm_dpm *dpm)
dpm->last_el != armv8_curel_from_core_mode(arm_reg->mode))
continue;
/* Special case: ARM_MODE_SYS has no SPSR at EL1 */
if (r->number == ARMV8_SPSR_EL1 && arm->core_mode == ARM_MODE_SYS)
continue;
retval = dpmv8_read_reg(dpm, r, i);
if (retval != ERROR_OK)
goto fail;
+38 -38
View File
@@ -202,6 +202,7 @@ static int cortex_a_mmu_modify(struct target *target, int enable)
static int cortex_a_init_debug_access(struct target *target)
{
struct armv7a_common *armv7a = target_to_armv7a(target);
uint32_t dscr;
int retval;
/* lock memory-mapped access to debug registers to prevent
@@ -231,6 +232,16 @@ static int cortex_a_init_debug_access(struct target *target)
/* Resync breakpoint registers */
/* Enable halt for breakpoint, watchpoint and vector catch */
retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
armv7a->debug_base + CPUDBG_DSCR, &dscr);
if (retval != ERROR_OK)
return retval;
retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
armv7a->debug_base + CPUDBG_DSCR, dscr | DSCR_HALT_DBG_MODE);
if (retval != ERROR_OK)
return retval;
/* Since this is likely called from init or reset, update target state information*/
return cortex_a_poll(target);
}
@@ -714,39 +725,26 @@ static int cortex_a_poll(struct target *target)
/* We have a halting debug event */
LOG_DEBUG("Target halted");
target->state = TARGET_HALTED;
if ((prev_target_state == TARGET_RUNNING)
|| (prev_target_state == TARGET_UNKNOWN)
|| (prev_target_state == TARGET_RESET)) {
retval = cortex_a_debug_entry(target);
retval = cortex_a_debug_entry(target);
if (retval != ERROR_OK)
return retval;
if (target->smp) {
retval = update_halt_gdb(target);
if (retval != ERROR_OK)
return retval;
if (target->smp) {
retval = update_halt_gdb(target);
if (retval != ERROR_OK)
return retval;
}
}
if (prev_target_state == TARGET_DEBUG_RUNNING) {
target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
} else { /* prev_target_state is RUNNING, UNKNOWN or RESET */
if (arm_semihosting(target, &retval) != 0)
return retval;
target_call_event_callbacks(target,
TARGET_EVENT_HALTED);
}
if (prev_target_state == TARGET_DEBUG_RUNNING) {
LOG_DEBUG(" ");
retval = cortex_a_debug_entry(target);
if (retval != ERROR_OK)
return retval;
if (target->smp) {
retval = update_halt_gdb(target);
if (retval != ERROR_OK)
return retval;
}
target_call_event_callbacks(target,
TARGET_EVENT_DEBUG_HALTED);
}
}
} else
target->state = TARGET_RUNNING;
@@ -769,19 +767,6 @@ static int cortex_a_halt(struct target *target)
if (retval != ERROR_OK)
return retval;
/*
* enter halting debug mode
*/
retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
armv7a->debug_base + CPUDBG_DSCR, &dscr);
if (retval != ERROR_OK)
return retval;
retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
armv7a->debug_base + CPUDBG_DSCR, dscr | DSCR_HALT_DBG_MODE);
if (retval != ERROR_OK)
return retval;
int64_t then = timeval_ms();
for (;; ) {
retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
@@ -2889,7 +2874,20 @@ static int cortex_r4_target_create(struct target *target, Jim_Interp *interp)
static void cortex_a_deinit_target(struct target *target)
{
struct cortex_a_common *cortex_a = target_to_cortex_a(target);
struct arm_dpm *dpm = &cortex_a->armv7a_common.dpm;
struct armv7a_common *armv7a = &cortex_a->armv7a_common;
struct arm_dpm *dpm = &armv7a->dpm;
uint32_t dscr;
int retval;
if (target_was_examined(target)) {
/* Disable halt for breakpoint, watchpoint and vector catch */
retval = mem_ap_read_atomic_u32(armv7a->debug_ap,
armv7a->debug_base + CPUDBG_DSCR, &dscr);
if (retval == ERROR_OK)
mem_ap_write_atomic_u32(armv7a->debug_ap,
armv7a->debug_base + CPUDBG_DSCR,
dscr & ~DSCR_HALT_DBG_MODE);
}
free(cortex_a->brp_list);
free(dpm->dbp);
@@ -3160,6 +3158,7 @@ struct target_type cortexa_target = {
.deassert_reset = cortex_a_deassert_reset,
/* REVISIT allow exporting VFP3 registers ... */
.get_gdb_arch = arm_get_gdb_arch,
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = cortex_a_read_memory,
@@ -3239,6 +3238,7 @@ struct target_type cortexr4_target = {
.deassert_reset = cortex_a_deassert_reset,
/* REVISIT allow exporting VFP3 registers ... */
.get_gdb_arch = arm_get_gdb_arch,
.get_gdb_reg_list = arm_get_gdb_reg_list,
.read_memory = cortex_a_read_phys_memory,
+56 -10
View File
@@ -510,7 +510,10 @@ static int cortex_m_poll(struct target *target)
}
if (cortex_m->dcb_dhcsr & S_RESET_ST) {
target->state = TARGET_RESET;
if (target->state != TARGET_RESET) {
target->state = TARGET_RESET;
LOG_INFO("%s: external reset detected", target_name(target));
}
return ERROR_OK;
}
@@ -564,6 +567,17 @@ static int cortex_m_poll(struct target *target)
}
}
/* Check that target is truly halted, since the target could be resumed externally */
if ((prev_target_state == TARGET_HALTED) && !(cortex_m->dcb_dhcsr & S_HALT)) {
/* registers are now invalid */
register_cache_invalidate(armv7m->arm.core_cache);
target->state = TARGET_RUNNING;
LOG_WARNING("%s: external resume detected", target_name(target));
target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
retval = ERROR_OK;
}
/* Did we detect a failure condition that we cleared? */
if (detected_failure != ERROR_OK)
retval = detected_failure;
@@ -863,10 +877,17 @@ static int cortex_m_step(struct target *target, int current,
else {
/* Set a temporary break point */
if (breakpoint)
if (breakpoint) {
retval = cortex_m_set_breakpoint(target, breakpoint);
else
retval = breakpoint_add(target, pc_value, 2, BKPT_HARD);
} else {
enum breakpoint_type type = BKPT_HARD;
if (cortex_m->fp_rev == 0 && pc_value > 0x1FFFFFFF) {
/* FPB rev.1 cannot handle such addr, try BKPT instr */
type = BKPT_SOFT;
}
retval = breakpoint_add(target, pc_value, 2, type);
}
bool tmp_bp_set = (retval == ERROR_OK);
/* No more breakpoints left, just do a step */
@@ -1041,10 +1062,18 @@ static int cortex_m_assert_reset(struct target *target)
retval = ERROR_OK;
} else {
/* Use a standard Cortex-M3 software reset mechanism.
* We default to using VECRESET as it is supported on all current cores.
* We default to using VECRESET as it is supported on all current cores
* (except Cortex-M0, M0+ and M1 which support SYSRESETREQ only!)
* This has the disadvantage of not resetting the peripherals, so a
* reset-init event handler is needed to perform any peripheral resets.
*/
if (!cortex_m->vectreset_supported
&& reset_config == CORTEX_M_RESET_VECTRESET) {
reset_config = CORTEX_M_RESET_SYSRESETREQ;
LOG_WARNING("VECTRESET is not supported on this Cortex-M core, using SYSRESETREQ instead.");
LOG_WARNING("Set 'cortex_m reset_config sysresetreq'.");
}
LOG_DEBUG("Using Cortex-M %s", (reset_config == CORTEX_M_RESET_SYSRESETREQ)
? "SYSRESETREQ" : "VECTRESET");
@@ -2027,6 +2056,9 @@ int cortex_m_examine(struct target *target)
}
LOG_DEBUG("cpuid: 0x%8.8" PRIx32 "", cpuid);
/* VECTRESET is not supported on Cortex-M0, M0+ and M1 */
cortex_m->vectreset_supported = i > 1;
if (i == 4) {
target_read_u32(target, MVFR0, &mvfr0);
target_read_u32(target, MVFR1, &mvfr1);
@@ -2244,14 +2276,19 @@ static int cortex_m_init_arch_info(struct target *target,
static int cortex_m_target_create(struct target *target, Jim_Interp *interp)
{
struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common));
cortex_m->common_magic = CORTEX_M_COMMON_MAGIC;
struct adiv5_private_config *pc;
pc = (struct adiv5_private_config *)target->private_config;
if (adiv5_verify_config(pc) != ERROR_OK)
return ERROR_FAIL;
struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common));
if (cortex_m == NULL) {
LOG_ERROR("No memory creating target");
return ERROR_FAIL;
}
cortex_m->common_magic = CORTEX_M_COMMON_MAGIC;
cortex_m->apsel = pc->ap_num;
cortex_m_init_arch_info(target, cortex_m, pc->dap);
@@ -2418,8 +2455,16 @@ COMMAND_HANDLER(handle_cortex_m_reset_config_command)
if (CMD_ARGC > 0) {
if (strcmp(*CMD_ARGV, "sysresetreq") == 0)
cortex_m->soft_reset_config = CORTEX_M_RESET_SYSRESETREQ;
else if (strcmp(*CMD_ARGV, "vectreset") == 0)
cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET;
else if (strcmp(*CMD_ARGV, "vectreset") == 0) {
if (target_was_examined(target)
&& !cortex_m->vectreset_supported)
LOG_WARNING("VECTRESET is not supported on your Cortex-M core!");
else
cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET;
} else
return ERROR_COMMAND_SYNTAX_ERROR;
}
switch (cortex_m->soft_reset_config) {
@@ -2461,7 +2506,7 @@ static const struct command_registration cortex_m_exec_command_handlers[] = {
.handler = handle_cortex_m_reset_config_command,
.mode = COMMAND_ANY,
.help = "configure software reset handling",
.usage = "['srst'|'sysresetreq'|'vectreset']",
.usage = "['sysresetreq'|'vectreset']",
},
COMMAND_REGISTRATION_DONE
};
@@ -2499,6 +2544,7 @@ struct target_type cortexm_target = {
.deassert_reset = cortex_m_deassert_reset,
.soft_reset_halt = cortex_m_soft_reset_halt,
.get_gdb_arch = arm_get_gdb_arch,
.get_gdb_reg_list = armv7m_get_gdb_reg_list,
.read_memory = cortex_m_read_memory,
+1
View File
@@ -184,6 +184,7 @@ struct cortex_m_common {
struct reg_cache *dwt_cache;
enum cortex_m_soft_reset_config soft_reset_config;
bool vectreset_supported;
enum cortex_m_isrmasking_mode isrmasking_mode;
+5
View File
@@ -1387,6 +1387,8 @@ static int dsp563xx_run_algorithm(struct target *target,
}
for (i = 0; i < num_mem_params; i++) {
if (mem_params[i].direction == PARAM_IN)
continue;
retval = target_write_buffer(target, mem_params[i].address,
mem_params[i].size, mem_params[i].value);
if (retval != ERROR_OK)
@@ -1394,6 +1396,9 @@ static int dsp563xx_run_algorithm(struct target *target,
}
for (i = 0; i < num_reg_params; i++) {
if (reg_params[i].direction == PARAM_IN)
continue;
struct reg *reg = register_get_by_name(dsp563xx->core_cache,
reg_params[i].reg_name,
0);
+119 -73
View File
@@ -34,27 +34,60 @@
#include "esirisc.h"
#define RESET_TIMEOUT 5000 /* 5s */
#define STEP_TIMEOUT 1000 /* 1s */
#define RESET_TIMEOUT 5000 /* 5s */
#define STEP_TIMEOUT 1000 /* 1s */
/*
* eSi-RISC targets support a configurable number of interrupts;
* up to 32 interrupts are supported.
*/
static const char * const esirisc_exceptions[] = {
"Reset", "HardwareFailure", "NMI", "InstBreakpoint", "DataBreakpoint",
"Unsupported", "PrivilegeViolation", "InstBusError", "DataBusError",
"AlignmentError", "ArithmeticError", "SystemCall", "MemoryManagement",
"Unrecoverable", "Reserved",
"Interrupt0", "Interrupt1", "Interrupt2", "Interrupt3",
"Interrupt4", "Interrupt5", "Interrupt6", "Interrupt7",
"Interrupt8", "Interrupt9", "Interrupt10", "Interrupt11",
"Interrupt12", "Interrupt13", "Interrupt14", "Interrupt15",
"Interrupt16", "Interrupt17", "Interrupt18", "Interrupt19",
"Interrupt20", "Interrupt21", "Interrupt22", "Interrupt23",
"Interrupt24", "Interrupt25", "Interrupt26", "Interrupt27",
"Interrupt28", "Interrupt29", "Interrupt30", "Interrupt31",
static const char * const esirisc_exception_strings[] = {
[EID_RESET] = "Reset",
[EID_HARDWARE_FAILURE] = "HardwareFailure",
[EID_NMI] = "NMI",
[EID_INST_BREAKPOINT] = "InstBreakpoint",
[EID_DATA_BREAKPOINT] = "DataBreakpoint",
[EID_UNSUPPORTED] = "Unsupported",
[EID_PRIVILEGE_VIOLATION] = "PrivilegeViolation",
[EID_INST_BUS_ERROR] = "InstBusError",
[EID_DATA_BUS_ERROR] = "DataBusError",
[EID_ALIGNMENT_ERROR] = "AlignmentError",
[EID_ARITHMETIC_ERROR] = "ArithmeticError",
[EID_SYSTEM_CALL] = "SystemCall",
[EID_MEMORY_MANAGEMENT] = "MemoryManagement",
[EID_UNRECOVERABLE] = "Unrecoverable",
[EID_INTERRUPTn+0] = "Interrupt0",
[EID_INTERRUPTn+1] = "Interrupt1",
[EID_INTERRUPTn+2] = "Interrupt2",
[EID_INTERRUPTn+3] = "Interrupt3",
[EID_INTERRUPTn+4] = "Interrupt4",
[EID_INTERRUPTn+5] = "Interrupt5",
[EID_INTERRUPTn+6] = "Interrupt6",
[EID_INTERRUPTn+7] = "Interrupt7",
[EID_INTERRUPTn+8] = "Interrupt8",
[EID_INTERRUPTn+9] = "Interrupt9",
[EID_INTERRUPTn+10] = "Interrupt10",
[EID_INTERRUPTn+11] = "Interrupt11",
[EID_INTERRUPTn+12] = "Interrupt12",
[EID_INTERRUPTn+13] = "Interrupt13",
[EID_INTERRUPTn+14] = "Interrupt14",
[EID_INTERRUPTn+15] = "Interrupt15",
[EID_INTERRUPTn+16] = "Interrupt16",
[EID_INTERRUPTn+17] = "Interrupt17",
[EID_INTERRUPTn+18] = "Interrupt18",
[EID_INTERRUPTn+19] = "Interrupt19",
[EID_INTERRUPTn+20] = "Interrupt20",
[EID_INTERRUPTn+21] = "Interrupt21",
[EID_INTERRUPTn+22] = "Interrupt22",
[EID_INTERRUPTn+23] = "Interrupt23",
[EID_INTERRUPTn+24] = "Interrupt24",
[EID_INTERRUPTn+25] = "Interrupt25",
[EID_INTERRUPTn+26] = "Interrupt26",
[EID_INTERRUPTn+27] = "Interrupt27",
[EID_INTERRUPTn+28] = "Interrupt28",
[EID_INTERRUPTn+29] = "Interrupt29",
[EID_INTERRUPTn+30] = "Interrupt30",
[EID_INTERRUPTn+31] = "Interrupt31",
};
/*
@@ -142,7 +175,7 @@ static int esirisc_disable_interrupts(struct target *target)
retval = esirisc_jtag_read_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, &etc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: ETC", target_name(target));
LOG_ERROR("%s: failed to read Thread CSR: ETC", target_name(target));
return retval;
}
@@ -150,7 +183,7 @@ static int esirisc_disable_interrupts(struct target *target)
retval = esirisc_jtag_write_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, etc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: ETC", target_name(target));
LOG_ERROR("%s: failed to write Thread CSR: ETC", target_name(target));
return retval;
}
@@ -169,7 +202,7 @@ static int esirisc_enable_interrupts(struct target *target)
retval = esirisc_jtag_read_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, &etc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: ETC", target_name(target));
LOG_ERROR("%s: failed to read Thread CSR: ETC", target_name(target));
return retval;
}
@@ -177,7 +210,7 @@ static int esirisc_enable_interrupts(struct target *target)
retval = esirisc_jtag_write_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC, etc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: ETC", target_name(target));
LOG_ERROR("%s: failed to write Thread CSR: ETC", target_name(target));
return retval;
}
@@ -195,7 +228,7 @@ static int esirisc_save_interrupts(struct target *target)
int retval = esirisc_jtag_read_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC,
&esirisc->etc_save);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: ETC", target_name(target));
LOG_ERROR("%s: failed to read Thread CSR: ETC", target_name(target));
return retval;
}
@@ -212,7 +245,7 @@ static int esirisc_restore_interrupts(struct target *target)
int retval = esirisc_jtag_write_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETC,
esirisc->etc_save);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: ETC", target_name(target));
LOG_ERROR("%s: failed to write Thread CSR: ETC", target_name(target));
return retval;
}
@@ -230,7 +263,7 @@ static int esirisc_save_hwdc(struct target *target)
int retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_HWDC,
&esirisc->hwdc_save);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: HWDC", target_name(target));
LOG_ERROR("%s: failed to read Thread CSR: HWDC", target_name(target));
return retval;
}
@@ -248,7 +281,7 @@ static int esirisc_restore_hwdc(struct target *target)
int retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_HWDC,
esirisc->hwdc_save);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: HWDC", target_name(target));
LOG_ERROR("%s: failed to write Debug CSR: HWDC", target_name(target));
return retval;
}
@@ -478,14 +511,14 @@ static int esirisc_add_breakpoint(struct target *target, struct breakpoint *brea
retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBAn + bp_index,
breakpoint->address);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: IBA", target_name(target));
LOG_ERROR("%s: failed to write Debug CSR: IBA", target_name(target));
return retval;
}
/* enable instruction breakpoint */
retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, &ibc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: IBC", target_name(target));
LOG_ERROR("%s: failed to read Debug CSR: IBC", target_name(target));
return retval;
}
@@ -493,7 +526,7 @@ static int esirisc_add_breakpoint(struct target *target, struct breakpoint *brea
retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, ibc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: IBC", target_name(target));
LOG_ERROR("%s: failed to write Debug CSR: IBC", target_name(target));
return retval;
}
@@ -529,7 +562,7 @@ static int esirisc_remove_breakpoint(struct target *target, struct breakpoint *b
/* disable instruction breakpoint */
retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, &ibc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: IBC", target_name(target));
LOG_ERROR("%s: failed to read Debug CSR: IBC", target_name(target));
return retval;
}
@@ -537,7 +570,7 @@ static int esirisc_remove_breakpoint(struct target *target, struct breakpoint *b
retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, ibc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: IBC", target_name(target));
LOG_ERROR("%s: failed to write Debug CSR: IBC", target_name(target));
return retval;
}
@@ -557,7 +590,7 @@ static int esirisc_remove_breakpoints(struct target *target)
/* clear instruction breakpoints */
int retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_IBC, 0);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: IBC", target_name(target));
LOG_ERROR("%s: failed to write Debug CSR: IBC", target_name(target));
return retval;
}
@@ -604,14 +637,14 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc
retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBAn + wp_index,
watchpoint->address);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: DBA", target_name(target));
LOG_ERROR("%s: failed to write Debug CSR: DBA", target_name(target));
return retval;
}
/* specify data breakpoint size */
retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBS, &dbs);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: DBS", target_name(target));
LOG_ERROR("%s: failed to read Debug CSR: DBS", target_name(target));
return retval;
}
@@ -642,14 +675,14 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc
retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBS, dbs);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: DBS", target_name(target));
LOG_ERROR("%s: failed to write Debug CSR: DBS", target_name(target));
return retval;
}
/* enable data breakpoint */
retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, &dbc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: DBC", target_name(target));
LOG_ERROR("%s: failed to read Debug CSR: DBC", target_name(target));
return retval;
}
@@ -677,7 +710,7 @@ static int esirisc_add_watchpoint(struct target *target, struct watchpoint *watc
retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, dbc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: DBC", target_name(target));
LOG_ERROR("%s: failed to write Debug CSR: DBC", target_name(target));
return retval;
}
@@ -713,7 +746,7 @@ static int esirisc_remove_watchpoint(struct target *target, struct watchpoint *w
/* disable data breakpoint */
retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, &dbc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: DBC", target_name(target));
LOG_ERROR("%s: failed to read Debug CSR: DBC", target_name(target));
return retval;
}
@@ -721,7 +754,7 @@ static int esirisc_remove_watchpoint(struct target *target, struct watchpoint *w
retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, dbc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: DBC", target_name(target));
LOG_ERROR("%s: failed to write Debug CSR: DBC", target_name(target));
return retval;
}
@@ -741,7 +774,7 @@ static int esirisc_remove_watchpoints(struct target *target)
/* clear data breakpoints */
int retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DBC, 0);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: DBC", target_name(target));
LOG_ERROR("%s: failed to write Debug CSR: DBC", target_name(target));
return retval;
}
@@ -782,7 +815,7 @@ static int esirisc_disable_step(struct target *target)
retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DC, &dc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: DC", target_name(target));
LOG_ERROR("%s: failed to read Debug CSR: DC", target_name(target));
return retval;
}
@@ -790,7 +823,7 @@ static int esirisc_disable_step(struct target *target)
retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DC, dc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: DC", target_name(target));
LOG_ERROR("%s: failed to write Debug CSR: DC", target_name(target));
return retval;
}
@@ -808,7 +841,7 @@ static int esirisc_enable_step(struct target *target)
retval = esirisc_jtag_read_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DC, &dc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: DC", target_name(target));
LOG_ERROR("%s: failed to read Debug CSR: DC", target_name(target));
return retval;
}
@@ -816,7 +849,7 @@ static int esirisc_enable_step(struct target *target)
retval = esirisc_jtag_write_csr(jtag_info, CSR_DEBUG, CSR_DEBUG_DC, dc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: DC", target_name(target));
LOG_ERROR("%s: failed to write Debug CSR: DC", target_name(target));
return retval;
}
@@ -1132,7 +1165,7 @@ static int esirisc_reset_entry(struct target *target)
/* read exception table address */
retval = esirisc_jtag_read_csr(jtag_info, CSR_THREAD, CSR_THREAD_ETA, &eta);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: ETA", target_name(target));
LOG_ERROR("%s: failed to read Thread CSR: ETA", target_name(target));
return retval;
}
@@ -1147,7 +1180,7 @@ static int esirisc_reset_entry(struct target *target)
/* write reset entry point */
retval = esirisc_jtag_write_csr(jtag_info, CSR_THREAD, CSR_THREAD_EPC, epc);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to write CSR: EPC", target_name(target));
LOG_ERROR("%s: failed to write Thread CSR: EPC", target_name(target));
return retval;
}
@@ -1215,15 +1248,9 @@ static int esirisc_arch_state(struct target *target)
uint32_t eid = buf_get_u32(esirisc->eid->value, 0, esirisc->eid->size);
uint32_t ed = buf_get_u32(esirisc->ed->value, 0, esirisc->ed->size);
LOG_DEBUG("-");
const char *exception = "Unknown";
if (eid < ARRAY_SIZE(esirisc_exceptions))
exception = esirisc_exceptions[eid];
LOG_USER("target halted due to %s, exception: %s\n"
"EPC: 0x%" PRIx32 " ECAS: 0x%" PRIx32 " EID: 0x%" PRIx32 " ED: 0x%" PRIx32,
debug_reason_name(target), exception, epc, ecas, eid, ed);
"EPC: 0x%" PRIx32 ", ECAS: 0x%" PRIx32 ", EID: 0x%" PRIx32 ", ED: 0x%" PRIx32,
debug_reason_name(target), esirisc_exception_strings[eid], epc, ecas, eid, ed);
return ERROR_OK;
}
@@ -1242,7 +1269,7 @@ static const char *esirisc_get_gdb_arch(struct target *target)
*/
if (esirisc->gdb_arch == NULL && target_was_examined(target))
esirisc->gdb_arch = alloc_printf("esirisc:%d_bit_%d_reg_%s",
esirisc->num_bits, esirisc->num_regs, esirisc_cache_arch(esirisc));
esirisc->num_bits, esirisc->num_regs, esirisc_cache_arch_name(esirisc));
return esirisc->gdb_arch;
}
@@ -1477,7 +1504,7 @@ static int esirisc_identify(struct target *target)
retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_ARCH0, &csr);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: ARCH0", target_name(target));
LOG_ERROR("%s: failed to read Configuration CSR: ARCH0", target_name(target));
return retval;
}
@@ -1486,7 +1513,7 @@ static int esirisc_identify(struct target *target)
retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_MEM, &csr);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: MEM", target_name(target));
LOG_ERROR("%s: failed to read Configuration CSR: MEM", target_name(target));
return retval;
}
@@ -1495,7 +1522,7 @@ static int esirisc_identify(struct target *target)
retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_IC, &csr);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: IC", target_name(target));
LOG_ERROR("%s: failed to read Configuration CSR: IC", target_name(target));
return retval;
}
@@ -1503,7 +1530,7 @@ static int esirisc_identify(struct target *target)
retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_DC, &csr);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: DC", target_name(target));
LOG_ERROR("%s: failed to read Configuration CSR: DC", target_name(target));
return retval;
}
@@ -1511,13 +1538,21 @@ static int esirisc_identify(struct target *target)
retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_DBG, &csr);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read CSR: DBG", target_name(target));
LOG_ERROR("%s: failed to read Configuration CSR: DBG", target_name(target));
return retval;
}
esirisc->num_breakpoints = (csr >> 7) & 0xf; /* DBG.BP */
esirisc->num_watchpoints = (csr >> 12) & 0xf; /* DBG.WP */
retval = esirisc_jtag_read_csr(jtag_info, CSR_CONFIG, CSR_CONFIG_TRACE, &csr);
if (retval != ERROR_OK) {
LOG_ERROR("%s: failed to read Configuration CSR: TRACE", target_name(target));
return retval;
}
esirisc->has_trace = !!(csr & 1<<0); /* TRACE.T */
return ERROR_OK;
}
@@ -1616,13 +1651,14 @@ static int esirisc_examine(struct target *target)
target_set_examined(target);
LOG_INFO("%s: %d bit, %d registers, %s%s%s", target_name(target),
esirisc->num_bits, esirisc->num_regs,
target_endianness(target),
esirisc->has_icache ? ", icache" : "",
esirisc->has_dcache ? ", dcache" : "");
esirisc->num_bits, esirisc->num_regs,
target_endianness(target),
esirisc->has_icache ? ", icache" : "",
esirisc->has_dcache ? ", dcache" : "");
LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints", target_name(target),
esirisc->num_breakpoints, esirisc->num_watchpoints);
LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints%s", target_name(target),
esirisc->num_breakpoints, esirisc->num_watchpoints,
esirisc->has_trace ? ", trace" : "");
}
return ERROR_OK;
@@ -1644,7 +1680,7 @@ COMMAND_HANDLER(handle_esirisc_cache_arch_command)
}
}
command_print(CMD_CTX, "esirisc cache_arch %s", esirisc_cache_arch(esirisc));
command_print(CMD_CTX, "esirisc cache_arch %s", esirisc_cache_arch_name(esirisc));
return ERROR_OK;
}
@@ -1719,6 +1755,17 @@ COMMAND_HANDLER(handle_esirisc_hwdc_command)
}
static const struct command_registration esirisc_exec_command_handlers[] = {
{
.name = "flush_caches",
.handler = handle_esirisc_flush_caches_command,
.mode = COMMAND_EXEC,
.help = "flush instruction and data caches",
.usage = "",
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration esirisc_any_command_handlers[] = {
{
.name = "cache_arch",
.handler = handle_esirisc_cache_arch_command,
@@ -1726,13 +1773,6 @@ static const struct command_registration esirisc_exec_command_handlers[] = {
.help = "configure cache architecture",
.usage = "['harvard'|'von_neumann']",
},
{
.name = "flush_caches",
.handler = handle_esirisc_flush_caches_command,
.mode = COMMAND_EXEC,
.help = "flush instruction and data caches",
.usage = "",
},
{
.name = "hwdc",
.handler = handle_esirisc_hwdc_command,
@@ -1740,6 +1780,12 @@ static const struct command_registration esirisc_exec_command_handlers[] = {
.help = "configure hardware debug control",
.usage = "['all'|'none'|mask ...]",
},
{
.chain = esirisc_exec_command_handlers
},
{
.chain = esirisc_trace_command_handlers
},
COMMAND_REGISTRATION_DONE
};
@@ -1749,7 +1795,7 @@ static const struct command_registration esirisc_command_handlers[] = {
.mode = COMMAND_ANY,
.help = "eSi-RISC command group",
.usage = "",
.chain = esirisc_exec_command_handlers,
.chain = esirisc_any_command_handlers,
},
COMMAND_REGISTRATION_DONE
};
+9 -3
View File
@@ -20,12 +20,14 @@
#ifndef OPENOCD_TARGET_ESIRISC_H
#define OPENOCD_TARGET_ESIRISC_H
#include <helper/types.h>
#include <target/breakpoints.h>
#include <target/register.h>
#include <target/target.h>
#include "esirisc_jtag.h"
#include "esirisc_regs.h"
#include "esirisc_trace.h"
#define MAX_BREAKPOINTS 8
#define MAX_WATCHPOINTS 8
@@ -88,11 +90,15 @@ struct esirisc_common {
int num_regs;
bool has_icache;
bool has_dcache;
int num_breakpoints;
int num_watchpoints;
bool has_trace;
int num_breakpoints;
struct breakpoint *breakpoints_p[MAX_BREAKPOINTS];
int num_watchpoints;
struct watchpoint *watchpoints_p[MAX_WATCHPOINTS];
struct esirisc_trace trace_info;
};
union esirisc_memory {
@@ -116,7 +122,7 @@ static inline struct esirisc_common *target_to_esirisc(struct target *target)
return (struct esirisc_common *)target->arch_info;
}
static inline char *esirisc_cache_arch(struct esirisc_common *esirisc)
static inline char *esirisc_cache_arch_name(struct esirisc_common *esirisc)
{
return esirisc->cache_arch == ESIRISC_CACHE_HARVARD ? "harvard" : "von_neumann";
}
+15
View File
@@ -265,6 +265,7 @@ int esirisc_jtag_read_byte(struct esirisc_jtag *jtag_info, uint32_t address, uin
return retval;
*data = *d;
LOG_DEBUG("address: 0x%" PRIx32 ", data: 0x%" PRIx8, address, *data);
return ERROR_OK;
}
@@ -292,6 +293,7 @@ int esirisc_jtag_read_hword(struct esirisc_jtag *jtag_info, uint32_t address, ui
return retval;
*data = le_to_h_u16(d);
LOG_DEBUG("address: 0x%" PRIx32 ", data: 0x%" PRIx16, address, *data);
return ERROR_OK;
}
@@ -319,6 +321,7 @@ int esirisc_jtag_read_word(struct esirisc_jtag *jtag_info, uint32_t address, uin
return retval;
*data = le_to_h_u32(d);
LOG_DEBUG("address: 0x%" PRIx32 ", data: 0x%" PRIx32, address, *data);
return ERROR_OK;
}
@@ -328,6 +331,8 @@ int esirisc_jtag_write_byte(struct esirisc_jtag *jtag_info, uint32_t address, ui
struct scan_field out_fields[2];
uint8_t a[4];
LOG_DEBUG("address: 0x%" PRIx32 ", data: 0x%" PRIx8, address, data);
out_fields[0].num_bits = 32;
out_fields[0].out_value = a;
h_u32_to_be(a, address);
@@ -346,6 +351,8 @@ int esirisc_jtag_write_hword(struct esirisc_jtag *jtag_info, uint32_t address, u
struct scan_field out_fields[2];
uint8_t a[4], d[2];
LOG_DEBUG("address: 0x%" PRIx32 ", data: 0x%" PRIx16, address, data);
out_fields[0].num_bits = 32;
out_fields[0].out_value = a;
h_u32_to_be(a, address);
@@ -365,6 +372,8 @@ int esirisc_jtag_write_word(struct esirisc_jtag *jtag_info, uint32_t address, ui
struct scan_field out_fields[2];
uint8_t a[4], d[4];
LOG_DEBUG("address: 0x%" PRIx32 ", data: 0x%" PRIx32, address, data);
out_fields[0].num_bits = 32;
out_fields[0].out_value = a;
h_u32_to_be(a, address);
@@ -400,6 +409,7 @@ int esirisc_jtag_read_reg(struct esirisc_jtag *jtag_info, uint8_t reg, uint32_t
return retval;
*data = le_to_h_u32(d);
LOG_DEBUG("register: 0x%" PRIx32 ", data: 0x%" PRIx32, reg, *data);
return ERROR_OK;
}
@@ -409,6 +419,8 @@ int esirisc_jtag_write_reg(struct esirisc_jtag *jtag_info, uint8_t reg, uint32_t
struct scan_field out_fields[2];
uint8_t d[4];
LOG_DEBUG("register: 0x%" PRIx32 ", data: 0x%" PRIx32, reg, data);
out_fields[0].num_bits = 8;
out_fields[0].out_value = &reg;
out_fields[0].in_value = NULL;
@@ -445,6 +457,7 @@ int esirisc_jtag_read_csr(struct esirisc_jtag *jtag_info, uint8_t bank, uint8_t
return retval;
*data = le_to_h_u32(d);
LOG_DEBUG("bank: 0x%" PRIx32 ", csr: 0x%" PRIx32 ", data: 0x%" PRIx32, bank, csr, *data);
return ERROR_OK;
}
@@ -454,6 +467,8 @@ int esirisc_jtag_write_csr(struct esirisc_jtag *jtag_info, uint8_t bank, uint8_t
struct scan_field out_fields[2];
uint8_t c[2], d[4];
LOG_DEBUG("bank: 0x%" PRIx32 ", csr: 0x%" PRIx32 ", data: 0x%" PRIx32, bank, csr, data);
out_fields[0].num_bits = 16;
out_fields[0].out_value = c;
h_u16_to_be(c, (csr << 5) | bank);
+1
View File
@@ -20,6 +20,7 @@
#ifndef OPENOCD_TARGET_ESIRISC_JTAG_H
#define OPENOCD_TARGET_ESIRISC_JTAG_H
#include <helper/types.h>
#include <jtag/jtag.h>
/* TAP Instructions */
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More