Merge commit '59dc1b7eb4f3a0fda23d2c8624c3ecd26515fec8' into sam-update
# Conflicts: # src/platforms/common/cdcacm.c
This commit is contained in:
commit
c73329f7d4
@ -275,9 +275,18 @@ bool cmd_swdp_scan(target *t, int argc, char **argv)
|
||||
static void display_target(int i, target *t, void *context)
|
||||
{
|
||||
(void)context;
|
||||
gdb_outf("%2d %c %s %s\n", i, target_attached(t)?'*':' ',
|
||||
target_driver_name(t),
|
||||
(target_core_name(t)) ? target_core_name(t): "");
|
||||
if (!strcmp(target_driver_name(t), "ARM Cortex-M")) {
|
||||
gdb_outf("***%2d%sUnknown %s Designer %3x Partno %3x %s\n",
|
||||
i, target_attached(t)?" * ":" ",
|
||||
target_driver_name(t),
|
||||
target_designer(t),
|
||||
target_idcode(t),
|
||||
(target_core_name(t)) ? target_core_name(t): "");
|
||||
} else {
|
||||
gdb_outf("%2d %c %s %s\n", i, target_attached(t)?'*':' ',
|
||||
target_driver_name(t),
|
||||
(target_core_name(t)) ? target_core_name(t): "");
|
||||
}
|
||||
}
|
||||
|
||||
bool cmd_targets(target *t, int argc, char **argv)
|
||||
|
@ -45,6 +45,5 @@ bool platform_srst_get_val(void);
|
||||
bool platform_target_get_power(void);
|
||||
void platform_target_set_power(bool power);
|
||||
void platform_request_boot(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -51,6 +51,8 @@ void target_detach(target *t);
|
||||
bool target_attached(target *t);
|
||||
const char *target_driver_name(target *t);
|
||||
const char *target_core_name(target *t);
|
||||
unsigned int target_designer(target *t);
|
||||
unsigned int target_idcode(target *t);
|
||||
|
||||
/* Memory access functions */
|
||||
bool target_mem_map(target *t, char *buf, size_t len);
|
||||
|
@ -58,8 +58,8 @@ static const struct usb_device_descriptor dev = {
|
||||
.bDeviceClass = 0xEF, /* Miscellaneous Device */
|
||||
.bDeviceSubClass = 2, /* Common Class */
|
||||
.bDeviceProtocol = 1, /* Interface Association */
|
||||
#ifdef SAMD21E17
|
||||
.bMaxPacketSize0 = 64,
|
||||
#if defined(SAMD21E17) || defined(LM4F)
|
||||
.bMaxPacketSize0 = 64, /*Fixed for icdi*/
|
||||
#else
|
||||
.bMaxPacketSize0 = 32,
|
||||
#endif
|
||||
|
@ -345,6 +345,17 @@ void remote_adiv5_dp_defaults(ADIv5_DP_t *dp)
|
||||
"Please update BMP firmware for substantial speed increase!\n");
|
||||
return;
|
||||
}
|
||||
if (dp->dp_jd_index < JTAG_MAX_DEVS) {
|
||||
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, REMOTE_HL_JTAG_DEV_STR,
|
||||
dp->dp_jd_index);
|
||||
platform_buffer_write(construct, s);
|
||||
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
|
||||
if ((!s) || (construct[0] != REMOTE_RESP_OK)) {
|
||||
DEBUG_WARN(
|
||||
"Please update BMP firmware to allow high level jtag commands!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
dp->low_access = remote_adiv5_low_access;
|
||||
dp->dp_read = remote_adiv5_dp_read;
|
||||
dp->ap_write = remote_adiv5_ap_write;
|
||||
@ -352,3 +363,20 @@ void remote_adiv5_dp_defaults(ADIv5_DP_t *dp)
|
||||
dp->mem_read = remote_ap_mem_read;
|
||||
dp->mem_write_sized = remote_ap_mem_write_sized;
|
||||
}
|
||||
|
||||
void remote_add_jtag_dev(int i, const jtag_dev_t *jtag_dev)
|
||||
{
|
||||
uint8_t construct[REMOTE_MAX_MSG_SIZE];
|
||||
int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,
|
||||
REMOTE_JTAG_ADD_DEV_STR,
|
||||
i,
|
||||
jtag_dev->dr_prescan,
|
||||
jtag_dev->dr_postscan,
|
||||
jtag_dev->ir_len,
|
||||
jtag_dev->ir_prescan,
|
||||
jtag_dev->ir_postscan,
|
||||
jtag_dev->current_ir);
|
||||
platform_buffer_write(construct, s);
|
||||
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
|
||||
/* No check for error here. Done in remote_adiv5_dp_defaults!*/
|
||||
}
|
||||
|
@ -39,5 +39,6 @@ void remote_srst_set_val(bool assert);
|
||||
bool remote_srst_get_val(void);
|
||||
const char *platform_target_voltage(void);
|
||||
void remote_adiv5_dp_defaults(ADIv5_DP_t *dp);
|
||||
void remote_add_jtag_dev(int i, const jtag_dev_t *jtag_dev);
|
||||
#define __BMP_REMOTE_H_
|
||||
#endif
|
||||
|
@ -47,11 +47,11 @@ uint8_t mode;
|
||||
/*- Variables ---------------------------------------------------------------*/
|
||||
static hid_device *handle = NULL;
|
||||
static uint8_t hid_buffer[1024 + 1];
|
||||
static int report_size = 512 + 1; // TODO: read actual report size
|
||||
static int report_size = 64 + 1; // TODO: read actual report size
|
||||
/* LPC845 Breakout Board Rev. 0 report invalid response with > 65 bytes */
|
||||
int dap_init(bmp_info_t *info)
|
||||
{
|
||||
printf("dap_init\n");
|
||||
DEBUG_INFO("dap_init\n");
|
||||
if (hid_init())
|
||||
return -1;
|
||||
int size = strlen(info->serial);
|
||||
@ -129,14 +129,7 @@ static uint32_t dap_dp_low_access(struct ADIv5_DP_s *dp, uint8_t RnW,
|
||||
|
||||
static uint32_t dap_dp_read_reg(ADIv5_DP_t *dp, uint16_t addr)
|
||||
{
|
||||
uint32_t res;
|
||||
if (addr & ADIV5_APnDP) {
|
||||
dap_dp_low_access(dp, ADIV5_LOW_READ, addr, 0);
|
||||
res = dap_dp_low_access(dp, ADIV5_LOW_READ,
|
||||
ADIV5_DP_RDBUFF, 0);
|
||||
} else {
|
||||
res = dap_dp_low_access(dp, ADIV5_LOW_READ, addr, 0);
|
||||
}
|
||||
uint32_t res = dap_dp_low_access(dp, ADIV5_LOW_READ, addr, 0);
|
||||
DEBUG_PROBE("dp_read %04x %08" PRIx32 "\n", addr, res);
|
||||
return res;
|
||||
}
|
||||
|
@ -339,8 +339,7 @@ uint32_t dap_read_reg(ADIv5_DP_t *dp, uint8_t reg)
|
||||
{
|
||||
uint8_t buf[8];
|
||||
uint8_t dap_index = 0;
|
||||
if (dp->dev)
|
||||
dap_index = dp->dev->dev;
|
||||
dap_index = dp->dp_jd_index;
|
||||
buf[0] = ID_DAP_TRANSFER;
|
||||
buf[1] = dap_index;
|
||||
buf[2] = 0x01; // Request size
|
||||
@ -358,8 +357,7 @@ void dap_write_reg(ADIv5_DP_t *dp, uint8_t reg, uint32_t data)
|
||||
|
||||
buf[0] = ID_DAP_TRANSFER;
|
||||
uint8_t dap_index = 0;
|
||||
if (dp->dev)
|
||||
dap_index = dp->dev->dev;
|
||||
dap_index = dp->dp_jd_index;
|
||||
buf[1] = dap_index;
|
||||
buf[2] = 0x01; // Request size
|
||||
buf[3] = reg & ~DAP_TRANSFER_RnW;;
|
||||
@ -390,17 +388,16 @@ unsigned int dap_read_block(ADIv5_AP_t *ap, void *dest, uint32_t src,
|
||||
uint8_t buf[1024];
|
||||
unsigned int sz = len >> align;
|
||||
uint8_t dap_index = 0;
|
||||
if (ap->dp->dev)
|
||||
dap_index = ap->dp->dev->dev;
|
||||
dap_index = ap->dp->dp_jd_index;
|
||||
buf[0] = ID_DAP_TRANSFER_BLOCK;
|
||||
buf[1] = dap_index;
|
||||
buf[2] = sz & 0xff;
|
||||
buf[3] = (sz >> 8) & 0xff;
|
||||
buf[4] = SWD_AP_DRW | DAP_TRANSFER_RnW;
|
||||
dbg_dap_cmd(buf, 1023, 5 + 1);
|
||||
dbg_dap_cmd(buf, 1023, 5);
|
||||
unsigned int transferred = buf[0] + (buf[1] << 8);
|
||||
if (buf[2] >= DAP_TRANSFER_FAULT) {
|
||||
DEBUG_WARN("dap_read_block @ %08 "PRIx32 " fault -> line reset\n", src);
|
||||
DEBUG_WARN("dap_read_block @ %08" PRIx32 " fault -> line reset\n", src);
|
||||
dap_line_reset();
|
||||
}
|
||||
if (sz != transferred) {
|
||||
@ -426,8 +423,7 @@ unsigned int dap_write_block(ADIv5_AP_t *ap, uint32_t dest, const void *src,
|
||||
uint8_t buf[1024];
|
||||
unsigned int sz = len >> align;
|
||||
uint8_t dap_index = 0;
|
||||
if (ap->dp->dev)
|
||||
dap_index = ap->dp->dev->dev;
|
||||
dap_index = ap->dp->dp_jd_index;
|
||||
buf[0] = ID_DAP_TRANSFER_BLOCK;
|
||||
buf[1] = dap_index;
|
||||
buf[2] = sz & 0xff;
|
||||
@ -527,8 +523,7 @@ static uint8_t *mem_access_setup(ADIv5_AP_t *ap, uint8_t *p,
|
||||
break;
|
||||
}
|
||||
uint8_t dap_index = 0;
|
||||
if (ap->dp->dev)
|
||||
dap_index = ap->dp->dev->dev;
|
||||
dap_index = ap->dp->dp_jd_index;
|
||||
*p++ = ID_DAP_TRANSFER;
|
||||
*p++ = dap_index;
|
||||
*p++ = 3; /* Nr transfers */
|
||||
@ -563,8 +558,7 @@ uint32_t dap_ap_read(ADIv5_AP_t *ap, uint16_t addr)
|
||||
uint8_t buf[63], *p = buf;
|
||||
buf[0] = ID_DAP_TRANSFER;
|
||||
uint8_t dap_index = 0;
|
||||
if (ap->dp->dev)
|
||||
dap_index = ap->dp->dev->dev;
|
||||
dap_index = ap->dp->dp_jd_index;
|
||||
*p++ = ID_DAP_TRANSFER;
|
||||
*p++ = dap_index;
|
||||
*p++ = 2; /* Nr transfers */
|
||||
@ -584,8 +578,7 @@ void dap_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
|
||||
DEBUG_PROBE("dap_ap_write addr %04x value %08x\n", addr, value);
|
||||
uint8_t buf[63], *p = buf;
|
||||
uint8_t dap_index = 0;
|
||||
if (ap->dp->dev)
|
||||
dap_index = ap->dp->dev->dev;
|
||||
dap_index = ap->dp->dp_jd_index;
|
||||
*p++ = ID_DAP_TRANSFER;
|
||||
*p++ = dap_index;
|
||||
*p++ = 2; /* Nr transfers */
|
||||
|
@ -161,9 +161,13 @@ static int find_debuggers( BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
|
||||
}
|
||||
/* Either serial and/or ident_string match or are not given.
|
||||
* Check type.*/
|
||||
if ((desc.idVendor == VENDOR_ID_BMP) &&
|
||||
(desc.idProduct == PRODUCT_ID_BMP)) {
|
||||
type = BMP_TYPE_BMP;
|
||||
if (desc.idVendor == VENDOR_ID_BMP) {
|
||||
if (desc.idProduct == PRODUCT_ID_BMP) {
|
||||
type = BMP_TYPE_BMP;
|
||||
} else if (desc.idProduct == PRODUCT_ID_BMP_BL) {
|
||||
DEBUG_WARN("BMP in botloader mode found. Restart or reflash!\n");
|
||||
continue;
|
||||
}
|
||||
} else if ((strstr(manufacturer, "CMSIS")) || (strstr(product, "CMSIS"))) {
|
||||
type = BMP_TYPE_CMSIS_DAP;
|
||||
} else if (desc.idVendor == VENDOR_ID_STLINK) {
|
||||
@ -388,6 +392,12 @@ int platform_swdptap_init(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void platform_add_jtag_dev(int i, const jtag_dev_t *jtag_dev)
|
||||
{
|
||||
if (info.bmp_type == BMP_TYPE_BMP)
|
||||
remote_add_jtag_dev(i, jtag_dev);
|
||||
}
|
||||
|
||||
int platform_jtag_scan(const uint8_t *lrlens)
|
||||
{
|
||||
switch (info.bmp_type) {
|
||||
|
@ -15,6 +15,7 @@ void platform_buffer_flush(void);
|
||||
#define SET_RUN_STATE(x)
|
||||
|
||||
#define VENDOR_ID_BMP 0x1d50
|
||||
#define PRODUCT_ID_BMP_BL 0x6017
|
||||
#define PRODUCT_ID_BMP 0x6018
|
||||
|
||||
typedef enum bmp_type_s {
|
||||
|
@ -1041,13 +1041,13 @@ int jtag_scan_stlinkv2(bmp_info_t *info, const uint8_t *irlens)
|
||||
jtag_dev_count = stlink_read_idcodes(info, idcodes);
|
||||
/* Check for known devices and handle accordingly */
|
||||
for(int i = 0; i < jtag_dev_count; i++)
|
||||
jtag_devs[i].idcode = idcodes[i];
|
||||
jtag_devs[i].jd_idcode = idcodes[i];
|
||||
for(int i = 0; i < jtag_dev_count; i++)
|
||||
for(int j = 0; dev_descr[j].idcode; j++)
|
||||
if((jtag_devs[i].idcode & dev_descr[j].idmask) ==
|
||||
if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) ==
|
||||
dev_descr[j].idcode) {
|
||||
if(dev_descr[j].handler)
|
||||
dev_descr[j].handler(&jtag_devs[i]);
|
||||
dev_descr[j].handler(i, dev_descr[j].idcode);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -158,6 +158,7 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
|
||||
int c;
|
||||
opt->opt_target_dev = 1;
|
||||
opt->opt_flash_size = 16 * 1024 *1024;
|
||||
opt->opt_flash_start = 0xffffffff;
|
||||
while((c = getopt(argc, argv, "eEhHv:d:s:I:c:CnltVta:S:jpP:rR")) != -1) {
|
||||
switch(c) {
|
||||
case 'c':
|
||||
@ -265,9 +266,18 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
|
||||
static void display_target(int i, target *t, void *context)
|
||||
{
|
||||
(void)context;
|
||||
DEBUG_INFO("*** %2d %c %s %s\n", i, target_attached(t)?'*':' ',
|
||||
target_driver_name(t),
|
||||
(target_core_name(t)) ? target_core_name(t): "");
|
||||
if (!strcmp(target_driver_name(t), "ARM Cortex-M")) {
|
||||
DEBUG_INFO("***%2d%sUnknown %s Designer %3x Partno %3x %s\n",
|
||||
i, target_attached(t)?" * ":" ",
|
||||
target_driver_name(t),
|
||||
target_designer(t),
|
||||
target_idcode(t),
|
||||
(target_core_name(t)) ? target_core_name(t): "");
|
||||
} else {
|
||||
DEBUG_INFO("*** %2d %c %s %s\n", i, target_attached(t)?'*':' ',
|
||||
target_driver_name(t),
|
||||
(target_core_name(t)) ? target_core_name(t): "");
|
||||
}
|
||||
}
|
||||
|
||||
int cl_execute(BMP_CL_OPTIONS_t *opt)
|
||||
@ -353,7 +363,7 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (opt->opt_flash_start < flash_start)
|
||||
if (opt->opt_flash_start == 0xffffffff)
|
||||
opt->opt_flash_start = flash_start;
|
||||
if (opt->opt_mode == BMP_MODE_TEST)
|
||||
goto target_detach;
|
||||
|
@ -1,41 +1,63 @@
|
||||
# Blackmagic for ST -Link Adapters
|
||||
# Blackmagic for STLINK Adapters
|
||||
|
||||
For ST-LINK V3 and ST-LINKV 2/1, as found on all Nucleo and recent Discovery
|
||||
boards, use the pc-stlinkv2 branch, running on the PC and with original,
|
||||
recent ST firmware.
|
||||
STLINK-V3, ST-LINK/V2-1 and /V2 with original, recent ST firmware can can use the hosted branch, running the GDB server on PC.
|
||||
|
||||
Only if you have a ST-LINK V22 with STM32F103C8 versus the STM32F103CB on V2/1
|
||||
and you want to rewire and use the UART, consider reflashing the the Stlink
|
||||
firmware.
|
||||
Running the BMP firmware on ST-LINK/V2 and ST-LINK/V2-1 provides:
|
||||
- built-in gdb server on the dongle
|
||||
- VCP on ST-LINK/V2. Access to VCP lines needs additional wires to the STM32F103C8!
|
||||
- VCP on ST-LINK/V2 clones ([Baite](https://www.mikrocontroller.net/attachment/356780/st-linkV2-mini_LRG.jpg)), accessible on the bare PCB.
|
||||
- no mass storage device (MSD). A MSD may collide with company policies.
|
||||
|
||||
On ST-LINK V2, the original ST Bootloader can also be used with
|
||||
For all commands below, unplug all other BMP/ST-LINK beside the target(*1)
|
||||
|
||||
- Compile firmware with "make PROBE_HOST=stlink ST_BOOTLOADER=1"
|
||||
## Upload BMP Firmware:
|
||||
|
||||
- Upload firmware with stlink-tool from [stlink-tool](https://github.com/jeanthom/stlink-tool.git).
|
||||
Before upload, replug the stlink to enter the bootloader.
|
||||
- Keep the original ST Bootloader.
|
||||
|
||||
- After each stlink replug, call "stlink-tool" without arguments
|
||||
to enter BMP or on Linux use some udev rule like
|
||||
- Compile firmware with `make PROBE_HOST=stlink ST_BOOTLOADER=1`
|
||||
|
||||
- Upload firmware with stlink-tool from [stlink-tool](https://github.com/UweBonnes/stlink-tool/tree/stlinkv21)(*3).
|
||||
|
||||
- For ST-LINK/V2, as on older disco boards, un- and replug USB to enter the bootloader.
|
||||
|
||||
- Upload BMP firmware with `stlink-tool blackmagic.bin`
|
||||
|
||||
- For ST-LINK/V2, after each stlink replug, call either `blackmacic -t` or `stlink-tool` without arguments or on Linux use some udev rule like
|
||||
|
||||
`> cat /etc/udev/rules.d/98-stlink.rules`
|
||||
|
||||
`SUBSYSTEM=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", ACTION=="add", RUN+="<path-to>/stlink-tool"`
|
||||
|
||||
- To enter Bootloader again either replug or use "dfu-util -e".
|
||||
With more than one DFU device connected, you need to specify
|
||||
the needed device
|
||||
to enter the BMP firmware
|
||||
|
||||
## Reverting to original ST Firmware with running BMP firmware:
|
||||
|
||||
- Get STLINK upgrade [firmware](https://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-programmers/stsw-link007.html) and unzip. Change to "stsw-link007/AllPlatforms/" in the unzipped directory.
|
||||
|
||||
- To enter Bootloader again use `dfu-util -e`, or with ST-LINK/V2 un- and replug.
|
||||
|
||||
- For ST-LINK/V2(Standalone) run `java -jar STLinkUpgrade.jar -jtag_swim -force_prog`
|
||||
|
||||
- For ST-LINK/V2(embedded) run `java -jar STLinkUpgrade.jar -jtag -force_prog`
|
||||
|
||||
- For ST-LINK/V21 run `java -jar STLinkUpgrade.jar -msvcp -force_prog`
|
||||
|
||||
- For STLINK-V3 run `java -jar STLinkUpgrade.jar -d8_d32_msc_br -force_prog` (*2)
|
||||
|
||||
<br> (*1) Command arguments are available to specify some specific of several devices. Look at the help for blackmagic, stlink-tool and dfu-util if really needed. For STLinkUpgrade.jar, no documentation is known, but `strings ./st/stlinkupgrade/app/a.class` may give a clue.<
|
||||
<br> (*2) Loading firmware V37 and higher to STLINK-V3 with original bootloader will inhibit further debugging the F723 on the ST-LINK itself. There are patched bootloaders out there that do not set RDP2.
|
||||
<br> (*3) Pull request to original author pending.
|
||||
|
||||
## Versions
|
||||
|
||||
### [Standalone ST-LINKV2](https://www.st.com/content/st_com/en/products/development-tools/hardware-development-tools/development-tool-hardware-for-mcus/debug-hardware-for-mcus/debug-hardware-for-stm32-mcus/st-link-v2.html)
|
||||
### [Standalone ST-LINK/V2](https://www.st.com/content/st_com/en/products/development-tools/hardware-development-tools/development-tool-hardware-for-mcus/debug-hardware-for-mcus/debug-hardware-for-stm32-mcus/st-link-v2.html)
|
||||
Accessible connectors for JTAG/SWD (20-pin) and SWIM.
|
||||
ST-LINKV2/ISOL).
|
||||
### ST-LINKV2 clones aka "baite"
|
||||
ST-LINK/V2/ISOL).
|
||||
### ST-LINK/V2 clones aka "baite"
|
||||
JTAG/SWD/SWIM are on a 10-pin connector. CPU SWD pins are accessible on the
|
||||
board.
|
||||
### SWIM-only ST-LINK adapters on STM8 Discovery boards
|
||||
JTAG and target SWIM pins are accessible on connector (footprints). They are handled in the swlink branch.
|
||||
JTAG and target SWIM pins are accessible on connector (footprints). They are handled in the swlink platform.
|
||||
### SWIM-only ST-LINK adapters on STM8 Nucleo-Stm8 boards
|
||||
As only a SWIM connector is accessible, they are not usefull as BMP target.
|
||||
### [SWD only ST-LINK adapter](https://www.st.com/content/ccc/resource/technical/document/technical_note/group0/30/c8/1d/0f/15/62/46/ef/DM00290229/files/DM00290229.pdf/jcr:content/translations/en.DM00290229.pdf) (Stm32 Nucleo Boards, recent Discovery boards)
|
||||
@ -46,12 +68,12 @@ As only a SWIM connector is accessible, they are not usefull as BMP target.
|
||||
Newer variants have transistor for USB reenumeration
|
||||
Newer variants may switch onboard target power.
|
||||
Newer Variants may have level shifters for some signals to onboard target.
|
||||
#### ST-Link/V1
|
||||
CDCACM USART pins are not accessible. MCO output is used for LED.
|
||||
#### ST-Link/V2 and ST-Link/V2-A
|
||||
#### ST-LINK/V1
|
||||
CDCACM USART pins are not accessible. MCO output is used for LED. Use the swlink platform!
|
||||
#### ST-LINK/V2 and ST-LINK/V2-A
|
||||
CDCACM USART pins are not accessible. MCO is connected to on board target.
|
||||
#### ST-Link/V2-1 and ST-Link/V2-B
|
||||
### [STLINK-V3SET](https://www.st.com/content/st_com/en/products/development-tools/hardware-development-tools/development-tool-hardware-for-mcus/debug-hardware-for-mcus/debug-hardware-for-stm32-mcus/stlink-v3set.html)
|
||||
#### ST-LINK/V2-1 and ST-LINK/V2-B
|
||||
#### [STLINK-V3SET](https://www.st.com/content/st_com/en/products/development-tools/hardware-development-tools/development-tool-hardware-for-mcus/debug-hardware-for-mcus/debug-hardware-for-stm32-mcus/stlink-v3set.html)
|
||||
|
||||
## Wiring on Discovery and Nucleo Boards
|
||||
|
||||
@ -74,20 +96,13 @@ the 2 jumper shortening the 4-pin connector like this:
|
||||
|
||||
## BMP version detection and handling
|
||||
All ST-LINK variants
|
||||
PC13/14 open -> Standalone ST-LINKV2 or baite, some STM32 Disco w/o accessible
|
||||
PC13/14 open -> Standalone ST-LINK/V2 or baite, some STM32 Disco w/o accessible
|
||||
UART RX/TX
|
||||
|
||||
PC13 low -> SWIM internal connection
|
||||
|
||||
PC13/PC14 both low -> ST-LinkV2 on some F4_Diso boards.
|
||||
PC13/PC14 both low -> ST-LINK/V2 on some F4_Diso boards.
|
||||
|
||||
## Reflashing BMP back to ST-LINK V2 original firmware
|
||||
|
||||
If you built the firmware to use ST-Link v2's bootloader (with `ST_BOOTLOADER=1`), you should be able to reflash back to original firmware using the [STLinkUpgrade utility](https://www.st.com/en/development-tools/stsw-link007.html). Do not check the "Change type" checkbox unless you know what you are doing, as it will change the USB VID:PID and change how it operates.
|
||||
|
||||
Replug ST-LINK before flashing if the utility doesn't detect it.
|
||||
##ST-LINK V2.1 Force Bootloader entry
|
||||
## ST-LINK V2.1 force Bootloader entry
|
||||
On ST-LINK V2/2-1 boards with the original bootloader, you can force
|
||||
bootloader entry with asserting NRST of the STM32F103CB of the USB
|
||||
powered board. Serveral attempts may be needed.
|
||||
https://www.carminenoviello.com/2016/02/26/restore-st-link-interface-bad-update-2-26-15-firmware/
|
||||
bootloader entry with asserting [NRST](https://www.carminenoviello.com/2016/02/26/restore-st-link-interface-bad-update-2-26-15-firmware/) of the STM32F103CB of the USB powered board. Serveral attempts may be needed.
|
||||
|
73
src/remote.c
73
src/remote.c
@ -126,12 +126,10 @@ static void _respondS(char respCode, const char *s)
|
||||
}
|
||||
|
||||
static ADIv5_DP_t remote_dp = {
|
||||
.dp_read = firmware_swdp_read,
|
||||
.ap_read = firmware_ap_read,
|
||||
.ap_write = firmware_ap_write,
|
||||
.mem_read = firmware_mem_read,
|
||||
.mem_write_sized = firmware_mem_write_sized,
|
||||
.low_access = firmware_swdp_low_access,
|
||||
};
|
||||
|
||||
|
||||
@ -142,8 +140,10 @@ void remotePacketProcessSWD(uint8_t i, char *packet)
|
||||
bool badParity;
|
||||
|
||||
switch (packet[1]) {
|
||||
case REMOTE_INIT: /* SS = initialise ================================= */
|
||||
case REMOTE_INIT: /* SS = initialise =============================== */
|
||||
if (i==2) {
|
||||
remote_dp.dp_read = firmware_swdp_read;
|
||||
remote_dp.low_access = firmware_swdp_low_access;
|
||||
swdptap_init();
|
||||
_respond(REMOTE_RESP_OK, 0);
|
||||
} else {
|
||||
@ -151,26 +151,26 @@ void remotePacketProcessSWD(uint8_t i, char *packet)
|
||||
}
|
||||
break;
|
||||
|
||||
case REMOTE_IN_PAR: /* = In parity ================================== */
|
||||
case REMOTE_IN_PAR: /* SI = In parity ============================= */
|
||||
ticks=remotehston(2,&packet[2]);
|
||||
badParity = swd_proc.swdptap_seq_in_parity(¶m, ticks);
|
||||
_respond(badParity?REMOTE_RESP_PARERR:REMOTE_RESP_OK,param);
|
||||
break;
|
||||
|
||||
case REMOTE_IN: /* = In ========================================= */
|
||||
case REMOTE_IN: /* Si = In ======================================= */
|
||||
ticks=remotehston(2,&packet[2]);
|
||||
param = swd_proc.swdptap_seq_in(ticks);
|
||||
_respond(REMOTE_RESP_OK,param);
|
||||
break;
|
||||
|
||||
case REMOTE_OUT: /* = Out ======================================== */
|
||||
case REMOTE_OUT: /* So= Out ====================================== */
|
||||
ticks=remotehston(2,&packet[2]);
|
||||
param=remotehston(-1, &packet[4]);
|
||||
swd_proc.swdptap_seq_out(param, ticks);
|
||||
_respond(REMOTE_RESP_OK, 0);
|
||||
break;
|
||||
|
||||
case REMOTE_OUT_PAR: /* = Out parity ================================= */
|
||||
case REMOTE_OUT_PAR: /* SO = Out parity ========================== */
|
||||
ticks=remotehston(2,&packet[2]);
|
||||
param=remotehston(-1, &packet[4]);
|
||||
swd_proc.swdptap_seq_out_parity(param, ticks);
|
||||
@ -189,21 +189,21 @@ void remotePacketProcessJTAG(uint8_t i, char *packet)
|
||||
uint64_t DO;
|
||||
uint8_t ticks;
|
||||
uint64_t DI;
|
||||
|
||||
jtag_dev_t jtag_dev;
|
||||
switch (packet[1]) {
|
||||
case REMOTE_INIT: /* = initialise ================================= */
|
||||
jtagtap_init();
|
||||
case REMOTE_INIT: /* JS = initialise ============================= */
|
||||
remote_dp.dp_read = fw_adiv5_jtagdp_read;
|
||||
remote_dp.low_access = fw_adiv5_jtagdp_low_access;
|
||||
jtagtap_init();
|
||||
_respond(REMOTE_RESP_OK, 0);
|
||||
break;
|
||||
|
||||
case REMOTE_RESET: /* = reset ================================= */
|
||||
case REMOTE_RESET: /* JR = reset ================================= */
|
||||
jtag_proc.jtagtap_reset();
|
||||
_respond(REMOTE_RESP_OK, 0);
|
||||
break;
|
||||
|
||||
case REMOTE_TMS: /* = TMS Sequence ================================== */
|
||||
case REMOTE_TMS: /* JT = TMS Sequence ============================ */
|
||||
ticks=remotehston(2,&packet[2]);
|
||||
MS=remotehston(2,&packet[4]);
|
||||
|
||||
@ -215,7 +215,7 @@ void remotePacketProcessJTAG(uint8_t i, char *packet)
|
||||
}
|
||||
break;
|
||||
|
||||
case REMOTE_TDITDO_TMS: /* = TDI/TDO ========================================= */
|
||||
case REMOTE_TDITDO_TMS: /* JD = TDI/TDO ========================================= */
|
||||
case REMOTE_TDITDO_NOTMS:
|
||||
|
||||
if (i<5) {
|
||||
@ -232,7 +232,7 @@ void remotePacketProcessJTAG(uint8_t i, char *packet)
|
||||
}
|
||||
break;
|
||||
|
||||
case REMOTE_NEXT: /* = NEXT ======================================== */
|
||||
case REMOTE_NEXT: /* JN = NEXT ======================================== */
|
||||
if (i!=4) {
|
||||
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_WRONGLEN);
|
||||
} else {
|
||||
@ -241,6 +241,23 @@ void remotePacketProcessJTAG(uint8_t i, char *packet)
|
||||
}
|
||||
break;
|
||||
|
||||
case REMOTE_ADD_JTAG_DEV: /* JJ = fill firmware jtag_devs */
|
||||
if (i < 22) {
|
||||
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_WRONGLEN);
|
||||
} else {
|
||||
memset(&jtag_dev, 0, sizeof(jtag_dev));
|
||||
uint8_t index = remotehston(2, &packet[ 2]);
|
||||
jtag_dev.dr_prescan = remotehston(2, &packet[ 4]);
|
||||
jtag_dev.dr_postscan = remotehston(2, &packet[ 6]);
|
||||
jtag_dev.ir_len = remotehston(2, &packet[ 8]);
|
||||
jtag_dev.ir_prescan = remotehston(2, &packet[10]);
|
||||
jtag_dev.ir_postscan = remotehston(2, &packet[12]);
|
||||
jtag_dev.current_ir = remotehston(8, &packet[14]);
|
||||
jtag_add_device(index, &jtag_dev);
|
||||
_respond(REMOTE_RESP_OK, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_UNRECOGNISED);
|
||||
break;
|
||||
@ -309,16 +326,24 @@ void remotePacketProcessHL(uint8_t i, char *packet)
|
||||
remote_ap.apsel = remotehston(2, packet);
|
||||
remote_ap.dp = &remote_dp;
|
||||
switch (index) {
|
||||
case REMOTE_HL_CHECK:
|
||||
case REMOTE_HL_CHECK: /* HC = Check availability of HL commands*/
|
||||
_respond(REMOTE_RESP_OK, 0);
|
||||
break;
|
||||
case REMOTE_DP_READ:
|
||||
case REMOTE_HL_JTAG_DEV: /* HJ for jtag device to use */
|
||||
if (i < 4) {
|
||||
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_WRONGLEN);
|
||||
} else {
|
||||
remote_dp.dp_jd_index = remotehston(2, packet);
|
||||
_respond(REMOTE_RESP_OK, 0);
|
||||
}
|
||||
break;
|
||||
case REMOTE_DP_READ: /* Hd = Read from DP register */
|
||||
packet += 2;
|
||||
uint16_t addr16 = remotehston(4, packet);
|
||||
uint32_t data = adiv5_dp_read(&remote_dp, addr16);
|
||||
_respond_buf(REMOTE_RESP_OK, (uint8_t*)&data, 4);
|
||||
break;
|
||||
case REMOTE_LOW_ACCESS:
|
||||
case REMOTE_LOW_ACCESS: /* HL = Low level access */
|
||||
packet += 2;
|
||||
addr16 = remotehston(4, packet);
|
||||
packet += 4;
|
||||
@ -326,13 +351,13 @@ void remotePacketProcessHL(uint8_t i, char *packet)
|
||||
data = remote_dp.low_access(&remote_dp, remote_ap.apsel, addr16, value);
|
||||
_respond_buf(REMOTE_RESP_OK, (uint8_t*)&data, 4);
|
||||
break;
|
||||
case REMOTE_AP_READ:
|
||||
case REMOTE_AP_READ: /* Ha = Read from AP register*/
|
||||
packet += 2;
|
||||
addr16 = remotehston(4, packet);
|
||||
data = adiv5_ap_read(&remote_ap, addr16);
|
||||
_respond_buf(REMOTE_RESP_OK, (uint8_t*)&data, 4);
|
||||
break;
|
||||
case REMOTE_AP_WRITE:
|
||||
case REMOTE_AP_WRITE: /* Ha = Write to AP register*/
|
||||
packet += 2;
|
||||
addr16 = remotehston(4, packet);
|
||||
packet += 4;
|
||||
@ -340,12 +365,12 @@ void remotePacketProcessHL(uint8_t i, char *packet)
|
||||
adiv5_ap_write(&remote_ap, addr16, value);
|
||||
_respond(REMOTE_RESP_OK, 0);
|
||||
break;
|
||||
case REMOTE_AP_MEM_READ:
|
||||
case REMOTE_AP_MEM_READ: /* HM = Read from Mem and set csw */
|
||||
packet += 2;
|
||||
remote_ap.csw = remotehston(8, packet);
|
||||
packet += 6;
|
||||
/*fall through*/
|
||||
case REMOTE_MEM_READ:
|
||||
case REMOTE_MEM_READ: /* Hh = Read from Mem */
|
||||
packet += 2;
|
||||
uint32_t address = remotehston(8, packet);
|
||||
packet += 8;
|
||||
@ -359,12 +384,12 @@ void remotePacketProcessHL(uint8_t i, char *packet)
|
||||
_respond(REMOTE_RESP_ERR, 0);
|
||||
remote_ap.dp->fault = 0;
|
||||
break;
|
||||
case REMOTE_AP_MEM_WRITE_SIZED:
|
||||
case REMOTE_AP_MEM_WRITE_SIZED: /* Hm = Write to memory and set csw */
|
||||
packet += 2;
|
||||
remote_ap.csw = remotehston(8, packet);
|
||||
packet += 6;
|
||||
/*fall through*/
|
||||
case REMOTE_MEM_WRITE_SIZED:
|
||||
case REMOTE_MEM_WRITE_SIZED: /* HH = Write to memory*/
|
||||
packet += 2;
|
||||
enum align align = remotehston(2, packet);
|
||||
packet += 2;
|
||||
@ -386,7 +411,7 @@ void remotePacketProcessHL(uint8_t i, char *packet)
|
||||
remote_ap.dp->fault = 0;
|
||||
break;
|
||||
}
|
||||
_respond_buf(REMOTE_RESP_OK, src, len);
|
||||
_respond(REMOTE_RESP_OK, 0);
|
||||
break;
|
||||
default:
|
||||
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_UNRECOGNISED);
|
||||
|
18
src/remote.h
18
src/remote.h
@ -76,6 +76,7 @@
|
||||
#define REMOTE_VOLTAGE 'V'
|
||||
#define REMOTE_SRST_SET 'Z'
|
||||
#define REMOTE_SRST_GET 'z'
|
||||
#define REMOTE_ADD_JTAG_DEV 'J'
|
||||
|
||||
/* Protocol response options */
|
||||
#define REMOTE_RESP_OK 'K'
|
||||
@ -85,6 +86,7 @@
|
||||
|
||||
/* High level protocol elements */
|
||||
#define REMOTE_HL_CHECK 'C'
|
||||
#define REMOTE_HL_JTAG_DEV 'J'
|
||||
#define REMOTE_HL_PACKET 'H'
|
||||
#define REMOTE_DP_READ 'd'
|
||||
#define REMOTE_LOW_ACCESS 'L'
|
||||
@ -137,17 +139,29 @@
|
||||
|
||||
#define REMOTE_JTAG_NEXT (char []){ REMOTE_SOM, REMOTE_JTAG_PACKET, REMOTE_NEXT, \
|
||||
'%','c','%','c',REMOTE_EOM, 0 }
|
||||
|
||||
/* HL protocol elements */
|
||||
#define HEX '%', '0', '2', 'x'
|
||||
#define HEX_U32(x) '%', '0', '8', 'x'
|
||||
#define CHR(x) '%', 'c'
|
||||
|
||||
#define REMOTE_JTAG_ADD_DEV_STR (char []){ REMOTE_SOM, REMOTE_JTAG_PACKET,\
|
||||
REMOTE_ADD_JTAG_DEV, \
|
||||
'%','0','2','x', /* index */ \
|
||||
'%','0','2','x', /* dr_prescan */ \
|
||||
'%','0','2','x', /* dr_postscan */ \
|
||||
'%','0','2','x', /* ir_len */ \
|
||||
'%','0','2','x', /* ir_prescan */ \
|
||||
'%','0','2','x', /* ir_postscan */ \
|
||||
HEX_U32(current_ir), /* current_ir */ \
|
||||
REMOTE_EOM, 0}
|
||||
|
||||
#define REMOTE_HL_CHECK_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_HL_CHECK, REMOTE_EOM, 0 }
|
||||
#define REMOTE_HL_JTAG_DEV_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, \
|
||||
REMOTE_HL_JTAG_DEV, '%', '0', '2', 'x', REMOTE_EOM, 0 }
|
||||
#define REMOTE_MEM_READ_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_MEM_READ, \
|
||||
HEX_U32(address), HEX_U32(count), REMOTE_EOM, 0 }
|
||||
#define REMOTE_DP_READ_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_DP_READ, \
|
||||
'f', 'f','%', '0', '4', 'x', REMOTE_EOM, 0 }
|
||||
'f', 'f', '%', '0', '4', 'x', REMOTE_EOM, 0 }
|
||||
#define REMOTE_LOW_ACCESS_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_LOW_ACCESS, \
|
||||
'%','0', '2', 'x', '%', '0', '4', 'x', HEX_U32(csw), REMOTE_EOM, 0 }
|
||||
#define REMOTE_AP_READ_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_AP_READ, \
|
||||
|
@ -36,6 +36,13 @@
|
||||
* are consistently named and accessible when needed in the codebase.
|
||||
*/
|
||||
|
||||
/* Values from ST RM0436 (STM32MP157), 66.9 APx_IDR
|
||||
* and ST RM0438 (STM32L5) 52.3.1, AP_IDR */
|
||||
#define ARM_AP_TYPE_AHB 1
|
||||
#define ARM_AP_TYPE_APB 3
|
||||
#define ARM_AP_TYPE_AXI 4
|
||||
#define ARM_AP_TYPE_AHB5 5
|
||||
|
||||
/* ROM table CIDR values */
|
||||
#define CIDR0_OFFSET 0xFF0 /* DBGCID0 */
|
||||
#define CIDR1_OFFSET 0xFF4 /* DBGCID1 */
|
||||
@ -191,10 +198,15 @@ static const struct {
|
||||
{0x00d, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ETM11", "(Embedded Trace)")},
|
||||
{0x00e, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 FBP", "(Flash Patch and Breakpoint)")},
|
||||
{0x101, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("System TSGEN", "(Time Stamp Generator)")},
|
||||
{0x471, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M0 ROM", "(Cortex-M0 ROM)")},
|
||||
{0x490, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 GIC", "(Generic Interrupt Controller)")},
|
||||
{0x4c7, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 PPB", "(Private Peripheral Bus ROM Table)")},
|
||||
{0x4c0, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M0+ ROM", "(Cortex-M0+ ROM)")},
|
||||
{0x4c3, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M3 ROM", "(Cortex-M3 ROM)")},
|
||||
{0x4c4, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M4 ROM", "(Cortex-M4 ROM)")},
|
||||
{0x4c7, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 PPB", "(Cortex-M7 Private Peripheral Bus ROM Table)")},
|
||||
{0x4c8, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 ROM", "(Cortex-M7 ROM)")},
|
||||
{0x906, 0x14, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight CTI", "(Cross Trigger)")},
|
||||
{0x907, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ETB", "(Trace Buffer)")},
|
||||
{0x907, 0x21, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ETB", "(Trace Buffer)")},
|
||||
{0x908, 0x12, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight CSTF", "(Trace Funnel)")},
|
||||
{0x910, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight ETM9", "(Embedded Trace)")},
|
||||
{0x912, 0x11, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight TPIU", "(Trace Port Interface Unit)")},
|
||||
@ -208,7 +220,7 @@ static const struct {
|
||||
{0x924, 0x13, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M3 ETM", "(Embedded Trace)")},
|
||||
{0x925, 0x13, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M4 ETM", "(Embedded Trace)")},
|
||||
{0x930, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-R4 ETM", "(Embedded Trace)")},
|
||||
{0x932, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight MTB-M0+", "(Simple Execution Trace)")},
|
||||
{0x932, 0x31, 0x0a31, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight MTB-M0+", "(Simple Execution Trace)")},
|
||||
{0x941, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight TPIU-Lite", "(Trace Port Interface Unit)")},
|
||||
{0x950, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight Component", "(unidentified Cortex-A9 component)")},
|
||||
{0x955, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight Component", "(unidentified Cortex-A5 component)")},
|
||||
@ -299,6 +311,99 @@ uint64_t adiv5_ap_read_pidr(ADIv5_AP_t *ap, uint32_t addr)
|
||||
return pidr;
|
||||
}
|
||||
|
||||
/* Prepare to read SYSROM and SYSROM PIDR
|
||||
*
|
||||
* Try hard to halt, if not connecting under reset
|
||||
* Request TRCENA and default vector catch
|
||||
* release from reset when connecting under reset.
|
||||
*
|
||||
* E.g. Stm32F7
|
||||
* - fails reading romtable in WFI
|
||||
* - fails with some AP accesses when romtable is read under reset.
|
||||
* - fails reading some ROMTABLE entries w/o TRCENA
|
||||
* - fails reading outside SYSROM when halted from WFI and
|
||||
* DBGMCU_CR not set.
|
||||
*
|
||||
* Keep a copy of DEMCR at startup to restore with exit, to
|
||||
* not interrupt tracing initialed by the CPU.
|
||||
*/
|
||||
static bool cortexm_prepare(ADIv5_AP_t *ap)
|
||||
{
|
||||
platform_timeout to ;
|
||||
platform_timeout_set(&to, cortexm_wait_timeout);
|
||||
uint32_t dhcsr_ctl = CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN |
|
||||
CORTEXM_DHCSR_C_HALT;
|
||||
uint32_t dhcsr_valid = CORTEXM_DHCSR_S_HALT | CORTEXM_DHCSR_C_DEBUGEN;
|
||||
#ifdef PLATFORM_HAS_DEBUG
|
||||
uint32_t start_time = platform_time_ms();
|
||||
#endif
|
||||
uint32_t dhcsr;
|
||||
bool reset_seen = false;
|
||||
while (true) {
|
||||
adiv5_mem_write(ap, CORTEXM_DHCSR, &dhcsr_ctl, sizeof(dhcsr_ctl));
|
||||
dhcsr = adiv5_mem_read32(ap, CORTEXM_DHCSR);
|
||||
/* On a sleeping STM32F7, invalid DHCSR reads with e.g. 0xffffffff and
|
||||
* 0x0xA05F0000 may happen.
|
||||
* M23/33 will have S_SDE set when debug is allowed
|
||||
*/
|
||||
if ((dhcsr != 0xffffffff) && /* Invalid read */
|
||||
((dhcsr & 0xf000fff0) == 0)) {/* Check RAZ bits */
|
||||
if ((dhcsr & CORTEXM_DHCSR_S_RESET_ST) && !reset_seen) {
|
||||
if (connect_assert_srst)
|
||||
break;
|
||||
reset_seen = true;
|
||||
continue;
|
||||
}
|
||||
if ((dhcsr & dhcsr_valid) == dhcsr_valid) { /* Halted */
|
||||
DEBUG_INFO("Halt via DHCSR: success %08" PRIx32 " after %"
|
||||
PRId32 "ms\n",
|
||||
dhcsr, platform_time_ms() - start_time);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (platform_timeout_is_expired(&to)) {
|
||||
DEBUG_WARN("Halt via DHCSR: Failure DHCSR %08" PRIx32 " after % "
|
||||
PRId32 "ms\nTry again, evt. with longer timeout or "
|
||||
"connect under reset\n",
|
||||
dhcsr, platform_time_ms() - start_time);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ap->ap_cortexm_demcr = adiv5_mem_read32(ap, CORTEXM_DEMCR);
|
||||
uint32_t demcr = CORTEXM_DEMCR_TRCENA | CORTEXM_DEMCR_VC_HARDERR |
|
||||
CORTEXM_DEMCR_VC_CORERESET;
|
||||
adiv5_mem_write(ap, CORTEXM_DEMCR, &demcr, sizeof(demcr));
|
||||
platform_timeout_set(&to, cortexm_wait_timeout);
|
||||
platform_srst_set_val(false);
|
||||
while (1) {
|
||||
dhcsr = adiv5_mem_read32(ap, CORTEXM_DHCSR);
|
||||
if (!(dhcsr & CORTEXM_DHCSR_S_RESET_ST))
|
||||
break;
|
||||
if (platform_timeout_is_expired(&to)) {
|
||||
DEBUG_WARN("Error releasing from srst\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* Apply device specific settings for successfull Romtable scan
|
||||
*
|
||||
* STM32F7 in WFI will not read ROMTABLE when using WFI
|
||||
*/
|
||||
if ((ap->dp->targetid >> 1 & 0x7ff) == 0x20) {
|
||||
uint32_t dbgmcu_cr = 7;
|
||||
uint32_t dbgmcu_cr_addr = 0xE0042004;
|
||||
switch ((ap->dp->targetid >> 16) & 0xfff) {
|
||||
case 0x449:
|
||||
case 0x451:
|
||||
case 0x452:
|
||||
ap->ap_storage = adiv5_mem_read32(ap, dbgmcu_cr_addr);
|
||||
dbgmcu_cr = ap->ap_storage | 7;
|
||||
adiv5_mem_write(ap, dbgmcu_cr_addr, &dbgmcu_cr, sizeof(dbgmcu_cr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, int num_entry)
|
||||
{
|
||||
(void) num_entry;
|
||||
@ -306,6 +411,15 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
|
||||
if (addr == 0) /* No rom table on this AP */
|
||||
return false;
|
||||
uint32_t cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET);
|
||||
if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE) {
|
||||
/* Maybe caused by a not halted CortexM */
|
||||
if (!ap->apsel && ((ap->idr & 0xf) == ARM_AP_TYPE_AHB)) {
|
||||
if (!cortexm_prepare(ap))
|
||||
return false; /* Halting failed! */
|
||||
/* CPU now halted, read cidr again. */
|
||||
cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET);
|
||||
}
|
||||
}
|
||||
bool res = false;
|
||||
#if defined(ENABLE_DEBUG)
|
||||
char indent[recursion + 1];
|
||||
@ -333,8 +447,10 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
|
||||
|
||||
/* ROM table */
|
||||
if (cid_class == cidc_romtab) {
|
||||
uint16_t designer = ((pidr >> 24) & 0xf00) | ((pidr >> 12) & 0x7f);
|
||||
uint16_t partno = pidr & 0xfff;
|
||||
#if defined(ENABLE_DEBUG) && defined(PLATFORM_HAS_DEBUG)
|
||||
/* Check SYSMEM bit */
|
||||
#if defined(ENABLE_DEBUG)
|
||||
uint32_t memtype = adiv5_mem_read32(ap, addr | ADIV5_ROM_MEMTYPE) &
|
||||
ADIV5_ROM_MEMTYPE_SYSMEM;
|
||||
|
||||
@ -342,11 +458,18 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
|
||||
DEBUG_WARN("Fault reading ROM table entry\n");
|
||||
}
|
||||
|
||||
DEBUG_INFO("ROM: Table BASE=0x%" PRIx32 " SYSMEM=0x%" PRIx32
|
||||
", PIDR 0x%02" PRIx32 "%08" PRIx32 "\n", addr,
|
||||
memtype, (uint32_t)(pidr >> 32), (uint32_t)pidr);
|
||||
DEBUG_INFO("ROM: Table BASE=0x%" PRIx32 " SYSMEM=0x%08" PRIx32
|
||||
", designer %3x Partno %3x\n", addr, memtype, designer,
|
||||
partno);
|
||||
#endif
|
||||
|
||||
if (recursion == 0) {
|
||||
ap->ap_designer = designer;
|
||||
ap->ap_partno = partno;
|
||||
if ((ap->ap_designer == AP_DESIGNER_ATMEL) && (ap->ap_partno == 0xcd0)) {
|
||||
cortexm_probe(ap);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 960; i++) {
|
||||
adiv5_dp_error(ap->dp);
|
||||
uint32_t entry = adiv5_mem_read32(ap, addr + i*4);
|
||||
@ -365,7 +488,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
|
||||
}
|
||||
|
||||
/* Probe recursively */
|
||||
res |= adiv5_component_probe(
|
||||
adiv5_component_probe(
|
||||
ap, addr + (entry & ADIV5_ROM_ROMENTRY_OFFSET),
|
||||
recursion + 1, i);
|
||||
}
|
||||
@ -424,7 +547,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
|
||||
switch (pidr_pn_bits[i].arch) {
|
||||
case aa_cortexm:
|
||||
DEBUG_INFO("%s-> cortexm_probe\n", indent + 1);
|
||||
cortexm_probe(ap, false);
|
||||
cortexm_probe(ap);
|
||||
break;
|
||||
case aa_cortexa:
|
||||
DEBUG_INFO("\n -> cortexa_probe\n");
|
||||
@ -490,12 +613,12 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel)
|
||||
DEBUG_INFO("AP %3d: IDR=%08"PRIx32" CFG=%08"PRIx32" BASE=%08" PRIx32
|
||||
" CSW=%08"PRIx32"\n", apsel, ap->idr, cfg, ap->base, ap->csw);
|
||||
#endif
|
||||
adiv5_ap_ref(ap);
|
||||
return ap;
|
||||
}
|
||||
|
||||
void adiv5_dp_init(ADIv5_DP_t *dp)
|
||||
{
|
||||
volatile bool probed = false;
|
||||
volatile uint32_t ctrlstat = 0;
|
||||
adiv5_dp_ref(dp);
|
||||
#if PC_HOSTED == 1
|
||||
@ -625,12 +748,7 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
|
||||
*/
|
||||
|
||||
/* The rest should only be added after checking ROM table */
|
||||
probed |= adiv5_component_probe(ap, ap->base, 0, 0);
|
||||
if (!probed && (dp->idcode & 0xfff) == 0x477) {
|
||||
DEBUG_INFO("-> cortexm_probe forced\n");
|
||||
cortexm_probe(ap, true);
|
||||
probed = true;
|
||||
}
|
||||
adiv5_component_probe(ap, ap->base, 0, 0);
|
||||
}
|
||||
adiv5_dp_unref(dp);
|
||||
}
|
||||
|
@ -86,6 +86,19 @@
|
||||
#define ADIV5_AP_BASE ADIV5_AP_REG(0xF8)
|
||||
#define ADIV5_AP_IDR ADIV5_AP_REG(0xFC)
|
||||
|
||||
/* Known designers seen in SYSROM-PIDR. Ignore Bit 7 from the designer bits*/
|
||||
#define AP_DESIGNER_FREESCALE 0x00e
|
||||
#define AP_DESIGNER_TEXAS 0x017
|
||||
#define AP_DESIGNER_ATMEL 0x01f
|
||||
#define AP_DESIGNER_STM 0x020
|
||||
#define AP_DESIGNER_CYPRESS 0x034
|
||||
#define AP_DESIGNER_INFINEON 0x041
|
||||
#define AP_DESIGNER_NORDIC 0x244
|
||||
#define AP_DESIGNER_ARM 0x43b
|
||||
/*LPC845 with designer 501. Strange!? */
|
||||
#define AP_DESIGNER_SPECULAR 0x501
|
||||
#define AP_DESIGNER_ENERGY_MICRO 0x673
|
||||
|
||||
/* AP Control and Status Word (CSW) */
|
||||
#define ADIV5_AP_CSW_DBGSWENABLE (1u << 31)
|
||||
/* Bits 30:24 - Prot, Implementation defined, for Cortex-M3: */
|
||||
@ -161,15 +174,8 @@ typedef struct ADIv5_DP_s {
|
||||
void (*mem_read)(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len);
|
||||
void (*mem_write_sized)(ADIv5_AP_t *ap, uint32_t dest, const void *src,
|
||||
size_t len, enum align align);
|
||||
#if PC_HOSTED == 1
|
||||
jtag_dev_t *dev;
|
||||
uint8_t dp_jd_index;
|
||||
uint8_t fault;
|
||||
#else
|
||||
union {
|
||||
jtag_dev_t *dev;
|
||||
uint8_t fault;
|
||||
};
|
||||
#endif
|
||||
} ADIv5_DP_t;
|
||||
|
||||
struct ADIv5_AP_s {
|
||||
@ -181,6 +187,10 @@ struct ADIv5_AP_s {
|
||||
uint32_t idr;
|
||||
uint32_t base;
|
||||
uint32_t csw;
|
||||
uint32_t ap_cortexm_demcr; /* Copy of demcr when starting */
|
||||
uint32_t ap_storage; /* E.g to hold STM32F7 initial DBGMCU_CR value.*/
|
||||
uint16_t ap_designer;
|
||||
uint16_t ap_partno;
|
||||
};
|
||||
|
||||
#if PC_HOSTED == 0
|
||||
@ -250,10 +260,12 @@ void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value);
|
||||
void adiv5_dp_init(ADIv5_DP_t *dp);
|
||||
void platform_adiv5_dp_defaults(ADIv5_DP_t *dp);
|
||||
ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel);
|
||||
void remote_jtag_dev(const jtag_dev_t *jtag_dev);
|
||||
void adiv5_ap_ref(ADIv5_AP_t *ap);
|
||||
void adiv5_ap_unref(ADIv5_AP_t *ap);
|
||||
void platform_add_jtag_dev(const int dev_index, const jtag_dev_t *jtag_dev);
|
||||
|
||||
void adiv5_jtag_dp_handler(jtag_dev_t *dev);
|
||||
void adiv5_jtag_dp_handler(uint8_t jd_index, uint32_t j_idcode);
|
||||
int platform_jtag_dp_init(ADIv5_DP_t *dp);
|
||||
|
||||
void adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len);
|
||||
|
@ -41,7 +41,7 @@ static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp);
|
||||
|
||||
static void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort);
|
||||
|
||||
void adiv5_jtag_dp_handler(jtag_dev_t *dev)
|
||||
void adiv5_jtag_dp_handler(uint8_t jd_index, uint32_t j_idcode)
|
||||
{
|
||||
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
|
||||
if (!dp) { /* calloc failed: heap exhaustion */
|
||||
@ -49,9 +49,9 @@ void adiv5_jtag_dp_handler(jtag_dev_t *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
dp->dev = dev;
|
||||
dp->dp_jd_index = jd_index;
|
||||
if ((PC_HOSTED == 0 ) || (!platform_jtag_dp_init(dp))) {
|
||||
dp->idcode = dev->idcode;
|
||||
dp->idcode = j_idcode;
|
||||
dp->dp_read = fw_adiv5_jtagdp_read;
|
||||
dp->error = adiv5_jtagdp_error;
|
||||
dp->low_access = fw_adiv5_jtagdp_low_access;
|
||||
@ -85,11 +85,11 @@ uint32_t fw_adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
|
||||
|
||||
request = ((uint64_t)value << 3) | ((addr >> 1) & 0x06) | (RnW?1:0);
|
||||
|
||||
jtag_dev_write_ir(&jtag_proc, dp->dev, APnDP ? IR_APACC : IR_DPACC);
|
||||
jtag_dev_write_ir(&jtag_proc, dp->dp_jd_index, APnDP ? IR_APACC : IR_DPACC);
|
||||
|
||||
platform_timeout_set(&timeout, 2000);
|
||||
do {
|
||||
jtag_dev_shift_dr(&jtag_proc, dp->dev, (uint8_t*)&response,
|
||||
jtag_dev_shift_dr(&jtag_proc, dp->dp_jd_index, (uint8_t*)&response,
|
||||
(uint8_t*)&request, 35);
|
||||
ack = response & 0x07;
|
||||
} while(!platform_timeout_is_expired(&timeout) && (ack == JTAGDP_ACK_WAIT));
|
||||
@ -106,6 +106,6 @@ uint32_t fw_adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
|
||||
static void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort)
|
||||
{
|
||||
uint64_t request = (uint64_t)abort << 3;
|
||||
jtag_dev_write_ir(&jtag_proc, dp->dev, IR_ABORT);
|
||||
jtag_dev_shift_dr(&jtag_proc, dp->dev, NULL, (const uint8_t*)&request, 35);
|
||||
jtag_dev_write_ir(&jtag_proc, dp->dp_jd_index, IR_ABORT);
|
||||
jtag_dev_shift_dr(&jtag_proc, dp->dp_jd_index, NULL, (const uint8_t*)&request, 35);
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ int adiv5_swdp_scan(void)
|
||||
|
||||
target_list_free();
|
||||
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
|
||||
dp->dp_jd_index = JTAG_MAX_DEVS; /* Tag for BMP_REMOTE */
|
||||
if (!dp) { /* calloc failed: heap exhaustion */
|
||||
DEBUG_WARN("calloc: failed in %s\n", __func__);
|
||||
return -1;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
* This file is part of the Black Magic Debug project.
|
||||
*
|
||||
* Copyright (C) 2012 Black Sphere Technologies Ltd.
|
||||
* Copyright (C) 2012-2020 Black Sphere Technologies Ltd.
|
||||
* Written by Gareth McMullin <gareth@blacksphere.co.nz>,
|
||||
* Koen De Vleeschauwer and Uwe Bonne
|
||||
* Koen De Vleeschauwer and Uwe Bonnes
|
||||
*
|
||||
* 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
|
||||
@ -35,6 +35,7 @@
|
||||
#include "cortexm.h"
|
||||
#include "platform.h"
|
||||
#include "command.h"
|
||||
#include "gdb_packet.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
@ -263,28 +264,7 @@ static void cortexm_priv_free(void *priv)
|
||||
free(priv);
|
||||
}
|
||||
|
||||
static bool cortexm_forced_halt(target *t)
|
||||
{
|
||||
target_halt_request(t);
|
||||
platform_srst_set_val(false);
|
||||
uint32_t dhcsr = 0;
|
||||
uint32_t start_time = platform_time_ms();
|
||||
const uint32_t dhcsr_halted_bits = CORTEXM_DHCSR_S_HALT | CORTEXM_DHCSR_S_REGRDY |
|
||||
CORTEXM_DHCSR_C_HALT | CORTEXM_DHCSR_C_DEBUGEN;
|
||||
/* Try hard to halt the target. STM32F7 in WFI
|
||||
needs multiple writes!*/
|
||||
while (platform_time_ms() < start_time + cortexm_wait_timeout) {
|
||||
dhcsr = target_mem_read32(t, CORTEXM_DHCSR);
|
||||
if ((dhcsr & dhcsr_halted_bits) == dhcsr_halted_bits)
|
||||
break;
|
||||
target_halt_request(t);
|
||||
}
|
||||
if ((dhcsr & dhcsr_halted_bits) != dhcsr_halted_bits)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cortexm_probe(ADIv5_AP_t *ap, bool forced)
|
||||
bool cortexm_probe(ADIv5_AP_t *ap)
|
||||
{
|
||||
target *t;
|
||||
|
||||
@ -294,6 +274,8 @@ bool cortexm_probe(ADIv5_AP_t *ap, bool forced)
|
||||
}
|
||||
|
||||
adiv5_ap_ref(ap);
|
||||
t->t_designer = ap->ap_designer;
|
||||
t->idcode = ap->ap_partno;
|
||||
struct cortexm_priv *priv = calloc(1, sizeof(*priv));
|
||||
if (!priv) { /* calloc failed: heap exhaustion */
|
||||
DEBUG_WARN("calloc: failed in %s\n", __func__);
|
||||
@ -337,6 +319,10 @@ bool cortexm_probe(ADIv5_AP_t *ap, bool forced)
|
||||
|
||||
case 0xc27:
|
||||
t->core = "M7";
|
||||
if ((((cpuid >> 20) & 0xf) == 0) && (((cpuid >> 0) & 0xf) < 2)) {
|
||||
DEBUG_WARN("Silicon bug: Single stepping will enter pending "
|
||||
"exception handler with this M7 core revision!\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xc60:
|
||||
@ -391,40 +377,80 @@ bool cortexm_probe(ADIv5_AP_t *ap, bool forced)
|
||||
} else {
|
||||
target_check_error(t);
|
||||
}
|
||||
|
||||
/* Only force halt if read ROM Table failed and there is no DPv2
|
||||
* targetid!
|
||||
* So long, only STM32L0 is expected to enter this cause.
|
||||
*/
|
||||
if (forced && !ap->dp->targetid)
|
||||
if (!cortexm_forced_halt(t))
|
||||
return false;
|
||||
|
||||
#define PROBE(x) \
|
||||
do { if ((x)(t)) {target_halt_resume(t, 0); return true;} else target_check_error(t); } while (0)
|
||||
|
||||
PROBE(stm32f1_probe);
|
||||
PROBE(stm32f4_probe);
|
||||
PROBE(stm32h7_probe);
|
||||
PROBE(stm32l0_probe); /* STM32L0xx & STM32L1xx */
|
||||
PROBE(stm32l4_probe);
|
||||
PROBE(lpc11xx_probe);
|
||||
PROBE(lpc15xx_probe);
|
||||
PROBE(lpc43xx_probe);
|
||||
PROBE(lpc546xx_probe);
|
||||
PROBE(sam3x_probe);
|
||||
PROBE(sam4l_probe);
|
||||
PROBE(nrf51_probe);
|
||||
PROBE(samd_probe);
|
||||
PROBE(samx5x_probe);
|
||||
PROBE(lmi_probe);
|
||||
PROBE(kinetis_probe);
|
||||
PROBE(efm32_probe);
|
||||
PROBE(msp432_probe);
|
||||
PROBE(ke04_probe);
|
||||
PROBE(lpc17xx_probe);
|
||||
switch (ap->ap_designer) {
|
||||
case AP_DESIGNER_FREESCALE:
|
||||
PROBE(kinetis_probe);
|
||||
if (ap->ap_partno == 0x88c) {
|
||||
t->driver = "MIMXRT10xx(no flash)";
|
||||
target_halt_resume(t, 0);
|
||||
}
|
||||
break;
|
||||
case AP_DESIGNER_STM:
|
||||
PROBE(stm32f1_probe);
|
||||
PROBE(stm32f4_probe);
|
||||
PROBE(stm32h7_probe);
|
||||
PROBE(stm32l0_probe);
|
||||
PROBE(stm32l4_probe);
|
||||
if (ap->ap_partno == 0x472) {
|
||||
t->driver = "STM32L552(no flash)";
|
||||
target_halt_resume(t, 0);
|
||||
}
|
||||
break;
|
||||
case AP_DESIGNER_CYPRESS:
|
||||
DEBUG_WARN("Unhandled Cypress device\n");
|
||||
break;
|
||||
case AP_DESIGNER_INFINEON:
|
||||
DEBUG_WARN("Unhandled Infineon device\n");
|
||||
break;
|
||||
case AP_DESIGNER_NORDIC:
|
||||
PROBE(nrf51_probe);
|
||||
break;
|
||||
case AP_DESIGNER_ATMEL:
|
||||
PROBE(sam4l_probe);
|
||||
PROBE(samd_probe);
|
||||
PROBE(samx5x_probe);
|
||||
break;
|
||||
case AP_DESIGNER_ENERGY_MICRO:
|
||||
PROBE(efm32_probe);
|
||||
break;
|
||||
case AP_DESIGNER_TEXAS:
|
||||
PROBE(msp432_probe);
|
||||
break;
|
||||
case AP_DESIGNER_SPECULAR:
|
||||
PROBE(lpc11xx_probe); /* LPC845 */
|
||||
break;
|
||||
default:
|
||||
if (ap->ap_designer != AP_DESIGNER_ARM) {
|
||||
/* Report unexpected designers */
|
||||
#if PC_HOSTED == 0
|
||||
gdb_outf("Please report Designer %3x and Partno %3x and the "
|
||||
"probed device\n", ap->ap_designer, ap->ap_partno);
|
||||
#else
|
||||
DEBUG_WARN("Please report Designer %3x and Partno %3x and the "
|
||||
"probed device\n", ap->ap_designer, ap->ap_partno);
|
||||
#endif
|
||||
}
|
||||
if (ap->ap_partno == 0x4c3) /* Cortex-M3 ROM */
|
||||
PROBE(stm32f1_probe); /* Care for STM32F1 clones */
|
||||
else if (ap->ap_partno == 0x471) { /* Cortex-M0 ROM */
|
||||
PROBE(lpc11xx_probe); /* LPC24C11 */
|
||||
PROBE(lpc43xx_probe);
|
||||
}
|
||||
else if (ap->ap_partno == 0x4c4) /* Cortex-M4 ROM */
|
||||
PROBE(lpc43xx_probe);
|
||||
/* Info on PIDR of these parts wanted! */
|
||||
PROBE(sam3x_probe);
|
||||
PROBE(lpc15xx_probe);
|
||||
PROBE(lmi_probe);
|
||||
PROBE(ke04_probe);
|
||||
PROBE(lpc17xx_probe);
|
||||
}
|
||||
#undef PROBE
|
||||
|
||||
/* Restart the CortexM we stopped for Romtable scan. Allow pure debug.*/
|
||||
target_halt_resume(t, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -438,9 +464,6 @@ bool cortexm_attach(target *t)
|
||||
target_check_error(t);
|
||||
|
||||
target_halt_request(t);
|
||||
if (!cortexm_forced_halt(t))
|
||||
return false;
|
||||
|
||||
/* Request halt on reset */
|
||||
target_mem_write32(t, CORTEXM_DEMCR, priv->demcr);
|
||||
|
||||
@ -474,6 +497,22 @@ bool cortexm_attach(target *t)
|
||||
target_mem_write32(t, CORTEXM_FPB_CTRL,
|
||||
CORTEXM_FPB_CTRL_KEY | CORTEXM_FPB_CTRL_ENABLE);
|
||||
|
||||
uint32_t dhcsr = target_mem_read32(t, CORTEXM_DHCSR);
|
||||
dhcsr = target_mem_read32(t, CORTEXM_DHCSR);
|
||||
if (dhcsr & CORTEXM_DHCSR_S_RESET_ST) {
|
||||
platform_srst_set_val(false);
|
||||
platform_timeout timeout;
|
||||
platform_timeout_set(&timeout, 1000);
|
||||
while (1) {
|
||||
uint32_t dhcsr = target_mem_read32(t, CORTEXM_DHCSR);
|
||||
if (!(dhcsr & CORTEXM_DHCSR_S_RESET_ST))
|
||||
break;
|
||||
if (platform_timeout_is_expired(&timeout)) {
|
||||
DEBUG_WARN("Error releasing from srst\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -490,6 +529,9 @@ void cortexm_detach(target *t)
|
||||
for(i = 0; i < priv->hw_watchpoint_max; i++)
|
||||
target_mem_write32(t, CORTEXM_DWT_FUNC(i), 0);
|
||||
|
||||
/* Restort DEMCR*/
|
||||
ADIv5_AP_t *ap = cortexm_ap(t);
|
||||
target_mem_write32(t, CORTEXM_DEMCR, ap->ap_cortexm_demcr);
|
||||
/* Disable debug */
|
||||
target_mem_write32(t, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY);
|
||||
/* Add some clock cycles to get the CPU running again.*/
|
||||
|
@ -171,7 +171,7 @@ extern long cortexm_wait_timeout;
|
||||
|
||||
#define CORTEXM_TOPT_INHIBIT_SRST (1 << 2)
|
||||
|
||||
bool cortexm_probe(ADIv5_AP_t *ap, bool forced);
|
||||
bool cortexm_probe(ADIv5_AP_t *ap);
|
||||
ADIv5_AP_t *cortexm_ap(target *t);
|
||||
|
||||
bool cortexm_attach(target *t);
|
||||
|
@ -22,7 +22,7 @@ typedef const struct jtag_dev_descr_s {
|
||||
const uint32_t idcode;
|
||||
const uint32_t idmask;
|
||||
const char * const descr;
|
||||
void (*const handler)(jtag_dev_t *dev);
|
||||
void (*const handler)(uint8_t jd_index, uint32_t j_idcode);
|
||||
} jtag_dev_descr_t;
|
||||
extern jtag_dev_descr_t dev_descr[];
|
||||
|
||||
|
@ -36,6 +36,16 @@ int jtag_dev_count;
|
||||
/* bucket of ones for don't care TDI */
|
||||
static const uint8_t ones[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
|
||||
|
||||
#if PC_HOSTED == 0
|
||||
void jtag_add_device(const int dev_index, const jtag_dev_t *jtag_dev)
|
||||
{
|
||||
if (dev_index == 0)
|
||||
memset(&jtag_devs, 0, sizeof(jtag_devs));
|
||||
memcpy(&jtag_devs[dev_index], jtag_dev, sizeof(jtag_dev_t));
|
||||
jtag_dev_count = dev_index + 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Scan JTAG chain for devices, store IR length and IDCODE (if present).
|
||||
* Reset TAP state machine.
|
||||
* Select Shift-IR state.
|
||||
@ -94,7 +104,7 @@ int jtag_scan(const uint8_t *irlens)
|
||||
}
|
||||
jtag_devs[jtag_dev_count].ir_len = *irlens;
|
||||
jtag_devs[jtag_dev_count].ir_prescan = j;
|
||||
jtag_devs[jtag_dev_count].dev = jtag_dev_count;
|
||||
jtag_devs[jtag_dev_count].jd_dev = jtag_dev_count;
|
||||
j += *irlens;
|
||||
irlens++;
|
||||
jtag_dev_count++;
|
||||
@ -117,7 +127,7 @@ int jtag_scan(const uint8_t *irlens)
|
||||
if(jtag_devs[jtag_dev_count].ir_len == 1) break;
|
||||
jtag_devs[++jtag_dev_count].ir_len = 1;
|
||||
jtag_devs[jtag_dev_count].ir_prescan = j;
|
||||
jtag_devs[jtag_dev_count].dev = jtag_dev_count;
|
||||
jtag_devs[jtag_dev_count].jd_dev = jtag_dev_count;
|
||||
} else jtag_devs[jtag_dev_count].ir_len++;
|
||||
j++;
|
||||
}
|
||||
@ -169,34 +179,40 @@ int jtag_scan(const uint8_t *irlens)
|
||||
jtagtap_shift_dr();
|
||||
for(i = 0; i < jtag_dev_count; i++) {
|
||||
if(!jtag_proc.jtagtap_next(0, 1)) continue;
|
||||
jtag_devs[i].idcode = 1;
|
||||
jtag_devs[i].jd_idcode = 1;
|
||||
for(j = 2; j; j <<= 1)
|
||||
if(jtag_proc.jtagtap_next(0, 1)) jtag_devs[i].idcode |= j;
|
||||
if(jtag_proc.jtagtap_next(0, 1)) jtag_devs[i].jd_idcode |= j;
|
||||
|
||||
}
|
||||
DEBUG_INFO("Return to Run-Test/Idle\n");
|
||||
jtag_proc.jtagtap_next(1, 1);
|
||||
jtagtap_return_idle();
|
||||
#if PC_HOSTED == 1
|
||||
/*Transfer needed device information to firmware jtag_devs*/
|
||||
for(i = 0; i < jtag_dev_count; i++)
|
||||
platform_add_jtag_dev(i, &jtag_devs[i]);
|
||||
#endif
|
||||
|
||||
/* Check for known devices and handle accordingly */
|
||||
for(i = 0; i < jtag_dev_count; i++)
|
||||
for(j = 0; dev_descr[j].idcode; j++)
|
||||
if((jtag_devs[i].idcode & dev_descr[j].idmask) ==
|
||||
if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) ==
|
||||
dev_descr[j].idcode) {
|
||||
jtag_devs[i].current_ir = -1;
|
||||
/* Save description in table */
|
||||
jtag_devs[i].descr = dev_descr[j].descr;
|
||||
jtag_devs[i].jd_descr = dev_descr[j].descr;
|
||||
/* Call handler to initialise/probe device further */
|
||||
if(dev_descr[j].handler)
|
||||
dev_descr[j].handler(&jtag_devs[i]);
|
||||
dev_descr[j].handler(i, dev_descr[j].idcode);
|
||||
break;
|
||||
}
|
||||
|
||||
return jtag_dev_count;
|
||||
}
|
||||
|
||||
void jtag_dev_write_ir(jtag_proc_t *jp, jtag_dev_t *d, uint32_t ir)
|
||||
void jtag_dev_write_ir(jtag_proc_t *jp, uint8_t jd_index, uint32_t ir)
|
||||
{
|
||||
jtag_dev_t *d = &jtag_devs[jd_index];
|
||||
if(ir == d->current_ir) return;
|
||||
for(int i = 0; i < jtag_dev_count; i++)
|
||||
jtag_devs[i].current_ir = -1;
|
||||
@ -209,8 +225,9 @@ void jtag_dev_write_ir(jtag_proc_t *jp, jtag_dev_t *d, uint32_t ir)
|
||||
jtagtap_return_idle();
|
||||
}
|
||||
|
||||
void jtag_dev_shift_dr(jtag_proc_t *jp, jtag_dev_t *d, uint8_t *dout, const uint8_t *din, int ticks)
|
||||
void jtag_dev_shift_dr(jtag_proc_t *jp, uint8_t jd_index, uint8_t *dout, const uint8_t *din, int ticks)
|
||||
{
|
||||
jtag_dev_t *d = &jtag_devs[jd_index];
|
||||
jtagtap_shift_dr();
|
||||
jp->jtagtap_tdi_seq(0, ones, d->dr_prescan);
|
||||
if(dout)
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
typedef struct jtag_dev_s {
|
||||
union {
|
||||
uint8_t dev;
|
||||
uint8_t jd_dev;
|
||||
uint8_t dr_prescan;
|
||||
};
|
||||
uint8_t dr_postscan;
|
||||
@ -35,16 +35,16 @@ typedef struct jtag_dev_s {
|
||||
uint8_t ir_len;
|
||||
uint8_t ir_prescan;
|
||||
uint8_t ir_postscan;
|
||||
uint32_t idcode;
|
||||
const char *descr;
|
||||
uint32_t jd_idcode;
|
||||
const char *jd_descr;
|
||||
uint32_t current_ir;
|
||||
} jtag_dev_t;
|
||||
|
||||
extern struct jtag_dev_s jtag_devs[JTAG_MAX_DEVS+1];
|
||||
extern int jtag_dev_count;
|
||||
|
||||
void jtag_dev_write_ir(jtag_proc_t *jp, jtag_dev_t *dev, uint32_t ir);
|
||||
void jtag_dev_shift_dr(jtag_proc_t *jp, jtag_dev_t *dev, uint8_t *dout, const uint8_t *din, int ticks);
|
||||
|
||||
void jtag_dev_write_ir(jtag_proc_t *jp, uint8_t jd_index, uint32_t ir);
|
||||
void jtag_dev_shift_dr(jtag_proc_t *jp, uint8_t jd_index, uint8_t *dout, const uint8_t *din, int ticks);
|
||||
void jtag_add_device(const int dev_index, const jtag_dev_t *jtag_dev);
|
||||
#endif
|
||||
|
||||
|
@ -137,7 +137,7 @@ lpc11xx_probe(target *t)
|
||||
target_add_commands(t, lpc11xx_cmd_list, "LPC8N04");
|
||||
return true;
|
||||
}
|
||||
if (idcode) {
|
||||
if ((t->t_designer != AP_DESIGNER_SPECULAR) && idcode) {
|
||||
DEBUG_INFO("LPC11xx: Unknown IDCODE 0x%08" PRIx32 "\n", idcode);
|
||||
}
|
||||
idcode = target_mem_read32(t, LPC8XX_DEVICE_ID);
|
||||
|
@ -132,7 +132,6 @@ bool nrf51_probe(target *t)
|
||||
if ((info_part != 0xffffffff) && (info_part != 0) &&
|
||||
((info_part & 0x00ff000) == 0x52000)) {
|
||||
uint32_t ram_size = target_mem_read32(t, NRF52_INFO_RAM);
|
||||
t->idcode = info_part;
|
||||
t->driver = "Nordic nRF52";
|
||||
t->target_options |= CORTEXM_TOPT_INHIBIT_SRST;
|
||||
target_add_ram(t, 0x20000000, ram_size * 1024);
|
||||
@ -379,6 +378,12 @@ const struct command_s nrf51_mdm_cmd_list[] = {
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
#define MDM_POWER_EN ADIV5_DP_REG(0x01)
|
||||
#define MDM_SELECT_AP ADIV5_DP_REG(0x02)
|
||||
#define MDM_STATUS ADIV5_AP_REG(0x08)
|
||||
#define MDM_CONTROL ADIV5_AP_REG(0x04)
|
||||
#define MDM_PROT_EN ADIV5_AP_REG(0x0C)
|
||||
|
||||
void nrf51_mdm_probe(ADIv5_AP_t *ap)
|
||||
{
|
||||
switch(ap->idr) {
|
||||
@ -397,18 +402,16 @@ void nrf51_mdm_probe(ADIv5_AP_t *ap)
|
||||
t->priv = ap;
|
||||
t->priv_free = (void*)adiv5_ap_unref;
|
||||
|
||||
t->driver = "Nordic nRF52 Access Port";
|
||||
uint32_t status = adiv5_ap_read(ap, MDM_PROT_EN);
|
||||
status = adiv5_ap_read(ap, MDM_PROT_EN);
|
||||
if (status)
|
||||
t->driver = "Nordic nRF52 Access Port";
|
||||
else
|
||||
t->driver = "Nordic nRF52 Access Port (protected)";
|
||||
t->regs_size = 4;
|
||||
target_add_commands(t, nrf51_mdm_cmd_list, t->driver);
|
||||
}
|
||||
|
||||
#define MDM_POWER_EN ADIV5_DP_REG(0x01)
|
||||
#define MDM_SELECT_AP ADIV5_DP_REG(0x02)
|
||||
#define MDM_STATUS ADIV5_AP_REG(0x08)
|
||||
#define MDM_CONTROL ADIV5_AP_REG(0x04)
|
||||
#define MDM_PROT_EN ADIV5_AP_REG(0x0C)
|
||||
|
||||
|
||||
static bool nrf51_mdm_cmd_erase_mass(target *t, int argc, const char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
|
@ -170,9 +170,9 @@ static void sam4_add_flash(target *t,
|
||||
target_add_flash(t, f);
|
||||
}
|
||||
|
||||
static size_t sam_flash_size(uint32_t idcode)
|
||||
static size_t sam_flash_size(uint32_t cidr)
|
||||
{
|
||||
switch (idcode & CHIPID_CIDR_NVPSIZ_MASK) {
|
||||
switch (cidr & CHIPID_CIDR_NVPSIZ_MASK) {
|
||||
case CHIPID_CIDR_NVPSIZ_8K:
|
||||
return 0x2000;
|
||||
case CHIPID_CIDR_NVPSIZ_16K:
|
||||
@ -197,9 +197,9 @@ static size_t sam_flash_size(uint32_t idcode)
|
||||
|
||||
bool sam3x_probe(target *t)
|
||||
{
|
||||
t->idcode = target_mem_read32(t, SAM3X_CHIPID_CIDR);
|
||||
size_t size = sam_flash_size(t->idcode);
|
||||
switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
|
||||
uint32_t cidr = target_mem_read32(t, SAM3X_CHIPID_CIDR);
|
||||
size_t size = sam_flash_size(cidr);
|
||||
switch (cidr & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
|
||||
case CHIPID_CIDR_ARCH_SAM3XxC | CHIPID_CIDR_EPROC_CM3:
|
||||
case CHIPID_CIDR_ARCH_SAM3XxE | CHIPID_CIDR_EPROC_CM3:
|
||||
case CHIPID_CIDR_ARCH_SAM3XxG | CHIPID_CIDR_EPROC_CM3:
|
||||
@ -212,9 +212,9 @@ bool sam3x_probe(target *t)
|
||||
return true;
|
||||
}
|
||||
|
||||
t->idcode = target_mem_read32(t, SAM34NSU_CHIPID_CIDR);
|
||||
size = sam_flash_size(t->idcode);
|
||||
switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
|
||||
cidr = target_mem_read32(t, SAM34NSU_CHIPID_CIDR);
|
||||
size = sam_flash_size(cidr);
|
||||
switch (cidr & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
|
||||
case CHIPID_CIDR_ARCH_SAM3NxA | CHIPID_CIDR_EPROC_CM3:
|
||||
case CHIPID_CIDR_ARCH_SAM3NxB | CHIPID_CIDR_EPROC_CM3:
|
||||
case CHIPID_CIDR_ARCH_SAM3NxC | CHIPID_CIDR_EPROC_CM3:
|
||||
@ -224,7 +224,7 @@ bool sam3x_probe(target *t)
|
||||
t->driver = "Atmel SAM3N/S";
|
||||
target_add_ram(t, 0x20000000, 0x200000);
|
||||
/* These devices only have a single bank */
|
||||
size = sam_flash_size(t->idcode);
|
||||
size = sam_flash_size(cidr);
|
||||
sam3_add_flash(t, SAM3N_EEFC_BASE, 0x400000, size);
|
||||
target_add_commands(t, sam3x_cmd_list, "SAM3N/S");
|
||||
return true;
|
||||
@ -248,7 +248,7 @@ bool sam3x_probe(target *t)
|
||||
case CHIPID_CIDR_ARCH_SAM4SDC | CHIPID_CIDR_EPROC_CM4:
|
||||
t->driver = "Atmel SAM4S";
|
||||
target_add_ram(t, 0x20000000, 0x400000);
|
||||
size_t size = sam_flash_size(t->idcode);
|
||||
size_t size = sam_flash_size(cidr);
|
||||
if (size <= 0x80000) {
|
||||
/* Smaller devices have a single bank */
|
||||
sam4_add_flash(t, SAM4S_EEFC_BASE(0), 0x400000, size);
|
||||
|
@ -186,13 +186,13 @@ static void sam4l_add_flash(target *t, uint32_t addr, size_t length)
|
||||
}
|
||||
|
||||
/* Return size of RAM */
|
||||
static size_t sam_ram_size(uint32_t idcode) {
|
||||
return __ram_size[((idcode >> CHIPID_CIDR_SRAMSIZ_SHIFT) & CHIPID_CIDR_SRAMSIZ_MASK)];
|
||||
static size_t sam_ram_size(uint32_t cidr) {
|
||||
return __ram_size[((cidr >> CHIPID_CIDR_SRAMSIZ_SHIFT) & CHIPID_CIDR_SRAMSIZ_MASK)];
|
||||
}
|
||||
|
||||
/* Return size of FLASH */
|
||||
static size_t sam_nvp_size(uint32_t idcode) {
|
||||
return __nvp_size[((idcode >> CHIPID_CIDR_NVPSIZ_SHIFT) & CHIPID_CIDR_NVPSIZ_MASK)];
|
||||
static size_t sam_nvp_size(uint32_t cidr) {
|
||||
return __nvp_size[((cidr >> CHIPID_CIDR_NVPSIZ_SHIFT) & CHIPID_CIDR_NVPSIZ_MASK)];
|
||||
}
|
||||
|
||||
#define SMAP_BASE 0x400a3000
|
||||
@ -228,14 +228,14 @@ bool sam4l_probe(target *t)
|
||||
{
|
||||
size_t ram_size, flash_size;
|
||||
|
||||
t->idcode = target_mem_read32(t, SAM4L_CHIPID_CIDR);
|
||||
if (((t->idcode >> CHIPID_CIDR_ARCH_SHIFT) & CHIPID_CIDR_ARCH_MASK) == SAM4L_ARCH) {
|
||||
uint32_t cidr = target_mem_read32(t, SAM4L_CHIPID_CIDR);
|
||||
if (((cidr >> CHIPID_CIDR_ARCH_SHIFT) & CHIPID_CIDR_ARCH_MASK) == SAM4L_ARCH) {
|
||||
t->driver = "Atmel SAM4L";
|
||||
/* this function says we need to do "extra" stuff after reset */
|
||||
t->extended_reset = sam4l_extended_reset;
|
||||
ram_size = sam_ram_size(t->idcode);
|
||||
ram_size = sam_ram_size(cidr);
|
||||
target_add_ram(t, 0x20000000, ram_size);
|
||||
flash_size = sam_nvp_size(t->idcode);
|
||||
flash_size = sam_nvp_size(cidr);
|
||||
sam4l_add_flash(t, 0x0, flash_size);
|
||||
DEBUG_INFO("\nSAM4L: RAM = 0x%x (%dK), FLASH = 0x%x (%dK)\n",
|
||||
(unsigned int) ram_size, (unsigned int) (ram_size / 1024),
|
||||
|
@ -847,8 +847,9 @@ static bool samd_cmd_ssb(target *t, int argc, const char **argv)
|
||||
if (target_check_error(t))
|
||||
return -1;
|
||||
|
||||
tc_printf(t, "Set the security bit! "
|
||||
"You will need to issue 'monitor erase_mass' to clear this.\n");
|
||||
tc_printf(t, "Security bit set! "
|
||||
"Scan again, attach and issue 'monitor erase_mass' to reset.\n");
|
||||
|
||||
target_reset(t);
|
||||
return true;
|
||||
}
|
||||
|
@ -118,9 +118,10 @@ static void stm32f1_add_flash(target *t,
|
||||
|
||||
bool stm32f1_probe(target *t)
|
||||
{
|
||||
if (t->t_designer == AP_DESIGNER_ARM)
|
||||
t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff;
|
||||
size_t flash_size;
|
||||
size_t block_size = 0x400;
|
||||
t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff;
|
||||
switch(t->idcode) {
|
||||
case 0x410: /* Medium density */
|
||||
case 0x412: /* Low density */
|
||||
@ -167,10 +168,6 @@ bool stm32f1_probe(target *t)
|
||||
stm32f1_add_flash(t, 0x8000000, 0x80000, 0x800);
|
||||
target_add_commands(t, stm32f1_cmd_list, "STM32F3");
|
||||
return true;
|
||||
}
|
||||
|
||||
t->idcode = target_mem_read32(t, DBGMCU_IDCODE_F0) & 0xfff;
|
||||
switch(t->idcode) {
|
||||
case 0x444: /* STM32F03 RM0091 Rev.7, STM32F030x[4|6] RM0360 Rev. 4*/
|
||||
t->driver = "STM32F03";
|
||||
flash_size = 0x8000;
|
||||
|
@ -197,28 +197,22 @@ char *stm32f4_get_chip_name(uint32_t idcode)
|
||||
|
||||
static void stm32f7_detach(target *t)
|
||||
{
|
||||
target_mem_write32(t, DBGMCU_CR, t->target_storage);
|
||||
ADIv5_AP_t *ap = cortexm_ap(t);
|
||||
target_mem_write32(t, DBGMCU_CR, ap->ap_storage);
|
||||
cortexm_detach(t);
|
||||
}
|
||||
|
||||
bool stm32f4_probe(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = cortexm_ap(t);
|
||||
uint32_t idcode;
|
||||
|
||||
idcode = (ap->dp->targetid >> 16) & 0xfff;
|
||||
if (!idcode)
|
||||
idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xFFF;
|
||||
|
||||
if (idcode == ID_STM32F20X) {
|
||||
if (t->idcode == ID_STM32F20X) {
|
||||
/* F405 revision A have a wrong IDCODE, use ARM_CPUID to make the
|
||||
* distinction with F205. Revision is also wrong (0x2000 instead
|
||||
* of 0x1000). See F40x/F41x errata. */
|
||||
uint32_t cpuid = target_mem_read32(t, ARM_CPUID);
|
||||
if ((cpuid & 0xFFF0) == 0xC240)
|
||||
idcode = ID_STM32F40X;
|
||||
t->idcode = ID_STM32F40X;
|
||||
}
|
||||
switch(idcode) {
|
||||
switch(t->idcode) {
|
||||
case ID_STM32F74X: /* F74x RM0385 Rev.4 */
|
||||
case ID_STM32F76X: /* F76x F77x RM0410 */
|
||||
case ID_STM32F72X: /* F72x F73x RM0431 */
|
||||
@ -234,8 +228,7 @@ bool stm32f4_probe(target *t)
|
||||
case ID_STM32F412: /* F412 RM0402 Rev.4, 256 kB Ram */
|
||||
case ID_STM32F401E: /* F401 D/E RM0368 Rev.3 */
|
||||
case ID_STM32F413: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */
|
||||
t->idcode = idcode;
|
||||
t->driver = stm32f4_get_chip_name(idcode);
|
||||
t->driver = stm32f4_get_chip_name(t->idcode);
|
||||
t->attach = stm32f4_attach;
|
||||
target_add_commands(t, stm32f4_cmd_list, t->driver);
|
||||
return true;
|
||||
@ -306,8 +299,6 @@ static bool stm32f4_attach(target *t)
|
||||
bool use_dual_bank = false;
|
||||
target_mem_map_free(t);
|
||||
if (is_f7) {
|
||||
t->target_storage = target_mem_read32(t, DBGMCU_CR);
|
||||
target_mem_write32(t, DBGMCU_CR, DBG_SLEEP);
|
||||
target_add_ram(t, 0x00000000, 0x4000); /* 16 k ITCM Ram */
|
||||
target_add_ram(t, 0x20000000, 0x20000); /* 128 k DTCM Ram */
|
||||
target_add_ram(t, 0x20020000, 0x60000); /* 384 k Ram */
|
||||
|
@ -57,7 +57,7 @@ static int stm32h7_flash_erase(struct target_flash *f, target_addr addr,
|
||||
static int stm32h7_flash_write(struct target_flash *f,
|
||||
target_addr dest, const void *src, size_t len);
|
||||
|
||||
static const char stm32h74_driver_str[] = "STM32H74x";
|
||||
static const char stm32h7_driver_str[] = "STM32H7";
|
||||
|
||||
enum stm32h7_regs
|
||||
{
|
||||
@ -142,14 +142,14 @@ enum stm32h7_regs
|
||||
#define D3DBGCKEN (1 << 22)
|
||||
|
||||
|
||||
#define FLASH_SIZE_REG 0x1ff1e880
|
||||
|
||||
#define BANK1_START 0x08000000
|
||||
#define NUM_SECTOR_PER_BANK 8
|
||||
#define FLASH_SECTOR_SIZE 0x20000
|
||||
#define BANK2_START 0x08100000
|
||||
enum ID_STM32H7 {
|
||||
ID_STM32H74x = 0x450,
|
||||
ID_STM32H74x = 0x450, /* RM0433, RM0399 */
|
||||
ID_STM32H7Bx = 0x480, /* RM0455 */
|
||||
ID_STM32H72x = 0x483, /* RM0468 */
|
||||
};
|
||||
|
||||
struct stm32h7_flash {
|
||||
@ -188,11 +188,6 @@ static bool stm32h7_attach(target *t)
|
||||
{
|
||||
if (!cortexm_attach(t))
|
||||
return false;
|
||||
/* RM0433 Rev 4 is not really clear, what bits are needed.
|
||||
* Set all possible relevant bits for now. */
|
||||
uint32_t dbgmcu_cr = target_mem_read32(t, DBGMCU_CR);
|
||||
t->target_storage = dbgmcu_cr;
|
||||
target_mem_write32(t, DBGMCU_CR, DBGSLEEP_D1 | D1DBGCKEN);
|
||||
/* If IWDG runs as HARDWARE watchdog (44.3.4) erase
|
||||
* will be aborted by the Watchdog and erase fails!
|
||||
* Setting IWDG_KR to 0xaaaa does not seem to help!*/
|
||||
@ -226,14 +221,18 @@ static void stm32h7_detach(target *t)
|
||||
|
||||
bool stm32h7_probe(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = cortexm_ap(t);
|
||||
uint32_t idcode = (ap->dp->targetid >> 16) & 0xfff;
|
||||
if (idcode == ID_STM32H74x) {
|
||||
t->idcode = idcode;
|
||||
t->driver = stm32h74_driver_str;
|
||||
uint32_t idcode = t->idcode;
|
||||
if (idcode == ID_STM32H74x || idcode == ID_STM32H7Bx || idcode == ID_STM32H72x) {
|
||||
t->driver = stm32h7_driver_str;
|
||||
t->attach = stm32h7_attach;
|
||||
t->detach = stm32h7_detach;
|
||||
target_add_commands(t, stm32h7_cmd_list, stm32h74_driver_str);
|
||||
target_add_commands(t, stm32h7_cmd_list, stm32h7_driver_str);
|
||||
t->target_storage = target_mem_read32(t, DBGMCU_CR);
|
||||
/* RM0433 Rev 4 is not really clear, what bits are needed in DBGMCU_CR.
|
||||
* Maybe more flags needed?
|
||||
*/
|
||||
uint32_t dbgmcu_cr = DBGSLEEP_D1 | D1DBGCKEN;
|
||||
target_mem_write32(t, DBGMCU_CR, dbgmcu_cr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -439,7 +438,12 @@ static bool stm32h7_uid(target *t, int argc, const char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
uint32_t uid = 0x1ff1e800;
|
||||
if (t->idcode == ID_STM32H7Bx) {
|
||||
uid = 0x08fff800; /* 7B3/7A3/7B0 */
|
||||
}
|
||||
|
||||
int i;
|
||||
tc_printf(t, "0x");
|
||||
for (i = 0; i < 12; i = i + 4) {
|
||||
@ -555,21 +559,28 @@ static bool stm32h7_cmd_rev(target *t, int argc, const char **argv)
|
||||
switch (dev_id) {
|
||||
case 0x450:
|
||||
tc_printf(t, "STM32H742/743/753/750\n");
|
||||
|
||||
/* Print revision */
|
||||
char rev = '?';
|
||||
for (size_t i = 0;
|
||||
i < sizeof(stm32h7xx_revisions)/sizeof(struct stm32h7xx_rev); i++) {
|
||||
/* Check for matching revision */
|
||||
if (stm32h7xx_revisions[i].rev_id == rev_id) {
|
||||
rev = stm32h7xx_revisions[i].revision;
|
||||
}
|
||||
}
|
||||
tc_printf(t, "Revision %c\n", rev);
|
||||
break;
|
||||
|
||||
case 0x480:
|
||||
tc_printf(t, "STM32H7B3/7A3/7B0\n");
|
||||
break;
|
||||
case 0x483:
|
||||
tc_printf(t, "STM32H723/733/725/735/730\n");
|
||||
break;
|
||||
default:
|
||||
tc_printf(t, "Unknown STM32H7. This driver may not support it!\n");
|
||||
}
|
||||
|
||||
/* Print revision */
|
||||
char rev = '?';
|
||||
for (size_t i = 0;
|
||||
i < sizeof(stm32h7xx_revisions)/sizeof(struct stm32h7xx_rev); i++) {
|
||||
/* Check for matching revision */
|
||||
if (stm32h7xx_revisions[i].rev_id == rev_id) {
|
||||
rev = stm32h7xx_revisions[i].revision;
|
||||
}
|
||||
}
|
||||
tc_printf(t, "Revision %c\n", rev);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -268,31 +268,22 @@ static void stm32l_add_eeprom(target *t, uint32_t addr, size_t length)
|
||||
STM32L0xx parts as well as the STM32L1xx's. */
|
||||
bool stm32l0_probe(target* t)
|
||||
{
|
||||
uint32_t idcode;
|
||||
|
||||
idcode = target_mem_read32(t, STM32L1_DBGMCU_IDCODE_PHYS) & 0xfff;
|
||||
switch (idcode) {
|
||||
switch (t->idcode) {
|
||||
case 0x416: /* CAT. 1 device */
|
||||
case 0x429: /* CAT. 2 device */
|
||||
case 0x427: /* CAT. 3 device */
|
||||
case 0x436: /* CAT. 4 device */
|
||||
case 0x437: /* CAT. 5 device */
|
||||
t->idcode = idcode;
|
||||
t->driver = "STM32L1x";
|
||||
target_add_ram(t, 0x20000000, 0x14000);
|
||||
stm32l_add_flash(t, 0x8000000, 0x80000, 0x100);
|
||||
//stm32l_add_eeprom(t, 0x8080000, 0x4000);
|
||||
target_add_commands(t, stm32lx_cmd_list, "STM32L1x");
|
||||
return true;
|
||||
}
|
||||
|
||||
idcode = target_mem_read32(t, STM32L0_DBGMCU_IDCODE_PHYS) & 0xfff;
|
||||
switch (idcode) {
|
||||
case 0x457: /* STM32L0xx Cat1 */
|
||||
case 0x425: /* STM32L0xx Cat2 */
|
||||
case 0x417: /* STM32L0xx Cat3 */
|
||||
case 0x447: /* STM32L0xx Cat5 */
|
||||
t->idcode = idcode;
|
||||
t->driver = "STM32L0x";
|
||||
target_add_ram(t, 0x20000000, 0x5000);
|
||||
stm32l_add_flash(t, 0x8000000, 0x10000, 0x80);
|
||||
|
@ -373,18 +373,11 @@ static void stm32l4_detach(target *t)
|
||||
|
||||
bool stm32l4_probe(target *t)
|
||||
{
|
||||
uint32_t idcode_reg = STM32L4_DBGMCU_IDCODE_PHYS;
|
||||
ADIv5_AP_t *ap = cortexm_ap(t);
|
||||
if (ap->dp->idcode == 0x0BC11477)
|
||||
idcode_reg = STM32G0_DBGMCU_IDCODE_PHYS;
|
||||
uint32_t idcode = target_mem_read32(t, idcode_reg) & 0xfff;
|
||||
|
||||
struct stm32l4_info const *chip = stm32l4_get_chip_info(idcode);
|
||||
struct stm32l4_info const *chip = stm32l4_get_chip_info(t->idcode);
|
||||
|
||||
if( !chip->idcode ) /* Not found */
|
||||
return false;
|
||||
|
||||
t->idcode = idcode;
|
||||
t->driver = chip->designator;
|
||||
t->attach = stm32l4_attach;
|
||||
t->detach = stm32l4_detach;
|
||||
|
@ -502,6 +502,16 @@ const char *target_core_name(target *t)
|
||||
return t->core;
|
||||
}
|
||||
|
||||
unsigned int target_designer(target *t)
|
||||
{
|
||||
return t->t_designer;
|
||||
}
|
||||
|
||||
unsigned int target_idcode(target *t)
|
||||
{
|
||||
return t->idcode;
|
||||
}
|
||||
|
||||
uint32_t target_mem_read32(target *t, uint32_t addr)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
@ -111,7 +111,8 @@ struct target_s {
|
||||
|
||||
/* target-defined options */
|
||||
unsigned target_options;
|
||||
uint32_t idcode;
|
||||
uint16_t t_designer;
|
||||
uint16_t idcode;
|
||||
uint32_t target_storage;
|
||||
|
||||
struct target_ram *ram;
|
||||
|
Loading…
x
Reference in New Issue
Block a user