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`
|
||||
|
||||
LINE 2 & 3
|
||||
set $vn [expr (1024 * $x)]
|
||||
set $vn [expr {1024 * $x}]
|
||||
global $vn
|
||||
|
||||
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]
|
||||
|
||||
arm mcr 15 [expr ($regs>>12)&0x7] \
|
||||
[expr ($regs>>0)&0xf] [expr ($regs>>4)&0xf] \
|
||||
[expr ($regs>>8)&0x7] $value
|
||||
arm mcr 15 [expr @{($regs >> 12) & 0x7@}] \
|
||||
[expr @{($regs >> 0) & 0xf@}] [expr @{($regs >> 4) & 0xf@}] \
|
||||
[expr @{($regs >> 8) & 0x7@}] $value
|
||||
@}
|
||||
@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)
|
||||
@example
|
||||
> 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
|
||||
@end example
|
||||
@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
|
||||
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.
|
||||
@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}
|
||||
@*The bit pattern loaded by the TAP into the JTAG shift register
|
||||
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
|
||||
DCache on Cortex-M7.
|
||||
@example
|
||||
set CSW_HPROT3_CACHEABLE [expr 1 << 27]
|
||||
set CSW_HPROT3_CACHEABLE [expr @{1 << 27@}]
|
||||
samv.dap apcsw $CSW_HPROT3_CACHEABLE $CSW_HPROT3_CACHEABLE
|
||||
@end example
|
||||
|
||||
Another example clears SPROT bit and leaves the rest of pattern intact:
|
||||
@example
|
||||
set CSW_SPROT [expr 1 << 30]
|
||||
set CSW_SPROT [expr @{1 << 30@}]
|
||||
samv.dap apcsw 0 $CSW_SPROT
|
||||
@end example
|
||||
|
||||
|
@ -6351,13 +6357,22 @@ flash bank $_FLASHNAME cc3220sf 0 0 0 0 $_TARGETNAME
|
|||
@end deffn
|
||||
|
||||
@deffn {Flash Driver} {efm32}
|
||||
All members of the EFM32 microcontroller family from Energy Micro include
|
||||
internal flash and use ARM Cortex-M3 cores. The driver automatically recognizes
|
||||
a number of these chips using the chip identification register, and
|
||||
All members of the EFM32/EFR32 microcontroller family from Energy Micro (now Silicon Labs)
|
||||
include internal flash and use Arm Cortex-M3 or Cortex-M4 cores. The driver automatically
|
||||
recognizes a number of these chips using the chip identification register, and
|
||||
autoconfigures itself.
|
||||
@example
|
||||
flash bank $_FLASHNAME efm32 0 0 0 0 $_TARGETNAME
|
||||
@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
|
||||
debug interface by writing the correct values to the 'Debug Lock Word'. OpenOCD supports
|
||||
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 @} @{
|
||||
# Load data from fname filename at foffset offset to
|
||||
# target at address. Load at most length bytes.
|
||||
load_image $fname [expr $address - $foffset] bin \
|
||||
load_image $fname [expr @{$address - $foffset@}] bin \
|
||||
$address $length
|
||||
@}
|
||||
@end example
|
||||
|
@ -10431,7 +10446,7 @@ trivial challenge-response protocol could be implemented as follows in a
|
|||
configuration file, immediately following @command{init}:
|
||||
@example
|
||||
set challenge [riscv authdata_read]
|
||||
riscv authdata_write [expr $challenge + 1]
|
||||
riscv authdata_write [expr @{$challenge + 1@}]
|
||||
@end example
|
||||
|
||||
@deffn {Command} {riscv authdata_read} [index=0]
|
||||
|
@ -12142,7 +12157,7 @@ it reads a file and executes as a script.
|
|||
@example
|
||||
set x 6
|
||||
set y 7
|
||||
puts [format "The answer: %d" [expr $x * $y]]
|
||||
puts [format "The answer: %d" [expr @{$x * $y@}]]
|
||||
@end example
|
||||
@enumerate
|
||||
@item The SET command creates 2 variables, X and Y.
|
||||
|
@ -12213,13 +12228,13 @@ proc myproc @{ @} @{
|
|||
@b{Dynamic variable creation}
|
||||
@example
|
||||
# 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
|
||||
set vn [format "BIT%d" $x]
|
||||
# Make it a global
|
||||
global $vn
|
||||
# Set it.
|
||||
set $vn [expr (1 << $x)]
|
||||
set $vn [expr @{1 << $x@}]
|
||||
@}
|
||||
@end example
|
||||
@b{Dynamic proc/command creation}
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
* Copyright (C) 2014 Nemui Trinomius *
|
||||
* 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 *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
|
@ -45,13 +48,16 @@
|
|||
#define EFM32_FLASH_WDATAREADY_TMO 100
|
||||
#define EFM32_FLASH_WRITE_TMO 100
|
||||
|
||||
#define EFM32_FLASH_BASE 0
|
||||
|
||||
/* 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_USER_DATA EFM32_MSC_INFO_BASE
|
||||
#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)
|
||||
|
||||
/* 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_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 {
|
||||
int family_id;
|
||||
const char *name;
|
||||
|
@ -98,13 +125,6 @@ struct efm32_family_data {
|
|||
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 {
|
||||
const struct efm32_family_data *family_data;
|
||||
uint16_t flash_sz_kib;
|
||||
|
@ -115,6 +135,15 @@ struct efm32_info {
|
|||
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[] = {
|
||||
{ 16, "EFR32MG1P 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 },
|
||||
};
|
||||
|
||||
const struct flash_driver efm32_flash;
|
||||
|
||||
static int efm32x_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||
uint32_t offset, uint32_t count);
|
||||
static int efm32x_priv_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||
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)
|
||||
{
|
||||
|
@ -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,
|
||||
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;
|
||||
|
||||
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,
|
||||
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;
|
||||
|
||||
return target_write_u32(bank->target, base + offset, value);
|
||||
}
|
||||
|
||||
static int efm32x_read_info(struct flash_bank *bank,
|
||||
struct efm32_info *efm32_info)
|
||||
static int efm32x_read_info(struct flash_bank *bank)
|
||||
{
|
||||
int ret;
|
||||
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));
|
||||
|
||||
|
@ -327,20 +359,61 @@ static int efm32x_read_info(struct flash_bank *bank,
|
|||
/* flash bank efm32 <base> <size> 0 0 <target#> */
|
||||
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)
|
||||
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;
|
||||
efm32x_info->probed = false;
|
||||
memset(efm32x_info->lb_page, 0xff, LOCKBITS_PAGE_SZ);
|
||||
|
||||
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 */
|
||||
static int efm32x_set_reg_bits(struct flash_bank *bank, uint32_t reg,
|
||||
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)
|
||||
{
|
||||
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,
|
||||
(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;
|
||||
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);
|
||||
|
@ -470,20 +542,28 @@ static int efm32x_erase(struct flash_bank *bank, unsigned int first,
|
|||
}
|
||||
|
||||
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)
|
||||
LOG_ERROR("Failed to erase page %d", i);
|
||||
}
|
||||
|
||||
ret = efm32x_set_wren(bank, 0);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
int data_size = 0;
|
||||
uint32_t *ptr = NULL;
|
||||
|
@ -557,35 +637,84 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
|
|||
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)
|
||||
{
|
||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
||||
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||
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);
|
||||
if (ret != ERROR_OK) {
|
||||
LOG_ERROR("Failed to erase LB page");
|
||||
if (extra_data)
|
||||
free(extra_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return efm32x_write(bank, (uint8_t *)efm32x_info->lb_page, EFM32_MSC_LOCK_BITS,
|
||||
LOCKBITS_PAGE_SZ);
|
||||
if (extra_data) {
|
||||
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)
|
||||
{
|
||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
||||
uint32_t dw = efm32x_info->lb_page[page >> 5];
|
||||
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||
uint32_t dw = 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;
|
||||
}
|
||||
|
||||
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 mask = 0;
|
||||
|
||||
|
@ -605,11 +734,6 @@ static int efm32x_protect(struct flash_bank *bank, int set, unsigned int first,
|
|||
struct target *target = bank->target;
|
||||
int ret = 0;
|
||||
|
||||
if (!set) {
|
||||
LOG_ERROR("Erase device data to reset page locks");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_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,
|
||||
uint32_t offset, uint32_t count)
|
||||
uint32_t address, uint32_t count)
|
||||
{
|
||||
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;
|
||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
||||
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||
int ret = ERROR_OK;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
static int efm32x_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||
uint32_t offset, uint32_t count)
|
||||
static int efm32x_priv_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||
uint32_t addr, uint32_t count)
|
||||
{
|
||||
struct target *target = bank->target;
|
||||
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;
|
||||
}
|
||||
|
||||
if (offset & 0x3) {
|
||||
LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte "
|
||||
"alignment", offset);
|
||||
if (addr & 0x3) {
|
||||
LOG_ERROR("addr 0x%" PRIx32 " breaks required 4-byte "
|
||||
"alignment", addr);
|
||||
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
|
||||
}
|
||||
|
||||
|
@ -906,7 +1029,7 @@ static int efm32x_write(struct flash_bank *bank, const uint8_t *buffer,
|
|||
goto cleanup;
|
||||
|
||||
/* 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 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;
|
||||
memcpy(&value, buffer, sizeof(uint32_t));
|
||||
|
||||
retval = efm32x_write_word(bank, offset, value);
|
||||
retval = efm32x_write_word(bank, addr, value);
|
||||
if (retval != ERROR_OK)
|
||||
goto reset_pg_and_lock;
|
||||
|
||||
words_remaining--;
|
||||
buffer += 4;
|
||||
offset += 4;
|
||||
addr += 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -939,63 +1062,77 @@ cleanup:
|
|||
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)
|
||||
{
|
||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
||||
struct efm32_info efm32_mcu_info;
|
||||
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||
struct efm32_info *efm32_mcu_info = &(efm32x_info->info);
|
||||
int ret;
|
||||
uint32_t base_address = 0x00000000;
|
||||
|
||||
efm32x_info->probed = false;
|
||||
memset(efm32x_info->lb_page, 0xff, LOCKBITS_PAGE_SZ);
|
||||
int bank_index = efm32x_get_bank_index(bank->base);
|
||||
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)
|
||||
return ret;
|
||||
|
||||
LOG_INFO("detected part: %s Gecko, rev %d",
|
||||
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 page size = %dbytes", efm32_mcu_info.page_size);
|
||||
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 page size = %dbytes", efm32_mcu_info->page_size);
|
||||
|
||||
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);
|
||||
assert(efm32_mcu_info->page_size != 0);
|
||||
|
||||
free(bank->sectors);
|
||||
bank->sectors = NULL;
|
||||
|
||||
bank->base = base_address;
|
||||
bank->size = (num_pages * efm32_mcu_info.page_size);
|
||||
bank->num_sectors = num_pages;
|
||||
if (bank->base == EFM32_FLASH_BASE) {
|
||||
bank->num_sectors = efm32_mcu_info->flash_sz_kib * 1024 /
|
||||
efm32_mcu_info->page_size;
|
||||
assert(bank->num_sectors > 0);
|
||||
|
||||
ret = efm32x_read_lock_data(bank);
|
||||
if (ret != ERROR_OK) {
|
||||
LOG_ERROR("Failed to read LB data");
|
||||
return ret;
|
||||
}
|
||||
ret = efm32x_read_lock_data(bank);
|
||||
if (ret != ERROR_OK) {
|
||||
LOG_ERROR("Failed to read LB data");
|
||||
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 (int i = 0; i < num_pages; i++) {
|
||||
bank->sectors[i].offset = i * efm32_mcu_info.page_size;
|
||||
bank->sectors[i].size = efm32_mcu_info.page_size;
|
||||
for (uint32_t i = 0; i < bank->num_sectors; i++) {
|
||||
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_protected = 1;
|
||||
}
|
||||
|
||||
efm32x_info->probed = true;
|
||||
efm32x_info->probed[bank_index] = true;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int efm32x_auto_probe(struct flash_bank *bank)
|
||||
{
|
||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
||||
if (efm32x_info->probed)
|
||||
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||
|
||||
int bank_index = efm32x_get_bank_index(bank->base);
|
||||
assert(bank_index >= 0);
|
||||
|
||||
if (efm32x_info->probed[bank_index])
|
||||
return ERROR_OK;
|
||||
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)
|
||||
{
|
||||
struct efm32_info info;
|
||||
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||
int ret;
|
||||
|
||||
ret = efm32x_read_info(bank, &info);
|
||||
ret = efm32x_read_info(bank);
|
||||
if (ret != ERROR_OK) {
|
||||
LOG_ERROR("Failed to read EFM32 info");
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1051,7 +1189,7 @@ COMMAND_HANDLER(efm32x_handle_debuglock_command)
|
|||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
|
||||
struct efm32x_flash_chip *efm32x_info = bank->driver_priv;
|
||||
|
||||
target = bank->target;
|
||||
|
||||
|
@ -1110,5 +1248,5 @@ const struct flash_driver efm32_flash = {
|
|||
.erase_check = default_flash_blank_check,
|
||||
.protect_check = efm32x_protect_check,
|
||||
.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();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
log_output = output;
|
||||
|
|
|
@ -72,6 +72,7 @@ __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6)));
|
|||
* Initialize logging module. Call during program startup.
|
||||
*/
|
||||
void log_init(void);
|
||||
void log_exit(void);
|
||||
int set_log_output(struct command_context *cmd_ctx, FILE *output);
|
||||
|
||||
int log_register_commands(struct command_context *cmd_ctx);
|
||||
|
|
|
@ -1273,7 +1273,7 @@ static int jtag_examine_chain(void)
|
|||
jtag_tap_init(tap);
|
||||
}
|
||||
|
||||
if ((idcode & 1) == 0) {
|
||||
if ((idcode & 1) == 0 && !tap->ignore_bypass) {
|
||||
/* Zero for LSB indicates a device in bypass */
|
||||
LOG_INFO("TAP %s does not have valid IDCODE (idcode=0x%" PRIx32 ")",
|
||||
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_EXPECTED_ID 5
|
||||
#define NTAP_OPT_VERSION 6
|
||||
#define NTAP_OPT_BYPASS 7
|
||||
|
||||
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 = "-expected-id", .value = NTAP_OPT_EXPECTED_ID },
|
||||
{ .name = "-ignore-version", .value = NTAP_OPT_VERSION },
|
||||
{ .name = "-ignore-bypass", .value = NTAP_OPT_BYPASS },
|
||||
{ .name = NULL, .value = -1},
|
||||
};
|
||||
|
||||
|
|
|
@ -135,6 +135,9 @@ struct jtag_tap {
|
|||
/** Flag saying whether to ignore version field in expected_ids[] */
|
||||
bool ignore_version;
|
||||
|
||||
/** Flag saying whether to ignore the bypass bit in the code */
|
||||
bool ignore_bypass;
|
||||
|
||||
/** current instruction */
|
||||
uint8_t *cur_instr;
|
||||
/** 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_EXPECTED_ID 5
|
||||
#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,
|
||||
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 = "-expected-id", .value = NTAP_OPT_EXPECTED_ID },
|
||||
{ .name = "-ignore-version", .value = NTAP_OPT_VERSION },
|
||||
{ .name = "-ignore-bypass", .value = NTAP_OPT_BYPASS },
|
||||
{ .name = NULL, .value = -1 },
|
||||
};
|
||||
|
||||
|
@ -617,6 +619,9 @@ static int jim_newtap_cmd(struct jim_getopt_info *goi)
|
|||
case NTAP_OPT_VERSION:
|
||||
tap->ignore_version = true;
|
||||
break;
|
||||
case NTAP_OPT_BYPASS:
|
||||
tap->ignore_bypass = true;
|
||||
break;
|
||||
} /* switch (n->value) */
|
||||
} /* while (goi->argc) */
|
||||
|
||||
|
@ -887,6 +892,7 @@ static const struct command_registration jtag_subcommand_handlers[] = {
|
|||
"['-enable'|'-disable'] "
|
||||
"['-expected_id' number] "
|
||||
"['-ignore-version'] "
|
||||
"['-ignore-bypass'] "
|
||||
"['-ircapture' number] "
|
||||
"['-mask' number]",
|
||||
},
|
||||
|
|
|
@ -437,6 +437,8 @@ int openocd_main(int argc, char *argv[])
|
|||
rtt_exit();
|
||||
free_config();
|
||||
|
||||
log_exit();
|
||||
|
||||
if (ret == ERROR_FAIL)
|
||||
return EXIT_FAILURE;
|
||||
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("debug = 0x%08" PRIx64, debug);
|
||||
|
||||
if (!pc->cti)
|
||||
if (!pc->cti) {
|
||||
LOG_TARGET_ERROR(target, "CTI not specified");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
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,
|
||||
jim_nvp_value2name_simple(nvp_target_event, event)->name,
|
||||
target_event_name(event),
|
||||
target_name(target));
|
||||
|
||||
target_handle_event(target, event);
|
||||
|
@ -4821,7 +4821,7 @@ void target_handle_event(struct target *target, enum target_event e)
|
|||
target_name(target),
|
||||
target_type_name(target),
|
||||
e,
|
||||
jim_nvp_value2name_simple(nvp_target_event, e)->name,
|
||||
target_event_name(e),
|
||||
Jim_GetString(teap->body, NULL));
|
||||
|
||||
/* 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) {
|
||||
Jim_MakeErrorMessage(teap->interp);
|
||||
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),
|
||||
Jim_GetString(Jim_GetResult(teap->interp), NULL));
|
||||
/* clean both error code and stacktrace before return */
|
||||
|
@ -5508,9 +5508,9 @@ COMMAND_HANDLER(handle_target_event_list)
|
|||
command_print(CMD, "------------------------- | "
|
||||
"----------------------------------------");
|
||||
while (teap) {
|
||||
struct jim_nvp *opt = jim_nvp_value2name_simple(nvp_target_event, teap->event);
|
||||
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;
|
||||
}
|
||||
command_print(CMD, "***END***");
|
||||
|
|
|
@ -43,6 +43,8 @@ $_TARGETNAME configure -work-area-phys 0x10000000 -work-area-size $_WORKAREASIZE
|
|||
|
||||
set _FLASHNAME $_CHIPNAME.flash
|
||||
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 srst is not fitted use SYSRESETREQ to
|
||||
|
|
Loading…
Reference in New Issue