Merge commit '59dc1b7eb4f3a0fda23d2c8624c3ecd26515fec8' into sam-update

# Conflicts:
#	src/platforms/common/cdcacm.c
This commit is contained in:
Jason Kotzin 2022-08-10 18:33:59 -07:00
commit c73329f7d4
36 changed files with 594 additions and 306 deletions

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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!*/
}

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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) {

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;

View File

@ -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.

View File

@ -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(&param, 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);

View File

@ -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, \

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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.*/

View File

@ -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);

View File

@ -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[];

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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),

View File

@ -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;
}

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;