Merge branch 'master' into from_upstream
Change-Id: I61e24edbdeceddba265514fd7e0a489ec23e2a4c
This commit is contained in:
commit
b6fabdd429
|
@ -174,7 +174,7 @@ them. It is similar to this bash statement.
|
||||||
EXPORT vn=`date`
|
EXPORT vn=`date`
|
||||||
|
|
||||||
LINE 2 & 3
|
LINE 2 & 3
|
||||||
set $vn [expr (1024 * $x)]
|
set $vn [expr {1024 * $x}]
|
||||||
global $vn
|
global $vn
|
||||||
|
|
||||||
In line 1, we dynamically created a variable name. Here, we are
|
In line 1, we dynamically created a variable name. Here, we are
|
||||||
|
|
|
@ -2009,9 +2009,9 @@ proc setc15 @{regs value@} @{
|
||||||
|
|
||||||
echo [format "set p15 0x%04x, 0x%08x" $regs $value]
|
echo [format "set p15 0x%04x, 0x%08x" $regs $value]
|
||||||
|
|
||||||
arm mcr 15 [expr ($regs>>12)&0x7] \
|
arm mcr 15 [expr @{($regs >> 12) & 0x7@}] \
|
||||||
[expr ($regs>>0)&0xf] [expr ($regs>>4)&0xf] \
|
[expr @{($regs >> 0) & 0xf@}] [expr @{($regs >> 4) & 0xf@}] \
|
||||||
[expr ($regs>>8)&0x7] $value
|
[expr @{($regs >> 8) & 0x7@}] $value
|
||||||
@}
|
@}
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
@ -3157,7 +3157,9 @@ the target's supply voltage.
|
||||||
The result can be converted to Volts (ignoring the most significant bytes, always zero)
|
The result can be converted to Volts (ignoring the most significant bytes, always zero)
|
||||||
@example
|
@example
|
||||||
> set a [st-link cmd 8 0xf7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
|
> set a [st-link cmd 8 0xf7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
|
||||||
> echo [expr 2*1.2*([lindex $a 4]+256*[lindex $a 5])/([lindex $a 0]+256*[lindex $a 1])]
|
> set n [expr @{[lindex $a 4] + 256 * [lindex $a 5]@}]
|
||||||
|
> set d [expr @{[lindex $a 0] + 256 * [lindex $a 1]@}]
|
||||||
|
> echo [expr @{2 * 1.2 * $n / $d@}]
|
||||||
3.24891518738
|
3.24891518738
|
||||||
@end example
|
@end example
|
||||||
@end deffn
|
@end deffn
|
||||||
|
@ -4151,6 +4153,10 @@ option. When vendors put out multiple versions of a chip, or use the same
|
||||||
JTAG-level ID for several largely-compatible chips, it may be more practical
|
JTAG-level ID for several largely-compatible chips, it may be more practical
|
||||||
to ignore the version field than to update config files to handle all of
|
to ignore the version field than to update config files to handle all of
|
||||||
the various chip IDs. The version field is defined as bit 28-31 of the IDCODE.
|
the various chip IDs. The version field is defined as bit 28-31 of the IDCODE.
|
||||||
|
@item @code{-ignore-bypass}
|
||||||
|
@*Specify this to ignore the 'bypass' bit of the idcode. Some vendor put
|
||||||
|
an invalid idcode regarding this bit. Specify this to ignore this bit and
|
||||||
|
to not consider this tap in bypass mode.
|
||||||
@item @code{-ircapture} @var{NUMBER}
|
@item @code{-ircapture} @var{NUMBER}
|
||||||
@*The bit pattern loaded by the TAP into the JTAG shift register
|
@*The bit pattern loaded by the TAP into the JTAG shift register
|
||||||
on entry to the @sc{ircapture} state, such as 0x01.
|
on entry to the @sc{ircapture} state, such as 0x01.
|
||||||
|
@ -4523,13 +4529,13 @@ where the mask bit is 1. The following example sets HPROT3 (cacheable)
|
||||||
and leaves the rest of the pattern intact. It configures memory access through
|
and leaves the rest of the pattern intact. It configures memory access through
|
||||||
DCache on Cortex-M7.
|
DCache on Cortex-M7.
|
||||||
@example
|
@example
|
||||||
set CSW_HPROT3_CACHEABLE [expr 1 << 27]
|
set CSW_HPROT3_CACHEABLE [expr @{1 << 27@}]
|
||||||
samv.dap apcsw $CSW_HPROT3_CACHEABLE $CSW_HPROT3_CACHEABLE
|
samv.dap apcsw $CSW_HPROT3_CACHEABLE $CSW_HPROT3_CACHEABLE
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
Another example clears SPROT bit and leaves the rest of pattern intact:
|
Another example clears SPROT bit and leaves the rest of pattern intact:
|
||||||
@example
|
@example
|
||||||
set CSW_SPROT [expr 1 << 30]
|
set CSW_SPROT [expr @{1 << 30@}]
|
||||||
samv.dap apcsw 0 $CSW_SPROT
|
samv.dap apcsw 0 $CSW_SPROT
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
@ -6351,13 +6357,22 @@ flash bank $_FLASHNAME cc3220sf 0 0 0 0 $_TARGETNAME
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Flash Driver} {efm32}
|
@deffn {Flash Driver} {efm32}
|
||||||
All members of the EFM32 microcontroller family from Energy Micro include
|
All members of the EFM32/EFR32 microcontroller family from Energy Micro (now Silicon Labs)
|
||||||
internal flash and use ARM Cortex-M3 cores. The driver automatically recognizes
|
include internal flash and use Arm Cortex-M3 or Cortex-M4 cores. The driver automatically
|
||||||
a number of these chips using the chip identification register, and
|
recognizes a number of these chips using the chip identification register, and
|
||||||
autoconfigures itself.
|
autoconfigures itself.
|
||||||
@example
|
@example
|
||||||
flash bank $_FLASHNAME efm32 0 0 0 0 $_TARGETNAME
|
flash bank $_FLASHNAME efm32 0 0 0 0 $_TARGETNAME
|
||||||
@end example
|
@end example
|
||||||
|
It supports writing to the user data page, as well as the portion of the lockbits page
|
||||||
|
past 512 bytes on chips with larger page sizes. The latter is used by the SiLabs
|
||||||
|
bootloader/AppLoader system for encryption keys. Setting protection on these pages is
|
||||||
|
currently not supported.
|
||||||
|
@example
|
||||||
|
flash bank userdata.flash efm32 0x0FE00000 0 0 0 $_TARGETNAME
|
||||||
|
flash bank lockbits.flash efm32 0x0FE04000 0 0 0 $_TARGETNAME
|
||||||
|
@end example
|
||||||
|
|
||||||
A special feature of efm32 controllers is that it is possible to completely disable the
|
A special feature of efm32 controllers is that it is possible to completely disable the
|
||||||
debug interface by writing the correct values to the 'Debug Lock Word'. OpenOCD supports
|
debug interface by writing the correct values to the 'Debug Lock Word'. OpenOCD supports
|
||||||
this via the following command:
|
this via the following command:
|
||||||
|
@ -8611,7 +8626,7 @@ In addition the following arguments may be specified:
|
||||||
proc load_image_bin @{fname foffset address length @} @{
|
proc load_image_bin @{fname foffset address length @} @{
|
||||||
# Load data from fname filename at foffset offset to
|
# Load data from fname filename at foffset offset to
|
||||||
# target at address. Load at most length bytes.
|
# target at address. Load at most length bytes.
|
||||||
load_image $fname [expr $address - $foffset] bin \
|
load_image $fname [expr @{$address - $foffset@}] bin \
|
||||||
$address $length
|
$address $length
|
||||||
@}
|
@}
|
||||||
@end example
|
@end example
|
||||||
|
@ -10431,7 +10446,7 @@ trivial challenge-response protocol could be implemented as follows in a
|
||||||
configuration file, immediately following @command{init}:
|
configuration file, immediately following @command{init}:
|
||||||
@example
|
@example
|
||||||
set challenge [riscv authdata_read]
|
set challenge [riscv authdata_read]
|
||||||
riscv authdata_write [expr $challenge + 1]
|
riscv authdata_write [expr @{$challenge + 1@}]
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@deffn {Command} {riscv authdata_read} [index=0]
|
@deffn {Command} {riscv authdata_read} [index=0]
|
||||||
|
@ -12142,7 +12157,7 @@ it reads a file and executes as a script.
|
||||||
@example
|
@example
|
||||||
set x 6
|
set x 6
|
||||||
set y 7
|
set y 7
|
||||||
puts [format "The answer: %d" [expr $x * $y]]
|
puts [format "The answer: %d" [expr @{$x * $y@}]]
|
||||||
@end example
|
@end example
|
||||||
@enumerate
|
@enumerate
|
||||||
@item The SET command creates 2 variables, X and Y.
|
@item The SET command creates 2 variables, X and Y.
|
||||||
|
@ -12213,13 +12228,13 @@ proc myproc @{ @} @{
|
||||||
@b{Dynamic variable creation}
|
@b{Dynamic variable creation}
|
||||||
@example
|
@example
|
||||||
# Dynamically create a bunch of variables.
|
# Dynamically create a bunch of variables.
|
||||||
for @{ set x 0 @} @{ $x < 32 @} @{ set x [expr $x + 1]@} @{
|
for @{ set x 0 @} @{ $x < 32 @} @{ set x [expr @{$x + 1@}]@} @{
|
||||||
# Create var name
|
# Create var name
|
||||||
set vn [format "BIT%d" $x]
|
set vn [format "BIT%d" $x]
|
||||||
# Make it a global
|
# Make it a global
|
||||||
global $vn
|
global $vn
|
||||||
# Set it.
|
# Set it.
|
||||||
set $vn [expr (1 << $x)]
|
set $vn [expr @{1 << $x@}]
|
||||||
@}
|
@}
|
||||||
@end example
|
@end example
|
||||||
@b{Dynamic proc/command creation}
|
@b{Dynamic proc/command creation}
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
* Copyright (C) 2014 Nemui Trinomius *
|
* Copyright (C) 2014 Nemui Trinomius *
|
||||||
* nemuisan_kawausogasuki@live.jp *
|
* nemuisan_kawausogasuki@live.jp *
|
||||||
* *
|
* *
|
||||||
|
* Copyright (C) 2021 Doug Brunner *
|
||||||
|
* doug.a.brunner@gmail.com *
|
||||||
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* 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 *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
* the Free Software Foundation; either version 2 of the License, or *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
@ -45,13 +48,16 @@
|
||||||
#define EFM32_FLASH_WDATAREADY_TMO 100
|
#define EFM32_FLASH_WDATAREADY_TMO 100
|
||||||
#define EFM32_FLASH_WRITE_TMO 100
|
#define EFM32_FLASH_WRITE_TMO 100
|
||||||
|
|
||||||
|
#define EFM32_FLASH_BASE 0
|
||||||
|
|
||||||
/* size in bytes, not words; must fit all Gecko devices */
|
/* size in bytes, not words; must fit all Gecko devices */
|
||||||
#define LOCKBITS_PAGE_SZ 512
|
#define LOCKWORDS_SZ 512
|
||||||
|
|
||||||
#define EFM32_MSC_INFO_BASE 0x0fe00000
|
#define EFM32_MSC_INFO_BASE 0x0fe00000
|
||||||
|
|
||||||
#define EFM32_MSC_USER_DATA EFM32_MSC_INFO_BASE
|
#define EFM32_MSC_USER_DATA EFM32_MSC_INFO_BASE
|
||||||
#define EFM32_MSC_LOCK_BITS (EFM32_MSC_INFO_BASE+0x4000)
|
#define EFM32_MSC_LOCK_BITS (EFM32_MSC_INFO_BASE+0x4000)
|
||||||
|
#define EFM32_MSC_LOCK_BITS_EXTRA (EFM32_MSC_LOCK_BITS+LOCKWORDS_SZ)
|
||||||
#define EFM32_MSC_DEV_INFO (EFM32_MSC_INFO_BASE+0x8000)
|
#define EFM32_MSC_DEV_INFO (EFM32_MSC_INFO_BASE+0x8000)
|
||||||
|
|
||||||
/* PAGE_SIZE is not present in Zero, Happy and the original Gecko MCU */
|
/* PAGE_SIZE is not present in Zero, Happy and the original Gecko MCU */
|
||||||
|
@ -83,6 +89,27 @@
|
||||||
#define EFM32_MSC_REG_LOCK_SERIES1 0x040
|
#define EFM32_MSC_REG_LOCK_SERIES1 0x040
|
||||||
#define EFM32_MSC_LOCK_LOCKKEY 0x1b71
|
#define EFM32_MSC_LOCK_LOCKKEY 0x1b71
|
||||||
|
|
||||||
|
enum efm32_bank_index {
|
||||||
|
EFM32_BANK_INDEX_MAIN,
|
||||||
|
EFM32_BANK_INDEX_USER_DATA,
|
||||||
|
EFM32_BANK_INDEX_LOCK_BITS,
|
||||||
|
EFM32_N_BANKS
|
||||||
|
};
|
||||||
|
|
||||||
|
static int efm32x_get_bank_index(target_addr_t base)
|
||||||
|
{
|
||||||
|
switch (base) {
|
||||||
|
case EFM32_FLASH_BASE:
|
||||||
|
return EFM32_BANK_INDEX_MAIN;
|
||||||
|
case EFM32_MSC_USER_DATA:
|
||||||
|
return EFM32_BANK_INDEX_USER_DATA;
|
||||||
|
case EFM32_MSC_LOCK_BITS:
|
||||||
|
return EFM32_BANK_INDEX_LOCK_BITS;
|
||||||
|
default:
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct efm32_family_data {
|
struct efm32_family_data {
|
||||||
int family_id;
|
int family_id;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -98,13 +125,6 @@ struct efm32_family_data {
|
||||||
uint32_t msc_regbase;
|
uint32_t msc_regbase;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct efm32x_flash_bank {
|
|
||||||
bool probed;
|
|
||||||
uint32_t lb_page[LOCKBITS_PAGE_SZ/4];
|
|
||||||
uint32_t reg_base;
|
|
||||||
uint32_t reg_lock;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct efm32_info {
|
struct efm32_info {
|
||||||
const struct efm32_family_data *family_data;
|
const struct efm32_family_data *family_data;
|
||||||
uint16_t flash_sz_kib;
|
uint16_t flash_sz_kib;
|
||||||
|
@ -115,6 +135,15 @@ struct efm32_info {
|
||||||
uint16_t page_size;
|
uint16_t page_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct efm32x_flash_chip {
|
||||||
|
struct efm32_info info;
|
||||||
|
bool probed[EFM32_N_BANKS];
|
||||||
|
uint32_t lb_page[LOCKWORDS_SZ/4];
|
||||||
|
uint32_t reg_base;
|
||||||
|
uint32_t reg_lock;
|
||||||
|
uint32_t refcount;
|
||||||
|
};
|
||||||
|
|
||||||
static const struct efm32_family_data efm32_families[] = {
|
static const struct efm32_family_data efm32_families[] = {
|
||||||
{ 16, "EFR32MG1P Mighty", .series = 1 },
|
{ 16, "EFR32MG1P Mighty", .series = 1 },
|
||||||
{ 17, "EFR32MG1B Mighty", .series = 1 },
|
{ 17, "EFR32MG1B Mighty", .series = 1 },
|
||||||
|
@ -175,9 +204,12 @@ static const struct efm32_family_data efm32_families[] = {
|
||||||
{ 122, "EZR32HG Happy", .series = 0, .page_size = 1024 },
|
{ 122, "EZR32HG Happy", .series = 0, .page_size = 1024 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct flash_driver efm32_flash;
|
||||||
|
|
||||||
static int efm32x_write(struct flash_bank *bank, const uint8_t *buffer,
|
static int efm32x_priv_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||||
uint32_t offset, uint32_t count);
|
uint32_t addr, uint32_t count);
|
||||||
|
|
||||||
|
static int efm32x_write_only_lockbits(struct flash_bank *bank);
|
||||||
|
|
||||||
static int efm32x_get_flash_size(struct flash_bank *bank, uint16_t *flash_sz)
|
static int efm32x_get_flash_size(struct flash_bank *bank, uint16_t *flash_sz)
|
||||||
{
|
{
|
||||||
|
@ -207,7 +239,7 @@ static int efm32x_get_prod_rev(struct flash_bank *bank, uint8_t *prev)
|
||||||
static int efm32x_read_reg_u32(struct flash_bank *bank, target_addr_t offset,
|
static int efm32x_read_reg_u32(struct flash_bank *bank, target_addr_t offset,
|
||||||
uint32_t *value)
|
uint32_t *value)
|
||||||
{
|
{
|
||||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
uint32_t base = efm32x_info->reg_base;
|
uint32_t base = efm32x_info->reg_base;
|
||||||
|
|
||||||
return target_read_u32(bank->target, base + offset, value);
|
return target_read_u32(bank->target, base + offset, value);
|
||||||
|
@ -216,18 +248,18 @@ static int efm32x_read_reg_u32(struct flash_bank *bank, target_addr_t offset,
|
||||||
static int efm32x_write_reg_u32(struct flash_bank *bank, target_addr_t offset,
|
static int efm32x_write_reg_u32(struct flash_bank *bank, target_addr_t offset,
|
||||||
uint32_t value)
|
uint32_t value)
|
||||||
{
|
{
|
||||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
uint32_t base = efm32x_info->reg_base;
|
uint32_t base = efm32x_info->reg_base;
|
||||||
|
|
||||||
return target_write_u32(bank->target, base + offset, value);
|
return target_write_u32(bank->target, base + offset, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int efm32x_read_info(struct flash_bank *bank,
|
static int efm32x_read_info(struct flash_bank *bank)
|
||||||
struct efm32_info *efm32_info)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
uint32_t cpuid = 0;
|
uint32_t cpuid = 0;
|
||||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
|
struct efm32_info *efm32_info = &(efm32x_info->info);
|
||||||
|
|
||||||
memset(efm32_info, 0, sizeof(struct efm32_info));
|
memset(efm32_info, 0, sizeof(struct efm32_info));
|
||||||
|
|
||||||
|
@ -327,20 +359,61 @@ static int efm32x_read_info(struct flash_bank *bank,
|
||||||
/* flash bank efm32 <base> <size> 0 0 <target#> */
|
/* flash bank efm32 <base> <size> 0 0 <target#> */
|
||||||
FLASH_BANK_COMMAND_HANDLER(efm32x_flash_bank_command)
|
FLASH_BANK_COMMAND_HANDLER(efm32x_flash_bank_command)
|
||||||
{
|
{
|
||||||
struct efm32x_flash_bank *efm32x_info;
|
struct efm32x_flash_chip *efm32x_info = NULL;
|
||||||
|
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
efm32x_info = malloc(sizeof(struct efm32x_flash_bank));
|
int bank_index = efm32x_get_bank_index(bank->base);
|
||||||
|
if (bank_index < 0) {
|
||||||
|
LOG_ERROR("Flash bank with base address %" PRIx32 " is not supported",
|
||||||
|
(uint32_t) bank->base);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* look for an existing flash structure matching target */
|
||||||
|
for (struct flash_bank *bank_iter = flash_bank_list(); bank_iter; bank_iter = bank_iter->next) {
|
||||||
|
if (bank_iter->driver == &efm32_flash
|
||||||
|
&& bank_iter->target == bank->target
|
||||||
|
&& bank->driver_priv) {
|
||||||
|
efm32x_info = bank->driver_priv;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!efm32x_info) {
|
||||||
|
/* target not matched, make a new one */
|
||||||
|
efm32x_info = calloc(1, sizeof(struct efm32x_flash_chip));
|
||||||
|
|
||||||
|
memset(efm32x_info->lb_page, 0xff, LOCKWORDS_SZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
++efm32x_info->refcount;
|
||||||
bank->driver_priv = efm32x_info;
|
bank->driver_priv = efm32x_info;
|
||||||
efm32x_info->probed = false;
|
|
||||||
memset(efm32x_info->lb_page, 0xff, LOCKBITS_PAGE_SZ);
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove flash structure corresponding to this bank,
|
||||||
|
* if and only if it's not used by any others
|
||||||
|
*/
|
||||||
|
static void efm32x_free_driver_priv(struct flash_bank *bank)
|
||||||
|
{
|
||||||
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
|
|
||||||
|
if (efm32x_info) {
|
||||||
|
/* Use ref count to determine if it can be freed; scanning bank list doesn't work,
|
||||||
|
* because this function can be called after some banks in the list have been
|
||||||
|
* already destroyed */
|
||||||
|
--efm32x_info->refcount;
|
||||||
|
if (efm32x_info->refcount == 0) {
|
||||||
|
free(efm32x_info);
|
||||||
|
bank->driver_priv = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* set or reset given bits in a register */
|
/* set or reset given bits in a register */
|
||||||
static int efm32x_set_reg_bits(struct flash_bank *bank, uint32_t reg,
|
static int efm32x_set_reg_bits(struct flash_bank *bank, uint32_t reg,
|
||||||
uint32_t bitmask, int set)
|
uint32_t bitmask, int set)
|
||||||
|
@ -368,7 +441,7 @@ static int efm32x_set_wren(struct flash_bank *bank, int write_enable)
|
||||||
|
|
||||||
static int efm32x_msc_lock(struct flash_bank *bank, int lock)
|
static int efm32x_msc_lock(struct flash_bank *bank, int lock)
|
||||||
{
|
{
|
||||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
return efm32x_write_reg_u32(bank, efm32x_info->reg_lock,
|
return efm32x_write_reg_u32(bank, efm32x_info->reg_lock,
|
||||||
(lock ? 0 : EFM32_MSC_LOCK_LOCKKEY));
|
(lock ? 0 : EFM32_MSC_LOCK_LOCKKEY));
|
||||||
}
|
}
|
||||||
|
@ -416,7 +489,6 @@ static int efm32x_erase_page(struct flash_bank *bank, uint32_t addr)
|
||||||
*/
|
*/
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
uint32_t status = 0;
|
uint32_t status = 0;
|
||||||
addr += bank->base;
|
|
||||||
LOG_DEBUG("erasing flash page at 0x%08" PRIx32, addr);
|
LOG_DEBUG("erasing flash page at 0x%08" PRIx32, addr);
|
||||||
|
|
||||||
ret = efm32x_write_reg_u32(bank, EFM32_MSC_REG_ADDRB, addr);
|
ret = efm32x_write_reg_u32(bank, EFM32_MSC_REG_ADDRB, addr);
|
||||||
|
@ -470,20 +542,28 @@ static int efm32x_erase(struct flash_bank *bank, unsigned int first,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = first; i <= last; i++) {
|
for (unsigned int i = first; i <= last; i++) {
|
||||||
ret = efm32x_erase_page(bank, bank->sectors[i].offset);
|
ret = efm32x_erase_page(bank, bank->base + bank->sectors[i].offset);
|
||||||
if (ret != ERROR_OK)
|
if (ret != ERROR_OK)
|
||||||
LOG_ERROR("Failed to erase page %d", i);
|
LOG_ERROR("Failed to erase page %d", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = efm32x_set_wren(bank, 0);
|
ret = efm32x_set_wren(bank, 0);
|
||||||
efm32x_msc_lock(bank, 1);
|
efm32x_msc_lock(bank, 1);
|
||||||
|
if (ret != ERROR_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (bank->base == EFM32_MSC_LOCK_BITS) {
|
||||||
|
ret = efm32x_write_only_lockbits(bank);
|
||||||
|
if (ret != ERROR_OK)
|
||||||
|
LOG_ERROR("Failed to restore lockbits after erase");
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int efm32x_read_lock_data(struct flash_bank *bank)
|
static int efm32x_read_lock_data(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
int data_size = 0;
|
int data_size = 0;
|
||||||
uint32_t *ptr = NULL;
|
uint32_t *ptr = NULL;
|
||||||
|
@ -557,35 +637,84 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int efm32x_write_only_lockbits(struct flash_bank *bank)
|
||||||
|
{
|
||||||
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
|
return efm32x_priv_write(bank, (uint8_t *)efm32x_info->lb_page, EFM32_MSC_LOCK_BITS, LOCKWORDS_SZ);
|
||||||
|
}
|
||||||
|
|
||||||
static int efm32x_write_lock_data(struct flash_bank *bank)
|
static int efm32x_write_lock_data(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
/* Preserve any data written to the high portion of the lockbits page */
|
||||||
|
assert(efm32x_info->info.page_size >= LOCKWORDS_SZ);
|
||||||
|
uint32_t extra_bytes = efm32x_info->info.page_size - LOCKWORDS_SZ;
|
||||||
|
uint8_t *extra_data = NULL;
|
||||||
|
if (extra_bytes) {
|
||||||
|
extra_data = malloc(extra_bytes);
|
||||||
|
ret = target_read_buffer(bank->target, EFM32_MSC_LOCK_BITS_EXTRA, extra_bytes, extra_data);
|
||||||
|
if (ret != ERROR_OK) {
|
||||||
|
LOG_ERROR("Failed to read extra contents of LB page");
|
||||||
|
free(extra_data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = efm32x_erase_page(bank, EFM32_MSC_LOCK_BITS);
|
ret = efm32x_erase_page(bank, EFM32_MSC_LOCK_BITS);
|
||||||
if (ret != ERROR_OK) {
|
if (ret != ERROR_OK) {
|
||||||
LOG_ERROR("Failed to erase LB page");
|
LOG_ERROR("Failed to erase LB page");
|
||||||
|
if (extra_data)
|
||||||
|
free(extra_data);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return efm32x_write(bank, (uint8_t *)efm32x_info->lb_page, EFM32_MSC_LOCK_BITS,
|
if (extra_data) {
|
||||||
LOCKBITS_PAGE_SZ);
|
ret = efm32x_priv_write(bank, extra_data, EFM32_MSC_LOCK_BITS_EXTRA, extra_bytes);
|
||||||
|
free(extra_data);
|
||||||
|
if (ret != ERROR_OK) {
|
||||||
|
LOG_ERROR("Failed to restore extra contents of LB page");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return efm32x_write_only_lockbits(bank);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int efm32x_get_page_lock(struct flash_bank *bank, size_t page)
|
static int efm32x_get_page_lock(struct flash_bank *bank, size_t page)
|
||||||
{
|
{
|
||||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
uint32_t dw = efm32x_info->lb_page[page >> 5];
|
uint32_t dw = 0;
|
||||||
uint32_t mask = 0;
|
uint32_t mask = 0;
|
||||||
|
|
||||||
mask = 1 << (page & 0x1f);
|
switch (bank->base) {
|
||||||
|
case EFM32_FLASH_BASE:
|
||||||
|
dw = efm32x_info->lb_page[page >> 5];
|
||||||
|
mask = 1 << (page & 0x1f);
|
||||||
|
break;
|
||||||
|
case EFM32_MSC_USER_DATA:
|
||||||
|
dw = efm32x_info->lb_page[126];
|
||||||
|
mask = 0x1;
|
||||||
|
break;
|
||||||
|
case EFM32_MSC_LOCK_BITS:
|
||||||
|
dw = efm32x_info->lb_page[126];
|
||||||
|
mask = 0x2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return (dw & mask) ? 0 : 1;
|
return (dw & mask) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int efm32x_set_page_lock(struct flash_bank *bank, size_t page, int set)
|
static int efm32x_set_page_lock(struct flash_bank *bank, size_t page, int set)
|
||||||
{
|
{
|
||||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
|
|
||||||
|
if (bank->base != EFM32_FLASH_BASE) {
|
||||||
|
LOG_ERROR("Locking user and lockbits pages is not supported yet");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t *dw = &efm32x_info->lb_page[page >> 5];
|
uint32_t *dw = &efm32x_info->lb_page[page >> 5];
|
||||||
uint32_t mask = 0;
|
uint32_t mask = 0;
|
||||||
|
|
||||||
|
@ -605,11 +734,6 @@ static int efm32x_protect(struct flash_bank *bank, int set, unsigned int first,
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!set) {
|
|
||||||
LOG_ERROR("Erase device data to reset page locks");
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
|
@ -633,16 +757,15 @@ static int efm32x_protect(struct flash_bank *bank, int set, unsigned int first,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int efm32x_write_block(struct flash_bank *bank, const uint8_t *buf,
|
static int efm32x_write_block(struct flash_bank *bank, const uint8_t *buf,
|
||||||
uint32_t offset, uint32_t count)
|
uint32_t address, uint32_t count)
|
||||||
{
|
{
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
uint32_t buffer_size = 16384;
|
uint32_t buffer_size = 16384;
|
||||||
struct working_area *write_algorithm;
|
struct working_area *write_algorithm;
|
||||||
struct working_area *source;
|
struct working_area *source;
|
||||||
uint32_t address = bank->base + offset;
|
|
||||||
struct reg_param reg_params[5];
|
struct reg_param reg_params[5];
|
||||||
struct armv7m_algorithm armv7m_info;
|
struct armv7m_algorithm armv7m_info;
|
||||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
int ret = ERROR_OK;
|
int ret = ERROR_OK;
|
||||||
|
|
||||||
/* see contrib/loaders/flash/efm32.S for src */
|
/* see contrib/loaders/flash/efm32.S for src */
|
||||||
|
@ -864,8 +987,8 @@ static int efm32x_write_word(struct flash_bank *bank, uint32_t addr,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int efm32x_write(struct flash_bank *bank, const uint8_t *buffer,
|
static int efm32x_priv_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||||
uint32_t offset, uint32_t count)
|
uint32_t addr, uint32_t count)
|
||||||
{
|
{
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
uint8_t *new_buffer = NULL;
|
uint8_t *new_buffer = NULL;
|
||||||
|
@ -875,9 +998,9 @@ static int efm32x_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset & 0x3) {
|
if (addr & 0x3) {
|
||||||
LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte "
|
LOG_ERROR("addr 0x%" PRIx32 " breaks required 4-byte "
|
||||||
"alignment", offset);
|
"alignment", addr);
|
||||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -906,7 +1029,7 @@ static int efm32x_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* try using a block write */
|
/* try using a block write */
|
||||||
retval = efm32x_write_block(bank, buffer, offset, words_remaining);
|
retval = efm32x_write_block(bank, buffer, addr, words_remaining);
|
||||||
|
|
||||||
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
|
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
|
||||||
/* if block write failed (no sufficient working area),
|
/* if block write failed (no sufficient working area),
|
||||||
|
@ -918,13 +1041,13 @@ static int efm32x_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
memcpy(&value, buffer, sizeof(uint32_t));
|
memcpy(&value, buffer, sizeof(uint32_t));
|
||||||
|
|
||||||
retval = efm32x_write_word(bank, offset, value);
|
retval = efm32x_write_word(bank, addr, value);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
goto reset_pg_and_lock;
|
goto reset_pg_and_lock;
|
||||||
|
|
||||||
words_remaining--;
|
words_remaining--;
|
||||||
buffer += 4;
|
buffer += 4;
|
||||||
offset += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -939,63 +1062,77 @@ cleanup:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int efm32x_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||||
|
uint32_t offset, uint32_t count)
|
||||||
|
{
|
||||||
|
if (bank->base == EFM32_MSC_LOCK_BITS && offset < LOCKWORDS_SZ) {
|
||||||
|
LOG_ERROR("Cannot write to lock words");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
return efm32x_priv_write(bank, buffer, bank->base + offset, count);
|
||||||
|
}
|
||||||
|
|
||||||
static int efm32x_probe(struct flash_bank *bank)
|
static int efm32x_probe(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
struct efm32_info efm32_mcu_info;
|
struct efm32_info *efm32_mcu_info = &(efm32x_info->info);
|
||||||
int ret;
|
int ret;
|
||||||
uint32_t base_address = 0x00000000;
|
|
||||||
|
|
||||||
efm32x_info->probed = false;
|
int bank_index = efm32x_get_bank_index(bank->base);
|
||||||
memset(efm32x_info->lb_page, 0xff, LOCKBITS_PAGE_SZ);
|
assert(bank_index >= 0);
|
||||||
|
|
||||||
ret = efm32x_read_info(bank, &efm32_mcu_info);
|
efm32x_info->probed[bank_index] = false;
|
||||||
|
memset(efm32x_info->lb_page, 0xff, LOCKWORDS_SZ);
|
||||||
|
|
||||||
|
ret = efm32x_read_info(bank);
|
||||||
if (ret != ERROR_OK)
|
if (ret != ERROR_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
LOG_INFO("detected part: %s Gecko, rev %d",
|
LOG_INFO("detected part: %s Gecko, rev %d",
|
||||||
efm32_mcu_info.family_data->name, efm32_mcu_info.prod_rev);
|
efm32_mcu_info->family_data->name, efm32_mcu_info->prod_rev);
|
||||||
LOG_INFO("flash size = %dkbytes", efm32_mcu_info.flash_sz_kib);
|
LOG_INFO("flash size = %dkbytes", efm32_mcu_info->flash_sz_kib);
|
||||||
LOG_INFO("flash page size = %dbytes", efm32_mcu_info.page_size);
|
LOG_INFO("flash page size = %dbytes", efm32_mcu_info->page_size);
|
||||||
|
|
||||||
assert(efm32_mcu_info.page_size != 0);
|
assert(efm32_mcu_info->page_size != 0);
|
||||||
|
|
||||||
int num_pages = efm32_mcu_info.flash_sz_kib * 1024 /
|
|
||||||
efm32_mcu_info.page_size;
|
|
||||||
|
|
||||||
assert(num_pages > 0);
|
|
||||||
|
|
||||||
free(bank->sectors);
|
free(bank->sectors);
|
||||||
bank->sectors = NULL;
|
bank->sectors = NULL;
|
||||||
|
|
||||||
bank->base = base_address;
|
if (bank->base == EFM32_FLASH_BASE) {
|
||||||
bank->size = (num_pages * efm32_mcu_info.page_size);
|
bank->num_sectors = efm32_mcu_info->flash_sz_kib * 1024 /
|
||||||
bank->num_sectors = num_pages;
|
efm32_mcu_info->page_size;
|
||||||
|
assert(bank->num_sectors > 0);
|
||||||
|
|
||||||
ret = efm32x_read_lock_data(bank);
|
ret = efm32x_read_lock_data(bank);
|
||||||
if (ret != ERROR_OK) {
|
if (ret != ERROR_OK) {
|
||||||
LOG_ERROR("Failed to read LB data");
|
LOG_ERROR("Failed to read LB data");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
bank->num_sectors = 1;
|
||||||
|
bank->size = bank->num_sectors * efm32_mcu_info->page_size;
|
||||||
|
bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
|
||||||
|
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
|
for (uint32_t i = 0; i < bank->num_sectors; i++) {
|
||||||
|
bank->sectors[i].offset = i * efm32_mcu_info->page_size;
|
||||||
for (int i = 0; i < num_pages; i++) {
|
bank->sectors[i].size = efm32_mcu_info->page_size;
|
||||||
bank->sectors[i].offset = i * efm32_mcu_info.page_size;
|
|
||||||
bank->sectors[i].size = efm32_mcu_info.page_size;
|
|
||||||
bank->sectors[i].is_erased = -1;
|
bank->sectors[i].is_erased = -1;
|
||||||
bank->sectors[i].is_protected = 1;
|
bank->sectors[i].is_protected = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
efm32x_info->probed = true;
|
efm32x_info->probed[bank_index] = true;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int efm32x_auto_probe(struct flash_bank *bank)
|
static int efm32x_auto_probe(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
if (efm32x_info->probed)
|
|
||||||
|
int bank_index = efm32x_get_bank_index(bank->base);
|
||||||
|
assert(bank_index >= 0);
|
||||||
|
|
||||||
|
if (efm32x_info->probed[bank_index])
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
return efm32x_probe(bank);
|
return efm32x_probe(bank);
|
||||||
}
|
}
|
||||||
|
@ -1026,16 +1163,17 @@ static int efm32x_protect_check(struct flash_bank *bank)
|
||||||
|
|
||||||
static int get_efm32x_info(struct flash_bank *bank, struct command_invocation *cmd)
|
static int get_efm32x_info(struct flash_bank *bank, struct command_invocation *cmd)
|
||||||
{
|
{
|
||||||
struct efm32_info info;
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = efm32x_read_info(bank, &info);
|
ret = efm32x_read_info(bank);
|
||||||
if (ret != ERROR_OK) {
|
if (ret != ERROR_OK) {
|
||||||
LOG_ERROR("Failed to read EFM32 info");
|
LOG_ERROR("Failed to read EFM32 info");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
command_print_sameline(cmd, "%s Gecko, rev %d", info.family_data->name, info.prod_rev);
|
command_print_sameline(cmd, "%s Gecko, rev %d", efm32x_info->info.family_data->name,
|
||||||
|
efm32x_info->info.prod_rev);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1051,7 +1189,7 @@ COMMAND_HANDLER(efm32x_handle_debuglock_command)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||||
|
|
||||||
target = bank->target;
|
target = bank->target;
|
||||||
|
|
||||||
|
@ -1110,5 +1248,5 @@ const struct flash_driver efm32_flash = {
|
||||||
.erase_check = default_flash_blank_check,
|
.erase_check = default_flash_blank_check,
|
||||||
.protect_check = efm32x_protect_check,
|
.protect_check = efm32x_protect_check,
|
||||||
.info = get_efm32x_info,
|
.info = get_efm32x_info,
|
||||||
.free_driver_priv = default_flash_free_driver_priv,
|
.free_driver_priv = efm32x_free_driver_priv,
|
||||||
};
|
};
|
||||||
|
|
|
@ -302,6 +302,15 @@ void log_init(void)
|
||||||
start = last_time = timeval_ms();
|
start = last_time = timeval_ms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void log_exit(void)
|
||||||
|
{
|
||||||
|
if (log_output && log_output != stderr) {
|
||||||
|
/* Close log file, if it was open and wasn't stderr. */
|
||||||
|
fclose(log_output);
|
||||||
|
}
|
||||||
|
log_output = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int set_log_output(struct command_context *cmd_ctx, FILE *output)
|
int set_log_output(struct command_context *cmd_ctx, FILE *output)
|
||||||
{
|
{
|
||||||
log_output = output;
|
log_output = output;
|
||||||
|
|
|
@ -72,6 +72,7 @@ __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6)));
|
||||||
* Initialize logging module. Call during program startup.
|
* Initialize logging module. Call during program startup.
|
||||||
*/
|
*/
|
||||||
void log_init(void);
|
void log_init(void);
|
||||||
|
void log_exit(void);
|
||||||
int set_log_output(struct command_context *cmd_ctx, FILE *output);
|
int set_log_output(struct command_context *cmd_ctx, FILE *output);
|
||||||
|
|
||||||
int log_register_commands(struct command_context *cmd_ctx);
|
int log_register_commands(struct command_context *cmd_ctx);
|
||||||
|
|
|
@ -1273,7 +1273,7 @@ static int jtag_examine_chain(void)
|
||||||
jtag_tap_init(tap);
|
jtag_tap_init(tap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((idcode & 1) == 0) {
|
if ((idcode & 1) == 0 && !tap->ignore_bypass) {
|
||||||
/* Zero for LSB indicates a device in bypass */
|
/* Zero for LSB indicates a device in bypass */
|
||||||
LOG_INFO("TAP %s does not have valid IDCODE (idcode=0x%" PRIx32 ")",
|
LOG_INFO("TAP %s does not have valid IDCODE (idcode=0x%" PRIx32 ")",
|
||||||
tap->dotted_name, idcode);
|
tap->dotted_name, idcode);
|
||||||
|
|
|
@ -59,6 +59,7 @@ static int jim_newtap_expected_id(struct jim_nvp *n, struct jim_getopt_info *goi
|
||||||
#define NTAP_OPT_DISABLED 4
|
#define NTAP_OPT_DISABLED 4
|
||||||
#define NTAP_OPT_EXPECTED_ID 5
|
#define NTAP_OPT_EXPECTED_ID 5
|
||||||
#define NTAP_OPT_VERSION 6
|
#define NTAP_OPT_VERSION 6
|
||||||
|
#define NTAP_OPT_BYPASS 7
|
||||||
|
|
||||||
static int jim_hl_newtap_cmd(struct jim_getopt_info *goi)
|
static int jim_hl_newtap_cmd(struct jim_getopt_info *goi)
|
||||||
{
|
{
|
||||||
|
@ -75,6 +76,7 @@ static int jim_hl_newtap_cmd(struct jim_getopt_info *goi)
|
||||||
{ .name = "-disable", .value = NTAP_OPT_DISABLED },
|
{ .name = "-disable", .value = NTAP_OPT_DISABLED },
|
||||||
{ .name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID },
|
{ .name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID },
|
||||||
{ .name = "-ignore-version", .value = NTAP_OPT_VERSION },
|
{ .name = "-ignore-version", .value = NTAP_OPT_VERSION },
|
||||||
|
{ .name = "-ignore-bypass", .value = NTAP_OPT_BYPASS },
|
||||||
{ .name = NULL, .value = -1},
|
{ .name = NULL, .value = -1},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,9 @@ struct jtag_tap {
|
||||||
/** Flag saying whether to ignore version field in expected_ids[] */
|
/** Flag saying whether to ignore version field in expected_ids[] */
|
||||||
bool ignore_version;
|
bool ignore_version;
|
||||||
|
|
||||||
|
/** Flag saying whether to ignore the bypass bit in the code */
|
||||||
|
bool ignore_bypass;
|
||||||
|
|
||||||
/** current instruction */
|
/** current instruction */
|
||||||
uint8_t *cur_instr;
|
uint8_t *cur_instr;
|
||||||
/** Bypass register selected */
|
/** Bypass register selected */
|
||||||
|
|
|
@ -470,6 +470,7 @@ static int jim_newtap_expected_id(struct jim_nvp *n, struct jim_getopt_info *goi
|
||||||
#define NTAP_OPT_DISABLED 4
|
#define NTAP_OPT_DISABLED 4
|
||||||
#define NTAP_OPT_EXPECTED_ID 5
|
#define NTAP_OPT_EXPECTED_ID 5
|
||||||
#define NTAP_OPT_VERSION 6
|
#define NTAP_OPT_VERSION 6
|
||||||
|
#define NTAP_OPT_BYPASS 7
|
||||||
|
|
||||||
static int jim_newtap_ir_param(struct jim_nvp *n, struct jim_getopt_info *goi,
|
static int jim_newtap_ir_param(struct jim_nvp *n, struct jim_getopt_info *goi,
|
||||||
struct jtag_tap *tap)
|
struct jtag_tap *tap)
|
||||||
|
@ -532,6 +533,7 @@ static int jim_newtap_cmd(struct jim_getopt_info *goi)
|
||||||
{ .name = "-disable", .value = NTAP_OPT_DISABLED },
|
{ .name = "-disable", .value = NTAP_OPT_DISABLED },
|
||||||
{ .name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID },
|
{ .name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID },
|
||||||
{ .name = "-ignore-version", .value = NTAP_OPT_VERSION },
|
{ .name = "-ignore-version", .value = NTAP_OPT_VERSION },
|
||||||
|
{ .name = "-ignore-bypass", .value = NTAP_OPT_BYPASS },
|
||||||
{ .name = NULL, .value = -1 },
|
{ .name = NULL, .value = -1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -617,6 +619,9 @@ static int jim_newtap_cmd(struct jim_getopt_info *goi)
|
||||||
case NTAP_OPT_VERSION:
|
case NTAP_OPT_VERSION:
|
||||||
tap->ignore_version = true;
|
tap->ignore_version = true;
|
||||||
break;
|
break;
|
||||||
|
case NTAP_OPT_BYPASS:
|
||||||
|
tap->ignore_bypass = true;
|
||||||
|
break;
|
||||||
} /* switch (n->value) */
|
} /* switch (n->value) */
|
||||||
} /* while (goi->argc) */
|
} /* while (goi->argc) */
|
||||||
|
|
||||||
|
@ -887,6 +892,7 @@ static const struct command_registration jtag_subcommand_handlers[] = {
|
||||||
"['-enable'|'-disable'] "
|
"['-enable'|'-disable'] "
|
||||||
"['-expected_id' number] "
|
"['-expected_id' number] "
|
||||||
"['-ignore-version'] "
|
"['-ignore-version'] "
|
||||||
|
"['-ignore-bypass'] "
|
||||||
"['-ircapture' number] "
|
"['-ircapture' number] "
|
||||||
"['-mask' number]",
|
"['-mask' number]",
|
||||||
},
|
},
|
||||||
|
|
|
@ -437,6 +437,8 @@ int openocd_main(int argc, char *argv[])
|
||||||
rtt_exit();
|
rtt_exit();
|
||||||
free_config();
|
free_config();
|
||||||
|
|
||||||
|
log_exit();
|
||||||
|
|
||||||
if (ret == ERROR_FAIL)
|
if (ret == ERROR_FAIL)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
else if (ret != ERROR_OK)
|
else if (ret != ERROR_OK)
|
||||||
|
|
|
@ -2635,8 +2635,10 @@ static int aarch64_examine_first(struct target *target)
|
||||||
LOG_DEBUG("ttypr = 0x%08" PRIx64, ttypr);
|
LOG_DEBUG("ttypr = 0x%08" PRIx64, ttypr);
|
||||||
LOG_DEBUG("debug = 0x%08" PRIx64, debug);
|
LOG_DEBUG("debug = 0x%08" PRIx64, debug);
|
||||||
|
|
||||||
if (!pc->cti)
|
if (!pc->cti) {
|
||||||
|
LOG_TARGET_ERROR(target, "CTI not specified");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
armv8->cti = pc->cti;
|
armv8->cti = pc->cti;
|
||||||
|
|
||||||
|
|
|
@ -1843,7 +1843,7 @@ int target_call_event_callbacks(struct target *target, enum target_event event)
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("target event %i (%s) for core %s", event,
|
LOG_DEBUG("target event %i (%s) for core %s", event,
|
||||||
jim_nvp_value2name_simple(nvp_target_event, event)->name,
|
target_event_name(event),
|
||||||
target_name(target));
|
target_name(target));
|
||||||
|
|
||||||
target_handle_event(target, event);
|
target_handle_event(target, event);
|
||||||
|
@ -4821,7 +4821,7 @@ void target_handle_event(struct target *target, enum target_event e)
|
||||||
target_name(target),
|
target_name(target),
|
||||||
target_type_name(target),
|
target_type_name(target),
|
||||||
e,
|
e,
|
||||||
jim_nvp_value2name_simple(nvp_target_event, e)->name,
|
target_event_name(e),
|
||||||
Jim_GetString(teap->body, NULL));
|
Jim_GetString(teap->body, NULL));
|
||||||
|
|
||||||
/* Override current target by the target an event
|
/* Override current target by the target an event
|
||||||
|
@ -4845,7 +4845,7 @@ void target_handle_event(struct target *target, enum target_event e)
|
||||||
if (retval != JIM_OK) {
|
if (retval != JIM_OK) {
|
||||||
Jim_MakeErrorMessage(teap->interp);
|
Jim_MakeErrorMessage(teap->interp);
|
||||||
LOG_USER("Error executing event %s on target %s:\n%s",
|
LOG_USER("Error executing event %s on target %s:\n%s",
|
||||||
jim_nvp_value2name_simple(nvp_target_event, e)->name,
|
target_event_name(e),
|
||||||
target_name(target),
|
target_name(target),
|
||||||
Jim_GetString(Jim_GetResult(teap->interp), NULL));
|
Jim_GetString(Jim_GetResult(teap->interp), NULL));
|
||||||
/* clean both error code and stacktrace before return */
|
/* clean both error code and stacktrace before return */
|
||||||
|
@ -5508,9 +5508,9 @@ COMMAND_HANDLER(handle_target_event_list)
|
||||||
command_print(CMD, "------------------------- | "
|
command_print(CMD, "------------------------- | "
|
||||||
"----------------------------------------");
|
"----------------------------------------");
|
||||||
while (teap) {
|
while (teap) {
|
||||||
struct jim_nvp *opt = jim_nvp_value2name_simple(nvp_target_event, teap->event);
|
|
||||||
command_print(CMD, "%-25s | %s",
|
command_print(CMD, "%-25s | %s",
|
||||||
opt->name, Jim_GetString(teap->body, NULL));
|
target_event_name(teap->event),
|
||||||
|
Jim_GetString(teap->body, NULL));
|
||||||
teap = teap->next;
|
teap = teap->next;
|
||||||
}
|
}
|
||||||
command_print(CMD, "***END***");
|
command_print(CMD, "***END***");
|
||||||
|
|
|
@ -43,6 +43,8 @@ $_TARGETNAME configure -work-area-phys 0x10000000 -work-area-size $_WORKAREASIZE
|
||||||
|
|
||||||
set _FLASHNAME $_CHIPNAME.flash
|
set _FLASHNAME $_CHIPNAME.flash
|
||||||
flash bank $_FLASHNAME efm32 0 0 0 0 $_TARGETNAME
|
flash bank $_FLASHNAME efm32 0 0 0 0 $_TARGETNAME
|
||||||
|
flash bank userdata.flash efm32 0x0FE00000 0 0 0 $_TARGETNAME
|
||||||
|
flash bank lockbits.flash efm32 0x0FE04000 0 0 0 $_TARGETNAME
|
||||||
|
|
||||||
if {![using_hla]} {
|
if {![using_hla]} {
|
||||||
# if srst is not fitted use SYSRESETREQ to
|
# if srst is not fitted use SYSRESETREQ to
|
||||||
|
|
Loading…
Reference in New Issue