Merge pull request #119 from gnu-mcu-eclipse/riscv-upd
Update to master (Aug 10, 2017)
This commit is contained in:
commit
12bb3a4fd4
|
@ -6,7 +6,7 @@ ARM_OBJCOPY ?= $(ARM_CROSS_COMPILE)objcopy
|
||||||
|
|
||||||
ARM_AFLAGS = -EL -mthumb
|
ARM_AFLAGS = -EL -mthumb
|
||||||
|
|
||||||
arm: armv7m_kinetis_wdog.inc
|
arm: armv7m_kinetis_wdog.inc armv7m_kinetis_wdog32.inc
|
||||||
|
|
||||||
armv7m_%.elf: armv7m_%.s
|
armv7m_%.elf: armv7m_%.s
|
||||||
$(ARM_AS) $(ARM_AFLAGS) $< -o $@
|
$(ARM_AS) $(ARM_AFLAGS) $< -o $@
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/* Autogenerated with ../../../src/helper/bin2char.sh */
|
/* Autogenerated with ../../../src/helper/bin2char.sh */
|
||||||
0x04,0x4b,0x05,0x4a,0xda,0x81,0x05,0x4a,0xda,0x81,0x01,0x24,0x1a,0x88,0xa2,0x43,
|
0x04,0x4a,0xc2,0x81,0x04,0x4a,0xc2,0x81,0x01,0x24,0x02,0x88,0xa2,0x43,0x02,0x80,
|
||||||
0x1a,0x80,0x06,0xe0,0x00,0x20,0x05,0x40,0x20,0xc5,0x00,0x00,0x28,0xd9,0x00,0x00,
|
0x05,0xe0,0x00,0x00,0x20,0xc5,0x00,0x00,0x28,0xd9,0x00,0x00,0x00,0x00,0x00,0xbe,
|
||||||
0x00,0x00,0x00,0xbe,
|
|
||||||
|
|
|
@ -19,7 +19,9 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Disable watchdog for Kinetis Kx and KVx
|
Disable watchdog for Kinetis Kx and KVx
|
||||||
Parameters: none
|
Parameters:
|
||||||
|
r0 ... WDOG base (in)
|
||||||
|
|
||||||
Used instruction set should work on both Cortex-M4 and M0+
|
Used instruction set should work on both Cortex-M4 and M0+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -28,7 +30,6 @@
|
||||||
.cpu cortex-m0
|
.cpu cortex-m0
|
||||||
.thumb
|
.thumb
|
||||||
|
|
||||||
WDOG_ADDR = 0x40052000
|
|
||||||
/* WDOG registers offsets */
|
/* WDOG registers offsets */
|
||||||
WDOG_STCTRLH = 0
|
WDOG_STCTRLH = 0
|
||||||
WDOG_UNLOCK = 0x0e
|
WDOG_UNLOCK = 0x0e
|
||||||
|
@ -39,17 +40,16 @@ WDOG_KEY2 = 0xd928
|
||||||
.thumb_func
|
.thumb_func
|
||||||
start:
|
start:
|
||||||
/* WDOG_UNLOCK = 0xC520 */
|
/* WDOG_UNLOCK = 0xC520 */
|
||||||
ldr r3, =WDOG_ADDR
|
|
||||||
ldr r2, =WDOG_KEY1
|
ldr r2, =WDOG_KEY1
|
||||||
strh r2, [r3, WDOG_UNLOCK]
|
strh r2, [r0, WDOG_UNLOCK]
|
||||||
/* WDOG_UNLOCK = 0xD928 */
|
/* WDOG_UNLOCK = 0xD928 */
|
||||||
ldr r2, =WDOG_KEY2
|
ldr r2, =WDOG_KEY2
|
||||||
strh r2, [r3, WDOG_UNLOCK]
|
strh r2, [r0, WDOG_UNLOCK]
|
||||||
/* WDOG_STCTRLH clear bit 0 */
|
/* WDOG_STCTRLH clear bit 0 */
|
||||||
movs r4, #1
|
movs r4, #1
|
||||||
ldrh r2, [r3, WDOG_STCTRLH]
|
ldrh r2, [r0, WDOG_STCTRLH]
|
||||||
bics r2, r4
|
bics r2, r4
|
||||||
strh r2, [r3, WDOG_STCTRLH]
|
strh r2, [r0, WDOG_STCTRLH]
|
||||||
/* OpenOCD checks exit point address. Jump to the very end. */
|
/* OpenOCD checks exit point address. Jump to the very end. */
|
||||||
b done
|
b done
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
/* Autogenerated with ../../../src/helper/bin2char.sh */
|
||||||
|
0x02,0x68,0x08,0x4b,0x1a,0x42,0x08,0x4b,0x01,0xd0,0x43,0x60,0x02,0xe0,0x83,0x80,
|
||||||
|
0x1b,0x0c,0x83,0x80,0x80,0x24,0xa2,0x43,0x20,0x24,0x22,0x43,0x02,0x60,0x03,0x4b,
|
||||||
|
0x83,0x60,0x06,0xe0,0x00,0x20,0x00,0x00,0x20,0xc5,0x28,0xd9,0x00,0x04,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0xbe,
|
|
@ -0,0 +1,81 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2017 Tomas Vanek *
|
||||||
|
* vanekt@fbl.cz *
|
||||||
|
* *
|
||||||
|
* 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, write to the *
|
||||||
|
* Free Software Foundation, Inc. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Disable watchdog, 32-bit version for newer Kinetis
|
||||||
|
Parameters:
|
||||||
|
r0 ... WDOG32 base (in)
|
||||||
|
|
||||||
|
Used instruction set should work on both Cortex-M4 and M0+
|
||||||
|
*/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.syntax unified
|
||||||
|
.cpu cortex-m0
|
||||||
|
.thumb
|
||||||
|
|
||||||
|
/* WDOG registers offsets */
|
||||||
|
WDOG_CS = 0
|
||||||
|
WDOG_CNT = 4
|
||||||
|
WDOG_TOVAL = 8
|
||||||
|
|
||||||
|
WDOG_KEY = 0xd928c520
|
||||||
|
|
||||||
|
.thumb_func
|
||||||
|
start:
|
||||||
|
/* test WDOG_CS bit CMD32EN */
|
||||||
|
ldr r2, [r0, WDOG_CS]
|
||||||
|
ldr r3, =0x2000
|
||||||
|
tst r2, r3
|
||||||
|
ldr r3, =WDOG_KEY
|
||||||
|
beq cmd16
|
||||||
|
|
||||||
|
/* WDOG_CNT = key */
|
||||||
|
str r3, [r0, WDOG_CNT]
|
||||||
|
b unlocked
|
||||||
|
|
||||||
|
cmd16:
|
||||||
|
/* WDOG_CNT = key, halfword by halfword */
|
||||||
|
strh r3, [r0, WDOG_CNT]
|
||||||
|
lsrs r3, r3, #16
|
||||||
|
strh r3, [r0, WDOG_CNT]
|
||||||
|
|
||||||
|
/* WDOG_CS: clear EN bit 7, set UPDATE bit 5 */
|
||||||
|
unlocked:
|
||||||
|
movs r4, #0x80
|
||||||
|
bics r2, r4
|
||||||
|
movs r4, #0x20
|
||||||
|
orrs r2, r4
|
||||||
|
str r2, [r0, WDOG_CS]
|
||||||
|
/* All active WDOG registers have to be updated, set dummy timeout */
|
||||||
|
/* WDOG_TOVAL = 0x400 */
|
||||||
|
ldr r3, =0x400
|
||||||
|
str r3, [r0, WDOG_TOVAL]
|
||||||
|
/* OpenOCD checks exit point address. Jump to the very end. */
|
||||||
|
b done
|
||||||
|
|
||||||
|
.pool
|
||||||
|
|
||||||
|
/* Avoid padding at .text segment end. Otherwise exit point check fails. */
|
||||||
|
.skip ( . - start + 2) & 2, 0
|
||||||
|
done:
|
||||||
|
bkpt #0
|
||||||
|
|
||||||
|
.end
|
||||||
|
|
|
@ -682,7 +682,8 @@ bash$ openocd --help
|
||||||
--version | -v display OpenOCD version
|
--version | -v display OpenOCD version
|
||||||
--file | -f use configuration file <name>
|
--file | -f use configuration file <name>
|
||||||
--search | -s dir to search for config files and scripts
|
--search | -s dir to search for config files and scripts
|
||||||
--debug | -d set debug level <0-3>
|
--debug | -d set debug level to 3
|
||||||
|
| -d<n> set debug level to <level>
|
||||||
--log_output | -l redirect log output to file <name>
|
--log_output | -l redirect log output to file <name>
|
||||||
--command | -c run <command>
|
--command | -c run <command>
|
||||||
@end verbatim
|
@end verbatim
|
||||||
|
@ -4715,15 +4716,18 @@ each block, and the specified length must stay within that bank.
|
||||||
@end deffn
|
@end deffn
|
||||||
@comment no current checks for errors if fill blocks touch multiple banks!
|
@comment no current checks for errors if fill blocks touch multiple banks!
|
||||||
|
|
||||||
@deffn Command {flash write_bank} num filename offset
|
@deffn Command {flash write_bank} num filename [offset]
|
||||||
Write the binary @file{filename} to flash bank @var{num},
|
Write the binary @file{filename} to flash bank @var{num},
|
||||||
starting at @var{offset} bytes from the beginning of the bank.
|
starting at @var{offset} bytes from the beginning of the bank. If @var{offset}
|
||||||
|
is omitted, start at the beginning of the flash bank.
|
||||||
The @var{num} parameter is a value shown by @command{flash banks}.
|
The @var{num} parameter is a value shown by @command{flash banks}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn Command {flash read_bank} num filename offset length
|
@deffn Command {flash read_bank} num filename [offset [length]]
|
||||||
Read @var{length} bytes from the flash bank @var{num} starting at @var{offset}
|
Read @var{length} bytes from the flash bank @var{num} starting at @var{offset}
|
||||||
and write the contents to the binary @file{filename}.
|
and write the contents to the binary @file{filename}. If @var{offset} is
|
||||||
|
omitted, start at the beginning of the flash bank. If @var{length} is omitted,
|
||||||
|
read the remaining bytes from the flash bank.
|
||||||
The @var{num} parameter is a value shown by @command{flash banks}.
|
The @var{num} parameter is a value shown by @command{flash banks}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@ -5361,15 +5365,28 @@ nor is Chip Erase (only Sector Erase is implemented).}
|
||||||
|
|
||||||
@deffn {Flash Driver} kinetis
|
@deffn {Flash Driver} kinetis
|
||||||
@cindex kinetis
|
@cindex kinetis
|
||||||
Kx and KLx members of the Kinetis microcontroller family from Freescale include
|
Kx, KLx, KVx and KE1x members of the Kinetis microcontroller family
|
||||||
|
from NXP (former Freescale) include
|
||||||
internal flash and use ARM Cortex-M0+ or M4 cores. The driver automatically
|
internal flash and use ARM Cortex-M0+ or M4 cores. The driver automatically
|
||||||
recognizes flash size and a number of flash banks (1-4) using the chip
|
recognizes flash size and a number of flash banks (1-4) using the chip
|
||||||
identification register, and autoconfigures itself.
|
identification register, and autoconfigures itself.
|
||||||
|
Use kinetis_ke driver for KE0x devices.
|
||||||
|
|
||||||
|
The @var{kinetis} driver defines option:
|
||||||
|
@itemize
|
||||||
|
@item -sim-base @var{addr} ... base of System Integration Module where chip identification resides. Driver tries two known locations if option is omitted.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
@example
|
@example
|
||||||
flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME
|
flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
@deffn Command {kinetis create_banks}
|
||||||
|
Configuration command enables automatic creation of additional flash banks
|
||||||
|
based on real flash layout of device. Banks are created during device probe.
|
||||||
|
Use 'flash probe 0' to force probe.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
@deffn Command {kinetis fcf_source} [protection|write]
|
@deffn Command {kinetis fcf_source} [protection|write]
|
||||||
Select what source is used when writing to a Flash Configuration Field.
|
Select what source is used when writing to a Flash Configuration Field.
|
||||||
@option{protection} mode builds FCF content from protection bits previously
|
@option{protection} mode builds FCF content from protection bits previously
|
||||||
|
@ -5446,10 +5463,11 @@ Command disables watchdog timer.
|
||||||
|
|
||||||
@deffn {Flash Driver} kinetis_ke
|
@deffn {Flash Driver} kinetis_ke
|
||||||
@cindex kinetis_ke
|
@cindex kinetis_ke
|
||||||
KE members of the Kinetis microcontroller family from Freescale include
|
KE0x members of the Kinetis microcontroller family from Freescale include
|
||||||
internal flash and use ARM Cortex-M0+. The driver automatically recognizes
|
internal flash and use ARM Cortex-M0+. The driver automatically recognizes
|
||||||
the KE family and sub-family using the chip identification register, and
|
the KE0x sub-family using the chip identification register, and
|
||||||
autoconfigures itself.
|
autoconfigures itself.
|
||||||
|
Use kinetis (not kinetis_ke) driver for KE1x devices.
|
||||||
|
|
||||||
@example
|
@example
|
||||||
flash bank $_FLASHNAME kinetis_ke 0 0 0 0 $_TARGETNAME
|
flash bank $_FLASHNAME kinetis_ke 0 0 0 0 $_TARGETNAME
|
||||||
|
@ -5971,16 +5989,21 @@ The @var{num} parameter is a value shown by @command{flash banks}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn Command {stm32f2x options_read} num
|
@deffn Command {stm32f2x options_read} num
|
||||||
Reads and displays user options and (where implemented) boot_addr0 and boot_addr1.
|
Reads and displays user options and (where implemented) boot_addr0, boot_addr1, optcr2.
|
||||||
The @var{num} parameter is a value shown by @command{flash banks}.
|
The @var{num} parameter is a value shown by @command{flash banks}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn Command {stm32f2x options_write} num user_options boot_addr0 boot_addr1
|
@deffn Command {stm32f2x options_write} num user_options boot_addr0 boot_addr1
|
||||||
Writes user options and (where implemented) boot_addr0 and boot_addr1 in raw format.
|
Writes user options and (where implemented) boot_addr0 and boot_addr1 in raw format.
|
||||||
Warning: The meaning of the various bits depends on the device, always check datasheet!
|
Warning: The meaning of the various bits depends on the device, always check datasheet!
|
||||||
The @var{num} parameter is a value shown by @command{flash banks}, user_options a
|
The @var{num} parameter is a value shown by @command{flash banks}, @var{user_options} a
|
||||||
12 bit value, consisting of bits 31-28 and 7-0 of FLASH_OPTCR, boot_addr0 and boot_addr1
|
12 bit value, consisting of bits 31-28 and 7-0 of FLASH_OPTCR, @var{boot_addr0} and
|
||||||
two halfwords (of FLASH_OPTCR1).
|
@var{boot_addr1} two halfwords (of FLASH_OPTCR1).
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn Command {stm32f2x optcr2_write} num optcr2
|
||||||
|
Writes FLASH_OPTCR2 options. Warning: Clearing PCROPi bits requires a full mass erase!
|
||||||
|
The @var{num} parameter is a value shown by @command{flash banks}, @var{optcr2} a 32-bit word.
|
||||||
@end deffn
|
@end deffn
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@ -6832,12 +6855,13 @@ non-zero exit code to the parent process.
|
||||||
@deffn Command debug_level [n]
|
@deffn Command debug_level [n]
|
||||||
@cindex message level
|
@cindex message level
|
||||||
Display debug level.
|
Display debug level.
|
||||||
If @var{n} (from 0..3) is provided, then set it to that level.
|
If @var{n} (from 0..4) is provided, then set it to that level.
|
||||||
This affects the kind of messages sent to the server log.
|
This affects the kind of messages sent to the server log.
|
||||||
Level 0 is error messages only;
|
Level 0 is error messages only;
|
||||||
level 1 adds warnings;
|
level 1 adds warnings;
|
||||||
level 2 adds informational messages;
|
level 2 adds informational messages;
|
||||||
and level 3 adds debugging messages.
|
level 3 adds debugging messages;
|
||||||
|
and level 4 adds verbose low-level debug messages.
|
||||||
The default is level 2, but that can be overridden on
|
The default is level 2, but that can be overridden on
|
||||||
the command line along with the location of that log
|
the command line along with the location of that log
|
||||||
file (which is normally the server's standard output).
|
file (which is normally the server's standard output).
|
||||||
|
|
|
@ -464,7 +464,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
|
||||||
.bank_number = 0,
|
.bank_number = 0,
|
||||||
.base_address = FLASH_BANK_BASE_S,
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
.controller_address = 0x400e0a00,
|
.controller_address = 0x400e0a00,
|
||||||
.flash_wait_states = 6, /* workaround silicon bug */
|
.flash_wait_states = 5,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 1024 * 1024,
|
.size_bytes = 1024 * 1024,
|
||||||
.nsectors = 128,
|
.nsectors = 128,
|
||||||
|
@ -499,7 +499,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
|
||||||
.bank_number = 0,
|
.bank_number = 0,
|
||||||
.base_address = FLASH_BANK_BASE_S,
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
.controller_address = 0x400e0a00,
|
.controller_address = 0x400e0a00,
|
||||||
.flash_wait_states = 6, /* workaround silicon bug */
|
.flash_wait_states = 5,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 512 * 1024,
|
.size_bytes = 512 * 1024,
|
||||||
.nsectors = 64,
|
.nsectors = 64,
|
||||||
|
@ -532,7 +532,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
|
||||||
.bank_number = 0,
|
.bank_number = 0,
|
||||||
.base_address = FLASH_BANK_BASE_S,
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
.controller_address = 0x400e0a00,
|
.controller_address = 0x400e0a00,
|
||||||
.flash_wait_states = 6, /* workaround silicon bug */
|
.flash_wait_states = 5,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 512 * 1024,
|
.size_bytes = 512 * 1024,
|
||||||
.nsectors = 64,
|
.nsectors = 64,
|
||||||
|
@ -565,7 +565,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
|
||||||
.bank_number = 0,
|
.bank_number = 0,
|
||||||
.base_address = FLASH_BANK_BASE_S,
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
.controller_address = 0x400e0a00,
|
.controller_address = 0x400e0a00,
|
||||||
.flash_wait_states = 6, /* workaround silicon bug */
|
.flash_wait_states = 5,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 512 * 1024,
|
.size_bytes = 512 * 1024,
|
||||||
.nsectors = 64,
|
.nsectors = 64,
|
||||||
|
@ -598,7 +598,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
|
||||||
.bank_number = 0,
|
.bank_number = 0,
|
||||||
.base_address = FLASH_BANK_BASE_S,
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
.controller_address = 0x400e0a00,
|
.controller_address = 0x400e0a00,
|
||||||
.flash_wait_states = 6, /* workaround silicon bug */
|
.flash_wait_states = 5,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 1024 * 1024,
|
.size_bytes = 1024 * 1024,
|
||||||
.nsectors = 128,
|
.nsectors = 128,
|
||||||
|
@ -631,7 +631,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
|
||||||
.bank_number = 0,
|
.bank_number = 0,
|
||||||
.base_address = FLASH_BANK_BASE_S,
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
.controller_address = 0x400e0a00,
|
.controller_address = 0x400e0a00,
|
||||||
.flash_wait_states = 6, /* workaround silicon bug */
|
.flash_wait_states = 5,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 1024 * 1024,
|
.size_bytes = 1024 * 1024,
|
||||||
.nsectors = 128,
|
.nsectors = 128,
|
||||||
|
@ -1279,7 +1279,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
|
||||||
.bank_number = 0,
|
.bank_number = 0,
|
||||||
.base_address = FLASH_BANK0_BASE_SD,
|
.base_address = FLASH_BANK0_BASE_SD,
|
||||||
.controller_address = 0x400e0a00,
|
.controller_address = 0x400e0a00,
|
||||||
.flash_wait_states = 6, /* workaround silicon bug */
|
.flash_wait_states = 5,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 512 * 1024,
|
.size_bytes = 512 * 1024,
|
||||||
.nsectors = 64,
|
.nsectors = 64,
|
||||||
|
@ -1295,7 +1295,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
|
||||||
.bank_number = 1,
|
.bank_number = 1,
|
||||||
.base_address = FLASH_BANK1_BASE_1024K_SD,
|
.base_address = FLASH_BANK1_BASE_1024K_SD,
|
||||||
.controller_address = 0x400e0c00,
|
.controller_address = 0x400e0c00,
|
||||||
.flash_wait_states = 6, /* workaround silicon bug */
|
.flash_wait_states = 5,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 512 * 1024,
|
.size_bytes = 512 * 1024,
|
||||||
.nsectors = 64,
|
.nsectors = 64,
|
||||||
|
@ -1305,10 +1305,10 @@ static const struct sam4_chip_details all_sam4_details[] = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
/* at91samg53n19 */
|
/* atsamg53n19 */
|
||||||
{
|
{
|
||||||
.chipid_cidr = 0x247e0ae0,
|
.chipid_cidr = 0x247e0ae0,
|
||||||
.name = "at91samg53n19",
|
.name = "atsamg53n19",
|
||||||
.total_flash_size = 512 * 1024,
|
.total_flash_size = 512 * 1024,
|
||||||
.total_sram_size = 96 * 1024,
|
.total_sram_size = 96 * 1024,
|
||||||
.n_gpnvms = 2,
|
.n_gpnvms = 2,
|
||||||
|
@ -1323,7 +1323,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
|
||||||
.bank_number = 0,
|
.bank_number = 0,
|
||||||
.base_address = FLASH_BANK_BASE_S,
|
.base_address = FLASH_BANK_BASE_S,
|
||||||
.controller_address = 0x400e0a00,
|
.controller_address = 0x400e0a00,
|
||||||
.flash_wait_states = 6, /* workaround silicon bug */
|
.flash_wait_states = 5,
|
||||||
.present = 1,
|
.present = 1,
|
||||||
.size_bytes = 512 * 1024,
|
.size_bytes = 512 * 1024,
|
||||||
.nsectors = 64,
|
.nsectors = 64,
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include <target/cortex_m.h>
|
#include <target/cortex_m.h>
|
||||||
|
|
||||||
#define SAMD_NUM_SECTORS 16
|
#define SAMD_NUM_PROT_BLOCKS 16
|
||||||
#define SAMD_PAGE_SIZE_MAX 1024
|
#define SAMD_PAGE_SIZE_MAX 1024
|
||||||
|
|
||||||
#define SAMD_FLASH ((uint32_t)0x00000000) /* physical Flash memory */
|
#define SAMD_FLASH ((uint32_t)0x00000000) /* physical Flash memory */
|
||||||
|
@ -286,6 +286,7 @@ struct samd_info {
|
||||||
uint32_t page_size;
|
uint32_t page_size;
|
||||||
int num_pages;
|
int num_pages;
|
||||||
int sector_size;
|
int sector_size;
|
||||||
|
int prot_block_size;
|
||||||
|
|
||||||
bool probed;
|
bool probed;
|
||||||
struct target *target;
|
struct target *target;
|
||||||
|
@ -319,7 +320,7 @@ static const struct samd_part *samd_find_part(uint32_t id)
|
||||||
|
|
||||||
static int samd_protect_check(struct flash_bank *bank)
|
static int samd_protect_check(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
int res;
|
int res, prot_block;
|
||||||
uint16_t lock;
|
uint16_t lock;
|
||||||
|
|
||||||
res = target_read_u16(bank->target,
|
res = target_read_u16(bank->target,
|
||||||
|
@ -328,8 +329,8 @@ static int samd_protect_check(struct flash_bank *bank)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
/* Lock bits are active-low */
|
/* Lock bits are active-low */
|
||||||
for (int i = 0; i < bank->num_sectors; i++)
|
for (prot_block = 0; prot_block < bank->num_prot_blocks; prot_block++)
|
||||||
bank->sectors[i].is_protected = !(lock & (1<<i));
|
bank->prot_blocks[prot_block].is_protected = !(lock & (1u<<prot_block));
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -380,8 +381,6 @@ static int samd_probe(struct flash_bank *bank)
|
||||||
|
|
||||||
bank->size = part->flash_kb * 1024;
|
bank->size = part->flash_kb * 1024;
|
||||||
|
|
||||||
chip->sector_size = bank->size / SAMD_NUM_SECTORS;
|
|
||||||
|
|
||||||
res = samd_get_flash_page_info(bank->target, &chip->page_size,
|
res = samd_get_flash_page_info(bank->target, &chip->page_size,
|
||||||
&chip->num_pages);
|
&chip->num_pages);
|
||||||
if (res != ERROR_OK) {
|
if (res != ERROR_OK) {
|
||||||
|
@ -397,21 +396,23 @@ static int samd_probe(struct flash_bank *bank)
|
||||||
part->flash_kb, chip->num_pages, chip->page_size);
|
part->flash_kb, chip->num_pages, chip->page_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Erase granularity = 1 row = 4 pages */
|
||||||
|
chip->sector_size = chip->page_size * 4;
|
||||||
|
|
||||||
/* Allocate the sector table */
|
/* Allocate the sector table */
|
||||||
bank->num_sectors = SAMD_NUM_SECTORS;
|
bank->num_sectors = chip->num_pages / 4;
|
||||||
bank->sectors = calloc(bank->num_sectors, sizeof((bank->sectors)[0]));
|
bank->sectors = alloc_block_array(0, chip->sector_size, bank->num_sectors);
|
||||||
if (!bank->sectors)
|
if (!bank->sectors)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
/* Fill out the sector information: all SAMD sectors are the same size and
|
/* 16 protection blocks per device */
|
||||||
* there is always a fixed number of them. */
|
chip->prot_block_size = bank->size / SAMD_NUM_PROT_BLOCKS;
|
||||||
for (int i = 0; i < bank->num_sectors; i++) {
|
|
||||||
bank->sectors[i].size = chip->sector_size;
|
/* Allocate the table of protection blocks */
|
||||||
bank->sectors[i].offset = i * chip->sector_size;
|
bank->num_prot_blocks = SAMD_NUM_PROT_BLOCKS;
|
||||||
/* mark as unknown */
|
bank->prot_blocks = alloc_block_array(0, chip->prot_block_size, bank->num_prot_blocks);
|
||||||
bank->sectors[i].is_erased = -1;
|
if (!bank->prot_blocks)
|
||||||
bank->sectors[i].is_protected = -1;
|
return ERROR_FAIL;
|
||||||
}
|
|
||||||
|
|
||||||
samd_protect_check(bank);
|
samd_protect_check(bank);
|
||||||
|
|
||||||
|
@ -606,9 +607,10 @@ out_user_row:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int samd_protect(struct flash_bank *bank, int set, int first, int last)
|
static int samd_protect(struct flash_bank *bank, int set, int first_prot_bl, int last_prot_bl)
|
||||||
{
|
{
|
||||||
struct samd_info *chip = (struct samd_info *)bank->driver_priv;
|
int res = ERROR_OK;
|
||||||
|
int prot_block;
|
||||||
|
|
||||||
/* We can issue lock/unlock region commands with the target running but
|
/* 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
|
* the settings won't persist unless we're able to modify the LOCK regions
|
||||||
|
@ -618,18 +620,16 @@ static int samd_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = ERROR_OK;
|
for (prot_block = first_prot_bl; prot_block <= last_prot_bl; prot_block++) {
|
||||||
|
if (set != bank->prot_blocks[prot_block].is_protected) {
|
||||||
for (int s = first; s <= last; s++) {
|
/* Load an address that is within this protection block (we use offset 0) */
|
||||||
if (set != bank->sectors[s].is_protected) {
|
|
||||||
/* Load an address that is within this sector (we use offset 0) */
|
|
||||||
res = target_write_u32(bank->target,
|
res = target_write_u32(bank->target,
|
||||||
SAMD_NVMCTRL + SAMD_NVMCTRL_ADDR,
|
SAMD_NVMCTRL + SAMD_NVMCTRL_ADDR,
|
||||||
((s * chip->sector_size) >> 1));
|
bank->prot_blocks[prot_block].offset >> 1);
|
||||||
if (res != ERROR_OK)
|
if (res != ERROR_OK)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
/* Tell the controller to lock that sector */
|
/* Tell the controller to lock that block */
|
||||||
res = samd_issue_nvmctrl_command(bank->target,
|
res = samd_issue_nvmctrl_command(bank->target,
|
||||||
set ? SAMD_NVM_CMD_LR : SAMD_NVM_CMD_UR);
|
set ? SAMD_NVM_CMD_LR : SAMD_NVM_CMD_UR);
|
||||||
if (res != ERROR_OK)
|
if (res != ERROR_OK)
|
||||||
|
@ -644,7 +644,7 @@ static int samd_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
* locked. See Table 9-3 in the SAMD20 datasheet for more details. */
|
* locked. See Table 9-3 in the SAMD20 datasheet for more details. */
|
||||||
|
|
||||||
res = samd_modify_user_row(bank->target, set ? 0x0000 : 0xFFFF,
|
res = samd_modify_user_row(bank->target, set ? 0x0000 : 0xFFFF,
|
||||||
48 + first, 48 + last);
|
48 + first_prot_bl, 48 + last_prot_bl);
|
||||||
if (res != ERROR_OK)
|
if (res != ERROR_OK)
|
||||||
LOG_WARNING("SAMD: protect settings were not made persistent!");
|
LOG_WARNING("SAMD: protect settings were not made persistent!");
|
||||||
|
|
||||||
|
@ -656,10 +656,9 @@ exit:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int samd_erase(struct flash_bank *bank, int first, int last)
|
static int samd_erase(struct flash_bank *bank, int first_sect, int last_sect)
|
||||||
{
|
{
|
||||||
int res;
|
int res, s;
|
||||||
int rows_in_sector;
|
|
||||||
struct samd_info *chip = (struct samd_info *)bank->driver_priv;
|
struct samd_info *chip = (struct samd_info *)bank->driver_priv;
|
||||||
|
|
||||||
if (bank->target->state != TARGET_HALTED) {
|
if (bank->target->state != TARGET_HALTED) {
|
||||||
|
@ -673,26 +672,12 @@ static int samd_erase(struct flash_bank *bank, int first, int last)
|
||||||
return ERROR_FLASH_BANK_NOT_PROBED;
|
return ERROR_FLASH_BANK_NOT_PROBED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The SAMD NVM has row erase granularity. There are four pages in a row
|
|
||||||
* and the number of rows in a sector depends on the sector size, which in
|
|
||||||
* turn depends on the Flash capacity as there is a fixed number of
|
|
||||||
* sectors. */
|
|
||||||
rows_in_sector = chip->sector_size / (chip->page_size * 4);
|
|
||||||
|
|
||||||
/* For each sector to be erased */
|
/* For each sector to be erased */
|
||||||
for (int s = first; s <= last; s++) {
|
for (s = first_sect; s <= last_sect; s++) {
|
||||||
if (bank->sectors[s].is_protected) {
|
res = samd_erase_row(bank->target, bank->sectors[s].offset);
|
||||||
LOG_ERROR("SAMD: failed to erase sector %d. That sector is write-protected", s);
|
if (res != ERROR_OK) {
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
LOG_ERROR("SAMD: failed to erase sector %d at 0x%08" PRIx32, s, bank->sectors[s].offset);
|
||||||
}
|
return res;
|
||||||
|
|
||||||
/* For each row in that sector */
|
|
||||||
for (int r = s * rows_in_sector; r < (s + 1) * rows_in_sector; r++) {
|
|
||||||
res = samd_erase_row(bank->target, r * chip->page_size * 4);
|
|
||||||
if (res != ERROR_OK) {
|
|
||||||
LOG_ERROR("SAMD: failed to erase sector %d", s);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#define EFM_FAMILY_ID_HAPPY_GECKO 77
|
#define EFM_FAMILY_ID_HAPPY_GECKO 77
|
||||||
#define EZR_FAMILY_ID_WONDER_GECKO 120
|
#define EZR_FAMILY_ID_WONDER_GECKO 120
|
||||||
#define EZR_FAMILY_ID_LEOPARD_GECKO 121
|
#define EZR_FAMILY_ID_LEOPARD_GECKO 121
|
||||||
|
#define EZR_FAMILY_ID_HAPPY_GECKO 122
|
||||||
|
|
||||||
#define EFM32_FLASH_ERASE_TMO 100
|
#define EFM32_FLASH_ERASE_TMO 100
|
||||||
#define EFM32_FLASH_WDATAREADY_TMO 100
|
#define EFM32_FLASH_WDATAREADY_TMO 100
|
||||||
|
@ -178,7 +179,8 @@ static int efm32x_read_info(struct flash_bank *bank,
|
||||||
EFM_FAMILY_ID_TINY_GECKO == efm32_info->part_family)
|
EFM_FAMILY_ID_TINY_GECKO == efm32_info->part_family)
|
||||||
efm32_info->page_size = 512;
|
efm32_info->page_size = 512;
|
||||||
else if (EFM_FAMILY_ID_ZERO_GECKO == efm32_info->part_family ||
|
else if (EFM_FAMILY_ID_ZERO_GECKO == efm32_info->part_family ||
|
||||||
EFM_FAMILY_ID_HAPPY_GECKO == efm32_info->part_family)
|
EFM_FAMILY_ID_HAPPY_GECKO == efm32_info->part_family ||
|
||||||
|
EZR_FAMILY_ID_HAPPY_GECKO == efm32_info->part_family)
|
||||||
efm32_info->page_size = 1024;
|
efm32_info->page_size = 1024;
|
||||||
else if (EFM_FAMILY_ID_GIANT_GECKO == efm32_info->part_family ||
|
else if (EFM_FAMILY_ID_GIANT_GECKO == efm32_info->part_family ||
|
||||||
EFM_FAMILY_ID_LEOPARD_GECKO == efm32_info->part_family) {
|
EFM_FAMILY_ID_LEOPARD_GECKO == efm32_info->part_family) {
|
||||||
|
@ -236,6 +238,7 @@ static int efm32x_decode_info(struct efm32_info *info, char *buf, int buf_size)
|
||||||
switch (info->part_family) {
|
switch (info->part_family) {
|
||||||
case EZR_FAMILY_ID_WONDER_GECKO:
|
case EZR_FAMILY_ID_WONDER_GECKO:
|
||||||
case EZR_FAMILY_ID_LEOPARD_GECKO:
|
case EZR_FAMILY_ID_LEOPARD_GECKO:
|
||||||
|
case EZR_FAMILY_ID_HAPPY_GECKO:
|
||||||
printed = snprintf(buf, buf_size, "EZR32 ");
|
printed = snprintf(buf, buf_size, "EZR32 ");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -270,6 +273,7 @@ static int efm32x_decode_info(struct efm32_info *info, char *buf, int buf_size)
|
||||||
printed = snprintf(buf, buf_size, "Zero Gecko");
|
printed = snprintf(buf, buf_size, "Zero Gecko");
|
||||||
break;
|
break;
|
||||||
case EFM_FAMILY_ID_HAPPY_GECKO:
|
case EFM_FAMILY_ID_HAPPY_GECKO:
|
||||||
|
case EZR_FAMILY_ID_HAPPY_GECKO:
|
||||||
printed = snprintf(buf, buf_size, "Happy Gecko");
|
printed = snprintf(buf, buf_size, "Happy Gecko");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -59,10 +59,14 @@
|
||||||
*
|
*
|
||||||
* Sector sizes in kiBytes:
|
* Sector sizes in kiBytes:
|
||||||
* 1 MiByte part with 4 x 16, 1 x 64, 7 x 128.
|
* 1 MiByte part with 4 x 16, 1 x 64, 7 x 128.
|
||||||
|
* 1.5 MiByte part with 4 x 16, 1 x 64, 11 x 128.
|
||||||
* 2 MiByte part with 4 x 16, 1 x 64, 7 x 128, 4 x 16, 1 x 64, 7 x 128.
|
* 2 MiByte part with 4 x 16, 1 x 64, 7 x 128, 4 x 16, 1 x 64, 7 x 128.
|
||||||
* 1 MiByte STM32F42x/43x part with DB1M Option set:
|
* 1 MiByte STM32F42x/43x part with DB1M Option set:
|
||||||
* 4 x 16, 1 x 64, 3 x 128, 4 x 16, 1 x 64, 3 x 128.
|
* 4 x 16, 1 x 64, 3 x 128, 4 x 16, 1 x 64, 3 x 128.
|
||||||
*
|
*
|
||||||
|
* STM32F7[2|3]
|
||||||
|
* 512 kiByte part with 4 x 16, 1 x 64, 3 x 128.
|
||||||
|
*
|
||||||
* STM32F7[4|5]
|
* STM32F7[4|5]
|
||||||
* 1 MiByte part with 4 x 32, 1 x 128, 3 x 256.
|
* 1 MiByte part with 4 x 32, 1 x 128, 3 x 256.
|
||||||
*
|
*
|
||||||
|
@ -93,6 +97,12 @@
|
||||||
* RM0410
|
* RM0410
|
||||||
* http://www.st.com/resource/en/reference_manual/dm00224583.pdf
|
* http://www.st.com/resource/en/reference_manual/dm00224583.pdf
|
||||||
*
|
*
|
||||||
|
* RM0430
|
||||||
|
* http://www.st.com/resource/en/reference_manual/dm00305666.pdf
|
||||||
|
*
|
||||||
|
* RM0431
|
||||||
|
* http://www.st.com/resource/en/reference_manual/dm00305990.pdf
|
||||||
|
*
|
||||||
* STM32F1x series - notice that this code was copy, pasted and knocked
|
* STM32F1x series - notice that this code was copy, pasted and knocked
|
||||||
* into a stm32f2x driver, so in case something has been converted or
|
* into a stm32f2x driver, so in case something has been converted or
|
||||||
* bugs haven't been fixed, here are the original manuals:
|
* bugs haven't been fixed, here are the original manuals:
|
||||||
|
@ -121,6 +131,7 @@
|
||||||
#define STM32_FLASH_CR 0x40023c10
|
#define STM32_FLASH_CR 0x40023c10
|
||||||
#define STM32_FLASH_OPTCR 0x40023c14
|
#define STM32_FLASH_OPTCR 0x40023c14
|
||||||
#define STM32_FLASH_OPTCR1 0x40023c18
|
#define STM32_FLASH_OPTCR1 0x40023c18
|
||||||
|
#define STM32_FLASH_OPTCR2 0x40023c1c
|
||||||
|
|
||||||
/* FLASH_CR register bits */
|
/* FLASH_CR register bits */
|
||||||
#define FLASH_PG (1 << 0)
|
#define FLASH_PG (1 << 0)
|
||||||
|
@ -152,6 +163,10 @@
|
||||||
#define OPTCR_START (1 << 1)
|
#define OPTCR_START (1 << 1)
|
||||||
#define OPTCR_NDBANK (1 << 29) /* not dual bank mode */
|
#define OPTCR_NDBANK (1 << 29) /* not dual bank mode */
|
||||||
#define OPTCR_DB1M (1 << 30) /* 1 MiB devices dual flash bank option */
|
#define OPTCR_DB1M (1 << 30) /* 1 MiB devices dual flash bank option */
|
||||||
|
#define OPTCR_SPRMOD (1 << 31) /* switches PCROPi/nWPRi interpretation */
|
||||||
|
|
||||||
|
/* STM32_FLASH_OPTCR2 register bits */
|
||||||
|
#define OPTCR2_PCROP_RDP (1 << 31) /* erase PCROP zone when decreasing RDP */
|
||||||
|
|
||||||
/* register unlock keys */
|
/* register unlock keys */
|
||||||
#define KEY1 0x45670123
|
#define KEY1 0x45670123
|
||||||
|
@ -166,14 +181,17 @@ struct stm32x_options {
|
||||||
uint16_t user_options; /* bit 0-7 usual options, bit 8-11 extra options */
|
uint16_t user_options; /* bit 0-7 usual options, bit 8-11 extra options */
|
||||||
uint32_t protection;
|
uint32_t protection;
|
||||||
uint32_t boot_addr;
|
uint32_t boot_addr;
|
||||||
|
uint32_t optcr2_pcrop;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stm32x_flash_bank {
|
struct stm32x_flash_bank {
|
||||||
struct stm32x_options option_bytes;
|
struct stm32x_options option_bytes;
|
||||||
int probed;
|
int probed;
|
||||||
bool has_large_mem; /* F42x/43x/469/479/7xx in dual bank mode */
|
bool has_large_mem; /* F42x/43x/469/479/7xx in dual bank mode */
|
||||||
bool has_boot_addr; /* F7xx */
|
|
||||||
bool has_extra_options; /* F42x/43x/469/479/7xx */
|
bool has_extra_options; /* F42x/43x/469/479/7xx */
|
||||||
|
bool has_boot_addr; /* F7xx */
|
||||||
|
bool has_optcr2_pcrop; /* F72x/73x */
|
||||||
|
int protection_bits; /* F413/423 */
|
||||||
uint32_t user_bank_size;
|
uint32_t user_bank_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -328,11 +346,13 @@ static int stm32x_read_options(struct flash_bank *bank)
|
||||||
* whereas F7 6 bits (IWDG_SW and WWDG_SW) in user_options */
|
* whereas F7 6 bits (IWDG_SW and WWDG_SW) in user_options */
|
||||||
stm32x_info->option_bytes.user_options = optiondata & 0xfc;
|
stm32x_info->option_bytes.user_options = optiondata & 0xfc;
|
||||||
stm32x_info->option_bytes.RDP = (optiondata >> 8) & 0xff;
|
stm32x_info->option_bytes.RDP = (optiondata >> 8) & 0xff;
|
||||||
stm32x_info->option_bytes.protection = (optiondata >> 16) & 0xfff;
|
stm32x_info->option_bytes.protection =
|
||||||
|
(optiondata >> 16) & (~(0xffff << stm32x_info->protection_bits) & 0xffff);
|
||||||
|
|
||||||
if (stm32x_info->has_extra_options) {
|
if (stm32x_info->has_extra_options) {
|
||||||
/* F42x/43x/469/479 and 7xx have up to 4 bits of extra options */
|
/* F42x/43x/469/479 and 7xx have up to 4 bits of extra options */
|
||||||
stm32x_info->option_bytes.user_options |= (optiondata >> 20) & 0xf00;
|
stm32x_info->option_bytes.user_options |= (optiondata >> 20) &
|
||||||
|
((0xf00 << (stm32x_info->protection_bits - 12)) & 0xf00);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stm32x_info->has_large_mem || stm32x_info->has_boot_addr) {
|
if (stm32x_info->has_large_mem || stm32x_info->has_boot_addr) {
|
||||||
|
@ -350,6 +370,20 @@ static int stm32x_read_options(struct flash_bank *bank)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stm32x_info->has_optcr2_pcrop) {
|
||||||
|
retval = target_read_u32(target, STM32_FLASH_OPTCR2, &optiondata);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
stm32x_info->option_bytes.optcr2_pcrop = optiondata;
|
||||||
|
if (stm32x_info->has_optcr2_pcrop &&
|
||||||
|
(stm32x_info->option_bytes.optcr2_pcrop & ~OPTCR2_PCROP_RDP)) {
|
||||||
|
LOG_INFO("PCROP Engaged");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stm32x_info->option_bytes.optcr2_pcrop = 0x0;
|
||||||
|
}
|
||||||
|
|
||||||
if (stm32x_info->option_bytes.RDP != 0xAA)
|
if (stm32x_info->option_bytes.RDP != 0xAA)
|
||||||
LOG_INFO("Device Security Bit Set");
|
LOG_INFO("Device Security Bit Set");
|
||||||
|
|
||||||
|
@ -371,11 +405,13 @@ static int stm32x_write_options(struct flash_bank *bank)
|
||||||
/* rebuild option data */
|
/* rebuild option data */
|
||||||
optiondata = stm32x_info->option_bytes.user_options & 0xfc;
|
optiondata = stm32x_info->option_bytes.user_options & 0xfc;
|
||||||
optiondata |= stm32x_info->option_bytes.RDP << 8;
|
optiondata |= stm32x_info->option_bytes.RDP << 8;
|
||||||
optiondata |= (stm32x_info->option_bytes.protection & 0x0fff) << 16;
|
optiondata |= (stm32x_info->option_bytes.protection &
|
||||||
|
(~(0xffff << stm32x_info->protection_bits))) << 16;
|
||||||
|
|
||||||
if (stm32x_info->has_extra_options) {
|
if (stm32x_info->has_extra_options) {
|
||||||
/* F42x/43x/469/479 and 7xx have up to 4 bits of extra options */
|
/* F42x/43x/469/479 and 7xx have up to 4 bits of extra options */
|
||||||
optiondata |= (stm32x_info->option_bytes.user_options & 0xf00) << 20;
|
optiondata |= (stm32x_info->option_bytes.user_options &
|
||||||
|
((0xf00 << (stm32x_info->protection_bits - 12)) & 0xf00)) << 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stm32x_info->has_large_mem || stm32x_info->has_boot_addr) {
|
if (stm32x_info->has_large_mem || stm32x_info->has_boot_addr) {
|
||||||
|
@ -392,6 +428,14 @@ static int stm32x_write_options(struct flash_bank *bank)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* program extra pcrop register */
|
||||||
|
if (stm32x_info->has_optcr2_pcrop) {
|
||||||
|
retval = target_write_u32(target, STM32_FLASH_OPTCR2,
|
||||||
|
stm32x_info->option_bytes.optcr2_pcrop);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/* program options */
|
/* program options */
|
||||||
retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata);
|
retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -418,6 +462,8 @@ static int stm32x_write_options(struct flash_bank *bank)
|
||||||
static int stm32x_protect_check(struct flash_bank *bank)
|
static int stm32x_protect_check(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
|
struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
|
||||||
|
struct flash_sector *prot_blocks;
|
||||||
|
int num_prot_blocks;
|
||||||
|
|
||||||
/* read write protection settings */
|
/* read write protection settings */
|
||||||
int retval = stm32x_read_options(bank);
|
int retval = stm32x_read_options(bank);
|
||||||
|
@ -426,27 +472,18 @@ static int stm32x_protect_check(struct flash_bank *bank)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stm32x_info->has_boot_addr && stm32x_info->has_large_mem) {
|
if (bank->prot_blocks) {
|
||||||
/* F76x/77x: bit k protects sectors 2*k and 2*k+1 */
|
num_prot_blocks = bank->num_prot_blocks;
|
||||||
for (int i = 0; i < (bank->num_sectors >> 1); i++) {
|
prot_blocks = bank->prot_blocks;
|
||||||
if (stm32x_info->option_bytes.protection & (1 << i)) {
|
|
||||||
bank->sectors[i << 1].is_protected = 0;
|
|
||||||
bank->sectors[(i << 1) + 1].is_protected = 0;
|
|
||||||
} else {
|
|
||||||
bank->sectors[i << 1].is_protected = 1;
|
|
||||||
bank->sectors[(i << 1) + 1].is_protected = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* one protection bit per sector */
|
num_prot_blocks = bank->num_sectors;
|
||||||
for (int i = 0; i < bank->num_sectors; i++) {
|
prot_blocks = bank->sectors;
|
||||||
if (stm32x_info->option_bytes.protection & (1 << i))
|
|
||||||
bank->sectors[i].is_protected = 0;
|
|
||||||
else
|
|
||||||
bank->sectors[i].is_protected = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < num_prot_blocks; i++)
|
||||||
|
prot_blocks[i].is_protected =
|
||||||
|
~(stm32x_info->option_bytes.protection >> i) & 1;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,17 +552,6 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stm32x_info->has_boot_addr && stm32x_info->has_large_mem) {
|
|
||||||
/* F76x/77x: bit k protects sectors 2*k and 2*k+1 */
|
|
||||||
if ((first & 1) != 0 || (last & 1) != 1) {
|
|
||||||
LOG_ERROR("sector protection must be double sector aligned");
|
|
||||||
return ERROR_FAIL;
|
|
||||||
} else {
|
|
||||||
first >>= 1;
|
|
||||||
last >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = first; i <= last; i++) {
|
for (int i = first; i <= last; i++) {
|
||||||
if (set)
|
if (set)
|
||||||
stm32x_info->option_bytes.protection &= ~(1 << i);
|
stm32x_info->option_bytes.protection &= ~(1 << i);
|
||||||
|
@ -829,7 +855,7 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
{
|
{
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
|
struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
|
||||||
int i;
|
int i, num_prot_blocks;
|
||||||
uint16_t flash_size_in_kb;
|
uint16_t flash_size_in_kb;
|
||||||
uint32_t flash_size_reg = 0x1FFF7A22;
|
uint32_t flash_size_reg = 0x1FFF7A22;
|
||||||
uint16_t max_sector_size_in_kb = 128;
|
uint16_t max_sector_size_in_kb = 128;
|
||||||
|
@ -841,15 +867,31 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
stm32x_info->has_large_mem = false;
|
stm32x_info->has_large_mem = false;
|
||||||
stm32x_info->has_boot_addr = false;
|
stm32x_info->has_boot_addr = false;
|
||||||
stm32x_info->has_extra_options = false;
|
stm32x_info->has_extra_options = false;
|
||||||
|
stm32x_info->has_optcr2_pcrop = false;
|
||||||
|
stm32x_info->protection_bits = 12; /* max. number of nWRPi bits (in FLASH_OPTCR !!!) */
|
||||||
|
num_prot_blocks = 0;
|
||||||
|
|
||||||
|
if (bank->sectors) {
|
||||||
|
free(bank->sectors);
|
||||||
|
bank->num_sectors = 0;
|
||||||
|
bank->sectors = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bank->prot_blocks) {
|
||||||
|
free(bank->prot_blocks);
|
||||||
|
bank->num_prot_blocks = 0;
|
||||||
|
bank->prot_blocks = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* read stm32 device id register */
|
/* read stm32 device id register */
|
||||||
int retval = stm32x_get_device_id(bank, &device_id);
|
int retval = stm32x_get_device_id(bank, &device_id);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
|
LOG_INFO("device id = 0x%08" PRIx32 "", device_id);
|
||||||
|
device_id &= 0xfff; /* only bits 0-11 are used further on */
|
||||||
|
|
||||||
/* set max flash size depending on family, id taken from AN2606 */
|
/* set max flash size depending on family, id taken from AN2606 */
|
||||||
switch (device_id & 0xfff) {
|
switch (device_id) {
|
||||||
case 0x411: /* F20x/21x */
|
case 0x411: /* F20x/21x */
|
||||||
case 0x413: /* F40x/41x */
|
case 0x413: /* F40x/41x */
|
||||||
max_flash_size_in_kb = 1024;
|
max_flash_size_in_kb = 1024;
|
||||||
|
@ -892,6 +934,21 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
stm32x_info->has_boot_addr = true;
|
stm32x_info->has_boot_addr = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x452: /* F72x/73x */
|
||||||
|
max_flash_size_in_kb = 512;
|
||||||
|
flash_size_reg = 0x1FF07A22; /* yes, 0x1FF*0*7A22, not 0x1FF*F*7A22 */
|
||||||
|
stm32x_info->has_extra_options = true;
|
||||||
|
stm32x_info->has_boot_addr = true;
|
||||||
|
stm32x_info->has_optcr2_pcrop = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x463: /* F413x/423x */
|
||||||
|
max_flash_size_in_kb = 1536;
|
||||||
|
stm32x_info->has_extra_options = true;
|
||||||
|
stm32x_info->protection_bits = 15;
|
||||||
|
num_prot_blocks = 15;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_WARNING("Cannot identify target as a STM32 family.");
|
LOG_WARNING("Cannot identify target as a STM32 family.");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
@ -920,12 +977,8 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
/* did we assign flash size? */
|
/* did we assign flash size? */
|
||||||
assert(flash_size_in_kb != 0xffff);
|
assert(flash_size_in_kb != 0xffff);
|
||||||
|
|
||||||
/* Devices with > 1024 kiByte always are dual-banked */
|
|
||||||
if (flash_size_in_kb > 1024)
|
|
||||||
stm32x_info->has_large_mem = true;
|
|
||||||
|
|
||||||
/* F42x/43x/469/479 1024 kiByte devices have a dual bank option */
|
/* F42x/43x/469/479 1024 kiByte devices have a dual bank option */
|
||||||
if ((device_id & 0xfff) == 0x419 || (device_id & 0xfff) == 0x434) {
|
if ((device_id == 0x419) || (device_id == 0x434)) {
|
||||||
uint32_t optiondata;
|
uint32_t optiondata;
|
||||||
retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata);
|
retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
|
@ -942,7 +995,7 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* F76x/77x devices have a dual bank option */
|
/* F76x/77x devices have a dual bank option */
|
||||||
if ((device_id & 0xfff) == 0x451) {
|
if (device_id == 0x451) {
|
||||||
uint32_t optiondata;
|
uint32_t optiondata;
|
||||||
retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata);
|
retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
|
@ -963,11 +1016,6 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
int num_pages = flash_size_in_kb / max_sector_size_in_kb
|
int num_pages = flash_size_in_kb / max_sector_size_in_kb
|
||||||
+ (stm32x_info->has_large_mem ? 8 : 4);
|
+ (stm32x_info->has_large_mem ? 8 : 4);
|
||||||
|
|
||||||
if (bank->sectors) {
|
|
||||||
free(bank->sectors);
|
|
||||||
bank->sectors = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bank->base = base_address;
|
bank->base = base_address;
|
||||||
bank->num_sectors = num_pages;
|
bank->num_sectors = num_pages;
|
||||||
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
|
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
|
||||||
|
@ -978,15 +1026,44 @@ static int stm32x_probe(struct flash_bank *bank)
|
||||||
bank->size = 0;
|
bank->size = 0;
|
||||||
LOG_DEBUG("allocated %d sectors", num_pages);
|
LOG_DEBUG("allocated %d sectors", num_pages);
|
||||||
|
|
||||||
|
/* F76x/77x in dual bank mode */
|
||||||
|
if ((device_id == 0x451) && stm32x_info->has_large_mem)
|
||||||
|
num_prot_blocks = num_pages >> 1;
|
||||||
|
|
||||||
|
if (num_prot_blocks) {
|
||||||
|
bank->prot_blocks = malloc(sizeof(struct flash_sector) * num_prot_blocks);
|
||||||
|
for (i = 0; i < num_prot_blocks; i++)
|
||||||
|
bank->prot_blocks[i].is_protected = 0;
|
||||||
|
LOG_DEBUG("allocated %d prot blocks", num_prot_blocks);
|
||||||
|
}
|
||||||
|
|
||||||
if (stm32x_info->has_large_mem) {
|
if (stm32x_info->has_large_mem) {
|
||||||
/* dual-bank */
|
/* dual-bank */
|
||||||
setup_bank(bank, 0, flash_size_in_kb >> 1, max_sector_size_in_kb);
|
setup_bank(bank, 0, flash_size_in_kb >> 1, max_sector_size_in_kb);
|
||||||
setup_bank(bank, num_pages >> 1, flash_size_in_kb >> 1,
|
setup_bank(bank, num_pages >> 1, flash_size_in_kb >> 1,
|
||||||
max_sector_size_in_kb);
|
max_sector_size_in_kb);
|
||||||
|
|
||||||
|
/* F767x/F77x in dual mode, one protection bit refers to two adjacent sectors */
|
||||||
|
if (device_id == 0x451) {
|
||||||
|
for (i = 0; i < num_prot_blocks; i++) {
|
||||||
|
bank->prot_blocks[i].offset = bank->sectors[i << 1].offset;
|
||||||
|
bank->prot_blocks[i].size = bank->sectors[i << 1].size << 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* single-bank */
|
/* single-bank */
|
||||||
setup_bank(bank, 0, flash_size_in_kb, max_sector_size_in_kb);
|
setup_bank(bank, 0, flash_size_in_kb, max_sector_size_in_kb);
|
||||||
|
|
||||||
|
/* F413/F423, sectors 14 and 15 share one common protection bit */
|
||||||
|
if (device_id == 0x463) {
|
||||||
|
for (i = 0; i < num_prot_blocks; i++) {
|
||||||
|
bank->prot_blocks[i].offset = bank->sectors[i].offset;
|
||||||
|
bank->prot_blocks[i].size = bank->sectors[i].size;
|
||||||
|
}
|
||||||
|
bank->prot_blocks[num_prot_blocks - 1].size <<= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
bank->num_prot_blocks = num_prot_blocks;
|
||||||
assert((bank->size >> 10) == flash_size_in_kb);
|
assert((bank->size >> 10) == flash_size_in_kb);
|
||||||
|
|
||||||
stm32x_info->probed = 1;
|
stm32x_info->probed = 1;
|
||||||
|
@ -1107,6 +1184,14 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
case 0x1001:
|
case 0x1001:
|
||||||
rev_str = "Z";
|
rev_str = "Z";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x2000:
|
||||||
|
rev_str = "B";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x3000:
|
||||||
|
rev_str = "C";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1134,6 +1219,26 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x452:
|
||||||
|
device_str = "STM32F7[2|3]x";
|
||||||
|
|
||||||
|
switch (rev_id) {
|
||||||
|
case 0x1000:
|
||||||
|
rev_str = "A";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x463:
|
||||||
|
device_str = "STM32F4[1|2]3";
|
||||||
|
|
||||||
|
switch (rev_id) {
|
||||||
|
case 0x1000:
|
||||||
|
rev_str = "A";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
snprintf(buf, buf_size, "Cannot identify target as a STM32F2/4/7\n");
|
snprintf(buf, buf_size, "Cannot identify target as a STM32F2/4/7\n");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
@ -1164,8 +1269,8 @@ COMMAND_HANDLER(stm32x_handle_lock_command)
|
||||||
target = bank->target;
|
target = bank->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
LOG_ERROR("Target not halted");
|
LOG_INFO("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
/* return ERROR_TARGET_NOT_HALTED; */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stm32x_read_options(bank) != ERROR_OK) {
|
if (stm32x_read_options(bank) != ERROR_OK) {
|
||||||
|
@ -1203,8 +1308,8 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
|
||||||
target = bank->target;
|
target = bank->target;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
LOG_ERROR("Target not halted");
|
LOG_INFO("Target not halted");
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
/* return ERROR_TARGET_NOT_HALTED; */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stm32x_read_options(bank) != ERROR_OK) {
|
if (stm32x_read_options(bank) != ERROR_OK) {
|
||||||
|
@ -1215,6 +1320,9 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
|
||||||
/* clear readout protection and complementary option bytes
|
/* clear readout protection and complementary option bytes
|
||||||
* this will also force a device unlock if set */
|
* this will also force a device unlock if set */
|
||||||
stm32x_info->option_bytes.RDP = 0xAA;
|
stm32x_info->option_bytes.RDP = 0xAA;
|
||||||
|
if (stm32x_info->has_optcr2_pcrop) {
|
||||||
|
stm32x_info->option_bytes.optcr2_pcrop = OPTCR2_PCROP_RDP | (~1 << bank->num_sectors);
|
||||||
|
}
|
||||||
|
|
||||||
if (stm32x_write_options(bank) != ERROR_OK) {
|
if (stm32x_write_options(bank) != ERROR_OK) {
|
||||||
command_print(CMD_CTX, "%s failed to unlock device", bank->driver->name);
|
command_print(CMD_CTX, "%s failed to unlock device", bank->driver->name);
|
||||||
|
@ -1327,8 +1435,12 @@ COMMAND_HANDLER(stm32f2x_handle_options_read_command)
|
||||||
" boot_add0 0x%04X, boot_add1 0x%04X",
|
" boot_add0 0x%04X, boot_add1 0x%04X",
|
||||||
stm32x_info->option_bytes.user_options,
|
stm32x_info->option_bytes.user_options,
|
||||||
boot_addr & 0xffff, (boot_addr & 0xffff0000) >> 16);
|
boot_addr & 0xffff, (boot_addr & 0xffff0000) >> 16);
|
||||||
|
if (stm32x_info->has_optcr2_pcrop) {
|
||||||
|
command_print(CMD_CTX, "stm32f2x optcr2_pcrop 0x%08X",
|
||||||
|
stm32x_info->option_bytes.optcr2_pcrop);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
command_print(CMD_CTX, "stm32f2x user_options 0x%03X,",
|
command_print(CMD_CTX, "stm32f2x user_options 0x%03X",
|
||||||
stm32x_info->option_bytes.user_options);
|
stm32x_info->option_bytes.user_options);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1345,7 +1457,7 @@ COMMAND_HANDLER(stm32f2x_handle_options_write_command)
|
||||||
int retval;
|
int retval;
|
||||||
struct flash_bank *bank;
|
struct flash_bank *bank;
|
||||||
struct stm32x_flash_bank *stm32x_info = NULL;
|
struct stm32x_flash_bank *stm32x_info = NULL;
|
||||||
uint16_t user_options, boot_addr0, boot_addr1;
|
uint16_t user_options, boot_addr0, boot_addr1, options_mask;
|
||||||
|
|
||||||
if (CMD_ARGC < 1) {
|
if (CMD_ARGC < 1) {
|
||||||
command_print(CMD_CTX, "stm32f2x options_write <bank> ...");
|
command_print(CMD_CTX, "stm32f2x options_write <bank> ...");
|
||||||
|
@ -1378,9 +1490,11 @@ COMMAND_HANDLER(stm32f2x_handle_options_write_command)
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], user_options);
|
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], user_options);
|
||||||
if (user_options & (stm32x_info->has_extra_options ? ~0xffc : ~0xfc)) {
|
options_mask = !stm32x_info->has_extra_options ? ~0xfc :
|
||||||
|
~(((0xf00 << (stm32x_info->protection_bits - 12)) | 0xff) & 0xffc);
|
||||||
|
if (user_options & options_mask) {
|
||||||
command_print(CMD_CTX, "stm32f2x invalid user_options");
|
command_print(CMD_CTX, "stm32f2x invalid user_options");
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
stm32x_info->option_bytes.user_options = user_options;
|
stm32x_info->option_bytes.user_options = user_options;
|
||||||
|
@ -1400,6 +1514,48 @@ COMMAND_HANDLER(stm32f2x_handle_options_write_command)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
COMMAND_HANDLER(stm32f2x_handle_optcr2_write_command)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
struct flash_bank *bank;
|
||||||
|
struct stm32x_flash_bank *stm32x_info = NULL;
|
||||||
|
uint32_t optcr2_pcrop;
|
||||||
|
|
||||||
|
if (CMD_ARGC != 2) {
|
||||||
|
command_print(CMD_CTX, "stm32f2x optcr2_write <bank> <optcr2_value>");
|
||||||
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
|
||||||
|
if (ERROR_OK != retval)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
stm32x_info = bank->driver_priv;
|
||||||
|
if (!stm32x_info->has_optcr2_pcrop) {
|
||||||
|
command_print(CMD_CTX, "no optcr2 register");
|
||||||
|
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
command_print(CMD_CTX, "INFO: To disable PCROP, set PCROP_RDP"
|
||||||
|
" with PCROPi bits STILL SET, then\nlock device and"
|
||||||
|
" finally unlock it. Clears PCROP and mass erases flash.");
|
||||||
|
|
||||||
|
retval = stm32x_read_options(bank);
|
||||||
|
if (ERROR_OK != retval)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], optcr2_pcrop);
|
||||||
|
stm32x_info->option_bytes.optcr2_pcrop = optcr2_pcrop;
|
||||||
|
|
||||||
|
if (stm32x_write_options(bank) != ERROR_OK) {
|
||||||
|
command_print(CMD_CTX, "stm32f2x failed to write options");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
command_print(CMD_CTX, "stm32f2x optcr2_write complete.");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct command_registration stm32x_exec_command_handlers[] = {
|
static const struct command_registration stm32x_exec_command_handlers[] = {
|
||||||
{
|
{
|
||||||
.name = "lock",
|
.name = "lock",
|
||||||
|
@ -1433,9 +1589,17 @@ static const struct command_registration stm32x_exec_command_handlers[] = {
|
||||||
.name = "options_write",
|
.name = "options_write",
|
||||||
.handler = stm32f2x_handle_options_write_command,
|
.handler = stm32f2x_handle_options_write_command,
|
||||||
.mode = COMMAND_EXEC,
|
.mode = COMMAND_EXEC,
|
||||||
.usage = "bank_id user_options [ boot_add0 boot_add1]",
|
.usage = "bank_id user_options [ boot_add0 boot_add1 ]",
|
||||||
.help = "Write option bytes",
|
.help = "Write option bytes",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "optcr2_write",
|
||||||
|
.handler = stm32f2x_handle_optcr2_write_command,
|
||||||
|
.mode = COMMAND_EXEC,
|
||||||
|
.usage = "bank_id optcr2",
|
||||||
|
.help = "Write optcr2 word",
|
||||||
|
},
|
||||||
|
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -790,6 +790,11 @@ static int stm32lx_probe(struct flash_bank *bank)
|
||||||
flash_size_in_kb = 256;
|
flash_size_in_kb = 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 0x429 devices only use the lowest 8 bits of the flash size register */
|
||||||
|
if (retval == ERROR_OK && (device_id & 0xfff) == 0x429) {
|
||||||
|
flash_size_in_kb &= 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
/* Failed reading flash size or flash size invalid (early silicon),
|
/* Failed reading flash size or flash size invalid (early silicon),
|
||||||
* default to max target family */
|
* default to max target family */
|
||||||
if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
|
if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
|
||||||
|
|
|
@ -583,9 +583,10 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
|
||||||
{
|
{
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
|
size_t length;
|
||||||
struct fileio *fileio;
|
struct fileio *fileio;
|
||||||
|
|
||||||
if (CMD_ARGC != 3)
|
if (CMD_ARGC < 2 || CMD_ARGC > 3)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
struct duration bench;
|
struct duration bench;
|
||||||
|
@ -596,7 +597,16 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
|
offset = 0;
|
||||||
|
|
||||||
|
if (CMD_ARGC > 2)
|
||||||
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
|
||||||
|
|
||||||
|
if (offset > p->size) {
|
||||||
|
LOG_ERROR("Offset 0x%8.8" PRIx32 " is out of range of the flash bank",
|
||||||
|
offset);
|
||||||
|
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
|
if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
@ -608,20 +618,38 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = malloc(filesize);
|
length = MIN(filesize, p->size - offset);
|
||||||
|
|
||||||
|
if (!length) {
|
||||||
|
LOG_INFO("Nothing to write to flash bank");
|
||||||
|
fileio_close(fileio);
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length != filesize)
|
||||||
|
LOG_INFO("File content exceeds flash bank size. Only writing the "
|
||||||
|
"first %zu bytes of the file", length);
|
||||||
|
|
||||||
|
buffer = malloc(length);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
fileio_close(fileio);
|
fileio_close(fileio);
|
||||||
LOG_ERROR("Out of memory");
|
LOG_ERROR("Out of memory");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
size_t buf_cnt;
|
size_t buf_cnt;
|
||||||
if (fileio_read(fileio, filesize, buffer, &buf_cnt) != ERROR_OK) {
|
if (fileio_read(fileio, length, buffer, &buf_cnt) != ERROR_OK) {
|
||||||
free(buffer);
|
free(buffer);
|
||||||
fileio_close(fileio);
|
fileio_close(fileio);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = flash_driver_write(p, buffer, offset, buf_cnt);
|
if (buf_cnt != length) {
|
||||||
|
LOG_ERROR("Short read");
|
||||||
|
free(buffer);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = flash_driver_write(p, buffer, offset, length);
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
|
@ -629,8 +657,8 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
|
||||||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
|
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
|
||||||
command_print(CMD_CTX, "wrote %zu bytes from file %s to flash bank %u"
|
command_print(CMD_CTX, "wrote %zu bytes from file %s to flash bank %u"
|
||||||
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
|
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
|
||||||
filesize, CMD_ARGV[1], p->bank_number, offset,
|
length, CMD_ARGV[1], p->bank_number, offset,
|
||||||
duration_elapsed(&bench), duration_kbps(&bench, filesize));
|
duration_elapsed(&bench), duration_kbps(&bench, length));
|
||||||
}
|
}
|
||||||
|
|
||||||
fileio_close(fileio);
|
fileio_close(fileio);
|
||||||
|
@ -646,7 +674,7 @@ COMMAND_HANDLER(handle_flash_read_bank_command)
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
size_t written;
|
size_t written;
|
||||||
|
|
||||||
if (CMD_ARGC != 4)
|
if (CMD_ARGC < 2 || CMD_ARGC > 4)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
struct duration bench;
|
struct duration bench;
|
||||||
|
@ -654,11 +682,31 @@ COMMAND_HANDLER(handle_flash_read_bank_command)
|
||||||
|
|
||||||
struct flash_bank *p;
|
struct flash_bank *p;
|
||||||
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
|
int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
|
||||||
|
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
|
offset = 0;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], length);
|
|
||||||
|
if (CMD_ARGC > 2)
|
||||||
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
|
||||||
|
|
||||||
|
if (offset > p->size) {
|
||||||
|
LOG_ERROR("Offset 0x%8.8" PRIx32 " is out of range of the flash bank",
|
||||||
|
offset);
|
||||||
|
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
length = p->size - offset;
|
||||||
|
|
||||||
|
if (CMD_ARGC > 3)
|
||||||
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], length);
|
||||||
|
|
||||||
|
if (offset + length > p->size) {
|
||||||
|
LOG_ERROR("Length of %" PRIu32 " bytes with offset 0x%8.8" PRIx32
|
||||||
|
" is out of range of the flash bank", length, offset);
|
||||||
|
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
buffer = malloc(length);
|
buffer = malloc(length);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
|
@ -705,6 +753,7 @@ COMMAND_HANDLER(handle_flash_verify_bank_command)
|
||||||
struct fileio *fileio;
|
struct fileio *fileio;
|
||||||
size_t read_cnt;
|
size_t read_cnt;
|
||||||
size_t filesize;
|
size_t filesize;
|
||||||
|
size_t length;
|
||||||
int differ;
|
int differ;
|
||||||
|
|
||||||
if (CMD_ARGC < 2 || CMD_ARGC > 3)
|
if (CMD_ARGC < 2 || CMD_ARGC > 3)
|
||||||
|
@ -741,14 +790,26 @@ COMMAND_HANDLER(handle_flash_verify_bank_command)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_file = malloc(filesize);
|
length = MIN(filesize, p->size - offset);
|
||||||
|
|
||||||
|
if (!length) {
|
||||||
|
LOG_INFO("Nothing to compare with flash bank");
|
||||||
|
fileio_close(fileio);
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length != filesize)
|
||||||
|
LOG_INFO("File content exceeds flash bank size. Only comparing the "
|
||||||
|
"first %zu bytes of the file", length);
|
||||||
|
|
||||||
|
buffer_file = malloc(length);
|
||||||
if (buffer_file == NULL) {
|
if (buffer_file == NULL) {
|
||||||
LOG_ERROR("Out of memory");
|
LOG_ERROR("Out of memory");
|
||||||
fileio_close(fileio);
|
fileio_close(fileio);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = fileio_read(fileio, filesize, buffer_file, &read_cnt);
|
retval = fileio_read(fileio, length, buffer_file, &read_cnt);
|
||||||
fileio_close(fileio);
|
fileio_close(fileio);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("File read failure");
|
LOG_ERROR("File read failure");
|
||||||
|
@ -756,20 +817,20 @@ COMMAND_HANDLER(handle_flash_verify_bank_command)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read_cnt != filesize) {
|
if (read_cnt != length) {
|
||||||
LOG_ERROR("Short read");
|
LOG_ERROR("Short read");
|
||||||
free(buffer_file);
|
free(buffer_file);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_flash = malloc(filesize);
|
buffer_flash = malloc(length);
|
||||||
if (buffer_flash == NULL) {
|
if (buffer_flash == NULL) {
|
||||||
LOG_ERROR("Out of memory");
|
LOG_ERROR("Out of memory");
|
||||||
free(buffer_file);
|
free(buffer_file);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = flash_driver_read(p, buffer_flash, offset, read_cnt);
|
retval = flash_driver_read(p, buffer_flash, offset, length);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("Flash read error");
|
LOG_ERROR("Flash read error");
|
||||||
free(buffer_flash);
|
free(buffer_flash);
|
||||||
|
@ -780,15 +841,15 @@ COMMAND_HANDLER(handle_flash_verify_bank_command)
|
||||||
if (duration_measure(&bench) == ERROR_OK)
|
if (duration_measure(&bench) == ERROR_OK)
|
||||||
command_print(CMD_CTX, "read %zd bytes from file %s and flash bank %u"
|
command_print(CMD_CTX, "read %zd bytes from file %s and flash bank %u"
|
||||||
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
|
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
|
||||||
read_cnt, CMD_ARGV[1], p->bank_number, offset,
|
length, CMD_ARGV[1], p->bank_number, offset,
|
||||||
duration_elapsed(&bench), duration_kbps(&bench, read_cnt));
|
duration_elapsed(&bench), duration_kbps(&bench, length));
|
||||||
|
|
||||||
differ = memcmp(buffer_file, buffer_flash, read_cnt);
|
differ = memcmp(buffer_file, buffer_flash, length);
|
||||||
command_print(CMD_CTX, "contents %s", differ ? "differ" : "match");
|
command_print(CMD_CTX, "contents %s", differ ? "differ" : "match");
|
||||||
if (differ) {
|
if (differ) {
|
||||||
uint32_t t;
|
uint32_t t;
|
||||||
int diffs = 0;
|
int diffs = 0;
|
||||||
for (t = 0; t < read_cnt; t++) {
|
for (t = 0; t < length; t++) {
|
||||||
if (buffer_flash[t] == buffer_file[t])
|
if (buffer_flash[t] == buffer_file[t])
|
||||||
continue;
|
continue;
|
||||||
command_print(CMD_CTX, "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x",
|
command_print(CMD_CTX, "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x",
|
||||||
|
@ -908,10 +969,9 @@ static const struct command_registration flash_exec_command_handlers[] = {
|
||||||
.name = "write_bank",
|
.name = "write_bank",
|
||||||
.handler = handle_flash_write_bank_command,
|
.handler = handle_flash_write_bank_command,
|
||||||
.mode = COMMAND_EXEC,
|
.mode = COMMAND_EXEC,
|
||||||
.usage = "bank_id filename offset",
|
.usage = "bank_id filename [offset]",
|
||||||
.help = "Write binary data from file to flash bank, "
|
.help = "Write binary data from file to flash bank. Allow optional "
|
||||||
"starting at specified byte offset from the "
|
"offset from beginning of the bank (defaults to zero).",
|
||||||
"beginning of the bank.",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "write_image",
|
.name = "write_image",
|
||||||
|
@ -926,10 +986,9 @@ static const struct command_registration flash_exec_command_handlers[] = {
|
||||||
.name = "read_bank",
|
.name = "read_bank",
|
||||||
.handler = handle_flash_read_bank_command,
|
.handler = handle_flash_read_bank_command,
|
||||||
.mode = COMMAND_EXEC,
|
.mode = COMMAND_EXEC,
|
||||||
.usage = "bank_id filename offset length",
|
.usage = "bank_id filename [offset [length]]",
|
||||||
.help = "Read binary data from flash bank to file, "
|
.help = "Read binary data from flash bank to file. Allow optional "
|
||||||
"starting at specified byte offset from the "
|
"offset from beginning of the bank (defaults to zero).",
|
||||||
"beginning of the bank.",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "verify_bank",
|
.name = "verify_bank",
|
||||||
|
|
|
@ -50,11 +50,12 @@ static int64_t current_time;
|
||||||
|
|
||||||
static int64_t start;
|
static int64_t start;
|
||||||
|
|
||||||
static const char * const log_strings[5] = {
|
static const char * const log_strings[6] = {
|
||||||
"User : ",
|
"User : ",
|
||||||
"Error: ",
|
"Error: ",
|
||||||
"Warn : ", /* want a space after each colon, all same width, colons aligned */
|
"Warn : ", /* want a space after each colon, all same width, colons aligned */
|
||||||
"Info : ",
|
"Info : ",
|
||||||
|
"Debug: ",
|
||||||
"Debug: "
|
"Debug: "
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -234,8 +235,8 @@ COMMAND_HANDLER(handle_debug_level_command)
|
||||||
if (CMD_ARGC == 1) {
|
if (CMD_ARGC == 1) {
|
||||||
int new_level;
|
int new_level;
|
||||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], new_level);
|
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], new_level);
|
||||||
if ((new_level > LOG_LVL_DEBUG) || (new_level < LOG_LVL_SILENT)) {
|
if ((new_level > LOG_LVL_DEBUG_IO) || (new_level < LOG_LVL_SILENT)) {
|
||||||
LOG_ERROR("level must be between %d and %d", LOG_LVL_SILENT, LOG_LVL_DEBUG);
|
LOG_ERROR("level must be between %d and %d", LOG_LVL_SILENT, LOG_LVL_DEBUG_IO);
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
debug_level = new_level;
|
debug_level = new_level;
|
||||||
|
@ -279,7 +280,8 @@ static struct command_registration log_command_handlers[] = {
|
||||||
.mode = COMMAND_ANY,
|
.mode = COMMAND_ANY,
|
||||||
.help = "Sets the verbosity level of debugging output. "
|
.help = "Sets the verbosity level of debugging output. "
|
||||||
"0 shows errors only; 1 adds warnings; "
|
"0 shows errors only; 1 adds warnings; "
|
||||||
"2 (default) adds other info; 3 adds debugging.",
|
"2 (default) adds other info; 3 adds debugging; "
|
||||||
|
"4 adds extra verbose debugging.",
|
||||||
.usage = "number",
|
.usage = "number",
|
||||||
},
|
},
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
|
@ -303,7 +305,7 @@ void log_init(void)
|
||||||
int retval = parse_int(debug_env, &value);
|
int retval = parse_int(debug_env, &value);
|
||||||
if (ERROR_OK == retval &&
|
if (ERROR_OK == retval &&
|
||||||
debug_level >= LOG_LVL_SILENT &&
|
debug_level >= LOG_LVL_SILENT &&
|
||||||
debug_level <= LOG_LVL_DEBUG)
|
debug_level <= LOG_LVL_DEBUG_IO)
|
||||||
debug_level = value;
|
debug_level = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
* LOG_LVL_WARNING - non-fatal errors, that may be resolved later
|
* LOG_LVL_WARNING - non-fatal errors, that may be resolved later
|
||||||
* LOG_LVL_INFO - state information, etc.
|
* LOG_LVL_INFO - state information, etc.
|
||||||
* LOG_LVL_DEBUG - debug statements, execution trace
|
* LOG_LVL_DEBUG - debug statements, execution trace
|
||||||
|
* LOG_LVL_DEBUG_IO - verbose debug, low-level I/O trace
|
||||||
*/
|
*/
|
||||||
enum log_levels {
|
enum log_levels {
|
||||||
LOG_LVL_SILENT = -3,
|
LOG_LVL_SILENT = -3,
|
||||||
|
@ -54,7 +55,8 @@ enum log_levels {
|
||||||
LOG_LVL_ERROR = 0,
|
LOG_LVL_ERROR = 0,
|
||||||
LOG_LVL_WARNING = 1,
|
LOG_LVL_WARNING = 1,
|
||||||
LOG_LVL_INFO = 2,
|
LOG_LVL_INFO = 2,
|
||||||
LOG_LVL_DEBUG = 3
|
LOG_LVL_DEBUG = 3,
|
||||||
|
LOG_LVL_DEBUG_IO = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
void log_printf(enum log_levels level, const char *file, unsigned line,
|
void log_printf(enum log_levels level, const char *file, unsigned line,
|
||||||
|
@ -102,6 +104,14 @@ extern int debug_level;
|
||||||
|
|
||||||
#define LOG_LEVEL_IS(FOO) ((debug_level) >= (FOO))
|
#define LOG_LEVEL_IS(FOO) ((debug_level) >= (FOO))
|
||||||
|
|
||||||
|
#define LOG_DEBUG_IO(expr ...) \
|
||||||
|
do { \
|
||||||
|
if (debug_level >= LOG_LVL_DEBUG_IO) \
|
||||||
|
log_printf_lf(LOG_LVL_DEBUG, \
|
||||||
|
__FILE__, __LINE__, __func__, \
|
||||||
|
expr); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define LOG_DEBUG(expr ...) \
|
#define LOG_DEBUG(expr ...) \
|
||||||
do { \
|
do { \
|
||||||
if (debug_level >= LOG_LVL_DEBUG) \
|
if (debug_level >= LOG_LVL_DEBUG) \
|
||||||
|
|
|
@ -596,7 +596,7 @@ static int cmsis_dap_swd_run_queue(void)
|
||||||
{
|
{
|
||||||
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
|
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
|
||||||
|
|
||||||
LOG_DEBUG("Executing %d queued transactions", pending_transfer_count);
|
LOG_DEBUG_IO("Executing %d queued transactions", pending_transfer_count);
|
||||||
|
|
||||||
if (queued_retval != ERROR_OK) {
|
if (queued_retval != ERROR_OK) {
|
||||||
LOG_DEBUG("Skipping due to previous errors: %d", queued_retval);
|
LOG_DEBUG("Skipping due to previous errors: %d", queued_retval);
|
||||||
|
@ -616,7 +616,7 @@ static int cmsis_dap_swd_run_queue(void)
|
||||||
uint8_t cmd = pending_transfers[i].cmd;
|
uint8_t cmd = pending_transfers[i].cmd;
|
||||||
uint32_t data = pending_transfers[i].data;
|
uint32_t data = pending_transfers[i].data;
|
||||||
|
|
||||||
LOG_DEBUG("%s %s reg %x %"PRIx32,
|
LOG_DEBUG_IO("%s %s reg %x %"PRIx32,
|
||||||
cmd & SWD_CMD_APnDP ? "AP" : "DP",
|
cmd & SWD_CMD_APnDP ? "AP" : "DP",
|
||||||
cmd & SWD_CMD_RnW ? "read" : "write",
|
cmd & SWD_CMD_RnW ? "read" : "write",
|
||||||
(cmd & SWD_CMD_A32) >> 1, data);
|
(cmd & SWD_CMD_A32) >> 1, data);
|
||||||
|
@ -674,7 +674,7 @@ static int cmsis_dap_swd_run_queue(void)
|
||||||
uint32_t tmp = data;
|
uint32_t tmp = data;
|
||||||
idx += 4;
|
idx += 4;
|
||||||
|
|
||||||
LOG_DEBUG("Read result: %"PRIx32, data);
|
LOG_DEBUG_IO("Read result: %"PRIx32, data);
|
||||||
|
|
||||||
/* Imitate posted AP reads */
|
/* Imitate posted AP reads */
|
||||||
if ((pending_transfers[i].cmd & SWD_CMD_APnDP) ||
|
if ((pending_transfers[i].cmd & SWD_CMD_APnDP) ||
|
||||||
|
|
|
@ -1109,12 +1109,12 @@ static void ftdi_swd_swdio_en(bool enable)
|
||||||
*/
|
*/
|
||||||
static int ftdi_swd_run_queue(void)
|
static int ftdi_swd_run_queue(void)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("Executing %zu queued transactions", swd_cmd_queue_length);
|
LOG_DEBUG_IO("Executing %zu queued transactions", swd_cmd_queue_length);
|
||||||
int retval;
|
int retval;
|
||||||
struct signal *led = find_signal_by_name("LED");
|
struct signal *led = find_signal_by_name("LED");
|
||||||
|
|
||||||
if (queued_retval != ERROR_OK) {
|
if (queued_retval != ERROR_OK) {
|
||||||
LOG_DEBUG("Skipping due to previous errors: %d", queued_retval);
|
LOG_DEBUG_IO("Skipping due to previous errors: %d", queued_retval);
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1135,7 +1135,7 @@ static int ftdi_swd_run_queue(void)
|
||||||
for (size_t i = 0; i < swd_cmd_queue_length; i++) {
|
for (size_t i = 0; i < swd_cmd_queue_length; i++) {
|
||||||
int ack = buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1, 3);
|
int ack = buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1, 3);
|
||||||
|
|
||||||
LOG_DEBUG("%s %s %s reg %X = %08"PRIx32,
|
LOG_DEBUG_IO("%s %s %s reg %X = %08"PRIx32,
|
||||||
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
|
ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK",
|
||||||
swd_cmd_queue[i].cmd & SWD_CMD_APnDP ? "AP" : "DP",
|
swd_cmd_queue[i].cmd & SWD_CMD_APnDP ? "AP" : "DP",
|
||||||
swd_cmd_queue[i].cmd & SWD_CMD_RnW ? "read" : "write",
|
swd_cmd_queue[i].cmd & SWD_CMD_RnW ? "read" : "write",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2016 by Square, Inc. *
|
* Copyright (C) 2017 by Square, Inc. *
|
||||||
* Steven Stallion <stallion@squareup.com> *
|
* Steven Stallion <stallion@squareup.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 *
|
||||||
|
@ -20,34 +20,35 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "rtos.h"
|
#include <helper/types.h>
|
||||||
#include "rtos_standard_stackings.h"
|
#include <rtos/rtos.h>
|
||||||
#include "target/armv7m.h"
|
#include <rtos/rtos_standard_stackings.h>
|
||||||
|
#include <target/armv7m.h>
|
||||||
|
|
||||||
static const struct stack_register_offset rtos_uCOS_III_Cortex_M_stack_offsets[ARMV7M_NUM_CORE_REGS] = {
|
static const struct stack_register_offset rtos_uCOS_III_Cortex_M_stack_offsets[] = {
|
||||||
{ 0x20, 32 }, /* r0 */
|
{ 0x20, 32 }, /* r0 */
|
||||||
{ 0x24, 32 }, /* r1 */
|
{ 0x24, 32 }, /* r1 */
|
||||||
{ 0x28, 32 }, /* r2 */
|
{ 0x28, 32 }, /* r2 */
|
||||||
{ 0x2c, 32 }, /* r3 */
|
{ 0x2c, 32 }, /* r3 */
|
||||||
{ 0x00, 32 }, /* r4 */
|
{ 0x00, 32 }, /* r4 */
|
||||||
{ 0x04, 32 }, /* r5 */
|
{ 0x04, 32 }, /* r5 */
|
||||||
{ 0x08, 32 }, /* r6 */
|
{ 0x08, 32 }, /* r6 */
|
||||||
{ 0x0c, 32 }, /* r7 */
|
{ 0x0c, 32 }, /* r7 */
|
||||||
{ 0x10, 32 }, /* r8 */
|
{ 0x10, 32 }, /* r8 */
|
||||||
{ 0x14, 32 }, /* r9 */
|
{ 0x14, 32 }, /* r9 */
|
||||||
{ 0x18, 32 }, /* r10 */
|
{ 0x18, 32 }, /* r10 */
|
||||||
{ 0x1c, 32 }, /* r11 */
|
{ 0x1c, 32 }, /* r11 */
|
||||||
{ 0x30, 32 }, /* r12 */
|
{ 0x30, 32 }, /* r12 */
|
||||||
{ -2, 32 }, /* sp */
|
{ -2, 32 }, /* sp */
|
||||||
{ 0x34, 32 }, /* lr */
|
{ 0x34, 32 }, /* lr */
|
||||||
{ 0x38, 32 }, /* pc */
|
{ 0x38, 32 }, /* pc */
|
||||||
{ 0x3c, 32 }, /* xPSR */
|
{ 0x3c, 32 }, /* xPSR */
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct rtos_register_stacking rtos_uCOS_III_Cortex_M_stacking = {
|
const struct rtos_register_stacking rtos_uCOS_III_Cortex_M_stacking = {
|
||||||
0x40, /* stack_registers_size */
|
0x40, /* stack_registers_size */
|
||||||
-1, /* stack_growth_direction */
|
-1, /* stack_growth_direction */
|
||||||
ARMV7M_NUM_CORE_REGS, /* num_output_registers */
|
ARRAY_SIZE(rtos_uCOS_III_Cortex_M_stack_offsets), /* num_output_registers */
|
||||||
rtos_generic_stack_align8, /* stack_alignment */
|
rtos_generic_stack_align8, /* stack_alignment */
|
||||||
rtos_uCOS_III_Cortex_M_stack_offsets /* register_offsets */
|
rtos_uCOS_III_Cortex_M_stack_offsets /* register_offsets */
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2016 by Square, Inc. *
|
* Copyright (C) 2017 by Square, Inc. *
|
||||||
* Steven Stallion <stallion@squareup.com> *
|
* Steven Stallion <stallion@squareup.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 *
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "rtos.h"
|
#include <rtos/rtos.h>
|
||||||
|
|
||||||
extern const struct rtos_register_stacking rtos_uCOS_III_Cortex_M_stacking;
|
extern const struct rtos_register_stacking rtos_uCOS_III_Cortex_M_stacking;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2016 by Square, Inc. *
|
* Copyright (C) 2017 by Square, Inc. *
|
||||||
* Steven Stallion <stallion@squareup.com> *
|
* Steven Stallion <stallion@squareup.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 *
|
||||||
|
@ -20,14 +20,14 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <helper/log.h>
|
||||||
#include <helper/time_support.h>
|
#include <helper/time_support.h>
|
||||||
#include <jtag/jtag.h>
|
#include <helper/types.h>
|
||||||
#include "target/target.h"
|
#include <rtos/rtos.h>
|
||||||
#include "target/target_type.h"
|
#include <target/target.h>
|
||||||
#include "rtos.h"
|
#include <target/target_type.h>
|
||||||
#include "helper/log.h"
|
|
||||||
#include "helper/types.h"
|
#include "rtos_ucos_iii_stackings.h"
|
||||||
#include "rtos/rtos_ucos_iii_stackings.h"
|
|
||||||
|
|
||||||
#ifndef UCOS_III_MAX_STRLEN
|
#ifndef UCOS_III_MAX_STRLEN
|
||||||
#define UCOS_III_MAX_STRLEN 64
|
#define UCOS_III_MAX_STRLEN 64
|
||||||
|
@ -55,18 +55,18 @@ struct uCOS_III_params {
|
||||||
|
|
||||||
static const struct uCOS_III_params uCOS_III_params_list[] = {
|
static const struct uCOS_III_params uCOS_III_params_list[] = {
|
||||||
{
|
{
|
||||||
"cortex_m", /* target_name */
|
"cortex_m", /* target_name */
|
||||||
sizeof(uint32_t), /* pointer_width */
|
sizeof(uint32_t), /* pointer_width */
|
||||||
0, /* thread_stack_offset */
|
0, /* thread_stack_offset */
|
||||||
0, /* thread_name_offset */
|
0, /* thread_name_offset */
|
||||||
0, /* thread_state_offset */
|
0, /* thread_state_offset */
|
||||||
0, /* thread_priority_offset */
|
0, /* thread_priority_offset */
|
||||||
0, /* thread_prev_offset */
|
0, /* thread_prev_offset */
|
||||||
0, /* thread_next_offset */
|
0, /* thread_next_offset */
|
||||||
false, /* thread_offsets_updated */
|
false, /* thread_offsets_updated */
|
||||||
1, /* threadid_start */
|
1, /* threadid_start */
|
||||||
&rtos_uCOS_III_Cortex_M_stacking, /* stacking_info */
|
&rtos_uCOS_III_Cortex_M_stacking, /* stacking_info */
|
||||||
0, /* num_threads */
|
0, /* num_threads */
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -159,10 +159,10 @@ static int uCOS_III_find_last_thread_address(struct rtos *rtos, symbol_address_t
|
||||||
symbol_address_t thread_list_address = 0;
|
symbol_address_t thread_list_address = 0;
|
||||||
|
|
||||||
retval = target_read_memory(rtos->target,
|
retval = target_read_memory(rtos->target,
|
||||||
rtos->symbols[uCOS_III_VAL_OSTaskDbgListPtr].address,
|
rtos->symbols[uCOS_III_VAL_OSTaskDbgListPtr].address,
|
||||||
params->pointer_width,
|
params->pointer_width,
|
||||||
1,
|
1,
|
||||||
(void *)&thread_list_address);
|
(void *)&thread_list_address);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("uCOS-III: failed to read thread list address");
|
LOG_ERROR("uCOS-III: failed to read thread list address");
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -173,10 +173,10 @@ static int uCOS_III_find_last_thread_address(struct rtos *rtos, symbol_address_t
|
||||||
*thread_address = thread_list_address;
|
*thread_address = thread_list_address;
|
||||||
|
|
||||||
retval = target_read_memory(rtos->target,
|
retval = target_read_memory(rtos->target,
|
||||||
thread_list_address + params->thread_next_offset,
|
thread_list_address + params->thread_next_offset,
|
||||||
params->pointer_width,
|
params->pointer_width,
|
||||||
1,
|
1,
|
||||||
(void *)&thread_list_address);
|
(void *)&thread_list_address);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("uCOS-III: failed to read next thread address");
|
LOG_ERROR("uCOS-III: failed to read next thread address");
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -227,10 +227,10 @@ static int uCOS_III_update_thread_offsets(struct rtos *rtos)
|
||||||
const struct thread_offset_map *thread_offset_map = &thread_offset_maps[i];
|
const struct thread_offset_map *thread_offset_map = &thread_offset_maps[i];
|
||||||
|
|
||||||
int retval = target_read_memory(rtos->target,
|
int retval = target_read_memory(rtos->target,
|
||||||
rtos->symbols[thread_offset_map->symbol_value].address,
|
rtos->symbols[thread_offset_map->symbol_value].address,
|
||||||
params->pointer_width,
|
params->pointer_width,
|
||||||
1,
|
1,
|
||||||
(void *)thread_offset_map->thread_offset);
|
(void *)thread_offset_map->thread_offset);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("uCOS-III: failed to read thread offset");
|
LOG_ERROR("uCOS-III: failed to read thread offset");
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -244,7 +244,7 @@ static int uCOS_III_update_thread_offsets(struct rtos *rtos)
|
||||||
static int uCOS_III_detect_rtos(struct target *target)
|
static int uCOS_III_detect_rtos(struct target *target)
|
||||||
{
|
{
|
||||||
return target->rtos->symbols != NULL &&
|
return target->rtos->symbols != NULL &&
|
||||||
target->rtos->symbols[uCOS_III_VAL_OSRunning].address != 0;
|
target->rtos->symbols[uCOS_III_VAL_OSRunning].address != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uCOS_III_reset_handler(struct target *target, enum target_reset_mode reset_mode, void *priv)
|
static int uCOS_III_reset_handler(struct target *target, enum target_reset_mode reset_mode, void *priv)
|
||||||
|
@ -263,8 +263,7 @@ static int uCOS_III_create(struct target *target)
|
||||||
|
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(uCOS_III_params_list); i++)
|
for (size_t i = 0; i < ARRAY_SIZE(uCOS_III_params_list); i++)
|
||||||
if (strcmp(uCOS_III_params_list[i].target_name, target->type->name) == 0) {
|
if (strcmp(uCOS_III_params_list[i].target_name, target->type->name) == 0) {
|
||||||
params = malloc(sizeof(*params) +
|
params = malloc(sizeof(*params) + (UCOS_III_MAX_THREADS * sizeof(*params->threads)));
|
||||||
UCOS_III_MAX_THREADS * sizeof(*params->threads));
|
|
||||||
if (params == NULL) {
|
if (params == NULL) {
|
||||||
LOG_ERROR("uCOS-III: out of memory");
|
LOG_ERROR("uCOS-III: out of memory");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
@ -294,13 +293,18 @@ static int uCOS_III_update_threads(struct rtos *rtos)
|
||||||
uint8_t rtos_running;
|
uint8_t rtos_running;
|
||||||
|
|
||||||
retval = target_read_u8(rtos->target,
|
retval = target_read_u8(rtos->target,
|
||||||
rtos->symbols[uCOS_III_VAL_OSRunning].address,
|
rtos->symbols[uCOS_III_VAL_OSRunning].address,
|
||||||
&rtos_running);
|
&rtos_running);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("uCOS-III: failed to read RTOS running");
|
LOG_ERROR("uCOS-III: failed to read RTOS running");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rtos_running != 1 && rtos_running != 0) {
|
||||||
|
LOG_ERROR("uCOS-III: invalid RTOS running value");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!rtos_running) {
|
if (!rtos_running) {
|
||||||
rtos->thread_details = calloc(1, sizeof(struct thread_detail));
|
rtos->thread_details = calloc(1, sizeof(struct thread_detail));
|
||||||
if (rtos->thread_details == NULL) {
|
if (rtos->thread_details == NULL) {
|
||||||
|
@ -327,10 +331,10 @@ static int uCOS_III_update_threads(struct rtos *rtos)
|
||||||
symbol_address_t current_thread_address = 0;
|
symbol_address_t current_thread_address = 0;
|
||||||
|
|
||||||
retval = target_read_memory(rtos->target,
|
retval = target_read_memory(rtos->target,
|
||||||
rtos->symbols[uCOS_III_VAL_OSTCBCurPtr].address,
|
rtos->symbols[uCOS_III_VAL_OSTCBCurPtr].address,
|
||||||
params->pointer_width,
|
params->pointer_width,
|
||||||
1,
|
1,
|
||||||
(void *)¤t_thread_address);
|
(void *)¤t_thread_address);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("uCOS-III: failed to read current thread address");
|
LOG_ERROR("uCOS-III: failed to read current thread address");
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -338,8 +342,8 @@ static int uCOS_III_update_threads(struct rtos *rtos)
|
||||||
|
|
||||||
/* read number of tasks */
|
/* read number of tasks */
|
||||||
retval = target_read_u16(rtos->target,
|
retval = target_read_u16(rtos->target,
|
||||||
rtos->symbols[uCOS_III_VAL_OSTaskQty].address,
|
rtos->symbols[uCOS_III_VAL_OSTaskQty].address,
|
||||||
(void *)&rtos->thread_count);
|
(void *)&rtos->thread_count);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("uCOS-III: failed to read thread count");
|
LOG_ERROR("uCOS-III: failed to read thread count");
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -368,9 +372,7 @@ static int uCOS_III_update_threads(struct rtos *rtos)
|
||||||
char thread_str_buffer[UCOS_III_MAX_STRLEN + 1];
|
char thread_str_buffer[UCOS_III_MAX_STRLEN + 1];
|
||||||
|
|
||||||
/* find or create new threadid */
|
/* find or create new threadid */
|
||||||
retval = uCOS_III_find_or_create_thread(rtos,
|
retval = uCOS_III_find_or_create_thread(rtos, thread_address, &thread_detail->threadid);
|
||||||
thread_address,
|
|
||||||
&thread_detail->threadid);
|
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("uCOS-III: failed to find or create thread");
|
LOG_ERROR("uCOS-III: failed to find or create thread");
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -385,19 +387,19 @@ static int uCOS_III_update_threads(struct rtos *rtos)
|
||||||
symbol_address_t thread_name_address = 0;
|
symbol_address_t thread_name_address = 0;
|
||||||
|
|
||||||
retval = target_read_memory(rtos->target,
|
retval = target_read_memory(rtos->target,
|
||||||
thread_address + params->thread_name_offset,
|
thread_address + params->thread_name_offset,
|
||||||
params->pointer_width,
|
params->pointer_width,
|
||||||
1,
|
1,
|
||||||
(void *)&thread_name_address);
|
(void *)&thread_name_address);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("uCOS-III: failed to name address");
|
LOG_ERROR("uCOS-III: failed to name address");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = target_read_buffer(rtos->target,
|
retval = target_read_buffer(rtos->target,
|
||||||
thread_name_address,
|
thread_name_address,
|
||||||
sizeof(thread_str_buffer),
|
sizeof(thread_str_buffer),
|
||||||
(void *)thread_str_buffer);
|
(void *)thread_str_buffer);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("uCOS-III: failed to read thread name");
|
LOG_ERROR("uCOS-III: failed to read thread name");
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -411,16 +413,16 @@ static int uCOS_III_update_threads(struct rtos *rtos)
|
||||||
uint8_t thread_priority;
|
uint8_t thread_priority;
|
||||||
|
|
||||||
retval = target_read_u8(rtos->target,
|
retval = target_read_u8(rtos->target,
|
||||||
thread_address + params->thread_state_offset,
|
thread_address + params->thread_state_offset,
|
||||||
&thread_state);
|
&thread_state);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("uCOS-III: failed to read thread state");
|
LOG_ERROR("uCOS-III: failed to read thread state");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = target_read_u8(rtos->target,
|
retval = target_read_u8(rtos->target,
|
||||||
thread_address + params->thread_priority_offset,
|
thread_address + params->thread_priority_offset,
|
||||||
&thread_priority);
|
&thread_priority);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("uCOS-III: failed to read thread priority");
|
LOG_ERROR("uCOS-III: failed to read thread priority");
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -434,15 +436,15 @@ static int uCOS_III_update_threads(struct rtos *rtos)
|
||||||
thread_state_str = "Unknown";
|
thread_state_str = "Unknown";
|
||||||
|
|
||||||
snprintf(thread_str_buffer, sizeof(thread_str_buffer), "State: %s, Priority: %d",
|
snprintf(thread_str_buffer, sizeof(thread_str_buffer), "State: %s, Priority: %d",
|
||||||
thread_state_str, thread_priority);
|
thread_state_str, thread_priority);
|
||||||
thread_detail->extra_info_str = strdup(thread_str_buffer);
|
thread_detail->extra_info_str = strdup(thread_str_buffer);
|
||||||
|
|
||||||
/* read previous thread address */
|
/* read previous thread address */
|
||||||
retval = target_read_memory(rtos->target,
|
retval = target_read_memory(rtos->target,
|
||||||
thread_address + params->thread_prev_offset,
|
thread_address + params->thread_prev_offset,
|
||||||
params->pointer_width,
|
params->pointer_width,
|
||||||
1,
|
1,
|
||||||
(void *)&thread_address);
|
(void *)&thread_address);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("uCOS-III: failed to read previous thread address");
|
LOG_ERROR("uCOS-III: failed to read previous thread address");
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -470,19 +472,19 @@ static int uCOS_III_get_thread_reg_list(struct rtos *rtos, threadid_t threadid,
|
||||||
symbol_address_t stack_address = 0;
|
symbol_address_t stack_address = 0;
|
||||||
|
|
||||||
retval = target_read_memory(rtos->target,
|
retval = target_read_memory(rtos->target,
|
||||||
thread_address + params->thread_stack_offset,
|
thread_address + params->thread_stack_offset,
|
||||||
params->pointer_width,
|
params->pointer_width,
|
||||||
1,
|
1,
|
||||||
(void *)&stack_address);
|
(void *)&stack_address);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("uCOS-III: failed to read stack address");
|
LOG_ERROR("uCOS-III: failed to read stack address");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rtos_generic_stack_read(rtos->target,
|
return rtos_generic_stack_read(rtos->target,
|
||||||
params->stacking_info,
|
params->stacking_info,
|
||||||
stack_address,
|
stack_address,
|
||||||
hex_reg_list);
|
hex_reg_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uCOS_III_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
static int uCOS_III_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
|
||||||
|
|
|
@ -3037,16 +3037,16 @@ static void handle_md_output(struct command_context *cmd_ctx,
|
||||||
const char *value_fmt;
|
const char *value_fmt;
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 8:
|
case 8:
|
||||||
value_fmt = "%16.16llx ";
|
value_fmt = "%16.16"PRIx64" ";
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
value_fmt = "%8.8x ";
|
value_fmt = "%8.8"PRIx64" ";
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
value_fmt = "%4.4x ";
|
value_fmt = "%4.4"PRIx64" ";
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
value_fmt = "%2.2x ";
|
value_fmt = "%2.2"PRIx64" ";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* "can't happen", caller checked */
|
/* "can't happen", caller checked */
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
#
|
|
||||||
# Freescale Kinetis KE02 devices
|
|
||||||
#
|
|
||||||
|
|
||||||
set CHIPNAME ke02
|
|
||||||
source [find target/kex.cfg]
|
|
|
@ -1,6 +0,0 @@
|
||||||
#
|
|
||||||
# Freescale Kinetis KE04 devices
|
|
||||||
#
|
|
||||||
|
|
||||||
set CHIPNAME ke04
|
|
||||||
source [find target/kex.cfg]
|
|
|
@ -1,6 +0,0 @@
|
||||||
#
|
|
||||||
# Freescale Kinetis KE06 devices
|
|
||||||
#
|
|
||||||
|
|
||||||
set CHIPNAME ke06
|
|
||||||
source [find target/kex.cfg]
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Freescale Kinetis KE series devices
|
# Freescale Kinetis KE0x series devices
|
||||||
#
|
#
|
||||||
|
|
||||||
source [find target/swj-dp.tcl]
|
source [find target/swj-dp.tcl]
|
||||||
|
@ -21,11 +21,7 @@ if { [info exists WORKAREASIZE] } {
|
||||||
if { [info exists CPUTAPID] } {
|
if { [info exists CPUTAPID] } {
|
||||||
set _CPUTAPID $CPUTAPID
|
set _CPUTAPID $CPUTAPID
|
||||||
} else {
|
} else {
|
||||||
if { [using_jtag] } {
|
set _CPUTAPID 0x0bc11477
|
||||||
set _CPUTAPID 0x4ba00477
|
|
||||||
} {
|
|
||||||
set _CPUTAPID 0x2ba01477
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
|
swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
|
|
@ -0,0 +1,7 @@
|
||||||
|
#
|
||||||
|
# NXP (Freescale) Kinetis KE1xF devices
|
||||||
|
#
|
||||||
|
|
||||||
|
set CHIPNAME ke
|
||||||
|
|
||||||
|
source [find target/kx.cfg]
|
|
@ -0,0 +1,7 @@
|
||||||
|
#
|
||||||
|
# NXP (Freescale) Kinetis KE1xZ devices
|
||||||
|
#
|
||||||
|
|
||||||
|
set CHIPNAME ke
|
||||||
|
|
||||||
|
source [find target/klx.cfg]
|
|
@ -1,5 +1,6 @@
|
||||||
#
|
#
|
||||||
# Freescale Kinetis KL series devices
|
# NXP (former Freescale) Kinetis KL series devices
|
||||||
|
# Also used for Cortex-M0+ equipped members of KVx and KE1xZ series
|
||||||
#
|
#
|
||||||
|
|
||||||
source [find target/swj-dp.tcl]
|
source [find target/swj-dp.tcl]
|
||||||
|
@ -31,11 +32,13 @@ target create $_TARGETNAME cortex_m -chain-position $_CHIPNAME.cpu
|
||||||
|
|
||||||
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
||||||
|
|
||||||
set _FLASHNAME $_CHIPNAME.flash
|
set _FLASHNAME $_CHIPNAME.pflash
|
||||||
flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME
|
flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME
|
||||||
|
kinetis create_banks
|
||||||
|
|
||||||
# Table 5-1. Clock Summary of KL25 Sub-Family Reference Manual
|
# Table 5-1. Clock Summary of KL25 Sub-Family Reference Manual
|
||||||
# specifies up to 1MHz for VLPR mode.
|
# specifies up to 1MHz for VLPR mode and up to 24MHz for run mode;
|
||||||
|
# Table 17 of Sub-Family Data Sheet rev4 lists 25MHz as the maximum frequency.
|
||||||
adapter_khz 1000
|
adapter_khz 1000
|
||||||
|
|
||||||
reset_config srst_nogate
|
reset_config srst_nogate
|
||||||
|
@ -51,10 +54,9 @@ if {![using_hla]} {
|
||||||
cortex_m reset_config sysresetreq
|
cortex_m reset_config sysresetreq
|
||||||
}
|
}
|
||||||
|
|
||||||
# Table 5-1. Clock Summary of KL25 Sub-Family Reference Manual
|
# Disable watchdog not to disturb OpenOCD algorithms running on MCU
|
||||||
# specifies up to 24MHz for run mode; Table 17 of Sub-Family Data
|
# (e.g. armv7m_checksum_memory() in verify_image)
|
||||||
# Sheet rev4 lists 25MHz as the maximum frequency.
|
# Flash driver also disables watchdog before FTFA flash programming.
|
||||||
# Uncoment only if VLPR mode is not used
|
$_TARGETNAME configure -event reset-init {
|
||||||
#$_TARGETNAME configure -event reset-init {
|
kinetis disable_wdog
|
||||||
# adapter_khz 24000
|
}
|
||||||
#}
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#
|
#
|
||||||
# Freescale Kinetis Kx series devices
|
# NXP (former Freescale) Kinetis Kx series devices
|
||||||
|
# Also used for Cortex-M4 equipped members of KVx and KE1xF series
|
||||||
#
|
#
|
||||||
|
|
||||||
source [find target/swj-dp.tcl]
|
source [find target/swj-dp.tcl]
|
||||||
|
@ -35,8 +36,9 @@ target create $_TARGETNAME cortex_m -chain-position $_CHIPNAME.cpu
|
||||||
|
|
||||||
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
||||||
|
|
||||||
set _FLASHNAME $_CHIPNAME.flash
|
set _FLASHNAME $_CHIPNAME.pflash
|
||||||
flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME
|
flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME
|
||||||
|
kinetis create_banks
|
||||||
|
|
||||||
adapter_khz 1000
|
adapter_khz 1000
|
||||||
|
|
||||||
|
@ -52,3 +54,11 @@ if {![using_hla]} {
|
||||||
# perform a soft reset
|
# perform a soft reset
|
||||||
cortex_m reset_config sysresetreq
|
cortex_m reset_config sysresetreq
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Disable watchdog not to disturb OpenOCD algorithms running on MCU
|
||||||
|
# (e.g. armv7m_checksum_memory() in verify_image)
|
||||||
|
# Flash driver also disables watchdog before FTFA flash programming.
|
||||||
|
$_TARGETNAME configure -event reset-init {
|
||||||
|
kinetis disable_wdog
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,8 @@ set _TARGETNAME $_CHIPNAME.cpu
|
||||||
jtag newtap zynq_pl bs -irlen 6 -ircapture 0x1 -irmask 0x03 \
|
jtag newtap zynq_pl bs -irlen 6 -ircapture 0x1 -irmask 0x03 \
|
||||||
-expected-id 0x23727093 \
|
-expected-id 0x23727093 \
|
||||||
-expected-id 0x13722093 \
|
-expected-id 0x13722093 \
|
||||||
-expected-id 0x03727093
|
-expected-id 0x03727093 \
|
||||||
|
-expected-id 0x03736093
|
||||||
|
|
||||||
jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id 0x4ba00477
|
jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id 0x4ba00477
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue