Merge pull request #976 from riscv/from_upstream

Merge up to d4575b647a from upstream
This commit is contained in:
Tim Newsome 2023-12-21 09:23:11 -08:00 committed by GitHub
commit 62758f2087
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 1830 additions and 370 deletions

130
LICENSES/preferred/CC0-1.0 Normal file
View File

@ -0,0 +1,130 @@
Valid-License-Identifier: CC0-1.0
SPDX-URL: https://spdx.org/licenses/CC0-1.0.html
Usage-Guide:
To use the Creative Commons Zero v1.0 Universal License put the following
SPDX tag/value pair into a comment according to the placement guidelines in
the licensing rules documentation:
SPDX-License-Identifier: CC0-1.0
License-Text:
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

View File

@ -66,6 +66,7 @@ EXTRA_DIST += \
LICENSES/preferred/BSD-2-Clause-Views \
LICENSES/preferred/BSD-3-Clause \
LICENSES/preferred/BSD-Source-Code \
LICENSES/preferred/CC0-1.0 \
LICENSES/preferred/GFDL-1.2 \
LICENSES/preferred/gfdl-1.2.texi.readme \
LICENSES/preferred/GPL-2.0 \

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-License-Identifier: CC0-1.0
/*
* Since at least FreeRTOS V7.5.3 uxTopUsedPriority is no longer

View File

@ -5325,6 +5325,18 @@ Displays the current target state:
(Also, @pxref{eventpolling,,Event Polling}.)
@end deffn
@deffn {Command} {$target_name debug_reason}
Displays the current debug reason:
@code{debug-request},
@code{breakpoint},
@code{watchpoint},
@code{watchpoint-and-breakpoint},
@code{single-step},
@code{target-not-halted},
@code{program-exit},
@code{exception-catch} or @code{undefined}.
@end deffn
@deffn {Command} {$target_name eventlist}
Displays a table listing all event handlers
currently associated with this target.
@ -9387,8 +9399,8 @@ for similar mechanisms that do not consume hardware breakpoints.)
Remove the breakpoint at @var{address} or all breakpoints.
@end deffn
@deffn {Command} {rwp} address
Remove data watchpoint on @var{address}
@deffn {Command} {rwp} @option{all} | address
Remove data watchpoint on @var{address} or all watchpoints.
@end deffn
@deffn {Command} {wp} [address len [(@option{r}|@option{w}|@option{a}) [value [mask]]]]
@ -12709,7 +12721,7 @@ Return information about the flash banks
@item @b{capture} <@var{command}>
Run <@var{command}> and return full log output that was produced during
its execution. Example:
its execution together with the command output. Example:
@example
> capture "reset init"

View File

@ -815,7 +815,8 @@ static const struct command_registration rsl10_exec_command_handlers[] = {
.help = "Mass erase all unprotected flash areas",
.usage = "",
},
COMMAND_REGISTRATION_DONE};
COMMAND_REGISTRATION_DONE
};
static const struct command_registration rsl10_command_handlers[] = {
{
@ -825,7 +826,8 @@ static const struct command_registration rsl10_command_handlers[] = {
.usage = "",
.chain = rsl10_exec_command_handlers,
},
COMMAND_REGISTRATION_DONE};
COMMAND_REGISTRATION_DONE
};
const struct flash_driver rsl10_flash = {
.name = "rsl10",

View File

@ -22,10 +22,22 @@
/* Shared table of known SPI flash devices for SPI-based flash drivers. Taken
* from device datasheets and Linux SPI flash drivers. */
const struct flash_device flash_devices[] = {
/* name, read_cmd, qread_cmd, pprog_cmd, erase_cmd, chip_erase_cmd, device_id,
* pagesize, sectorsize, size_in_bytes
* note: device id is usually 3 bytes long, however the unused highest byte counts
* continuation codes for manufacturer id as per JEP106xx */
/* Note: device_id is usually 3 bytes long, however the unused highest byte counts
* continuation codes for manufacturer id as per JEP106xx.
*
* All sizes (page, sector/block and flash) are in bytes.
*
* Guide to select a proper erase command (if both sector and block erase cmds are available):
* Use 4kbit sector erase cmd and set erase size to the size of sector for small devices
* (4Mbit and less, size <= 0x80000) to prevent too raw erase granularity.
* Use 64kbit block erase cmd and set erase size to the size of block for bigger devices
* (8Mbit and more, size >= 0x100000) to keep erase speed reasonable.
* If the device implements also 32kbit block erase, use it for 8Mbit, size == 0x100000.
*/
/* name read qread page erase chip device_id page erase flash
* _cmd _cmd _prog _cmd* _erase size size* size
* _cmd _cmd
*/
FLASH_ID("st m25pe10", 0x03, 0x00, 0x02, 0xd8, 0x00, 0x00118020, 0x100, 0x10000, 0x20000),
FLASH_ID("st m25pe20", 0x03, 0x00, 0x02, 0xd8, 0x00, 0x00128020, 0x100, 0x10000, 0x40000),
FLASH_ID("st m25pe40", 0x03, 0x00, 0x02, 0xd8, 0x00, 0x00138020, 0x100, 0x10000, 0x80000),
@ -174,6 +186,11 @@ const struct flash_device flash_devices[] = {
FLASH_ID("zetta zd25q16", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001560ba, 0x100, 0x10000, 0x200000),
/* FRAM, no erase commands, no write page or sectors */
/* name read qread page device_id total
* _cmd _cmd _prog size
* _cmd
*/
FRAM_ID("fu mb85rs16n", 0x03, 0, 0x02, 0x00010104, 0x800),
FRAM_ID("fu mb85rs32v", 0x03, 0, 0x02, 0x00010204, 0x1000), /* exists ? */
FRAM_ID("fu mb85rs64v", 0x03, 0, 0x02, 0x00020304, 0x2000),

View File

@ -99,8 +99,7 @@ static struct log_capture_state *command_log_capture_start(Jim_Interp *interp)
* The tcl return value is empty for openocd commands that provide
* progress output.
*
* Therefore we set the tcl return value only if we actually
* captured output.
* For other commands, we prepend the logs to the tcl return value.
*/
static void command_log_capture_finish(struct log_capture_state *state)
{
@ -109,15 +108,18 @@ static void command_log_capture_finish(struct log_capture_state *state)
log_remove_callback(tcl_output, state);
int length;
Jim_GetString(state->output, &length);
int loglen;
const char *log_result = Jim_GetString(state->output, &loglen);
int reslen;
const char *cmd_result = Jim_GetString(Jim_GetResult(state->interp), &reslen);
if (length > 0)
Jim_SetResult(state->interp, state->output);
else {
/* No output captured, use tcl return value (which could
* be empty too). */
}
// Just in case the log doesn't end with a newline, we add it
if (loglen != 0 && reslen != 0 && log_result[loglen - 1] != '\n')
Jim_AppendString(state->interp, state->output, "\n", 1);
Jim_AppendString(state->interp, state->output, cmd_result, reslen);
Jim_SetResult(state->interp, state->output);
Jim_DecrRefCount(state->interp, state->output);
free(state);
@ -691,8 +693,8 @@ COMMAND_HANDLER(handle_echo)
return ERROR_OK;
}
/* Capture progress output and return as tcl return value. If the
* progress output was empty, return tcl return value.
/* Return both the progress output (LOG_INFO and higher)
* and the tcl return value of a command.
*/
static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{

View File

@ -2,15 +2,15 @@
/*
* The manufacturer's standard identification code list appears in JEP106.
* Copyright (c) 2022 JEDEC. All rights reserved.
* Copyright (c) 2023 JEDEC. All rights reserved.
*
* JEP106 is regularly updated. For the current manufacturer's standard
* identification code list, please visit the JEDEC website at www.jedec.org .
*/
/* This file is aligned to revision JEP106BG May 2023. */
/* This file is aligned to revision JEP106BH September 2023. */
/* "NXP (Philips)" is reported below, while missing in JEP106BG */
/* "NXP (Philips)" is reported below, while missing since JEP106BG */
[0][0x01 - 1] = "AMD",
[0][0x02 - 1] = "AMI",
@ -1375,7 +1375,7 @@
[10][0x65 - 1] = "Esperanto Technologies",
[10][0x66 - 1] = "JinSheng Electronic (Shenzhen) Co Ltd",
[10][0x67 - 1] = "Shenzhen Shi Bolunshuai Technology",
[10][0x68 - 1] = "Shanghai Rei Zuan Information Tech",
[10][0x68 - 1] = "Shanghai Rui Zuan Information Tech",
[10][0x69 - 1] = "Fraunhofer IIS",
[10][0x6a - 1] = "Kandou Bus SA",
[10][0x6b - 1] = "Acer",
@ -1841,4 +1841,51 @@
[14][0x3f - 1] = "Shenzhen Dingsheng Technology Co Ltd",
[14][0x40 - 1] = "EVAS Intelligence Co Ltd",
[14][0x41 - 1] = "Kaibright Electronic Technologies",
[14][0x42 - 1] = "Fraunhofer IMS",
[14][0x43 - 1] = "Shenzhen Xinrui Renhe Technology",
[14][0x44 - 1] = "Beijing Vcore Technology Co Ltd",
[14][0x45 - 1] = "Silicon Innovation Technologies Co Ltd",
[14][0x46 - 1] = "Shenzhen Zhengxinda Technology Co Ltd",
[14][0x47 - 1] = "Shenzhen Remai Electronics Co Lttd",
[14][0x48 - 1] = "Shenzhen Xinruiyan Electronics Co Ltd",
[14][0x49 - 1] = "CEC Huada Electronic Design Co Ltd",
[14][0x4a - 1] = "Westberry Technology Inc",
[14][0x4b - 1] = "Tongxin Microelectronics Co Ltd",
[14][0x4c - 1] = "UNIM Semiconductor (Shang Hai) Co Ltd",
[14][0x4d - 1] = "Shenzhen Qiaowenxingyu Industrial Co Ltd",
[14][0x4e - 1] = "ICC",
[14][0x4f - 1] = "Enfabrica Corporation",
[14][0x50 - 1] = "Niobium Microsystems Inc",
[14][0x51 - 1] = "Xiaoli AI Electronics (Shenzhen) Co Ltd",
[14][0x52 - 1] = "Silicon Mitus",
[14][0x53 - 1] = "Ajiatek Inc",
[14][0x54 - 1] = "HomeNet",
[14][0x55 - 1] = "Shenzhen Shubang Technology Co Ltd",
[14][0x56 - 1] = "Exacta Technologies Ltd",
[14][0x57 - 1] = "Synology",
[14][0x58 - 1] = "Trium Elektronik Bilgi Islem San Ve Dis",
[14][0x59 - 1] = "Shenzhen Hippstor Technology Co Ltd",
[14][0x5a - 1] = "SSCT",
[14][0x5b - 1] = "Sichuan Heentai Semiconductor Co Ltd",
[14][0x5c - 1] = "Zhejiang University",
[14][0x5d - 1] = "www.shingroup.cn",
[14][0x5e - 1] = "Suzhou Nano Mchip Technology Company",
[14][0x5f - 1] = "Feature Integration Technology Inc",
[14][0x60 - 1] = "d-Matrix",
[14][0x61 - 1] = "Golden Memory",
[14][0x62 - 1] = "Qingdao Thunderobot Technology Co Ltd",
[14][0x63 - 1] = "Shenzhen Tianxiang Chuangxin Technology",
[14][0x64 - 1] = "HYPHY USA",
[14][0x65 - 1] = "Valkyrie",
[14][0x66 - 1] = "Suzhou Hesetc Electronic Technology Co",
[14][0x67 - 1] = "Hainan Zhongyuncun Technology Co Ltd",
[14][0x68 - 1] = "Shenzhen Yousheng Bona Technology Co",
[14][0x69 - 1] = "Shenzhen Xinle Chuang Technology Co",
[14][0x6a - 1] = "DEEPX",
[14][0x6b - 1] = "iStarChip CA LLC",
[14][0x6c - 1] = "Shenzhen Vinreada Technology Co Ltd",
[14][0x6d - 1] = "Novatek Microelectronics Corp",
[14][0x6e - 1] = "Chemgdu EG Technology Co Ltd",
[14][0x6f - 1] = "AGI Technology",
[14][0x70 - 1] = "Syntiant",
/* EOF */

View File

@ -257,7 +257,7 @@ static int angie_usb_open(struct angie *device)
const uint16_t vids[] = {ANGIE_VID, ANGIE_VID, ANGIE_VID, ANGIE_VID, 0};
const uint16_t pids[] = {ANGIE_PID, ANGIE_PID_2, ANGIE_PID_3, ANGIE_PID_4, 0};
int ret = jtag_libusb_open(vids, pids, &usb_device_handle, NULL);
int ret = jtag_libusb_open(vids, pids, NULL, &usb_device_handle, NULL);
if (ret != ERROR_OK)
return ret;

View File

@ -677,7 +677,7 @@ static struct armjtagew *armjtagew_usb_open(void)
const uint16_t pids[] = { USB_PID, 0 };
struct libusb_device_handle *dev;
if (jtag_libusb_open(vids, pids, &dev, NULL) != ERROR_OK)
if (jtag_libusb_open(vids, pids, NULL, &dev, NULL) != ERROR_OK)
return NULL;
struct armjtagew *result = malloc(sizeof(struct armjtagew));

View File

@ -331,7 +331,7 @@ COMMAND_HANDLER(bcm2835gpio_handle_peripheral_base)
}
tmp_base = bcm2835_peri_base;
command_print(CMD, "BCM2835 GPIO: peripheral_base = 0x%08" PRIu64,
command_print(CMD, "BCM2835 GPIO: peripheral_base = 0x%08" PRIx64,
tmp_base);
return ERROR_OK;
}

View File

@ -487,7 +487,7 @@ static int esp_usb_jtag_init(void)
bitq_interface->in_rdy = esp_usb_jtag_in_rdy;
bitq_interface->in = esp_usb_jtag_in;
int r = jtag_libusb_open(vids, pids, &priv->usb_device, NULL);
int r = jtag_libusb_open(vids, pids, NULL, &priv->usb_device, NULL);
if (r != ERROR_OK) {
LOG_ERROR("esp_usb_jtag: could not find or open device!");
goto out;

View File

@ -246,7 +246,7 @@ static int ft232r_init(void)
{
uint16_t avids[] = {ft232r_vid, 0};
uint16_t apids[] = {ft232r_pid, 0};
if (jtag_libusb_open(avids, apids, &adapter, NULL)) {
if (jtag_libusb_open(avids, apids, NULL, &adapter, NULL)) {
const char *ft232r_serial_desc = adapter_get_required_serial();
LOG_ERROR("ft232r not found: vid=%04x, pid=%04x, serial=%s\n",
ft232r_vid, ft232r_pid, (!ft232r_serial_desc) ? "[any]" : ft232r_serial_desc);

View File

@ -275,7 +275,7 @@ static int kitprog_usb_open(void)
const uint16_t vids[] = { VID, 0 };
const uint16_t pids[] = { PID, 0 };
if (jtag_libusb_open(vids, pids, &kitprog_handle->usb_handle, NULL) != ERROR_OK) {
if (jtag_libusb_open(vids, pids, NULL, &kitprog_handle->usb_handle, NULL) != ERROR_OK) {
LOG_ERROR("Failed to open or find the device");
return ERROR_FAIL;
}

View File

@ -146,12 +146,13 @@ static bool jtag_libusb_match_serial(struct libusb_device_handle *device,
}
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
struct libusb_device_handle **out,
const char *product, struct libusb_device_handle **out,
adapter_get_alternate_serial_fn adapter_get_alternate_serial)
{
int cnt, idx, err_code;
int retval = ERROR_FAIL;
bool serial_mismatch = false;
bool product_mismatch = false;
struct libusb_device_handle *libusb_handle = NULL;
const char *serial = adapter_get_required_serial();
@ -188,10 +189,18 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
continue;
}
if (product &&
!string_descriptor_equal(libusb_handle, dev_desc.iProduct, product)) {
product_mismatch = true;
libusb_close(libusb_handle);
continue;
}
/* Success. */
*out = libusb_handle;
retval = ERROR_OK;
serial_mismatch = false;
product_mismatch = false;
break;
}
if (cnt >= 0)
@ -200,6 +209,9 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
if (serial_mismatch)
LOG_INFO("No device matches the serial string");
if (product_mismatch)
LOG_INFO("No device matches the product string");
if (retval != ERROR_OK)
libusb_exit(jtag_libusb_context);

View File

@ -33,7 +33,7 @@ typedef char * (*adapter_get_alternate_serial_fn)(struct libusb_device_handle *d
bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc,
const uint16_t vids[], const uint16_t pids[]);
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
struct libusb_device_handle **out,
const char *product, struct libusb_device_handle **out,
adapter_get_alternate_serial_fn adapter_get_alternate_serial);
void jtag_libusb_close(struct libusb_device_handle *dev);
int jtag_libusb_control_transfer(struct libusb_device_handle *dev,

View File

@ -695,7 +695,7 @@ struct opendous_jtag *opendous_usb_open(void)
struct opendous_jtag *result;
struct libusb_device_handle *devh;
if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, &devh, NULL) != ERROR_OK)
if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, NULL, &devh, NULL) != ERROR_OK)
return NULL;
jtag_libusb_set_configuration(devh, 0);

View File

@ -438,7 +438,7 @@ static int openjtag_init_cy7c65215(void)
int ret;
usbh = NULL;
ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, &usbh, NULL);
ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh, NULL);
if (ret != ERROR_OK) {
LOG_ERROR("unable to open cy7c65215 device");
goto err;

View File

@ -363,7 +363,7 @@ static int osbdm_flush(struct osbdm *osbdm, struct queue *queue)
static int osbdm_open(struct osbdm *osbdm)
{
(void)memset(osbdm, 0, sizeof(*osbdm));
if (jtag_libusb_open(osbdm_vid, osbdm_pid, &osbdm->devh, NULL) != ERROR_OK)
if (jtag_libusb_open(osbdm_vid, osbdm_pid, NULL, &osbdm->devh, NULL) != ERROR_OK)
return ERROR_FAIL;
if (libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)

View File

@ -1448,7 +1448,7 @@ static int rlink_init(void)
const uint16_t vids[] = { USB_IDVENDOR, 0 };
const uint16_t pids[] = { USB_IDPRODUCT, 0 };
if (jtag_libusb_open(vids, pids, &hdev, NULL) != ERROR_OK)
if (jtag_libusb_open(vids, pids, NULL, &hdev, NULL) != ERROR_OK)
return ERROR_FAIL;
struct libusb_device_descriptor descriptor;

View File

@ -3406,7 +3406,7 @@ static int stlink_usb_usb_open(void *handle, struct hl_interface_param_s *param)
in order to become operational.
*/
do {
if (jtag_libusb_open(param->vid, param->pid,
if (jtag_libusb_open(param->vid, param->pid, NULL,
&h->usb_backend_priv.fd, stlink_usb_get_alternate_serial) != ERROR_OK) {
LOG_ERROR("open failed");
return ERROR_FAIL;

View File

@ -675,7 +675,7 @@ static int icdi_usb_open(struct hl_interface_param_s *param, void **fd)
/* TI (Stellaris) ICDI provides its serial number in the USB descriptor;
no need to provide a callback here. */
jtag_libusb_open(param->vid, param->pid, &h->usb_dev, NULL);
jtag_libusb_open(param->vid, param->pid, NULL, &h->usb_dev, NULL);
if (!h->usb_dev) {
LOG_ERROR("open failed");

View File

@ -202,7 +202,7 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
bool renumeration = false;
int ret;
if (jtag_libusb_open(vids, pids, &temp, NULL) == ERROR_OK) {
if (jtag_libusb_open(vids, pids, NULL, &temp, NULL) == ERROR_OK) {
LOG_INFO("Altera USB-Blaster II (uninitialized) found");
LOG_INFO("Loading firmware...");
ret = load_usb_blaster_firmware(temp, low);
@ -216,13 +216,13 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
const uint16_t pids_renum[] = { low->ublast_pid, 0 };
if (renumeration == false) {
if (jtag_libusb_open(vids_renum, pids_renum, &low->libusb_dev, NULL) != ERROR_OK) {
if (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev, NULL) != ERROR_OK) {
LOG_ERROR("Altera USB-Blaster II not found");
return ERROR_FAIL;
}
} else {
int retry = 10;
while (jtag_libusb_open(vids_renum, pids_renum, &low->libusb_dev, NULL) != ERROR_OK && retry--) {
while (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev, NULL) != ERROR_OK && retry--) {
usleep(1000000);
LOG_INFO("Waiting for reenumerate...");
}

View File

@ -341,7 +341,7 @@ struct usbprog_jtag *usbprog_jtag_open(void)
const uint16_t pids[] = { PID, 0 };
struct libusb_device_handle *dev;
if (jtag_libusb_open(vids, pids, &dev, NULL) != ERROR_OK)
if (jtag_libusb_open(vids, pids, NULL, &dev, NULL) != ERROR_OK)
return NULL;
struct usbprog_jtag *tmp = malloc(sizeof(struct usbprog_jtag));

View File

@ -121,6 +121,7 @@ static int lattice_certus_enable_programming(struct jtag_tap *tap)
uint8_t buffer = 0;
field.num_bits = 8;
field.out_value = &buffer;
field.in_value = NULL;
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
jtag_add_runtest(2, TAP_IDLE);
return jtag_execute_queue();

View File

@ -83,6 +83,7 @@ static void os_free(struct target *target)
return;
free(target->rtos->symbols);
rtos_free_threadlist(target->rtos);
free(target->rtos);
target->rtos = NULL;
}

View File

@ -95,6 +95,8 @@ struct gdb_connection {
char *thread_list;
/* flag to mask the output from gdb_log_callback() */
enum gdb_output_flag output_flag;
/* Unique index for this GDB connection. */
unsigned int unique_index;
};
#if 0
@ -392,6 +394,7 @@ static void gdb_log_incoming_packet(struct connection *connection, char *packet)
return;
struct target *target = get_target_from_connection(connection);
struct gdb_connection *gdb_connection = connection->priv;
/* Avoid dumping non-printable characters to the terminal */
const unsigned packet_len = strlen(packet);
@ -406,14 +409,15 @@ static void gdb_log_incoming_packet(struct connection *connection, char *packet)
if (packet_prefix_printable) {
const unsigned int prefix_len = colon - packet + 1; /* + 1 to include the ':' */
const unsigned int payload_len = packet_len - prefix_len;
LOG_TARGET_DEBUG(target, "received packet: %.*s<binary-data-%u-bytes>", prefix_len,
packet, payload_len);
LOG_TARGET_DEBUG(target, "{%d} received packet: %.*s<binary-data-%u-bytes>",
gdb_connection->unique_index, prefix_len, packet, payload_len);
} else {
LOG_TARGET_DEBUG(target, "received packet: <binary-data-%u-bytes>", packet_len);
LOG_TARGET_DEBUG(target, "{%d} received packet: <binary-data-%u-bytes>",
gdb_connection->unique_index, packet_len);
}
} else {
/* All chars printable, dump the packet as is */
LOG_TARGET_DEBUG(target, "received packet: %s", packet);
LOG_TARGET_DEBUG(target, "{%d} received packet: %s", gdb_connection->unique_index, packet);
}
}
@ -424,13 +428,14 @@ static void gdb_log_outgoing_packet(struct connection *connection, char *packet_
return;
struct target *target = get_target_from_connection(connection);
struct gdb_connection *gdb_connection = connection->priv;
if (find_nonprint_char(packet_buf, packet_len))
LOG_TARGET_DEBUG(target, "sending packet: $<binary-data-%u-bytes>#%2.2x",
packet_len, checksum);
LOG_TARGET_DEBUG(target, "{%d} sending packet: $<binary-data-%u-bytes>#%2.2x",
gdb_connection->unique_index, packet_len, checksum);
else
LOG_TARGET_DEBUG(target, "sending packet: $%.*s#%2.2x", packet_len, packet_buf,
checksum);
LOG_TARGET_DEBUG(target, "{%d} sending packet: $%.*s#%2.2x",
gdb_connection->unique_index, packet_len, packet_buf, checksum);
}
static int gdb_put_packet_inner(struct connection *connection,
@ -1017,6 +1022,7 @@ static int gdb_new_connection(struct connection *connection)
struct target *target;
int retval;
int initial_ack;
static unsigned int next_unique_id = 1;
target = get_target_from_connection(connection);
connection->priv = gdb_connection;
@ -1039,6 +1045,7 @@ static int gdb_new_connection(struct connection *connection)
gdb_connection->target_desc.tdesc_length = 0;
gdb_connection->thread_list = NULL;
gdb_connection->output_flag = GDB_OUTPUT_NO;
gdb_connection->unique_index = next_unique_id++;
/* send ACK to GDB for debug request */
gdb_write(connection, "+", 1);
@ -1097,20 +1104,19 @@ static int gdb_new_connection(struct connection *connection)
}
}
gdb_actual_connections++;
log_printf_lf(all_targets->next ? LOG_LVL_INFO : LOG_LVL_DEBUG,
__FILE__, __LINE__, __func__,
"New GDB Connection: %d, Target %s, state: %s",
gdb_actual_connections,
gdb_connection->unique_index,
target_name(target),
target_state_name(target));
if (!target_was_examined(target)) {
LOG_ERROR("Target %s not examined yet, refuse gdb connection %d!",
target_name(target), gdb_actual_connections);
gdb_actual_connections--;
target_name(target), gdb_connection->unique_index);
return ERROR_TARGET_NOT_EXAMINED;
}
gdb_actual_connections++;
if (target->state != TARGET_HALTED)
LOG_WARNING("GDB connection %d on target %s not halted",
@ -1141,7 +1147,8 @@ static int gdb_connection_closed(struct connection *connection)
log_remove_callback(gdb_log_callback, connection);
gdb_actual_connections--;
LOG_DEBUG("GDB Close, Target: %s, state: %s, gdb_actual_connections=%d",
LOG_DEBUG("{%d} GDB Close, Target: %s, state: %s, gdb_actual_connections=%d",
gdb_connection->unique_index,
target_name(target),
target_state_name(target),
gdb_actual_connections);

View File

@ -1265,8 +1265,8 @@ static int arc_resume(struct target *target, int current, target_addr_t address,
/* current = 1: continue on current PC, otherwise continue at <address> */
if (!current) {
target_buffer_set_u32(target, pc->value, address);
pc->dirty = 1;
pc->valid = 1;
pc->dirty = true;
pc->valid = true;
LOG_DEBUG("Changing the value of current PC to 0x%08" TARGET_PRIxADDR, address);
}
@ -1281,7 +1281,7 @@ static int arc_resume(struct target *target, int current, target_addr_t address,
resume_pc, pc->dirty, pc->valid);
/* check if GDB tells to set our PC where to continue from */
if ((pc->valid == 1) && (resume_pc == target_buffer_get_u32(target, pc->value))) {
if (pc->valid && resume_pc == target_buffer_get_u32(target, pc->value)) {
value = target_buffer_get_u32(target, pc->value);
LOG_DEBUG("resume Core (when start-core) with PC @:0x%08" PRIx32, value);
CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_PC_REG, value));
@ -1573,9 +1573,6 @@ static int arc_set_breakpoint(struct target *target,
return ERROR_FAIL;
}
/* core instruction cache is now invalid. */
CHECK_RETVAL(arc_cache_invalidate(target));
return ERROR_OK;
}
@ -1658,9 +1655,6 @@ static int arc_unset_breakpoint(struct target *target,
return ERROR_FAIL;
}
/* core instruction cache is now invalid. */
CHECK_RETVAL(arc_cache_invalidate(target));
return retval;
}
@ -2013,8 +2007,8 @@ static int arc_step(struct target *target, int current, target_addr_t address,
/* current = 1: continue on current pc, otherwise continue at <address> */
if (!current) {
buf_set_u32(pc->value, 0, 32, address);
pc->dirty = 1;
pc->valid = 1;
pc->dirty = true;
pc->valid = true;
}
LOG_DEBUG("Target steps one instruction from PC=0x%" PRIx32,

View File

@ -61,6 +61,7 @@ enum arm_arch {
/** Known ARM implementor IDs */
enum arm_implementor {
ARM_IMPLEMENTOR_ARM = 0x41,
ARM_IMPLEMENTOR_INFINEON = 0x49,
ARM_IMPLEMENTOR_REALTEK = 0x72,
};
@ -230,12 +231,22 @@ struct arm {
uint32_t crn, uint32_t crm,
uint32_t *value);
/** Read coprocessor to two registers. */
int (*mrrc)(struct target *target, int cpnum,
uint32_t op, uint32_t crm,
uint64_t *value);
/** Write coprocessor register. */
int (*mcr)(struct target *target, int cpnum,
uint32_t op1, uint32_t op2,
uint32_t crn, uint32_t crm,
uint32_t value);
/** Write coprocessor from two registers. */
int (*mcrr)(struct target *target, int cpnum,
uint32_t op, uint32_t crm,
uint64_t value);
void *arch_info;
/** For targets conforming to ARM Debug Interface v5,

View File

@ -63,6 +63,29 @@ static int dpm_mrc(struct target *target, int cpnum,
return retval;
}
static int dpm_mrrc(struct target *target, int cpnum,
uint32_t op, uint32_t crm, uint64_t *value)
{
struct arm *arm = target_to_arm(target);
struct arm_dpm *dpm = arm->dpm;
int retval;
retval = dpm->prepare(dpm);
if (retval != ERROR_OK)
return retval;
LOG_DEBUG("MRRC p%d, %d, r0, r1, c%d", cpnum,
(int)op, (int)crm);
/* read coprocessor register into R0, R1; return via DCC */
retval = dpm->instr_read_data_r0_r1(dpm,
ARMV5_T_MRRC(cpnum, op, 0, 1, crm),
value);
/* (void) */ dpm->finish(dpm);
return retval;
}
static int dpm_mcr(struct target *target, int cpnum,
uint32_t op1, uint32_t op2, uint32_t crn, uint32_t crm,
uint32_t value)
@ -88,6 +111,29 @@ static int dpm_mcr(struct target *target, int cpnum,
return retval;
}
static int dpm_mcrr(struct target *target, int cpnum,
uint32_t op, uint32_t crm, uint64_t value)
{
struct arm *arm = target_to_arm(target);
struct arm_dpm *dpm = arm->dpm;
int retval;
retval = dpm->prepare(dpm);
if (retval != ERROR_OK)
return retval;
LOG_DEBUG("MCRR p%d, %d, r0, r1, c%d", cpnum,
(int)op, (int)crm);
/* read DCC into r0, r1; then write coprocessor register from R0, R1 */
retval = dpm->instr_write_data_r0_r1(dpm,
ARMV5_T_MCRR(cpnum, op, 0, 1, crm), value);
/* (void) */ dpm->finish(dpm);
return retval;
}
/*----------------------------------------------------------------------*/
/*
@ -1070,6 +1116,8 @@ int arm_dpm_setup(struct arm_dpm *dpm)
/* coprocessor access setup */
arm->mrc = dpm_mrc;
arm->mcr = dpm_mcr;
arm->mrrc = dpm_mrrc;
arm->mcrr = dpm_mcrr;
/* breakpoint setup -- optional until it works everywhere */
if (!target->type->add_breakpoint) {

View File

@ -72,6 +72,12 @@ struct arm_dpm {
int (*instr_write_data_r0)(struct arm_dpm *dpm,
uint32_t opcode, uint32_t data);
/**
* Runs two instructions, writing data to R0 and R1 before execution.
*/
int (*instr_write_data_r0_r1)(struct arm_dpm *dpm,
uint32_t opcode, uint64_t data);
/** Runs one instruction, writing data to R0 before execution. */
int (*instr_write_data_r0_64)(struct arm_dpm *dpm,
uint32_t opcode, uint64_t data);
@ -92,6 +98,13 @@ struct arm_dpm {
int (*instr_read_data_r0)(struct arm_dpm *dpm,
uint32_t opcode, uint32_t *data);
/**
* Runs two instructions, reading data from r0 and r1 after
* execution.
*/
int (*instr_read_data_r0_r1)(struct arm_dpm *dpm,
uint32_t opcode, uint64_t *data);
int (*instr_read_data_r0_64)(struct arm_dpm *dpm,
uint32_t opcode, uint64_t *data);

View File

@ -187,6 +187,17 @@
(0xee100010 | (crm) | ((op2) << 5) | ((cp) << 8) \
| ((rd) << 12) | ((crn) << 16) | ((op1) << 21))
/* Move to two ARM registers from coprocessor
* cp: Coprocessor number
* op: Coprocessor opcode
* rt: destination register 1
* rt2: destination register 2
* crm: coprocessor source register
*/
#define ARMV5_T_MRRC(cp, op, rt, rt2, crm) \
(0xec500000 | (crm) | ((op) << 4) | ((cp) << 8) \
| ((rt) << 12) | ((rt2) << 16))
/* Move to coprocessor from ARM register
* cp: Coprocessor number
* op1: Coprocessor opcode
@ -199,6 +210,17 @@
(0xee000010 | (crm) | ((op2) << 5) | ((cp) << 8) \
| ((rd) << 12) | ((crn) << 16) | ((op1) << 21))
/* Move to coprocessor from two ARM registers
* cp: Coprocessor number
* op: Coprocessor opcode
* rt: destination register 1
* rt2: destination register 2
* crm: coprocessor source register
*/
#define ARMV5_T_MCRR(cp, op, rt, rt2, crm) \
(0xec400000 | (crm) | ((op) << 4) | ((cp) << 8) \
| ((rt) << 12) | ((rt2) << 16))
/* Breakpoint instruction (ARMv5)
* im: 16-bit immediate
*/

View File

@ -1093,6 +1093,94 @@ COMMAND_HANDLER(handle_armv4_5_mcrmrc)
return ERROR_OK;
}
COMMAND_HANDLER(handle_armv4_5_mcrrmrrc)
{
bool is_mcrr = false;
unsigned int arg_cnt = 3;
if (!strcmp(CMD_NAME, "mcrr")) {
is_mcrr = true;
arg_cnt = 4;
}
if (arg_cnt != CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
struct target *target = get_current_target(CMD_CTX);
if (!target) {
command_print(CMD, "no current target");
return ERROR_FAIL;
}
if (!target_was_examined(target)) {
command_print(CMD, "%s: not yet examined", target_name(target));
return ERROR_TARGET_NOT_EXAMINED;
}
struct arm *arm = target_to_arm(target);
if (!is_arm(arm)) {
command_print(CMD, "%s: not an ARM", target_name(target));
return ERROR_FAIL;
}
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
int cpnum;
uint32_t op1;
uint32_t crm;
uint64_t value;
/* NOTE: parameter sequence matches ARM instruction set usage:
* MCRR pNUM, op1, rX1, rX2, CRm ; write CP from rX1 and rX2
* MREC pNUM, op1, rX1, rX2, CRm ; read CP into rX1 and rX2
* The "rXn" are necessarily omitted; they use Tcl mechanisms.
*/
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], cpnum);
if (cpnum & ~0xf) {
command_print(CMD, "coprocessor %d out of range", cpnum);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], op1);
if (op1 & ~0xf) {
command_print(CMD, "op1 %d out of range", op1);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], crm);
if (crm & ~0xf) {
command_print(CMD, "CRm %d out of range", crm);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
/*
* FIXME change the call syntax here ... simplest to just pass
* the MRC() or MCR() instruction to be executed. That will also
* let us support the "mrrc2" and "mcrr2" opcodes (toggling one bit)
* if that's ever needed.
*/
if (is_mcrr) {
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[3], value);
/* NOTE: parameters reordered! */
/* ARMV5_T_MCRR(cpnum, op1, crm) */
int retval = arm->mcrr(target, cpnum, op1, crm, value);
if (retval != ERROR_OK)
return retval;
} else {
value = 0;
/* NOTE: parameters reordered! */
/* ARMV5_T_MRRC(cpnum, op1, crm) */
int retval = arm->mrrc(target, cpnum, op1, crm, &value);
if (retval != ERROR_OK)
return retval;
command_print(CMD, "0x%" PRIx64, value);
}
return ERROR_OK;
}
static const struct command_registration arm_exec_command_handlers[] = {
{
.name = "reg",
@ -1115,6 +1203,20 @@ static const struct command_registration arm_exec_command_handlers[] = {
.help = "read coprocessor register",
.usage = "cpnum op1 CRn CRm op2",
},
{
.name = "mcrr",
.mode = COMMAND_EXEC,
.handler = handle_armv4_5_mcrrmrrc,
.help = "write coprocessor 64-bit register",
.usage = "cpnum op1 CRm value",
},
{
.name = "mrrc",
.mode = COMMAND_EXEC,
.handler = handle_armv4_5_mcrrmrrc,
.help = "read coprocessor 64-bit register",
.usage = "cpnum op1 CRm",
},
{
.chain = arm_all_profiles_command_handlers,
},
@ -1669,6 +1771,14 @@ static int arm_default_mrc(struct target *target, int cpnum,
return ERROR_FAIL;
}
static int arm_default_mrrc(struct target *target, int cpnum,
uint32_t op, uint32_t crm,
uint64_t *value)
{
LOG_ERROR("%s doesn't implement MRRC", target_type_name(target));
return ERROR_FAIL;
}
static int arm_default_mcr(struct target *target, int cpnum,
uint32_t op1, uint32_t op2,
uint32_t crn, uint32_t crm,
@ -1678,6 +1788,14 @@ static int arm_default_mcr(struct target *target, int cpnum,
return ERROR_FAIL;
}
static int arm_default_mcrr(struct target *target, int cpnum,
uint32_t op, uint32_t crm,
uint64_t value)
{
LOG_ERROR("%s doesn't implement MCRR", target_type_name(target));
return ERROR_FAIL;
}
int arm_init_arch_info(struct target *target, struct arm *arm)
{
target->arch_info = arm;
@ -1697,8 +1815,12 @@ int arm_init_arch_info(struct target *target, struct arm *arm)
if (!arm->mrc)
arm->mrc = arm_default_mrc;
if (!arm->mrrc)
arm->mrrc = arm_default_mrrc;
if (!arm->mcr)
arm->mcr = arm_default_mcr;
if (!arm->mcrr)
arm->mcrr = arm_default_mcrr;
return ERROR_OK;
}

View File

@ -725,7 +725,8 @@ static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
}
/**
* Read basic registers of the current context: R0 to R15, and CPSR;
* Read basic registers of the current context: R0 to R15, and CPSR in AArch32
* state or R0 to R31, PC and CPSR in AArch64 state;
* sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
* In normal operation this is called on entry to halting debug state,
* possibly after some other operations supporting restore of debug state
@ -772,9 +773,15 @@ int armv8_dpm_read_current_registers(struct arm_dpm *dpm)
/* update core mode and state */
armv8_set_cpsr(arm, cpsr);
for (unsigned int i = ARMV8_PC; i < cache->num_regs ; i++) {
/* read the remaining registers that would be required by GDB 'g' packet */
for (unsigned int i = ARMV8_R2; i <= ARMV8_PC ; i++) {
struct arm_reg *arm_reg;
/* in AArch32 skip AArch64 registers */
/* TODO: this should be detected below through arm_reg->mode */
if (arm->core_state != ARM_STATE_AARCH64 && i > ARMV8_R14 && i < ARMV8_PC)
continue;
r = armv8_reg_current(arm, i);
if (!r->exist || r->valid)
continue;

View File

@ -18,6 +18,11 @@
#include "rtos/rtos.h"
#include "smp.h"
enum breakpoint_watchpoint {
BREAKPOINT,
WATCHPOINT,
};
static const char * const breakpoint_type_strings[] = {
"hardware",
"software"
@ -418,26 +423,90 @@ int breakpoint_remove(struct target *target, target_addr_t address)
return retval;
}
int breakpoint_remove_all(struct target *target)
static int watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
{
struct watchpoint *watchpoint = target->watchpoints;
struct watchpoint **watchpoint_p = &target->watchpoints;
int retval;
while (watchpoint) {
if (watchpoint == watchpoint_to_remove)
break;
watchpoint_p = &watchpoint->next;
watchpoint = watchpoint->next;
}
if (!watchpoint)
return ERROR_WATCHPOINT_NOT_FOUND;
retval = target_remove_watchpoint(target, watchpoint);
if (retval != ERROR_OK) {
LOG_TARGET_ERROR(target, "could not remove watchpoint #%d on this target",
watchpoint->number);
return retval;
}
LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
(*watchpoint_p) = watchpoint->next;
free(watchpoint);
return ERROR_OK;
}
static int watchpoint_remove_all_internal(struct target *target)
{
struct watchpoint *watchpoint = target->watchpoints;
int retval = ERROR_OK;
while (watchpoint) {
struct watchpoint *tmp = watchpoint;
watchpoint = watchpoint->next;
int status = watchpoint_free(target, tmp);
if (status != ERROR_OK)
retval = status;
}
return retval;
}
static int breakpoint_watchpoint_remove_all(struct target *target, enum breakpoint_watchpoint bp_wp)
{
assert(bp_wp == BREAKPOINT || bp_wp == WATCHPOINT);
int retval = ERROR_OK;
if (target->smp) {
struct target_list *head;
foreach_smp_target(head, target->smp_targets) {
struct target *curr = head->target;
int status = breakpoint_remove_all_internal(curr);
int status = ERROR_OK;
if (bp_wp == BREAKPOINT)
status = breakpoint_remove_all_internal(curr);
else
status = watchpoint_remove_all_internal(curr);
if (status != ERROR_OK)
retval = status;
}
} else {
retval = breakpoint_remove_all_internal(target);
if (bp_wp == BREAKPOINT)
retval = breakpoint_remove_all_internal(target);
else
retval = watchpoint_remove_all_internal(target);
}
return retval;
}
int breakpoint_remove_all(struct target *target)
{
return breakpoint_watchpoint_remove_all(target, BREAKPOINT);
}
int watchpoint_remove_all(struct target *target)
{
return breakpoint_watchpoint_remove_all(target, WATCHPOINT);
}
int breakpoint_clear_target(struct target *target)
{
int retval = ERROR_OK;
@ -562,35 +631,6 @@ int watchpoint_add(struct target *target, target_addr_t address,
}
}
static int watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
{
struct watchpoint *watchpoint = target->watchpoints;
struct watchpoint **watchpoint_p = &target->watchpoints;
int retval;
while (watchpoint) {
if (watchpoint == watchpoint_to_remove)
break;
watchpoint_p = &watchpoint->next;
watchpoint = watchpoint->next;
}
if (!watchpoint)
return ERROR_WATCHPOINT_NOT_FOUND;
retval = target_remove_watchpoint(target, watchpoint);
if (retval != ERROR_OK) {
LOG_TARGET_ERROR(target, "could not remove watchpoint #%d on this target",
watchpoint->number);
return retval;
}
LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
(*watchpoint_p) = watchpoint->next;
free(watchpoint);
return ERROR_OK;
}
static int watchpoint_remove_internal(struct target *target, target_addr_t address)
{
struct watchpoint *watchpoint = target->watchpoints;

View File

@ -73,6 +73,7 @@ int watchpoint_add(struct target *target,
target_addr_t address, uint32_t length,
enum watchpoint_rw rw, uint64_t value, uint64_t mask);
int watchpoint_remove(struct target *target, target_addr_t address);
int watchpoint_remove_all(struct target *target);
/* report type and address of just hit watchpoint */
int watchpoint_hit(struct target *target, enum watchpoint_rw *rw,

View File

@ -471,6 +471,28 @@ static int cortex_a_instr_write_data_r0(struct arm_dpm *dpm,
return retval;
}
static int cortex_a_instr_write_data_r0_r1(struct arm_dpm *dpm,
uint32_t opcode, uint64_t data)
{
struct cortex_a_common *a = dpm_to_a(dpm);
uint32_t dscr = DSCR_INSTR_COMP;
int retval;
retval = cortex_a_instr_write_data_rt_dcc(dpm, 0, data & 0xffffffffULL);
if (retval != ERROR_OK)
return retval;
retval = cortex_a_instr_write_data_rt_dcc(dpm, 1, data >> 32);
if (retval != ERROR_OK)
return retval;
/* then the opcode, taking data from R0, R1 */
retval = cortex_a_exec_opcode(a->armv7a_common.arm.target,
opcode,
&dscr);
return retval;
}
static int cortex_a_instr_cpsr_sync(struct arm_dpm *dpm)
{
struct target *target = dpm->arm->target;
@ -539,6 +561,29 @@ static int cortex_a_instr_read_data_r0(struct arm_dpm *dpm,
return cortex_a_instr_read_data_rt_dcc(dpm, 0, data);
}
static int cortex_a_instr_read_data_r0_r1(struct arm_dpm *dpm,
uint32_t opcode, uint64_t *data)
{
uint32_t lo, hi;
int retval;
/* the opcode, writing data to RO, R1 */
retval = cortex_a_instr_read_data_r0(dpm, opcode, &lo);
if (retval != ERROR_OK)
return retval;
*data = lo;
/* write R1 to DCC */
retval = cortex_a_instr_read_data_rt_dcc(dpm, 1, &hi);
if (retval != ERROR_OK)
return retval;
*data |= (uint64_t)hi << 32;
return retval;
}
static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t,
uint32_t addr, uint32_t control)
{
@ -612,10 +657,12 @@ static int cortex_a_dpm_setup(struct cortex_a_common *a, uint32_t didr)
dpm->instr_write_data_dcc = cortex_a_instr_write_data_dcc;
dpm->instr_write_data_r0 = cortex_a_instr_write_data_r0;
dpm->instr_write_data_r0_r1 = cortex_a_instr_write_data_r0_r1;
dpm->instr_cpsr_sync = cortex_a_instr_cpsr_sync;
dpm->instr_read_data_dcc = cortex_a_instr_read_data_dcc;
dpm->instr_read_data_r0 = cortex_a_instr_read_data_r0;
dpm->instr_read_data_r0_r1 = cortex_a_instr_read_data_r0_r1;
dpm->bpwp_enable = cortex_a_bpwp_enable;
dpm->bpwp_disable = cortex_a_bpwp_disable;

View File

@ -111,6 +111,11 @@ static const struct cortex_m_part_info cortex_m_parts[] = {
.arch = ARM_ARCH_V8M,
.flags = CORTEX_M_F_HAS_FPV5,
},
{
.impl_part = INFINEON_SLX2_PARTNO,
.name = "Infineon-SLx2",
.arch = ARM_ARCH_V8M,
},
{
.impl_part = REALTEK_M200_PARTNO,
.name = "Real-M200 (KM0)",

View File

@ -45,19 +45,20 @@
*/
enum cortex_m_impl_part {
CORTEX_M_PARTNO_INVALID,
STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0x132), /* FIXME - confirm implementor! */
CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC20),
CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC21),
CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC23),
CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC24),
CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC27),
CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC60),
CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD20),
CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21),
CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31),
CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22),
REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd20),
REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd22),
STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0x132), /* FIXME - confirm implementor! */
CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC20),
CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC21),
CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC23),
CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC24),
CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC27),
CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC60),
CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD20),
CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21),
CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31),
CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22),
INFINEON_SLX2_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_INFINEON, 0xDB0),
REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd20),
REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd22),
};
/* Relevant Cortex-M flags, used in struct cortex_m_part_info.flags */

View File

@ -552,8 +552,8 @@ static int etm_set_reg(struct reg *reg, uint32_t value)
}
buf_set_u32(reg->value, 0, reg->size, value);
reg->valid = 1;
reg->dirty = 0;
reg->valid = true;
reg->dirty = false;
return ERROR_OK;
}

View File

@ -96,20 +96,22 @@ static int autodetect_image_type(struct image *image, const char *url)
static int identify_image_type(struct image *image, const char *type_string, const char *url)
{
if (type_string) {
if (!strcmp(type_string, "bin"))
if (!strcmp(type_string, "bin")) {
image->type = IMAGE_BINARY;
else if (!strcmp(type_string, "ihex"))
} else if (!strcmp(type_string, "ihex")) {
image->type = IMAGE_IHEX;
else if (!strcmp(type_string, "elf"))
} else if (!strcmp(type_string, "elf")) {
image->type = IMAGE_ELF;
else if (!strcmp(type_string, "mem"))
} else if (!strcmp(type_string, "mem")) {
image->type = IMAGE_MEMORY;
else if (!strcmp(type_string, "s19"))
} else if (!strcmp(type_string, "s19")) {
image->type = IMAGE_SRECORD;
else if (!strcmp(type_string, "build"))
} else if (!strcmp(type_string, "build")) {
image->type = IMAGE_BUILDER;
else
} else {
LOG_ERROR("Unknown image type: %s, use one of: bin, ihex, elf, mem, s19, build", type_string);
return ERROR_IMAGE_TYPE_UNKNOWN;
}
} else
return autodetect_image_type(image, url);
@ -966,12 +968,13 @@ int image_open(struct image *image, const char *url, const char *type_string)
retval = fileio_open(&image_binary->fileio, url, FILEIO_READ, FILEIO_BINARY);
if (retval != ERROR_OK)
return retval;
goto free_mem_on_error;
size_t filesize;
retval = fileio_size(image_binary->fileio, &filesize);
if (retval != ERROR_OK) {
fileio_close(image_binary->fileio);
return retval;
goto free_mem_on_error;
}
image->num_sections = 1;
@ -986,14 +989,14 @@ int image_open(struct image *image, const char *url, const char *type_string)
retval = fileio_open(&image_ihex->fileio, url, FILEIO_READ, FILEIO_TEXT);
if (retval != ERROR_OK)
return retval;
goto free_mem_on_error;
retval = image_ihex_buffer_complete(image);
if (retval != ERROR_OK) {
LOG_ERROR(
"failed buffering IHEX image, check server output for additional information");
fileio_close(image_ihex->fileio);
return retval;
goto free_mem_on_error;
}
} else if (image->type == IMAGE_ELF) {
struct image_elf *image_elf;
@ -1002,12 +1005,12 @@ int image_open(struct image *image, const char *url, const char *type_string)
retval = fileio_open(&image_elf->fileio, url, FILEIO_READ, FILEIO_BINARY);
if (retval != ERROR_OK)
return retval;
goto free_mem_on_error;
retval = image_elf_read_headers(image);
if (retval != ERROR_OK) {
fileio_close(image_elf->fileio);
return retval;
goto free_mem_on_error;
}
} else if (image->type == IMAGE_MEMORY) {
struct target *target = get_target(url);
@ -1037,14 +1040,14 @@ int image_open(struct image *image, const char *url, const char *type_string)
retval = fileio_open(&image_mot->fileio, url, FILEIO_READ, FILEIO_TEXT);
if (retval != ERROR_OK)
return retval;
goto free_mem_on_error;
retval = image_mot_buffer_complete(image);
if (retval != ERROR_OK) {
LOG_ERROR(
"failed buffering S19 image, check server output for additional information");
fileio_close(image_mot->fileio);
return retval;
goto free_mem_on_error;
}
} else if (image->type == IMAGE_BUILDER) {
image->num_sections = 0;
@ -1065,6 +1068,11 @@ int image_open(struct image *image, const char *url, const char *type_string)
}
return retval;
free_mem_on_error:
free(image->type_private);
image->type_private = NULL;
return retval;
};
int image_read_section(struct image *image,

View File

@ -27,7 +27,7 @@ static const char *mips_isa_strings[] = {
"MIPS32", "MIPS16", "", "MICRO MIPS32",
};
#define MIPS32_GDB_DUMMY_FP_REG 1
#define MIPS32_GDB_FP_REG 1
/*
* GDB registers
@ -39,7 +39,7 @@ static const struct {
enum reg_type type;
const char *group;
const char *feature;
int flag;
int size;
} mips32_regs[] = {
{ 0, "r0", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 1, "r1", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
@ -73,88 +73,93 @@ static const struct {
{ 29, "r29", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 30, "r30", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 31, "r31", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 32, "status", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
{ 33, "lo", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 34, "hi", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 35, "badvaddr", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
{ 36, "cause", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
{ 37, "pc", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 32, "lo", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 33, "hi", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 38, "f0", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 39, "f1", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 40, "f2", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 41, "f3", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 42, "f4", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 43, "f5", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 44, "f6", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 45, "f7", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 46, "f8", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 47, "f9", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 48, "f10", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 49, "f11", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 50, "f12", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 51, "f13", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 52, "f14", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 53, "f15", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 54, "f16", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 55, "f17", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 56, "f18", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 57, "f19", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 58, "f20", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 59, "f21", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 60, "f22", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 61, "f23", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 62, "f24", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 63, "f25", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 64, "f26", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 65, "f27", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 66, "f28", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 67, "f29", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 68, "f30", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 69, "f31", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 70, "fcsr", REG_TYPE_INT, "float",
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 71, "fir", REG_TYPE_INT, "float",
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 0, "f0", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 1, "f1", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 2, "f2", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 3, "f3", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 4, "f4", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 5, "f5", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 6, "f6", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 7, "f7", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 8, "f8", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 9, "f9", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 10, "f10", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 11, "f11", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 12, "f12", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 13, "f13", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 14, "f14", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 15, "f15", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 16, "f16", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 17, "f17", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 18, "f18", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 19, "f19", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 20, "f20", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 21, "f21", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 22, "f22", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 23, "f23", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 24, "f24", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 25, "f25", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 26, "f26", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 27, "f27", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 28, "f28", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 29, "f29", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 30, "f30", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 31, "f31", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FPC_INDEX + 0, "fcsr", REG_TYPE_INT, "float",
"org.gnu.gdb.mips.fpu", 0 },
{ MIPS32_REGLIST_FPC_INDEX + 1, "fir", REG_TYPE_INT, "float",
"org.gnu.gdb.mips.fpu", 0 },
{ MIPS32_REGLIST_C0_STATUS_INDEX, "status", REG_TYPE_INT, NULL,
"org.gnu.gdb.mips.cp0", 0 },
{ MIPS32_REGLIST_C0_BADVADDR_INDEX, "badvaddr", REG_TYPE_INT, NULL,
"org.gnu.gdb.mips.cp0", 0 },
{ MIPS32_REGLIST_C0_CAUSE_INDEX, "cause", REG_TYPE_INT, NULL,
"org.gnu.gdb.mips.cp0", 0 },
{ MIPS32_REGLIST_C0_PC_INDEX, "pc", REG_TYPE_INT, NULL,
"org.gnu.gdb.mips.cpu", 0 },
{ MIPS32_REGLIST_C0_GUESTCTL1_INDEX, "guestCtl1", REG_TYPE_INT, NULL,
"org.gnu.gdb.mips.cp0", 0 },
};
#define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs)
static uint8_t mips32_gdb_dummy_fp_value[] = {0, 0, 0, 0};
static int mips32_get_core_reg(struct reg *reg)
{
int retval;
@ -174,12 +179,21 @@ static int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
{
struct mips32_core_reg *mips32_reg = reg->arch_info;
struct target *target = mips32_reg->target;
uint32_t value = buf_get_u32(buf, 0, 32);
uint64_t value;
if (reg->size == 64)
value = buf_get_u64(buf, 0, 64);
else
value = buf_get_u32(buf, 0, 32);
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
buf_set_u32(reg->value, 0, 32, value);
if (reg->size == 64)
buf_set_u64(reg->value, 0, 64, value);
else
buf_set_u32(reg->value, 0, 32, value);
reg->dirty = true;
reg->valid = true;
@ -188,7 +202,8 @@ static int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
static int mips32_read_core_reg(struct target *target, unsigned int num)
{
uint32_t reg_value;
unsigned int cnum;
uint64_t reg_value = 0;
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
@ -196,17 +211,40 @@ static int mips32_read_core_reg(struct target *target, unsigned int num)
if (num >= MIPS32_NUM_REGS)
return ERROR_COMMAND_SYNTAX_ERROR;
reg_value = mips32->core_regs[num];
buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
if (num >= MIPS32_REGLIST_C0_INDEX) {
/* CP0 */
cnum = num - MIPS32_REGLIST_C0_INDEX;
reg_value = mips32->core_regs.cp0[cnum];
buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
} else if (num >= MIPS32_REGLIST_FPC_INDEX) {
/* FPCR */
cnum = num - MIPS32_REGLIST_FPC_INDEX;
reg_value = mips32->core_regs.fpcr[cnum];
buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
} else if (num >= MIPS32_REGLIST_FP_INDEX) {
/* FPR */
cnum = num - MIPS32_REGLIST_FP_INDEX;
reg_value = mips32->core_regs.fpr[cnum];
buf_set_u64(mips32->core_cache->reg_list[num].value, 0, 64, reg_value);
} else {
/* GPR */
cnum = num - MIPS32_REGLIST_GP_INDEX;
reg_value = mips32->core_regs.gpr[cnum];
buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
}
mips32->core_cache->reg_list[num].valid = true;
mips32->core_cache->reg_list[num].dirty = false;
LOG_DEBUG("read core reg %i value 0x%" PRIx64 "", num, reg_value);
return ERROR_OK;
}
static int mips32_write_core_reg(struct target *target, unsigned int num)
{
uint32_t reg_value;
unsigned int cnum;
uint64_t reg_value;
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
@ -214,9 +252,29 @@ static int mips32_write_core_reg(struct target *target, unsigned int num)
if (num >= MIPS32_NUM_REGS)
return ERROR_COMMAND_SYNTAX_ERROR;
reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
mips32->core_regs[num] = reg_value;
LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
if (num >= MIPS32_REGLIST_C0_INDEX) {
/* CP0 */
cnum = num - MIPS32_REGLIST_C0_INDEX;
reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
mips32->core_regs.cp0[cnum] = (uint32_t)reg_value;
} else if (num >= MIPS32_REGLIST_FPC_INDEX) {
/* FPCR */
cnum = num - MIPS32_REGLIST_FPC_INDEX;
reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
mips32->core_regs.fpcr[cnum] = (uint32_t)reg_value;
} else if (num >= MIPS32_REGLIST_FP_INDEX) {
/* FPR */
cnum = num - MIPS32_REGLIST_FP_INDEX;
reg_value = buf_get_u64(mips32->core_cache->reg_list[num].value, 0, 64);
mips32->core_regs.fpr[cnum] = reg_value;
} else {
/* GPR */
cnum = num - MIPS32_REGLIST_GP_INDEX;
reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
mips32->core_regs.gpr[cnum] = (uint32_t)reg_value;
}
LOG_DEBUG("write core reg %i value 0x%" PRIx64 "", num, reg_value);
mips32->core_cache->reg_list[num].valid = true;
mips32->core_cache->reg_list[num].dirty = false;
@ -246,10 +304,13 @@ int mips32_save_context(struct target *target)
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
/* read core registers */
mips32_pracc_read_regs(ejtag_info, mips32->core_regs);
int retval = mips32_pracc_read_regs(mips32);
if (retval != ERROR_OK) {
LOG_ERROR("Could not read core registers from target");
return retval;
}
for (i = 0; i < MIPS32_NUM_REGS; i++) {
if (!mips32->core_cache->reg_list[i].valid)
@ -265,7 +326,6 @@ int mips32_restore_context(struct target *target)
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
for (i = 0; i < MIPS32_NUM_REGS; i++) {
if (mips32->core_cache->reg_list[i].dirty)
@ -273,7 +333,7 @@ int mips32_restore_context(struct target *target)
}
/* write core regs */
mips32_pracc_write_regs(ejtag_info, mips32->core_regs);
mips32_pracc_write_regs(mips32);
return ERROR_OK;
}
@ -285,7 +345,7 @@ int mips32_arch_state(struct target *target)
LOG_USER("target halted in %s mode due to %s, pc: 0x%8.8" PRIx32 "",
mips_isa_strings[mips32->isa_mode],
debug_reason_name(target),
buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32));
return ERROR_OK;
}
@ -322,25 +382,19 @@ struct reg_cache *mips32_build_reg_cache(struct target *target)
arch_info[i].mips32_common = mips32;
reg_list[i].name = mips32_regs[i].name;
reg_list[i].size = 32;
reg_list[i].size = mips32_regs[i].size ? 64 : 32;
if (mips32_regs[i].flag == MIPS32_GDB_DUMMY_FP_REG) {
reg_list[i].value = mips32_gdb_dummy_fp_value;
reg_list[i].valid = true;
reg_list[i].arch_info = NULL;
register_init_dummy(&reg_list[i]);
} else {
reg_list[i].value = calloc(1, 4);
reg_list[i].valid = false;
reg_list[i].type = &mips32_reg_type;
reg_list[i].arch_info = &arch_info[i];
reg_list[i].value = mips32_regs[i].size ? calloc(1, 8) : calloc(1, 4);
reg_list[i].valid = false;
reg_list[i].type = &mips32_reg_type;
reg_list[i].arch_info = &arch_info[i];
reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
if (reg_list[i].reg_data_type)
reg_list[i].reg_data_type->type = mips32_regs[i].type;
else
LOG_ERROR("unable to allocate reg type list");
reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
if (reg_list[i].reg_data_type)
reg_list[i].reg_data_type->type = mips32_regs[i].type;
else
LOG_ERROR("unable to allocate reg type list");
}
reg_list[i].dirty = false;
@ -407,7 +461,7 @@ static int mips32_run_and_wait(struct target *target, target_addr_t entry_point,
return ERROR_TARGET_TIMEOUT;
}
pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32);
if (exit_point && (pc != exit_point)) {
LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc);
return ERROR_TARGET_TIMEOUT;
@ -751,15 +805,82 @@ int mips32_cpu_probe(struct target *target)
return ERROR_OK;
}
/* reads dsp implementation info from CP0 Config3 register {DSPP, DSPREV}*/
void mips32_read_config_dsp(struct mips32_common *mips32, struct mips_ejtag *ejtag_info)
{
uint32_t dsp_present = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPP_MASK) >> MIPS32_CONFIG3_DSPP_SHIFT);
if (dsp_present) {
mips32->dsp_imp = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPREV_MASK) >> MIPS32_CONFIG3_DSPREV_SHIFT) + 1;
LOG_USER("DSP implemented: %s, rev %d", "yes", mips32->dsp_imp);
} else {
LOG_USER("DSP implemented: %s", "no");
}
}
/* read fpu implementation info from CP0 Config1 register {CU1, FP}*/
int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejtag *ejtag_info)
{
int retval;
uint32_t fp_imp = (ejtag_info->config[1] & MIPS32_CONFIG1_FP_MASK) >> MIPS32_CONFIG1_FP_SHIFT;
char buf[60] = {0};
if (!fp_imp) {
LOG_USER("FPU implemented: %s", "no");
mips32->fp_imp = MIPS32_FP_IMP_NONE;
return ERROR_OK;
}
uint32_t status_value;
bool status_fr, status_cu1;
retval = mips32_cp0_read(ejtag_info, &status_value, MIPS32_C0_STATUS, 0);
if (retval != ERROR_OK) {
LOG_ERROR("Failed to read cp0 status register");
return retval;
}
status_fr = (status_value >> MIPS32_CP0_STATUS_FR_SHIFT) & 0x1;
status_cu1 = (status_value >> MIPS32_CP0_STATUS_CU1_SHIFT) & 0x1;
if (status_cu1) {
/* TODO: read fpu(cp1) config register for current operating mode.
* Now its set to 32 bits by default. */
snprintf(buf, sizeof(buf), "yes");
fp_imp = MIPS32_FP_IMP_32;
} else {
snprintf(buf, sizeof(buf), "yes, disabled");
fp_imp = MIPS32_FP_IMP_UNKNOWN;
}
mips32->fpu_in_64bit = status_fr;
mips32->fpu_enabled = status_cu1;
LOG_USER("FPU implemented: %s", buf);
mips32->fp_imp = fp_imp;
return ERROR_OK;
}
/* Checks if current target implements Common Device Memory Map and therefore Fast Debug Channel (MD00090) */
void mips32_read_config_fdc(struct mips32_common *mips32, struct mips_ejtag *ejtag_info, uint32_t dcr)
{
if (((ejtag_info->config[3] & MIPS32_CONFIG3_CDMM_MASK) != 0) && ((dcr & EJTAG_DCR_FDC) != 0)) {
mips32->fdc = 1;
mips32->semihosting = 1;
} else {
mips32->fdc = 0;
mips32->semihosting = 0;
}
}
/* read config to config3 cp0 registers and log isa implementation */
int mips32_read_config_regs(struct target *target)
{
struct mips32_common *mips32 = target_to_mips32(target);
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
char buf[60] = {0};
int retval;
if (ejtag_info->config_regs == 0)
for (int i = 0; i != 4; i++) {
int retval = mips32_cp0_read(ejtag_info, &ejtag_info->config[i], 16, i);
retval = mips32_cp0_read(ejtag_info, &ejtag_info->config[i], 16, i);
if (retval != ERROR_OK) {
LOG_ERROR("isa info not available, failed to read cp0 config register: %" PRId32, i);
ejtag_info->config_regs = 0;
@ -774,27 +895,56 @@ int mips32_read_config_regs(struct target *target)
LOG_DEBUG("read %"PRIu32" config registers", ejtag_info->config_regs);
mips32->isa_rel = (ejtag_info->config[0] & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT;
snprintf(buf, sizeof(buf), ", release %s(AR=%d)",
mips32->isa_rel == MIPS32_RELEASE_1 ? "1"
: mips32->isa_rel == MIPS32_RELEASE_2 ? "2"
: mips32->isa_rel == MIPS32_RELEASE_6 ? "6"
: "unknown", mips32->isa_rel);
if (ejtag_info->impcode & EJTAG_IMP_MIPS16) {
mips32->isa_imp = MIPS32_MIPS16;
LOG_USER("MIPS32 with MIPS16 support implemented");
LOG_USER("ISA implemented: %s%s", "MIPS32, MIPS16", buf);
} else if (ejtag_info->config_regs >= 4) { /* config3 implemented */
unsigned isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT;
if (isa_imp == 1) {
mips32->isa_imp = MMIPS32_ONLY;
LOG_USER("MICRO MIPS32 only implemented");
LOG_USER("ISA implemented: %s%s", "microMIPS32", buf);
} else if (isa_imp != 0) {
mips32->isa_imp = MIPS32_MMIPS32;
LOG_USER("MIPS32 and MICRO MIPS32 implemented");
LOG_USER("ISA implemented: %s%s", "MIPS32, microMIPS32", buf);
}
} else if (mips32->isa_imp == MIPS32_ONLY) {
/* initial default value */
LOG_USER("ISA implemented: %s%s", "MIPS32", buf);
}
if (mips32->isa_imp == MIPS32_ONLY) /* initial default value */
LOG_USER("MIPS32 only implemented");
/* Retrieve DSP info */
mips32_read_config_dsp(mips32, ejtag_info);
/* Retrieve if Float Point CoProcessor Implemented */
retval = mips32_read_config_fpu(mips32, ejtag_info);
if (retval != ERROR_OK) {
LOG_ERROR("fpu info is not available, error while reading cp0 status");
mips32->fp_imp = MIPS32_FP_IMP_NONE;
return retval;
}
uint32_t dcr;
retval = target_read_u32(target, EJTAG_DCR, &dcr);
if (retval != ERROR_OK) {
LOG_ERROR("failed to read EJTAG_DCR register");
return retval;
}
/* Determine if FDC and CDMM are implemented for this core */
mips32_read_config_fdc(mips32, ejtag_info, dcr);
return ERROR_OK;
}
int mips32_checksum_memory(struct target *target, target_addr_t address,
uint32_t count, uint32_t *checksum)
{

View File

@ -46,9 +46,21 @@
#define MIPS32_CONFIG0_AR_SHIFT 10
#define MIPS32_CONFIG0_AR_MASK (0x7 << MIPS32_CONFIG0_AR_SHIFT)
#define MIPS32_CONFIG1_FP_SHIFT 0
#define MIPS32_CONFIG1_FP_MASK BIT(MIPS32_CONFIG1_FP_SHIFT)
#define MIPS32_CONFIG1_DL_SHIFT 10
#define MIPS32_CONFIG1_DL_MASK (0x7 << MIPS32_CONFIG1_DL_SHIFT)
#define MIPS32_CONFIG3_CDMM_SHIFT 3
#define MIPS32_CONFIG3_CDMM_MASK BIT(MIPS32_CONFIG3_CDMM_SHIFT)
#define MIPS32_CONFIG3_DSPP_SHIFT 10
#define MIPS32_CONFIG3_DSPP_MASK BIT(MIPS32_CONFIG3_DSPP_SHIFT)
#define MIPS32_CONFIG3_DSPREV_SHIFT 11
#define MIPS32_CONFIG3_DSPREV_MASK BIT(MIPS32_CONFIG3_DSPREV_SHIFT)
#define MIPS32_CONFIG3_ISA_SHIFT 14
#define MIPS32_CONFIG3_ISA_MASK (3 << MIPS32_CONFIG3_ISA_SHIFT)
@ -57,6 +69,141 @@
#define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000
#define MIPS32_NUM_DSPREGS 9
/* Bit Mask indicating CP0 register supported by this core */
#define MIPS_CP0_MK4 0x0001
#define MIPS_CP0_MAPTIV_UC 0x0002
#define MIPS_CP0_MAPTIV_UP 0x0004
#define MIPS_CP0_IAPTIV 0x0008
/* CP0 Status register fields */
#define MIPS32_CP0_STATUS_FR_SHIFT 26
#define MIPS32_CP0_STATUS_CU1_SHIFT 29
/* CP1 FIR register fields */
#define MIPS32_CP1_FIR_F64_SHIFT 22
static const struct {
unsigned int reg;
unsigned int sel;
const char *name;
const unsigned int core;
} mips32_cp0_regs[] = {
{0, 0, "index", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{0, 1, "mvpcontrol", MIPS_CP0_IAPTIV},
{0, 2, "mvpconf0", MIPS_CP0_IAPTIV},
{0, 3, "mvpconf1", MIPS_CP0_IAPTIV},
{1, 0, "random", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{1, 1, "vpecontrol", MIPS_CP0_IAPTIV},
{1, 2, "vpeconf0", MIPS_CP0_IAPTIV},
{1, 3, "vpeconf1", MIPS_CP0_IAPTIV},
{1, 4, "yqmask", MIPS_CP0_IAPTIV},
{1, 5, "vpeschedule", MIPS_CP0_IAPTIV},
{1, 6, "vpeschefback", MIPS_CP0_IAPTIV},
{1, 7, "vpeopt", MIPS_CP0_IAPTIV},
{2, 0, "entrylo0", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{2, 1, "tcstatus", MIPS_CP0_IAPTIV},
{2, 2, "tcbind", MIPS_CP0_IAPTIV},
{2, 3, "tcrestart", MIPS_CP0_IAPTIV},
{2, 4, "tchalt", MIPS_CP0_IAPTIV},
{2, 5, "tccontext", MIPS_CP0_IAPTIV},
{2, 6, "tcschedule", MIPS_CP0_IAPTIV},
{2, 7, "tcschefback", MIPS_CP0_IAPTIV},
{3, 0, "entrylo1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{3, 7, "tcopt", MIPS_CP0_IAPTIV},
{4, 0, "context", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{4, 2, "userlocal", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{5, 0, "pagemask", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{5, 1, "pagegrain", MIPS_CP0_MAPTIV_UP},
{5, 2, "segctl0", MIPS_CP0_IAPTIV},
{5, 3, "segctl1", MIPS_CP0_IAPTIV},
{5, 4, "segctl2", MIPS_CP0_IAPTIV},
{6, 0, "wired", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{6, 1, "srsconf0", MIPS_CP0_IAPTIV},
{6, 2, "srsconf1", MIPS_CP0_IAPTIV},
{6, 3, "srsconf2", MIPS_CP0_IAPTIV},
{6, 4, "srsconf3", MIPS_CP0_IAPTIV},
{6, 5, "srsconf4", MIPS_CP0_IAPTIV},
{7, 0, "hwrena", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{8, 0, "badvaddr", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{8, 1, "badinstr", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
{8, 2, "badinstrp", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
{9, 0, "count", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{10, 0, "entryhi", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{10, 4, "guestctl1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
{10, 5, "guestctl2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
{10, 6, "guestctl3", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
{11, 0, "compare", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{11, 4, "guestctl0ext", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
{12, 0, "status", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{12, 1, "intctl", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{12, 2, "srsctl", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{12, 3, "srsmap", MIPS_CP0_IAPTIV},
{12, 3, "srsmap1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
{12, 4, "view_ipl", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{12, 5, "srsmap2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
{12, 6, "guestctl0", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
{12, 7, "gtoffset", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
{13, 0, "cause", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{13, 5, "nestedexc", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{14, 0, "epc", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{14, 2, "nestedepc", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{15, 0, "prid", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{15, 1, "ebase", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{15, 2, "cdmmbase", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{15, 3, "cmgcrbase", MIPS_CP0_IAPTIV},
{16, 0, "config", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{16, 1, "config1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{16, 2, "config2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{16, 3, "config3", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{16, 4, "config4", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{16, 5, "config5", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{16, 7, "config7", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{17, 0, "lladdr", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{18, 0, "watchlo0", MIPS_CP0_IAPTIV},
{18, 1, "watchlo1", MIPS_CP0_IAPTIV},
{18, 2, "watchlo2", MIPS_CP0_IAPTIV},
{18, 3, "watchlo3", MIPS_CP0_IAPTIV},
{19, 0, "watchhi0", MIPS_CP0_IAPTIV},
{19, 1, "watchhi1", MIPS_CP0_IAPTIV},
{19, 2, "watchhi2", MIPS_CP0_IAPTIV},
{19, 3, "watchhi3", MIPS_CP0_IAPTIV},
{23, 0, "debug", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{23, 1, "tracecontrol", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{23, 2, "tracecontrol2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{23, 3, "usertracedata1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{23, 4, "tracebpc", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{23, 4, "traceibpc", MIPS_CP0_IAPTIV},
{23, 5, "tracedbpc", MIPS_CP0_IAPTIV},
{24, 0, "depc", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{24, 2, "tracecontrol3", MIPS_CP0_IAPTIV},
{24, 3, "usertracedata2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{25, 0, "perfctl0", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{25, 1, "perfcnt0", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{25, 2, "perfctl1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{25, 3, "perfcnt1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{26, 0, "errctl", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{27, 0, "cacheerr", MIPS_CP0_IAPTIV},
{28, 0, "itaglo", MIPS_CP0_IAPTIV},
{28, 0, "taglo", MIPS_CP0_IAPTIV},
{28, 1, "idatalo", MIPS_CP0_IAPTIV},
{28, 1, "datalo", MIPS_CP0_IAPTIV},
{28, 2, "dtaglo", MIPS_CP0_IAPTIV},
{28, 3, "ddatalo", MIPS_CP0_IAPTIV},
{28, 4, "l23taglo", MIPS_CP0_IAPTIV},
{28, 5, "l23datalo", MIPS_CP0_IAPTIV},
{29, 1, "idatahi", MIPS_CP0_IAPTIV},
{29, 2, "dtaghi", MIPS_CP0_IAPTIV},
{29, 5, "l23datahi", MIPS_CP0_IAPTIV},
{30, 0, "errorepc", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{31, 0, "desave", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{31, 2, "kscratch1", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
{31, 3, "kscratch2", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
};
#define MIPS32NUMCP0REGS ((int)ARRAY_SIZE(mips32_cp0_regs))
/* Insert extra NOPs after the DRET instruction on exit from debug. */
#define EJTAG_QUIRK_PAD_DRET BIT(0)
@ -67,6 +214,30 @@ enum {
MIPS32NUMCOREREGS
};
/* offsets into mips32 core register cache */
#define MIPS32_REG_GP_COUNT 34
#define MIPS32_REG_FP_COUNT 32
#define MIPS32_REG_FPC_COUNT 2
#define MIPS32_REG_C0_COUNT 5
#define MIPS32_REGLIST_GP_INDEX 0
#define MIPS32_REGLIST_FP_INDEX (MIPS32_REGLIST_GP_INDEX + MIPS32_REG_GP_COUNT)
#define MIPS32_REGLIST_FPC_INDEX (MIPS32_REGLIST_FP_INDEX + MIPS32_REG_FP_COUNT)
#define MIPS32_REGLIST_C0_INDEX (MIPS32_REGLIST_FPC_INDEX + MIPS32_REG_FPC_COUNT)
#define MIPS32_REGLIST_C0_STATUS_INDEX (MIPS32_REGLIST_C0_INDEX + 0)
#define MIPS32_REGLIST_C0_BADVADDR_INDEX (MIPS32_REGLIST_C0_INDEX + 1)
#define MIPS32_REGLIST_C0_CAUSE_INDEX (MIPS32_REGLIST_C0_INDEX + 2)
#define MIPS32_REGLIST_C0_PC_INDEX (MIPS32_REGLIST_C0_INDEX + 3)
#define MIPS32_REGLIST_C0_GUESTCTL1_INDEX (MIPS32_REGLIST_C0_INDEX + 4)
#define MIPS32_REG_C0_STATUS_INDEX 0
#define MIPS32_REG_C0_BADVADDR_INDEX 1
#define MIPS32_REG_C0_CAUSE_INDEX 2
#define MIPS32_REG_C0_PC_INDEX 3
#define MIPS32_REG_C0_GUESTCTL1_INDEX 4
enum mips32_isa_mode {
MIPS32_ISA_MIPS32 = 0,
MIPS32_ISA_MIPS16E = 1,
@ -80,21 +251,67 @@ enum mips32_isa_imp {
MIPS32_MMIPS32 = 3,
};
/* Release 2~5 does not have much change regarding to the ISA under User mode,
* therefore no new Architecture Revision(AR) level is assigned to them.
* Release 6 changed some instruction's encoding/mnemonic, removed instructions that
* has lost its purposes/none are using, and added some new instructions as well.
*/
enum mips32_isa_rel {
MIPS32_RELEASE_1 = 0,
MIPS32_RELEASE_2 = 1,
MIPS32_RELEASE_6 = 2,
MIPS32_RELEASE_UNKNOWN,
};
enum mips32_fp_imp {
MIPS32_FP_IMP_NONE = 0,
MIPS32_FP_IMP_32 = 1,
MIPS32_FP_IMP_64 = 2,
MIPS32_FP_IMP_UNKNOWN = 3,
};
enum mips32_dsp_imp {
MIPS32_DSP_IMP_NONE = 0,
MIPS32_DSP_IMP_REV1 = 1,
MIPS32_DSP_IMP_REV2 = 2,
};
struct mips32_comparator {
int used;
uint32_t bp_value;
uint32_t reg_address;
};
struct mips32_core_regs {
uint32_t gpr[MIPS32_REG_GP_COUNT];
uint64_t fpr[MIPS32_REG_FP_COUNT];
uint32_t fpcr[MIPS32_REG_FPC_COUNT];
uint32_t cp0[MIPS32_REG_C0_COUNT];
};
struct mips32_common {
unsigned int common_magic;
void *arch_info;
struct reg_cache *core_cache;
struct mips_ejtag ejtag_info;
uint32_t core_regs[MIPS32NUMCOREREGS];
struct mips32_core_regs core_regs;
enum mips32_isa_mode isa_mode;
enum mips32_isa_imp isa_imp;
enum mips32_isa_rel isa_rel;
enum mips32_fp_imp fp_imp;
enum mips32_dsp_imp dsp_imp;
int fdc;
int semihosting;
uint32_t cp0_mask;
/* FPU enabled (cp0.status.cu1) */
bool fpu_enabled;
/* FPU mode (cp0.status.fr) */
bool fpu_in_64bit;
/* processor identification register */
uint32_t prid;
@ -394,6 +611,173 @@ struct mips32_algorithm {
#define MIPS16_SDBBP(isa) (isa ? MMIPS16_SDBBP : MIPS16_ISA_SDBBP)
/*
* MIPS32 Config1 Register (CP0 Register 16, Select 1)
*/
#define MIPS32_CFG1_M 0x80000000 /* Config2 implemented */
#define MIPS32_CFG1_MMUSMASK 0x7e000000 /* mmu size - 1 */
#define MIPS32_CFG1_MMUSSHIFT 25
#define MIPS32_CFG1_ISMASK 0x01c00000 /* icache lines 64<<n */
#define MIPS32_CFG1_ISSHIFT 22
#define MIPS32_CFG1_ILMASK 0x00380000 /* icache line size 2<<n */
#define MIPS32_CFG1_ILSHIFT 19
#define MIPS32_CFG1_IAMASK 0x00070000 /* icache ways - 1 */
#define MIPS32_CFG1_IASHIFT 16
#define MIPS32_CFG1_DSMASK 0x0000e000 /* dcache lines 64<<n */
#define MIPS32_CFG1_DSSHIFT 13
#define MIPS32_CFG1_DLMASK 0x00001c00 /* dcache line size 2<<n */
#define MIPS32_CFG1_DLSHIFT 10
#define MIPS32_CFG1_DAMASK 0x00000380 /* dcache ways - 1 */
#define MIPS32_CFG1_DASHIFT 7
#define MIPS32_CFG1_C2 0x00000040 /* Coprocessor 2 present */
#define MIPS32_CFG1_MD 0x00000020 /* MDMX implemented */
#define MIPS32_CFG1_PC 0x00000010 /* performance counters implemented */
#define MIPS32_CFG1_WR 0x00000008 /* watch registers implemented */
#define MIPS32_CFG1_CA 0x00000004 /* compression (mips16) implemented */
#define MIPS32_CFG1_EP 0x00000002 /* ejtag implemented */
#define MIPS32_CFG1_FP 0x00000001 /* fpu implemented */
/*
* MIPS32 Coprocessor 0 register numbers
*/
#define MIPS32_C0_INDEX 0
#define MIPS32_C0_INX 0
#define MIPS32_C0_RANDOM 1
#define MIPS32_C0_RAND 1
#define MIPS32_C0_ENTRYLO0 2
#define MIPS32_C0_TLBLO0 2
#define MIPS32_C0_ENTRYLO1 3
#define MIPS32_C0_TLBLO1 3
#define MIPS32_C0_CONTEXT 4
#define MIPS32_C0_CTXT 4
#define MIPS32_C0_PAGEMASK 5
#define MIPS32_C0_PAGEGRAIN (5, 1)
#define MIPS32_C0_WIRED 6
#define MIPS32_C0_HWRENA 7
#define MIPS32_C0_BADVADDR 8
#define MIPS32_C0_VADDR 8
#define MIPS32_C0_COUNT 9
#define MIPS32_C0_ENTRYHI 10
#define MIPS32_C0_TLBHI 10
#define MIPS32_C0_GUESTCTL1 10
#define MIPS32_C0_COMPARE 11
#define MIPS32_C0_STATUS 12
#define MIPS32_C0_SR 12
#define MIPS32_C0_INTCTL (12, 1)
#define MIPS32_C0_SRSCTL (12, 2)
#define MIPS32_C0_SRSMAP (12, 3)
#define MIPS32_C0_CAUSE 13
#define MIPS32_C0_CR 13
#define MIPS32_C0_EPC 14
#define MIPS32_C0_PRID 15
#define MIPS32_C0_EBASE (15, 1)
#define MIPS32_C0_CONFIG 16
#define MIPS32_C0_CONFIG0 (16, 0)
#define MIPS32_C0_CONFIG1 (16, 1)
#define MIPS32_C0_CONFIG2 (16, 2)
#define MIPS32_C0_CONFIG3 (16, 3)
#define MIPS32_C0_LLADDR 17
#define MIPS32_C0_WATCHLO 18
#define MIPS32_C0_WATCHHI 19
#define MIPS32_C0_DEBUG 23
#define MIPS32_C0_DEPC 24
#define MIPS32_C0_PERFCNT 25
#define MIPS32_C0_ERRCTL 26
#define MIPS32_C0_CACHEERR 27
#define MIPS32_C0_TAGLO 28
#define MIPS32_C0_ITAGLO 28
#define MIPS32_C0_DTAGLO (28, 2)
#define MIPS32_C0_TAGLO2 (28, 4)
#define MIPS32_C0_DATALO (28, 1)
#define MIPS32_C0_IDATALO (28, 1)
#define MIPS32_C0_DDATALO (28, 3)
#define MIPS32_C0_DATALO2 (28, 5)
#define MIPS32_C0_TAGHI 29
#define MIPS32_C0_ITAGHI 29
#define MIPS32_C0_DATAHI (29, 1)
#define MIPS32_C0_ERRPC 30
#define MIPS32_C0_DESAVE 31
/*
* MIPS32 MMU types
*/
#define MIPS32_MMU_TLB 1
#define MIPS32_MMU_BAT 2
#define MIPS32_MMU_FIXED 3
#define MIPS32_MMU_DUAL_VTLB_FTLB 4
enum mips32_cpu_vendor {
MIPS32_CPU_VENDOR_MTI,
MIPS32_CPU_VENDOR_ALCHEMY,
MIPS32_CPU_VENDOR_BROADCOM,
MIPS32_CPU_VENDOR_ALTERA,
MIPS32_CPU_VENDOR_LEXRA,
};
enum mips32_isa_supported {
MIPS16,
MIPS32,
MIPS64,
MICROMIPS_ONLY,
MIPS32_AT_RESET_AND_MICROMIPS,
MICROMIPS_AT_RESET_AND_MIPS32,
};
struct mips32_cpu_features {
/* Type of CPU (4Kc, 24Kf, etc.) */
uint32_t cpu_core;
/* Internal representation of cpu type */
uint32_t cpu_type;
/* Processor vendor */
enum mips32_cpu_vendor vendor;
/* Supported ISA and boot config */
enum mips32_isa_supported isa;
/* PRID */
uint32_t prid;
/* Processor implemented the MultiThreading ASE */
bool mtase;
/* Processor implemented the DSP ASE */
bool dspase;
/* Processor implemented the SmartMIPS ASE */
bool smase;
/* Processor implemented the MIPS16[e] ASE */
bool m16ase;
/* Processor implemented the microMIPS ASE */
bool micromipsase;
/* Processor implemented the Virtualization ASE */
uint32_t vzase;
uint32_t vz_guest_id_width;
/* ebase.cpuid number */
uint32_t cpuid;
uint32_t inst_cache_size;
uint32_t data_cache_size;
uint32_t mmu_type;
uint32_t tlb_entries;
uint32_t num_shadow_regs;
/* Processor implemented the MSA module */
bool msa;
/* Processor implemented mfhc0 and mthc0 instructions */
bool mvh;
bool guest_ctl1_present;
bool cdmm;
};
extern const struct command_registration mips32_command_handlers[];
int mips32_arch_state(struct target *target);

View File

@ -823,9 +823,13 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz
return retval;
}
int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
int mips32_pracc_write_regs(struct mips32_common *mips32)
{
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
uint32_t *gprs = mips32->core_regs.gpr;
uint32_t *c0rs = mips32->core_regs.cp0;
pracc_queue_init(&ctx);
uint32_t cp0_write_code[] = {
@ -837,66 +841,178 @@ int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
MIPS32_MTC0(ctx.isa, 1, 24, 0), /* move $1 to depc (pc) */
};
uint32_t cp0_write_data[] = {
/* lo */
gprs[32],
/* hi */
gprs[33],
/* status */
c0rs[0],
/* badvaddr */
c0rs[1],
/* cause */
c0rs[2],
/* depc (pc) */
c0rs[3],
};
for (size_t i = 0; i < ARRAY_SIZE(cp0_write_code); i++) {
/* load CP0 value in $1 */
pracc_add_li32(&ctx, 1, cp0_write_data[i], 0);
/* write value from $1 to CP0 register */
pracc_add(&ctx, 0, cp0_write_code[i]);
}
/* load registers 2 to 31 with li32, optimize */
for (int i = 2; i < 32; i++)
pracc_add_li32(&ctx, i, regs[i], 1);
pracc_add_li32(&ctx, i, gprs[i], 1);
for (int i = 0; i != 6; i++) {
pracc_add_li32(&ctx, 1, regs[i + 32], 0); /* load CPO value in $1 */
pracc_add(&ctx, 0, cp0_write_code[i]); /* write value from $1 to CPO register */
}
pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); /* load $15 in DeSave */
pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, UPPER16((regs[1])))); /* load upper half word in $1 */
pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 1, 1, LOWER16((regs[1])))); /* load lower half word in $1 */
/* load $15 in DeSave */
pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0));
/* load upper half word in $1 */
pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, UPPER16((gprs[1]))));
/* jump to start */
pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));
/* load lower half word in $1 */
pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 1, 1, LOWER16((gprs[1]))));
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
ejtag_info->reg8 = regs[8];
ejtag_info->reg9 = regs[9];
ejtag_info->reg8 = gprs[8];
ejtag_info->reg9 = gprs[9];
pracc_queue_free(&ctx);
return ctx.retval;
}
int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
/* Saves content in `$1` to `DeSave(cp0.31.0)` and loads `MIPS32_PRACC_BASE_ADDR` into `$1` */
static void mips32_pracc_store_regs_set_base_addr(struct pracc_queue_info *ctx)
{
struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
pracc_queue_init(&ctx);
/* move $1 to COP0 DeSave */
pracc_add(ctx, 0, MIPS32_MTC0(ctx->isa, 1, 31, 0));
/* $1 = MIP32_PRACC_BASE_ADDR */
pracc_add(ctx, 0, MIPS32_LUI(ctx->isa, 1, PRACC_UPPER_BASE_ADDR));
}
uint32_t cp0_read_code[] = {
MIPS32_MFC0(ctx.isa, 8, 12, 0), /* move status to $8 */
MIPS32_MFLO(ctx.isa, 8), /* move lo to $8 */
MIPS32_MFHI(ctx.isa, 8), /* move hi to $8 */
MIPS32_MFC0(ctx.isa, 8, 8, 0), /* move badvaddr to $8 */
MIPS32_MFC0(ctx.isa, 8, 13, 0), /* move cause to $8 */
MIPS32_MFC0(ctx.isa, 8, 24, 0), /* move depc (pc) to $8 */
/* This function assumes the address for saving is stored in `$1`.
* And that action is performed in `mips32_pracc_set_save_base_addr`.
*/
static void mips32_pracc_store_regs_gpr(struct pracc_queue_info *ctx, unsigned int offset_gpr)
{
for (int i = 2; i != 32; i++)
pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + offset_gpr + (i * 4),
MIPS32_SW(ctx->isa, i, PRACC_OUT_OFFSET + offset_gpr + (i * 4), 1));
}
static void mips32_pracc_store_regs_lohi(struct pracc_queue_info *ctx)
{
uint32_t lohi_read_code[] = {
MIPS32_MFLO(ctx->isa, 8), /* move lo to $8 */
MIPS32_MFHI(ctx->isa, 8), /* move hi to $8 */
};
pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 1, 31, 0)); /* move $1 to COP0 DeSave */
pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, PRACC_UPPER_BASE_ADDR)); /* $1 = MIP32_PRACC_BASE_ADDR */
for (int i = 2; i != 32; i++) /* store GPR's 2 to 31 */
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i * 4),
MIPS32_SW(ctx.isa, i, PRACC_OUT_OFFSET + (i * 4), 1));
for (int i = 0; i != 6; i++) {
pracc_add(&ctx, 0, cp0_read_code[i]); /* load COP0 needed registers to $8 */
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4, /* store $8 at PARAM OUT */
MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + (i + 32) * 4, 1));
/* store lo & hi */
for (int i = 0; i < 2; i++) {
/* load COP0 needed registers to $8 */
pracc_add(ctx, 0, lohi_read_code[i]);
/* store $8 at PARAM OUT */
pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4,
MIPS32_SW(ctx->isa, 8, PRACC_OUT_OFFSET + (i + 32) * 4, 1));
}
pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 8, 31, 0)); /* move DeSave to $8, reg1 value */
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + 4, /* store reg1 value from $8 to param out */
MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + 4, 1));
}
pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 1, 31, 0)); /* move COP0 DeSave to $1, restore reg1 */
pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); /* load $15 in DeSave */
/* Saves CP0 registers [status, badvaddr, cause, depc] */
static void mips32_pracc_store_regs_cp0_context(struct pracc_queue_info *ctx, unsigned int offset_cp0)
{
uint32_t cp0_read_code[] = {
MIPS32_MFC0(ctx->isa, 8, 12, 0), /* move status to $8 */
MIPS32_MFC0(ctx->isa, 8, 8, 0), /* move badvaddr to $8 */
MIPS32_MFC0(ctx->isa, 8, 13, 0), /* move cause to $8 */
MIPS32_MFC0(ctx->isa, 8, 24, 0), /* move depc (pc) to $8 */
};
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs, 1);
/* store cp0 */
for (size_t i = 0; i < ARRAY_SIZE(cp0_read_code); i++) {
size_t offset = offset_cp0 + (i * 4);
/* load COP0 needed registers to $8 */
pracc_add(ctx, 0, cp0_read_code[i]);
/* store $8 at PARAM OUT */
pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + offset,
MIPS32_SW(ctx->isa, 8, PRACC_OUT_OFFSET + offset, 1));
}
}
/* Loads original content of $1 into $8,
* then store it to the batch data access address.
* Finally it restores $1 from DeSave.
*/
static void mips32_pracc_store_regs_restore(struct pracc_queue_info *ctx)
{
/* move DeSave to $8, reg1 value */
pracc_add(ctx, 0, MIPS32_MFC0(ctx->isa, 8, 31, 0));
/* store reg1 value from $8 to param out */
pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + 4,
MIPS32_SW(ctx->isa, 8, PRACC_OUT_OFFSET + 4, 1));
/* move COP0 DeSave to $1, restore reg1 */
pracc_add(ctx, 0, MIPS32_MFC0(ctx->isa, 1, 31, 0));
}
/* This function performs following actions:
* Saves `$1` to `DeSave`,
* then load `PRACC_UPPER_BASE_ADDR` for saving the register data structure into `$1`,
* Saves `$2` ~ `$31` to `PRACC_UPPER_BASE_ADDR + offset_gpr`
* Saves HI and LO,
* Saves necessary cp0 registers.
*/
static void mips32_pracc_store_regs(struct pracc_queue_info *ctx,
unsigned int offset_gpr, unsigned int offset_cp0)
{
mips32_pracc_store_regs_set_base_addr(ctx);
mips32_pracc_store_regs_gpr(ctx, offset_gpr);
mips32_pracc_store_regs_lohi(ctx);
mips32_pracc_store_regs_cp0_context(ctx, offset_cp0);
mips32_pracc_store_regs_restore(ctx);
}
int mips32_pracc_read_regs(struct mips32_common *mips32)
{
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
struct mips32_core_regs *core_regs = &mips32->core_regs;
unsigned int offset_gpr = ((uint8_t *)&core_regs->gpr[0]) - (uint8_t *)core_regs;
unsigned int offset_cp0 = ((uint8_t *)&core_regs->cp0[0]) - (uint8_t *)core_regs;
/*
* This procedure has to be in 2 distinctive steps, because we can
* only know whether FP is enabled after reading CP0.
*
* Step 1: Read everything except CP1 stuff
* Step 2: Read CP1 stuff if FP is implemented
*/
pracc_queue_init(&ctx);
mips32_pracc_store_regs(&ctx, offset_gpr, offset_cp0);
/* jump to start */
pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));
/* load $15 in DeSave */
pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0));
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, (uint32_t *)&mips32->core_regs, 1);
ejtag_info->reg8 = regs[8]; /* reg8 is saved but not restored, next called function should restore it */
ejtag_info->reg9 = regs[9];
pracc_queue_free(&ctx);
/* reg8 is saved but not restored, next called function should restore it */
ejtag_info->reg8 = mips32->core_regs.gpr[8];
ejtag_info->reg9 = mips32->core_regs.gpr[9];
/* we only care if FP is actually impl'd and if cp1 is enabled */
/* since we already read cp0 in the prev step */
/* now we know what's in cp0.status */
/* TODO: Read FPRs */
return ctx.retval;
}

View File

@ -36,6 +36,8 @@
#define PRACC_BLOCK 128 /* 1 Kbyte */
struct mips32_common;
struct pa_list {
uint32_t instr;
uint32_t addr;
@ -64,8 +66,8 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info,
int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source,
int write_t, uint32_t addr, int count, uint32_t *buf);
int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs);
int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs);
int mips32_pracc_read_regs(struct mips32_common *mips32);
int mips32_pracc_write_regs(struct mips32_common *mips32);
/**
* \b mips32_cp0_read

View File

@ -247,8 +247,8 @@ static int mips64_set_core_reg(struct reg *reg, uint8_t *buf)
return ERROR_TARGET_NOT_HALTED;
buf_set_u64(reg->value, 0, 64, value);
reg->dirty = 1;
reg->valid = 1;
reg->dirty = true;
reg->valid = true;
return ERROR_OK;
}
@ -265,8 +265,8 @@ static int mips64_read_core_reg(struct target *target, int num)
reg_value = mips64->core_regs[num];
buf_set_u64(mips64->core_cache->reg_list[num].value, 0, 64, reg_value);
mips64->core_cache->reg_list[num].valid = 1;
mips64->core_cache->reg_list[num].dirty = 0;
mips64->core_cache->reg_list[num].valid = true;
mips64->core_cache->reg_list[num].dirty = false;
return ERROR_OK;
}
@ -284,8 +284,8 @@ static int mips64_write_core_reg(struct target *target, int num)
reg_value = buf_get_u64(mips64->core_cache->reg_list[num].value, 0, 64);
mips64->core_regs[num] = reg_value;
LOG_DEBUG("write core reg %i value 0x%" PRIx64 "", num, reg_value);
mips64->core_cache->reg_list[num].valid = 1;
mips64->core_cache->reg_list[num].dirty = 0;
mips64->core_cache->reg_list[num].valid = true;
mips64->core_cache->reg_list[num].dirty = false;
return ERROR_OK;
}
@ -297,8 +297,8 @@ int mips64_invalidate_core_regs(struct target *target)
unsigned int i;
for (i = 0; i < mips64->core_cache->num_regs; i++) {
mips64->core_cache->reg_list[i].valid = 0;
mips64->core_cache->reg_list[i].dirty = 0;
mips64->core_cache->reg_list[i].valid = false;
mips64->core_cache->reg_list[i].dirty = false;
}
return ERROR_OK;

View File

@ -123,11 +123,12 @@
/* Debug Control Register DCR */
#define EJTAG_DCR 0xFF300000
#define EJTAG_DCR_ENM (1 << 29)
#define EJTAG_DCR_DB (1 << 17)
#define EJTAG_DCR_IB (1 << 16)
#define EJTAG_DCR_INTE (1 << 4)
#define EJTAG_DCR_MP (1 << 2)
#define EJTAG_DCR_ENM BIT(29)
#define EJTAG_DCR_FDC BIT(18)
#define EJTAG_DCR_DB BIT(17)
#define EJTAG_DCR_IB BIT(16)
#define EJTAG_DCR_INTE BIT(4)
#define EJTAG_DCR_MP BIT(2)
/* breakpoint support */
/* EJTAG_V20_* was tested on Broadcom BCM7401

View File

@ -108,11 +108,11 @@ static int mips_m4k_debug_entry(struct target *target)
mips32->isa_mode = MIPS32_ISA_MIPS32;
/* other than mips32 only and isa bit set ? */
if (mips32->isa_imp && buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1))
if (mips32->isa_imp && buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 1))
mips32->isa_mode = mips32->isa_imp == 2 ? MIPS32_ISA_MIPS16E : MIPS32_ISA_MMIPS32;
LOG_DEBUG("entered debug state at PC 0x%" PRIx32 ", target->state: %s",
buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32),
buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32),
target_state_name(target));
return ERROR_OK;
@ -443,18 +443,18 @@ static int mips_m4k_internal_restore(struct target *target, int current,
/* current = 1: continue on current pc, otherwise continue at <address> */
if (!current) {
mips_m4k_isa_filter(mips32->isa_imp, &address);
buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
mips32->core_cache->reg_list[MIPS32_PC].dirty = true;
mips32->core_cache->reg_list[MIPS32_PC].valid = true;
buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32, address);
mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].dirty = true;
mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].valid = true;
}
if ((mips32->isa_imp > 1) && debug_execution) /* if more than one isa supported */
buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1, mips32->isa_mode);
buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 1, mips32->isa_mode);
if (!current)
resume_pc = address;
else
resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32);
mips32_restore_context(target);
@ -537,15 +537,15 @@ static int mips_m4k_step(struct target *target, int current,
/* current = 1: continue on current pc, otherwise continue at <address> */
if (!current) {
mips_m4k_isa_filter(mips32->isa_imp, &address);
buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
mips32->core_cache->reg_list[MIPS32_PC].dirty = true;
mips32->core_cache->reg_list[MIPS32_PC].valid = true;
buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32, address);
mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].dirty = true;
mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].valid = true;
}
/* the front-end may request us not to handle breakpoints */
if (handle_breakpoints) {
breakpoint = breakpoint_find(target,
buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32));
if (breakpoint)
mips_m4k_unset_breakpoint(target, breakpoint);
}

View File

@ -625,8 +625,8 @@ static int mips_mips64_resume(struct target *target, int current,
/* current = 1: continue on current pc, otherwise continue at <address> */
if (!current) {
buf_set_u64(pc->value, 0, 64, address);
pc->dirty = 1;
pc->valid = 1;
pc->dirty = true;
pc->valid = true;
}
resume_pc = buf_get_u64(pc->value, 0, 64);
@ -717,8 +717,8 @@ static int mips_mips64_step(struct target *target, int current,
* <address> */
if (!current) {
buf_set_u64(pc->value, 0, 64, address);
pc->dirty = 1;
pc->valid = 1;
pc->dirty = true;
pc->valid = true;
}
/* the front-end may request us not to handle breakpoints */

View File

@ -3053,6 +3053,10 @@ COMMAND_HANDLER(handle_reg_command)
LOG_DEBUG("-");
struct target *target = get_current_target(CMD_CTX);
if (!target_was_examined(target)) {
LOG_ERROR("Target not examined yet");
return ERROR_TARGET_NOT_EXAMINED;
}
struct reg *reg = NULL;
/* list all available registers for the current target */
@ -3117,7 +3121,7 @@ COMMAND_HANDLER(handle_reg_command)
if (!reg) {
command_print(CMD, "%i is out of bounds, the current target "
"has only %i registers (0 - %i)", num, count, count - 1);
return ERROR_OK;
return ERROR_FAIL;
}
} else {
/* access a single register by its name */
@ -3136,9 +3140,9 @@ COMMAND_HANDLER(handle_reg_command)
if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0')
&& (CMD_ARGV[1][0] <= '9')))) {
if ((CMD_ARGC == 2) && (strcmp(CMD_ARGV[1], "force") == 0))
reg->valid = 0;
reg->valid = false;
if (reg->valid == 0) {
if (!reg->valid) {
int retval = reg->type->get(reg);
if (retval != ERROR_OK) {
LOG_ERROR("Could not read register '%s'", reg->name);
@ -3176,7 +3180,7 @@ COMMAND_HANDLER(handle_reg_command)
not_found:
command_print(CMD, "register %s not found in current target", CMD_ARGV[0]);
return ERROR_OK;
return ERROR_FAIL;
}
COMMAND_HANDLER(handle_poll_command)
@ -4071,13 +4075,14 @@ COMMAND_HANDLER(handle_wp_command)
struct watchpoint *watchpoint = target->watchpoints;
while (watchpoint) {
char wp_type = (watchpoint->rw == WPT_READ ? 'r' : (watchpoint->rw == WPT_WRITE ? 'w' : 'a'));
command_print(CMD, "address: " TARGET_ADDR_FMT
", len: 0x%8.8" PRIx32
", r/w/a: %i, value: 0x%8.8" PRIx64
", r/w/a: %c, value: 0x%8.8" PRIx64
", mask: 0x%8.8" PRIx64,
watchpoint->address,
watchpoint->length,
(int)watchpoint->rw,
wp_type,
watchpoint->value,
watchpoint->mask);
watchpoint = watchpoint->next;
@ -4138,17 +4143,28 @@ COMMAND_HANDLER(handle_wp_command)
COMMAND_HANDLER(handle_rwp_command)
{
int retval;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
target_addr_t addr;
COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
struct target *target = get_current_target(CMD_CTX);
int retval = watchpoint_remove(target, addr);
if (!strcmp(CMD_ARGV[0], "all")) {
retval = watchpoint_remove_all(target);
if (retval != ERROR_OK)
command_print(CMD, "Error during removal of watchpoint at address " TARGET_ADDR_FMT, addr);
if (retval != ERROR_OK) {
command_print(CMD, "Error encountered during removal of all watchpoints.");
command_print(CMD, "Some watchpoints may have remained set.");
}
} else {
target_addr_t addr;
COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
retval = watchpoint_remove(target, addr);
if (retval != ERROR_OK)
command_print(CMD, "Error during removal of watchpoint at address " TARGET_ADDR_FMT, addr);
}
return retval;
}
@ -5135,7 +5151,7 @@ static int target_jim_get_reg(Jim_Interp *interp, int argc,
return JIM_ERR;
}
if (force) {
if (force || !reg->valid) {
int retval = reg->type->get(reg);
if (retval != ERROR_OK) {
@ -5860,6 +5876,18 @@ COMMAND_HANDLER(handle_target_current_state)
return ERROR_OK;
}
COMMAND_HANDLER(handle_target_debug_reason)
{
if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
struct target *target = get_current_target(CMD_CTX);
command_print(CMD, "%s", debug_reason_name(target));
return ERROR_OK;
}
static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
struct jim_getopt_info goi;
@ -6011,6 +6039,13 @@ static const struct command_registration target_instance_command_handlers[] = {
.help = "displays the current state of this target",
.usage = "",
},
{
.name = "debug_reason",
.mode = COMMAND_EXEC,
.handler = handle_target_debug_reason,
.help = "displays the debug reason of this target",
.usage = "",
},
{
.name = "arp_examine",
.mode = COMMAND_EXEC,
@ -6110,7 +6145,7 @@ static int target_create(struct jim_getopt_info *goi)
if (e != JIM_OK)
return e;
struct transport *tr = get_current_transport();
if (tr->override_target) {
if (tr && tr->override_target) {
e = tr->override_target(&cp);
if (e != ERROR_OK) {
LOG_ERROR("The selected transport doesn't support this target");
@ -7067,7 +7102,7 @@ static const struct command_registration target_exec_command_handlers[] = {
.handler = handle_rwp_command,
.mode = COMMAND_EXEC,
.help = "remove watchpoint",
.usage = "address",
.usage = "'all' | address",
},
{
.name = "load_image",

View File

@ -0,0 +1,23 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# configuration file for Advantech IMX8QM DMSSE20
#
# only JTAG supported
transport select jtag
# set a safe JTAG clock speed, can be overridden
adapter speed 1000
# default JTAG configuration has only SRST and no TRST
reset_config srst_only srst_push_pull
# delay after SRST goes inactive
adapter srst delay 70
# board has an i.MX8QM with 4 Cortex-A53 cores and 2 Cortex-A72
set CHIPNAME imx8qm
set CHIPCORES 6
# source SoC configuration
source [find tcl/target/imx8qm.cfg]

View File

@ -0,0 +1,25 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
#
# Texas Instruments AM243 Launchpad
# https://www.ti.com/tool/LP-AM243
#
# AM243 Launchpad has an xds110 onboard.
source [find interface/xds110.cfg]
transport select jtag
# default JTAG configuration has only SRST and no TRST
reset_config srst_only srst_push_pull
# delay after SRST goes inactive
adapter srst delay 20
if { ![info exists SOC] } {
set SOC am243
}
source [find target/ti_k3.cfg]
adapter speed 250

View File

@ -0,0 +1,25 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
#
# Texas Instruments AM263 Launchpad
# https://www.ti.com/tool/LP-AM263
#
# AM263 Launchpad has an xds110 onboard.
source [find interface/xds110.cfg]
transport select jtag
# default JTAG configuration has only SRST and no TRST
reset_config srst_only srst_push_pull
# delay after SRST goes inactive
adapter srst delay 20
if { ![info exists SOC] } {
set SOC am263
}
source [find target/ti_k3.cfg]
adapter speed 250

View File

@ -0,0 +1,25 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
#
# Texas Instruments AM273 Launchpad
# https://www.ti.com/tool/LP-AM273
#
# AM273 Launchpad has an xds110 onboard.
source [find interface/xds110.cfg]
transport select jtag
# default JTAG configuration has only SRST and no TRST
reset_config srst_only srst_push_pull
# delay after SRST goes inactive
adapter srst delay 20
if { ![info exists SOC] } {
set SOC am273
}
source [find target/ti_k3.cfg]
adapter speed 250

View File

@ -5,6 +5,7 @@
#
source [find target/swj-dp.tcl]
source [find mem_helper.tcl]
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
@ -116,3 +117,51 @@ proc nrf52_recover {} {
}
add_help_text nrf52_recover "Mass erase and unlock nRF52 device"
tpiu create $_CHIPNAME.tpiu -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0xE0040000
lappend _telnet_autocomplete_skip _proc_pre_enable_$_CHIPNAME.tpiu
proc _proc_pre_enable_$_CHIPNAME.tpiu {_targetname _chipname} {
targets $_targetname
# Read FICR.INFO.PART
set PART [mrw 0x10000100]
switch $PART {
0x52840 -
0x52833 -
0x52832 {
if { [$_chipname.tpiu cget -protocol] eq "sync" } {
if { [$_chipname.tpiu cget -port-width] != 4 } {
echo "Error. Device only supports 4-bit sync traces."
return
}
# Set TRACECONFIG.TRACEMUX to enable synchronous trace
mmw 0x4000055C 0x00020000 0x00010000
$_targetname configure -event reset-end {
mmw 0x4000055C 0x00020000 0x00010000
}
} else {
# Set TRACECONFIG.TRACEMUX to enable SWO
mmw 0x4000055C 0x00010000 0x00020000
$_targetname configure -event reset-end {
mmw 0x4000055C 0x00010000 0x00020000
}
}
}
0x52820 -
0x52811 -
0x52810 -
0x52805 {
echo "Error: Device does not support TPIU"
return
}
default {
echo "Error: Unknown device"
return
}
}
}
$_CHIPNAME.tpiu configure -event pre-enable "_proc_pre_enable_$_CHIPNAME.tpiu $_TARGETNAME $_CHIPNAME"

View File

@ -2,24 +2,30 @@
# Copyright (C) 2019-2021 Texas Instruments Incorporated - http://www.ti.com/
#
# Texas Instruments K3 devices:
# * AM243: https://www.ti.com/lit/pdf/spruim2
# Has 4 R5 Cores, M4F and an M3
# * AM263: https://www.ti.com/lit/pdf/spruj17
# Has 4 R5 Cores and an M3
# * AM273: https://www.ti.com/lit/pdf/spruiu0
# Has 2 R5 Cores and an M3
# * AM625: https://www.ti.com/lit/pdf/spruiv7a
# Has 4 ARMV8 Cores and 1 R5 Core and an M4F
# * AM62A7: https://www.ti.com/lit/pdf/spruj16a
# Has 4 ARMV8 Cores and 2 R5 Cores
# * AM62P: https://www.ti.com/lit/pdf/spruj83
# Has 4 ARMV8 Cores and 2 R5 Cores
# * AM642: https://www.ti.com/lit/pdf/spruim2
# Has 2 ARMV8 Cores and 4 R5 Cores, M4F and an M3
# * AM654x: https://www.ti.com/lit/pdf/spruid7
# Has 4 ARMV8 Cores and 2 R5 Cores and an M3
# * J721E: https://www.ti.com/lit/pdf/spruil1
# Has 2 ARMV8 Cores and 6 R5 Cores and an M3
# * J7200: https://www.ti.com/lit/pdf/spruiu1
# Has 2 ARMV8 Cores and 4 R5 Cores and an M3
# * J721E: https://www.ti.com/lit/pdf/spruil1
# Has 2 ARMV8 Cores and 6 R5 Cores and an M3
# * J721S2: https://www.ti.com/lit/pdf/spruj28
# Has 2 ARMV8 Cores and 6 R5 Cores and an M4F
# * J784S4/AM69: http://www.ti.com/lit/zip/spruj52
# Has 8 ARMV8 Cores and 8 R5 Cores
# * AM642: https://www.ti.com/lit/pdf/spruim2
# Has 2 ARMV8 Cores and 4 R5 Cores, M4F and an M3
# * AM625: https://www.ti.com/lit/pdf/spruiv7a
# Has 4 ARMV8 Cores and 1 R5 Core and an M4F
# * AM62a7: https://www.ti.com/lit/pdf/spruj16a
# Has 4 ARMV8 Cores and 2 R5 Cores
# * AM62P: https://www.ti.com/lit/pdf/spruj83
# Has 4 ARMV8 Cores and 2 R5 Cores
#
source [find target/swj-dp.tcl]
@ -44,6 +50,7 @@ set CM3_CTIBASE {0x3C016000}
# sysctrl power-ap unlock offsets
set _sysctrl_ap_unlock_offsets {0xf0 0x44}
set _sysctrl_ap_num 7
# All the ARMV8s are the next processors.
# CL0,CORE0 CL0,CORE1 CL1,CORE0 CL1,CORE1
@ -55,6 +62,7 @@ set ARMV8_CTIBASE {0x90420000 0x90520000 0x90820000 0x90920000}
set R5_DBGBASE {0x9d010000 0x9d012000 0x9d410000 0x9d412000 0x9d510000 0x9d512000}
set R5_CTIBASE {0x9d018000 0x9d019000 0x9d418000 0x9d419000 0x9d518000 0x9d519000}
set R5_NAMES {mcu_r5.0 mcu_r5.1 main0_r5.0 main0_r5.1 main1_r5.0 main1_r5.1}
set _r5_ap_num 1
# Finally an General Purpose(GP) MCU
set CM4_CTIBASE {0x20001000}
@ -64,8 +72,46 @@ set _gp_mcu_cores 0
# General Purpose MCU power-ap unlock offsets
set _gp_mcu_ap_unlock_offsets {0xf0 0x60}
# Generic mem-ap port number
set _mem_ap_num 2
# Set configuration overrides for each SOC
switch $_soc {
am263 {
set _K3_DAP_TAPID 0x2bb7d02f
# Mem-ap port
set _mem_ap_num 6
# AM263 has 0 ARMV8 CPUs
set _armv8_cores 0
# AM263 has 2 cluster of 2 R5s cores.
set _r5_cores 4
set R5_NAMES {main0_r5.0 main0_r5.1 main1_r5.0 main1_r5.1}
set R5_DBGBASE {0x90030000 0x90032000 0x90050000 0x90052000}
set R5_CTIBASE {0x90038000 0x90039000 0x90058000 0x90059000}
set _r5_ap_num 5
}
am273 {
set _K3_DAP_TAPID 0x1bb6a02f
# Mem-ap port
set _mem_ap_num 6
# system controller is on AP0
set _sysctrl_ap_num 0
# AM273 has 0 ARMV8 CPUs
set _armv8_cores 0
# AM273 has 1 cluster of 2 R5s cores.
set _r5_cores 2
set R5_NAMES {main0_r5.0 main0_r5.1}
set R5_DBGBASE {0x90030000 0x90032000}
set R5_CTIBASE {0x90038000 0x90039000}
set _r5_ap_num 5
}
am654 {
set _K3_DAP_TAPID 0x0bb5a02f
@ -80,6 +126,7 @@ switch $_soc {
# Sysctrl power-ap unlock offsets
set _sysctrl_ap_unlock_offsets {0xf0 0x50}
}
am243 -
am642 {
set _K3_DAP_TAPID 0x0bb3802f
@ -97,6 +144,12 @@ switch $_soc {
# M4 processor
set _gp_mcu_cores 1
# Overrides for am243
if { "$_soc" == "am243" } {
# Uses the same JTAG ID
set _armv8_cores 0
}
}
am625 {
set _K3_DAP_TAPID 0x0bb7e02f
@ -248,6 +301,13 @@ switch $_soc {
}
}
proc _get_rtos_type_for_cpu { target_name } {
if { [info exists ::RTOS($target_name)] } {
return $::RTOS($target_name)
}
return none
}
set _CHIPNAME $_soc
swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_K3_DAP_TAPID -ignore-version
@ -259,8 +319,13 @@ set _TARGETNAME $_CHIPNAME.cpu
set _CTINAME $_CHIPNAME.cti
# sysctrl is always present
cti create $_CTINAME.sysctrl -dap $_CHIPNAME.dap -ap-num 7 -baseaddr [lindex $CM3_CTIBASE 0]
target create $_TARGETNAME.sysctrl cortex_m -dap $_CHIPNAME.dap -ap-num 7 -defer-examine
cti create $_CTINAME.sysctrl -dap $_CHIPNAME.dap \
-ap-num $_sysctrl_ap_num -baseaddr [lindex $CM3_CTIBASE 0]
target create $_TARGETNAME.sysctrl cortex_m -dap $_CHIPNAME.dap \
-ap-num $_sysctrl_ap_num -defer-examine \
-rtos [_get_rtos_type_for_cpu $_TARGETNAME.sysctrl]
$_TARGETNAME.sysctrl configure -event reset-assert { }
proc sysctrl_up {} {
@ -303,8 +368,9 @@ for { set _core 0 } { $_core < $_armv8_cores } { incr _core } {
cti create $_CTINAME.$_armv8_cpu_name.$_core -dap $_CHIPNAME.dap -ap-num 1 \
-baseaddr [lindex $ARMV8_CTIBASE $_core]
target create $_TARGETNAME.$_armv8_cpu_name.$_core aarch64 -dap $_CHIPNAME.dap \
-dbgbase [lindex $ARMV8_DBGBASE $_core] -cti $_CTINAME.$_armv8_cpu_name.$_core -defer-examine
target create $_TARGETNAME.$_armv8_cpu_name.$_core aarch64 -dap $_CHIPNAME.dap -coreid $_core \
-dbgbase [lindex $ARMV8_DBGBASE $_core] -cti $_CTINAME.$_armv8_cpu_name.$_core -defer-examine \
-rtos [_get_rtos_type_for_cpu $_TARGETNAME.$_armv8_cpu_name.$_core]
set _v8_smp_targets "$_v8_smp_targets $_TARGETNAME.$_armv8_cpu_name.$_core"
@ -323,34 +389,37 @@ for { set _core 0 } { $_core < $_armv8_cores } { incr _core } {
}
}
# Setup ARMV8 proc commands based on CPU to prevent people confusing SoCs
set _armv8_up_cmd "$_armv8_cpu_name"_up
# Available if V8_SMP_DEBUG is set to non-zero value
set _armv8_smp_cmd "$_armv8_cpu_name"_smp
if { $_armv8_cores > 0 } {
# Setup ARMV8 proc commands based on CPU to prevent people confusing SoCs
set _armv8_up_cmd "$_armv8_cpu_name"_up
# Available if V8_SMP_DEBUG is set to non-zero value
set _armv8_smp_cmd "$_armv8_cpu_name"_smp
if { $_v8_smp_debug == 0 } {
proc $_armv8_up_cmd { args } {
foreach _core $args {
targets $_core
_cpu_no_smp_up
if { $_v8_smp_debug == 0 } {
proc $_armv8_up_cmd { args } {
foreach _core $args {
targets $_core
_cpu_no_smp_up
}
}
} else {
proc $_armv8_smp_cmd { args } {
_armv8_smp_up
}
# Declare SMP
target smp {*}$_v8_smp_targets
}
} else {
proc $_armv8_smp_cmd { args } {
_armv8_smp_up
}
# Declare SMP
target smp $:::_v8_smp_targets
}
for { set _core 0 } { $_core < $_r5_cores } { incr _core } {
set _r5_name [lindex $R5_NAMES $_core]
cti create $_CTINAME.$_r5_name -dap $_CHIPNAME.dap -ap-num 1 \
cti create $_CTINAME.$_r5_name -dap $_CHIPNAME.dap -ap-num $_r5_ap_num \
-baseaddr [lindex $R5_CTIBASE $_core]
# inactive core examination will fail - wait till startup of additional core
target create $_TARGETNAME.$_r5_name cortex_r4 -dap $_CHIPNAME.dap \
-dbgbase [lindex $R5_DBGBASE $_core] -ap-num 1 -defer-examine
-dbgbase [lindex $R5_DBGBASE $_core] -ap-num $_r5_ap_num -defer-examine \
-rtos [_get_rtos_type_for_cpu $_TARGETNAME.$_r5_name]
$_TARGETNAME.$_r5_name configure -event gdb-attach {
_cpu_no_smp_up
@ -368,7 +437,8 @@ proc r5_up { args } {
if { $_gp_mcu_cores != 0 } {
cti create $_CTINAME.gp_mcu -dap $_CHIPNAME.dap -ap-num 8 -baseaddr [lindex $CM4_CTIBASE 0]
target create $_TARGETNAME.gp_mcu cortex_m -dap $_CHIPNAME.dap -ap-num 8 -defer-examine
target create $_TARGETNAME.gp_mcu cortex_m -dap $_CHIPNAME.dap -ap-num 8 -defer-examine \
-rtos [_get_rtos_type_for_cpu $_TARGETNAME.gp_mcu]
$_TARGETNAME.gp_mcu configure -event reset-assert { }
proc gp_mcu_up {} {
@ -404,4 +474,7 @@ if { 0 == [string compare [adapter name] dmem ] } {
} else {
puts "ERROR: ${SOC} data is missing to support dmem access!"
}
} else {
# AXI AP access port for SoC address map
target create $_CHIPNAME.axi_ap mem_ap -dap $_CHIPNAME.dap -ap-num $_mem_ap_num
}

View File

@ -77,6 +77,7 @@ bNumInterfaces
idProduct
idVendor
iInterface
iManufacturer
iProduct
iSerialNumber
wMaxPacketSize