Merge pull request #976 from riscv/from_upstream
Merge up to d4575b647a
from upstream
This commit is contained in:
commit
62758f2087
|
@ -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.
|
|
@ -66,6 +66,7 @@ EXTRA_DIST += \
|
||||||
LICENSES/preferred/BSD-2-Clause-Views \
|
LICENSES/preferred/BSD-2-Clause-Views \
|
||||||
LICENSES/preferred/BSD-3-Clause \
|
LICENSES/preferred/BSD-3-Clause \
|
||||||
LICENSES/preferred/BSD-Source-Code \
|
LICENSES/preferred/BSD-Source-Code \
|
||||||
|
LICENSES/preferred/CC0-1.0 \
|
||||||
LICENSES/preferred/GFDL-1.2 \
|
LICENSES/preferred/GFDL-1.2 \
|
||||||
LICENSES/preferred/gfdl-1.2.texi.readme \
|
LICENSES/preferred/gfdl-1.2.texi.readme \
|
||||||
LICENSES/preferred/GPL-2.0 \
|
LICENSES/preferred/GPL-2.0 \
|
||||||
|
|
|
@ -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
|
* Since at least FreeRTOS V7.5.3 uxTopUsedPriority is no longer
|
||||||
|
|
|
@ -5325,6 +5325,18 @@ Displays the current target state:
|
||||||
(Also, @pxref{eventpolling,,Event Polling}.)
|
(Also, @pxref{eventpolling,,Event Polling}.)
|
||||||
@end deffn
|
@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}
|
@deffn {Command} {$target_name eventlist}
|
||||||
Displays a table listing all event handlers
|
Displays a table listing all event handlers
|
||||||
currently associated with this target.
|
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.
|
Remove the breakpoint at @var{address} or all breakpoints.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Command} {rwp} address
|
@deffn {Command} {rwp} @option{all} | address
|
||||||
Remove data watchpoint on @var{address}
|
Remove data watchpoint on @var{address} or all watchpoints.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Command} {wp} [address len [(@option{r}|@option{w}|@option{a}) [value [mask]]]]
|
@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}>
|
@item @b{capture} <@var{command}>
|
||||||
|
|
||||||
Run <@var{command}> and return full log output that was produced during
|
Run <@var{command}> and return full log output that was produced during
|
||||||
its execution. Example:
|
its execution together with the command output. Example:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
> capture "reset init"
|
> capture "reset init"
|
||||||
|
|
|
@ -815,7 +815,8 @@ static const struct command_registration rsl10_exec_command_handlers[] = {
|
||||||
.help = "Mass erase all unprotected flash areas",
|
.help = "Mass erase all unprotected flash areas",
|
||||||
.usage = "",
|
.usage = "",
|
||||||
},
|
},
|
||||||
COMMAND_REGISTRATION_DONE};
|
COMMAND_REGISTRATION_DONE
|
||||||
|
};
|
||||||
|
|
||||||
static const struct command_registration rsl10_command_handlers[] = {
|
static const struct command_registration rsl10_command_handlers[] = {
|
||||||
{
|
{
|
||||||
|
@ -825,7 +826,8 @@ static const struct command_registration rsl10_command_handlers[] = {
|
||||||
.usage = "",
|
.usage = "",
|
||||||
.chain = rsl10_exec_command_handlers,
|
.chain = rsl10_exec_command_handlers,
|
||||||
},
|
},
|
||||||
COMMAND_REGISTRATION_DONE};
|
COMMAND_REGISTRATION_DONE
|
||||||
|
};
|
||||||
|
|
||||||
const struct flash_driver rsl10_flash = {
|
const struct flash_driver rsl10_flash = {
|
||||||
.name = "rsl10",
|
.name = "rsl10",
|
||||||
|
|
|
@ -22,10 +22,22 @@
|
||||||
/* Shared table of known SPI flash devices for SPI-based flash drivers. Taken
|
/* Shared table of known SPI flash devices for SPI-based flash drivers. Taken
|
||||||
* from device datasheets and Linux SPI flash drivers. */
|
* from device datasheets and Linux SPI flash drivers. */
|
||||||
const struct flash_device flash_devices[] = {
|
const struct flash_device flash_devices[] = {
|
||||||
/* name, read_cmd, qread_cmd, pprog_cmd, erase_cmd, chip_erase_cmd, device_id,
|
/* Note: device_id is usually 3 bytes long, however the unused highest byte counts
|
||||||
* pagesize, sectorsize, size_in_bytes
|
* 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 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 m25pe20", 0x03, 0x00, 0x02, 0xd8, 0x00, 0x00128020, 0x100, 0x10000, 0x40000),
|
||||||
FLASH_ID("st m25pe40", 0x03, 0x00, 0x02, 0xd8, 0x00, 0x00138020, 0x100, 0x10000, 0x80000),
|
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),
|
FLASH_ID("zetta zd25q16", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001560ba, 0x100, 0x10000, 0x200000),
|
||||||
|
|
||||||
/* FRAM, no erase commands, no write page or sectors */
|
/* 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 mb85rs16n", 0x03, 0, 0x02, 0x00010104, 0x800),
|
||||||
FRAM_ID("fu mb85rs32v", 0x03, 0, 0x02, 0x00010204, 0x1000), /* exists ? */
|
FRAM_ID("fu mb85rs32v", 0x03, 0, 0x02, 0x00010204, 0x1000), /* exists ? */
|
||||||
FRAM_ID("fu mb85rs64v", 0x03, 0, 0x02, 0x00020304, 0x2000),
|
FRAM_ID("fu mb85rs64v", 0x03, 0, 0x02, 0x00020304, 0x2000),
|
||||||
|
|
|
@ -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
|
* The tcl return value is empty for openocd commands that provide
|
||||||
* progress output.
|
* progress output.
|
||||||
*
|
*
|
||||||
* Therefore we set the tcl return value only if we actually
|
* For other commands, we prepend the logs to the tcl return value.
|
||||||
* captured output.
|
|
||||||
*/
|
*/
|
||||||
static void command_log_capture_finish(struct log_capture_state *state)
|
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);
|
log_remove_callback(tcl_output, state);
|
||||||
|
|
||||||
int length;
|
int loglen;
|
||||||
Jim_GetString(state->output, &length);
|
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)
|
// Just in case the log doesn't end with a newline, we add it
|
||||||
Jim_SetResult(state->interp, state->output);
|
if (loglen != 0 && reslen != 0 && log_result[loglen - 1] != '\n')
|
||||||
else {
|
Jim_AppendString(state->interp, state->output, "\n", 1);
|
||||||
/* No output captured, use tcl return value (which could
|
|
||||||
* be empty too). */
|
Jim_AppendString(state->interp, state->output, cmd_result, reslen);
|
||||||
}
|
|
||||||
|
Jim_SetResult(state->interp, state->output);
|
||||||
Jim_DecrRefCount(state->interp, state->output);
|
Jim_DecrRefCount(state->interp, state->output);
|
||||||
|
|
||||||
free(state);
|
free(state);
|
||||||
|
@ -691,8 +693,8 @@ COMMAND_HANDLER(handle_echo)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Capture progress output and return as tcl return value. If the
|
/* Return both the progress output (LOG_INFO and higher)
|
||||||
* progress output was empty, return tcl return value.
|
* and the tcl return value of a command.
|
||||||
*/
|
*/
|
||||||
static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The manufacturer's standard identification code list appears in JEP106.
|
* 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
|
* JEP106 is regularly updated. For the current manufacturer's standard
|
||||||
* identification code list, please visit the JEDEC website at www.jedec.org .
|
* 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][0x01 - 1] = "AMD",
|
||||||
[0][0x02 - 1] = "AMI",
|
[0][0x02 - 1] = "AMI",
|
||||||
|
@ -1375,7 +1375,7 @@
|
||||||
[10][0x65 - 1] = "Esperanto Technologies",
|
[10][0x65 - 1] = "Esperanto Technologies",
|
||||||
[10][0x66 - 1] = "JinSheng Electronic (Shenzhen) Co Ltd",
|
[10][0x66 - 1] = "JinSheng Electronic (Shenzhen) Co Ltd",
|
||||||
[10][0x67 - 1] = "Shenzhen Shi Bolunshuai Technology",
|
[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][0x69 - 1] = "Fraunhofer IIS",
|
||||||
[10][0x6a - 1] = "Kandou Bus SA",
|
[10][0x6a - 1] = "Kandou Bus SA",
|
||||||
[10][0x6b - 1] = "Acer",
|
[10][0x6b - 1] = "Acer",
|
||||||
|
@ -1841,4 +1841,51 @@
|
||||||
[14][0x3f - 1] = "Shenzhen Dingsheng Technology Co Ltd",
|
[14][0x3f - 1] = "Shenzhen Dingsheng Technology Co Ltd",
|
||||||
[14][0x40 - 1] = "EVAS Intelligence Co Ltd",
|
[14][0x40 - 1] = "EVAS Intelligence Co Ltd",
|
||||||
[14][0x41 - 1] = "Kaibright Electronic Technologies",
|
[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 */
|
/* EOF */
|
||||||
|
|
|
@ -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 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};
|
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)
|
if (ret != ERROR_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -677,7 +677,7 @@ static struct armjtagew *armjtagew_usb_open(void)
|
||||||
const uint16_t pids[] = { USB_PID, 0 };
|
const uint16_t pids[] = { USB_PID, 0 };
|
||||||
struct libusb_device_handle *dev;
|
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;
|
return NULL;
|
||||||
|
|
||||||
struct armjtagew *result = malloc(sizeof(struct armjtagew));
|
struct armjtagew *result = malloc(sizeof(struct armjtagew));
|
||||||
|
|
|
@ -331,7 +331,7 @@ COMMAND_HANDLER(bcm2835gpio_handle_peripheral_base)
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp_base = bcm2835_peri_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);
|
tmp_base);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -487,7 +487,7 @@ static int esp_usb_jtag_init(void)
|
||||||
bitq_interface->in_rdy = esp_usb_jtag_in_rdy;
|
bitq_interface->in_rdy = esp_usb_jtag_in_rdy;
|
||||||
bitq_interface->in = esp_usb_jtag_in;
|
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) {
|
if (r != ERROR_OK) {
|
||||||
LOG_ERROR("esp_usb_jtag: could not find or open device!");
|
LOG_ERROR("esp_usb_jtag: could not find or open device!");
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -246,7 +246,7 @@ static int ft232r_init(void)
|
||||||
{
|
{
|
||||||
uint16_t avids[] = {ft232r_vid, 0};
|
uint16_t avids[] = {ft232r_vid, 0};
|
||||||
uint16_t apids[] = {ft232r_pid, 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();
|
const char *ft232r_serial_desc = adapter_get_required_serial();
|
||||||
LOG_ERROR("ft232r not found: vid=%04x, pid=%04x, serial=%s\n",
|
LOG_ERROR("ft232r not found: vid=%04x, pid=%04x, serial=%s\n",
|
||||||
ft232r_vid, ft232r_pid, (!ft232r_serial_desc) ? "[any]" : ft232r_serial_desc);
|
ft232r_vid, ft232r_pid, (!ft232r_serial_desc) ? "[any]" : ft232r_serial_desc);
|
||||||
|
|
|
@ -275,7 +275,7 @@ static int kitprog_usb_open(void)
|
||||||
const uint16_t vids[] = { VID, 0 };
|
const uint16_t vids[] = { VID, 0 };
|
||||||
const uint16_t pids[] = { PID, 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");
|
LOG_ERROR("Failed to open or find the device");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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[],
|
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)
|
adapter_get_alternate_serial_fn adapter_get_alternate_serial)
|
||||||
{
|
{
|
||||||
int cnt, idx, err_code;
|
int cnt, idx, err_code;
|
||||||
int retval = ERROR_FAIL;
|
int retval = ERROR_FAIL;
|
||||||
bool serial_mismatch = false;
|
bool serial_mismatch = false;
|
||||||
|
bool product_mismatch = false;
|
||||||
struct libusb_device_handle *libusb_handle = NULL;
|
struct libusb_device_handle *libusb_handle = NULL;
|
||||||
const char *serial = adapter_get_required_serial();
|
const char *serial = adapter_get_required_serial();
|
||||||
|
|
||||||
|
@ -188,10 +189,18 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (product &&
|
||||||
|
!string_descriptor_equal(libusb_handle, dev_desc.iProduct, product)) {
|
||||||
|
product_mismatch = true;
|
||||||
|
libusb_close(libusb_handle);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Success. */
|
/* Success. */
|
||||||
*out = libusb_handle;
|
*out = libusb_handle;
|
||||||
retval = ERROR_OK;
|
retval = ERROR_OK;
|
||||||
serial_mismatch = false;
|
serial_mismatch = false;
|
||||||
|
product_mismatch = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (cnt >= 0)
|
if (cnt >= 0)
|
||||||
|
@ -200,6 +209,9 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
|
||||||
if (serial_mismatch)
|
if (serial_mismatch)
|
||||||
LOG_INFO("No device matches the serial string");
|
LOG_INFO("No device matches the serial string");
|
||||||
|
|
||||||
|
if (product_mismatch)
|
||||||
|
LOG_INFO("No device matches the product string");
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
libusb_exit(jtag_libusb_context);
|
libusb_exit(jtag_libusb_context);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc,
|
||||||
const uint16_t vids[], const uint16_t pids[]);
|
const uint16_t vids[], const uint16_t pids[]);
|
||||||
int jtag_libusb_open(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);
|
adapter_get_alternate_serial_fn adapter_get_alternate_serial);
|
||||||
void jtag_libusb_close(struct libusb_device_handle *dev);
|
void jtag_libusb_close(struct libusb_device_handle *dev);
|
||||||
int jtag_libusb_control_transfer(struct libusb_device_handle *dev,
|
int jtag_libusb_control_transfer(struct libusb_device_handle *dev,
|
||||||
|
|
|
@ -695,7 +695,7 @@ struct opendous_jtag *opendous_usb_open(void)
|
||||||
struct opendous_jtag *result;
|
struct opendous_jtag *result;
|
||||||
|
|
||||||
struct libusb_device_handle *devh;
|
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;
|
return NULL;
|
||||||
|
|
||||||
jtag_libusb_set_configuration(devh, 0);
|
jtag_libusb_set_configuration(devh, 0);
|
||||||
|
|
|
@ -438,7 +438,7 @@ static int openjtag_init_cy7c65215(void)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
usbh = NULL;
|
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) {
|
if (ret != ERROR_OK) {
|
||||||
LOG_ERROR("unable to open cy7c65215 device");
|
LOG_ERROR("unable to open cy7c65215 device");
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
@ -363,7 +363,7 @@ static int osbdm_flush(struct osbdm *osbdm, struct queue *queue)
|
||||||
static int osbdm_open(struct osbdm *osbdm)
|
static int osbdm_open(struct osbdm *osbdm)
|
||||||
{
|
{
|
||||||
(void)memset(osbdm, 0, sizeof(*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;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
if (libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)
|
if (libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)
|
||||||
|
|
|
@ -1448,7 +1448,7 @@ static int rlink_init(void)
|
||||||
|
|
||||||
const uint16_t vids[] = { USB_IDVENDOR, 0 };
|
const uint16_t vids[] = { USB_IDVENDOR, 0 };
|
||||||
const uint16_t pids[] = { USB_IDPRODUCT, 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;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
struct libusb_device_descriptor descriptor;
|
struct libusb_device_descriptor descriptor;
|
||||||
|
|
|
@ -3406,7 +3406,7 @@ static int stlink_usb_usb_open(void *handle, struct hl_interface_param_s *param)
|
||||||
in order to become operational.
|
in order to become operational.
|
||||||
*/
|
*/
|
||||||
do {
|
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) {
|
&h->usb_backend_priv.fd, stlink_usb_get_alternate_serial) != ERROR_OK) {
|
||||||
LOG_ERROR("open failed");
|
LOG_ERROR("open failed");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
|
@ -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;
|
/* TI (Stellaris) ICDI provides its serial number in the USB descriptor;
|
||||||
no need to provide a callback here. */
|
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) {
|
if (!h->usb_dev) {
|
||||||
LOG_ERROR("open failed");
|
LOG_ERROR("open failed");
|
||||||
|
|
|
@ -202,7 +202,7 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
|
||||||
bool renumeration = false;
|
bool renumeration = false;
|
||||||
int ret;
|
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("Altera USB-Blaster II (uninitialized) found");
|
||||||
LOG_INFO("Loading firmware...");
|
LOG_INFO("Loading firmware...");
|
||||||
ret = load_usb_blaster_firmware(temp, low);
|
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 };
|
const uint16_t pids_renum[] = { low->ublast_pid, 0 };
|
||||||
|
|
||||||
if (renumeration == false) {
|
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");
|
LOG_ERROR("Altera USB-Blaster II not found");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int retry = 10;
|
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);
|
usleep(1000000);
|
||||||
LOG_INFO("Waiting for reenumerate...");
|
LOG_INFO("Waiting for reenumerate...");
|
||||||
}
|
}
|
||||||
|
|
|
@ -341,7 +341,7 @@ struct usbprog_jtag *usbprog_jtag_open(void)
|
||||||
const uint16_t pids[] = { PID, 0 };
|
const uint16_t pids[] = { PID, 0 };
|
||||||
struct libusb_device_handle *dev;
|
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;
|
return NULL;
|
||||||
|
|
||||||
struct usbprog_jtag *tmp = malloc(sizeof(struct usbprog_jtag));
|
struct usbprog_jtag *tmp = malloc(sizeof(struct usbprog_jtag));
|
||||||
|
|
|
@ -121,6 +121,7 @@ static int lattice_certus_enable_programming(struct jtag_tap *tap)
|
||||||
uint8_t buffer = 0;
|
uint8_t buffer = 0;
|
||||||
field.num_bits = 8;
|
field.num_bits = 8;
|
||||||
field.out_value = &buffer;
|
field.out_value = &buffer;
|
||||||
|
field.in_value = NULL;
|
||||||
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
|
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
|
||||||
jtag_add_runtest(2, TAP_IDLE);
|
jtag_add_runtest(2, TAP_IDLE);
|
||||||
return jtag_execute_queue();
|
return jtag_execute_queue();
|
||||||
|
|
|
@ -83,6 +83,7 @@ static void os_free(struct target *target)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
free(target->rtos->symbols);
|
free(target->rtos->symbols);
|
||||||
|
rtos_free_threadlist(target->rtos);
|
||||||
free(target->rtos);
|
free(target->rtos);
|
||||||
target->rtos = NULL;
|
target->rtos = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,8 @@ struct gdb_connection {
|
||||||
char *thread_list;
|
char *thread_list;
|
||||||
/* flag to mask the output from gdb_log_callback() */
|
/* flag to mask the output from gdb_log_callback() */
|
||||||
enum gdb_output_flag output_flag;
|
enum gdb_output_flag output_flag;
|
||||||
|
/* Unique index for this GDB connection. */
|
||||||
|
unsigned int unique_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -392,6 +394,7 @@ static void gdb_log_incoming_packet(struct connection *connection, char *packet)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct target *target = get_target_from_connection(connection);
|
struct target *target = get_target_from_connection(connection);
|
||||||
|
struct gdb_connection *gdb_connection = connection->priv;
|
||||||
|
|
||||||
/* Avoid dumping non-printable characters to the terminal */
|
/* Avoid dumping non-printable characters to the terminal */
|
||||||
const unsigned packet_len = strlen(packet);
|
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) {
|
if (packet_prefix_printable) {
|
||||||
const unsigned int prefix_len = colon - packet + 1; /* + 1 to include the ':' */
|
const unsigned int prefix_len = colon - packet + 1; /* + 1 to include the ':' */
|
||||||
const unsigned int payload_len = packet_len - prefix_len;
|
const unsigned int payload_len = packet_len - prefix_len;
|
||||||
LOG_TARGET_DEBUG(target, "received packet: %.*s<binary-data-%u-bytes>", prefix_len,
|
LOG_TARGET_DEBUG(target, "{%d} received packet: %.*s<binary-data-%u-bytes>",
|
||||||
packet, payload_len);
|
gdb_connection->unique_index, prefix_len, packet, payload_len);
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
/* All chars printable, dump the packet as is */
|
/* 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;
|
return;
|
||||||
|
|
||||||
struct target *target = get_target_from_connection(connection);
|
struct target *target = get_target_from_connection(connection);
|
||||||
|
struct gdb_connection *gdb_connection = connection->priv;
|
||||||
|
|
||||||
if (find_nonprint_char(packet_buf, packet_len))
|
if (find_nonprint_char(packet_buf, packet_len))
|
||||||
LOG_TARGET_DEBUG(target, "sending packet: $<binary-data-%u-bytes>#%2.2x",
|
LOG_TARGET_DEBUG(target, "{%d} sending packet: $<binary-data-%u-bytes>#%2.2x",
|
||||||
packet_len, checksum);
|
gdb_connection->unique_index, packet_len, checksum);
|
||||||
else
|
else
|
||||||
LOG_TARGET_DEBUG(target, "sending packet: $%.*s#%2.2x", packet_len, packet_buf,
|
LOG_TARGET_DEBUG(target, "{%d} sending packet: $%.*s#%2.2x",
|
||||||
checksum);
|
gdb_connection->unique_index, packet_len, packet_buf, checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gdb_put_packet_inner(struct connection *connection,
|
static int gdb_put_packet_inner(struct connection *connection,
|
||||||
|
@ -1017,6 +1022,7 @@ static int gdb_new_connection(struct connection *connection)
|
||||||
struct target *target;
|
struct target *target;
|
||||||
int retval;
|
int retval;
|
||||||
int initial_ack;
|
int initial_ack;
|
||||||
|
static unsigned int next_unique_id = 1;
|
||||||
|
|
||||||
target = get_target_from_connection(connection);
|
target = get_target_from_connection(connection);
|
||||||
connection->priv = gdb_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->target_desc.tdesc_length = 0;
|
||||||
gdb_connection->thread_list = NULL;
|
gdb_connection->thread_list = NULL;
|
||||||
gdb_connection->output_flag = GDB_OUTPUT_NO;
|
gdb_connection->output_flag = GDB_OUTPUT_NO;
|
||||||
|
gdb_connection->unique_index = next_unique_id++;
|
||||||
|
|
||||||
/* send ACK to GDB for debug request */
|
/* send ACK to GDB for debug request */
|
||||||
gdb_write(connection, "+", 1);
|
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,
|
log_printf_lf(all_targets->next ? LOG_LVL_INFO : LOG_LVL_DEBUG,
|
||||||
__FILE__, __LINE__, __func__,
|
__FILE__, __LINE__, __func__,
|
||||||
"New GDB Connection: %d, Target %s, state: %s",
|
"New GDB Connection: %d, Target %s, state: %s",
|
||||||
gdb_actual_connections,
|
gdb_connection->unique_index,
|
||||||
target_name(target),
|
target_name(target),
|
||||||
target_state_name(target));
|
target_state_name(target));
|
||||||
|
|
||||||
if (!target_was_examined(target)) {
|
if (!target_was_examined(target)) {
|
||||||
LOG_ERROR("Target %s not examined yet, refuse gdb connection %d!",
|
LOG_ERROR("Target %s not examined yet, refuse gdb connection %d!",
|
||||||
target_name(target), gdb_actual_connections);
|
target_name(target), gdb_connection->unique_index);
|
||||||
gdb_actual_connections--;
|
|
||||||
return ERROR_TARGET_NOT_EXAMINED;
|
return ERROR_TARGET_NOT_EXAMINED;
|
||||||
}
|
}
|
||||||
|
gdb_actual_connections++;
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED)
|
if (target->state != TARGET_HALTED)
|
||||||
LOG_WARNING("GDB connection %d on target %s not 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);
|
log_remove_callback(gdb_log_callback, connection);
|
||||||
|
|
||||||
gdb_actual_connections--;
|
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_name(target),
|
||||||
target_state_name(target),
|
target_state_name(target),
|
||||||
gdb_actual_connections);
|
gdb_actual_connections);
|
||||||
|
|
|
@ -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> */
|
/* current = 1: continue on current PC, otherwise continue at <address> */
|
||||||
if (!current) {
|
if (!current) {
|
||||||
target_buffer_set_u32(target, pc->value, address);
|
target_buffer_set_u32(target, pc->value, address);
|
||||||
pc->dirty = 1;
|
pc->dirty = true;
|
||||||
pc->valid = 1;
|
pc->valid = true;
|
||||||
LOG_DEBUG("Changing the value of current PC to 0x%08" TARGET_PRIxADDR, address);
|
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);
|
resume_pc, pc->dirty, pc->valid);
|
||||||
|
|
||||||
/* check if GDB tells to set our PC where to continue from */
|
/* 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);
|
value = target_buffer_get_u32(target, pc->value);
|
||||||
LOG_DEBUG("resume Core (when start-core) with PC @:0x%08" PRIx32, 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));
|
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;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* core instruction cache is now invalid. */
|
|
||||||
CHECK_RETVAL(arc_cache_invalidate(target));
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1658,9 +1655,6 @@ static int arc_unset_breakpoint(struct target *target,
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* core instruction cache is now invalid. */
|
|
||||||
CHECK_RETVAL(arc_cache_invalidate(target));
|
|
||||||
|
|
||||||
return retval;
|
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> */
|
/* current = 1: continue on current pc, otherwise continue at <address> */
|
||||||
if (!current) {
|
if (!current) {
|
||||||
buf_set_u32(pc->value, 0, 32, address);
|
buf_set_u32(pc->value, 0, 32, address);
|
||||||
pc->dirty = 1;
|
pc->dirty = true;
|
||||||
pc->valid = 1;
|
pc->valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("Target steps one instruction from PC=0x%" PRIx32,
|
LOG_DEBUG("Target steps one instruction from PC=0x%" PRIx32,
|
||||||
|
|
|
@ -61,6 +61,7 @@ enum arm_arch {
|
||||||
/** Known ARM implementor IDs */
|
/** Known ARM implementor IDs */
|
||||||
enum arm_implementor {
|
enum arm_implementor {
|
||||||
ARM_IMPLEMENTOR_ARM = 0x41,
|
ARM_IMPLEMENTOR_ARM = 0x41,
|
||||||
|
ARM_IMPLEMENTOR_INFINEON = 0x49,
|
||||||
ARM_IMPLEMENTOR_REALTEK = 0x72,
|
ARM_IMPLEMENTOR_REALTEK = 0x72,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -230,12 +231,22 @@ struct arm {
|
||||||
uint32_t crn, uint32_t crm,
|
uint32_t crn, uint32_t crm,
|
||||||
uint32_t *value);
|
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. */
|
/** Write coprocessor register. */
|
||||||
int (*mcr)(struct target *target, int cpnum,
|
int (*mcr)(struct target *target, int cpnum,
|
||||||
uint32_t op1, uint32_t op2,
|
uint32_t op1, uint32_t op2,
|
||||||
uint32_t crn, uint32_t crm,
|
uint32_t crn, uint32_t crm,
|
||||||
uint32_t value);
|
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;
|
void *arch_info;
|
||||||
|
|
||||||
/** For targets conforming to ARM Debug Interface v5,
|
/** For targets conforming to ARM Debug Interface v5,
|
||||||
|
|
|
@ -63,6 +63,29 @@ static int dpm_mrc(struct target *target, int cpnum,
|
||||||
return retval;
|
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,
|
static int dpm_mcr(struct target *target, int cpnum,
|
||||||
uint32_t op1, uint32_t op2, uint32_t crn, uint32_t crm,
|
uint32_t op1, uint32_t op2, uint32_t crn, uint32_t crm,
|
||||||
uint32_t value)
|
uint32_t value)
|
||||||
|
@ -88,6 +111,29 @@ static int dpm_mcr(struct target *target, int cpnum,
|
||||||
return retval;
|
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 */
|
/* coprocessor access setup */
|
||||||
arm->mrc = dpm_mrc;
|
arm->mrc = dpm_mrc;
|
||||||
arm->mcr = dpm_mcr;
|
arm->mcr = dpm_mcr;
|
||||||
|
arm->mrrc = dpm_mrrc;
|
||||||
|
arm->mcrr = dpm_mcrr;
|
||||||
|
|
||||||
/* breakpoint setup -- optional until it works everywhere */
|
/* breakpoint setup -- optional until it works everywhere */
|
||||||
if (!target->type->add_breakpoint) {
|
if (!target->type->add_breakpoint) {
|
||||||
|
|
|
@ -72,6 +72,12 @@ struct arm_dpm {
|
||||||
int (*instr_write_data_r0)(struct arm_dpm *dpm,
|
int (*instr_write_data_r0)(struct arm_dpm *dpm,
|
||||||
uint32_t opcode, uint32_t data);
|
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. */
|
/** Runs one instruction, writing data to R0 before execution. */
|
||||||
int (*instr_write_data_r0_64)(struct arm_dpm *dpm,
|
int (*instr_write_data_r0_64)(struct arm_dpm *dpm,
|
||||||
uint32_t opcode, uint64_t data);
|
uint32_t opcode, uint64_t data);
|
||||||
|
@ -92,6 +98,13 @@ struct arm_dpm {
|
||||||
int (*instr_read_data_r0)(struct arm_dpm *dpm,
|
int (*instr_read_data_r0)(struct arm_dpm *dpm,
|
||||||
uint32_t opcode, uint32_t *data);
|
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,
|
int (*instr_read_data_r0_64)(struct arm_dpm *dpm,
|
||||||
uint32_t opcode, uint64_t *data);
|
uint32_t opcode, uint64_t *data);
|
||||||
|
|
||||||
|
|
|
@ -187,6 +187,17 @@
|
||||||
(0xee100010 | (crm) | ((op2) << 5) | ((cp) << 8) \
|
(0xee100010 | (crm) | ((op2) << 5) | ((cp) << 8) \
|
||||||
| ((rd) << 12) | ((crn) << 16) | ((op1) << 21))
|
| ((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
|
/* Move to coprocessor from ARM register
|
||||||
* cp: Coprocessor number
|
* cp: Coprocessor number
|
||||||
* op1: Coprocessor opcode
|
* op1: Coprocessor opcode
|
||||||
|
@ -199,6 +210,17 @@
|
||||||
(0xee000010 | (crm) | ((op2) << 5) | ((cp) << 8) \
|
(0xee000010 | (crm) | ((op2) << 5) | ((cp) << 8) \
|
||||||
| ((rd) << 12) | ((crn) << 16) | ((op1) << 21))
|
| ((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)
|
/* Breakpoint instruction (ARMv5)
|
||||||
* im: 16-bit immediate
|
* im: 16-bit immediate
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1093,6 +1093,94 @@ COMMAND_HANDLER(handle_armv4_5_mcrmrc)
|
||||||
return ERROR_OK;
|
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[] = {
|
static const struct command_registration arm_exec_command_handlers[] = {
|
||||||
{
|
{
|
||||||
.name = "reg",
|
.name = "reg",
|
||||||
|
@ -1115,6 +1203,20 @@ static const struct command_registration arm_exec_command_handlers[] = {
|
||||||
.help = "read coprocessor register",
|
.help = "read coprocessor register",
|
||||||
.usage = "cpnum op1 CRn CRm op2",
|
.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,
|
.chain = arm_all_profiles_command_handlers,
|
||||||
},
|
},
|
||||||
|
@ -1669,6 +1771,14 @@ static int arm_default_mrc(struct target *target, int cpnum,
|
||||||
return ERROR_FAIL;
|
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,
|
static int arm_default_mcr(struct target *target, int cpnum,
|
||||||
uint32_t op1, uint32_t op2,
|
uint32_t op1, uint32_t op2,
|
||||||
uint32_t crn, uint32_t crm,
|
uint32_t crn, uint32_t crm,
|
||||||
|
@ -1678,6 +1788,14 @@ static int arm_default_mcr(struct target *target, int cpnum,
|
||||||
return ERROR_FAIL;
|
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)
|
int arm_init_arch_info(struct target *target, struct arm *arm)
|
||||||
{
|
{
|
||||||
target->arch_info = arm;
|
target->arch_info = arm;
|
||||||
|
@ -1697,8 +1815,12 @@ int arm_init_arch_info(struct target *target, struct arm *arm)
|
||||||
|
|
||||||
if (!arm->mrc)
|
if (!arm->mrc)
|
||||||
arm->mrc = arm_default_mrc;
|
arm->mrc = arm_default_mrc;
|
||||||
|
if (!arm->mrrc)
|
||||||
|
arm->mrrc = arm_default_mrrc;
|
||||||
if (!arm->mcr)
|
if (!arm->mcr)
|
||||||
arm->mcr = arm_default_mcr;
|
arm->mcr = arm_default_mcr;
|
||||||
|
if (!arm->mcrr)
|
||||||
|
arm->mcrr = arm_default_mcrr;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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).
|
* 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,
|
* In normal operation this is called on entry to halting debug state,
|
||||||
* possibly after some other operations supporting restore of 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 */
|
/* update core mode and state */
|
||||||
armv8_set_cpsr(arm, cpsr);
|
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;
|
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);
|
r = armv8_reg_current(arm, i);
|
||||||
if (!r->exist || r->valid)
|
if (!r->exist || r->valid)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -18,6 +18,11 @@
|
||||||
#include "rtos/rtos.h"
|
#include "rtos/rtos.h"
|
||||||
#include "smp.h"
|
#include "smp.h"
|
||||||
|
|
||||||
|
enum breakpoint_watchpoint {
|
||||||
|
BREAKPOINT,
|
||||||
|
WATCHPOINT,
|
||||||
|
};
|
||||||
|
|
||||||
static const char * const breakpoint_type_strings[] = {
|
static const char * const breakpoint_type_strings[] = {
|
||||||
"hardware",
|
"hardware",
|
||||||
"software"
|
"software"
|
||||||
|
@ -418,26 +423,90 @@ int breakpoint_remove(struct target *target, target_addr_t address)
|
||||||
return retval;
|
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;
|
int retval = ERROR_OK;
|
||||||
if (target->smp) {
|
if (target->smp) {
|
||||||
struct target_list *head;
|
struct target_list *head;
|
||||||
|
|
||||||
foreach_smp_target(head, target->smp_targets) {
|
foreach_smp_target(head, target->smp_targets) {
|
||||||
struct target *curr = head->target;
|
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)
|
if (status != ERROR_OK)
|
||||||
retval = status;
|
retval = status;
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
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 breakpoint_clear_target(struct target *target)
|
||||||
{
|
{
|
||||||
int retval = ERROR_OK;
|
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)
|
static int watchpoint_remove_internal(struct target *target, target_addr_t address)
|
||||||
{
|
{
|
||||||
struct watchpoint *watchpoint = target->watchpoints;
|
struct watchpoint *watchpoint = target->watchpoints;
|
||||||
|
|
|
@ -73,6 +73,7 @@ int watchpoint_add(struct target *target,
|
||||||
target_addr_t address, uint32_t length,
|
target_addr_t address, uint32_t length,
|
||||||
enum watchpoint_rw rw, uint64_t value, uint64_t mask);
|
enum watchpoint_rw rw, uint64_t value, uint64_t mask);
|
||||||
int watchpoint_remove(struct target *target, target_addr_t address);
|
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 */
|
/* report type and address of just hit watchpoint */
|
||||||
int watchpoint_hit(struct target *target, enum watchpoint_rw *rw,
|
int watchpoint_hit(struct target *target, enum watchpoint_rw *rw,
|
||||||
|
|
|
@ -471,6 +471,28 @@ static int cortex_a_instr_write_data_r0(struct arm_dpm *dpm,
|
||||||
return retval;
|
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)
|
static int cortex_a_instr_cpsr_sync(struct arm_dpm *dpm)
|
||||||
{
|
{
|
||||||
struct target *target = dpm->arm->target;
|
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);
|
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,
|
static int cortex_a_bpwp_enable(struct arm_dpm *dpm, unsigned index_t,
|
||||||
uint32_t addr, uint32_t control)
|
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_dcc = cortex_a_instr_write_data_dcc;
|
||||||
dpm->instr_write_data_r0 = cortex_a_instr_write_data_r0;
|
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_cpsr_sync = cortex_a_instr_cpsr_sync;
|
||||||
|
|
||||||
dpm->instr_read_data_dcc = cortex_a_instr_read_data_dcc;
|
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 = 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_enable = cortex_a_bpwp_enable;
|
||||||
dpm->bpwp_disable = cortex_a_bpwp_disable;
|
dpm->bpwp_disable = cortex_a_bpwp_disable;
|
||||||
|
|
|
@ -111,6 +111,11 @@ static const struct cortex_m_part_info cortex_m_parts[] = {
|
||||||
.arch = ARM_ARCH_V8M,
|
.arch = ARM_ARCH_V8M,
|
||||||
.flags = CORTEX_M_F_HAS_FPV5,
|
.flags = CORTEX_M_F_HAS_FPV5,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.impl_part = INFINEON_SLX2_PARTNO,
|
||||||
|
.name = "Infineon-SLx2",
|
||||||
|
.arch = ARM_ARCH_V8M,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.impl_part = REALTEK_M200_PARTNO,
|
.impl_part = REALTEK_M200_PARTNO,
|
||||||
.name = "Real-M200 (KM0)",
|
.name = "Real-M200 (KM0)",
|
||||||
|
|
|
@ -45,19 +45,20 @@
|
||||||
*/
|
*/
|
||||||
enum cortex_m_impl_part {
|
enum cortex_m_impl_part {
|
||||||
CORTEX_M_PARTNO_INVALID,
|
CORTEX_M_PARTNO_INVALID,
|
||||||
STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0x132), /* FIXME - confirm implementor! */
|
STAR_MC1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0x132), /* FIXME - confirm implementor! */
|
||||||
CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC20),
|
CORTEX_M0_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC20),
|
||||||
CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC21),
|
CORTEX_M1_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC21),
|
||||||
CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC23),
|
CORTEX_M3_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC23),
|
||||||
CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC24),
|
CORTEX_M4_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC24),
|
||||||
CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC27),
|
CORTEX_M7_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC27),
|
||||||
CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC60),
|
CORTEX_M0P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xC60),
|
||||||
CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD20),
|
CORTEX_M23_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD20),
|
||||||
CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21),
|
CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21),
|
||||||
CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31),
|
CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31),
|
||||||
CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22),
|
CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22),
|
||||||
REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd20),
|
INFINEON_SLX2_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_INFINEON, 0xDB0),
|
||||||
REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd22),
|
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 */
|
/* Relevant Cortex-M flags, used in struct cortex_m_part_info.flags */
|
||||||
|
|
|
@ -552,8 +552,8 @@ static int etm_set_reg(struct reg *reg, uint32_t value)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_set_u32(reg->value, 0, reg->size, value);
|
buf_set_u32(reg->value, 0, reg->size, value);
|
||||||
reg->valid = 1;
|
reg->valid = true;
|
||||||
reg->dirty = 0;
|
reg->dirty = false;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
static int identify_image_type(struct image *image, const char *type_string, const char *url)
|
||||||
{
|
{
|
||||||
if (type_string) {
|
if (type_string) {
|
||||||
if (!strcmp(type_string, "bin"))
|
if (!strcmp(type_string, "bin")) {
|
||||||
image->type = IMAGE_BINARY;
|
image->type = IMAGE_BINARY;
|
||||||
else if (!strcmp(type_string, "ihex"))
|
} else if (!strcmp(type_string, "ihex")) {
|
||||||
image->type = IMAGE_IHEX;
|
image->type = IMAGE_IHEX;
|
||||||
else if (!strcmp(type_string, "elf"))
|
} else if (!strcmp(type_string, "elf")) {
|
||||||
image->type = IMAGE_ELF;
|
image->type = IMAGE_ELF;
|
||||||
else if (!strcmp(type_string, "mem"))
|
} else if (!strcmp(type_string, "mem")) {
|
||||||
image->type = IMAGE_MEMORY;
|
image->type = IMAGE_MEMORY;
|
||||||
else if (!strcmp(type_string, "s19"))
|
} else if (!strcmp(type_string, "s19")) {
|
||||||
image->type = IMAGE_SRECORD;
|
image->type = IMAGE_SRECORD;
|
||||||
else if (!strcmp(type_string, "build"))
|
} else if (!strcmp(type_string, "build")) {
|
||||||
image->type = IMAGE_BUILDER;
|
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;
|
return ERROR_IMAGE_TYPE_UNKNOWN;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
return autodetect_image_type(image, url);
|
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);
|
retval = fileio_open(&image_binary->fileio, url, FILEIO_READ, FILEIO_BINARY);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
goto free_mem_on_error;
|
||||||
|
|
||||||
size_t filesize;
|
size_t filesize;
|
||||||
retval = fileio_size(image_binary->fileio, &filesize);
|
retval = fileio_size(image_binary->fileio, &filesize);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
fileio_close(image_binary->fileio);
|
fileio_close(image_binary->fileio);
|
||||||
return retval;
|
goto free_mem_on_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
image->num_sections = 1;
|
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);
|
retval = fileio_open(&image_ihex->fileio, url, FILEIO_READ, FILEIO_TEXT);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
goto free_mem_on_error;
|
||||||
|
|
||||||
retval = image_ihex_buffer_complete(image);
|
retval = image_ihex_buffer_complete(image);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR(
|
LOG_ERROR(
|
||||||
"failed buffering IHEX image, check server output for additional information");
|
"failed buffering IHEX image, check server output for additional information");
|
||||||
fileio_close(image_ihex->fileio);
|
fileio_close(image_ihex->fileio);
|
||||||
return retval;
|
goto free_mem_on_error;
|
||||||
}
|
}
|
||||||
} else if (image->type == IMAGE_ELF) {
|
} else if (image->type == IMAGE_ELF) {
|
||||||
struct image_elf *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);
|
retval = fileio_open(&image_elf->fileio, url, FILEIO_READ, FILEIO_BINARY);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
goto free_mem_on_error;
|
||||||
|
|
||||||
retval = image_elf_read_headers(image);
|
retval = image_elf_read_headers(image);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
fileio_close(image_elf->fileio);
|
fileio_close(image_elf->fileio);
|
||||||
return retval;
|
goto free_mem_on_error;
|
||||||
}
|
}
|
||||||
} else if (image->type == IMAGE_MEMORY) {
|
} else if (image->type == IMAGE_MEMORY) {
|
||||||
struct target *target = get_target(url);
|
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);
|
retval = fileio_open(&image_mot->fileio, url, FILEIO_READ, FILEIO_TEXT);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
goto free_mem_on_error;
|
||||||
|
|
||||||
retval = image_mot_buffer_complete(image);
|
retval = image_mot_buffer_complete(image);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR(
|
LOG_ERROR(
|
||||||
"failed buffering S19 image, check server output for additional information");
|
"failed buffering S19 image, check server output for additional information");
|
||||||
fileio_close(image_mot->fileio);
|
fileio_close(image_mot->fileio);
|
||||||
return retval;
|
goto free_mem_on_error;
|
||||||
}
|
}
|
||||||
} else if (image->type == IMAGE_BUILDER) {
|
} else if (image->type == IMAGE_BUILDER) {
|
||||||
image->num_sections = 0;
|
image->num_sections = 0;
|
||||||
|
@ -1065,6 +1068,11 @@ int image_open(struct image *image, const char *url, const char *type_string)
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
free_mem_on_error:
|
||||||
|
free(image->type_private);
|
||||||
|
image->type_private = NULL;
|
||||||
|
return retval;
|
||||||
};
|
};
|
||||||
|
|
||||||
int image_read_section(struct image *image,
|
int image_read_section(struct image *image,
|
||||||
|
|
|
@ -27,7 +27,7 @@ static const char *mips_isa_strings[] = {
|
||||||
"MIPS32", "MIPS16", "", "MICRO MIPS32",
|
"MIPS32", "MIPS16", "", "MICRO MIPS32",
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MIPS32_GDB_DUMMY_FP_REG 1
|
#define MIPS32_GDB_FP_REG 1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GDB registers
|
* GDB registers
|
||||||
|
@ -39,7 +39,7 @@ static const struct {
|
||||||
enum reg_type type;
|
enum reg_type type;
|
||||||
const char *group;
|
const char *group;
|
||||||
const char *feature;
|
const char *feature;
|
||||||
int flag;
|
int size;
|
||||||
} mips32_regs[] = {
|
} mips32_regs[] = {
|
||||||
{ 0, "r0", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
{ 0, "r0", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||||
{ 1, "r1", 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 },
|
{ 29, "r29", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||||
{ 30, "r30", 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 },
|
{ 31, "r31", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||||
{ 32, "status", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
|
{ 32, "lo", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
||||||
{ 33, "lo", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
|
{ 33, "hi", 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 },
|
|
||||||
|
|
||||||
{ 38, "f0", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 0, "f0", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 39, "f1", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 1, "f1", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 40, "f2", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 2, "f2", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 41, "f3", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 3, "f3", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 42, "f4", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 4, "f4", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 43, "f5", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 5, "f5", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 44, "f6", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 6, "f6", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 45, "f7", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 7, "f7", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 46, "f8", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 8, "f8", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 47, "f9", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 9, "f9", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 48, "f10", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 10, "f10", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 49, "f11", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 11, "f11", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 50, "f12", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 12, "f12", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 51, "f13", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 13, "f13", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 52, "f14", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 14, "f14", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 53, "f15", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 15, "f15", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 54, "f16", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 16, "f16", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 55, "f17", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 17, "f17", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 56, "f18", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 18, "f18", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 57, "f19", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 19, "f19", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 58, "f20", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 20, "f20", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 59, "f21", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 21, "f21", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 60, "f22", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 22, "f22", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 61, "f23", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 23, "f23", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 62, "f24", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 24, "f24", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 63, "f25", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 25, "f25", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 64, "f26", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 26, "f26", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 65, "f27", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 27, "f27", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 66, "f28", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 28, "f28", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 67, "f29", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 29, "f29", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 68, "f30", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 30, "f30", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 69, "f31", REG_TYPE_IEEE_SINGLE, NULL,
|
{ MIPS32_REGLIST_FP_INDEX + 31, "f31", REG_TYPE_IEEE_DOUBLE, NULL,
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
|
||||||
{ 70, "fcsr", REG_TYPE_INT, "float",
|
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
{ MIPS32_REGLIST_FPC_INDEX + 0, "fcsr", REG_TYPE_INT, "float",
|
||||||
{ 71, "fir", REG_TYPE_INT, "float",
|
"org.gnu.gdb.mips.fpu", 0 },
|
||||||
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
|
{ 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)
|
#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)
|
static int mips32_get_core_reg(struct reg *reg)
|
||||||
{
|
{
|
||||||
int retval;
|
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 mips32_core_reg *mips32_reg = reg->arch_info;
|
||||||
struct target *target = mips32_reg->target;
|
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)
|
if (target->state != TARGET_HALTED)
|
||||||
return ERROR_TARGET_NOT_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->dirty = true;
|
||||||
reg->valid = 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)
|
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 */
|
/* get pointers to arch-specific information */
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
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)
|
if (num >= MIPS32_NUM_REGS)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
reg_value = mips32->core_regs[num];
|
if (num >= MIPS32_REGLIST_C0_INDEX) {
|
||||||
buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
|
/* 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].valid = true;
|
||||||
mips32->core_cache->reg_list[num].dirty = false;
|
mips32->core_cache->reg_list[num].dirty = false;
|
||||||
|
|
||||||
|
LOG_DEBUG("read core reg %i value 0x%" PRIx64 "", num, reg_value);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mips32_write_core_reg(struct target *target, unsigned int num)
|
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 */
|
/* get pointers to arch-specific information */
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
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)
|
if (num >= MIPS32_NUM_REGS)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
|
if (num >= MIPS32_REGLIST_C0_INDEX) {
|
||||||
mips32->core_regs[num] = reg_value;
|
/* CP0 */
|
||||||
LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
|
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].valid = true;
|
||||||
mips32->core_cache->reg_list[num].dirty = false;
|
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 */
|
/* get pointers to arch-specific information */
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
struct mips32_common *mips32 = target_to_mips32(target);
|
||||||
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
|
|
||||||
|
|
||||||
/* read core registers */
|
/* 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++) {
|
for (i = 0; i < MIPS32_NUM_REGS; i++) {
|
||||||
if (!mips32->core_cache->reg_list[i].valid)
|
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 */
|
/* get pointers to arch-specific information */
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
struct mips32_common *mips32 = target_to_mips32(target);
|
||||||
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
|
|
||||||
|
|
||||||
for (i = 0; i < MIPS32_NUM_REGS; i++) {
|
for (i = 0; i < MIPS32_NUM_REGS; i++) {
|
||||||
if (mips32->core_cache->reg_list[i].dirty)
|
if (mips32->core_cache->reg_list[i].dirty)
|
||||||
|
@ -273,7 +333,7 @@ int mips32_restore_context(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write core regs */
|
/* write core regs */
|
||||||
mips32_pracc_write_regs(ejtag_info, mips32->core_regs);
|
mips32_pracc_write_regs(mips32);
|
||||||
|
|
||||||
return ERROR_OK;
|
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 "",
|
LOG_USER("target halted in %s mode due to %s, pc: 0x%8.8" PRIx32 "",
|
||||||
mips_isa_strings[mips32->isa_mode],
|
mips_isa_strings[mips32->isa_mode],
|
||||||
debug_reason_name(target),
|
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;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -322,25 +382,19 @@ struct reg_cache *mips32_build_reg_cache(struct target *target)
|
||||||
arch_info[i].mips32_common = mips32;
|
arch_info[i].mips32_common = mips32;
|
||||||
|
|
||||||
reg_list[i].name = mips32_regs[i].name;
|
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_regs[i].size ? calloc(1, 8) : calloc(1, 4);
|
||||||
reg_list[i].value = mips32_gdb_dummy_fp_value;
|
reg_list[i].valid = false;
|
||||||
reg_list[i].valid = true;
|
reg_list[i].type = &mips32_reg_type;
|
||||||
reg_list[i].arch_info = NULL;
|
reg_list[i].arch_info = &arch_info[i];
|
||||||
register_init_dummy(®_list[i]);
|
|
||||||
} else {
|
reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
|
||||||
reg_list[i].value = calloc(1, 4);
|
if (reg_list[i].reg_data_type)
|
||||||
reg_list[i].valid = false;
|
reg_list[i].reg_data_type->type = mips32_regs[i].type;
|
||||||
reg_list[i].type = &mips32_reg_type;
|
else
|
||||||
reg_list[i].arch_info = &arch_info[i];
|
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;
|
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;
|
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)) {
|
if (exit_point && (pc != exit_point)) {
|
||||||
LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc);
|
LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc);
|
||||||
return ERROR_TARGET_TIMEOUT;
|
return ERROR_TARGET_TIMEOUT;
|
||||||
|
@ -751,15 +805,82 @@ int mips32_cpu_probe(struct target *target)
|
||||||
return ERROR_OK;
|
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 */
|
/* read config to config3 cp0 registers and log isa implementation */
|
||||||
int mips32_read_config_regs(struct target *target)
|
int mips32_read_config_regs(struct target *target)
|
||||||
{
|
{
|
||||||
struct mips32_common *mips32 = target_to_mips32(target);
|
struct mips32_common *mips32 = target_to_mips32(target);
|
||||||
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
|
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
|
||||||
|
char buf[60] = {0};
|
||||||
|
int retval;
|
||||||
|
|
||||||
if (ejtag_info->config_regs == 0)
|
if (ejtag_info->config_regs == 0)
|
||||||
for (int i = 0; i != 4; i++) {
|
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) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("isa info not available, failed to read cp0 config register: %" PRId32, i);
|
LOG_ERROR("isa info not available, failed to read cp0 config register: %" PRId32, i);
|
||||||
ejtag_info->config_regs = 0;
|
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);
|
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) {
|
if (ejtag_info->impcode & EJTAG_IMP_MIPS16) {
|
||||||
mips32->isa_imp = MIPS32_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 */
|
} else if (ejtag_info->config_regs >= 4) { /* config3 implemented */
|
||||||
unsigned isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT;
|
unsigned isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT;
|
||||||
if (isa_imp == 1) {
|
if (isa_imp == 1) {
|
||||||
mips32->isa_imp = MMIPS32_ONLY;
|
mips32->isa_imp = MMIPS32_ONLY;
|
||||||
LOG_USER("MICRO MIPS32 only implemented");
|
LOG_USER("ISA implemented: %s%s", "microMIPS32", buf);
|
||||||
|
|
||||||
} else if (isa_imp != 0) {
|
} else if (isa_imp != 0) {
|
||||||
mips32->isa_imp = MIPS32_MMIPS32;
|
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 */
|
/* Retrieve DSP info */
|
||||||
LOG_USER("MIPS32 only implemented");
|
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;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mips32_checksum_memory(struct target *target, target_addr_t address,
|
int mips32_checksum_memory(struct target *target, target_addr_t address,
|
||||||
uint32_t count, uint32_t *checksum)
|
uint32_t count, uint32_t *checksum)
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,9 +46,21 @@
|
||||||
#define MIPS32_CONFIG0_AR_SHIFT 10
|
#define MIPS32_CONFIG0_AR_SHIFT 10
|
||||||
#define MIPS32_CONFIG0_AR_MASK (0x7 << MIPS32_CONFIG0_AR_SHIFT)
|
#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_SHIFT 10
|
||||||
#define MIPS32_CONFIG1_DL_MASK (0x7 << MIPS32_CONFIG1_DL_SHIFT)
|
#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_SHIFT 14
|
||||||
#define MIPS32_CONFIG3_ISA_MASK (3 << MIPS32_CONFIG3_ISA_SHIFT)
|
#define MIPS32_CONFIG3_ISA_MASK (3 << MIPS32_CONFIG3_ISA_SHIFT)
|
||||||
|
|
||||||
|
@ -57,6 +69,141 @@
|
||||||
|
|
||||||
#define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000
|
#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. */
|
/* Insert extra NOPs after the DRET instruction on exit from debug. */
|
||||||
#define EJTAG_QUIRK_PAD_DRET BIT(0)
|
#define EJTAG_QUIRK_PAD_DRET BIT(0)
|
||||||
|
|
||||||
|
@ -67,6 +214,30 @@ enum {
|
||||||
MIPS32NUMCOREREGS
|
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 {
|
enum mips32_isa_mode {
|
||||||
MIPS32_ISA_MIPS32 = 0,
|
MIPS32_ISA_MIPS32 = 0,
|
||||||
MIPS32_ISA_MIPS16E = 1,
|
MIPS32_ISA_MIPS16E = 1,
|
||||||
|
@ -80,21 +251,67 @@ enum mips32_isa_imp {
|
||||||
MIPS32_MMIPS32 = 3,
|
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 {
|
struct mips32_comparator {
|
||||||
int used;
|
int used;
|
||||||
uint32_t bp_value;
|
uint32_t bp_value;
|
||||||
uint32_t reg_address;
|
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 {
|
struct mips32_common {
|
||||||
unsigned int common_magic;
|
unsigned int common_magic;
|
||||||
|
|
||||||
void *arch_info;
|
void *arch_info;
|
||||||
struct reg_cache *core_cache;
|
struct reg_cache *core_cache;
|
||||||
struct mips_ejtag ejtag_info;
|
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_mode isa_mode;
|
||||||
enum mips32_isa_imp isa_imp;
|
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 */
|
/* processor identification register */
|
||||||
uint32_t prid;
|
uint32_t prid;
|
||||||
|
@ -394,6 +611,173 @@ struct mips32_algorithm {
|
||||||
|
|
||||||
#define MIPS16_SDBBP(isa) (isa ? MMIPS16_SDBBP : MIPS16_ISA_SDBBP)
|
#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[];
|
extern const struct command_registration mips32_command_handlers[];
|
||||||
|
|
||||||
int mips32_arch_state(struct target *target);
|
int mips32_arch_state(struct target *target);
|
||||||
|
|
|
@ -823,9 +823,13 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz
|
||||||
return retval;
|
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};
|
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);
|
pracc_queue_init(&ctx);
|
||||||
|
|
||||||
uint32_t cp0_write_code[] = {
|
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) */
|
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 */
|
/* load registers 2 to 31 with li32, optimize */
|
||||||
for (int i = 2; i < 32; i++)
|
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++) {
|
/* load $15 in DeSave */
|
||||||
pracc_add_li32(&ctx, 1, regs[i + 32], 0); /* load CPO value in $1 */
|
pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0));
|
||||||
pracc_add(&ctx, 0, cp0_write_code[i]); /* write value from $1 to CPO register */
|
/* load upper half word in $1 */
|
||||||
}
|
pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, UPPER16((gprs[1]))));
|
||||||
pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); /* load $15 in DeSave */
|
/* jump to start */
|
||||||
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)));
|
||||||
pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
|
/* load lower half word in $1 */
|
||||||
pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 1, 1, LOWER16((regs[1])))); /* 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);
|
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
|
||||||
|
|
||||||
ejtag_info->reg8 = regs[8];
|
ejtag_info->reg8 = gprs[8];
|
||||||
ejtag_info->reg9 = regs[9];
|
ejtag_info->reg9 = gprs[9];
|
||||||
pracc_queue_free(&ctx);
|
pracc_queue_free(&ctx);
|
||||||
return ctx.retval;
|
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};
|
/* move $1 to COP0 DeSave */
|
||||||
pracc_queue_init(&ctx);
|
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[] = {
|
/* This function assumes the address for saving is stored in `$1`.
|
||||||
MIPS32_MFC0(ctx.isa, 8, 12, 0), /* move status to $8 */
|
* And that action is performed in `mips32_pracc_set_save_base_addr`.
|
||||||
MIPS32_MFLO(ctx.isa, 8), /* move lo to $8 */
|
*/
|
||||||
MIPS32_MFHI(ctx.isa, 8), /* move hi to $8 */
|
static void mips32_pracc_store_regs_gpr(struct pracc_queue_info *ctx, unsigned int offset_gpr)
|
||||||
MIPS32_MFC0(ctx.isa, 8, 8, 0), /* move badvaddr to $8 */
|
{
|
||||||
MIPS32_MFC0(ctx.isa, 8, 13, 0), /* move cause to $8 */
|
for (int i = 2; i != 32; i++)
|
||||||
MIPS32_MFC0(ctx.isa, 8, 24, 0), /* move depc (pc) to $8 */
|
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 */
|
/* store lo & hi */
|
||||||
pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, PRACC_UPPER_BASE_ADDR)); /* $1 = MIP32_PRACC_BASE_ADDR */
|
for (int i = 0; i < 2; i++) {
|
||||||
|
/* load COP0 needed registers to $8 */
|
||||||
for (int i = 2; i != 32; i++) /* store GPR's 2 to 31 */
|
pracc_add(ctx, 0, lohi_read_code[i]);
|
||||||
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i * 4),
|
/* store $8 at PARAM OUT */
|
||||||
MIPS32_SW(ctx.isa, i, PRACC_OUT_OFFSET + (i * 4), 1));
|
pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4,
|
||||||
|
MIPS32_SW(ctx->isa, 8, PRACC_OUT_OFFSET + (i + 32) * 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));
|
|
||||||
}
|
}
|
||||||
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 */
|
/* Saves CP0 registers [status, badvaddr, cause, depc] */
|
||||||
pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
|
static void mips32_pracc_store_regs_cp0_context(struct pracc_queue_info *ctx, unsigned int offset_cp0)
|
||||||
pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); /* load $15 in DeSave */
|
{
|
||||||
|
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);
|
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;
|
return ctx.retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,8 @@
|
||||||
|
|
||||||
#define PRACC_BLOCK 128 /* 1 Kbyte */
|
#define PRACC_BLOCK 128 /* 1 Kbyte */
|
||||||
|
|
||||||
|
struct mips32_common;
|
||||||
|
|
||||||
struct pa_list {
|
struct pa_list {
|
||||||
uint32_t instr;
|
uint32_t instr;
|
||||||
uint32_t addr;
|
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 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 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_read_regs(struct mips32_common *mips32);
|
||||||
int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs);
|
int mips32_pracc_write_regs(struct mips32_common *mips32);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \b mips32_cp0_read
|
* \b mips32_cp0_read
|
||||||
|
|
|
@ -247,8 +247,8 @@ static int mips64_set_core_reg(struct reg *reg, uint8_t *buf)
|
||||||
return ERROR_TARGET_NOT_HALTED;
|
return ERROR_TARGET_NOT_HALTED;
|
||||||
|
|
||||||
buf_set_u64(reg->value, 0, 64, value);
|
buf_set_u64(reg->value, 0, 64, value);
|
||||||
reg->dirty = 1;
|
reg->dirty = true;
|
||||||
reg->valid = 1;
|
reg->valid = true;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -265,8 +265,8 @@ static int mips64_read_core_reg(struct target *target, int num)
|
||||||
|
|
||||||
reg_value = mips64->core_regs[num];
|
reg_value = mips64->core_regs[num];
|
||||||
buf_set_u64(mips64->core_cache->reg_list[num].value, 0, 64, reg_value);
|
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].valid = true;
|
||||||
mips64->core_cache->reg_list[num].dirty = 0;
|
mips64->core_cache->reg_list[num].dirty = false;
|
||||||
|
|
||||||
return ERROR_OK;
|
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);
|
reg_value = buf_get_u64(mips64->core_cache->reg_list[num].value, 0, 64);
|
||||||
mips64->core_regs[num] = reg_value;
|
mips64->core_regs[num] = reg_value;
|
||||||
LOG_DEBUG("write core reg %i value 0x%" PRIx64 "", 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].valid = true;
|
||||||
mips64->core_cache->reg_list[num].dirty = 0;
|
mips64->core_cache->reg_list[num].dirty = false;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -297,8 +297,8 @@ int mips64_invalidate_core_regs(struct target *target)
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i < mips64->core_cache->num_regs; 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].valid = false;
|
||||||
mips64->core_cache->reg_list[i].dirty = 0;
|
mips64->core_cache->reg_list[i].dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
|
@ -123,11 +123,12 @@
|
||||||
|
|
||||||
/* Debug Control Register DCR */
|
/* Debug Control Register DCR */
|
||||||
#define EJTAG_DCR 0xFF300000
|
#define EJTAG_DCR 0xFF300000
|
||||||
#define EJTAG_DCR_ENM (1 << 29)
|
#define EJTAG_DCR_ENM BIT(29)
|
||||||
#define EJTAG_DCR_DB (1 << 17)
|
#define EJTAG_DCR_FDC BIT(18)
|
||||||
#define EJTAG_DCR_IB (1 << 16)
|
#define EJTAG_DCR_DB BIT(17)
|
||||||
#define EJTAG_DCR_INTE (1 << 4)
|
#define EJTAG_DCR_IB BIT(16)
|
||||||
#define EJTAG_DCR_MP (1 << 2)
|
#define EJTAG_DCR_INTE BIT(4)
|
||||||
|
#define EJTAG_DCR_MP BIT(2)
|
||||||
|
|
||||||
/* breakpoint support */
|
/* breakpoint support */
|
||||||
/* EJTAG_V20_* was tested on Broadcom BCM7401
|
/* EJTAG_V20_* was tested on Broadcom BCM7401
|
||||||
|
|
|
@ -108,11 +108,11 @@ static int mips_m4k_debug_entry(struct target *target)
|
||||||
mips32->isa_mode = MIPS32_ISA_MIPS32;
|
mips32->isa_mode = MIPS32_ISA_MIPS32;
|
||||||
|
|
||||||
/* other than mips32 only and isa bit set ? */
|
/* 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;
|
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",
|
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));
|
target_state_name(target));
|
||||||
|
|
||||||
return ERROR_OK;
|
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> */
|
/* current = 1: continue on current pc, otherwise continue at <address> */
|
||||||
if (!current) {
|
if (!current) {
|
||||||
mips_m4k_isa_filter(mips32->isa_imp, &address);
|
mips_m4k_isa_filter(mips32->isa_imp, &address);
|
||||||
buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
|
buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32, address);
|
||||||
mips32->core_cache->reg_list[MIPS32_PC].dirty = true;
|
mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].dirty = true;
|
||||||
mips32->core_cache->reg_list[MIPS32_PC].valid = 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 */
|
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)
|
if (!current)
|
||||||
resume_pc = address;
|
resume_pc = address;
|
||||||
else
|
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);
|
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> */
|
/* current = 1: continue on current pc, otherwise continue at <address> */
|
||||||
if (!current) {
|
if (!current) {
|
||||||
mips_m4k_isa_filter(mips32->isa_imp, &address);
|
mips_m4k_isa_filter(mips32->isa_imp, &address);
|
||||||
buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
|
buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32, address);
|
||||||
mips32->core_cache->reg_list[MIPS32_PC].dirty = true;
|
mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].dirty = true;
|
||||||
mips32->core_cache->reg_list[MIPS32_PC].valid = true;
|
mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the front-end may request us not to handle breakpoints */
|
/* the front-end may request us not to handle breakpoints */
|
||||||
if (handle_breakpoints) {
|
if (handle_breakpoints) {
|
||||||
breakpoint = breakpoint_find(target,
|
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)
|
if (breakpoint)
|
||||||
mips_m4k_unset_breakpoint(target, breakpoint);
|
mips_m4k_unset_breakpoint(target, breakpoint);
|
||||||
}
|
}
|
||||||
|
|
|
@ -625,8 +625,8 @@ static int mips_mips64_resume(struct target *target, int current,
|
||||||
/* current = 1: continue on current pc, otherwise continue at <address> */
|
/* current = 1: continue on current pc, otherwise continue at <address> */
|
||||||
if (!current) {
|
if (!current) {
|
||||||
buf_set_u64(pc->value, 0, 64, address);
|
buf_set_u64(pc->value, 0, 64, address);
|
||||||
pc->dirty = 1;
|
pc->dirty = true;
|
||||||
pc->valid = 1;
|
pc->valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
resume_pc = buf_get_u64(pc->value, 0, 64);
|
resume_pc = buf_get_u64(pc->value, 0, 64);
|
||||||
|
@ -717,8 +717,8 @@ static int mips_mips64_step(struct target *target, int current,
|
||||||
* <address> */
|
* <address> */
|
||||||
if (!current) {
|
if (!current) {
|
||||||
buf_set_u64(pc->value, 0, 64, address);
|
buf_set_u64(pc->value, 0, 64, address);
|
||||||
pc->dirty = 1;
|
pc->dirty = true;
|
||||||
pc->valid = 1;
|
pc->valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the front-end may request us not to handle breakpoints */
|
/* the front-end may request us not to handle breakpoints */
|
||||||
|
|
|
@ -3053,6 +3053,10 @@ COMMAND_HANDLER(handle_reg_command)
|
||||||
LOG_DEBUG("-");
|
LOG_DEBUG("-");
|
||||||
|
|
||||||
struct target *target = get_current_target(CMD_CTX);
|
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;
|
struct reg *reg = NULL;
|
||||||
|
|
||||||
/* list all available registers for the current target */
|
/* list all available registers for the current target */
|
||||||
|
@ -3117,7 +3121,7 @@ COMMAND_HANDLER(handle_reg_command)
|
||||||
if (!reg) {
|
if (!reg) {
|
||||||
command_print(CMD, "%i is out of bounds, the current target "
|
command_print(CMD, "%i is out of bounds, the current target "
|
||||||
"has only %i registers (0 - %i)", num, count, count - 1);
|
"has only %i registers (0 - %i)", num, count, count - 1);
|
||||||
return ERROR_OK;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* access a single register by its name */
|
/* 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')
|
if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0')
|
||||||
&& (CMD_ARGV[1][0] <= '9')))) {
|
&& (CMD_ARGV[1][0] <= '9')))) {
|
||||||
if ((CMD_ARGC == 2) && (strcmp(CMD_ARGV[1], "force") == 0))
|
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);
|
int retval = reg->type->get(reg);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("Could not read register '%s'", reg->name);
|
LOG_ERROR("Could not read register '%s'", reg->name);
|
||||||
|
@ -3176,7 +3180,7 @@ COMMAND_HANDLER(handle_reg_command)
|
||||||
|
|
||||||
not_found:
|
not_found:
|
||||||
command_print(CMD, "register %s not found in current target", CMD_ARGV[0]);
|
command_print(CMD, "register %s not found in current target", CMD_ARGV[0]);
|
||||||
return ERROR_OK;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_poll_command)
|
COMMAND_HANDLER(handle_poll_command)
|
||||||
|
@ -4071,13 +4075,14 @@ COMMAND_HANDLER(handle_wp_command)
|
||||||
struct watchpoint *watchpoint = target->watchpoints;
|
struct watchpoint *watchpoint = target->watchpoints;
|
||||||
|
|
||||||
while (watchpoint) {
|
while (watchpoint) {
|
||||||
|
char wp_type = (watchpoint->rw == WPT_READ ? 'r' : (watchpoint->rw == WPT_WRITE ? 'w' : 'a'));
|
||||||
command_print(CMD, "address: " TARGET_ADDR_FMT
|
command_print(CMD, "address: " TARGET_ADDR_FMT
|
||||||
", len: 0x%8.8" PRIx32
|
", 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,
|
", mask: 0x%8.8" PRIx64,
|
||||||
watchpoint->address,
|
watchpoint->address,
|
||||||
watchpoint->length,
|
watchpoint->length,
|
||||||
(int)watchpoint->rw,
|
wp_type,
|
||||||
watchpoint->value,
|
watchpoint->value,
|
||||||
watchpoint->mask);
|
watchpoint->mask);
|
||||||
watchpoint = watchpoint->next;
|
watchpoint = watchpoint->next;
|
||||||
|
@ -4138,17 +4143,28 @@ COMMAND_HANDLER(handle_wp_command)
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_rwp_command)
|
COMMAND_HANDLER(handle_rwp_command)
|
||||||
{
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
if (CMD_ARGC != 1)
|
if (CMD_ARGC != 1)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
target_addr_t addr;
|
|
||||||
COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
|
|
||||||
|
|
||||||
struct target *target = get_current_target(CMD_CTX);
|
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)
|
if (retval != ERROR_OK) {
|
||||||
command_print(CMD, "Error during removal of watchpoint at address " TARGET_ADDR_FMT, addr);
|
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;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -5135,7 +5151,7 @@ static int target_jim_get_reg(Jim_Interp *interp, int argc,
|
||||||
return JIM_ERR;
|
return JIM_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (force) {
|
if (force || !reg->valid) {
|
||||||
int retval = reg->type->get(reg);
|
int retval = reg->type->get(reg);
|
||||||
|
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
|
@ -5860,6 +5876,18 @@ COMMAND_HANDLER(handle_target_current_state)
|
||||||
return ERROR_OK;
|
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)
|
static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
{
|
{
|
||||||
struct jim_getopt_info goi;
|
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",
|
.help = "displays the current state of this target",
|
||||||
.usage = "",
|
.usage = "",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "debug_reason",
|
||||||
|
.mode = COMMAND_EXEC,
|
||||||
|
.handler = handle_target_debug_reason,
|
||||||
|
.help = "displays the debug reason of this target",
|
||||||
|
.usage = "",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.name = "arp_examine",
|
.name = "arp_examine",
|
||||||
.mode = COMMAND_EXEC,
|
.mode = COMMAND_EXEC,
|
||||||
|
@ -6110,7 +6145,7 @@ static int target_create(struct jim_getopt_info *goi)
|
||||||
if (e != JIM_OK)
|
if (e != JIM_OK)
|
||||||
return e;
|
return e;
|
||||||
struct transport *tr = get_current_transport();
|
struct transport *tr = get_current_transport();
|
||||||
if (tr->override_target) {
|
if (tr && tr->override_target) {
|
||||||
e = tr->override_target(&cp);
|
e = tr->override_target(&cp);
|
||||||
if (e != ERROR_OK) {
|
if (e != ERROR_OK) {
|
||||||
LOG_ERROR("The selected transport doesn't support this target");
|
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,
|
.handler = handle_rwp_command,
|
||||||
.mode = COMMAND_EXEC,
|
.mode = COMMAND_EXEC,
|
||||||
.help = "remove watchpoint",
|
.help = "remove watchpoint",
|
||||||
.usage = "address",
|
.usage = "'all' | address",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "load_image",
|
.name = "load_image",
|
||||||
|
|
|
@ -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]
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -5,6 +5,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
source [find target/swj-dp.tcl]
|
source [find target/swj-dp.tcl]
|
||||||
|
source [find mem_helper.tcl]
|
||||||
|
|
||||||
if { [info exists CHIPNAME] } {
|
if { [info exists CHIPNAME] } {
|
||||||
set _CHIPNAME $CHIPNAME
|
set _CHIPNAME $CHIPNAME
|
||||||
|
@ -116,3 +117,51 @@ proc nrf52_recover {} {
|
||||||
}
|
}
|
||||||
|
|
||||||
add_help_text nrf52_recover "Mass erase and unlock nRF52 device"
|
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"
|
||||||
|
|
|
@ -2,24 +2,30 @@
|
||||||
# Copyright (C) 2019-2021 Texas Instruments Incorporated - http://www.ti.com/
|
# Copyright (C) 2019-2021 Texas Instruments Incorporated - http://www.ti.com/
|
||||||
#
|
#
|
||||||
# Texas Instruments K3 devices:
|
# 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
|
# * AM654x: https://www.ti.com/lit/pdf/spruid7
|
||||||
# Has 4 ARMV8 Cores and 2 R5 Cores and an M3
|
# 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
|
# * J7200: https://www.ti.com/lit/pdf/spruiu1
|
||||||
# Has 2 ARMV8 Cores and 4 R5 Cores and an M3
|
# 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
|
# * J721S2: https://www.ti.com/lit/pdf/spruj28
|
||||||
# Has 2 ARMV8 Cores and 6 R5 Cores and an M4F
|
# Has 2 ARMV8 Cores and 6 R5 Cores and an M4F
|
||||||
# * J784S4/AM69: http://www.ti.com/lit/zip/spruj52
|
# * J784S4/AM69: http://www.ti.com/lit/zip/spruj52
|
||||||
# Has 8 ARMV8 Cores and 8 R5 Cores
|
# 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]
|
source [find target/swj-dp.tcl]
|
||||||
|
@ -44,6 +50,7 @@ set CM3_CTIBASE {0x3C016000}
|
||||||
|
|
||||||
# sysctrl power-ap unlock offsets
|
# sysctrl power-ap unlock offsets
|
||||||
set _sysctrl_ap_unlock_offsets {0xf0 0x44}
|
set _sysctrl_ap_unlock_offsets {0xf0 0x44}
|
||||||
|
set _sysctrl_ap_num 7
|
||||||
|
|
||||||
# All the ARMV8s are the next processors.
|
# All the ARMV8s are the next processors.
|
||||||
# CL0,CORE0 CL0,CORE1 CL1,CORE0 CL1,CORE1
|
# 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_DBGBASE {0x9d010000 0x9d012000 0x9d410000 0x9d412000 0x9d510000 0x9d512000}
|
||||||
set R5_CTIBASE {0x9d018000 0x9d019000 0x9d418000 0x9d419000 0x9d518000 0x9d519000}
|
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_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
|
# Finally an General Purpose(GP) MCU
|
||||||
set CM4_CTIBASE {0x20001000}
|
set CM4_CTIBASE {0x20001000}
|
||||||
|
@ -64,8 +72,46 @@ set _gp_mcu_cores 0
|
||||||
# General Purpose MCU power-ap unlock offsets
|
# General Purpose MCU power-ap unlock offsets
|
||||||
set _gp_mcu_ap_unlock_offsets {0xf0 0x60}
|
set _gp_mcu_ap_unlock_offsets {0xf0 0x60}
|
||||||
|
|
||||||
|
# Generic mem-ap port number
|
||||||
|
set _mem_ap_num 2
|
||||||
|
|
||||||
# Set configuration overrides for each SOC
|
# Set configuration overrides for each SOC
|
||||||
switch $_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 {
|
am654 {
|
||||||
set _K3_DAP_TAPID 0x0bb5a02f
|
set _K3_DAP_TAPID 0x0bb5a02f
|
||||||
|
|
||||||
|
@ -80,6 +126,7 @@ switch $_soc {
|
||||||
# Sysctrl power-ap unlock offsets
|
# Sysctrl power-ap unlock offsets
|
||||||
set _sysctrl_ap_unlock_offsets {0xf0 0x50}
|
set _sysctrl_ap_unlock_offsets {0xf0 0x50}
|
||||||
}
|
}
|
||||||
|
am243 -
|
||||||
am642 {
|
am642 {
|
||||||
set _K3_DAP_TAPID 0x0bb3802f
|
set _K3_DAP_TAPID 0x0bb3802f
|
||||||
|
|
||||||
|
@ -97,6 +144,12 @@ switch $_soc {
|
||||||
|
|
||||||
# M4 processor
|
# M4 processor
|
||||||
set _gp_mcu_cores 1
|
set _gp_mcu_cores 1
|
||||||
|
|
||||||
|
# Overrides for am243
|
||||||
|
if { "$_soc" == "am243" } {
|
||||||
|
# Uses the same JTAG ID
|
||||||
|
set _armv8_cores 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
am625 {
|
am625 {
|
||||||
set _K3_DAP_TAPID 0x0bb7e02f
|
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
|
set _CHIPNAME $_soc
|
||||||
|
|
||||||
swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_K3_DAP_TAPID -ignore-version
|
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
|
set _CTINAME $_CHIPNAME.cti
|
||||||
|
|
||||||
# sysctrl is always present
|
# sysctrl is always present
|
||||||
cti create $_CTINAME.sysctrl -dap $_CHIPNAME.dap -ap-num 7 -baseaddr [lindex $CM3_CTIBASE 0]
|
cti create $_CTINAME.sysctrl -dap $_CHIPNAME.dap \
|
||||||
target create $_TARGETNAME.sysctrl cortex_m -dap $_CHIPNAME.dap -ap-num 7 -defer-examine
|
-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 { }
|
$_TARGETNAME.sysctrl configure -event reset-assert { }
|
||||||
|
|
||||||
proc sysctrl_up {} {
|
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 \
|
cti create $_CTINAME.$_armv8_cpu_name.$_core -dap $_CHIPNAME.dap -ap-num 1 \
|
||||||
-baseaddr [lindex $ARMV8_CTIBASE $_core]
|
-baseaddr [lindex $ARMV8_CTIBASE $_core]
|
||||||
|
|
||||||
target create $_TARGETNAME.$_armv8_cpu_name.$_core aarch64 -dap $_CHIPNAME.dap \
|
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
|
-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"
|
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
|
if { $_armv8_cores > 0 } {
|
||||||
set _armv8_up_cmd "$_armv8_cpu_name"_up
|
# Setup ARMV8 proc commands based on CPU to prevent people confusing SoCs
|
||||||
# Available if V8_SMP_DEBUG is set to non-zero value
|
set _armv8_up_cmd "$_armv8_cpu_name"_up
|
||||||
set _armv8_smp_cmd "$_armv8_cpu_name"_smp
|
# Available if V8_SMP_DEBUG is set to non-zero value
|
||||||
|
set _armv8_smp_cmd "$_armv8_cpu_name"_smp
|
||||||
|
|
||||||
if { $_v8_smp_debug == 0 } {
|
if { $_v8_smp_debug == 0 } {
|
||||||
proc $_armv8_up_cmd { args } {
|
proc $_armv8_up_cmd { args } {
|
||||||
foreach _core $args {
|
foreach _core $args {
|
||||||
targets $_core
|
targets $_core
|
||||||
_cpu_no_smp_up
|
_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 } {
|
for { set _core 0 } { $_core < $_r5_cores } { incr _core } {
|
||||||
set _r5_name [lindex $R5_NAMES $_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]
|
-baseaddr [lindex $R5_CTIBASE $_core]
|
||||||
|
|
||||||
# inactive core examination will fail - wait till startup of additional core
|
# inactive core examination will fail - wait till startup of additional core
|
||||||
target create $_TARGETNAME.$_r5_name cortex_r4 -dap $_CHIPNAME.dap \
|
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 {
|
$_TARGETNAME.$_r5_name configure -event gdb-attach {
|
||||||
_cpu_no_smp_up
|
_cpu_no_smp_up
|
||||||
|
@ -368,7 +437,8 @@ proc r5_up { args } {
|
||||||
|
|
||||||
if { $_gp_mcu_cores != 0 } {
|
if { $_gp_mcu_cores != 0 } {
|
||||||
cti create $_CTINAME.gp_mcu -dap $_CHIPNAME.dap -ap-num 8 -baseaddr [lindex $CM4_CTIBASE 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 { }
|
$_TARGETNAME.gp_mcu configure -event reset-assert { }
|
||||||
|
|
||||||
proc gp_mcu_up {} {
|
proc gp_mcu_up {} {
|
||||||
|
@ -404,4 +474,7 @@ if { 0 == [string compare [adapter name] dmem ] } {
|
||||||
} else {
|
} else {
|
||||||
puts "ERROR: ${SOC} data is missing to support dmem access!"
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,7 @@ bNumInterfaces
|
||||||
idProduct
|
idProduct
|
||||||
idVendor
|
idVendor
|
||||||
iInterface
|
iInterface
|
||||||
|
iManufacturer
|
||||||
iProduct
|
iProduct
|
||||||
iSerialNumber
|
iSerialNumber
|
||||||
wMaxPacketSize
|
wMaxPacketSize
|
||||||
|
|
Loading…
Reference in New Issue